Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: execute a global hook for all hooking projects #15009

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Aetherall
Copy link

Summary

Hi :)

When specifying a global hook in a multi-project setup, the hook function gets the project configuration passed in second parameter. Its very handy to factorize the global hook definition.

Example of the factorized hook i am using ( long and not interesting but for reference )

/// @ddd-ts/tools/jest.setup.ts
import { exec } from "child_process"
import { writeFileSync } from "fs";
import { Config } from "jest";

type ProjectConfig = Config & {
  globals: {
    CURRENT_WORKSPACE: string;
    CURRENT_WORKSPACE_PATH: string;
    CURRENT_WORKSPACE_PRETEST: string;
    CURRENT_WORKSPACE_WAIT: string;
    CURRENT_WORKSPACE_POSTTEST: string;
  }
}

export default async (globalConfig: Config, projectConfig: ProjectConfig) => {
  console.log(`Setting up workspace ${projectConfig.globals.CURRENT_WORKSPACE}`)

  const cwd = projectConfig.globals.CURRENT_WORKSPACE_PATH

  const pretest = projectConfig.globals.CURRENT_WORKSPACE_PRETEST

  if (!pretest) {
    return;
  }

  console.log('[PRETEST] running')
  const pretestProcess = exec(pretest, { cwd })

  await new Promise<void>((resolve, reject) => {
    pretestProcess.on('error', reject)
    pretestProcess.on('exit', (code) => code ? reject() : resolve())
  })
  console.log('[PRETEST] finished')


  const wait = projectConfig.globals.CURRENT_WORKSPACE_WAIT

  if (!wait) {
    return;
  }

  console.log('[WAIT] running')
  const waitProcess = exec(wait, { cwd })

  await new Promise<void>((resolve, reject) => {
    waitProcess.on('error', reject)
    waitProcess.on('exit', (code) => code ? reject() : resolve())
  })
  console.log('[WAIT] finished')
}
/// @ddd-ts/tools/jest.config.ts
import type { Config } from "jest";
import { getPnpmWorkspaces, WorkspaceInfo } from "workspace-tools";

export const config = (workspace: WorkspaceInfo[number]) => ({
  displayName: workspace.name,
  rootDir: `${workspace.path}/src`,
  testEnvironment: "node",
  globals: {
    CURRENT_WORKSPACE: workspace.name,
    CURRENT_WORKSPACE_PATH: workspace.path,
    CURRENT_WORKSPACE_PRETEST: workspace.packageJson.scripts?.["pretest"],
    CURRENT_WORKSPACE_POSTTEST: workspace.packageJson.scripts?.["posttest"],
    CURRENT_WORKSPACE_WAIT: workspace.packageJson.scripts?.["wait"],
  },
  testMatch: ["**/*.spec.ts"],
  globalSetup: "../node_modules/@ddd-ts/tools/jest.setup.ts",
  globalTeardown: "../node_modules/@ddd-ts/tools/jest.teardown.ts",
  transform: {
    "^.+\\.(t|j)sx?$": [
      "@swc/jest",
      {
        jsc: {
          parser: {
            syntax: "typescript",
            decorators: true,
          },
        },
      },
    ],
  },
} satisfies Config);

export default () => {
  const cwd = process.cwd();
  const ws = getPnpmWorkspaces(cwd);
  const current = ws.find((w) => w.path === cwd);

  if (!current) {
    throw new Error("Could not find current workspace");
  }

  return config(current);
};
/// @ddd-ts/tools/jest.workspace.config.ts
import type { Config } from "jest";
import { getPnpmWorkspaces, WorkspaceInfo } from "workspace-tools";

export const config = (workspace: WorkspaceInfo[number]) => ({
  displayName: workspace.name,
  rootDir: `${workspace.path}/src`,
  testEnvironment: "node",
  globals: {
    CURRENT_WORKSPACE: workspace.name,
    CURRENT_WORKSPACE_PATH: workspace.path,
    CURRENT_WORKSPACE_PRETEST: workspace.packageJson.scripts?.["pretest"],
    CURRENT_WORKSPACE_POSTTEST: workspace.packageJson.scripts?.["posttest"],
    CURRENT_WORKSPACE_WAIT: workspace.packageJson.scripts?.["wait"],
  },
  testMatch: ["**/*.spec.ts"],
  globalSetup: "../node_modules/@ddd-ts/tools/jest.setup.ts",
  globalTeardown: "../node_modules/@ddd-ts/tools/jest.teardown.ts",
  transform: {
    "^.+\\.(t|j)sx?$": [
      "@swc/jest",
      {
        jsc: {
          parser: {
            syntax: "typescript",
            decorators: true,
          },
        },
      },
    ],
  },
} satisfies Config);

export default () => {
  const cwd = process.cwd();
  const ws = getPnpmWorkspaces(cwd);
  const current = ws.find((w) => w.path === cwd);

  if (!current) {
    throw new Error("Could not find current workspace");
  }

  return config(current);
};

With such a system, I am able to have a working configuration whether I run tests from the root of my monorepo or one of the packages, through any tooling, and with the capacity to boot the test environment of each package.

However, the current way of checking which global hook to run does not allow to reuse the same file.
After a lookup I found out this looks like a very simple issue to solve, so I gave it a shot.

Test plan

I've seen some e2e test folder, but I dont know where should I put this ? Can I add a test case to the existing globalHook suite ?

Thanks for your time !

Copy link

linux-foundation-easycla bot commented Apr 5, 2024

CLA Not Signed

Copy link

netlify bot commented Apr 5, 2024

Deploy Preview for jestjs ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 2fec7ed
🔍 Latest deploy log https://app.netlify.com/sites/jestjs/deploys/66104b8918b00f000884fcf3
😎 Deploy Preview https://deploy-preview-15009--jestjs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@Aetherall Aetherall force-pushed the elo/global-hook-one-file-many-outcomes branch from eabce89 to 2fec7ed Compare April 5, 2024 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant