From dc06aab044d2d092e2412963b0b2adf360fa91b9 Mon Sep 17 00:00:00 2001 From: BrickheadJohnny Date: Wed, 24 Jul 2024 06:28:32 +0200 Subject: [PATCH 1/2] fix(explorer): increase cache time --- src/app/explorer/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/explorer/page.tsx b/src/app/explorer/page.tsx index d89bfca089..f05f0ebde5 100644 --- a/src/app/explorer/page.tsx +++ b/src/app/explorer/page.tsx @@ -29,14 +29,14 @@ const Page = async ({ searchParams }: { searchParams: SearchParams }) => { const [ssrFeaturedGuilds, ssrNewestGuilds] = await Promise.all([ fetch(`${env.NEXT_PUBLIC_API.replace("/v1", "")}${featuredPath}`, { next: { - revalidate: 300, + revalidate: 600, }, }) .then((res) => res.json()) .catch((_) => []), fetch(`${env.NEXT_PUBLIC_API.replace("/v1", "")}${newestPath}`, { next: { - revalidate: 300, + revalidate: 600, }, }) .then((res) => res.json()) From 1514f37f3e1b2f7e7c7bc787d7d1a467525fdb25 Mon Sep 17 00:00:00 2001 From: BrickheadJohnny <92519134+BrickheadJohnny@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:04:53 +0200 Subject: [PATCH 2/2] Playwright (#1407) * chore: remove cypress related stuff * feat: set up Playwright & create an example test * feat: add the `Playwright Tests` GitHub Action * fix(gh action): add Build step * cleanup(.gitignore): remove unnecessary line * fix(gh action): install browsers before dependencies * cleanup(fixtures): remove `console.log` * fix(gh action): provide envs * feat: run workflow on successful deployment * feat: use `navigator.userAgent` to detect test user * fix(gh action): run for specific URLs & pass deployment URL as env var * fix(env): add `NEXT_PUBLIC_E2E_WALLET_MNEMONIC` * fix(gh action): more specific url * fix invalid workflow file * trigger * fix(gh action): negate `contains` * fix(gh action): install dependencies * fix(playwright.config): webServer config * debug: temporarily log deployment_url * fix(playwright): always generate html report * fix(gh action): use `deployment_status.target_url` * cleanup: revert env changes * cleanup: remove unnecessary steps from workflow file * fix: install `@playwright/test` globally * fix: copy playwright to node_modules * fix: install `@playwright/test` only * cleanup: remove fake success returns in onchain tx related tests * chore: upgrade `@playwright/test` * fix: revert workflow changes, just run `npm ci` * fix(gh action): concurrency --- .env.example | 1 - .github/workflows/playwright.yml | 32 + .gitignore | 9 +- biome.json | 2 +- cypress.config.ts | 53 - .../0-manage-roles.spec.ts | 167 --- .../0-payment-requirement.spec.ts | 98 -- .../e2e/2-guild-checkout/1-guild-pins.spec.ts | 56 - .../e2e/2-guild-checkout/2-nft-reward.spec.ts | 110 -- cypress/e2e/readme.md | 59 - cypress/fixtures/cypress-gang-nft.png | Bin 21536 -> 0 bytes .../fixtures/testUserDiscordGateables.json | 8 - cypress/support/commands.ts | 32 - cypress/support/e2e.ts | 1 - cypress/tsconfig.json | 10 - package-lock.json | 1086 +---------------- package.json | 11 +- playwright.config.ts | 71 ++ playwright/auth.setup.ts | 89 ++ playwright/constants.ts | 4 + playwright/dummy.spec.ts | 12 + playwright/fixtures.ts | 95 ++ .../GuildCheckout/hooks/useMintGuildPin.tsx | 8 - .../CreateNftForm/hooks/useCreateNft.ts | 4 - .../[guild]/collect/hooks/useCollectNft.ts | 4 - src/hooks/useSubmitTransaction.ts | 9 - .../hooks/useRegisterVault.ts | 5 - src/rewards/Token/hooks/useCollectToken.tsx | 4 - src/rewards/Token/hooks/useRegisterPool.tsx | 4 - src/rewards/Token/hooks/useWithdrawPool.tsx | 3 - src/v2/components/Account/Account.tsx | 8 +- .../WalletSelectorModal.tsx | 2 + .../components/ConnectorButton.tsx | 1 + src/v2/hooks/useAutoReconnect.ts | 11 +- src/wagmiConfig/index.ts | 80 +- src/wagmiConfig/mockConnector.ts | 17 +- tsconfig.json | 6 +- 37 files changed, 457 insertions(+), 1715 deletions(-) create mode 100644 .github/workflows/playwright.yml delete mode 100644 cypress.config.ts delete mode 100644 cypress/e2e/1-roles-requirements-rewards/0-manage-roles.spec.ts delete mode 100644 cypress/e2e/2-guild-checkout/0-payment-requirement.spec.ts delete mode 100644 cypress/e2e/2-guild-checkout/1-guild-pins.spec.ts delete mode 100644 cypress/e2e/2-guild-checkout/2-nft-reward.spec.ts delete mode 100644 cypress/e2e/readme.md delete mode 100644 cypress/fixtures/cypress-gang-nft.png delete mode 100644 cypress/fixtures/testUserDiscordGateables.json delete mode 100644 cypress/support/commands.ts delete mode 100644 cypress/support/e2e.ts delete mode 100644 cypress/tsconfig.json create mode 100644 playwright.config.ts create mode 100644 playwright/auth.setup.ts create mode 100644 playwright/constants.ts create mode 100644 playwright/dummy.spec.ts create mode 100644 playwright/fixtures.ts diff --git a/.env.example b/.env.example index 9e2515f1d9..2d080aaa47 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,6 @@ ALCHEMY_KEY="" ARBITRUM_ALCHEMY_KEY="" BALANCY_TOKEN="" BASE_ALCHEMY_KEY="" -CYPRESS_RECORD_KEY="" EDGE_CONFIG="" GOERLI_ALCHEMY_KEY="" GUILD_API_KEY="" diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000000..d4c315e440 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,32 @@ +name: Playwright Tests +on: + deployment_status: + workflow_dispatch: + +concurrency: + group: "playwright" + +jobs: + test: + if: github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success' + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + env: + DEPLOYMENT_URL: ${{ github.event.deployment_status.target_url }} + run: npm run test + - uses: actions/upload-artifact@v4 + if: ${{ failure() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2f93b01b8a..5284569a4c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,9 +29,6 @@ yarn-error.log* .vercel -cypress/screenshots -cypress/videos - .idea *.tsbuildinfo @@ -39,3 +36,9 @@ cypress/videos storybook-static bun.lockb + +/playwright-report/ +/blob-report/ +/playwright/.cache/ +/playwright/.auth/ +/playwright/results diff --git a/biome.json b/biome.json index f3769b5e7d..63f837aa5b 100644 --- a/biome.json +++ b/biome.json @@ -10,7 +10,7 @@ "attributePosition": "auto" }, "files": { - "include": ["src", "cypress"], + "include": ["src", "playwright", "playwright.config.ts"], "ignore": ["node_modules", ".next", "public", ".out", "package-lock.json"] }, "organizeImports": { diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index 5bdd6e32f5..0000000000 --- a/cypress.config.ts +++ /dev/null @@ -1,53 +0,0 @@ -import fs from "fs" -// eslint-disable-next-line import/no-extraneous-dependencies -import { defineConfig } from "cypress" - -export default defineConfig({ - e2e: { - retries: 1, - experimentalMemoryManagement: true, - video: true, - baseUrl: "http://localhost:3000", - userAgent: "cypress", - specPattern: "./cypress/e2e/**/*.spec.ts", - defaultCommandTimeout: 15_000, - requestTimeout: 15_000, - env: { - guildApiV1Url: "https://api.guild.xyz/v1", - guildApiUrl: "https://api.guild.xyz/v2", - userAddress: "0x304Def656Babc745c53782639D3CaB00aCe8C843", - platformlessGuildName: "Platformless Cypress Gang", - platformlessGuildUrlName: "platformless-cypress-gang", - guildName: "Cypress Gang", - guildUrlName: "cypress-gang", - dcClientId: "868172385000509460", - dcServerId: "1096417797292171365", // We'll delete the created roles in this Discord server - tgId: "-1001653099938", - RUN_ID: "localhost", - TEST_GUILD_URL_NAME: "guild-e2e-cypress", - GUILD_CHECKOUT_TEST_GUILD_URL_NAME: "guild-checkout-e2e-cypress", - PINATA_PIN_FILE_API_URL: "https://api.pinata.cloud/pinning/pinFileToIPFS", - }, - setupNodeEvents(on, config) { - on( - "after:spec", - (spec: Cypress.Spec, results: CypressCommandLine.RunResult) => { - if (results && results.video) { - // Do we have failures for any retry attempts? - const failures = results.tests.some((test) => - test.attempts.some((attempt) => attempt.state === "failed") - ) - if (!failures) { - // delete the video if the spec passed and no tests retried - try { - fs.unlinkSync(results.video) - } catch (unlinkSyncError) { - console.log("[WARNING] fs.unlinkSync error", unlinkSyncError) - } - } - } - } - ) - }, - }, -}) diff --git a/cypress/e2e/1-roles-requirements-rewards/0-manage-roles.spec.ts b/cypress/e2e/1-roles-requirements-rewards/0-manage-roles.spec.ts deleted file mode 100644 index f28519766a..0000000000 --- a/cypress/e2e/1-roles-requirements-rewards/0-manage-roles.spec.ts +++ /dev/null @@ -1,167 +0,0 @@ -const CONTEXT = { - createdRoleId: undefined, - guild: undefined, - createdRequirement: undefined, -} - -describe("roles", () => { - beforeEach(() => { - cy.clearIndexedDB() - cy.visit(`/${Cypress.env("TEST_GUILD_URL_NAME")}`) - cy.connectWallet() - - cy.intercept( - "GET", - `${Cypress.env("guildApiUrl")}/guilds/guild-page/${Cypress.env( - "TEST_GUILD_URL_NAME" - )}` - ).as("fetchGuild") - }) - - it("can fetch guild id", () => { - cy.wait("@fetchGuild") - .then((intercept) => { - CONTEXT.guild = intercept.response.body - return intercept - }) - .its("response.statusCode") - .should("eq", 200) - }) - - it("can create a role without rewards", () => { - cy.intercept( - "POST", - `${Cypress.env("guildApiUrl")}/guilds/${CONTEXT.guild.id}/roles` - ).as("createRoleApiCall") - - cy.getByDataTest("add-role-button").click({ force: true }) - - cy.get("div[role='dialog'].chakra-slide").within(() => { - cy.get("input[name='name']").focus().blur() - cy.get( - "input[name='name'] ~ .chakra-collapse .chakra-form__error-message" - ).should("exist") - cy.get("input[name='name']").type("Cypress Test Role") - cy.get( - "input[name='name'] ~ .chakra-collapse .chakra-form__error-message" - ).should("not.exist") - - cy.contains("Open access").should("exist") - - cy.getByDataTest("save-role-button").click() - - cy.wait("@createRoleApiCall") - .then((intercept) => { - CONTEXT.createdRoleId = intercept.response?.body.id - return intercept - }) - .its("response.statusCode") - .should("eq", 201) - }) - }) - - it("can edit general role data", () => { - if (!CONTEXT.createdRoleId) - throw new Error("Can't run test, because couldn't create a role.") - - cy.intercept( - "PUT", - `${Cypress.env("guildApiUrl")}/guilds/${CONTEXT.guild.id}/roles/${ - CONTEXT.createdRoleId - }` - ).as("editRoleApiCall") - - cy.get(`#role-${CONTEXT.createdRoleId}`).should("exist") - cy.get(`#role-${CONTEXT.createdRoleId} button[aria-label='Edit role']`).click() - - cy.get("div[role='dialog'].chakra-slide").within(() => { - cy.get("input[name='name']").type(" (edited)") - cy.get("textarea[name='description']").type("wagmi") - - cy.getByDataTest("save-role-button").click() - cy.wait("@editRoleApiCall").its("response.statusCode").should("eq", 200) - }) - }) - - it("can add requirements", () => { - if (!CONTEXT.createdRoleId) - throw new Error("Can't run test, because couldn't create a role.") - - cy.intercept( - "POST", - `${Cypress.env("guildApiUrl")}/guilds/${CONTEXT.guild.id}/roles/${ - CONTEXT.createdRoleId - }/requirements` - ).as("createRequirementApiCall") - - cy.get(`#role-${CONTEXT.createdRoleId}`).should("exist") - cy.get(`#role-${CONTEXT.createdRoleId} button[aria-label='Edit role']`).click() - - cy.get("div[role='dialog'].chakra-slide").should("exist") - - cy.getByDataTest("add-requirement-button").click() - cy.getByDataTest("add-requirement-modal").within(() => { - cy.contains("Allowlist").click() - cy.get("textarea").type(Cypress.env("userAddress")) - cy.contains("Add requirement").click() - cy.wait("@createRequirementApiCall") - .its("response.statusCode") - .should("eq", 201) - }) - - cy.getByDataTest("add-requirement-button").click() - cy.getByDataTest("add-requirement-modal").within(() => { - cy.contains("Captcha").click() - cy.get("input[name='.data.maxAmount']").type("1") - cy.contains("Add requirement").click() - cy.wait("@createRequirementApiCall") - .its("response.statusCode") - .should("eq", 201) - }) - - cy.contains("Open access").should("not.exist") - }) - - it("can edit requirements list", () => { - if (!CONTEXT.createdRoleId) - throw new Error("Can't run test, because couldn't create a role.") - - cy.get(`#role-${CONTEXT.createdRoleId}`).should("exist") - cy.get(`#role-${CONTEXT.createdRoleId} button[aria-label='Edit role']`).click() - - cy.get("div[role='dialog'].chakra-slide").within(() => { - cy.get("button[aria-label='Remove requirement']").first().click() - }) - - cy.intercept( - "DELETE", - `${Cypress.env("guildApiUrl")}/guilds/*/roles/*/requirements/*` - ).as("deleteRequirement") - - cy.getByDataTest("delete-confirmation-button").click() - cy.wait("@deleteRequirement") - cy.contains("Requirement deleted!") - }) - - it("can delete a role", () => { - if (!CONTEXT.createdRoleId) - throw new Error("Can't run test, because couldn't create a role.") - - cy.get(`#role-${CONTEXT.createdRoleId}`).should("exist") - cy.get(`#role-${CONTEXT.createdRoleId} button[aria-label='Edit role']`).click() - - cy.get( - "div[role='dialog'].chakra-slide button[aria-label='Delete role']" - ).click() - - cy.intercept("DELETE", `${Cypress.env("guildApiUrl")}/guilds/*/roles/*`).as( - "deleteRole" - ) - - cy.getByDataTest("delete-confirmation-button").click() - cy.wait("@deleteRole") - cy.contains("Role deleted!") - }) -}) - -export {} diff --git a/cypress/e2e/2-guild-checkout/0-payment-requirement.spec.ts b/cypress/e2e/2-guild-checkout/0-payment-requirement.spec.ts deleted file mode 100644 index 0e040c795c..0000000000 --- a/cypress/e2e/2-guild-checkout/0-payment-requirement.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -const MUMBAI_USDC_ADDRESS = "0xe9dce89b076ba6107bb64ef30678efec11939234" -const UNHAPPY_PATH_ROLE_CARD_ID = "#role-90904" -const HAPPY_PATH_ROLE_CARD_ID = "#role-90671" - -describe("payment requirement", () => { - beforeEach(() => { - cy.clearIndexedDB() - cy.visit(`/${Cypress.env("GUILD_CHECKOUT_TEST_GUILD_URL_NAME")}`) - cy.connectWallet() - }) - - it("can create a payment requirement", () => { - cy.getByDataTest("add-role-button").click() - cy.getByDataTest("add-requirement-button").click() - cy.get("button") - .contains(/^Payment$/) - .click() - - cy.get("label").contains("Chain").click().type("Mumbai") - cy.getByDataTest("custom-select-option").contains("Polygon Mumbai").click() - cy.getByDataTest("payment-form-switch-network-button").should("exist") - - cy.get("label").contains("Token").click().type(`${MUMBAI_USDC_ADDRESS}{esc}`) - - cy.get("label").contains("Price").click().type("1") - - cy.getByDataTest("payment-form-switch-network-button").click() - cy.getByDataTest("payment-form-register-vault-button").click() - - cy.getByDataTest("add-requirement-modal").should("not.exist") - cy.get(".chakra-modal__body") - .contains(/^Pay(.)*on Polygon Mumbai/) - .should("exist") - }) - - it("can't buy a pass without allowance", () => { - cy.get(UNHAPPY_PATH_ROLE_CARD_ID).within(() => { - cy.getByDataTest("payment-requirement-buy-button").click() - }) - - cy.getByDataTest("token-info-fee-currency").should("contain", "1 USDT") - cy.getByDataTest("token-info-balance").should("contain", "0 USDT") - cy.getByDataTest("fees-table").get("span").should("contain", "1 USDT") - - cy.getByDataTest("tos-checkbox").should("not.be.visible") - cy.getByDataTest("buy-button").should("be.disabled") - - cy.get(".chakra-modal__footer").get("button").contains("Switch network").click() - - cy.getByDataTest("tos-checkbox").should("be.visible") - cy.getByDataTest("buy-allowance-button") - .should("be.visible") - .should("contain", "Allow Guild to use your USDT") - cy.getByDataTest("buy-button") - .should("be.disabled") - .should("contain", "Insufficient balance") - }) - - it("can buy a pass", () => { - cy.get(HAPPY_PATH_ROLE_CARD_ID).within(() => { - cy.getByDataTest("payment-requirement-buy-button").click() - }) - - cy.getByDataTest("token-info-fee-currency").should("contain", "1 USDC") - cy.getByDataTest("token-info-balance").should("contain", "10 USDC") - cy.getByDataTest("fees-table").get("span").should("contain", "1 USDC") - - cy.getByDataTest("tos-checkbox").should("not.be.visible") - cy.getByDataTest("buy-button").should("be.disabled") - - cy.get(".chakra-modal__footer").get("button").contains("Switch network").click() - - cy.getByDataTest("tos-checkbox").should("be.visible").click() - cy.getByDataTest("buy-button").should("be.enabled") - - cy.getByDataTest("buy-button") - .click() - .get(".chakra-alert") - .contains("Successful payment") - .should("be.visible") - }) - - it("can withdraw from a vault", () => { - cy.get(HAPPY_PATH_ROLE_CARD_ID).within(() => { - cy.getByDataTest("withdraw-button").should("be.enabled") - cy.getByDataTest("withdraw-button").should( - "contain", - "Switch to Polygon Mumbai to withdraw" - ) - cy.getByDataTest("withdraw-button").click() - - cy.getByDataTest("withdraw-button").should("be.enabled") - cy.getByDataTest("withdraw-button").click() - }) - - cy.get(".chakra-alert").contains("Successful withdraw").should("be.visible") - }) -}) diff --git a/cypress/e2e/2-guild-checkout/1-guild-pins.spec.ts b/cypress/e2e/2-guild-checkout/1-guild-pins.spec.ts deleted file mode 100644 index cb2c9ee864..0000000000 --- a/cypress/e2e/2-guild-checkout/1-guild-pins.spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -describe("guild pins", () => { - beforeEach(() => { - cy.clearIndexedDB() - }) - - it("can't see the guild pin reward card (unauthenticated)", () => { - cy.visit(Cypress.env("TEST_GUILD_URL_NAME")) - cy.getByDataTest("guild-pin-reward-card").should("not.exist") - }) - - it("can see the guild pin reward card (authenticated)", () => { - cy.visit(Cypress.env("TEST_GUILD_URL_NAME")) - cy.connectWallet() - - cy.getByDataTest("guild-pin-reward-card").should("exist") - }) - - it("can see the pin setup modal", () => { - cy.visit(Cypress.env("TEST_GUILD_URL_NAME")) - cy.connectWallet() - - cy.getByDataTest("guild-pin-reward-card") - .get("button") - .contains("Setup Guild Pin") - .click() - - cy.get(".chakra-modal__header").contains("Setup Guild Pin").should("be.visible") - }) - - it("can mint a guild pin", () => { - cy.visit(Cypress.env("GUILD_CHECKOUT_TEST_GUILD_URL_NAME")) - cy.connectWallet() - - cy.intercept("POST", `${Cypress.env("guildApiUrl")}/guilds/*/pin`).as("claim") - - cy.getByDataTest("guild-pin-reward-card") - .get("button") - .contains("Mint Guild Pin") - .click() - - cy.get(".chakra-modal__footer").get("button").contains("Switch network").click() - - cy.get(".chakra-modal__footer") - .getByDataTest("fees-table") - .get("span") - .should("contain", "0.001 MATIC") - - cy.get(".chakra-modal__footer").get("button").contains("Mint NFT").click() - - cy.wait("@claim") - - cy.get(".chakra-alert") - .contains("GUILD_PIN_E2E_TEST_SUCCESS") - .should("be.visible") - }) -}) diff --git a/cypress/e2e/2-guild-checkout/2-nft-reward.spec.ts b/cypress/e2e/2-guild-checkout/2-nft-reward.spec.ts deleted file mode 100644 index b9de174c93..0000000000 --- a/cypress/e2e/2-guild-checkout/2-nft-reward.spec.ts +++ /dev/null @@ -1,110 +0,0 @@ -describe("nft reward", () => { - beforeEach(() => { - cy.clearIndexedDB() - cy.visit(Cypress.env("GUILD_CHECKOUT_TEST_GUILD_URL_NAME")) - cy.connectWallet() - }) - - it("can deploy an nft contract", () => { - // Scrolling to the top of the page to avoid a rare edge case where the add reward button isn't clickable - cy.scrollTo("top") - - cy.getByDataTest("add-reward-button").click() - cy.get("div[role='group']").contains("Create a gated NFT").click({ force: true }) - - cy.get("header.chakra-modal__header").within(() => { - cy.get("p").contains("Add NFT reward").should("exist") - }) - - cy.fixture("cypress-gang-nft.png", null).as("imageInput") - // cy.fixture("cypress-gang-nft.png").as("imageInput") - cy.get("input[type=file]").selectFile("@imageInput", { force: true }) - - cy.get("input[name='name']").type("E2E Test NFT") - cy.get("input[name='symbol']").type("E2E") - cy.get("textarea[name='description']").type("This is the description...") - - cy.get("input[name='attributes.0.name']").should("not.exist") - cy.get("input[name='attributes.0.value']").should("not.exist") - - cy.get("button").contains("Add attribute").click() - - cy.get("input[name='attributes.0.name']").should("exist") - cy.get("input[name='attributes.0.value']").should("exist") - - cy.get("input[name='attributes.0.name']").type("something") - cy.get("input[name='attributes.0.value']").type("anything") - - cy.get("label").contains("Chain").click().type("Mumbai{enter}") - - cy.get("label").contains("Price").click().type(".12345") - - cy.getByDataTest("create-nft-switch-network-button").should("exist") - cy.getByDataTest("create-nft-button").should("be.disabled") - cy.getByDataTest("create-nft-switch-network-button").click() - cy.getByDataTest("create-nft-button").should("be.enabled") - - cy.getByDataTest("create-nft-button").click() - - cy.intercept("GET", "/api/pinata-key", { - body: { - jwt: "mockJWT", - key: "mockKey", - }, - }) - cy.intercept("POST", Cypress.env("PINATA_PIN_FILE_API_URL"), (req) => { - req.reply({ - body: { - IpfsHash: "QmcTynAiKGnwnF77xMEdNAPkjpmpWiWUwcnNdXKU84uJPt", - }, - }) - }) - - // You'll see both an error and a success toast in the tests, that's expected, since we don't actually call the contract & just return an empty object - cy.get(".chakra-alert") - .contains("Successfully deployed NFT contract", { timeout: 40_000 }) - .should("be.visible") - }) - - it("can't collect the nft if requirements aren't satisfied", () => { - cy.get("p") - .contains("Collect: Cypress Gang #1") - .within(() => { - cy.get("a").click() - }) - - cy.url().should("contain", "/collect/") - - cy.getByDataTest("collect-nft-button").should("be.disabled") - cy.getByDataTest("switch-network-button").click() - - cy.getByDataTest("collect-nft-button").should("be.disabled") - }) - - it("can collect an nft if requirements are satisfied", () => { - cy.intercept( - "POST", - `${Cypress.env("guildApiUrl")}/guilds/*/roles/*/role-platforms/*/claim` - ).as("claim") - - cy.get("p") - .contains("Collect: Cypress Gang #2") - .within(() => { - cy.get("a").click() - }) - - cy.url().should("contain", "/collect/") - - cy.getByDataTest("collect-nft-button").should("be.disabled") - cy.getByDataTest("switch-network-button").click() - - cy.getByDataTest("collect-nft-button").should("be.enabled") - cy.getByDataTest("collect-nft-button").click() - - cy.wait("@claim", { - responseTimeout: 40_000, - }) - - cy.get(".chakra-alert").contains("Successfully collected NFT!").should("exist") - }) -}) diff --git a/cypress/e2e/readme.md b/cypress/e2e/readme.md deleted file mode 100644 index f7323f2b4d..0000000000 --- a/cypress/e2e/readme.md +++ /dev/null @@ -1,59 +0,0 @@ -# E2E testing with Cypress - -We use [Cypress](https://www.cypress.io/) for testing. The setup is quite simple, anyone can start writing tests easily. - -### Writing tests - -You should put the `*.spec.ts` files in the `/cypress/e2e` folder. The folder structure is not well defined here, so feel free to change it. Currently there is a `0-guild` folder with the (platformless) guild related tests, a `1-roles-requirements-rewards` folder with the role/requirement related tests, and a `2-guild-checkout` folder with Payment, Guild Pin, and NFT reward related ones. - -It is recommended to start each test by removing data from indexedDB & connecting the mock wallet to the app, like so: - -```ts -before(() => { - cy.clearIndexedDB() - cy.connectWallet() -}) -``` - -Then, you can write the actual test. The official [Cypress guide](https://docs.cypress.io/guides/end-to-end-testing/writing-your-first-end-to-end-test) is a great starting point, it contains most of the resources you'll need to write E2E tests. - -### Custom commands - -Sometimes you can find yourself in a situation where you start repeating yourself. In this case, you can create a custom command within the `/cypress/support/commands.ts` file. We already have a couple of custom commands, like `getByDataTest`, `connectWallet`, and `clearIndexedDB`. - -### How to use selectors - -You should try to be as specific as possible when using the `cy.get()` command. In some cases, you might not be able to select the specific element you want just by using an ID or class - in that case, feel free to add a `data-test` HTML attribute to the element and use the custom `getByDataTest` command in your tests. Here's an example: - -```html - -``` - -```ts -cy.getByDataTest("my-awesome-button").click() -``` - -### Mocking data - -Although we (should) try to use real data in our tests, sometimes we can't avoid mocking API responses. You can define the mocked data in JSON files inside the `/cypress/fixtures` directory, and then use it in your tests using `cy.intercept` a: - -```ts -// Intercept an API call -cy.intercept(`${Cypress.env("guildApiUrl")}/some/endpoint`, { - statusCode: 200, - fixture: "someData.json", -}).as("mockedData") - -// Wait for the intercepted response -cy.wait("@mockedData") -``` - -You can find more details about this topic in the official Cypress docs: [fixture](https://docs.cypress.io/api/commands/fixture#docusaurus_skipToContent_fallback), [intercept](https://docs.cypress.io/api/commands/intercept#docusaurus_skipToContent_fallback) - -### Running Cypress locally - -You can open Cypress UI using the `npm run cypress:open` command. Make sure to set the `NEXT_PUBLIC_MOCK_CONNECTOR` env var to `true` & also define the `NEXT_PUBLIC_E2E_WALLET_MNEMONIC` env var (you can find its value in our 1Password). If you'd just like to run tests in headless mode, you can use the `npm run test` command. - -### GitHub Action - -There's a GitHub Action for running the tests. It'll run when we push a commit to `main`, or when we open a pull request. diff --git a/cypress/fixtures/cypress-gang-nft.png b/cypress/fixtures/cypress-gang-nft.png deleted file mode 100644 index 11aa220855cabb0dadf7a03cb390c1a776381480..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21536 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 GC+t5kgb!2z diff --git a/cypress/fixtures/testUserDiscordGateables.json b/cypress/fixtures/testUserDiscordGateables.json deleted file mode 100644 index 6ce8167d7e..0000000000 --- a/cypress/fixtures/testUserDiscordGateables.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "id": "1096417797292171365", - "name": "Cypress Gang", - "img": "/default_discord_icon.png", - "owner": true - } -] diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts deleted file mode 100644 index 61d389e206..0000000000 --- a/cypress/support/commands.ts +++ /dev/null @@ -1,32 +0,0 @@ -Cypress.Commands.add("getByDataTest", (selector: string) => - cy.get(`[data-test='${selector}']`) -) - -Cypress.Commands.add("connectWallet", () => { - cy.intercept("POST", `${Cypress.env("guildApiUrl")}/users/*/public-key`).as( - "setPubKey" - ) - - cy.getByDataTest("connect-wallet-button").click() - cy.get("[data-wagmi-connector-id='mock']").click() - - cy.getByDataTest("verify-address-button").should("be.visible") - cy.getByDataTest("verify-address-button").click() - - cy.wait("@setPubKey", { requestTimeout: 30_000, responseTimeout: 30_000 }) - .its("response.statusCode") - .should("eq", 200) -}) - -Cypress.Commands.add("clearIndexedDB", () => { - indexedDB.deleteDatabase("guild.xyz") -}) - -// biome-ignore lint/style/noNamespace: -declare namespace Cypress { - interface Chainable { - getByDataTest(selector: string): Chainable> - connectWallet(): Chainable> - clearIndexedDB(): Chainable> - } -} diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts deleted file mode 100644 index b7cb303d80..0000000000 --- a/cypress/support/e2e.ts +++ /dev/null @@ -1 +0,0 @@ -import "./commands" diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json deleted file mode 100644 index b6c74e8347..0000000000 --- a/cypress/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "target": "es5", - "lib": ["es5", "dom"], - "types": ["cypress", "node"], - "sourceMap": false - }, - "include": ["**/*.ts"] -} diff --git a/package-lock.json b/package-lock.json index daf4eb3151..4cd22bcb52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -108,6 +108,7 @@ "@biomejs/biome": "1.8.3", "@chromatic-com/storybook": "^1.6.0", "@hookform/devtools": "^4.3.0", + "@playwright/test": "^1.45.3", "@storybook/addon-essentials": "^8.1.11", "@storybook/addon-interactions": "^8.1.11", "@storybook/addon-links": "^8.1.11", @@ -125,7 +126,6 @@ "abitype": "^1.0.2", "autoprefixer": "^10.4.19", "circular-dependency-plugin": "^5.2.2", - "cypress": "^13.3.2", "dotenv-cli": "^7.4.1", "dpdm": "^3.14.0", "event-stream": "^4.0.1", @@ -3801,78 +3801,6 @@ "node": ">=6" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cypress/request": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", - "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "6.10.4", - "safe-buffer": "^5.1.2", - "tough-cookie": "^4.1.3", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@cypress/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/@dotlottie/common": { "version": "0.7.11", "resolved": "https://registry.npmjs.org/@dotlottie/common/-/common-0.7.11.tgz", @@ -7749,6 +7677,21 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.3.tgz", + "integrity": "sha512-UKF4XsBfy+u3MFWEH44hva1Q8Da28G6RFtR2+5saw+jgAFQV5yYnB1fu68Mz7fO+5GJF3wgwAIs0UelU8TxFrA==", + "devOptional": true, + "dependencies": { + "playwright": "1.45.3" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", @@ -12945,18 +12888,6 @@ "@types/send": "*" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true - }, - "node_modules/@types/sizzle": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", - "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", - "dev": true - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -12994,16 +12925,6 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "peer": true }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -15299,19 +15220,6 @@ "node": ">=8.9.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -15386,37 +15294,12 @@ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=6" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-fragments": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", @@ -15566,26 +15449,6 @@ "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", "peer": true }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -15717,21 +15580,6 @@ "node": ">=4" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true - }, "node_modules/async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", @@ -15751,15 +15599,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -16165,18 +16004,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -16493,15 +16320,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -16685,15 +16503,6 @@ "node": ">= 0.8" } }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -16955,15 +16764,6 @@ "node": "*" } }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -17056,6 +16856,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "peer": true, "engines": { "node": ">=8" } @@ -17141,15 +16942,6 @@ "node": ">=0.10.0" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -17183,37 +16975,6 @@ "node": ">= 0.2.0" } }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -17630,15 +17391,6 @@ "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", "dev": true }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -18209,193 +17961,6 @@ "uniq": "^1.0.0" } }, - "node_modules/cypress": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.0.tgz", - "integrity": "sha512-ou/MQUDq4tcDJI2FsPaod2FZpex4kpIK43JJlcBgWrX8WX7R/05ZxGTuxedOuZBfxjZxja+fbijZGyxiLP6CFA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@cypress/request": "^3.0.0", - "@cypress/xvfb": "^1.2.4", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.7.1", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.1", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.3", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" - }, - "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" - } - }, - "node_modules/cypress/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cypress/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/cypress/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true - }, - "node_modules/cypress/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", - "dev": true - }, - "node_modules/cypress/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.1.tgz", @@ -19275,6 +18840,8 @@ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -19288,6 +18855,8 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -19717,50 +19286,6 @@ "safe-buffer": "^5.1.1" } }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/executable/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", @@ -19861,26 +19386,6 @@ "url": "https://github.com/sponsors/jaydenseric" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -19987,44 +19492,11 @@ "walk-up-path": "^3.0.1" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/fflate": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/file-selector": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz", @@ -20744,30 +20216,6 @@ "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.2.tgz", "integrity": "sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==" }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "dependencies": { - "async": "^3.2.0" - } - }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -20859,21 +20307,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -21446,35 +20879,12 @@ "node": ">= 0.12.0" } }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", "dev": true }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, "node_modules/husky": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", @@ -21639,15 +21049,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/inline-style-parser": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", @@ -21759,18 +21160,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, "node_modules/is-core-module": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", @@ -21880,22 +21269,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -21928,15 +21301,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -22737,21 +22101,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "node_modules/jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", @@ -22809,15 +22158,6 @@ "node": ">= 8" } }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "dev": true, - "engines": { - "node": "> 0.8" - } - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -23333,77 +22673,6 @@ "listhen": "bin/listhen.mjs" } }, - "node_modules/listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/lit": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz", @@ -23511,12 +22780,6 @@ "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true - }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -23586,82 +22849,6 @@ "node": ">=8" } }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/logkitty": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", @@ -26628,12 +25815,6 @@ "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", "dev": true }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -26662,21 +25843,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -26890,12 +26056,6 @@ "node": ">=0.12" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -27082,6 +26242,49 @@ "pathe": "^1.1.2" } }, + "node_modules/playwright": { + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz", + "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", + "devOptional": true, + "dependencies": { + "playwright-core": "1.45.3" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz", + "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", + "devOptional": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pngjs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", @@ -27633,18 +26836,6 @@ } } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -28000,21 +27191,6 @@ "node": ">=8" } }, - "node_modules/qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/query-string": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", @@ -28059,12 +27235,6 @@ "node": ">=0.4.x" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -29767,15 +28937,6 @@ "node": ">= 6" } }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, - "dependencies": { - "throttleit": "^1.0.0" - } - }, "node_modules/request/node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", @@ -29868,12 +29029,6 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -30092,15 +29247,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -30553,35 +29699,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/slugify": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", @@ -31739,15 +30856,6 @@ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", "peer": true }, - "node_modules/throttleit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", - "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -31815,15 +30923,6 @@ "node": ">=14.0.0" } }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, - "engines": { - "node": ">=14.14" - } - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -31872,30 +30971,6 @@ "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -32487,15 +31562,6 @@ "node": ">=0.4.0" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/untun": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/untun/-/untun-0.1.3.tgz", @@ -32561,16 +31627,6 @@ "qs": "^6.11.2" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/url/node_modules/punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -33565,16 +32621,6 @@ "node": ">=12" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, "node_modules/yjs": { "version": "13.6.18", "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.18.tgz", diff --git a/package.json b/package.json index de7bd34faf..75274429be 100644 --- a/package.json +++ b/package.json @@ -9,16 +9,15 @@ "start": "next start", "type-check": "tsc --pretty --noEmit --incremental false --project './tsconfig.build.json'", "write-check": "npx @biomejs/biome check --write --unsafe .", - "cypress:open": "cypress open", - "cypress:open:mobile": "cypress open --config viewportWidth=375,viewportHeight=667", - "test": "cypress run", - "test:mobile": "cypress run --config viewportWidth=375,viewportHeight=667", "snyk-protect": "snyk-protect", "postinstall": "npx dotenv-cli -e .env.local -- bash -c 'npm i --no-save --ignore-scripts $WAAS_WEB_URL $WAAS_VIEM_URL'", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", "dcd": "npx tsx scripts/detectCircularDependencies.ts", - "analyze-bundle": "node scripts/bundleAnalyzer.mjs" + "analyze-bundle": "node scripts/bundleAnalyzer.mjs", + "test": "npx playwright test", + "test:ui": "npx playwright test --ui", + "test:debug": "npx playwright test --debug" }, "dependencies": { "@bugsnag/js": "^7.22.4", @@ -120,6 +119,7 @@ "@biomejs/biome": "1.8.3", "@chromatic-com/storybook": "^1.6.0", "@hookform/devtools": "^4.3.0", + "@playwright/test": "^1.45.3", "@storybook/addon-essentials": "^8.1.11", "@storybook/addon-interactions": "^8.1.11", "@storybook/addon-links": "^8.1.11", @@ -137,7 +137,6 @@ "abitype": "^1.0.2", "autoprefixer": "^10.4.19", "circular-dependency-plugin": "^5.2.2", - "cypress": "^13.3.2", "dotenv-cli": "^7.4.1", "dpdm": "^3.14.0", "event-stream": "^4.0.1", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000000..fa9dc2d5fc --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,71 @@ +import { defineConfig, devices } from "@playwright/test" + +const baseURL = process.env.DEPLOYMENT_URL || "http://localhost:3000" + +export default defineConfig({ + testDir: "./playwright", + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: "html", + outputDir: "playwright/results/", + + use: { + baseURL, + trace: "on-first-retry", + }, + + projects: [ + { + name: "auth-setup", + testMatch: /auth\.setup\.ts/, + use: { + ...devices["Desktop Chrome"], + userAgent: `${devices["Desktop Chrome"].userAgent} GUILD_E2E`, + }, + }, + { + name: "chromium", + use: { + ...devices["Desktop Chrome"], + userAgent: `${devices["Desktop Chrome"].userAgent} GUILD_E2E`, + }, + dependencies: ["auth-setup"], + }, + // { + // name: "firefox", + // use: { + // ...devices["Desktop Firefox"], + // }, + // dependencies: ["auth-setup"], + // }, + // { + // name: "webkit", + // use: { + // ...devices["Desktop Safari"], + // }, + // dependencies: ["auth-setup"], + // }, + // { + // name: "Mobile Chrome", + // use: { + // ...devices["Pixel 5"], + // }, + // dependencies: ["auth-setup"], + // }, + // { + // name: "Mobile Safari", + // use: { + // ...devices["iPhone 12"], + // }, + // dependencies: ["auth-setup"], + // }, + ], + + webServer: { + command: process.env.CI ? "" : "npm run start", + url: baseURL, + reuseExistingServer: true, + }, +}) diff --git a/playwright/auth.setup.ts b/playwright/auth.setup.ts new file mode 100644 index 0000000000..659a055409 --- /dev/null +++ b/playwright/auth.setup.ts @@ -0,0 +1,89 @@ +import fs from "fs" +import path from "path" +import { expect, test as setup } from "@playwright/test" +import { StoredKeyPair } from "utils/keyPair" +import { TEST_USER } from "./constants" + +const authFile = "playwright/.auth/user.json" + +setup("authenticate", async ({ page }) => { + await page.addInitScript(() => { + /** + * Always calling the `generateKey` method with `extractable: true`, so we can save & re-use the generated keys in our E2E tests + */ + const originalGenerateKey = window.crypto.subtle.generateKey + + window.crypto.subtle.generateKey = async function ( + algorithm, + _extractable, + keyUsages + ) { + return originalGenerateKey.call(this, algorithm, true, keyUsages) + } + }) + + await page.goto("/explorer") + await page.getByTestId("sign-in-button").click() + + const signInDialog = await page.getByRole("dialog", { + name: "Connect to Guild", + }) + expect(signInDialog).toBeVisible() + + await page.getByTestId("mock-connector-button").click() + await page.getByTestId("verify-address-button").click() + + const publicKeyResponse = await page + .waitForResponse(`**/v2/users/${TEST_USER.id}/public-key`) + .then((res) => res.json()) + + const storedKeyPairToSave = await page.evaluate( + async ({ userId }) => { + const idb = await new Promise((resolve, reject) => { + const request = indexedDB.open("guild.xyz") + + request.onsuccess = () => resolve(request.result) + request.onerror = () => reject(request.error) + }) + + const keyPair = await new Promise((resolve, reject) => { + const transaction = idb.transaction("signingKeyPairs", "readonly") + const store = transaction.objectStore("signingKeyPairs") + const request = store.get(userId) + + request.onsuccess = () => resolve(request.result) + request.onerror = () => reject(request.error) + }) + + const exportedPrivateKey = await window.crypto.subtle.exportKey( + "jwk", + keyPair.keyPair.privateKey + ) + const exportedPublicKey = await window.crypto.subtle.exportKey( + "jwk", + keyPair.keyPair.publicKey + ) + + return { + pubKey: keyPair.pubKey, + keyPair: { privateKey: exportedPrivateKey, publicKey: exportedPublicKey }, + } + }, + { userId: publicKeyResponse.id } + ) + + try { + fs.mkdirSync(path.join(__dirname, "/.auth")) + // biome-ignore lint/suspicious/noEmptyBlockStatements: we don't need to re-create the directory if it already exists + } catch {} + + fs.writeFileSync( + path.join(__dirname, "/.auth/keyPair.json"), + JSON.stringify(storedKeyPairToSave), + { + flag: "w+", + } + ) + + await page.context().storageState({ path: authFile }) +}) diff --git a/playwright/constants.ts b/playwright/constants.ts new file mode 100644 index 0000000000..40162d10fc --- /dev/null +++ b/playwright/constants.ts @@ -0,0 +1,4 @@ +export const TEST_USER = { + id: 953897, + address: "0x304def656babc745c53782639d3cab00ace8c843", +} as const diff --git a/playwright/dummy.spec.ts b/playwright/dummy.spec.ts new file mode 100644 index 0000000000..780b34b02b --- /dev/null +++ b/playwright/dummy.spec.ts @@ -0,0 +1,12 @@ +import { expect } from "@playwright/test" +import { TEST_USER } from "./constants" +import { test } from "./fixtures" + +test("dummy", async ({ pageWithKeyPair: { page } }) => { + await page.goto("/explorer") + + const accountCard = await page.getByTestId("account-card") + expect(accountCard).toBeVisible() + + await page.waitForResponse(`**/v2/users/${TEST_USER.id}/profile`) +}) diff --git a/playwright/fixtures.ts b/playwright/fixtures.ts new file mode 100644 index 0000000000..0ce74c8bd2 --- /dev/null +++ b/playwright/fixtures.ts @@ -0,0 +1,95 @@ +import { JsonWebKey } from "crypto" +import fs from "fs" +import path from "path" +import { type Page, test as base } from "@playwright/test" +import { StoredKeyPair } from "utils/keyPair" +import { TEST_USER } from "./constants" + +class PageWithKeyPair { + page: Page + + constructor(page: Page) { + this.page = page + } +} + +type Fixtures = { + pageWithKeyPair: PageWithKeyPair +} + +export const test = base.extend({ + pageWithKeyPair: async ({ browser }, use) => { + const context = await browser.newContext({ + storageState: "playwright/.auth/user.json", + }) + const pageWithKeyPair = new PageWithKeyPair(await context.newPage()) + + const keyPairPath = path.join(__dirname, "/.auth/keyPair.json") + const importedKeyPairData: { + pubKey: StoredKeyPair["pubKey"] + keyPair: { + publicKey: JsonWebKey + privateKey: JsonWebKey + } + } = JSON.parse(fs.readFileSync(keyPairPath, "utf8")) + + await pageWithKeyPair.page.addInitScript( + async ({ importedKeyPairData, userId }) => { + const importedPublicKey = await crypto.subtle.importKey( + "jwk", + importedKeyPairData.keyPair.publicKey, + { + name: "ECDSA", + namedCurve: "P-256", + }, + false, + ["verify"] + ) + + const importedPrivateKey = await crypto.subtle.importKey( + "jwk", + importedKeyPairData.keyPair.privateKey, + { + name: "ECDSA", + namedCurve: "P-256", + }, + false, + ["sign"] + ) + + const idb = await new Promise((resolve, reject) => { + const request = indexedDB.open("guild.xyz") + + request.onupgradeneeded = () => { + request.result.createObjectStore("signingKeyPairs") + } + + request.onsuccess = () => resolve(request.result) + request.onerror = () => reject(request.error) + }) + + await new Promise((resolve, reject) => { + const transaction = idb.transaction("signingKeyPairs", "readwrite") + const store = transaction.objectStore("signingKeyPairs") + + const keyPairToSave = { + pubKey: importedKeyPairData.pubKey, + keyPair: { + privateKey: importedPrivateKey, + publicKey: importedPublicKey, + }, + } satisfies StoredKeyPair + + const request = store.put(keyPairToSave, userId) + + request.onsuccess = () => resolve() + request.onerror = () => reject(request.error) + }) + }, + { importedKeyPairData, userId: TEST_USER.id } + ) + + await use(pageWithKeyPair) + await context.close() + }, +}) diff --git a/src/components/[guild]/Requirements/components/GuildCheckout/hooks/useMintGuildPin.tsx b/src/components/[guild]/Requirements/components/GuildCheckout/hooks/useMintGuildPin.tsx index 9166b6fc26..651cb52639 100644 --- a/src/components/[guild]/Requirements/components/GuildCheckout/hooks/useMintGuildPin.tsx +++ b/src/components/[guild]/Requirements/components/GuildCheckout/hooks/useMintGuildPin.tsx @@ -121,14 +121,6 @@ const useMintGuildPin = () => { account: walletClient.account, }) - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - toastWithTweetButton({ - title: "GUILD_PIN_E2E_TEST_SUCCESS", - tweetText: "", - }) - return Promise.resolve() - } - const hash = await walletClient.writeContract({ ...request, account: walletClient.account, diff --git a/src/components/[guild]/RolePlatforms/components/AddRoleRewardModal/components/AddContractCallPanel/components/CreateNftForm/hooks/useCreateNft.ts b/src/components/[guild]/RolePlatforms/components/AddRoleRewardModal/components/AddContractCallPanel/components/CreateNftForm/hooks/useCreateNft.ts index 833d17408b..c19c66b4c3 100644 --- a/src/components/[guild]/RolePlatforms/components/AddRoleRewardModal/components/AddContractCallPanel/components/CreateNftForm/hooks/useCreateNft.ts +++ b/src/components/[guild]/RolePlatforms/components/AddRoleRewardModal/components/AddContractCallPanel/components/CreateNftForm/hooks/useCreateNft.ts @@ -149,10 +149,6 @@ const useCreateNft = ( args: contractCallParams, }) - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - return Promise.resolve({} as CreateNFTResponse) - } - const hash = await walletClient.writeContract({ ...request, }) diff --git a/src/components/[guild]/collect/hooks/useCollectNft.ts b/src/components/[guild]/collect/hooks/useCollectNft.ts index 33cb4fb111..75ceb5daa3 100644 --- a/src/components/[guild]/collect/hooks/useCollectNft.ts +++ b/src/components/[guild]/collect/hooks/useCollectNft.ts @@ -155,10 +155,6 @@ const useCollectNft = () => { request = newClaimRequest } - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - return Promise.resolve({} as TransactionReceipt) - } - const hash = await walletClient.writeContract({ ...request, account: walletClient.account, diff --git a/src/hooks/useSubmitTransaction.ts b/src/hooks/useSubmitTransaction.ts index a43ad3e46e..b68f31ee36 100644 --- a/src/hooks/useSubmitTransaction.ts +++ b/src/hooks/useSubmitTransaction.ts @@ -182,15 +182,6 @@ const useSubmitTransaction = ( return } - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - setTxHash( - "0x0000000000000000000000000000000000000000000000000000000000000000" - ) - setTxSuccess(true) - onSuccess({} as TransactionReceipt, []) - return - } - // TODO: properly type this writeContract(contractCallConfig as WriteContractParameters) }, diff --git a/src/requirements/Payment/components/RegisterVaultForm/hooks/useRegisterVault.ts b/src/requirements/Payment/components/RegisterVaultForm/hooks/useRegisterVault.ts index dc2935ed6f..11f7a626ca 100644 --- a/src/requirements/Payment/components/RegisterVaultForm/hooks/useRegisterVault.ts +++ b/src/requirements/Payment/components/RegisterVaultForm/hooks/useRegisterVault.ts @@ -65,11 +65,6 @@ const useRegisterVault = ({ }) }, onSuccess: (_, events) => { - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - onSuccess("0") - return - } - const vaultRegisteredEvent = findEvent< typeof feeCollectorAbi, "VaultRegistered" diff --git a/src/rewards/Token/hooks/useCollectToken.tsx b/src/rewards/Token/hooks/useCollectToken.tsx index e134276bf1..f3873f8ff9 100644 --- a/src/rewards/Token/hooks/useCollectToken.tsx +++ b/src/rewards/Token/hooks/useCollectToken.tsx @@ -103,10 +103,6 @@ const useCollectToken = ( account: walletClient.account, }) - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - return Promise.resolve({} as TransactionReceipt) - } - const hash = await walletClient.writeContract({ ...request, account: walletClient.account, diff --git a/src/rewards/Token/hooks/useRegisterPool.tsx b/src/rewards/Token/hooks/useRegisterPool.tsx index 5425cc93ee..a505f9859b 100644 --- a/src/rewards/Token/hooks/useRegisterPool.tsx +++ b/src/rewards/Token/hooks/useRegisterPool.tsx @@ -36,10 +36,6 @@ const useRegisterPool = ( console.error(error) }, onSuccess: (_, events) => { - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - return - } - const poolRegisteredEvent = findEvent< typeof tokenRewardPoolAbi, "PoolRegistered" diff --git a/src/rewards/Token/hooks/useWithdrawPool.tsx b/src/rewards/Token/hooks/useWithdrawPool.tsx index b43dce4c5d..c92b446c9c 100644 --- a/src/rewards/Token/hooks/useWithdrawPool.tsx +++ b/src/rewards/Token/hooks/useWithdrawPool.tsx @@ -29,9 +29,6 @@ const useWithdrawPool = (chain: Chain, poolId: bigint, onSuccess: () => void) => console.error(error) }, onSuccess: () => { - if (process.env.NEXT_PUBLIC_MOCK_CONNECTOR) { - return - } captureEvent("Funds withdrawn from pool", { ...postHogOptions }) onSuccess() }, diff --git a/src/v2/components/Account/Account.tsx b/src/v2/components/Account/Account.tsx index ba32ec5929..26712937d6 100644 --- a/src/v2/components/Account/Account.tsx +++ b/src/v2/components/Account/Account.tsx @@ -31,7 +31,11 @@ export const Account = () => { if (!address) return ( - @@ -39,7 +43,7 @@ export const Account = () => { ) return ( - + diff --git a/src/v2/components/Web3ConnectionManager/WalletSelectorModal/components/ConnectorButton.tsx b/src/v2/components/Web3ConnectionManager/WalletSelectorModal/components/ConnectorButton.tsx index 78e004b47c..cea2495f09 100644 --- a/src/v2/components/Web3ConnectionManager/WalletSelectorModal/components/ConnectorButton.tsx +++ b/src/v2/components/Web3ConnectionManager/WalletSelectorModal/components/ConnectorButton.tsx @@ -52,6 +52,7 @@ const ConnectorButton = ({ connector, pendingConnector, connect, error }: Props) !error } loadingText={`${connectorName} - connecting...`} + data-testid={`${connector.id}-connector-button`} > {connectorIcon ? (
diff --git a/src/v2/hooks/useAutoReconnect.ts b/src/v2/hooks/useAutoReconnect.ts index d0b51116ce..491831e950 100644 --- a/src/v2/hooks/useAutoReconnect.ts +++ b/src/v2/hooks/useAutoReconnect.ts @@ -13,11 +13,14 @@ const useAutoReconnect = () => { let connected = false + let canConnectToSafe = false const safeConnector = connectors.find((connector) => connector.id === "safe") - const canConnectToSafe = await safeConnector - .getProvider() - .then((provider) => !!provider) - .catch(() => false) + if (safeConnector) { + canConnectToSafe = await safeConnector + .getProvider() + .then((provider) => !!provider) + .catch(() => false) + } const recentConnectorId = await config.storage.getItem("recentConnectorId") if (!recentConnectorId && !canConnectToSafe) return diff --git a/src/wagmiConfig/index.ts b/src/wagmiConfig/index.ts index a822c09535..e37f75f992 100644 --- a/src/wagmiConfig/index.ts +++ b/src/wagmiConfig/index.ts @@ -179,7 +179,11 @@ export const wagmiConfig = createConfig({ [blast.id]: http(), [blastSepolia.id]: http(), [oasisSapphire.id]: http(), - [sepolia.id]: http("https://ethereum-sepolia-rpc.publicnode.com"), + [sepolia.id]: http( + process.env.NEXT_PUBLIC_E2E_WALLET_MNEMONIC + ? "http://localhost:8545" + : "https://ethereum-sepolia-rpc.publicnode.com" + ), [astarZkEVM.id]: http(), [coreDao.id]: http(), [liskSepolia.id]: http(), @@ -191,40 +195,48 @@ export const wagmiConfig = createConfig({ [mint.id]: http(), }, ssr: true, - connectors: process.env.NEXT_PUBLIC_MOCK_CONNECTOR - ? [ - mock({ - accounts: [mnemonicToAccount(process.env.NEXT_PUBLIC_E2E_WALLET_MNEMONIC)], - }), - ] - : [ - injected(), - coinbaseWallet({ - appName: "Guild.xyz", - appLogoUrl: "https://guild.xyz/guild-icon.png", - version: "4", - }), - walletConnect({ - projectId: env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID, - showQrModal: true, - qrModalOptions: { - explorerRecommendedWalletIds: [ - "971e689d0a5be527bac79629b4ee9b925e82208e5168b733496a09c0faed0709", // OKX - "107bb20463699c4e614d3a2fb7b961e66f48774cb8f6d6c1aee789853280972c", // Bitcoin.com - "541d5dcd4ede02f3afaf75bf8e3e4c4f1fb09edb5fa6c4377ebf31c2785d9adf", // Ronin - "4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0", // Trust + connectors: + typeof navigator !== "undefined" && + navigator.userAgent.includes("GUILD_E2E") && + process.env.NEXT_PUBLIC_E2E_WALLET_MNEMONIC + ? [ + mock({ + accounts: [ + mnemonicToAccount(process.env.NEXT_PUBLIC_E2E_WALLET_MNEMONIC), ], - themeVariables: { - "--wcm-z-index": "10001", - "--w3m-z-index": "10001", - } as any, // casting it, so `--wcm-z-index` is accepted - }, - }), - safe({ - allowedDomains: [/gnosis-safe\.io$/, /app\.safe\.global$/], - debug: false, - }), - ], + features: { + reconnect: true, + }, + }), + ] + : [ + injected(), + coinbaseWallet({ + appName: "Guild.xyz", + appLogoUrl: "https://guild.xyz/guild-icon.png", + version: "4", + }), + walletConnect({ + projectId: env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID, + showQrModal: true, + qrModalOptions: { + explorerRecommendedWalletIds: [ + "971e689d0a5be527bac79629b4ee9b925e82208e5168b733496a09c0faed0709", // OKX + "107bb20463699c4e614d3a2fb7b961e66f48774cb8f6d6c1aee789853280972c", // Bitcoin.com + "541d5dcd4ede02f3afaf75bf8e3e4c4f1fb09edb5fa6c4377ebf31c2785d9adf", // Ronin + "4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0", // Trust + ], + themeVariables: { + "--wcm-z-index": "10001", + "--w3m-z-index": "10001", + } as any, // casting it, so `--wcm-z-index` is accepted + }, + }), + safe({ + allowedDomains: [/gnosis-safe\.io$/, /app\.safe\.global$/], + debug: false, + }), + ], }) export const COINBASE_INJECTED_WALLET_ID = "com.coinbase.wallet" diff --git a/src/wagmiConfig/mockConnector.ts b/src/wagmiConfig/mockConnector.ts index 171d5b0f97..c6f2080473 100644 --- a/src/wagmiConfig/mockConnector.ts +++ b/src/wagmiConfig/mockConnector.ts @@ -64,19 +64,21 @@ export function mock( let currentChainId = await this.getChainId() if (chainId && currentChainId !== chainId) { - const chain = await this.switchChain({ chainId }) - currentChainId = chain.id + const chain = await this.switchChain?.({ chainId }) + + if (chain) currentChainId = chain.id } connected = true + await config.storage?.setItem("mock.connected", true) return { accounts, chainId: currentChainId } }, async disconnect() { + await config.storage?.removeItem("mock.connected") connected = false }, async getAccounts() { - if (!connected) throw new Error("Connector is not connected") const provider = await this.getProvider() const accounts = await provider.request({ method: "eth_accounts" }) return accounts.map((x) => getAddress(x)) @@ -88,7 +90,10 @@ export function mock( }, async isAuthorized() { if (!features.reconnect) return false - if (!connected) return false + + const connectedLocal = await config.storage?.getItem("mock.connected") + if (!connectedLocal) return false + const accounts = await this.getAccounts() return !!accounts.length }, @@ -180,10 +185,10 @@ export function mock( return custom({ request })({ retryCount: 0 }) }, - async getClient({ chainId }) { + async getClient({ chainId } = {}) { const client = createWalletClient({ transport: http( - config.chains.find((c) => c.id === chainId).rpcUrls.default.http[0] + config.chains.find((c) => c.id === chainId)?.rpcUrls.default.http[0] ), account: parameters.accounts[0], }) as Client diff --git a/tsconfig.json b/tsconfig.json index d247ed23f5..9a5bd0c77f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,11 +32,11 @@ "./src/**/*.ts", "./src/**/*.tsx", "api/**/*.ts", - "cypress.config.ts", - "cypress/**/*.ts", ".next/types/**/*.ts", "tailwind.config.ts", - "scripts/detectCircularDependencies.ts" + "scripts/detectCircularDependencies.ts", + "playwright.config.ts", + "playwright/**/*.ts" ], "exclude": ["node_modules", ".next", "out"] }