diff options
author | Kristóf Marussy <kristof@marussy.com> | 2021-12-31 01:52:28 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2021-12-31 01:56:30 +0100 |
commit | 7108c642f4ff6dc5f0c4d30b8a8960064ff8e90f (patch) | |
tree | f8c0450a6e1b62f7e7f8470efd375b3659b91b2b /packages/preload | |
parent | refactor: Install devtools extensions earlier (diff) | |
download | sophie-7108c642f4ff6dc5f0c4d30b8a8960064ff8e90f.tar.gz sophie-7108c642f4ff6dc5f0c4d30b8a8960064ff8e90f.tar.zst sophie-7108c642f4ff6dc5f0c4d30b8a8960064ff8e90f.zip |
test: Add tests for main package
- Changed jest to run from the root package and reference the packages
as projects. This required moving the base jest config file away from
the project root.
- Module isolation seems to prevent ts-jest from loading the shared
package, so we disabled it for now.
- To better facilitate mocking, services should be split into interfaces
and implementation
- Had to downgrade to chald 4.1.2 as per
https://github.com/chalk/chalk/releases/tag/v5.0.0 at least until
https://github.com/microsoft/TypeScript/issues/46452 is resolved.
Diffstat (limited to 'packages/preload')
-rw-r--r-- | packages/preload/esbuild.config.js | 5 | ||||
-rw-r--r-- | packages/preload/jest.config.js | 2 | ||||
-rw-r--r-- | packages/preload/package.json | 3 | ||||
-rw-r--r-- | packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts | 36 | ||||
-rw-r--r-- | packages/preload/tsconfig.json | 3 |
5 files changed, 27 insertions, 22 deletions
diff --git a/packages/preload/esbuild.config.js b/packages/preload/esbuild.config.js index de51fc5..b73a071 100644 --- a/packages/preload/esbuild.config.js +++ b/packages/preload/esbuild.config.js | |||
@@ -1,5 +1,6 @@ | |||
1 | import { chrome, fileURLToDirname } from '../../config/build-common.js'; | 1 | import { chrome } from '../../config/buildConstants.js'; |
2 | import { getConfig } from '../../config/esbuild-config.js'; | 2 | import { getConfig } from '../../config/esbuildConfig.js'; |
3 | import { fileURLToDirname } from '../../config/utils.js'; | ||
3 | 4 | ||
4 | export default getConfig({ | 5 | export default getConfig({ |
5 | absWorkingDir: fileURLToDirname(import.meta.url), | 6 | absWorkingDir: fileURLToDirname(import.meta.url), |
diff --git a/packages/preload/jest.config.js b/packages/preload/jest.config.js index faecf9a..e474c4c 100644 --- a/packages/preload/jest.config.js +++ b/packages/preload/jest.config.js | |||
@@ -1,4 +1,4 @@ | |||
1 | import rootConfig from '../../jest.config.js'; | 1 | import rootConfig from '../../config/jest.config.base.js'; |
2 | 2 | ||
3 | /** @type {import('ts-jest').InitialOptionsTsJest} */ | 3 | /** @type {import('ts-jest').InitialOptionsTsJest} */ |
4 | export default { | 4 | export default { |
diff --git a/packages/preload/package.json b/packages/preload/package.json index e6dd0ee..9818ba8 100644 --- a/packages/preload/package.json +++ b/packages/preload/package.json | |||
@@ -6,7 +6,6 @@ | |||
6 | "type": "module", | 6 | "type": "module", |
7 | "types": "dist-types/index.d.ts", | 7 | "types": "dist-types/index.d.ts", |
8 | "scripts": { | 8 | "scripts": { |
9 | "test": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js", | ||
10 | "typecheck": "tsc" | 9 | "typecheck": "tsc" |
11 | }, | 10 | }, |
12 | "dependencies": { | 11 | "dependencies": { |
@@ -16,7 +15,7 @@ | |||
16 | "mobx-state-tree": "^5.1.0" | 15 | "mobx-state-tree": "^5.1.0" |
17 | }, | 16 | }, |
18 | "devDependencies": { | 17 | "devDependencies": { |
19 | "@types/jest": "^27.0.3", | 18 | "@types/jest": "^27.4.0", |
20 | "jest": "^27.4.5", | 19 | "jest": "^27.4.5", |
21 | "jest-mock": "^27.4.2", | 20 | "jest-mock": "^27.4.2", |
22 | "jsdom": "^19.0.0", | 21 | "jsdom": "^19.0.0", |
diff --git a/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts b/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts index 41937c2..fdd1cc5 100644 --- a/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts +++ b/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts | |||
@@ -18,7 +18,7 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { describe, it, jest } from '@jest/globals'; | 21 | import { jest } from '@jest/globals'; |
22 | import { mocked } from 'jest-mock'; | 22 | import { mocked } from 'jest-mock'; |
23 | import log from 'loglevel'; | 23 | import log from 'loglevel'; |
24 | import type { IJsonPatch } from 'mobx-state-tree'; | 24 | import type { IJsonPatch } from 'mobx-state-tree'; |
@@ -67,7 +67,9 @@ const invalidAction = { | |||
67 | action: 'not-a-valid-action', | 67 | action: 'not-a-valid-action', |
68 | } as unknown as Action; | 68 | } as unknown as Action; |
69 | 69 | ||
70 | log.disableAll(); | 70 | beforeAll(() => { |
71 | log.disableAll(); | ||
72 | }); | ||
71 | 73 | ||
72 | describe('createSophieRenderer', () => { | 74 | describe('createSophieRenderer', () => { |
73 | it('registers a shared store patch listener', () => { | 75 | it('registers a shared store patch listener', () => { |
@@ -95,59 +97,59 @@ describe('SophieRendererImpl', () => { | |||
95 | }); | 97 | }); |
96 | 98 | ||
97 | describe('onSharedStoreChange', () => { | 99 | describe('onSharedStoreChange', () => { |
98 | it('requests a snapshot from the main process', async () => { | 100 | it('should request a snapshot from the main process', async () => { |
99 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot); | 101 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot); |
100 | await sut.onSharedStoreChange(listener); | 102 | await sut.onSharedStoreChange(listener); |
101 | expect(ipcRenderer.invoke).toBeCalledWith(RendererToMainIpcMessage.GetSharedStoreSnapshot); | 103 | expect(ipcRenderer.invoke).toBeCalledWith(RendererToMainIpcMessage.GetSharedStoreSnapshot); |
102 | expect(listener.onSnapshot).toBeCalledWith(snapshot); | 104 | expect(listener.onSnapshot).toBeCalledWith(snapshot); |
103 | }); | 105 | }); |
104 | 106 | ||
105 | it('catches IPC errors without exposing them', async () => { | 107 | it('should catch IPC errors without exposing them', async () => { |
106 | mocked(ipcRenderer.invoke).mockRejectedValue(new Error('s3cr3t')); | 108 | mocked(ipcRenderer.invoke).mockRejectedValue(new Error('s3cr3t')); |
107 | await expect(sut.onSharedStoreChange(listener)).rejects.not.toHaveProperty( | 109 | await expect(sut.onSharedStoreChange(listener)).rejects.not.toHaveProperty( |
108 | 'message', | 110 | 'message', |
109 | expect.stringMatching(/s3cr3t/), | 111 | expect.stringMatching(/s3cr3t/), |
110 | ); | 112 | ); |
111 | expect(listener.onSnapshot).toBeCalledTimes(0); | 113 | expect(listener.onSnapshot).not.toBeCalled(); |
112 | }); | 114 | }); |
113 | 115 | ||
114 | it('does not pass on invalid snapshots', async () => { | 116 | it('should not pass on invalid snapshots', async () => { |
115 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(invalidSnapshot); | 117 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(invalidSnapshot); |
116 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); | 118 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); |
117 | expect(listener.onSnapshot).toBeCalledTimes(0); | 119 | expect(listener.onSnapshot).not.toBeCalled(); |
118 | }); | 120 | }); |
119 | }); | 121 | }); |
120 | 122 | ||
121 | describe('dispatchAction', () => { | 123 | describe('dispatchAction', () => { |
122 | it('dispatched valid actions', () => { | 124 | it('should dispatch valid actions', () => { |
123 | sut.dispatchAction(action); | 125 | sut.dispatchAction(action); |
124 | expect(ipcRenderer.send).toBeCalledWith(RendererToMainIpcMessage.DispatchAction, action); | 126 | expect(ipcRenderer.send).toBeCalledWith(RendererToMainIpcMessage.DispatchAction, action); |
125 | }); | 127 | }); |
126 | 128 | ||
127 | it('does not dispatch invalid actions', () => { | 129 | it('should not dispatch invalid actions', () => { |
128 | expect(() => sut.dispatchAction(invalidAction)).toThrowError(); | 130 | expect(() => sut.dispatchAction(invalidAction)).toThrowError(); |
129 | expect(ipcRenderer.send).toBeCalledTimes(0); | 131 | expect(ipcRenderer.send).not.toBeCalled(); |
130 | }); | 132 | }); |
131 | }); | 133 | }); |
132 | 134 | ||
133 | describe('when no listener is registered', () => { | 135 | describe('when no listener is registered', () => { |
134 | it('discards the received patch without any error', () => { | 136 | it('should discard the received patch without any error', () => { |
135 | onSharedStorePatch(event, patch); | 137 | onSharedStorePatch(event, patch); |
136 | }); | 138 | }); |
137 | }); | 139 | }); |
138 | 140 | ||
139 | function itRefusesToRegisterAnotherListener() { | 141 | function itRefusesToRegisterAnotherListener() { |
140 | it('refuses to register another listener', async () => { | 142 | it('should refuse to register another listener', async () => { |
141 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); | 143 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); |
142 | }); | 144 | }); |
143 | } | 145 | } |
144 | 146 | ||
145 | function itDoesNotPassPatchesToTheListener( | 147 | function itDoesNotPassPatchesToTheListener( |
146 | name: string = 'does not pass patches to the listener', | 148 | name: string = 'should not pass patches to the listener', |
147 | ) { | 149 | ) { |
148 | it(name, () => { | 150 | it(name, () => { |
149 | onSharedStorePatch(event, patch); | 151 | onSharedStorePatch(event, patch); |
150 | expect(listener.onPatch).toBeCalledTimes(0); | 152 | expect(listener.onPatch).not.toBeCalled(); |
151 | }); | 153 | }); |
152 | } | 154 | } |
153 | 155 | ||
@@ -157,12 +159,12 @@ describe('SophieRendererImpl', () => { | |||
157 | await sut.onSharedStoreChange(listener); | 159 | await sut.onSharedStoreChange(listener); |
158 | }); | 160 | }); |
159 | 161 | ||
160 | it('passes patches to the listener', () => { | 162 | it('should pass patches to the listener', () => { |
161 | onSharedStorePatch(event, patch); | 163 | onSharedStorePatch(event, patch); |
162 | expect(listener.onPatch).toBeCalledWith(patch); | 164 | expect(listener.onPatch).toBeCalledWith(patch); |
163 | }); | 165 | }); |
164 | 166 | ||
165 | it('catches listener errors', () => { | 167 | it('should catch listener errors', () => { |
166 | mocked(listener.onPatch).mockImplementation(() => { throw new Error(); }); | 168 | mocked(listener.onPatch).mockImplementation(() => { throw new Error(); }); |
167 | onSharedStorePatch(event, patch); | 169 | onSharedStorePatch(event, patch); |
168 | }); | 170 | }); |
@@ -176,7 +178,7 @@ describe('SophieRendererImpl', () => { | |||
176 | listener.onPatch.mockRestore(); | 178 | listener.onPatch.mockRestore(); |
177 | }); | 179 | }); |
178 | 180 | ||
179 | itDoesNotPassPatchesToTheListener('does not pass on patches any more'); | 181 | itDoesNotPassPatchesToTheListener('should not pass on patches any more'); |
180 | }); | 182 | }); |
181 | }); | 183 | }); |
182 | 184 | ||
diff --git a/packages/preload/tsconfig.json b/packages/preload/tsconfig.json index 0f27305..741d435 100644 --- a/packages/preload/tsconfig.json +++ b/packages/preload/tsconfig.json | |||
@@ -6,6 +6,9 @@ | |||
6 | "dom", | 6 | "dom", |
7 | "dom.iterable", | 7 | "dom.iterable", |
8 | "esnext" | 8 | "esnext" |
9 | ], | ||
10 | "types": [ | ||
11 | "@types/jest" | ||
9 | ] | 12 | ] |
10 | }, | 13 | }, |
11 | "references": [ | 14 | "references": [ |