From 78388e9fe24c2986a09eab242cbef8d914d70565 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Fri, 22 Jul 2022 12:08:11 +0200 Subject: [PATCH] Update e2e for patches Signed-off-by: Sebastian Martinez --- cypress.config.cjs | 2 + cypress/e2e/connect.spec.ts | 4 +- cypress/e2e/project.spec.ts | 25 +++++++- cypress/fixtures/projectCommit.json | 38 +++++++++++- cypress/fixtures/projectIssues.json | 87 ++++++++++++++++++++++++++- cypress/fixtures/projectPatches.json | 90 ++++++++++++++++++++++++++++ cypress/support/component.ts | 4 ++ cypress/support/e2e.ts | 10 ++++ vite.config.ts | 2 +- 9 files changed, 253 insertions(+), 9 deletions(-) create mode 100644 cypress/fixtures/projectPatches.json diff --git a/cypress.config.cjs b/cypress.config.cjs index c7637d8c8..1bce01860 100644 --- a/cypress.config.cjs +++ b/cypress.config.cjs @@ -4,6 +4,7 @@ const { startDevServer } = require('@cypress/vite-dev-server'); module.exports = defineConfig({ video: false, + defaultCommandTimeout: 10000, e2e: { setupNodeEvents(on, config) { return require('@cypress/code-coverage/task')(on, config); @@ -27,5 +28,6 @@ module.exports = defineConfig({ }, specPattern: 'src/**/*spec.ts', + indexHtmlFile: './index.html' }, }); diff --git a/cypress/e2e/connect.spec.ts b/cypress/e2e/connect.spec.ts index b1c059748..0e4b67763 100644 --- a/cypress/e2e/connect.spec.ts +++ b/cypress/e2e/connect.spec.ts @@ -10,8 +10,8 @@ describe("MetaMask", () => { }); cy.intercept("POST", "https://api.thegraph.com/subgraphs/name/radicle-dev/radicle-orgs-rinkeby", { data: { safe: null } } ); cy.intercept("https://gateway.ceramic.network/api/v0/streams", { fixture: "ceramicStream.json" }); - cy.get("button.connect").click(); - cy.get("button.secondary").click(); + cy.get("button.connect").should("have.text", "Connect").click(); + cy.get("button.secondary").should("have.text", "Connect with Metamask").click(); cy.get("button.address").should("contain", "3256 – 5721"); cy.window().then((win) => { win.ethereum.changeAccount("0xd3b5586D15140B6f793b260fd90588A0dAefc5B6"); diff --git a/cypress/e2e/project.spec.ts b/cypress/e2e/project.spec.ts index ee94ddc6e..a2d374cef 100644 --- a/cypress/e2e/project.spec.ts +++ b/cypress/e2e/project.spec.ts @@ -59,6 +59,7 @@ describe("Project view", () => { cy.intercept("https://willow.radicle.garden:8777/v1/projects/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy", { fixture: "projectInfo.json" }); cy.intercept("https://willow.radicle.garden:8777/v1/projects/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/remotes", { fixture: "projectRemotes.json" }); cy.intercept("https://willow.radicle.garden:8777/v1/projects/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/issues", { fixture: "projectIssues.json" }); + cy.intercept("https://willow.radicle.garden:8777/v1/projects/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/patches", { fixture: "projectPatches.json" }); cy.intercept("https://willow.radicle.garden:8777/v1/projects/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/tree/56e4e029c294b08546386e1fb706b772c7433c49", { fixture: "projectTree56e4e02.json" }); cy.intercept("https://willow.radicle.garden:8777/v1/projects/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/tree/cbf5df499ab4f4a908f1756fbe2c236a4530516a", { fixture: "projectTreecbf5df4.json" }); cy.intercept("https://willow.radicle.garden:8777/v1/projects/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/remotes/hyndc7nx9keq76p1bkw9831arcndeeu3trwsc7kxt3osmpi6j9oeke", { fixture: "projectBranches.json" }); @@ -154,13 +155,31 @@ describe("Project view", () => { cy.get("header .summary .text-medium").should("have.text", "initial commit"); cy.get("header pre.description").should("have.text", "this is the first commit of many"); cy.get("header .committer").should("have.text", "dabit3"); - cy.get("div.changeset-summary").should("have.text", "1 file(s) changed\n with\n 0 addition(s)\n and\n 0 deletion(s)"); - cy.get("header.file-header:nth-child(1) div.file-data > *") + cy.get("div.changeset-summary").should("have.text", "1 file(s) created, 1 file(s) deleted and 1 file(s) changed\n with\n 0 addition(s)\n and\n 0 deletion(s)"); + cy.get("header.file-header:nth-child(1) p.file-path") .first() - .should("have.text", "README.md") + .should("have.text", "test.md") .next() .should("have.text", "created"); cy.get("tr.diff-line td.diff-line-number").contains("16"); cy.get("tr.diff-line td.diff-line-content").contains("To prevent front-running, the RAD/USDC balances are set through the Uniswap router *proxy* contract"); }); + + it("Issues button", () => { + cy.get("div.stat.issue-count") + .click(); + cy.location().should((location) => { + expect(location.pathname).to.eq('/seeds/willow.radicle.garden/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/remotes/hyndc7nx9keq76p1bkw9831arcndeeu3trwsc7kxt3osmpi6j9oeke/issues'); + }); + cy.get("div.stat.issue-count").should("have.class", "active"); + }); + + it("Patches button", () => { + cy.get("div.stat.patch-count") + .click(); + cy.location().should((location) => { + expect(location.pathname).to.eq('/seeds/willow.radicle.garden/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/remotes/hyndc7nx9keq76p1bkw9831arcndeeu3trwsc7kxt3osmpi6j9oeke/patches'); + }); + cy.get("div.stat.patch-count").should("have.class", "active"); + }); }); diff --git a/cypress/fixtures/projectCommit.json b/cypress/fixtures/projectCommit.json index 08984c899..edcb31fbf 100644 --- a/cypress/fixtures/projectCommit.json +++ b/cypress/fixtures/projectCommit.json @@ -19,10 +19,44 @@ }, "diff": { "created": [ - "README.md" + { + "path": "test.md", + "diff": { + "type": "plain", + "hunks": [ + { + "header": "@@ -0,0 +1 @@\n", + "lines": [ + { + "type": "addition", + "line": "Hello world\n", + "lineNum": 1 + } + ] + } + ] + } + } ], "deleted": [ - "LICENSE" + { + "path": "test.md", + "diff": { + "type": "plain", + "hunks": [ + { + "header": "@@ -0,0 +1 @@\n", + "lines": [ + { + "type": "addition", + "line": "Hello world\n", + "lineNum": 1 + } + ] + } + ] + } + } ], "moved": [], "copied": [], diff --git a/cypress/fixtures/projectIssues.json b/cypress/fixtures/projectIssues.json index fe51488c7..f406ab5e4 100644 --- a/cypress/fixtures/projectIssues.json +++ b/cypress/fixtures/projectIssues.json @@ -1 +1,86 @@ -[] +[ + { + "id": "hnrk8qmheqbwxius3brqxohqrfmgdrphtirxo", + "author": { + "peer": "hyyg555wwkkutaysg6yr67qnu5d5ji54iur3n5uzzszndh8dp7ofue", + "urn": "rad:git:hnrk81wcokr48mkm544kh74kc9fqz84d3rfcy", + "profile": { + "name": "sebastinez", + "ens": { + "name": "sebastinez.radicle.eth" + } + } + }, + "title": "Testing strategy", + "state": { + "status": "open" + }, + "comment": { + "author": { + "peer": "hyyg555wwkkutaysg6yr67qnu5d5ji54iur3n5uzzszndh8dp7ofue", + "urn": "rad:git:hnrk81wcokr48mkm544kh74kc9fqz84d3rfcy", + "profile": { + "name": "sebastinez", + "ens": { + "name": "sebastinez.radicle.eth" + } + } + }, + "body": "We should define the scope we want to test in integration vs component testing (I don't mention E2E here on purpose since in our E2E tests we stubbed all responses and never hit a real server which equals to integration testing).\n\nWhile integration testing allows us to traverse the application and test navigation, component testing allows us to mount a component in isolation and check all the possible edge cases and possible regressions, and unit testing goes one step further to just individual functions on their correctness.\n\nIntegration testing npm run test:e2e eventually should be npm run test:integration\n\n**Connection through mocked Web3Provider**\n- Navigation through different URLs (e.g. the project pages, commits, issues, patches, etc.)\n- Assert the URLs we're hitting and that they update correctly, when state changes\n- Assert the least amount of display logic (we should leave that to component testing)\n If we are able to navigate to the correct URL and get the correct props, we shouldn't need to assert every piece of text.\nComponent testing npm run test:components\n\n- Assert the correct rendering\n- Test that the state of the component updates accordingly where applicable.\n**Unit tests npm run test:unit**\n\n- Util functions\nClasses (static and methods)\nI'll keep updating this issue.\nP.S.: Testing is not my expertise so any feedback is welcome.", + "reactions": { + + }, + "replies": null, + "timestamp": 1656509367 + }, + "discussion": [ + + ], + "labels": [ + "discussion" + ], + "timestamp": 1656509367 + }, + { + "id": "hnrkj4c35uoyceb3d1dsscx8qq55cikrd1aio", + "author": { + "peer": "hyyg555wwkkutaysg6yr67qnu5d5ji54iur3n5uzzszndh8dp7ofue", + "urn": "rad:git:hnrk81wcokr48mkm544kh74kc9fqz84d3rfcy", + "profile": { + "name": "sebastinez", + "ens": { + "name": "sebastinez.radicle.eth" + } + } + }, + "title": "Update README", + "state": { + "status": "closed" + }, + "comment": { + "author": { + "peer": "hyyg555wwkkutaysg6yr67qnu5d5ji54iur3n5uzzszndh8dp7ofue", + "urn": "rad:git:hnrk81wcokr48mkm544kh74kc9fqz84d3rfcy", + "profile": { + "name": "sebastinez", + "ens": { + "name": "sebastinez.radicle.eth" + } + } + }, + "body": "We should define the scope we want to test in integration vs component testing (I don't mention E2E here on purpose since in our E2E tests we stubbed all responses and never hit a real server which equals to integration testing).\n\nWhile integration testing allows us to traverse the application and test navigation, component testing allows us to mount a component in isolation and check all the possible edge cases and possible regressions, and unit testing goes one step further to just individual functions on their correctness.\n\nIntegration testing npm run test:e2e eventually should be npm run test:integration\n\n**Connection through mocked Web3Provider**\n- Navigation through different URLs (e.g. the project pages, commits, issues, patches, etc.)\n- Assert the URLs we're hitting and that they update correctly, when state changes\n- Assert the least amount of display logic (we should leave that to component testing)\n If we are able to navigate to the correct URL and get the correct props, we shouldn't need to assert every piece of text.\nComponent testing npm run test:components\n\n- Assert the correct rendering\n- Test that the state of the component updates accordingly where applicable.\n**Unit tests npm run test:unit**\n\n- Util functions\nClasses (static and methods)\nI'll keep updating this issue.\nP.S.: Testing is not my expertise so any feedback is welcome.", + "reactions": { + + }, + "replies": null, + "timestamp": 1656509367 + }, + "discussion": [ + + ], + "labels": [ + "discussion" + ], + "timestamp": 1656509367 + } +] diff --git a/cypress/fixtures/projectPatches.json b/cypress/fixtures/projectPatches.json new file mode 100644 index 000000000..7b75556c4 --- /dev/null +++ b/cypress/fixtures/projectPatches.json @@ -0,0 +1,90 @@ +[ + { + "id": "hnrkj4c35uoyceb3d1dsscx8qq55cikrd1aio", + "author": { + "peer": "hybepksbf5xzew3ztear7k7peddho5wfts3d8uyb9pcdu6sqgnwqak", + "urn": "rad:git:hnrkkxqo5jgx3bwbphdsmqyk9djkfr368czio", + "profile": { + "name": "Scooby", + "ens": null + } + }, + "title": "this is a patch with multiple commits and a merge base", + "state": "proposed", + "target": "upstream", + "labels": [], + "revisions": [ + { + "id": "d2a46e1f-88a9-4e72-bc68-3f6afc92003c", + "peer": "hybepksbf5xzew3ztear7k7peddho5wfts3d8uyb9pcdu6sqgnwqak", + "base": "58c1864cb6c6edd8682830d087bdcef7902cf62a", + "oid": "a36d8df141a0d3cedf47c4a42383ed98818195de", + "comment": { + "author": { + "peer": "hybepksbf5xzew3ztear7k7peddho5wfts3d8uyb9pcdu6sqgnwqak", + "urn": "rad:git:hnrkkxqo5jgx3bwbphdsmqyk9djkfr368czio", + "profile": { + "name": "Scooby", + "ens": null + } + }, + "body": "Signed-off-by: Sebastian Martinez ", + "reactions": { + + }, + "replies": null, + "timestamp": 1656666433 + }, + "discussion": [], + "reviews": {}, + "merges": [], + "changeset": null, + "timestamp": 1656666433 + } + ], + "timestamp": 1656666433 + }, + { + "id": "hnrkqjf6ucd3o8ffztt7yyeatuj9u4k4957xo", + "author": { + "peer": "hybepksbf5xzew3ztear7k7peddho5wfts3d8uyb9pcdu6sqgnwqak", + "urn": "rad:git:hnrkkxqo5jgx3bwbphdsmqyk9djkfr368czio", + "profile": { + "name": "Scooby", + "ens": null + } + }, + "title": "Removing files", + "state": "proposed", + "target": "upstream", + "labels": [], + "revisions": [ + { + "id": "7edbb9df-e921-4dff-b2e2-5b0a50c51188", + "peer": "hybepksbf5xzew3ztear7k7peddho5wfts3d8uyb9pcdu6sqgnwqak", + "base": "58c1864cb6c6edd8682830d087bdcef7902cf62a", + "oid": "6da5af5cf09b5db638b8a6f5ce386391c3b74da4", + "comment": { + "author": { + "peer": "hybepksbf5xzew3ztear7k7peddho5wfts3d8uyb9pcdu6sqgnwqak", + "urn": "rad:git:hnrkkxqo5jgx3bwbphdsmqyk9djkfr368czio", + "profile": { + "name": "Scooby", + "ens": null + } + }, + "body": "Signed-off-by: Sebastian Martinez ", + "reactions": {}, + "replies": null, + "timestamp": 1656667614 + }, + "discussion": [], + "reviews": {}, + "merges": [], + "changeset": null, + "timestamp": 1656667614 + } + ], + "timestamp": 1656667614 + } +] diff --git a/cypress/support/component.ts b/cypress/support/component.ts index b634ea9b3..691da185c 100644 --- a/cypress/support/component.ts +++ b/cypress/support/component.ts @@ -1 +1,5 @@ import '@testing-library/cypress/add-commands'; +import { Buffer } from "buffer"; + +//@ts-expect-error We need Buffer on the window object in the test env for component testing +window.Buffer = Buffer; diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index e28084d3c..d1a6bf6bf 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -3,6 +3,7 @@ import '@cypress/code-coverage/support'; import { JsonRpcProvider, JsonRpcSigner } from '@ethersproject/providers'; import '@testing-library/cypress/add-commands'; import { BigNumber, ethers } from 'ethers'; +import { Resolver } from "@ethersproject/providers"; declare global { interface Window { @@ -29,6 +30,15 @@ export class MockExtensionProvider extends ethers.providers.BaseProvider { return new JsonRpcSigner({}, this as unknown as JsonRpcProvider, addressOrIndex); } + async getResolver(name: string): Promise { + const address = "0x5E813e48a81977c6Fdd565ed5097eb600C73C4f0"; + return new Resolver(this, address, name, address); + } + + async lookupAddress(address: string | Promise): Promise { + return "mock.eth"; + } + changeAccount(address: string): void { this.currentAddress = address; this.emit("accountsChanged", [address]); diff --git a/vite.config.ts b/vite.config.ts index 7f2d54a6c..c27896fc4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -66,7 +66,7 @@ const config: UserConfig = { }; // For Vitest to work we need to unset READABLE_STREAM. -if (process.env.VITEST) { +if (process.env.VITEST || process.env.Cypress) { config.define = undefined; }