Merge pull request #2983 from alphagov/add-js-tests-for-fullscreen-table

Add js tests for fullscreen table
This commit is contained in:
Chris Hill-Scott
2019-06-17 10:00:53 +01:00
committed by GitHub
10 changed files with 394 additions and 34 deletions

View File

@@ -24,10 +24,10 @@
.on('scroll', this.maintainHeight);
if (
window.GOVUK.stopScrollingAtFooter &&
window.GOVUK.stopScrollingAtFooter.updateFooterTop
window.GOVUK.stickAtBottomWhenScrolling &&
window.GOVUK.stickAtBottomWhenScrolling.recalculate
) {
window.GOVUK.stopScrollingAtFooter.updateFooterTop();
window.GOVUK.stickAtBottomWhenScrolling.recalculate();
}
this.maintainWidth();

View File

@@ -6,7 +6,7 @@
"node": "10.15.3"
},
"scripts": {
"test": "gulp lint && jest tests/javascripts",
"test": "gulp lint && jest --config tests/javascripts/jest.config.js tests/javascripts",
"build": "gulp",
"watch": "gulp watch"
},

View File

@@ -1,18 +1,9 @@
beforeAll(() => {
// set up jQuery
window.jQuery = require('jquery');
$ = window.jQuery;
// load module code
require('govuk_frontend_toolkit/javascripts/govuk/modules.js');
require('../../app/assets/javascripts/autofocus.js');
});
afterAll(() => {
window.jQuery = null;
$ = null;
delete window.GOVUK;
require('./support/teardown.js');
});
describe('Autofocus', () => {

View File

@@ -1,13 +1,6 @@
const helpers = require('./support/helpers');
beforeAll(() => {
// set up jQuery
window.jQuery = require('jquery');
$ = window.jQuery;
// load module code
require('govuk_frontend_toolkit/javascripts/govuk/modules.js');
// TODO: remove this when tests for sticky JS are written
require('../../app/assets/javascripts/stick-to-window-when-scrolling.js');
@@ -15,10 +8,7 @@ beforeAll(() => {
});
afterAll(() => {
window.jQuery = null;
$ = null;
delete window.GOVUK;
require('./support/teardown.js');
});

View File

@@ -0,0 +1,313 @@
const helpers = require('./support/helpers');
beforeAll(() => {
// TODO: remove this when tests for sticky JS are written
require('../../app/assets/javascripts/stick-to-window-when-scrolling.js');
require('../../app/assets/javascripts/fullscreenTable.js');
});
afterAll(() => {
require('./support/teardown.js');
});
describe('FullscreenTable', () => {
let windowMock;
let container;
let tableFrame;
let table;
let numberColumnFrame;
beforeEach(() => {
const tableHeadings = () => {
let result = '';
const headings = ['1', 'name', 'email address', 'age', 'building number', 'address line 1', 'address line 2', 'postcode'];
headings.forEach((heading, idx) => {
if (idx === 0) {
result += `<th scope="col" class="table-field-heading-first">
<span class="visually-hidden">Row in file</span><span aria-hidden="true" class="table-field-invisible-error">${heading}</span>
</th>`;
} else {
result += `<th scope="col" class="table-field-heading">
${heading}
</th>`;
}
});
return result;
}
const rowCells = (cells) => {
let result = '';
Object.keys(cells).forEach((key, idx) => {
if (idx === 0) {
result += `<td class="table-field-index">
<span class="table-field-error">
${key}
</span>
</td>`;
} else {
result += `<td class="table-field-left-aligned ">
<div class="table-field-status-default">
${key}
</div>
</td>`;
}
});
return result;
};
const tableRows = () => {
let result = '';
const rows = [
['John Logie Baird', 'johnlbaird@gmail.com', '37', '22', 'Frith Street', 'Soho, London', 'W1D 4RF'],
['Guglielmo Marconi', 'gmarconi@hotmail.com', '21', 'Pontecchio Marconi', 'Via Celestini 1', 'Bologna', ''],
['Louis Braille', 'louisbraille@yahoo.co.uk', '', '56', 'Boulevard des Invalides', 'Paris', '75007'],
['Ray Tomlinson', 'hedy.lamarr@msn.com', '25', '870', '870 Winter Street', 'Waltham', 'MA 02451']
];
rows.forEach(row => {
result += `<tr class="table-row">${rowCells(row)}</tr>`;
});
return result;
}
windowMock = new helpers.WindowMock(jest);
// set up DOM
document.body.innerHTML =
`<main>
<div class="fullscreen-content" data-module="fullscreen-table">
<table class="table table-font-xsmall">
<caption class="heading-medium table-heading visuallyhidden">
people.csv
</caption>
<thead class="table-field-headings-visible">
<tr>
${tableHeadings()}
</tr>
</thead>
<tbody>
${tableRows()}
</tbody>
</table>
</div>
</main>`;
container = document.querySelector('.fullscreen-content');
});
afterEach(() => {
document.body.innerHTML = '';
});
describe("when it loads", () => {
test("it fixes the number column for each row without changing the semantics", () => {
// start module
window.GOVUK.modules.start();
tableFrame = document.querySelector('.fullscreen-scrollable-table');
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
expect(tableFrame).not.toBeNull();
expect(numberColumnFrame).not.toBeNull();
expect(numberColumnFrame.getAttribute('role')).toEqual('presentation');
});
test("it calls the sticky JS to update any cached dimensions", () => {
const stickyJSSpy = jest.spyOn(window.GOVUK.stickAtBottomWhenScrolling, 'recalculate');
// start module
window.GOVUK.modules.start();
expect(stickyJSSpy.mock.calls.length).toBe(1);
stickyJSSpy.mockClear();
});
});
describe("the height of the table should fit the vertical space available to it", () => {
let containerBoundingClientRectSpy;
beforeEach(() => {
// set the height and offset of the window and table container from the top of the document
// so just the top 268px of it appears on-screen
windowMock.setHeightTo(768);
container.setAttribute('style', 'height: 1000px');
containerBoundingClientRectSpy = jest.spyOn(container, 'getBoundingClientRect')
containerBoundingClientRectSpy.mockImplementation(() => { return { top: 500 } });
// start module
window.GOVUK.modules.start();
tableFrame = document.querySelector('.fullscreen-scrollable-table');
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
});
afterEach(() => {
windowMock.reset();
containerBoundingClientRectSpy.mockClear();
});
test("when the page has loaded", () => {
// the frames should crop to the top 268px of the table that is visible
expect(window.getComputedStyle(tableFrame)['height']).toEqual('268px');
expect(window.getComputedStyle(numberColumnFrame)['height']).toEqual('268px');
});
test("when the page has scrolled", () => {
// scroll the window so the table fills the height of the window (768px)
windowMock.scrollBy(500);
// the frames should crop to the window height
expect(window.getComputedStyle(tableFrame)['height']).toEqual('768px');
expect(window.getComputedStyle(numberColumnFrame)['height']).toEqual('768px');
});
test("when the page has resized", () => {
// resize the window by 232px (from 768px to 1000px)
windowMock.resizeTo({ height: 1000, width: 1024 });
// the frames should crop to the top 500px of the table now visible
expect(window.getComputedStyle(tableFrame)['height']).toEqual('500px');
expect(window.getComputedStyle(numberColumnFrame)['height']).toEqual('500px');
});
});
describe("the width of the table should fit the horizontal space available to it", () => {
let rowNumberColumnCell;
beforeEach(() => {
rowNumberColumnCell = container.querySelector('.table-field-index');
// set main content column width (used as module as gauge for table width)
windowMock.setWidthTo(1024);
document.querySelector('main').setAttribute('style', 'width: 742px');
// set total width of column for row numbers in table to 40px
rowNumberColumnCell.setAttribute('style', 'width: 40px');
// start module
window.GOVUK.modules.start();
tableFrame = document.querySelector('.fullscreen-scrollable-table');
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
});
afterEach(() => {
windowMock.reset();
});
test("when the page has loaded", () => {
// table should set its width to be that of `<main>`, minus margin-left for the row numbers column
expect(window.getComputedStyle(tableFrame)['width']).toEqual('702px'); // width of content column - numbers column
expect(window.getComputedStyle(tableFrame)['margin-left']).toEqual('40px'); // width of numbers column
// table for number column has 4px extra to allow space for drop shadow
expect(window.getComputedStyle(numberColumnFrame)['width']).toEqual('44px');
});
test("when the page has resized", () => {
// resize window and content column
document.querySelector('main').setAttribute('style', 'width: 720px');
windowMock.resizeTo({ height: 768, width: 960 });
// table should set its width to be that of `<main>`, minus margin-left for the row numbers column
expect(window.getComputedStyle(tableFrame)['width']).toEqual('680px'); // width of content column - numbers column
expect(window.getComputedStyle(tableFrame)['margin-left']).toEqual('40px'); // width of numbers column
// table for number column has 4px extra to allow space for drop shadow
expect(window.getComputedStyle(numberColumnFrame)['width']).toEqual('44px');
});
});
describe("when the table scrolls horizontally", () => {
let rightEdgeShadow;
beforeEach(() => {
// start module
window.GOVUK.modules.start();
tableFrame = document.querySelector('.fullscreen-scrollable-table');
table = tableFrame.querySelector('table');
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
rightEdgeShadow = container.querySelector('.fullscreen-right-shadow');
tableFrame.setAttribute('style', 'width: 742px');
table.setAttribute('style', 'width: 1000px');
});
test("the right edge of the table scroll area should have a drop-shadow if it isn't scrolled", () => {
tableFrame.scrollLeft = 0;
helpers.triggerEvent(tableFrame, 'scroll');
expect(numberColumnFrame.classList.contains('fullscreen-scrolled-table')).toBe(false);
expect(rightEdgeShadow.classList.contains('visible')).toBe(true);
});
test("the left edge of the table scroll area should have a drop-shadow if the table is scrolled to 100%", () => {
// scroll to end of table
tableFrame.scrollLeft = 258;
helpers.triggerEvent(tableFrame, 'scroll');
expect(numberColumnFrame.classList.contains('fullscreen-scrolled-table')).toBe(true);
expect(rightEdgeShadow.classList.contains('visible')).toBe(false);
});
test("both edges of the table scroll area should have a drop-shadow if the table is scrolled between 0% and 100%", () => {
// scroll to middle of table
tableFrame.scrollLeft = 129;
helpers.triggerEvent(tableFrame, 'scroll');
expect(numberColumnFrame.classList.contains('fullscreen-scrolled-table')).toBe(true);
expect(rightEdgeShadow.classList.contains('visible')).toBe(true);
});
});
});

View File

@@ -0,0 +1,3 @@
module.exports = {
setupFiles: ['./support/setup.js']
}

View File

@@ -1,19 +1,11 @@
beforeAll(() => {
// set up jQuery & HoganJS
window.jQuery = require('jquery');
$ = window.jQuery;
Hogan = require('hogan.js');
// load module code
require('govuk_frontend_toolkit/javascripts/govuk/modules.js');
require('../../app/assets/javascripts/listEntry.js');
});
afterAll(() => {
window.jQuery = null;
$ = null;
delete window.GOVUK;
require('./support/teardown.js');
});
describe("List entry", () => {

View File

@@ -75,6 +75,66 @@ class ElementQuery {
}
};
class WindowMock {
constructor (jest) {
this._defaults = {
height: window.innerHeight,
width: window.innerWidth
};
this._spies = {
document: {}
};
this._jest = jest;
}
setHeightTo (height) {
// mock DOM calls for window height
window.innerHeight = height;
// remove calls to document.documentElement.clientHeight when jQuery is gone. It's called to support older browsers like IE8
this._spies.document.clientHeight = this._jest.spyOn(document.documentElement, 'clientHeight', 'get').mockImplementation(() => height);
}
setWidthTo (width) {
// mock DOM calls for window width
window.innerWidth = width;
// remove calls to document.documentElement.clientWidth when jQuery is gone. It's called to support older browsers like IE8
this._spies.document.clientWidth = this._jest.spyOn(document.documentElement, 'clientWidth', 'get').mockImplementation(() => height);
}
resizeTo (dimensions) {
this.setHeightTo(dimensions.height);
this.setWidthTo(dimensions.width);
triggerEvent(window, 'resize');
}
scrollBy (scrollPosition) {
document.documentElement.scrollTop = scrollPosition;
triggerEvent(window, 'scroll');
}
reset () {
window.innerHeight = this._defaults.height;
window.innerWidth = this._defaults.width;
document.documentElement.scrollTop = 0;
// reset all spies
Object.keys(this._spies).forEach(key => {
const objectSpies = this._spies[key];
Object.keys(objectSpies).forEach(key => objectSpies[key].mockClear());
});
}
}
// function to ask certain questions of a DOM Element
const element = function (el) {
return new ElementQuery(el);
@@ -82,3 +142,4 @@ const element = function (el) {
exports.triggerEvent = triggerEvent;
exports.element = element;
exports.WindowMock = WindowMock;

View File

@@ -0,0 +1,6 @@
// set up jQuery
window.jQuery = require('jquery');
$ = window.jQuery;
// load module code
require('govuk_frontend_toolkit/javascripts/govuk/modules.js');

View File

@@ -0,0 +1,4 @@
window.jQuery = null;
$ = null;
delete window.GOVUK;