Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Jest Unit Tests #3417

Closed
eleanor-heath opened this issue May 17, 2023 · 3 comments
Closed

Introduce Jest Unit Tests #3417

eleanor-heath opened this issue May 17, 2023 · 3 comments

Comments

@eleanor-heath
Copy link
Contributor

eleanor-heath commented May 17, 2023

Subject of the issue/enhancement/features

Jest is a popular unit testing framework.
In the attached pull request I have unit tested the Header component.
You can run the test with the following command: yarn jesttest
Ensure that all packages are up to date when running the tests for the first time with npm install.

IDE Considerations
There is the option to add the Jest extension from within Visual Studio Code.
Screenshot 2023-05-17 at 14 14 59

This provides a visual view of all running tests. It automatically runs all tests in watch mode and can be used to debug tests.
Screenshot 2023-05-17 at 14 17 58

I have added in the jest env option to the eslinter to ensure the IDE recognises all jest references to avoid eslint errors appearing.

Unit Test Approach
To begin with we want to target all core jsx component templates to test that the component state gets updated correctly and the template renders as expected.

it('should display the header body', () => {
    const body = 'test body text';
    const props = {
      body
    };
    act(() => {
      render(<Header {...props} />, container);
    });
    expect(container.textContent).toBe(body);
  });

Here is an example component unit test above, it passes the body property to the Header component and then asserts that the Header templates' text content is equal to the body text that was passed into the template.

Folder Structure
All tests reside in a __tests__ directory. The structure of adding tests adjacent to the file they are testing and adding a test.js or spec.js extension to the end of the test file name was not an option for us as all tests are to be added to the framework. We do not require the spec.js or test.js named extension to the end of the test file names we have in the __tests__ directory.
We are required to mock our ES6 class files. These will be contained within a __mocks__ directory. The structure of this can be seen below. The example is relevant to core/js/adapt.js mock and Header component test.

-__mocks__
  -core
    -js
      -adapt.js
-__tests__
  -header.js

Further Code Considerations
Although we must have a base mock for our ES6 Classes of which are contained within the __mocks__ directory, we can override some of the default properties/returned function calls within individual tests. I have included an example below for how to override a returned function call.
This is the device mock where we originally set the returned value of isScreenSizeMin to true.

const mockDeviceInstance = {
  isScreenSizeMin: jest.fn().mockReturnValue(true)
};

const mockIsScreenSizeMinMock = jest.fn().mockReturnValue(true);
export default {
  __esModule: true,
  default: mockDeviceInstance,
  get isScreenSizeMin() {
    return mockIsScreenSizeMinMock;
  }
};

Within the test we can override this with a spy, an example of this is given below.
jest.spyOn(device, 'isScreenSizeMin').mockReturnValue(false);
This will ensure the device.isScreenSizeMin('medium') call within the Header.jsx template returns false when the test renders the template.

We can override properties from classes within individual tests by first ensuring the property is set up as a default value within the mock. Then in the test file, import the class and modify the property, an example can be seen below.

This is a mock with a property screenSize set to small.

const mockDeviceInstance = {
};

const mockIsScreenSizeMinMock = jest.fn().mockReturnValue(true);
export default {
  __esModule: true,
  default: mockDeviceInstance,
  screenSize: 'small'
};

Within the test you can then import the Device class and set the screenSize property to a value of your choice.

import Device from '../src/core/adapt-contrib-core';
it('es6 class property setting example', () => {
  Device.screenSize = 'small';
}

Note that we must also provide a default property in our mock with a class instance for when the class is exported with export default ClassName.

Question/Further Considerations
Are there any plans to unit test JS files? For example we could unit test our accessibility file a11y and ensure the functions are returning the correct values.

@eleanor-heath
Copy link
Contributor Author

eleanor-heath commented May 17, 2023

@cahirodoherty-learningpool @oliverfoster @swashbuck @kirsty-hames @taylortom @chris-steele @danielghost @guywillis @StuartNicholls

Can I gather some thoughts on this.

@oliverfoster
Copy link
Member

That all makes perfect sense and is easy to read in the files. Unit testing the ES6 Classes is going to prove a little problematic currently, see #3383 (comment)

@oliverfoster oliverfoster moved this from Needs Reviewing to Assigned in adapt_framework: The TODO Board Aug 21, 2023
@github-project-automation github-project-automation bot moved this from Assigned to Recently Released in adapt_framework: The TODO Board Sep 26, 2023
@github-actions
Copy link

🎉 This issue has been resolved in version 5.32.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants