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); }); }); });