From c978bd5caa0be32ffc290de9d884d00172e2fbe0 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 19 Jan 2024 12:22:08 +0100 Subject: [PATCH 1/9] start migrating jest files to TypeScript --- jest/{setup.js => setup.ts} | 2 +- jest/{setupAfterEnv.js => setupAfterEnv.ts} | 0 jest/{setupMockImages.js => setupMockImages.ts} | 8 ++------ src/types/modules/react-native-clipboard.d.ts | 16 ++++++++++++++++ 4 files changed, 19 insertions(+), 7 deletions(-) rename jest/{setup.js => setup.ts} (96%) rename jest/{setupAfterEnv.js => setupAfterEnv.ts} (100%) rename jest/{setupMockImages.js => setupMockImages.ts} (87%) create mode 100644 src/types/modules/react-native-clipboard.d.ts diff --git a/jest/setup.js b/jest/setup.ts similarity index 96% rename from jest/setup.js rename to jest/setup.ts index 38b4b55a68b3..ff53f957331d 100644 --- a/jest/setup.js +++ b/jest/setup.ts @@ -34,6 +34,6 @@ jest.spyOn(console, 'debug').mockImplementation((...params) => { // This mock is required for mocking file systems when running tests jest.mock('react-native-fs', () => ({ - unlink: jest.fn(() => new Promise((res) => res())), + unlink: jest.fn(() => new Promise((res) => res())), CachesDirectoryPath: jest.fn(), })); diff --git a/jest/setupAfterEnv.js b/jest/setupAfterEnv.ts similarity index 100% rename from jest/setupAfterEnv.js rename to jest/setupAfterEnv.ts diff --git a/jest/setupMockImages.js b/jest/setupMockImages.ts similarity index 87% rename from jest/setupMockImages.js rename to jest/setupMockImages.ts index 10925aca8736..c48797b3c07b 100644 --- a/jest/setupMockImages.js +++ b/jest/setupMockImages.ts @@ -1,14 +1,10 @@ import fs from 'fs'; import path from 'path'; -import _ from 'underscore'; -/** - * @param {String} imagePath - */ -function mockImages(imagePath) { +function mockImages(imagePath: string) { const imageFilenames = fs.readdirSync(path.resolve(__dirname, `../assets/${imagePath}/`)); // eslint-disable-next-line rulesdir/prefer-early-return - _.each(imageFilenames, (fileName) => { + imageFilenames.forEach((fileName) => { if (/\.svg/.test(fileName)) { jest.mock(`../assets/${imagePath}/${fileName}`, () => () => ''); } diff --git a/src/types/modules/react-native-clipboard.d.ts b/src/types/modules/react-native-clipboard.d.ts new file mode 100644 index 000000000000..14f418a3f8b9 --- /dev/null +++ b/src/types/modules/react-native-clipboard.d.ts @@ -0,0 +1,16 @@ +declare module '@react-native-clipboard/clipboard/jest/clipboard-mock' { + const mockClipboard: { + getString: jest.MockedFunction<() => Promise>; + getImagePNG: jest.MockedFunction<() => void>; + getImageJPG: jest.MockedFunction<() => void>; + setImage: jest.MockedFunction<() => void>; + setString: jest.MockedFunction<() => void>; + hasString: jest.MockedFunction<() => Promise>; + hasImage: jest.MockedFunction<() => Promise>; + hasURL: jest.MockedFunction<() => Promise>; + addListener: jest.MockedFunction<() => void>; + removeAllListeners: jest.MockedFunction<() => void>; + useClipboard: jest.MockedFunction<() => [string, jest.MockedFunction<() => void>]>; + }; + export default mockClipboard; +} From 0219ab460341e5cdf1618808b041132f7826a1b3 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 29 Jan 2024 15:12:24 +0100 Subject: [PATCH 2/9] migrate jest setup files to TypeScript --- jest/setup.ts | 3 ++- src/types/modules/mockStorage.d.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/types/modules/mockStorage.d.ts diff --git a/jest/setup.ts b/jest/setup.ts index ff53f957331d..29a3a043cfe7 100644 --- a/jest/setup.ts +++ b/jest/setup.ts @@ -1,6 +1,7 @@ import mockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock'; import '@shopify/flash-list/jestSetup'; import 'react-native-gesture-handler/jestSetup'; +import mockStorage from 'react-native-onyx/lib/storage/__mocks__'; import * as reanimatedJestUtils from 'react-native-reanimated/src/reanimated2/jestUtils'; import 'setimmediate'; import setupMockImages from './setupMockImages'; @@ -19,7 +20,7 @@ jest.mock('@react-native-clipboard/clipboard', () => mockClipboard); // Mock react-native-onyx storage layer because the SQLite storage layer doesn't work in jest. // Mocking this file in __mocks__ does not work because jest doesn't support mocking files that are not directly used in the testing project, // and we only want to mock the storage layer, not the whole Onyx module. -jest.mock('react-native-onyx/lib/storage', () => require('react-native-onyx/lib/storage/__mocks__')); +jest.mock('react-native-onyx/lib/storage', () => mockStorage); // Turn off the console logs for timing events. They are not relevant for unit tests and create a lot of noise jest.spyOn(console, 'debug').mockImplementation((...params) => { diff --git a/src/types/modules/mockStorage.d.ts b/src/types/modules/mockStorage.d.ts new file mode 100644 index 000000000000..61d4accd82af --- /dev/null +++ b/src/types/modules/mockStorage.d.ts @@ -0,0 +1,27 @@ +declare module 'react-native-onyx/lib/storage/__mocks__' { + const mockStorage: { + idbKeyvalSet: jest.MockedFunction<() => Promise>; + setItem: jest.MockedFunction<() => Promise>; + getItem: jest.MockedFunction<() => Promise>; + removeItem: jest.MockedFunction<() => Promise>; + removeItems: jest.MockedFunction<() => Promise>; + clear: jest.MockedFunction<() => Promise>; + getAllKeys: jest.MockedFunction<() => Promise>; + config: jest.MockedFunction<() => void>; + multiGet: jest.MockedFunction<() => Promise>; + multiSet: jest.MockedFunction<() => Promise>; + multiMerge: jest.MockedFunction<() => Promise>; + mergeItem: jest.MockedFunction<() => Promise>; + getStorageMap: jest.MockedFunction<() => unknown>; + setInitialMockData: jest.MockedFunction<(data: unknown) => void>; + getDatabaseSize: jest.MockedFunction< + () => Promise<{ + bytesRemaining: number; + bytesUsed: number; + }> + >; + setMemoryOnlyKeys: jest.MockedFunction<() => void>; + }; + + export default mockStorage; +} From 6cdf088114314447c546467025d465568ef8f690 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 29 Jan 2024 15:19:49 +0100 Subject: [PATCH 3/9] update jest config --- jest.config.js | 2 +- tests/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jest.config.js b/jest.config.js index de7ed4b1f974..be1e64933d61 100644 --- a/jest.config.js +++ b/jest.config.js @@ -22,7 +22,7 @@ module.exports = { doNotFake: ['nextTick'], }, testEnvironment: 'jsdom', - setupFiles: ['/jest/setup.js', './node_modules/@react-native-google-signin/google-signin/jest/build/setup.js'], + setupFiles: ['/jest/setup.ts', './node_modules/@react-native-google-signin/google-signin/jest/build/setup.js'], setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect', '/jest/setupAfterEnv.js', '/tests/perf-test/setupAfterEnv.js'], cacheDirectory: '/.jest-cache', moduleNameMapper: { diff --git a/tests/README.md b/tests/README.md index 6170006cb9bb..08c750f75829 100644 --- a/tests/README.md +++ b/tests/README.md @@ -45,9 +45,9 @@ const policies = createCollection( ); ``` -## Mocking `node_modules`, user modules, and what belongs in `jest/setup.js` +## Mocking `node_modules`, user modules, and what belongs in `jest/setup.ts` -If you need to mock a library that exists in `node_modules` then add it to the `__mocks__` folder in the root of the project. More information about this [here](https://jestjs.io/docs/manual-mocks#mocking-node-modules). If you need to mock an individual library you should create a mock module in a `__mocks__` subdirectory adjacent to the library as explained [here](https://jestjs.io/docs/manual-mocks#mocking-user-modules). However, keep in mind that when you do this you also must manually require the mock by calling something like `jest.mock('../../src/libs/Log');` at the top of an individual test file. If every test in the app will need something to be mocked that's a good case for adding it to `jest/setup.js`, but we should generally avoid adding user mocks or `node_modules` mocks to this file. Please use the `__mocks__` subdirectories wherever appropriate. +If you need to mock a library that exists in `node_modules` then add it to the `__mocks__` folder in the root of the project. More information about this [here](https://jestjs.io/docs/manual-mocks#mocking-node-modules). If you need to mock an individual library you should create a mock module in a `__mocks__` subdirectory adjacent to the library as explained [here](https://jestjs.io/docs/manual-mocks#mocking-user-modules). However, keep in mind that when you do this you also must manually require the mock by calling something like `jest.mock('../../src/libs/Log');` at the top of an individual test file. If every test in the app will need something to be mocked that's a good case for adding it to `jest/setup.ts`, but we should generally avoid adding user mocks or `node_modules` mocks to this file. Please use the `__mocks__` subdirectories wherever appropriate. ## Assertions From cc9f23cc260c63fd4527390212a5ba535e7e6e78 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 29 Jan 2024 15:23:00 +0100 Subject: [PATCH 4/9] update setupAfterEnv extension in jest config --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index be1e64933d61..59f7ef25ae88 100644 --- a/jest.config.js +++ b/jest.config.js @@ -23,7 +23,7 @@ module.exports = { }, testEnvironment: 'jsdom', setupFiles: ['/jest/setup.ts', './node_modules/@react-native-google-signin/google-signin/jest/build/setup.js'], - setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect', '/jest/setupAfterEnv.js', '/tests/perf-test/setupAfterEnv.js'], + setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect', '/jest/setupAfterEnv.ts', '/tests/perf-test/setupAfterEnv.ts'], cacheDirectory: '/.jest-cache', moduleNameMapper: { '\\.(lottie)$': '/__mocks__/fileMock.js', From 979a2bf88d32e86bed501573d62e68a0f3ee951e Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 29 Jan 2024 15:27:06 +0100 Subject: [PATCH 5/9] change extension for perf setupAfterEnv --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index 59f7ef25ae88..b347db593d83 100644 --- a/jest.config.js +++ b/jest.config.js @@ -23,7 +23,7 @@ module.exports = { }, testEnvironment: 'jsdom', setupFiles: ['/jest/setup.ts', './node_modules/@react-native-google-signin/google-signin/jest/build/setup.js'], - setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect', '/jest/setupAfterEnv.ts', '/tests/perf-test/setupAfterEnv.ts'], + setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect', '/jest/setupAfterEnv.ts', '/tests/perf-test/setupAfterEnv.js'], cacheDirectory: '/.jest-cache', moduleNameMapper: { '\\.(lottie)$': '/__mocks__/fileMock.js', From 87beb79f6d29a8b168ff5861291399e122eb0b4f Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Tue, 30 Jan 2024 11:23:58 +0100 Subject: [PATCH 6/9] replace storage mocks import with require --- jest/setup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jest/setup.ts b/jest/setup.ts index 29a3a043cfe7..cbadc675783c 100644 --- a/jest/setup.ts +++ b/jest/setup.ts @@ -1,7 +1,6 @@ import mockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock'; import '@shopify/flash-list/jestSetup'; import 'react-native-gesture-handler/jestSetup'; -import mockStorage from 'react-native-onyx/lib/storage/__mocks__'; import * as reanimatedJestUtils from 'react-native-reanimated/src/reanimated2/jestUtils'; import 'setimmediate'; import setupMockImages from './setupMockImages'; @@ -20,7 +19,8 @@ jest.mock('@react-native-clipboard/clipboard', () => mockClipboard); // Mock react-native-onyx storage layer because the SQLite storage layer doesn't work in jest. // Mocking this file in __mocks__ does not work because jest doesn't support mocking files that are not directly used in the testing project, // and we only want to mock the storage layer, not the whole Onyx module. -jest.mock('react-native-onyx/lib/storage', () => mockStorage); +// eslint-disable-next-line @typescript-eslint/no-unsafe-return +jest.mock('react-native-onyx/lib/storage', () => require('react-native-onyx/lib/storage/__mocks__')); // Turn off the console logs for timing events. They are not relevant for unit tests and create a lot of noise jest.spyOn(console, 'debug').mockImplementation((...params) => { From 7d4568fbe859100185ffcc45529bee3b4d64d531 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Tue, 30 Jan 2024 12:50:55 +0100 Subject: [PATCH 7/9] fix import paths --- jest/setup.ts | 4 ++-- src/types/modules/mockStorage.d.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jest/setup.ts b/jest/setup.ts index cbadc675783c..1d5d55d941f5 100644 --- a/jest/setup.ts +++ b/jest/setup.ts @@ -1,6 +1,7 @@ import mockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock'; import '@shopify/flash-list/jestSetup'; import 'react-native-gesture-handler/jestSetup'; +import storageMock from 'react-native-onyx/dist/storage/__mocks__'; import * as reanimatedJestUtils from 'react-native-reanimated/src/reanimated2/jestUtils'; import 'setimmediate'; import setupMockImages from './setupMockImages'; @@ -19,8 +20,7 @@ jest.mock('@react-native-clipboard/clipboard', () => mockClipboard); // Mock react-native-onyx storage layer because the SQLite storage layer doesn't work in jest. // Mocking this file in __mocks__ does not work because jest doesn't support mocking files that are not directly used in the testing project, // and we only want to mock the storage layer, not the whole Onyx module. -// eslint-disable-next-line @typescript-eslint/no-unsafe-return -jest.mock('react-native-onyx/lib/storage', () => require('react-native-onyx/lib/storage/__mocks__')); +jest.mock('react-native-onyx/dist/storage', () => storageMock); // Turn off the console logs for timing events. They are not relevant for unit tests and create a lot of noise jest.spyOn(console, 'debug').mockImplementation((...params) => { diff --git a/src/types/modules/mockStorage.d.ts b/src/types/modules/mockStorage.d.ts index 61d4accd82af..1bf8b18fae79 100644 --- a/src/types/modules/mockStorage.d.ts +++ b/src/types/modules/mockStorage.d.ts @@ -1,4 +1,4 @@ -declare module 'react-native-onyx/lib/storage/__mocks__' { +declare module 'react-native-onyx/dist/storage/__mocks__' { const mockStorage: { idbKeyvalSet: jest.MockedFunction<() => Promise>; setItem: jest.MockedFunction<() => Promise>; From f64e4a11cbe323ce339504bd88edf523a6789854 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Tue, 30 Jan 2024 12:53:40 +0100 Subject: [PATCH 8/9] change storage mock name --- jest/setup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jest/setup.ts b/jest/setup.ts index 1d5d55d941f5..68d904fac5be 100644 --- a/jest/setup.ts +++ b/jest/setup.ts @@ -1,7 +1,7 @@ import mockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock'; import '@shopify/flash-list/jestSetup'; import 'react-native-gesture-handler/jestSetup'; -import storageMock from 'react-native-onyx/dist/storage/__mocks__'; +import mockStorage from 'react-native-onyx/dist/storage/__mocks__'; import * as reanimatedJestUtils from 'react-native-reanimated/src/reanimated2/jestUtils'; import 'setimmediate'; import setupMockImages from './setupMockImages'; @@ -20,7 +20,7 @@ jest.mock('@react-native-clipboard/clipboard', () => mockClipboard); // Mock react-native-onyx storage layer because the SQLite storage layer doesn't work in jest. // Mocking this file in __mocks__ does not work because jest doesn't support mocking files that are not directly used in the testing project, // and we only want to mock the storage layer, not the whole Onyx module. -jest.mock('react-native-onyx/dist/storage', () => storageMock); +jest.mock('react-native-onyx/dist/storage', () => mockStorage); // Turn off the console logs for timing events. They are not relevant for unit tests and create a lot of noise jest.spyOn(console, 'debug').mockImplementation((...params) => { From ac8cc9f342839cfbc3c443b56a655d483a6307ce Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 2 Feb 2024 10:38:44 +0100 Subject: [PATCH 9/9] remove unnecessary declaration file --- src/types/modules/mockStorage.d.ts | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 src/types/modules/mockStorage.d.ts diff --git a/src/types/modules/mockStorage.d.ts b/src/types/modules/mockStorage.d.ts deleted file mode 100644 index 1bf8b18fae79..000000000000 --- a/src/types/modules/mockStorage.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -declare module 'react-native-onyx/dist/storage/__mocks__' { - const mockStorage: { - idbKeyvalSet: jest.MockedFunction<() => Promise>; - setItem: jest.MockedFunction<() => Promise>; - getItem: jest.MockedFunction<() => Promise>; - removeItem: jest.MockedFunction<() => Promise>; - removeItems: jest.MockedFunction<() => Promise>; - clear: jest.MockedFunction<() => Promise>; - getAllKeys: jest.MockedFunction<() => Promise>; - config: jest.MockedFunction<() => void>; - multiGet: jest.MockedFunction<() => Promise>; - multiSet: jest.MockedFunction<() => Promise>; - multiMerge: jest.MockedFunction<() => Promise>; - mergeItem: jest.MockedFunction<() => Promise>; - getStorageMap: jest.MockedFunction<() => unknown>; - setInitialMockData: jest.MockedFunction<(data: unknown) => void>; - getDatabaseSize: jest.MockedFunction< - () => Promise<{ - bytesRemaining: number; - bytesUsed: number; - }> - >; - setMemoryOnlyKeys: jest.MockedFunction<() => void>; - }; - - export default mockStorage; -}