aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/turbo-test-utils
diff options
context:
space:
mode:
Diffstat (limited to 'packages/turbo-test-utils')
-rw-r--r--packages/turbo-test-utils/README.md3
-rw-r--r--packages/turbo-test-utils/package.json40
-rw-r--r--packages/turbo-test-utils/src/index.ts9
-rw-r--r--packages/turbo-test-utils/src/mockEnv.ts12
-rw-r--r--packages/turbo-test-utils/src/spyConsole.ts25
-rw-r--r--packages/turbo-test-utils/src/spyExit.ts21
-rw-r--r--packages/turbo-test-utils/src/useFixtures.ts89
-rw-r--r--packages/turbo-test-utils/src/validateLogs.ts27
-rw-r--r--packages/turbo-test-utils/tsconfig.json6
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": "."
+ }
+}