diff --git a/.github/workflows/jest-testing.yml b/.github/workflows/jest-testing.yml new file mode 100644 index 00000000..f534eb2a --- /dev/null +++ b/.github/workflows/jest-testing.yml @@ -0,0 +1,38 @@ +name: Run Jest Tests + +on: + push: + branches: + - development +jobs: + test: + permissions: write-all + name: Run Jest Tests + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.10.0" + + - name: Install dependencies + run: yarn install + + - name: Run tests + run: yarn test | tee ./coverage.txt && exit ${PIPESTATUS[0]} + + - name: Jest Coverage Comment + # Ensures this step is run even on previous step failure (e.g. test failed) + if: always() + uses: MishaKav/jest-coverage-comment@main + with: + coverage-summary-path: coverage/coverage-summary.json + junitxml-path: junit.xml + junitxml-title: JUnit + coverage-path: ./coverage.txt diff --git a/.github/workflows/test-links.yml b/.github/workflows/test-links.yml deleted file mode 100644 index 8016ea5a..00000000 --- a/.github/workflows/test-links.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Run Jest Tests - -on: - push: - -jobs: - test: - name: Run Jest Tests - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: "20.10.0" - - - name: Install dependencies - run: yarn install - - - name: Run tests - run: yarn test diff --git a/jest.config.ts b/jest.config.ts index f4423578..1eb02783 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,13 +1,16 @@ import { config } from "dotenv"; +import type { Config } from "jest"; config(); const GITHUB_TOKEN = process.env.GITHUB_TOKEN; const OPENAI_API_KEY = process.env.OPENAI_API_KEY; process.argv = ["path/to/node", "path/to/script", `--auth`, `${GITHUB_TOKEN}`, "--open-ai", `${OPENAI_API_KEY}`]; -export default { +const cfg: Config = { transform: { "^.+\\.tsx?$": "babel-jest", }, moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], }; + +export default cfg; diff --git a/package.json b/package.json index 3f452144..40c6bea2 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "node": ">=20.10.0" }, "scripts": { - "test": "jest", + "test": "jest --setupFiles dotenv/config --coverage", "start": "tsx src/start.ts", "format": "run-s format:lint format:prettier format:cspell", "format:lint": "eslint --fix .", diff --git a/src/data-collection/collect-linked-pulls.test.ts b/src/data-collection/collect-linked-pulls.test.ts index 117f2940..5aa90f37 100644 --- a/src/data-collection/collect-linked-pulls.test.ts +++ b/src/data-collection/collect-linked-pulls.test.ts @@ -1,4 +1,3 @@ -import { config } from "dotenv"; import { IssueParams, parseGitHubUrl } from "../start"; import ISSUE_CROSS_REPO_LINK from "./fixtures/issue-89.json"; // pr188 is linked to this issue @@ -15,14 +14,6 @@ const PARAMS_ISSUE_NO_LINK: IssueParams = parseGitHubUrl(ISSUE_NO_LINK.html_url) // const PARAMS_PR_CROSS_REPO_LINK: IssueParams = parseGitHubUrl(PR_CROSS_REPO_LINK.html_url); // const PARAMS_PR_SAME_REPO_LINK: IssueParams = parseGitHubUrl(PR_SAME_REPO_LINK.html_url); -config(); -const GITHUB_TOKEN = process.env.GITHUB_TOKEN; -if (!GITHUB_TOKEN) { - console.warn("GITHUB_TOKEN is not set"); -} -// Mock process.argv -process.argv = ["path/to/node", "path/to/script", `--auth=${GITHUB_TOKEN}`]; - describe("Artificial scenarios for linking pull requests to issues", () => { it("should return an empty array when the issue does not have any associated link events", async () => { const result = await collectLinkedMergedPulls(PARAMS_ISSUE_NO_LINK); @@ -46,7 +37,9 @@ describe("Artificial scenarios for linking pull requests to issues", () => { describe("Real-world scenarios for linking pull requests to issues", () => { it("For the issue 'ubiquibot/comment-incentives/issues/22', the test should identify and return all the merged, linked pull requests that originate from this issue within the same repository 'ubiquibot/comment-incentives'", async () => { - const result = await collectLinkedMergedPulls(parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/22")); + const result = await collectLinkedMergedPulls( + parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/22") + ); const expectedUrl = "https://github.com/ubiquibot/comment-incentives/pull/25"; result.forEach((res) => expect(res.source.issue.html_url).toMatch(/\/pull\/\d+$/)); const matchingLinks = result.filter((res) => res.source.issue.html_url === expectedUrl); @@ -62,7 +55,9 @@ describe("Real-world scenarios for linking pull requests to issues", () => { }); it("For the issue 'ubiquibot/comment-incentives/issues/3', the test should identify and return all the merged, linked pull requests that originate from this issue within the same repository 'ubiquibot/comment-incentives'", async () => { - const result = await collectLinkedMergedPulls(parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/3")); + const result = await collectLinkedMergedPulls( + parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/3") + ); const expectedUrl = "https://github.com/ubiquibot/comment-incentives/pull/4"; result.forEach((res) => expect(res.source.issue.html_url).toMatch(/\/pull\/\d+$/)); const matchingLinks = result.filter((res) => res.source.issue.html_url === expectedUrl); @@ -70,7 +65,9 @@ describe("Real-world scenarios for linking pull requests to issues", () => { }); it("For the issue 'ubiquibot/comment-incentives/issues/15', the test should identify and return all the merged, linked pull requests that originate from this issue within the same repository 'ubiquibot/comment-incentives'", async () => { - const result = await collectLinkedMergedPulls(parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/15")); + const result = await collectLinkedMergedPulls( + parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/15") + ); const expectedUrl = "https://github.com/ubiquibot/comment-incentives/pull/16"; result.forEach((res) => expect(res.source.issue.html_url).toMatch(/\/pull\/\d+$/)); const matchingLinks = result.filter((res) => res.source.issue.html_url === expectedUrl); @@ -78,8 +75,13 @@ describe("Real-world scenarios for linking pull requests to issues", () => { }); it("For the issue 'ubiquibot/comment-incentives/issues/19', the test should identify and return all the merged, linked pull requests that originate from this issue within the same repository 'ubiquibot/comment-incentives'", async () => { - const result = await collectLinkedMergedPulls(parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/19")); - const expectedUrls = ["https://github.com/ubiquibot/comment-incentives/pull/21", "https://github.com/ubiquibot/comment-incentives/pull/23"]; + const result = await collectLinkedMergedPulls( + parseGitHubUrl("https://github.com/ubiquibot/comment-incentives/issues/19") + ); + const expectedUrls = [ + "https://github.com/ubiquibot/comment-incentives/pull/21", + "https://github.com/ubiquibot/comment-incentives/pull/23", + ]; expectedUrls.forEach((url) => { const matchingLinks = result.filter((res) => res.source.issue.html_url === url); expect(matchingLinks.length).toBeGreaterThan(0); diff --git a/src/parser/command-line.ts b/src/parser/command-line.ts index 28c400b5..a724c96d 100644 --- a/src/parser/command-line.ts +++ b/src/parser/command-line.ts @@ -1,6 +1,14 @@ import { Command } from "@commander-js/extra-typings"; +import { config } from "dotenv"; import packageJson from "../../package.json"; +if (process.env.NODE_ENV === "test") { + config(); + const GITHUB_TOKEN = process.env.GITHUB_TOKEN; + const OPENAI_API_KEY = process.env.OPENAI_API_KEY; + process.argv = ["path/to/node", "path/to/script", `--auth`, `${GITHUB_TOKEN}`, "--open-ai", `${OPENAI_API_KEY}`]; +} + const program = new Command() .requiredOption("-a, --auth ", "GitHub authentication token") .requiredOption("-o, --open-ai ", "OpenAi authentication token")