diff options
Diffstat (limited to 'packages/turbo-test-utils')
| -rw-r--r-- | packages/turbo-test-utils/README.md | 3 | ||||
| -rw-r--r-- | packages/turbo-test-utils/package.json | 40 | ||||
| -rw-r--r-- | packages/turbo-test-utils/src/index.ts | 9 | ||||
| -rw-r--r-- | packages/turbo-test-utils/src/mockEnv.ts | 12 | ||||
| -rw-r--r-- | packages/turbo-test-utils/src/spyConsole.ts | 25 | ||||
| -rw-r--r-- | packages/turbo-test-utils/src/spyExit.ts | 21 | ||||
| -rw-r--r-- | packages/turbo-test-utils/src/useFixtures.ts | 89 | ||||
| -rw-r--r-- | packages/turbo-test-utils/src/validateLogs.ts | 27 | ||||
| -rw-r--r-- | packages/turbo-test-utils/tsconfig.json | 6 |
9 files changed, 232 insertions, 0 deletions
diff --git a/packages/turbo-test-utils/README.md b/packages/turbo-test-utils/README.md new file mode 100644 index 0000000..60b6382 --- /dev/null +++ b/packages/turbo-test-utils/README.md @@ -0,0 +1,3 @@ +# `@turbo/test-utils` + +Internal package of generic testing utilities shared between [turborepo/packages/](https://github.com/vercel/turbo/tree/main/packages) diff --git a/packages/turbo-test-utils/package.json b/packages/turbo-test-utils/package.json new file mode 100644 index 0000000..ff3f7f9 --- /dev/null +++ b/packages/turbo-test-utils/package.json @@ -0,0 +1,40 @@ +{ + "name": "@turbo/test-utils", + "version": "0.0.0", + "private": true, + "description": "", + "homepage": "https://turbo.build/repo", + "keywords": [], + "author": "Vercel", + "main": "src/index.ts", + "license": "MPL-2.0", + "repository": { + "type": "git", + "url": "https://github.com/vercel/turbo", + "directory": "packages/turbo-test-utils" + }, + "bugs": { + "url": "https://github.com/vercel/turbo/issues" + }, + "scripts": { + "lint": "eslint src/**/*.ts", + "check-types": "tsc --noEmit" + }, + "devDependencies": { + "@types/fs-extra": "^9.0.13", + "@types/jest": "^27.4.0", + "@types/js-yaml": "^4.0.5", + "@types/node": "^16.11.12", + "@types/uuid": "^9.0.0", + "jest": "^27.4.3", + "ts-jest": "^27.1.1", + "@turbo/tsconfig": "workspace:*", + "typescript": "^4.7.4" + }, + "dependencies": { + "fs-extra": "^11.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.3", + "uuid": "^9.0.0" + } +} diff --git a/packages/turbo-test-utils/src/index.ts b/packages/turbo-test-utils/src/index.ts new file mode 100644 index 0000000..07d0496 --- /dev/null +++ b/packages/turbo-test-utils/src/index.ts @@ -0,0 +1,9 @@ +export { default as setupTestFixtures } from "./useFixtures"; +export { default as validateLogs } from "./validateLogs"; +export { default as mockEnv } from "./mockEnv"; + +export { default as spyExit } from "./spyExit"; +export type { SpyExit } from "./spyExit"; + +export { default as spyConsole } from "./spyConsole"; +export type { SpyConsole } from "./spyConsole"; diff --git a/packages/turbo-test-utils/src/mockEnv.ts b/packages/turbo-test-utils/src/mockEnv.ts new file mode 100644 index 0000000..31909b0 --- /dev/null +++ b/packages/turbo-test-utils/src/mockEnv.ts @@ -0,0 +1,12 @@ +export default function mockEnv() { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...OLD_ENV }; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); +} diff --git a/packages/turbo-test-utils/src/spyConsole.ts b/packages/turbo-test-utils/src/spyConsole.ts new file mode 100644 index 0000000..61722a5 --- /dev/null +++ b/packages/turbo-test-utils/src/spyConsole.ts @@ -0,0 +1,25 @@ +export type SpyConsole = { log?: any; error?: any; warn?: any }; + +export default function spyConsole() { + let spy: SpyConsole = {}; + + beforeEach(() => { + spy.log = jest.spyOn(console, "log").mockImplementation(() => {}); + spy.error = jest.spyOn(console, "error").mockImplementation(() => {}); + spy.warn = jest.spyOn(console, "warn").mockImplementation(() => {}); + }); + + afterEach(() => { + spy.log.mockClear(); + spy.error.mockClear(); + spy.warn.mockClear(); + }); + + afterAll(() => { + spy.log.mockRestore(); + spy.error.mockRestore(); + spy.warn.mockRestore(); + }); + + return spy; +} diff --git a/packages/turbo-test-utils/src/spyExit.ts b/packages/turbo-test-utils/src/spyExit.ts new file mode 100644 index 0000000..1df9844 --- /dev/null +++ b/packages/turbo-test-utils/src/spyExit.ts @@ -0,0 +1,21 @@ +export type SpyExit = { exit?: any }; + +export default function spyExit() { + let spy: SpyExit = {}; + + beforeEach(() => { + spy.exit = jest + .spyOn(process, "exit") + .mockImplementation(() => undefined as never); + }); + + afterEach(() => { + spy.exit.mockClear(); + }); + + afterAll(() => { + spy.exit.mockRestore(); + }); + + return spy; +} diff --git a/packages/turbo-test-utils/src/useFixtures.ts b/packages/turbo-test-utils/src/useFixtures.ts new file mode 100644 index 0000000..2c47f5a --- /dev/null +++ b/packages/turbo-test-utils/src/useFixtures.ts @@ -0,0 +1,89 @@ +import { v4 as uuidv4 } from "uuid"; +import path from "path"; +import fs from "fs-extra"; +import yaml from "js-yaml"; +import JSON5 from "json5"; + +export default function setupTestFixtures({ + directory, + test = "", +}: { + directory: string; + test?: string; +}) { + const fixtures: Array<string> = []; + const parentDirectory = path.join(directory, test ? test : "test-runs"); + + afterEach(() => { + fixtures.forEach((fixture) => { + fs.rmSync(fixture, { recursive: true, force: true }); + }); + }); + + afterAll(() => { + fs.rmSync(parentDirectory, { recursive: true, force: true }); + }); + + const useFixture = ({ fixture }: { fixture: string }) => { + const directoryName = uuidv4(); + const testDirectory = path.join(parentDirectory, directoryName); + if (!fs.existsSync(testDirectory)) { + fs.mkdirSync(testDirectory, { recursive: true }); + } + // keep track of it + fixtures.push(testDirectory); + + // copy fixture to test directory + const fixturePath = path.join(directory, "__fixtures__", test, fixture); + fs.copySync(fixturePath, testDirectory, { + recursive: true, + }); + + const getFilePath = (filename: string) => { + return path.isAbsolute(filename) + ? filename + : path.join(testDirectory, filename); + }; + + const readGenerator = (method: (filePath: string) => unknown) => { + return <T>(filename: string) => { + try { + return method(getFilePath(filename)) as T; + } catch (e) { + return undefined; + } + }; + }; + + const write = ( + filename: string, + content: string | NodeJS.ArrayBufferView + ) => { + fs.writeFileSync(getFilePath(filename), content); + }; + + const exists = (filename: string): boolean => { + return fs.existsSync(getFilePath(filename)); + }; + + const read = readGenerator((filePath) => fs.readFileSync(filePath, "utf8")); + const readJson = readGenerator((filePath) => + JSON5.parse(fs.readFileSync(filePath, "utf8")) + ); + const readYaml = readGenerator((filePath) => + yaml.load(fs.readFileSync(filePath, "utf8")) + ); + + return { + root: testDirectory, + read, + readJson, + readYaml, + write, + exists, + directoryName, + }; + }; + + return { useFixture }; +} diff --git a/packages/turbo-test-utils/src/validateLogs.ts b/packages/turbo-test-utils/src/validateLogs.ts new file mode 100644 index 0000000..b8e59ac --- /dev/null +++ b/packages/turbo-test-utils/src/validateLogs.ts @@ -0,0 +1,27 @@ +import { SpyConsole } from "./spyConsole"; + +export default function validateLogs( + logs: Array<string | (() => boolean | Array<any>)>, + mockConsole: SpyConsole["log"] | SpyConsole["error"], + options: { prefix?: string } = {} +) { + logs.forEach((log, idx) => { + if (typeof log === "function") { + const expected = log(); + expect(mockConsole).toHaveBeenNthCalledWith( + idx + 1, + ...(Array.isArray(expected) ? expected : [expected]) + ); + } else { + if (options.prefix) { + expect(mockConsole).toHaveBeenNthCalledWith( + idx + 1, + options.prefix, + log + ); + } else { + expect(mockConsole).toHaveBeenNthCalledWith(idx + 1, log); + } + } + }); +} diff --git a/packages/turbo-test-utils/tsconfig.json b/packages/turbo-test-utils/tsconfig.json new file mode 100644 index 0000000..0620a3c --- /dev/null +++ b/packages/turbo-test-utils/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@turbo/tsconfig/library.json", + "compilerOptions": { + "rootDir": "." + } +} |
