From f0e82b007acc443bf54619cda55466dfb49bc3a8 Mon Sep 17 00:00:00 2001 From: James Dabbs Date: Sat, 27 Jun 2026 22:06:28 -0700 Subject: [PATCH 1/3] =?UTF-8?q?chore(viewer):=20upgrade=20Cypress=2014=20?= =?UTF-8?q?=E2=86=92=2015=20and=20add=20e2e=20retries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump cypress 14.3.2 → 15.18.0. Node 22 satisfies v15's engines (^20.1 || ^22 || >=24) and none of v15's breaking changes touch how we use it (no component testing, no cy.stub 3-arg, no SelectorPlayground). v15 routing cy.url()/location()/title() through CDP/BiDi is a plus when pointing at live cross-origin deployments. Test Replay comes for free on `cypress run --record` (already used in CI). Add `retries: { runMode: 2, openMode: 0 }` to absorb transient flake on remote/live runs (network hiccups, async client-side deduction). Verified 16/16 green in the hermetic path (local build + fixture). --- packages/viewer/cypress.config.ts | 3 + packages/viewer/package.json | 2 +- pnpm-lock.yaml | 426 +++++++++++++----------------- 3 files changed, 189 insertions(+), 242 deletions(-) diff --git a/packages/viewer/cypress.config.ts b/packages/viewer/cypress.config.ts index c3f294a8..ddd03726 100644 --- a/packages/viewer/cypress.config.ts +++ b/packages/viewer/cypress.config.ts @@ -32,5 +32,8 @@ export default defineConfig({ experimentalRunAllSpecs: true, specPattern: 'cypress/e2e/**/*.{ts,tsx}', supportFile: false, + // Retry in CI/headless runs to absorb transient flake — network hiccups and + // async deduction when pointed at a live (non-intercepted) deployment. + retries: { runMode: 2, openMode: 0 }, }, }) diff --git a/packages/viewer/package.json b/packages/viewer/package.json index a6e69334..0cd90af6 100644 --- a/packages/viewer/package.json +++ b/packages/viewer/package.json @@ -52,7 +52,7 @@ "@types/katex": "^0.16.8", "@types/page": "^1.11.9", "@types/unist": "^2.0.10", - "cypress": "^14.3.2", + "cypress": "^15.18.0", "svelte": "^4.2.20", "svelte-check": "^3.6.3", "svelte-preprocess": "^5.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95695c10..389b2af2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -246,8 +246,8 @@ importers: specifier: ^2.0.10 version: 2.0.10 cypress: - specifier: ^14.3.2 - version: 14.4.1 + specifier: ^15.18.0 + version: 15.18.0 svelte: specifier: ^4.2.20 version: 4.2.20 @@ -451,9 +451,9 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@cypress/request@3.0.8': - resolution: {integrity: sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==} - engines: {node: '>= 6'} + '@cypress/request@4.0.1': + resolution: {integrity: sha512-y20e+e6dFYkOUUJLVUZTsJRuTiXZaUQ32WD+R/ux/HBybbTx4ge7cNINcua0pU8+SNkKuRbOF12mBmzuzM8n5w==} + engines: {node: '>= 14.17.0'} '@cypress/xvfb@1.2.4': resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} @@ -1428,6 +1428,9 @@ packages: '@types/sizzle@2.3.8': resolution: {integrity: sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==} + '@types/tmp@0.2.6': + resolution: {integrity: sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==} + '@types/unist@2.0.10': resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} @@ -1440,9 +1443,6 @@ packages: '@types/yaml-front-matter@4.1.3': resolution: {integrity: sha512-XDsnZdIZ8QGRFzfRTCSxjbm0NGQQfFPxk2zqy0DB4SH2TXJVptzdY+IgDNM1K2ZIjFvFaHo2l5wJd71JzMeI9A==} - '@types/yauzl@2.10.3': - resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@7.11.0': resolution: {integrity: sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1732,14 +1732,6 @@ packages: ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - ansi-escapes@7.0.0: resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} engines: {node: '>=18'} @@ -1752,6 +1744,10 @@ packages: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -1768,6 +1764,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -1820,13 +1820,6 @@ packages: assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - - async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -2072,10 +2065,6 @@ packages: check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - check-more-types@2.24.0: - resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} - engines: {node: '>= 0.8.0'} - cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -2129,10 +2118,6 @@ packages: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} - cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - cli-cursor@4.0.0: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2153,14 +2138,14 @@ packages: resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} engines: {node: 10.* || >= 12.*} - cli-truncate@2.1.0: - resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} - engines: {node: '>=8'} - cli-truncate@4.0.0: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} + engines: {node: '>=20'} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -2313,9 +2298,9 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - cypress@14.4.1: - resolution: {integrity: sha512-YSGvVXtTqSGRTyHbaxHI5dHU/9xc5ymaTIM4BU85GKhj980y6XgA3fShSpj5DatS8knXMsAvYItQxVQFHGpUtw==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + cypress@15.18.0: + resolution: {integrity: sha512-aLfOYSLlVt1b6QSoVUjbCY27taZlYAT8ST47xQbwd9pvQrY/g5gXi12yItZTB+kxkkj+ZcvUYmRLUC95SlCJsw==} + engines: {node: ^20.1.0 || ^22.0.0 || >=24.0.0} hasBin: true d3-array@3.2.4: @@ -2670,10 +2655,6 @@ packages: resolution: {integrity: sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw==} engines: {node: '>=10.13.0'} - enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - entities@2.1.0: resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==} @@ -2734,6 +2715,10 @@ packages: resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} @@ -2867,11 +2852,6 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - extract-zip@2.0.1: - resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} - engines: {node: '>= 10.17.0'} - hasBin: true - extsprintf@1.3.0: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} @@ -2905,10 +2885,6 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2962,6 +2938,10 @@ packages: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -3027,6 +3007,10 @@ packages: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} + engines: {node: '>=18'} + get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} @@ -3065,9 +3049,6 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} - getos@3.2.1: - resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==} - getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} @@ -3191,6 +3172,10 @@ packages: resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasha@5.2.2: + resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} + engines: {node: '>=8'} + hasown@2.0.0: resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} engines: {node: '>= 0.4'} @@ -3199,6 +3184,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + hast-to-hyperscript@10.0.3: resolution: {integrity: sha512-NuBoUStp4fRwmvlfbidlEiRSTk0gSHm+97q4Xn9CJ10HO+Py7nlTuDi6RhM1qLOureukGrCXLG7AAxaGqqyslQ==} @@ -3481,6 +3470,10 @@ packages: resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} engines: {node: '>=18'} + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -3739,10 +3732,6 @@ packages: resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} engines: {node: '>=14.16'} - lazy-ass@1.6.0: - resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} - engines: {node: '> 0.8'} - leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -3766,19 +3755,14 @@ packages: engines: {node: '>=20.17'} hasBin: true - listr2@3.14.0: - resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} - engines: {node: '>=10.0.0'} - peerDependencies: - enquirer: '>= 2.3.0 < 3' - peerDependenciesMeta: - enquirer: - optional: true - listr2@8.3.3: resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} engines: {node: '>=18.0.0'} + listr2@9.0.5: + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} + engines: {node: '>=20.0.0'} + load-json-file@4.0.0: resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} engines: {node: '>=4'} @@ -3829,6 +3813,9 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} @@ -3837,10 +3824,6 @@ packages: resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} engines: {node: '>=12'} - log-update@4.0.0: - resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} - engines: {node: '>=10'} - log-update@6.1.0: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} @@ -4710,8 +4693,8 @@ packages: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} - qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + qs@6.15.3: + resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} engines: {node: '>=0.6'} queue-microtask@1.2.3: @@ -4857,10 +4840,6 @@ packages: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} engines: {node: '>=14.16'} - restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - restore-cursor@4.0.0: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4877,9 +4856,6 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} @@ -4912,9 +4888,6 @@ packages: rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} @@ -4971,11 +4944,6 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} - engines: {node: '>=10'} - hasBin: true - semver@7.8.5: resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} engines: {node: '>=10'} @@ -5043,8 +5011,8 @@ packages: shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} engines: {node: '>= 0.4'} side-channel-map@1.0.1: @@ -5058,8 +5026,8 @@ packages: side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} engines: {node: '>= 0.4'} siginfo@2.0.0: @@ -5098,14 +5066,6 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slice-ansi@3.0.0: - resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} - engines: {node: '>=8'} - - slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -5114,6 +5074,10 @@ packages: resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} engines: {node: '>=18'} + slice-ansi@8.0.0: + resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} + engines: {node: '>=20'} + smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -5226,6 +5190,10 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.2.1: + resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} + engines: {node: '>=20'} + string.prototype.padend@3.1.6: resolution: {integrity: sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==} engines: {node: '>= 0.4'} @@ -5258,6 +5226,10 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -5365,6 +5337,12 @@ packages: resolution: {integrity: sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==} engines: {node: '>=16'} + systeminformation@5.31.11: + resolution: {integrity: sha512-I6O7iaUj23AXRgCPDDnvi3xHvdOLp4+1YMbF+X194lJwY1NeWojgHJPhslVKcmTtrLTguRk3QJK+xEdTiI3P0w==} + engines: {node: '>=8.0.0'} + os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] + hasBin: true + tapable@2.3.3: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} @@ -5399,9 +5377,6 @@ packages: throttleit@1.0.1: resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} @@ -5427,8 +5402,8 @@ packages: resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} engines: {node: '>=8.17.0'} - tmp@0.2.3: - resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + tmp@0.2.7: + resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==} engines: {node: '>=14.14'} to-fast-properties@2.0.0: @@ -5508,6 +5483,9 @@ packages: tsheredoc@1.0.1: resolution: {integrity: sha512-aOyKWGdZSKEMFnzlccLu3wwB4VgpGhJ6bZON9uM+p8hgHSczfMvPdspxX+Dkr+q8/Dpgla1UwK6pFLmutUEUaw==} + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -5542,9 +5520,9 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} @@ -5905,10 +5883,6 @@ packages: '@cloudflare/workers-types': optional: true - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -5990,6 +5964,10 @@ packages: yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yauzl@3.4.0: + resolution: {integrity: sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==} + engines: {node: '>=12'} + yazl@2.5.1: resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} @@ -6157,7 +6135,7 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@cypress/request@3.0.8': + '@cypress/request@4.0.1': dependencies: aws-sign2: 0.7.0 aws4: 1.12.0 @@ -6165,18 +6143,17 @@ snapshots: combined-stream: 1.0.8 extend: 3.0.2 forever-agent: 0.6.1 - form-data: 4.0.0 + form-data: 4.0.6 http-signature: 1.4.0 is-typedarray: 1.0.0 isstream: 0.1.2 json-stringify-safe: 5.0.1 mime-types: 2.1.35 performance-now: 2.1.0 - qs: 6.14.0 + qs: 6.15.3 safe-buffer: 5.2.1 tough-cookie: 5.1.2 tunnel-agent: 0.6.0 - uuid: 8.3.2 '@cypress/xvfb@1.2.4(supports-color@8.1.1)': dependencies: @@ -6939,6 +6916,8 @@ snapshots: '@types/sizzle@2.3.8': {} + '@types/tmp@0.2.6': {} + '@types/unist@2.0.10': {} '@types/vscode@1.89.0': {} @@ -6950,11 +6929,6 @@ snapshots: '@types/js-yaml': 4.0.9 '@types/node': 22.15.31 - '@types/yauzl@2.10.3': - dependencies: - '@types/node': 22.15.31 - optional: true - '@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.10.0 @@ -7344,12 +7318,6 @@ snapshots: dependencies: string-width: 4.2.3 - ansi-colors@4.1.3: {} - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - ansi-escapes@7.0.0: dependencies: environment: 1.1.0 @@ -7358,6 +7326,8 @@ snapshots: ansi-regex@6.0.1: {} + ansi-regex@6.2.2: {} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 @@ -7370,6 +7340,8 @@ snapshots: ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -7424,10 +7396,6 @@ snapshots: assertion-error@1.1.0: {} - astral-regex@2.0.0: {} - - async@3.2.5: {} - asynckit@0.4.0: {} at-least-node@1.0.0: {} @@ -7719,8 +7687,6 @@ snapshots: dependencies: get-func-name: 2.0.2 - check-more-types@2.24.0: {} - cheerio-select@2.1.0: dependencies: boolbase: 1.0.0 @@ -7791,10 +7757,6 @@ snapshots: cli-boxes@3.0.0: {} - cli-cursor@3.1.0: - dependencies: - restore-cursor: 3.1.0 - cli-cursor@4.0.0: dependencies: restore-cursor: 4.0.0 @@ -7817,16 +7779,16 @@ snapshots: optionalDependencies: '@colors/colors': 1.5.0 - cli-truncate@2.1.0: - dependencies: - slice-ansi: 3.0.0 - string-width: 4.2.3 - cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 string-width: 7.2.0 + cli-truncate@5.2.0: + dependencies: + slice-ansi: 8.0.0 + string-width: 8.2.1 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -7971,38 +7933,33 @@ snapshots: css-what@6.1.0: {} - cypress@14.4.1: + cypress@15.18.0: dependencies: - '@cypress/request': 3.0.8 + '@cypress/request': 4.0.1 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.8 + '@types/tmp': 0.2.6 arch: 2.2.0 blob-util: 2.0.2 bluebird: 3.7.2 buffer: 5.7.1 cachedir: 2.4.0 chalk: 4.1.2 - check-more-types: 2.24.0 ci-info: 4.2.0 - cli-cursor: 3.1.0 cli-table3: 0.6.1 commander: 6.2.1 common-tags: 1.8.2 dayjs: 1.11.10 debug: 4.4.3(supports-color@8.1.1) - enquirer: 2.4.1 eventemitter2: 6.4.7 execa: 4.1.0 executable: 4.1.1 - extract-zip: 2.0.1(supports-color@8.1.1) - figures: 3.2.0 fs-extra: 9.1.0 - getos: 3.2.1 + hasha: 5.2.2 is-installed-globally: 0.4.0 - lazy-ass: 1.6.0 - listr2: 3.14.0(enquirer@2.4.1) - lodash: 4.17.21 + listr2: 9.0.5 + lodash: 4.18.1 log-symbols: 4.1.0 minimist: 1.2.8 ospath: 1.2.2 @@ -8010,12 +7967,13 @@ snapshots: process: 0.11.10 proxy-from-env: 1.0.0 request-progress: 3.0.0 - semver: 7.7.2 supports-color: 8.1.1 - tmp: 0.2.3 + systeminformation: 5.31.11 + tmp: 0.2.7 tree-kill: 1.2.2 + tslib: 1.14.1 untildify: 4.0.0 - yauzl: 2.10.0 + yauzl: 3.4.0 d3-array@3.2.4: dependencies: @@ -8377,11 +8335,6 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 - enquirer@2.4.1: - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - entities@2.1.0: {} entities@4.5.0: {} @@ -8473,6 +8426,13 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 @@ -8710,16 +8670,6 @@ snapshots: extend@3.0.2: {} - extract-zip@2.0.1(supports-color@8.1.1): - dependencies: - debug: 4.4.3(supports-color@8.1.1) - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.3 - transitivePeerDependencies: - - supports-color - extsprintf@1.3.0: {} fast-deep-equal@3.1.3: {} @@ -8750,10 +8700,6 @@ snapshots: dependencies: pend: 1.2.0 - figures@3.2.0: - dependencies: - escape-string-regexp: 1.0.5 - file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -8817,6 +8763,14 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + forwarded@0.2.0: {} fp-and-or@0.1.4: {} @@ -8876,6 +8830,8 @@ snapshots: get-east-asian-width@1.3.0: {} + get-east-asian-width@1.6.0: {} + get-func-name@2.0.2: {} get-intrinsic@1.2.2: @@ -8903,7 +8859,7 @@ snapshots: get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 math-intrinsics: 1.1.0 get-proto@1.0.1: @@ -8927,10 +8883,6 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 - getos@3.2.1: - dependencies: - async: 3.2.5 - getpass@0.1.7: dependencies: assert-plus: 1.0.0 @@ -9068,6 +9020,11 @@ snapshots: has-yarn@3.0.0: {} + hasha@5.2.2: + dependencies: + is-stream: 2.0.1 + type-fest: 0.8.1 + hasown@2.0.0: dependencies: function-bind: 1.1.2 @@ -9076,6 +9033,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + hast-to-hyperscript@10.0.3: dependencies: '@types/unist': 2.0.10 @@ -9400,6 +9361,10 @@ snapshots: dependencies: get-east-asian-width: 1.3.0 + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.6.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -9651,8 +9616,6 @@ snapshots: dependencies: package-json: 8.1.1 - lazy-ass@1.6.0: {} - leven@3.1.0: {} levn@0.4.1: @@ -9685,22 +9648,18 @@ snapshots: transitivePeerDependencies: - supports-color - listr2@3.14.0(enquirer@2.4.1): + listr2@8.3.3: dependencies: - cli-truncate: 2.1.0 + cli-truncate: 4.0.0 colorette: 2.0.20 - log-update: 4.0.0 - p-map: 4.0.0 - rfdc: 1.3.0 - rxjs: 7.8.1 - through: 2.3.8 - wrap-ansi: 7.0.0 - optionalDependencies: - enquirer: 2.4.1 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 - listr2@8.3.3: + listr2@9.0.5: dependencies: - cli-truncate: 4.0.0 + cli-truncate: 5.2.0 colorette: 2.0.20 eventemitter3: 5.0.1 log-update: 6.1.0 @@ -9749,6 +9708,8 @@ snapshots: lodash@4.17.21: {} + lodash@4.18.1: {} + log-symbols@4.1.0: dependencies: chalk: 4.1.2 @@ -9759,13 +9720,6 @@ snapshots: chalk: 5.6.2 is-unicode-supported: 1.3.0 - log-update@4.0.0: - dependencies: - ansi-escapes: 4.3.2 - cli-cursor: 3.1.0 - slice-ansi: 4.0.0 - wrap-ansi: 6.2.0 - log-update@6.1.0: dependencies: ansi-escapes: 7.0.0 @@ -10795,9 +10749,10 @@ snapshots: dependencies: side-channel: 1.0.4 - qs@6.14.0: + qs@6.15.3: dependencies: - side-channel: 1.1.0 + es-define-property: 1.0.1 + side-channel: 1.1.1 queue-microtask@1.2.3: {} @@ -10983,11 +10938,6 @@ snapshots: dependencies: lowercase-keys: 3.0.0 - restore-cursor@3.1.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - restore-cursor@4.0.0: dependencies: onetime: 5.1.2 @@ -11002,8 +10952,6 @@ snapshots: reusify@1.0.4: {} - rfdc@1.3.0: {} - rfdc@1.4.1: {} rimraf@2.7.1: @@ -11057,10 +11005,6 @@ snapshots: rw@1.3.3: {} - rxjs@7.8.1: - dependencies: - tslib: 2.8.1 - sade@1.8.1: dependencies: mri: 1.2.0 @@ -11116,8 +11060,6 @@ snapshots: semver@7.6.2: {} - semver@7.7.2: {} - semver@7.8.5: {} send@0.18.0: @@ -11232,7 +11174,7 @@ snapshots: shell-quote@1.8.1: {} - side-channel-list@1.0.0: + side-channel-list@1.0.1: dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 @@ -11258,11 +11200,11 @@ snapshots: get-intrinsic: 1.2.2 object-inspect: 1.13.1 - side-channel@1.1.0: + side-channel@1.1.1: dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 - side-channel-list: 1.0.0 + side-channel-list: 1.0.1 side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 @@ -11306,18 +11248,6 @@ snapshots: slash@3.0.0: {} - slice-ansi@3.0.0: - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - - slice-ansi@4.0.0: - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.1 @@ -11328,6 +11258,11 @@ snapshots: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 + slice-ansi@8.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + smart-buffer@4.2.0: {} socks-proxy-agent@7.0.0: @@ -11445,6 +11380,11 @@ snapshots: get-east-asian-width: 1.3.0 strip-ansi: 7.1.0 + string-width@8.2.1: + dependencies: + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + string.prototype.padend@3.1.6: dependencies: call-bind: 1.0.7 @@ -11492,6 +11432,10 @@ snapshots: dependencies: ansi-regex: 6.0.1 + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + strip-bom@3.0.0: {} strip-final-newline@2.0.0: {} @@ -11587,6 +11531,8 @@ snapshots: magic-string: 0.30.10 periscopic: 3.1.0 + systeminformation@5.31.11: {} + tapable@2.3.3: {} tar-fs@2.1.1: @@ -11638,8 +11584,6 @@ snapshots: throttleit@1.0.1: {} - through@2.3.8: {} - tiny-glob@0.2.9: dependencies: globalyzer: 0.1.0 @@ -11661,7 +11605,7 @@ snapshots: dependencies: rimraf: 3.0.2 - tmp@0.2.3: {} + tmp@0.2.7: {} to-fast-properties@2.0.0: {} @@ -11730,6 +11674,8 @@ snapshots: tsheredoc@1.0.1: {} + tslib@1.14.1: {} + tslib@2.8.1: {} tsx@4.22.4: @@ -11762,7 +11708,7 @@ snapshots: type-fest@0.20.2: {} - type-fest@0.21.3: {} + type-fest@0.8.1: {} type-fest@1.4.0: {} @@ -12209,12 +12155,6 @@ snapshots: - bufferutil - utf-8-validate - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -12299,6 +12239,10 @@ snapshots: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 + yauzl@3.4.0: + dependencies: + pend: 1.2.0 + yazl@2.5.1: dependencies: buffer-crc32: 0.2.13 From ef4dc09fab7002f4bffbe486bd31fd5fb75c5f9a Mon Sep 17 00:00:00 2001 From: James Dabbs Date: Sat, 27 Jun 2026 22:22:55 -0700 Subject: [PATCH 2/3] test(viewer): run e2e against live deployments (pages/workers/preview) Add a CYPRESS_ENV target axis that resolves both the base URL and a data mode (fixture | live). local/CI stay hermetic (intercept the bundle with main.min.json); deployed targets (pages, workers, graphs, preview) run against the site's real R2 bundle, so we verify the actual deployments and their cross-consistency. - cypress.config.ts: resolveTarget() -> { baseUrl, mode }; expose mode via Cypress.env. Workers URLs added; preview reads PREVIEW_URL (per-version). - support: setup() intercepts only in fixture mode; add fixtureOnly() to skip exact, fixture-pinned assertions on live runs. - deduction/typesetting: move fixture-specific assertions (renumbered space IDs, snapshotted KaTeX HTML) under fixtureOnly; data-stable deduction checks still run live. - bin/e2e: take targets (default pages+workers consistency check) and health-check each; package scripts cy:run:{pages,workers,preview,graphs}. - doc/testing.md: document fixture vs live and the target table. Verified: hermetic 16/16; live pages and workers each 14 passed / 2 fixture-only skipped / 0 failed (identical). --- bin/e2e | 74 +++++++++++++----- doc/testing.md | 46 +++++++++-- packages/viewer/cypress.config.ts | 76 ++++++++++++++----- packages/viewer/cypress/e2e/deduction.spec.ts | 19 +++-- .../viewer/cypress/e2e/typesetting.spec.ts | 30 ++++---- packages/viewer/cypress/support/commands.ts | 16 +++- packages/viewer/cypress/support/index.ts | 2 +- packages/viewer/package.json | 10 ++- 8 files changed, 200 insertions(+), 73 deletions(-) diff --git a/bin/e2e b/bin/e2e index 2308ac12..de93ae41 100755 --- a/bin/e2e +++ b/bin/e2e @@ -1,30 +1,62 @@ #!/bin/bash +# +# Run the viewer's end-to-end suite against one or more deployed targets. +# +# ./bin/e2e # default: cross-consistency check (pages + workers) +# ./bin/e2e pages # the live Cloudflare Pages site +# ./bin/e2e workers # the live Cloudflare Workers site +# ./bin/e2e graphs # the graphs companion Worker +# ./bin/e2e preview # a Workers preview (set PREVIEW_URL=...) +# ./bin/e2e https://... # an arbitrary URL (treated as a preview) +# +# Targets resolve their base URL + data mode (live) in cypress.config.ts; these +# runs hit each deployment's real data bundle. Use `pnpm --filter viewer cy:run` +# (CYPRESS_ENV=local) for the hermetic, fixture-backed suite. -function run() { - url=$(getUrl "$1") - echo "$url" +set -euo pipefail - # wait for up to 5 minutes for the site to be available - for i in {1..30}; do - status=$(curl --write-out %{http_code} --silent --output /dev/null https://$url) - if [ "$status" -eq 200 ]; then - break - fi - sleep 10 - done +targets=("$@") +if [ ${#targets[@]} -eq 0 ]; then + targets=(pages workers) +fi - pnpm --filter viewer run cy:run --config baseUrl=https://$url +# Mirror cypress.config.ts so we can health-check a target before running. +function baseUrl() { + case "$1" in + pages | production) echo "https://topology.pi-base.org" ;; + workers) echo "https://pi-base-topology.fragrant-boat-7068.workers.dev" ;; + graphs) echo "https://pi-base-graphs.fragrant-boat-7068.workers.dev" ;; + preview) echo "${PREVIEW_URL:-}" ;; + *) echo "" ;; + esac } -function getUrl() { - if [ "$1" == "production" ]; then - echo "topology.pi-base.org" - elif [ -n "$1" ]; then - echo "$1.topology.pages.dev" - else - sha=$(git rev-parse --abbrev-ref HEAD | sed 's/\//-/g') - echo "$sha.topology.pages.dev" +# Wait up to 5 minutes for a URL to return 200 (preview/deploys may be warming). +function waitFor() { + local url="$1" + [ -z "$url" ] && return 0 + for _ in {1..30}; do + if [ "$(curl --silent --output /dev/null --write-out '%{http_code}' "$url/")" = "200" ]; then + return 0 fi + sleep 10 + done + echo "warning: $url did not return 200 within 5m; running anyway" >&2 } -run "$@" +status=0 +for target in "${targets[@]}"; do + # A bare URL is run as a preview against that URL. + if [[ "$target" == http* ]]; then + export PREVIEW_URL="$target" + target=preview + fi + + url=$(baseUrl "$target") + echo "▶ e2e against '$target'${url:+ ($url)}" + waitFor "$url" + + CYPRESS_ENV="$target" pnpm --filter viewer run cy:run || status=1 +done + +exit $status diff --git a/doc/testing.md b/doc/testing.md index 4954d86a..71158d6f 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -59,18 +59,48 @@ for more details. /packages/viewer $ pnpm run cy:run --config baseUrl= ``` +## Fixture vs. live data + +`CYPRESS_ENV` selects which deployment to test _and_ the data the suite runs +against: + +- **`fixture`** (default, used by `local`/CI) intercepts the data bundle with + `cypress/fixtures/main.min.json`, so content assertions are deterministic. +- **`live`** (all deployed targets) lets the app fetch its real R2 bundle, so we + exercise the actual deployment end-to-end and confirm the sites stay + consistent. + +| `CYPRESS_ENV` | URL | Mode | +| -------------------- | ------------------------------------ | ------- | +| `local` (default) | `http://localhost:5173` | fixture | +| `pages` | `https://topology.pi-base.org` | live | +| `workers` | `pi-base-topology.…workers.dev` | live | +| `graphs` | `pi-base-graphs.…workers.dev` | live | +| `preview` | `$PREVIEW_URL` | live | + +A handful of specs assert exact, fixture-pinned output (e.g. snapshotted KaTeX +HTML); these are wrapped in `fixtureOnly(...)` and skip automatically on live +runs. Set `CYPRESS_MODE=fixture` to force the deterministic fixture against a +deployed URL while debugging. + ## Remote End-to-End Testing -There is a `./bin/e2e` script to facilitate running the end-to-end test suite -against a few common external URLs: +The `./bin/e2e` script runs the suite against the deployed targets (live data), +health-checking each first: ```bash -# Run tests against the deployed production URL - $ ./bin/e2e production +# Cross-consistency check across the live sites (default: pages + workers) + $ ./bin/e2e -# Run tests against a Cloudflare Pages preview URL for a named branch - $ ./bin/e2e +# A single live target + $ ./bin/e2e pages + $ ./bin/e2e workers + $ ./bin/e2e graphs -# Run tests against a Cloudflare Pages preview URL for the current branch - $ ./bin/e2e +# A Workers preview ("wrangler versions upload" prints a per-version URL) + $ PREVIEW_URL=https://-pi-base-topology..workers.dev ./bin/e2e preview + $ ./bin/e2e https://-pi-base-topology..workers.dev ``` + +Equivalently, per-target package scripts: `pnpm --filter viewer run +cy:run:pages` (or `:workers` / `:preview` / `:graphs`). diff --git a/packages/viewer/cypress.config.ts b/packages/viewer/cypress.config.ts index ddd03726..378def5d 100644 --- a/packages/viewer/cypress.config.ts +++ b/packages/viewer/cypress.config.ts @@ -1,34 +1,72 @@ import { defineConfig } from 'cypress' -import { execSync } from 'child_process' -function getCurrentBranch() { - try { - return execSync('git rev-parse --abbrev-ref HEAD').toString().trim() - } catch (error) { - throw new Error(`Could not determine current git branch: ${error}`) - } -} +// The account's workers.dev subdomain for the viewer Workers (see +// doc/deployment.md). Used to address the deployed Workers directly. +const WORKERS_SUBDOMAIN = 'fragrant-boat-7068.workers.dev' + +type Mode = 'fixture' | 'live' +type Target = { baseUrl: string; mode: Mode } -function baseUrl({ CYPRESS_ENV = 'local' } = process.env) { - switch (CYPRESS_ENV) { +// `CYPRESS_ENV` selects which deployment to test and, with it, the data source: +// +// fixture — intercept the data bundle with cypress/fixtures/main.min.json for +// deterministic, hermetic runs (local dev + CI). +// live — hit the deployment's real R2 bundle end-to-end, to confirm the +// actual sites render real data and stay consistent across Pages / +// Workers / previews. +// +// `CYPRESS_MODE` can override the data source for a target (e.g. run a deployed +// URL against the fixture while debugging). +function targetFor(name: string): Target { + switch (name) { case 'local': - return 'http://localhost:5173' - case 'production': - return 'https://topology.pi-base.org' - case 'preview': - const branch = process.env.BRANCH || getCurrentBranch() - const domain = branch.toLowerCase().replaceAll('/', '-').slice(0, 28) - return `https://${domain}.topology.pages.dev` + return { baseUrl: 'http://localhost:5173', mode: 'fixture' } + case 'pages': + case 'production': // back-compat alias for the legacy Pages site + return { baseUrl: 'https://topology.pi-base.org', mode: 'live' } + case 'workers': + return { + baseUrl: `https://pi-base-topology.${WORKERS_SUBDOMAIN}`, + mode: 'live', + } + case 'graphs': + return { + baseUrl: `https://pi-base-graphs.${WORKERS_SUBDOMAIN}`, + mode: 'live', + } + case 'preview': { + // Workers preview URLs (`wrangler versions upload`) are per-version, not + // per-branch, so they can't be derived — pass the printed URL explicitly. + const url = process.env.PREVIEW_URL + if (!url) { + throw new Error( + 'CYPRESS_ENV=preview requires PREVIEW_URL — the per-version URL from ' + + "`wrangler versions upload` (or the PR's Workers Builds preview).", + ) + } + return { baseUrl: url, mode: 'live' } + } default: - throw new Error(`Invalid environment: ${CYPRESS_ENV}`) + throw new Error(`Invalid CYPRESS_ENV: ${name}`) } } +function resolveTarget( + { CYPRESS_ENV = 'local', CYPRESS_MODE } = process.env, +): Target { + const target = targetFor(CYPRESS_ENV) + return { ...target, mode: (CYPRESS_MODE as Mode) || target.mode } +} + +const target = resolveTarget() + export default defineConfig({ projectId: 'bkb3p8', chromeWebSecurity: false, + // Exposed to specs as `Cypress.env('mode')`; drives fixture vs. live data. + env: { mode: target.mode }, e2e: { - baseUrl: baseUrl(), + baseUrl: target.baseUrl, experimentalRunAllSpecs: true, specPattern: 'cypress/e2e/**/*.{ts,tsx}', supportFile: false, diff --git a/packages/viewer/cypress/e2e/deduction.spec.ts b/packages/viewer/cypress/e2e/deduction.spec.ts index bc31ce7c..7ce5394c 100644 --- a/packages/viewer/cypress/e2e/deduction.spec.ts +++ b/packages/viewer/cypress/e2e/deduction.spec.ts @@ -1,4 +1,4 @@ -import { setup } from '../support' +import { deduce, fixtureOnly, setup } from '../support' beforeEach(setup) @@ -8,13 +8,20 @@ it('finds proofs for the first space', () => { cy.contains('Functionally Hausdorff') }) -it('shows derived proofs', () => { - cy.visit('/spaces/S000004/properties/P000031') +// Pins a specific space ID → name and its auto-deduced proof. The minimal +// fixture renumbers spaces, so this ID→content mapping only holds under fixture +// data (live data has a different space at S000004). +fixtureOnly('derived proofs', () => { + it('shows derived proofs', () => { + cy.visit('/spaces/S000004/properties/P000031') + // Wait for the client-side prover before asserting derived content. + deduce() - cy.contains('Indiscrete Topology on a Two-Point Set') - cy.contains('Metacompact') + cy.contains('Indiscrete Topology on a Two-Point Set') + cy.contains('Metacompact') - cy.contains('Automatically deduced from the following', { timeout: 20000 }) + cy.contains('Automatically deduced from the following', { timeout: 20000 }) + }) }) it('derives proofs of converses', () => { diff --git a/packages/viewer/cypress/e2e/typesetting.spec.ts b/packages/viewer/cypress/e2e/typesetting.spec.ts index 8904e804..0f7b62c4 100644 --- a/packages/viewer/cypress/e2e/typesetting.spec.ts +++ b/packages/viewer/cypress/e2e/typesetting.spec.ts @@ -1,19 +1,23 @@ -import { deduce, setup } from '../support' +import { deduce, fixtureOnly, setup } from '../support' beforeEach(setup) -it('renders internal links', () => { - cy.visit('dev/preview') - deduce() +// Asserts exact KaTeX HTML against the dev typesetting tool — fixture-only, as +// the snapshot is brittle against live data / KaTeX version drift. +fixtureOnly('typesetting', () => { + it('renders internal links', () => { + cy.visit('dev/preview') + deduce() - cy.get('[data-testid=input]').type( - // {{} is Cypress escaping for {. See https://docs.cypress.io/api/commands/type#Arguments - `{{}S000001} is {{}P000001} as noted in {{}S000001|P000001}`, - ) + cy.get('[data-testid=input]').type( + // {{} is Cypress escaping for {. See https://docs.cypress.io/api/commands/type#Arguments + `{{}S000001} is {{}P000001} as noted in {{}S000001|P000001}`, + ) - cy.get('[data-testid=output]').contains( - // The T0T_0T0 rendering here is the text representation of the inner html of katex rendered math. - // We're effectively asserting that it _isn't_ still rendered as $T_0$ - 'Discrete topology on a two-point set is T0T_0T0​ as noted in Discrete topology on a two-point set is T0T_0T0​', - ) + cy.get('[data-testid=output]').contains( + // The T0T_0T0 rendering here is the text representation of the inner html of katex rendered math. + // We're effectively asserting that it _isn't_ still rendered as $T_0$ + 'Discrete topology on a two-point set is T0T_0T0​ as noted in Discrete topology on a two-point set is T0T_0T0​', + ) + }) }) diff --git a/packages/viewer/cypress/support/commands.ts b/packages/viewer/cypress/support/commands.ts index 4bc21ce6..3c7578c9 100644 --- a/packages/viewer/cypress/support/commands.ts +++ b/packages/viewer/cypress/support/commands.ts @@ -1,9 +1,23 @@ +// Whether the current run uses the deterministic fixture or the deployment's +// real data bundle (see cypress.config.ts / CYPRESS_ENV). +const live = Cypress.env('mode') === 'live' + export function setup() { cy.clearAllLocalStorage() - cy.intercept({ path: /main.json/ }, { fixture: 'main.min.json' }) + // In fixture mode, serve deterministic data so content assertions are stable. + // In live mode, let the app fetch its real bundle so we exercise the actual + // deployment end-to-end (and verify cross-site consistency). + if (!live) { + cy.intercept({ path: /main.json/ }, { fixture: 'main.min.json' }) + } } export function deduce() { cy.get('.progress').should('exist') cy.get('.progress', { timeout: 10000 }).should('not.exist') } + +// Wrap specs/blocks that assert exact, fixture-pinned output (e.g. snapshotted +// KaTeX HTML). They only make sense against deterministic data, so skip them on +// live deployments where the real bundle would make them brittle. +export const fixtureOnly = live ? describe.skip : describe diff --git a/packages/viewer/cypress/support/index.ts b/packages/viewer/cypress/support/index.ts index 50d2489b..75c7dafb 100644 --- a/packages/viewer/cypress/support/index.ts +++ b/packages/viewer/cypress/support/index.ts @@ -1 +1 @@ -export { deduce, setup } from './commands' +export { deduce, fixtureOnly, setup } from './commands' diff --git a/packages/viewer/package.json b/packages/viewer/package.json index 0cd90af6..e7b6eeba 100644 --- a/packages/viewer/package.json +++ b/packages/viewer/package.json @@ -11,11 +11,13 @@ "cf:preview:topology": "wrangler versions upload --env topology", "cf:preview:graphs": "wrangler versions upload --env graphs", "cy:open": "cypress open", - "cy:open:prev": "CYPRESS_ENV=preview cypress open", - "cy:open:prod": "CYPRESS_ENV=production cypress open", + "cy:open:pages": "CYPRESS_ENV=pages cypress open", + "cy:open:workers": "CYPRESS_ENV=workers cypress open", "cy:run": "cypress run", - "cy:run:prev": "CYPRESS_ENV=preview cypress run $@", - "cy:run:prod": "CYPRESS_ENV=production cypress run $@", + "cy:run:pages": "CYPRESS_ENV=pages cypress run", + "cy:run:workers": "CYPRESS_ENV=workers cypress run", + "cy:run:preview": "CYPRESS_ENV=preview cypress run", + "cy:run:graphs": "CYPRESS_ENV=graphs cypress run", "dev": "vite", "preview": "vite preview", "test": "vitest run", From e1e8fb9e4b36e81e717b0d1b5c9f777adc72ba72 Mon Sep 17 00:00:00 2001 From: James Dabbs Date: Sat, 27 Jun 2026 22:50:51 -0700 Subject: [PATCH 3/3] test(viewer): refresh fixture so deduction/typesetting run live too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These two specs were fixtureOnly because the curated fixture's space names had drifted from live (live now embeds LaTeX, e.g. S000001 = "Discrete topology on $\{0,1\}$"). Refresh the two tested spaces' display name/aliases (S000001, S000004) to current live values and rewrite the assertions to hold in both modes: a math-free name prefix for deduction, and a behavioral check (refs resolve; embedded math is typeset via KaTeX) instead of an exact HTML snapshot for typesetting. Drop the now-unused fixtureOnly helper. NB: the fixture predates a pi-base property-ID reorganization, so its property uids are NOT interchangeable with the live bundle's — only per-entity display fields were refreshed (a bulk by-uid remap would corrupt the trait/theorem corpus). Verified: hermetic 16/16; live pages and workers each 16/16 (identical) — the full suite now runs against the live deployments. --- doc/testing.md | 14 +++++--- packages/viewer/cypress/e2e/deduction.spec.ts | 23 ++++++------ .../viewer/cypress/e2e/typesetting.spec.ts | 35 ++++++++++--------- .../viewer/cypress/fixtures/main.min.json | 8 ++--- packages/viewer/cypress/support/commands.ts | 5 --- packages/viewer/cypress/support/index.ts | 2 +- 6 files changed, 43 insertions(+), 44 deletions(-) diff --git a/doc/testing.md b/doc/testing.md index 71158d6f..e939ec7f 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -78,10 +78,16 @@ against: | `graphs` | `pi-base-graphs.…workers.dev` | live | | `preview` | `$PREVIEW_URL` | live | -A handful of specs assert exact, fixture-pinned output (e.g. snapshotted KaTeX -HTML); these are wrapped in `fixtureOnly(...)` and skip automatically on live -runs. Set `CYPRESS_MODE=fixture` to force the deterministic fixture against a -deployed URL while debugging. +The whole suite runs in both modes; assertions are written to hold against the +real data (stable IDs, math-free name prefixes, behavioral checks) rather than +exact HTML snapshots. Set `CYPRESS_MODE=fixture` to force the deterministic +fixture against a deployed URL while debugging. + +The fixture (`cypress/fixtures/main.min.json`) is a hand-curated subset; keep its +tested entities (e.g. `S000001`, `S000004`, `P000001`) in sync with live data. +Note it predates a pi-base property-ID reorganization, so its property `uid`s are +**not** interchangeable with the current bundle's — refresh display fields per +entity, don't bulk-remap by `uid`. ## Remote End-to-End Testing diff --git a/packages/viewer/cypress/e2e/deduction.spec.ts b/packages/viewer/cypress/e2e/deduction.spec.ts index 7ce5394c..88a70955 100644 --- a/packages/viewer/cypress/e2e/deduction.spec.ts +++ b/packages/viewer/cypress/e2e/deduction.spec.ts @@ -1,4 +1,4 @@ -import { deduce, fixtureOnly, setup } from '../support' +import { deduce, setup } from '../support' beforeEach(setup) @@ -8,20 +8,17 @@ it('finds proofs for the first space', () => { cy.contains('Functionally Hausdorff') }) -// Pins a specific space ID → name and its auto-deduced proof. The minimal -// fixture renumbers spaces, so this ID→content mapping only holds under fixture -// data (live data has a different space at S000004). -fixtureOnly('derived proofs', () => { - it('shows derived proofs', () => { - cy.visit('/spaces/S000004/properties/P000031') - // Wait for the client-side prover before asserting derived content. - deduce() +it('shows derived proofs', () => { + cy.visit('/spaces/S000004/properties/P000031') + // Wait for the client-side prover before asserting derived content. + deduce() - cy.contains('Indiscrete Topology on a Two-Point Set') - cy.contains('Metacompact') + // Math-free prefix of the space name (the name embeds KaTeX), so this holds + // against both the fixture and live data. + cy.contains('Indiscrete topology on') + cy.contains('Metacompact') - cy.contains('Automatically deduced from the following', { timeout: 20000 }) - }) + cy.contains('Automatically deduced from the following', { timeout: 20000 }) }) it('derives proofs of converses', () => { diff --git a/packages/viewer/cypress/e2e/typesetting.spec.ts b/packages/viewer/cypress/e2e/typesetting.spec.ts index 0f7b62c4..86b664b9 100644 --- a/packages/viewer/cypress/e2e/typesetting.spec.ts +++ b/packages/viewer/cypress/e2e/typesetting.spec.ts @@ -1,23 +1,24 @@ -import { deduce, fixtureOnly, setup } from '../support' +import { deduce, setup } from '../support' beforeEach(setup) -// Asserts exact KaTeX HTML against the dev typesetting tool — fixture-only, as -// the snapshot is brittle against live data / KaTeX version drift. -fixtureOnly('typesetting', () => { - it('renders internal links', () => { - cy.visit('dev/preview') - deduce() +it('renders internal links', () => { + cy.visit('dev/preview') + deduce() - cy.get('[data-testid=input]').type( - // {{} is Cypress escaping for {. See https://docs.cypress.io/api/commands/type#Arguments - `{{}S000001} is {{}P000001} as noted in {{}S000001|P000001}`, - ) + cy.get('[data-testid=input]').type( + // {{} is Cypress escaping for {. See https://docs.cypress.io/api/commands/type#Arguments + `{{}S000001} is {{}P000001} as noted in {{}S000001|P000001}`, + ) - cy.get('[data-testid=output]').contains( - // The T0T_0T0 rendering here is the text representation of the inner html of katex rendered math. - // We're effectively asserting that it _isn't_ still rendered as $T_0$ - 'Discrete topology on a two-point set is T0T_0T0​ as noted in Discrete topology on a two-point set is T0T_0T0​', - ) - }) + // The references should resolve to names and any embedded math should be + // typeset by KaTeX — not left as literal `{...}` or `$...$`. We assert the + // behavior rather than an exact HTML snapshot, so it holds against live data + // (whose names embed math) and across KaTeX versions. + cy.get('[data-testid=output]') + .should('not.contain', '{S000001}') + .and('not.contain', '$T_0$') + .and('contain', 'Discrete topology on') + .and('contain', 'as noted in') + cy.get('[data-testid=output] .katex').should('exist') }) diff --git a/packages/viewer/cypress/fixtures/main.min.json b/packages/viewer/cypress/fixtures/main.min.json index 137ecfb6..9c0c3bb8 100644 --- a/packages/viewer/cypress/fixtures/main.min.json +++ b/packages/viewer/cypress/fixtures/main.min.json @@ -944,17 +944,17 @@ { "uid": "S000001", "counterexamples_id": 1, - "name": "Discrete topology on a two-point set", + "name": "Discrete topology on $\\{0,1\\}$", "description": "-", - "aliases": ["Finite Discrete Topology"], + "aliases": ["Discrete topology on a two-point set", "Finite discrete topology"], "refs": [] }, { "uid": "S000004", "counterexamples_id": 4, - "name": "Indiscrete Topology on a Two-Point Set", + "name": "Indiscrete topology on $\\{0,1\\}$", "description": "-", - "aliases": ["Indiscrete Topology on a Two-Point Set"], + "aliases": ["Indiscrete topology on a two-point set"], "refs": [] }, { diff --git a/packages/viewer/cypress/support/commands.ts b/packages/viewer/cypress/support/commands.ts index 3c7578c9..de6ba869 100644 --- a/packages/viewer/cypress/support/commands.ts +++ b/packages/viewer/cypress/support/commands.ts @@ -16,8 +16,3 @@ export function deduce() { cy.get('.progress').should('exist') cy.get('.progress', { timeout: 10000 }).should('not.exist') } - -// Wrap specs/blocks that assert exact, fixture-pinned output (e.g. snapshotted -// KaTeX HTML). They only make sense against deterministic data, so skip them on -// live deployments where the real bundle would make them brittle. -export const fixtureOnly = live ? describe.skip : describe diff --git a/packages/viewer/cypress/support/index.ts b/packages/viewer/cypress/support/index.ts index 75c7dafb..50d2489b 100644 --- a/packages/viewer/cypress/support/index.ts +++ b/packages/viewer/cypress/support/index.ts @@ -1 +1 @@ -export { deduce, fixtureOnly, setup } from './commands' +export { deduce, setup } from './commands'