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

New: Introduce Jest component testing to the framework (fixes #3417) #3383

Merged
merged 21 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fde2476
Issue#64/Introduce Jest component testing to the framework starting w…
Mar 31, 2023
2748f5c
issue#64/reverted change to adapt-contri-core
Mar 31, 2023
b3f0dce
Issue#64 - removed view and model mock
Mar 31, 2023
4549638
Issue#64 - modified mocks to only include what was needed for the tes…
May 17, 2023
3b8cf3a
Issue#64 - removed device.screenSize setting within test as device.sc…
May 17, 2023
c51aa98
Issue#64 - fixed package.json conflicts
May 17, 2023
ca1e9b7
Issue#64 - header file path update after initialising the core submodule
May 17, 2023
04f2c7b
Removed coverage reports
May 17, 2023
94abb38
Git ignore all files within the coverage directory
May 17, 2023
c1868de
Added package-lock
May 17, 2023
1b1a5a2
removed displayTitle test
May 17, 2023
c0b4f2e
isScreenSizeMin Mock const
May 19, 2023
e3743b4
removed react helpers extported templates as is it not used in the js…
May 19, 2023
a5804fc
Extended with a custom jest environment to allow ES Class unit tests …
oliverfoster Jul 11, 2023
5672e7d
Fix: files moved to test folder, test preperation/execution seperated.
joe-allen-89 Aug 4, 2023
88ea3e4
Files removed from root after being added to test folder.
joe-allen-89 Aug 4, 2023
d8219c4
Refactor
oliverfoster Sep 19, 2023
b99959a
Pull jest-environment-adapt from npm instead of github
oliverfoster Sep 19, 2023
7b3e819
Merged with master
oliverfoster Sep 19, 2023
fb382fd
Added npm test help
oliverfoster Sep 19, 2023
7acc018
Updating testing environment to 16 and removed typo
oliverfoster Sep 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"browser": true,
"commonjs": false,
"es2022": true,
"amd": true
"amd": true,
"jest": true
},
"extends": [
"standard",
Expand Down
18 changes: 18 additions & 0 deletions __mocks__/core/js/adapt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default {
course: {
get: jest.fn().mockReturnValue(
{
_components: {
_text: {
ariaRegion: 'Text Component Aria Text'
}
},
_extensions: {
_glossary: {
ariaRegion: 'Glossary Extension Aria Text'
}
}
}
)
}
};
12 changes: 12 additions & 0 deletions __mocks__/core/js/device.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const mockDeviceInstance = {
isScreenSizeMin: jest.fn().mockReturnValue(true)
};

const mockIsScreenSizeMinMock = jest.fn().mockReturnValue(true);
export default {
__esModule: true,
default: mockDeviceInstance,
get isScreenSizeMin() {
return mockIsScreenSizeMinMock;
}
};
1 change: 1 addition & 0 deletions __mocks__/core/js/logging.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default { removed: jest.fn() };
17 changes: 17 additions & 0 deletions __mocks__/core/js/reactHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import Header from '../../../src/core/adapt-contrib-core/templates/header';
import { jest } from '@jest/globals';

export const templates = {
header: jest.fn((props) => {
return <Header {...props} />;
})
};

export const prefixClasses = jest.fn((classNamePrefixes, classNames) => {
return classNames.map(className => `${classNamePrefixes}-${className}`).join(' ');
});

export const compile = jest.fn((template, props) => {
return template;
});
161 changes: 161 additions & 0 deletions __tests__/header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import React from 'react';
import Header from '../src/core/adapt-contrib-core/templates/header';
import { act } from 'react-dom/test-utils';
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals';
import device from 'core/js/device';
import { unmountComponentAtNode, render } from 'react-dom';

let container = null;
beforeEach(() => {
jest.clearAllMocks();
// setup a DOM element as a render target
container = document.createElement('div');
document.body.appendChild(container);
});

afterEach(() => {
// cleanup on exiting
unmountComponentAtNode(container);
container.remove();
container = null;
});

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

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

it('should be able to set the displayTitle', () => {
const displayTitle = 'test body text';
const props = {
displayTitle
};
act(() => {
render(<Header {...props} />, container);
});
expect(container.textContent).toBe('');
eleanor-heath marked this conversation as resolved.
Show resolved Hide resolved
});

it('should not display a header when there is no body text, display title or sized instruction set', () => {
const _id = 'header';
const props = {
_id
};
act(() => {
render(<Header {...props} />, container);
});
expect(container.textContent).toBe('');
});

it('should display the component description when the title, display title or instruction is not specified ' +
'and the _isA11yComponentDescriptionEnabled is enabled and the aria region is set', () => {
const props = {
_isA11yComponentDescriptionEnabled: true,
_component: 'text'
};
act(() => {
render(<Header {...props} />, container);
});
const ariaRegion = 'Text Component Aria Text';
expect(container.textContent).toBe(ariaRegion);
});

it('should display the extension description when the title, display title or instruction is not specified ' +
'and the _isA11yComponentDescriptionEnabled is enabled and the aria region is set', () => {
const props = {
_isA11yComponentDescriptionEnabled: true,
_extension: 'glossary'
};
act(() => {
render(<Header {...props} />, container);
});
const ariaRegion = 'Glossary Extension Aria Text';
expect(container.textContent).toBe(ariaRegion);
});

it('should not display anything when the title, display title or instruction is not specified' +
'and the _isA11yComponentDescriptionEnabled is not enabled', () => {
const props = {
_isA11yComponentDescriptionEnabled: false,
_component: 'text'
};
act(() => {
render(<Header {...props} />, container);
});
expect(container.textContent).toBe('');
});

it('should display the aria region the component description when the body along with aria region is specified' +
'and the _isA11yComponentDescriptionEnabled is enabled', () => {
const props = {
body: 'Text title',
_isA11yComponentDescriptionEnabled: true,
_component: 'text'
};
act(() => {
render(<Header {...props} />, container);
});
const ariaRegion = 'Text Component Aria Text';
const body = 'Text title';
expect(container.textContent).toContain(ariaRegion);
expect(container.textContent).toContain(body);
});

describe('Device screen size rendering', () => {
it('should not display the header mobile instructions when the isScreenSizeMin is medium', () => {
jest.spyOn(device, 'isScreenSizeMin').mockReturnValue(true);
const mobileInstruction = 'mobileInstruction';
const props = {
mobileInstruction
};
act(() => {
render(<Header {...props} />, container);
});
expect(container.textContent).toBe('');
});

it('should display the header instructions when the isScreenSizeMin is medium', () => {
jest.spyOn(device, 'isScreenSizeMin').mockReturnValue(true);
const mobileInstruction = 'mobileInstruction';
const instruction = 'instruction';
const props = {
mobileInstruction,
instruction
};
act(() => {
render(<Header {...props} />, container);
});
expect(container.textContent).toBe(instruction);
});

it('should display the header mobile instructions on small screen devices', () => {
jest.spyOn(device, 'isScreenSizeMin').mockReturnValue(false);
const mobileInstruction = 'mobileInstruction';
const props = {
mobileInstruction
};
act(() => {
render(<Header {...props} />, container);
});
expect(container.textContent).toBe(mobileInstruction);
});
});
});
6 changes: 6 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const presets = [
['@babel/preset-env', { targets: { node: 'current' } }],
['@babel/preset-react', { targets: { node: 'current' } }]
];

module.exports = { presets };
94 changes: 94 additions & 0 deletions coverage/clover.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1680274786710" clover="3.2.0">
<project timestamp="1680274786710" name="All files">
<metrics statements="85" coveredstatements="83" conditionals="22" coveredconditionals="18" methods="1" coveredmethods="1" elements="108" coveredelements="102" complexity="0" loc="85" ncloc="85" packages="1" files="1" classes="1"/>
<file name="header.jsx" path="/Users/eleanorheath/Desktop/Adapt/adapt_framework/src/core/templates/header.jsx">
<metrics statements="85" coveredstatements="83" conditionals="22" coveredconditionals="18" methods="1" coveredmethods="1"/>
<line num="1" count="1" type="stmt"/>
<line num="2" count="1" type="stmt"/>
<line num="3" count="1" type="stmt"/>
<line num="4" count="1" type="stmt"/>
<line num="5" count="1" type="stmt"/>
<line num="6" count="1" type="stmt"/>
<line num="7" count="1" type="stmt"/>
<line num="8" count="1" type="stmt"/>
<line num="9" count="1" type="stmt"/>
<line num="10" count="1" type="stmt"/>
<line num="11" count="1" type="stmt"/>
<line num="12" count="1" type="stmt"/>
<line num="13" count="1" type="stmt"/>
<line num="14" count="1" type="stmt"/>
<line num="15" count="1" type="stmt"/>
<line num="16" count="1" type="stmt"/>
<line num="17" count="1" type="stmt"/>
<line num="18" count="1" type="cond" truecount="1" falsecount="0"/>
<line num="19" count="8" type="stmt"/>
<line num="20" count="8" type="stmt"/>
<line num="21" count="8" type="stmt"/>
<line num="22" count="8" type="stmt"/>
<line num="23" count="8" type="stmt"/>
<line num="24" count="8" type="stmt"/>
<line num="25" count="8" type="stmt"/>
<line num="26" count="8" type="stmt"/>
<line num="27" count="8" type="stmt"/>
<line num="28" count="8" type="stmt"/>
<line num="29" count="8" type="stmt"/>
<line num="30" count="8" type="stmt"/>
<line num="31" count="8" type="stmt"/>
<line num="32" count="8" type="cond" truecount="0" falsecount="1"/>
<line num="33" count="8" type="cond" truecount="1" falsecount="0"/>
<line num="34" count="8" type="cond" truecount="0" falsecount="1"/>
<line num="35" count="8" type="stmt"/>
<line num="36" count="8" type="stmt"/>
<line num="37" count="8" type="cond" truecount="2" falsecount="0"/>
<line num="38" count="8" type="cond" truecount="1" falsecount="0"/>
<line num="39" count="8" type="stmt"/>
<line num="40" count="8" type="stmt"/>
<line num="41" count="8" type="cond" truecount="2" falsecount="0"/>
<line num="42" count="8" type="cond" truecount="0" falsecount="1"/>
<line num="43" count="8" type="cond" truecount="1" falsecount="0"/>
<line num="44" count="8" type="cond" truecount="3" falsecount="0"/>
<line num="45" count="1" type="stmt"/>
<line num="46" count="1" type="stmt"/>
<line num="47" count="1" type="stmt"/>
<line num="48" count="1" type="stmt"/>
<line num="49" count="1" type="stmt"/>
<line num="50" count="1" type="stmt"/>
<line num="51" count="1" type="cond" truecount="1" falsecount="0"/>
<line num="52" count="8" type="cond" truecount="2" falsecount="0"/>
<line num="53" count="4" type="stmt"/>
<line num="54" count="4" type="stmt"/>
<line num="55" count="4" type="stmt"/>
<line num="56" count="4" type="cond" truecount="0" falsecount="1"/>
<line num="57" count="0" type="stmt"/>
<line num="58" count="0" type="stmt"/>
<line num="59" count="8" type="stmt"/>
<line num="60" count="8" type="stmt"/>
<line num="61" count="8" type="stmt"/>
<line num="62" count="8" type="cond" truecount="2" falsecount="0"/>
<line num="63" count="1" type="stmt"/>
<line num="64" count="8" type="stmt"/>
<line num="65" count="8" type="stmt"/>
<line num="66" count="8" type="stmt"/>
<line num="67" count="8" type="cond" truecount="1" falsecount="0"/>
<line num="68" count="2" type="stmt"/>
<line num="69" count="2" type="stmt"/>
<line num="70" count="2" type="stmt"/>
<line num="71" count="8" type="stmt"/>
<line num="72" count="8" type="stmt"/>
<line num="73" count="8" type="stmt"/>
<line num="74" count="8" type="cond" truecount="1" falsecount="0"/>
<line num="75" count="2" type="stmt"/>
<line num="76" count="2" type="stmt"/>
<line num="77" count="2" type="stmt"/>
<line num="78" count="2" type="stmt"/>
<line num="79" count="8" type="stmt"/>
<line num="80" count="8" type="stmt"/>
<line num="81" count="8" type="stmt"/>
<line num="82" count="8" type="stmt"/>
<line num="83" count="8" type="stmt"/>
<line num="84" count="8" type="stmt"/>
<line num="85" count="8" type="stmt"/>
</file>
</project>
</coverage>
Loading