From f6f1e26e7e68305f164efcb4823d2c95e154e2d6 Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Wed, 29 Sep 2021 12:11:44 +0100 Subject: [PATCH] Add to globals from jsdom for frontend unit tests (#5283) * Add to globals from JSDOM for frontend unit tests * Fix tests GitOrigin-RevId: 3a73477d9e4c3316ab2c9510ce3360740c3feb53 --- services/web/package-lock.json | 6 +++ services/web/package.json | 1 + services/web/test/frontend/bootstrap.js | 29 +++++------- .../shared/hooks/use-persisted-state.test.js | 44 +++++++++---------- 4 files changed, 41 insertions(+), 39 deletions(-) diff --git a/services/web/package-lock.json b/services/web/package-lock.json index 2510374c4d..dbe3317c56 100644 --- a/services/web/package-lock.json +++ b/services/web/package-lock.json @@ -6036,6 +6036,12 @@ "chalk": "^4.0.0" } }, + "@juggle/resize-observer": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.1.tgz", + "integrity": "sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw==", + "dev": true + }, "@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", diff --git a/services/web/package.json b/services/web/package.json index 15e54815c8..afc493e38a 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -180,6 +180,7 @@ }, "devDependencies": { "@babel/register": "^7.14.5", + "@juggle/resize-observer": "^3.3.1", "@storybook/addon-a11y": "^6.2.9", "@storybook/addon-essentials": "^6.2.9", "@storybook/react": "^6.2.9", diff --git a/services/web/test/frontend/bootstrap.js b/services/web/test/frontend/bootstrap.js index c124511f35..b5a8c81801 100644 --- a/services/web/test/frontend/bootstrap.js +++ b/services/web/test/frontend/bootstrap.js @@ -8,9 +8,6 @@ require('jsdom-global')(undefined, { url: 'https://www.test-overleaf.com/', }) -// workaround for "keys.js in jsdom-global doesn't include AbortController" -global.AbortController = window.AbortController - const path = require('path') process.env.SHARELATEX_CONFIG = path.resolve( __dirname, @@ -80,20 +77,18 @@ moment.updateLocale('en', { }, }) -let inMemoryLocalStorage = {} -Object.defineProperty(global, 'localStorage', { - value: { - // localStorage returns `null` when the item does not exist - getItem: key => - inMemoryLocalStorage[key] !== undefined - ? inMemoryLocalStorage[key] - : null, - setItem: (key, value) => (inMemoryLocalStorage[key] = value), - clear: () => (inMemoryLocalStorage = {}), - removeItem: key => delete inMemoryLocalStorage[key], - }, - writable: true, -}) +// workaround for missing keys in jsdom-global's keys.js +global.AbortController = window.AbortController +global.MutationObserver = window.MutationObserver +global.StorageEvent = window.StorageEvent +global.SVGElement = window.SVGElement +global.localStorage = window.localStorage +global.performance = window.performance +global.requestAnimationFrame = window.requestAnimationFrame +global.sessionStorage = window.sessionStorage + +// add polyfill for ResizeObserver +global.ResizeObserver = window.ResizeObserver = require('@juggle/resize-observer').ResizeObserver // node-fetch doesn't accept relative URL's: https://github.com/node-fetch/node-fetch/blob/master/docs/v2-LIMITS.md#known-differences const fetch = require('node-fetch') diff --git a/services/web/test/frontend/shared/hooks/use-persisted-state.test.js b/services/web/test/frontend/shared/hooks/use-persisted-state.test.js index 5dcc4077ba..d75dc51655 100644 --- a/services/web/test/frontend/shared/hooks/use-persisted-state.test.js +++ b/services/web/test/frontend/shared/hooks/use-persisted-state.test.js @@ -7,9 +7,9 @@ import localStorage from '../../../../frontend/js/infrastructure/local-storage' describe('usePersistedState', function () { beforeEach(function () { - sinon.spy(global.localStorage, 'getItem') - sinon.spy(global.localStorage, 'removeItem') - sinon.spy(global.localStorage, 'setItem') + sinon.spy(window.Storage.prototype, 'getItem') + sinon.spy(window.Storage.prototype, 'removeItem') + sinon.spy(window.Storage.prototype, 'setItem') }) afterEach(function () { @@ -19,7 +19,7 @@ describe('usePersistedState', function () { it('reads the value from localStorage', function () { const key = 'test' localStorage.setItem(key, 'foo') - expect(global.localStorage.setItem).to.have.callCount(1) + expect(window.Storage.prototype.setItem).to.have.callCount(1) const Test = () => { const [value] = usePersistedState(key) @@ -30,9 +30,9 @@ describe('usePersistedState', function () { render() screen.getByText('foo') - expect(global.localStorage.getItem).to.have.callCount(1) - expect(global.localStorage.removeItem).to.have.callCount(0) - expect(global.localStorage.setItem).to.have.callCount(1) + expect(window.Storage.prototype.getItem).to.have.callCount(1) + expect(window.Storage.prototype.removeItem).to.have.callCount(0) + expect(window.Storage.prototype.setItem).to.have.callCount(1) expect(localStorage.getItem(key)).to.equal('foo') }) @@ -49,9 +49,9 @@ describe('usePersistedState', function () { render() screen.getByText('foo') - expect(global.localStorage.getItem).to.have.callCount(1) - expect(global.localStorage.removeItem).to.have.callCount(0) - expect(global.localStorage.setItem).to.have.callCount(0) + expect(window.Storage.prototype.getItem).to.have.callCount(1) + expect(window.Storage.prototype.removeItem).to.have.callCount(0) + expect(window.Storage.prototype.setItem).to.have.callCount(0) expect(localStorage.getItem(key)).to.be.null }) @@ -59,7 +59,7 @@ describe('usePersistedState', function () { it('stores the new value in localStorage', function () { const key = 'test:store' localStorage.setItem(key, 'foo') - expect(global.localStorage.setItem).to.have.callCount(1) + expect(window.Storage.prototype.setItem).to.have.callCount(1) const Test = () => { const [value, setValue] = usePersistedState(key, 'bar') @@ -75,9 +75,9 @@ describe('usePersistedState', function () { screen.getByText('baz') - expect(global.localStorage.getItem).to.have.callCount(1) - expect(global.localStorage.removeItem).to.have.callCount(0) - expect(global.localStorage.setItem).to.have.callCount(2) + expect(window.Storage.prototype.getItem).to.have.callCount(1) + expect(window.Storage.prototype.removeItem).to.have.callCount(0) + expect(window.Storage.prototype.setItem).to.have.callCount(2) expect(localStorage.getItem(key)).to.equal('baz') }) @@ -85,7 +85,7 @@ describe('usePersistedState', function () { it('removes the value from localStorage if it equals the default value', function () { const key = 'test:store-default' localStorage.setItem(key, 'foo') - expect(global.localStorage.setItem).to.have.callCount(1) + expect(window.Storage.prototype.setItem).to.have.callCount(1) const Test = () => { const [value, setValue] = usePersistedState(key, 'bar') @@ -106,9 +106,9 @@ describe('usePersistedState', function () { screen.getByText('bar') - expect(global.localStorage.getItem).to.have.callCount(2) - expect(global.localStorage.removeItem).to.have.callCount(1) - expect(global.localStorage.setItem).to.have.callCount(2) + expect(window.Storage.prototype.getItem).to.have.callCount(2) + expect(window.Storage.prototype.removeItem).to.have.callCount(1) + expect(window.Storage.prototype.setItem).to.have.callCount(2) expect(localStorage.getItem(key)).to.be.null }) @@ -116,7 +116,7 @@ describe('usePersistedState', function () { it('handles function values', function () { const key = 'test:store' localStorage.setItem(key, 'foo') - expect(global.localStorage.setItem).to.have.callCount(1) + expect(window.Storage.prototype.setItem).to.have.callCount(1) const Test = () => { const [value, setValue] = usePersistedState(key) @@ -132,9 +132,9 @@ describe('usePersistedState', function () { screen.getByText('foobar') - expect(global.localStorage.getItem).to.have.callCount(1) - expect(global.localStorage.removeItem).to.have.callCount(0) - expect(global.localStorage.setItem).to.have.callCount(2) + expect(window.Storage.prototype.getItem).to.have.callCount(1) + expect(window.Storage.prototype.removeItem).to.have.callCount(0) + expect(window.Storage.prototype.setItem).to.have.callCount(2) expect(localStorage.getItem(key)).to.equal('foobar') })