diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/main/src/infrastructure/config/impl/__tests__/ConfigFile.integ.test.ts | 34 | ||||
-rw-r--r-- | packages/test-utils/package.json | 4 | ||||
-rw-r--r-- | packages/test-utils/src/index.ts | 7 | ||||
-rw-r--r-- | packages/test-utils/src/testIf.ts | 70 |
4 files changed, 97 insertions, 18 deletions
diff --git a/packages/main/src/infrastructure/config/impl/__tests__/ConfigFile.integ.test.ts b/packages/main/src/infrastructure/config/impl/__tests__/ConfigFile.integ.test.ts index dd4aaaa..c443d99 100644 --- a/packages/main/src/infrastructure/config/impl/__tests__/ConfigFile.integ.test.ts +++ b/packages/main/src/infrastructure/config/impl/__tests__/ConfigFile.integ.test.ts | |||
@@ -29,10 +29,11 @@ import { | |||
29 | utimes, | 29 | utimes, |
30 | writeFile, | 30 | writeFile, |
31 | } from 'node:fs/promises'; | 31 | } from 'node:fs/promises'; |
32 | import { tmpdir } from 'node:os'; | 32 | import { platform, tmpdir, userInfo } from 'node:os'; |
33 | import path from 'node:path'; | 33 | import path from 'node:path'; |
34 | 34 | ||
35 | import { jest } from '@jest/globals'; | 35 | import { jest } from '@jest/globals'; |
36 | import { testIf } from '@sophie/test-utils'; | ||
36 | import { mocked } from 'jest-mock'; | 37 | import { mocked } from 'jest-mock'; |
37 | 38 | ||
38 | import Disposer from '../../../../utils/Disposer.js'; | 39 | import Disposer from '../../../../utils/Disposer.js'; |
@@ -249,19 +250,24 @@ describe('watchConfig', () => { | |||
249 | expect(callback).toHaveBeenCalled(); | 250 | expect(callback).toHaveBeenCalled(); |
250 | }); | 251 | }); |
251 | 252 | ||
252 | test('handles other filesystem errors', async () => { | 253 | // We can only cause a filesystem error by changing permissions if we run on a POSIX-like |
253 | const { mode } = await stat(userDataDir!); | 254 | // system and we aren't root (i.e., not in CI). |
254 | await writeFile(configFilePath, 'Hi Mars!', 'utf8'); | 255 | testIf(platform() !== 'win32' && userInfo().uid !== 0)( |
255 | // Remove permission to force a filesystem error. | 256 | 'handles other filesystem errors', |
256 | // eslint-disable-next-line no-bitwise -- Compute reduced permissions. | 257 | async () => { |
257 | await chmod(userDataDir!, mode & 0o666); | 258 | const { mode } = await stat(userDataDir!); |
258 | try { | 259 | await writeFile(configFilePath, 'Hi Mars!', 'utf8'); |
259 | await catchUpWithFilesystem(); | 260 | // Remove permission to force a filesystem error. |
260 | expect(callback).not.toHaveBeenCalled(); | 261 | // eslint-disable-next-line no-bitwise -- Compute reduced permissions. |
261 | } finally { | 262 | await chmod(userDataDir!, mode & 0o666); |
262 | await chmod(userDataDir!, mode); | 263 | try { |
263 | } | 264 | await catchUpWithFilesystem(); |
264 | }); | 265 | expect(callback).not.toHaveBeenCalled(); |
266 | } finally { | ||
267 | await chmod(userDataDir!, mode); | ||
268 | } | ||
269 | }, | ||
270 | ); | ||
265 | 271 | ||
266 | test('does not notify when the modification date is prior to the last write', async () => { | 272 | test('does not notify when the modification date is prior to the last write', async () => { |
267 | await repository.writeConfig('Hello World!'); | 273 | await repository.writeConfig('Hello World!'); |
diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 93f1626..8243cc5 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json | |||
@@ -10,6 +10,10 @@ | |||
10 | "types": "yarn g:types" | 10 | "types": "yarn g:types" |
11 | }, | 11 | }, |
12 | "dependencies": { | 12 | "dependencies": { |
13 | "@jest/globals": "^28.1.0", | ||
13 | "type-fest": "^2.13.0" | 14 | "type-fest": "^2.13.0" |
15 | }, | ||
16 | "devDependencies": { | ||
17 | "@jest/types": "^28.1.0" | ||
14 | } | 18 | } |
15 | } | 19 | } |
diff --git a/packages/test-utils/src/index.ts b/packages/test-utils/src/index.ts index 52ac98d..528b872 100644 --- a/packages/test-utils/src/index.ts +++ b/packages/test-utils/src/index.ts | |||
@@ -18,8 +18,7 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | ||
22 | eslint-disable-next-line import/prefer-default-export -- | ||
23 | Keep API consistent for more helpers in the future. | ||
24 | */ | ||
25 | export { default as fake } from './fake.js'; | 21 | export { default as fake } from './fake.js'; |
22 | |||
23 | export type { TestIf, TestIfConcurrent } from './testIf.js'; | ||
24 | export { default as testIf } from './testIf.js'; | ||
diff --git a/packages/test-utils/src/testIf.ts b/packages/test-utils/src/testIf.ts new file mode 100644 index 0000000..2309ddc --- /dev/null +++ b/packages/test-utils/src/testIf.ts | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import { test } from '@jest/globals'; | ||
22 | import type { Global } from '@jest/types'; | ||
23 | |||
24 | export interface TestIfConcurrent { | ||
25 | (condition: boolean): Global.ItConcurrentBase; | ||
26 | |||
27 | only(condition: boolean): Global.ItConcurrentBase; | ||
28 | |||
29 | skip(condition: boolean): Global.ItConcurrentBase; | ||
30 | } | ||
31 | |||
32 | export interface TestIf { | ||
33 | (condition: boolean): Global.ItBase; | ||
34 | |||
35 | only(condition: boolean): Global.ItBase; | ||
36 | |||
37 | skip(condition: boolean): Global.ItBase; | ||
38 | |||
39 | concurrent: TestIfConcurrent; | ||
40 | } | ||
41 | |||
42 | const testIfConcurrent: TestIfConcurrent = function concurrent( | ||
43 | condition: boolean, | ||
44 | ) { | ||
45 | return condition ? test.concurrent : test.concurrent.skip; | ||
46 | }; | ||
47 | |||
48 | testIfConcurrent.only = function only() { | ||
49 | return test.concurrent.only; | ||
50 | }; | ||
51 | |||
52 | testIfConcurrent.skip = function skip() { | ||
53 | return test.concurrent.skip; | ||
54 | }; | ||
55 | |||
56 | const testIf: TestIf = function testIf(condition: boolean) { | ||
57 | return condition ? test : test.skip; | ||
58 | }; | ||
59 | |||
60 | testIf.only = function only() { | ||
61 | return test.only; | ||
62 | }; | ||
63 | |||
64 | testIf.skip = function skip() { | ||
65 | return test.skip; | ||
66 | }; | ||
67 | |||
68 | testIf.concurrent = testIfConcurrent; | ||
69 | |||
70 | export default testIf; | ||