Skip to content

Commit

Permalink
perf: fetch tests in before hook (#7)
Browse files Browse the repository at this point in the history
* style: decouple onSkip and make request to fetch quarantined tests in before hook

* fix: types

* test: setup simple e2e test

* test: add e2e test

* ci: adjust timeout

* ci: add path filter

* docs: add changeset

* style: remove unused db.json
  • Loading branch information
wrn14897 authored Feb 15, 2023
1 parent 6eed6a3 commit 26aca55
Show file tree
Hide file tree
Showing 12 changed files with 676 additions and 68 deletions.
5 changes: 5 additions & 0 deletions .changeset/yellow-chicken-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@deploysentinel/cypress-quarantine': patch
---

perf: call fetchTestsToBeQuarantined task in before hook
25 changes: 25 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: E2E
on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- 'cypress/**'
- 'src/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
main:
timeout-minutes: 4
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install deps
uses: bahmutov/npm-install@v1
- name: Build pkg
run: yarn build
- name: Run tests
run: yarn ci:e2e
3 changes: 0 additions & 3 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
name: Unit

on:
push:
branches: [main]
pull_request:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
main:
timeout-minutes: 8
Expand Down
10 changes: 2 additions & 8 deletions cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,14 @@ import plugin from './dist/plugin';

export default defineConfig({
projectId: 'tacocat',
env: {
DEPLOYSENTINEL_KEY: '8549375e-20fb-4a5d-8871-cc0461a6c94c', // replace this with yours
DEPLOYSENTINEL_UPLOAD_ON_PASSES: true,
DEPLOYSENTINEL_LOG_VERBOSE: true,
DEPLOYSENTINEL_API_URL: 'http://localhost:8000/ci',
},
e2e: {
setupNodeEvents(on, config) {
plugin(on, config, {
apiUrl: 'http://localhost:8000/ci/quarantine-tests',
apiUrl: 'http://localhost:3000/tests',
meta: {
testFramework: 'cypress',
},
getTestId: (titles: string[]) => titles.join(' '),
getTestId: (titles: string[]) => titles.join(' > '),
});
return config;
},
Expand Down
5 changes: 5 additions & 0 deletions cypress/db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tests": {
"describe A > visits a website (should be skipped)": true
}
}
31 changes: 0 additions & 31 deletions cypress/e2e/fast.cy.js

This file was deleted.

33 changes: 33 additions & 0 deletions cypress/e2e/wiki.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
describe('describe A', () => {
it('visits a website (should be skipped)', () => {
cy.visit('https://www.wikipedia.org');
// Click on <input> #searchInput
cy.get('#searchInput').click();

// Fill "milk tea" on <input> #searchInput
cy.get('#searchInput').type('milk tea');

// Press Enter on input
cy.get('#searchInput').type('{Enter}');

cy.get('#firstHeading').should('include.text', 'Milk tea');

cy.get('[href="/wiki/Tea"]').click();
});

it('visits a website (should pass)', () => {
cy.visit('https://www.wikipedia.org');
// Click on <input> #searchInput
cy.get('#searchInput').click();

// Fill "milk tea" on <input> #searchInput
cy.get('#searchInput').type('milk tea');

// Press Enter on input
cy.get('#searchInput').type('{Enter}');

cy.get('#firstHeading').should('include.text', 'Milk tea');

cy.get('[href="/wiki/Milk"]').click();
});
});
22 changes: 22 additions & 0 deletions cypress/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const path = require('path')
const jsonServer = require('json-server');
const server = jsonServer.create();
const router = jsonServer.router(path.join(__dirname, 'db.json'))
const middlewares = jsonServer.defaults();

server.use(middlewares);
server.use(jsonServer.bodyParser);
server.use((req, res, next) => {
if (req.method === 'POST') {
// Converts POST to GET and move payload to query params
// This way it will make JSON Server that it's GET request
req.method = 'GET'
req.query = req.body
}
// Continue to JSON Server router
next()
});
server.use(router);
server.listen(3000, () => {
console.log('JSON Server is running');
});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"postbuild": "./bin/release-script.sh",
"ci:unit": "jest --coverage",
"ci:lint": "yarn lint && yarn tsc --noEmit",
"ci:e2e": "node ./cypress/server.js & yarn run cypress run --browser chrome",
"dev:unit": "jest --watchAll",
"prettier": "prettier --config .prettierrc --write .",
"lint": "eslint . --ext .ts",
Expand Down Expand Up @@ -45,6 +46,7 @@
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.2",
"json-server": "^0.17.1",
"prettier": "^2.8.4",
"rollup": "^2.79.0",
"rollup-plugin-dts": "^5.1.0",
Expand Down
37 changes: 27 additions & 10 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const axiosInstance = buildAxiosInstance({
maxContentLength: Infinity,
maxBodyLength: Infinity,
});
const fetchSkippedTestCases = async (
const fetchTestsToBeQuarantined = async (
url: string,
payload: {
path: string;
Expand All @@ -85,7 +85,10 @@ export default (
): [Cypress.PluginEvents, Cypress.PluginConfigOptions] => {
const cypressVersion = config['version'];
const envs = config['env'];
const skippedTestCasesPerSpec = new Map<string, Record<string, any>>();
const testsToBeQuarantinedPerSpec = new Map<
string,
Record<string, boolean>
>();
const gitClient = new GitClient({
// FIXME: this should be optional
error,
Expand All @@ -94,14 +97,15 @@ export default (
log(`Starting plugin [v${PKG_VERSION}]...`);

on('task', {
onSkip: async ({ path, titles }: { path: string; titles: string[] }) => {
fetchTestsToBeQuarantined: async (path: string) => {
try {
const commitInfo = await gitClient.getCommitInfo();
// pull from cache
let skippedTestCases = skippedTestCasesPerSpec.get(path);
if (!skippedTestCases) {
log(`Fetching skipped tests for spec: ${path}`);
skippedTestCases = await fetchSkippedTestCases(
let tests = testsToBeQuarantinedPerSpec.get(path);
if (!tests) {
const ts = Date.now();
log(`Fetching skipped tests for spec "${path}"`);
tests = await fetchTestsToBeQuarantined(
extraConfig.apiUrl,
{
path,
Expand All @@ -114,12 +118,25 @@ export default (
},
extraConfig.topLevelKey,
);
skippedTestCasesPerSpec.set(path, skippedTestCases as any);
log(
`Fetched skipped tests for spec "${path}" took ${
Date.now() - ts
} ms`,
);
testsToBeQuarantinedPerSpec.set(path, tests as any);
}
if (isPlainObject(skippedTestCases)) {
} catch (e) {
error(e);
}
return null;
},
onSkip: ({ path, titles }: { path: string; titles: string[] }) => {
try {
const tests = testsToBeQuarantinedPerSpec.get(path);
if (isPlainObject(tests)) {
const shouldSkip = Boolean(
lGet(
skippedTestCases,
tests,
extraConfig.getTestId
? extraConfig.getTestId(titles)
: titles[titles.length - 1],
Expand Down
4 changes: 4 additions & 0 deletions src/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const getTestTitles = (
// const isComponentTest = Boolean(Cypress.config('devServer' as any));
const getFilePath = () => Cypress.spec.relative;

before(function () {
cy.task('fetchTestsToBeQuarantined', getFilePath());
});

beforeEach(function () {
const currentTest = this.currentTest;
if (currentTest) {
Expand Down
Loading

0 comments on commit 26aca55

Please sign in to comment.