From 435334ba9c9ba845189434eea3b620bc7fa05786 Mon Sep 17 00:00:00 2001 From: Tom Byers Date: Mon, 13 May 2019 14:45:00 +0100 Subject: [PATCH] Add tests for full-screen table module --- tests/javascripts/fullscreenTable.test.js | 370 ++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 tests/javascripts/fullscreenTable.test.js diff --git a/tests/javascripts/fullscreenTable.test.js b/tests/javascripts/fullscreenTable.test.js new file mode 100644 index 000000000..0db261211 --- /dev/null +++ b/tests/javascripts/fullscreenTable.test.js @@ -0,0 +1,370 @@ +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'); + require('../../app/assets/javascripts/fullscreenTable.js'); +}); + +afterAll(() => { + window.jQuery = null; + $ = null; + + delete window.GOVUK; +}); + +describe('FullscreenTable', () => { + let container; + let tableFrame; + let table; + let numberColumnFrame; + + function setWindowHeightTo (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 + jest.spyOn(document.documentElement, 'clientHeight', 'get').mockImplementation(() => height); + + }; + + function setWindowWidthTo (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 + jest.spyOn(document.documentElement, 'clientWidth', 'get').mockImplementation(() => height); + + }; + + function resizeWindowTo (dimensions) { + + setWindowHeightTo(dimensions.height); + setWindowWidthTo(dimensions.width); + helpers.triggerEvent(window, 'resize'); + + }; + + function scrollWindowBy (scrollTop) { + + document.documentElement.scrollTop = scrollTop; + helpers.triggerEvent(window, 'scroll'); + + }; + + function resetWindowDimensions () { + + setWindowHeightTo(768); + setWindowWidthTo(1024); + + }; + + function setElementDimensionsAndOffset (el, opts) { + + const elOffsetSpy = jest.spyOn(el, 'getBoundingClientRect'); + + if (opts.height) { + el.setAttribute('style', `height: ${opts.height}px`); + } + + if (opts.width) { + el.setAttribute('style', `width: ${opts.width}px`); + } + + if (opts.offset) { + elOffsetSpy.mockImplementation(() => opts.offset); + } + + }; + + function setElementWidth (el, width) { + + el.setAttribute('style', `.width: ${width}px`); + + }; + + 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 + `; + } 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; + + } + + // set up DOM + document.body.innerHTML = + `
+
+ + + + + ${tableHeadings()} + + + + ${tableRows()} + +
+ people.csv +
+
+
`; + + container = document.querySelector('.fullscreen-content'); + + }); + + afterEach(() => { + + document.body.innerHTML = ''; + + }); + + describe("when it loads", () => { + + beforeEach(() => { + + // start module + window.GOVUK.modules.start(); + + }); + + test("it fixes the number column for each row without changing the semantics", () => { + + 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'); + + }); + + }); + + describe("the height of the table should fit the vertical space available to it", () => { + + 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 + setWindowHeightTo(768); + setElementDimensionsAndOffset(container, { height: 1000, offset: { top: 500 } }); + + // start module + window.GOVUK.modules.start(); + + tableFrame = document.querySelector('.fullscreen-scrollable-table'); + numberColumnFrame = document.querySelector('.fullscreen-fixed-table'); + + }); + + afterEach(() => { + + jest.clearAllMocks(); + resetWindowDimensions(); + scrollWindowBy(0); + + }); + + 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) + scrollWindowBy(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) + resizeWindowTo({ 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) + setWindowWidthTo(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(() => { + + jest.clearAllMocks(); + resetWindowDimensions(); + scrollWindowBy(0); + + }); + + 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'); + resizeWindowTo({ 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); + + }); + + }); + +});