diff --git a/app/assets/javascripts/fullscreenTable.js b/app/assets/javascripts/fullscreenTable.js
index 5a690022b..799e518d1 100644
--- a/app/assets/javascripts/fullscreenTable.js
+++ b/app/assets/javascripts/fullscreenTable.js
@@ -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();
diff --git a/package.json b/package.json
index 71c11b281..098318c9f 100644
--- a/package.json
+++ b/package.json
@@ -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"
},
diff --git a/tests/javascripts/autofocus.test.js b/tests/javascripts/autofocus.test.js
index 8419b2d62..cae67996f 100644
--- a/tests/javascripts/autofocus.test.js
+++ b/tests/javascripts/autofocus.test.js
@@ -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', () => {
diff --git a/tests/javascripts/collapsibleCheckboxes.test.js b/tests/javascripts/collapsibleCheckboxes.test.js
index b29a4d624..88cc74e17 100644
--- a/tests/javascripts/collapsibleCheckboxes.test.js
+++ b/tests/javascripts/collapsibleCheckboxes.test.js
@@ -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');
});
diff --git a/tests/javascripts/fullscreenTable.test.js b/tests/javascripts/fullscreenTable.test.js
new file mode 100644
index 000000000..c1130f1ce
--- /dev/null
+++ b/tests/javascripts/fullscreenTable.test.js
@@ -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 += `
+ Row in file${heading}
+ | `;
+ } else {
+ result += `
+ ${heading}
+ | `;
+ }
+ });
+
+ return result;
+ }
+
+ const rowCells = (cells) => {
+ let result = '';
+
+ Object.keys(cells).forEach((key, idx) => {
+ if (idx === 0) {
+ result += `
+
+ ${key}
+
+ | `;
+ } else {
+ result += `
+
+ ${key}
+
+ | `;
+ }
+ });
+
+ 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 += `${rowCells(row)}
`;
+ });
+
+ return result;
+
+ }
+
+ windowMock = new helpers.WindowMock(jest);
+
+ // set up DOM
+ document.body.innerHTML =
+ `
+
+
+
+ people.csv
+
+
+
+ ${tableHeadings()}
+
+
+
+ ${tableRows()}
+
+
+
+ `;
+
+ 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 ``, 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 ``, 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);
+
+ });
+
+ });
+
+});
diff --git a/tests/javascripts/jest.config.js b/tests/javascripts/jest.config.js
new file mode 100644
index 000000000..9fde149df
--- /dev/null
+++ b/tests/javascripts/jest.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ setupFiles: ['./support/setup.js']
+}
diff --git a/tests/javascripts/listEntry.test.js b/tests/javascripts/listEntry.test.js
index 80c67e3ae..dd58bdeb3 100644
--- a/tests/javascripts/listEntry.test.js
+++ b/tests/javascripts/listEntry.test.js
@@ -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", () => {
diff --git a/tests/javascripts/support/helpers.js b/tests/javascripts/support/helpers.js
index f951f317b..52ce86cda 100644
--- a/tests/javascripts/support/helpers.js
+++ b/tests/javascripts/support/helpers.js
@@ -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;
diff --git a/tests/javascripts/support/setup.js b/tests/javascripts/support/setup.js
new file mode 100644
index 000000000..be3fa1e6b
--- /dev/null
+++ b/tests/javascripts/support/setup.js
@@ -0,0 +1,6 @@
+// set up jQuery
+window.jQuery = require('jquery');
+$ = window.jQuery;
+
+// load module code
+require('govuk_frontend_toolkit/javascripts/govuk/modules.js');
diff --git a/tests/javascripts/support/teardown.js b/tests/javascripts/support/teardown.js
new file mode 100644
index 000000000..c7d00bf8b
--- /dev/null
+++ b/tests/javascripts/support/teardown.js
@@ -0,0 +1,4 @@
+window.jQuery = null;
+$ = null;
+
+delete window.GOVUK;