diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml new file mode 100644 index 0000000000000..4699b67d5ba15 --- /dev/null +++ b/.github/workflows/e2e-test.yml @@ -0,0 +1,20 @@ +name: Test Deployment +on: + deployment_status: + +jobs: + preview: + if: + github.event_name == 'deployment_status' && + github.event.deployment_status.state == 'success' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install dependencies + run: npm ci + env: + CI: true + - name: Run end-to-end tests. + run: npm run test:e2e + env: + VERCEL_PREVIEW_URL: ${{ github.event.deployment_status.target_url }} diff --git a/jest.config.js b/jest.config.js index 312d88ad8e023..b4578cf5aaad5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,4 +3,10 @@ export default { transform: {}, testEnvironment: "jsdom", coverageProvider: "v8", + testPathIgnorePatterns: ["/node_modules/", "/tests/e2e/"], + modulePathIgnorePatterns: ["/node_modules/", "/tests/e2e/"], + coveragePathIgnorePatterns: [ + "/node_modules/", + "/tests/E2E/", + ], }; diff --git a/jest.e2e.config.js b/jest.e2e.config.js new file mode 100644 index 0000000000000..656ab61f7c054 --- /dev/null +++ b/jest.e2e.config.js @@ -0,0 +1,7 @@ +export default { + clearMocks: true, + transform: {}, + testEnvironment: "node", + coverageProvider: "v8", + testMatch: ["/tests/e2e/**/*.test.js"], +}; diff --git a/package-lock.json b/package-lock.json index 2ffe6ec9008b2..2235a4b45ac63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "word-wrap": "^1.2.3" }, "devDependencies": { - "@actions/core": "^1.2.4", + "@actions/core": "^1.9.1", "@actions/github": "^4.0.0", "@testing-library/dom": "^8.17.1", "@testing-library/jest-dom": "^5.16.5", diff --git a/package.json b/package.json index c256229340145..b1bce12bfe7bc 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage", "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch", "test:update:snapshot": "node --experimental-vm-modules node_modules/jest/bin/jest.js -u", + "test:e2e": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.e2e.config.js", "theme-readme-gen": "node scripts/generate-theme-doc", "preview-theme": "node scripts/preview-theme", "generate-langs-json": "node scripts/generate-langs-json", @@ -17,7 +18,7 @@ "author": "Anurag Hazra", "license": "MIT", "devDependencies": { - "@actions/core": "^1.2.4", + "@actions/core": "^1.9.1", "@actions/github": "^4.0.0", "@testing-library/dom": "^8.17.1", "@testing-library/jest-dom": "^5.16.5", diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js new file mode 100644 index 0000000000000..91c9c38fe83aa --- /dev/null +++ b/tests/e2e/e2e.test.js @@ -0,0 +1,173 @@ +/** + * @file Contains end-to-end tests for the Vercel preview instance. + */ +import dotenv from "dotenv"; +dotenv.config(); + +import { describe } from "@jest/globals"; +import axios from "axios"; +import { renderRepoCard } from "../../src/cards/repo-card.js"; +import { renderStatsCard } from "../../src/cards/stats-card.js"; +import { renderTopLanguages } from "../../src/cards/top-languages-card.js"; +import { renderWakatimeCard } from "../../src/cards/wakatime-card.js"; + +// Script variables +const REPO = "dummy-cra"; +const USER = "grsdummy"; +const STATS_DATA = { + name: "grsdummy", + totalPRs: 1, + totalCommits: 2, + totalIssues: 1, + totalStars: 1, + contributedTo: 1, + rank: { + level: "A+", + score: 51.01622937949586, + }, +}; +const LANGS_DATA = { + TypeScript: { + color: "#3178c6", + name: "TypeScript", + size: 2049, + }, + HTML: { + color: "#e34c26", + name: "HTML", + size: 1721, + }, + CSS: { + color: "#563d7c", + name: "CSS", + size: 930, + }, + Python: { + color: "#3572A5", + name: "Python", + size: 671, + }, +}; +const WAKATIME_DATA = { + human_readable_range: "last week", + is_already_updating: false, + is_coding_activity_visible: false, + is_including_today: false, + is_other_usage_visible: false, + is_stuck: false, + is_up_to_date: false, + is_up_to_date_pending_future: false, + percent_calculated: 0, + range: "last_7_days", + status: "pending_update", + timeout: 15, + username: "grsdummy", + writes_only: false, +}; +const REPOSITORY_DATA = { + name: "dummy-cra", + nameWithOwner: "grsdummy/dummy-cra", + isPrivate: false, + isArchived: false, + isTemplate: false, + stargazers: { + totalCount: 1, + }, + description: "Dummy create react app.", + primaryLanguage: { + color: "#3178c6", + id: "MDg6TGFuZ3VhZ2UyODc=", + name: "TypeScript", + }, + forkCount: 0, + starCount: 1, +}; + +describe("Fetch Cards", () => { + let VERCEL_PREVIEW_URL; + + beforeAll(() => { + process.env.NODE_ENV = "development"; + VERCEL_PREVIEW_URL = process.env.VERCEL_PREVIEW_URL; + }); + + test("retrieve stats card", async () => { + expect(VERCEL_PREVIEW_URL).toBeDefined(); + + // Check if the Vercel preview instance stats card function is up and running. + await expect( + axios.get(`${VERCEL_PREVIEW_URL}/api?username=${USER}`), + ).resolves.not.toThrow(); + + // Get local stats card. + const localStatsCardSVG = renderStatsCard(STATS_DATA); + + // Get the Vercel preview stats card response. + const serverStatsSvg = await axios.get( + `${VERCEL_PREVIEW_URL}/api?username=${USER}`, + ); + + // Check if stats card from deployment matches the stats card from local. + expect(serverStatsSvg.data).toEqual(localStatsCardSVG); + }); + + test("retrieve language card", async () => { + expect(VERCEL_PREVIEW_URL).toBeDefined(); + + // Check if the Vercel preview instance language card function is up and running. + await expect( + axios.get(`${VERCEL_PREVIEW_URL}/api/top-langs/?username=${USER}`), + ).resolves.not.toThrow(); + + // Get local language card. + const localLanguageCardSVG = renderTopLanguages(LANGS_DATA); + + // Get the Vercel preview language card response. + const severLanguageSVG = await axios.get( + `${VERCEL_PREVIEW_URL}/api/top-langs/?username=${USER}`, + ); + + // Check if language card from deployment matches the local language card. + expect(severLanguageSVG.data).toEqual(localLanguageCardSVG); + }); + + test("retrieve WakaTime card", async () => { + expect(VERCEL_PREVIEW_URL).toBeDefined(); + + // Check if the Vercel preview instance WakaTime function is up and running. + await expect( + axios.get(`${VERCEL_PREVIEW_URL}/api/wakatime?username=${USER}`), + ).resolves.not.toThrow(); + + // Get local WakaTime card. + const localWakaCardSVG = renderWakatimeCard(WAKATIME_DATA); + + // Get the Vercel preview WakaTime card response. + const serverWakaTimeSvg = await axios.get( + `${VERCEL_PREVIEW_URL}/api/wakatime?username=${USER}`, + ); + + // Check if WakaTime card from deployment matches the local WakaTime card. + expect(serverWakaTimeSvg.data).toEqual(localWakaCardSVG); + }); + + test("retrieve repo card", async () => { + expect(VERCEL_PREVIEW_URL).toBeDefined(); + + // Check if the Vercel preview instance Repo function is up and running. + await expect( + axios.get(`${VERCEL_PREVIEW_URL}/api/pin/?username=${USER}&repo=${REPO}`), + ).resolves.not.toThrow(); + + // Get local repo card. + const localRepoCardSVG = renderRepoCard(REPOSITORY_DATA); + + // Get the Vercel preview repo card response. + const serverRepoSvg = await axios.get( + `${VERCEL_PREVIEW_URL}/api/pin/?username=${USER}&repo=${REPO}`, + ); + + // Check if Repo card from deployment matches the local Repo card. + expect(serverRepoSvg.data).toEqual(localRepoCardSVG); + }); +});