diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/i18n.test.ts | 62 | ||||
-rw-r--r-- | test/mock-async-storage.ts | 3 | ||||
-rw-r--r-- | test/mock-file.ts | 6 | ||||
-rw-r--r-- | test/mock-i18n.ts | 5 | ||||
-rw-r--r-- | test/mock-react-native-image.ts | 20 | ||||
-rw-r--r-- | test/mock-reactotron.ts | 1 | ||||
-rw-r--r-- | test/setup.ts | 13 | ||||
-rw-r--r-- | test/storyshots.test.ts | 6 |
8 files changed, 116 insertions, 0 deletions
diff --git a/test/i18n.test.ts b/test/i18n.test.ts new file mode 100644 index 0000000..61a4963 --- /dev/null +++ b/test/i18n.test.ts @@ -0,0 +1,62 @@ +const en = require("../app/i18n/en.json") +const { exec } = require("child_process") + +// Use this array for keys that for whatever reason aren't greppable so they +// don't hold your test suite hostage by always failing. +const EXCEPTIONS = [ + // "welcomeScreen.readyForLaunch", +] + +function iterate(obj, stack, array) { + for (const property in obj) { + if (Object.prototype.hasOwnProperty.call(obj, property)) { + if (typeof obj[property] === "object") { + iterate(obj[property], `${stack}.${property}`, array) + } else { + array.push(`${stack.slice(1)}.${property}`) + } + } + } + + return array +} + +/** + * This tests your codebase for missing i18n strings so you can avoid error strings at render time + * + * It was taken from https://gist.github.com/Michaelvilleneuve/8808ba2775536665d95b7577c9d8d5a1 + * and modified slightly to account for our Ignite higher order components, + * which take 'tx' and 'fooTx' props. + * The grep command is nasty looking, but it's essentially searching the codebase for 3 things: + * + * tx="*" + * Tx="" + * translate("" + * + * and then grabs the i18n key between the double quotes + * + * This approach isn't 100% perfect. If you are storing your key string in a variable because you + * are setting it conditionally, then it won't be picked up. + * + */ + +describe("i18n", () => { + test("There are no missing keys", (done) => { + // Actual command output: + // grep "Tx=\"\S*\"\|tx=\"\S*\"\|translate(\"\S*\"" -ohr './app' | grep -o "\".*\"" + const command = `grep "Tx=\\"\\S*\\"\\|tx=\\"\\S*\\"\\|translate(\\"\\S*\\"" -ohr './app' | grep -o "\\".*\\""` + exec(command, (_, stdout) => { + const allTranslationsDefined = iterate(en, "", []) + const allTranslationsUsed = stdout.replace(/"/g, "").split("\n") + allTranslationsUsed.splice(-1, 1) + + for (let i = 0; i < allTranslationsUsed.length; i += 1) { + if (!EXCEPTIONS.includes(allTranslationsUsed[i])) { + // You can add keys to EXCEPTIONS (above) if you don't want them included in the test + expect(allTranslationsDefined).toContainEqual(allTranslationsUsed[i]) + } + } + done() + }) + }, 240000) +}) diff --git a/test/mock-async-storage.ts b/test/mock-async-storage.ts new file mode 100644 index 0000000..a4da056 --- /dev/null +++ b/test/mock-async-storage.ts @@ -0,0 +1,3 @@ +import mockAsyncStorage from "@react-native-async-storage/async-storage/jest/async-storage-mock" + +jest.mock("@react-native-async-storage/async-storage", () => mockAsyncStorage) diff --git a/test/mock-file.ts b/test/mock-file.ts new file mode 100644 index 0000000..5bf851a --- /dev/null +++ b/test/mock-file.ts @@ -0,0 +1,6 @@ +export default { + height: 100, + width: 100, + scale: 2.0, + uri: "https://placekitten.com/200/200", +} diff --git a/test/mock-i18n.ts b/test/mock-i18n.ts new file mode 100644 index 0000000..47a6417 --- /dev/null +++ b/test/mock-i18n.ts @@ -0,0 +1,5 @@ +jest.mock("i18n-js", () => { + return { + t: (key) => `${key}.test`, + } +}) diff --git a/test/mock-react-native-image.ts b/test/mock-react-native-image.ts new file mode 100644 index 0000000..eeae6bb --- /dev/null +++ b/test/mock-react-native-image.ts @@ -0,0 +1,20 @@ +import * as ReactNative from "react-native" +import mockFile from "./mock-file" + +jest.doMock("react-native", () => { + // Extend ReactNative + return Object.setPrototypeOf( + { + Image: { + ...ReactNative.Image, + resolveAssetSource: jest.fn((source) => mockFile), // eslint-disable-line @typescript-eslint/no-unused-vars + getSize: jest.fn(( + uri: string, // eslint-disable-line @typescript-eslint/no-unused-vars + success: (width: number, height: number) => void, + failure?: (error: any) => void, // eslint-disable-line @typescript-eslint/no-unused-vars + ) => success(100, 100)), + }, + }, + ReactNative, + ) +}) diff --git a/test/mock-reactotron.ts b/test/mock-reactotron.ts new file mode 100644 index 0000000..b3bb818 --- /dev/null +++ b/test/mock-reactotron.ts @@ -0,0 +1 @@ +declare const tron // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/test/setup.ts b/test/setup.ts new file mode 100644 index 0000000..c0137f2 --- /dev/null +++ b/test/setup.ts @@ -0,0 +1,13 @@ +// we always make sure 'react-native' gets included first +import "react-native" + +// libraries to mock +import "./mock-react-native-image" +import "./mock-async-storage" +import "./mock-i18n" +import "./mock-reactotron" + +jest.useFakeTimers() +declare global { + let __TEST__ +} diff --git a/test/storyshots.test.ts b/test/storyshots.test.ts new file mode 100644 index 0000000..337aed9 --- /dev/null +++ b/test/storyshots.test.ts @@ -0,0 +1,6 @@ +import initStoryshots from "@storybook/addon-storyshots" + +initStoryshots({ + configPath: "./storybook", + framework: "react-native", +}) |