aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/turbo-workspaces/__tests__
diff options
context:
space:
mode:
author简律纯 <hsiangnianian@outlook.com>2023-04-28 01:36:44 +0800
committer简律纯 <hsiangnianian@outlook.com>2023-04-28 01:36:44 +0800
commitdd84b9d64fb98746a230cd24233ff50a562c39c9 (patch)
treeb583261ef00b3afe72ec4d6dacb31e57779a6faf /packages/turbo-workspaces/__tests__
parent0b46fcd72ac34382387b2bcf9095233efbcc52f4 (diff)
downloadHydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.tar.gz
HydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.zip
Diffstat (limited to 'packages/turbo-workspaces/__tests__')
-rw-r--r--packages/turbo-workspaces/__tests__/index.test.ts85
-rw-r--r--packages/turbo-workspaces/__tests__/managers.test.ts285
-rw-r--r--packages/turbo-workspaces/__tests__/test-utils.ts153
3 files changed, 523 insertions, 0 deletions
diff --git a/packages/turbo-workspaces/__tests__/index.test.ts b/packages/turbo-workspaces/__tests__/index.test.ts
new file mode 100644
index 0000000..21753be
--- /dev/null
+++ b/packages/turbo-workspaces/__tests__/index.test.ts
@@ -0,0 +1,85 @@
+import path from "path";
+import * as turboUtils from "@turbo/utils";
+import { setupTestFixtures } from "@turbo/test-utils";
+import { getWorkspaceDetails, convert } from "../src";
+import { generateConvertMatrix } from "./test-utils";
+import execa from "execa";
+
+jest.mock("execa", () => jest.fn());
+
+describe("Node entrypoint", () => {
+ const { useFixture } = setupTestFixtures({
+ directory: path.join(__dirname, "../"),
+ });
+
+ describe("convert", () => {
+ test.each(generateConvertMatrix())(
+ "detects $fixtureType project using $fixtureManager and converts to $toManager (interactive=$interactive dry=$dry install=$install)",
+ async ({
+ fixtureManager,
+ fixtureType,
+ toManager,
+ interactive,
+ dry,
+ install,
+ }) => {
+ const mockedGetAvailablePackageManagers = jest
+ .spyOn(turboUtils, "getAvailablePackageManagers")
+ .mockResolvedValue({
+ npm: {
+ available: true,
+ version: "8.19.2",
+ },
+ yarn: {
+ available: true,
+ version: "1.22.19",
+ },
+ pnpm: {
+ available: true,
+ version: "7.29.1",
+ },
+ });
+
+ const { root } = useFixture({
+ fixture: `./${fixtureManager}/${fixtureType}`,
+ });
+
+ // read
+ const details = await getWorkspaceDetails({ root });
+ expect(details.packageManager).toBe(fixtureManager);
+
+ // convert
+ const convertWrapper = () =>
+ convert({
+ root,
+ to: toManager,
+ options: { interactive, dry, skipInstall: !install },
+ });
+
+ if (fixtureManager === toManager) {
+ await expect(convertWrapper()).rejects.toThrowError(
+ "You are already using this package manager"
+ );
+ } else {
+ await expect(convertWrapper()).resolves.toBeUndefined();
+ // read again
+ const convertedDetails = await getWorkspaceDetails({
+ root,
+ });
+ expect(mockedGetAvailablePackageManagers).toHaveBeenCalled();
+
+ if (dry) {
+ expect(convertedDetails.packageManager).toBe(fixtureManager);
+ } else {
+ if (install) {
+ expect(execa).toHaveBeenCalled();
+ }
+ expect(convertedDetails.packageManager).toBe(toManager);
+ }
+ }
+
+ mockedGetAvailablePackageManagers.mockRestore();
+ }
+ );
+ });
+});
diff --git a/packages/turbo-workspaces/__tests__/managers.test.ts b/packages/turbo-workspaces/__tests__/managers.test.ts
new file mode 100644
index 0000000..73c5073
--- /dev/null
+++ b/packages/turbo-workspaces/__tests__/managers.test.ts
@@ -0,0 +1,285 @@
+import path from "path";
+import { setupTestFixtures } from "@turbo/test-utils";
+import { Logger } from "../src/logger";
+import MANAGERS from "../src/managers";
+import { PackageJson } from "../src/types";
+import fs from "fs-extra";
+import {
+ generateDetectMatrix,
+ generateCreateMatrix,
+ generateRemoveMatrix,
+ generateReadMatrix,
+ generateCleanMatrix,
+ generateConvertLockMatrix,
+} from "./test-utils";
+
+jest.mock("execa", () => jest.fn());
+
+describe("managers", () => {
+ const { useFixture } = setupTestFixtures({
+ directory: path.join(__dirname, "../"),
+ });
+
+ describe("detect", () => {
+ test.each(generateDetectMatrix())(
+ "$project $type project detected by $manager manager - (expect: $result)",
+ async ({ project, manager, type, result }) => {
+ const { root } = useFixture({ fixture: `./${project}/${type}` });
+
+ const detectResult = await MANAGERS[manager].detect({
+ workspaceRoot: root,
+ });
+
+ expect(detectResult).toEqual(result);
+ }
+ );
+ });
+
+ describe("create", () => {
+ test.each(generateCreateMatrix())(
+ "creates $manager project from $project $type project (interactive=$interactive, dry=$dry)",
+ async ({ project, manager, type, interactive, dry }) => {
+ expect.assertions(2);
+
+ const { root } = useFixture({ fixture: `./${project}/${type}` });
+ const testProject = await MANAGERS[project].read({
+ workspaceRoot: root,
+ });
+
+ expect(testProject.packageManager).toEqual(project);
+
+ await MANAGERS[manager].create({
+ project: testProject,
+ to: { name: manager, version: "1.2.3" },
+ logger: new Logger({ interactive, dry }),
+ options: {
+ interactive,
+ dry,
+ },
+ });
+
+ if (dry) {
+ expect(
+ await MANAGERS[project].detect({ workspaceRoot: root })
+ ).toEqual(true);
+ } else {
+ expect(
+ await MANAGERS[manager].detect({ workspaceRoot: root })
+ ).toEqual(true);
+ }
+ }
+ );
+ });
+
+ describe("remove", () => {
+ test.each(generateRemoveMatrix())(
+ "removes $fixtureManager from $fixtureManager $fixtureType project when moving to $toManager (withNodeModules=$withNodeModules, interactive=$interactive, dry=$dry)",
+ async ({
+ fixtureManager,
+ fixtureType,
+ toManager,
+ withNodeModules,
+ interactive,
+ dry,
+ }) => {
+ const { root, readJson, readYaml } = useFixture({
+ fixture: `./${fixtureManager}/${fixtureType}`,
+ });
+ const project = await MANAGERS[fixtureManager].read({
+ workspaceRoot: root,
+ });
+ expect(project.packageManager).toEqual(fixtureManager);
+
+ if (withNodeModules) {
+ fs.ensureDirSync(project.paths.nodeModules);
+ }
+
+ await MANAGERS[fixtureManager].remove({
+ project,
+ to: { name: toManager, version: "1.2.3" },
+ logger: new Logger({ interactive, dry }),
+ options: {
+ interactive,
+ dry,
+ },
+ });
+
+ if (withNodeModules) {
+ expect(fs.existsSync(project.paths.nodeModules)).toEqual(dry);
+ }
+
+ const packageJson = readJson<PackageJson>(project.paths.packageJson);
+ if (dry) {
+ expect(packageJson?.packageManager).toBeDefined();
+ expect(packageJson?.packageManager?.split("@")[0]).toEqual(
+ fixtureManager
+ );
+ if (fixtureType === "basic") {
+ if (fixtureManager === "pnpm") {
+ expect(project.paths.workspaceConfig).toBeDefined();
+ if (project.paths.workspaceConfig) {
+ const workspaceConfig = readYaml<{ packages: Array<string> }>(
+ project.paths.workspaceConfig
+ );
+ expect(workspaceConfig?.packages).toBeDefined();
+ expect(workspaceConfig?.packages).toEqual(
+ project.workspaceData.globs
+ );
+ }
+ } else {
+ expect(packageJson?.workspaces).toBeDefined();
+ expect(packageJson?.workspaces).toEqual(
+ project.workspaceData.globs
+ );
+ }
+ }
+ } else {
+ expect(packageJson?.packageManager).toBeUndefined();
+ if (fixtureType === "basic") {
+ expect(packageJson?.workspaces).toBeUndefined();
+
+ if (fixtureManager === "pnpm") {
+ expect(project.paths.workspaceConfig).toBeDefined();
+ if (project.paths.workspaceConfig) {
+ const workspaceConfig = readYaml<{ packages: Array<string> }>(
+ project.paths.workspaceConfig
+ );
+ expect(workspaceConfig).toBeUndefined();
+ }
+ }
+ }
+ }
+ }
+ );
+ });
+
+ describe("read", () => {
+ test.each(generateReadMatrix())(
+ "reads $toManager workspaces from $fixtureManager $fixtureType project - (shouldThrow: $shouldThrow)",
+ async ({ fixtureManager, fixtureType, toManager, shouldThrow }) => {
+ const { root, directoryName } = useFixture({
+ fixture: `./${fixtureManager}/${fixtureType}`,
+ });
+
+ const read = async () =>
+ MANAGERS[toManager].read({ workspaceRoot: path.join(root) });
+ if (shouldThrow) {
+ if (toManager === "pnpm") {
+ expect(read).rejects.toThrow(`Not a pnpm project`);
+ } else if (toManager === "yarn") {
+ expect(read).rejects.toThrow(`Not a yarn project`);
+ } else if (toManager === "npm") {
+ expect(read).rejects.toThrow(`Not an npm project`);
+ }
+ return;
+ }
+ const project = await MANAGERS[toManager].read({
+ workspaceRoot: path.join(root),
+ });
+
+ expect(project.name).toEqual(
+ fixtureType === "monorepo" ? `${toManager}-workspaces` : toManager
+ );
+ expect(project.packageManager).toEqual(toManager);
+
+ // paths
+ expect(project.paths.root).toMatch(
+ new RegExp(`^.*\/${directoryName}$`)
+ );
+ expect(project.paths.packageJson).toMatch(
+ new RegExp(`^.*\/${directoryName}\/package.json$`)
+ );
+
+ if (fixtureManager === "pnpm") {
+ new RegExp(`^.*\/${directoryName}\/pnpm-lock.yaml$`);
+ } else if (fixtureManager === "yarn") {
+ new RegExp(`^.*\/${directoryName}\/yarn.lock$`);
+ } else if (fixtureManager === "npm") {
+ new RegExp(`^.*\/${directoryName}\/package-lock.json$`);
+ } else {
+ throw new Error("Invalid fixtureManager");
+ }
+
+ if (fixtureType === "non-monorepo") {
+ expect(project.workspaceData.workspaces).toEqual([]);
+ expect(project.workspaceData.globs).toEqual([]);
+ } else {
+ expect(project.workspaceData.globs).toEqual(["apps/*", "packages/*"]);
+ project.workspaceData.workspaces.forEach((workspace) => {
+ const type = ["web", "docs"].includes(workspace.name)
+ ? "apps"
+ : "packages";
+ expect(workspace.paths.packageJson).toMatch(
+ new RegExp(
+ `^.*${directoryName}\/${type}\/${workspace.name}\/package.json$`
+ )
+ );
+ expect(workspace.paths.root).toMatch(
+ new RegExp(`^.*${directoryName}\/${type}\/${workspace.name}$`)
+ );
+ });
+ }
+ }
+ );
+ });
+
+ describe("clean", () => {
+ test.each(generateCleanMatrix())(
+ "cleans $fixtureManager $fixtureType project (interactive=$interactive, dry=$dry)",
+ async ({ fixtureManager, fixtureType, interactive, dry }) => {
+ const { root } = useFixture({
+ fixture: `./${fixtureManager}/${fixtureType}`,
+ });
+
+ const project = await MANAGERS[fixtureManager].read({
+ workspaceRoot: root,
+ });
+
+ expect(project.packageManager).toEqual(fixtureManager);
+
+ await MANAGERS[fixtureManager].clean({
+ project,
+ logger: new Logger({ interactive, dry }),
+ options: {
+ interactive,
+ dry,
+ },
+ });
+
+ expect(fs.existsSync(project.paths.lockfile)).toEqual(dry);
+ }
+ );
+ });
+
+ describe("convertLock", () => {
+ test.each(generateConvertLockMatrix())(
+ "converts lockfile for $fixtureManager $fixtureType project to $toManager format (interactive=$interactive, dry=$dry)",
+ async ({ fixtureManager, fixtureType, toManager, interactive, dry }) => {
+ const { root, exists } = useFixture({
+ fixture: `./${fixtureManager}/${fixtureType}`,
+ });
+
+ const project = await MANAGERS[fixtureManager].read({
+ workspaceRoot: root,
+ });
+
+ expect(project.packageManager).toEqual(fixtureManager);
+
+ await MANAGERS[toManager].convertLock({
+ project,
+ logger: new Logger(),
+ options: {
+ interactive,
+ dry,
+ },
+ });
+
+ if (fixtureManager !== toManager) {
+ expect(exists(project.paths.lockfile)).toEqual(dry);
+ } else {
+ expect(exists(project.paths.lockfile)).toEqual(true);
+ }
+ }
+ );
+ });
+});
diff --git a/packages/turbo-workspaces/__tests__/test-utils.ts b/packages/turbo-workspaces/__tests__/test-utils.ts
new file mode 100644
index 0000000..4d6c7c9
--- /dev/null
+++ b/packages/turbo-workspaces/__tests__/test-utils.ts
@@ -0,0 +1,153 @@
+import { PackageManager } from "../src/types";
+
+const PACKAGE_MANAGERS: Array<PackageManager> = ["pnpm", "npm", "yarn"];
+const REPO_TYPES = ["monorepo", "non-monorepo"];
+const BOOLEAN_OPTIONS = [true, false];
+
+export function generateConvertMatrix() {
+ const matrix = [];
+ for (const fixtureManager of PACKAGE_MANAGERS) {
+ for (const fixtureType of REPO_TYPES) {
+ for (const toManager of PACKAGE_MANAGERS) {
+ for (const interactive of BOOLEAN_OPTIONS) {
+ for (const dry of BOOLEAN_OPTIONS) {
+ for (const install of BOOLEAN_OPTIONS) {
+ matrix.push({
+ fixtureManager,
+ fixtureType,
+ toManager,
+ interactive,
+ dry,
+ install,
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+ return matrix;
+}
+
+export function generateDetectMatrix() {
+ const matrix = [];
+ for (const project of PACKAGE_MANAGERS) {
+ for (const manager of PACKAGE_MANAGERS) {
+ for (const type of REPO_TYPES) {
+ matrix.push({
+ project,
+ manager,
+ type,
+ result: project === manager,
+ });
+ }
+ }
+ }
+ return matrix;
+}
+
+export function generateCreateMatrix() {
+ const matrix = [];
+ for (const project of PACKAGE_MANAGERS) {
+ for (const manager of PACKAGE_MANAGERS) {
+ for (const type of REPO_TYPES) {
+ for (const interactive of BOOLEAN_OPTIONS) {
+ for (const dry of BOOLEAN_OPTIONS) {
+ matrix.push({
+ project,
+ manager,
+ type,
+ interactive,
+ dry,
+ });
+ }
+ }
+ }
+ }
+ }
+ return matrix;
+}
+
+export function generateReadMatrix() {
+ const matrix = [];
+ for (const fixtureManager of PACKAGE_MANAGERS) {
+ for (const fixtureType of REPO_TYPES) {
+ for (const toManager of PACKAGE_MANAGERS) {
+ matrix.push({
+ fixtureManager,
+ fixtureType,
+ toManager,
+ shouldThrow: fixtureManager !== toManager,
+ });
+ }
+ }
+ }
+
+ return matrix;
+}
+
+export function generateRemoveMatrix() {
+ const matrix = [];
+ for (const fixtureManager of PACKAGE_MANAGERS) {
+ for (const fixtureType of REPO_TYPES) {
+ for (const toManager of PACKAGE_MANAGERS) {
+ for (const withNodeModules of BOOLEAN_OPTIONS) {
+ for (const interactive of BOOLEAN_OPTIONS) {
+ for (const dry of BOOLEAN_OPTIONS) {
+ matrix.push({
+ fixtureManager,
+ fixtureType,
+ withNodeModules,
+ toManager,
+ interactive,
+ dry,
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+ return matrix;
+}
+
+export function generateCleanMatrix() {
+ const matrix = [];
+ for (const fixtureManager of PACKAGE_MANAGERS) {
+ for (const fixtureType of REPO_TYPES) {
+ for (const interactive of BOOLEAN_OPTIONS) {
+ for (const dry of BOOLEAN_OPTIONS) {
+ matrix.push({
+ fixtureManager,
+ fixtureType,
+ interactive,
+ dry,
+ });
+ }
+ }
+ }
+ }
+ return matrix;
+}
+
+export function generateConvertLockMatrix() {
+ const matrix = [];
+ for (const fixtureManager of PACKAGE_MANAGERS) {
+ for (const fixtureType of REPO_TYPES) {
+ for (const toManager of PACKAGE_MANAGERS) {
+ for (const interactive of BOOLEAN_OPTIONS) {
+ for (const dry of BOOLEAN_OPTIONS) {
+ matrix.push({
+ fixtureManager,
+ fixtureType,
+ toManager,
+ interactive,
+ dry,
+ });
+ }
+ }
+ }
+ }
+ }
+ return matrix;
+}