Skip to content

Commit

Permalink
Merge branch 'main' of github.com:openedx/react-unit-test-utils into …
Browse files Browse the repository at this point in the history
…Ali-Abbas/empty-render-issue
  • Loading branch information
Syed-Ali-Abbas-Zaidi committed Jan 3, 2024
2 parents 5206a59 + 9778bfa commit 226a36d
Show file tree
Hide file tree
Showing 18 changed files with 1,476 additions and 19,933 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.15
18
10 changes: 10 additions & 0 deletions .releaserc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
<<<<<<< HEAD
"branch": "master",
"tagFormat": "v${version}",
"verifyConditions": [
Expand Down Expand Up @@ -29,4 +30,13 @@
],
"success": [],
"fail": []
=======
"branches": ["main", "next"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
"@semantic-release/github"
]
>>>>>>> 9778bfab4b5763f12a149123cb133211e736fc82
}
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,16 @@ out.handleClick(); // out.handleClick = () => { setField2(null); }
expect(state.setField.field2).toHaveBeenCalledWith(null);
```
### `getEffect` - React useEffect hook testing utility method.
Simple utility for grabbing a useEffect call based on a list of prerequisite values.
Simple utility for grabbing useEffect calls based on a list of prerequisite values.
#### Usage
```js
import { getEffect } from '@edx/react-unit-test-utils';
import React from 'react';
import { getEffects } from '@edx/react-unit-test-utils';

jest.mock('react', () => ({
...jest.requireActual('react'),
useEffect: jest.fn(),
}));

const useMyHook = ({ val0, val1, method1 }) => {
useEffect(() => {
Expand All @@ -116,13 +122,13 @@ describe('useMyHook', () => {
beforeEach(() => { jest.clearAllMocks(); });
it('calls method1 with val0 on initial load', () => {
useMyHook({ val0, val1, method1 });
const cb = getEffect([]);
const cb = getEffect([], React)[0];
cb();
expect(method1).toHaveBeenCalledWith(val0);
});
it('calls method1 with val1 when either changes', () => {
useMyHook({ val0, val1, method1 });
const cb = getEffect([val1, method1]);
const cb = getEffect([val1, method1], React)[0];
cb();
expect(method1).toHaveBeenCalledWith(val1);
});
Expand Down
24 changes: 24 additions & 0 deletions documentation/decisions/0001-unit-testing-philosophy.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Unit Testing Philosophy
=======================

Context
=======

This repo aims to focus on support for a specific classification and type of test. The that end, it can be fairly opinionated in places in service of providing support for the full ecosystem of react component and hook unit testing.

Decision
========
This repo defines a unit test as a test that mocks as much as possible from the tested unit, to test it in complete isolation. Each unit to be tested (be it a component or a method), should be tested in terms of its output and behavior, given its inputs.
This means that component behavior (hooks) should generally be pulled out into separate methods/files for test, and that child components should be mocked when rendering a component to allow it to be tested in isolation.

Status
======
Proposed

Consequences
============

The tools and examples in this repo will be build with the intention of supporting:

* Component testing without importing/loading/testing child components
* Hook/behavior testing without testing react component integration.
24 changes: 24 additions & 0 deletions documentation/decisions/0002-shallow-renderer.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Shallow renderer
================

Context
=======

React components can be tested in a variety of ways, that tend to correspond with the "depth" of simulation/render of the component. In the phiolosphy of Unit-level testing, this repo provides a "shallow" react renderer, which allows for mocking of child components to provide a test ONLY of the component in question.

The renderer we use is built from `react-test-renderer`, and uses some logic from the now-deprecated `enzyme` library to ensure clean/small snapshots can be generated from a renderered component.

Decision
========

We will provide a `shallow` utility for rendering components, as well as a pattern and utility to mock child components for more isolated testing.

Consequences
============

The tools in this repo will not be optimized for running and then manipulating a component, or triggering its behaviors or that of its children.

Status
======

Proposed
22 changes: 22 additions & 0 deletions documentation/decisions/0003-strict-dictionaries.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Strict Dictionaries
===================

Context
=======

Vanilla javascript objects to not care/complain when called with "invalid" (missing) keys. This can produce unfortunate side-effects when using an object as a key-store, as an `undefined` value can make it through initial consumption to sometimes cause failures further down the line in less trace-able ways.

Tangentially, there is a strong tendency in testing to use "magic strings" in tests. These are strings typed directly into a test, rather than referenced from a variable. The standard solution for this in other languages is generally to put those values into a keyStore, but when doing so in JS, the object will allow access to un-initialized keys.

Decision
========

We will provide a StrictDict utility method to explicitly wrap key-store objects that should fail/complain when called with invalid keys.

Consequences
============
Code and tests written using this library should be able to completely avaoid the need to reference "magic strings" in their tests.

Status
======
Proposed
21 changes: 21 additions & 0 deletions documentation/decisions/0004-keyed-state.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Keyed useState
==============

Context
=======

React's `useState` hook does not track/care what value it is associated with in a given hook. It only registers the *order* in which it was called. This means that when mocking out `useState` calls, you must test the *order* of the calls in order to validate their initialization.

Decision
========

It is the opinion of the author of this repo that testing the order of state value initialization is an anti-pattern, as it involves testing an implementation detail. We will provide a simple wrapper (`useKeyedState`) around `useState` that takes a key purely for the purpose of making each `useState` call uniquely identifiable by something other than the order it was called in, within tests.

Consequences
============

React `useState` calls can be easily simulated and tested using provided utilities, but users will need to define a keyStore of state keys when defining state values for a hook module.

Status
======
Proposed
Loading

0 comments on commit 226a36d

Please sign in to comment.