chore: merge develop -> v13 6/8/23 (#26976)

* docs: revise contributor advice for node.js setup (#26652)

* feat: initial release of cypress/vite-plugin-cypress-esm (#26663)

* chore: release @cypress/vite-plugin-cypress-esm-v1.0.0

[skip ci]

* chore: upgrade Lerna to v5 and use Nx (#26660)

* dependency(deps): update dependency engine.io to v6.4.2 [security] (#26664)

* dependency(deps): update dependency engine.io to v6.4.2 [security]

* updating changelog

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Matt Schile <mschile@cypress.io>

* fix: updated CYPRESS_DOWNLOAD_PATH_TEMPLATE regex to allow multiple replacements (#25531)

* feat: Component Testing banner (#26625)

Co-authored-by: elevatebart <bart@cypress.io>

* chore: Update v8 snapshot cache (#26647)

Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com>
Co-authored-by: Ryan Manuel <ryanm@cypress.io>

* chore: 12.12.0 release updates (#26697)

* chore: cypress[26674] updated github workflows to use checklout@v3 and stop using set-output and move to  file use (#26696)

* fix: move types condition to the front (#26630)

* fix: move `types` condition to the front

* chore: update changelog

* optimize deps for vite

* update config

* try optimizeDeps.include

* missing dep

---------

Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>

* fix: revert #26452 (Yarn Plug n Play compat regression) (#26735)

* Revert "fix: correctly resolve dependencies for CT onboarding when using Yarn Plug n Play (#26452)"

This reverts commit 7a33f5c1a8.

* changelog

* changelog

* chore: fixing PR link in releaseData.json (#26734)

* chore: update stalebot config (#26745)

* misc: ACI empty state slideshows (#26692)

Co-authored-by: Stokes Player <stokes@cypress.io>

* fix: do not cache module resolution during launchpad dependency detection (#26726)

Co-authored-by: Mike Plummer <mikep@cypress.io>

* fix: Vite esm plugin issues (#26714)

* chore: Update v8 snapshot cache (#26707)

Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com>
Co-authored-by: Ryan Manuel <ryanm@cypress.io>

* chore: adding in repo token to explicitly use that while running commands [skip ci] (#26746)

* chore(dependency): update dependency @percy/cypress to ^3.1.2 🌟 (#26717)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>

* chore: Remove console.log (#26756)

* chore: put types condition first in the syncing script (#26743)

Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>

* test: create lists files after folders when in same directory in specs list (#26723)

Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>

* chore: update vm2 to 3.9.19 (#26772)

* chore: add telemetry to the proxy (#26695)

* chore: set up instrumentation and instrument middleware

* chore: set up console exporter

* chore: add parent span option to telemetry package

* chore: set up telemetry verbose mode

* chore: instrument the network proxy - part 1

* chore: make sure to terminate spans when request is aborted

* fix telemetry, create/end the request middle prior to sending the outbound request

* avoid telemetry ts build step, create entrypoint into packages/telemetry using TS conventions

* allow env vars to be "true" or "1"

* when creating child span, inherit their attributes directly from the parent

* create custom honeycomb exporter and span processor to log traces

* remove duplicate code that's already called in this.setRootContext

* cleanup

* more clean up

* update honeycomb network:proxy attributes, update console.log message

* yarn lock

* chore: remove performance API in middleware

* chore: end response on correct event

* recursively gather parent attributes on close

* added key and some clean up

* github action detector, move verbose into index, verbose log commands

* some tests

* clean up honeycomb exporter

* some renaming

* testing console trace link exporter

* Don't lose the top span when running in verbose.

* link to the right place for prod/dev

* changes to verbose to make sure it is read in the browser

* Apply suggestions from code review

* pass parent attributes between telemetry instances

* default to false

* 'fix' build issues

* src not dist

* add back on start span

* once more with feeling

* Fix some tests

* try this i guess

* revert auto build

* Apply suggestions from code review

Co-authored-by: Bill Glesias <bglesias@gmail.com>

* support failed commands

* Address PR comments

* Address PR Comments

* error handling

* handle all the errors

---------

Co-authored-by: Bill Glesias <bglesias@gmail.com>
Co-authored-by: Brian Mann <brian.mann86@gmail.com>

* chore: update triage workflow to add comment to contributor prs (#26493)

Co-authored-by: Ben M <benm@cypress.io>

* chore: telemetry pr cleanup (#26776)

* fix: fix UI flash when switching to debug page (#26761)

* chore: add Nx Cloud (#26712)

* chore: add empty nx.json [run ci]

* chore: add nx cloud runner [run ci]

* chore: add nx-cloud dep [run ci]

* chore: update local nx cloud accessToken to be read-only

* feat: update git related messages for runs and debug (#26758)

* feat(app): update DebugError copy

* feat: set isUsingGit project flag and consume in DebugContainer

* feat(app): update not using git icon for DebugError

* feat(app): displays alert on runs page when not using git

* feat(app): add component for when no runs for current branch

* feat(app): add warning for no runs for branch on runs container

* chore: add feat to CHANGELOG

* chore: remove logged status value

* chore: resolve import from merge conflict

* test(app): stub branch name for e2e runs spec

* chore: add line break in changelog entry

* chore: cleanup PR

* chore: fix i18n import for DebugBranchError

* chore: add utm and update Warning links to inline

* chore: capitalize Git in i18n

* ref: warning liink

* test: add i18n to tests

* test(app): change utm_source assertions

* chore: cleanup pr

* chore: remove unused prop

* test(app): remove no git warning when moving to runs page in e2e

* chore: change template logic

* chore: remove duplicate RUNS_TAB_MEDIUM const

* Changed Debug test assertion and reordered new components for Debug

---------

Co-authored-by: Stokes Player <stokes.player@gmail.com>

* chore: rename video processing events to capture/compress (#26800)

* chore: change processing nomenclature to compressing when printing the run.

* chore: rename 'capturing of' to 'capturing'

* chore: rename upload results to upload screenshots & videos (#26811)

* chore: rename upload results to upload screenshots & videos

* run ci

* chore: capture versions of relevant dependencies with `x-dependencies` header (#26814)

* chore: update changlelog script to handle revert pr ref (#26801)

* fix: Correct typescript scaffold dependency (#26815)

* fix: correct typescript scaffold dependency (#26204)

* add changelog

* Update change log for PR comment

Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com>

---------

Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com>
Co-authored-by: Mark Noonan <mark@cypress.io>

* chore: 12.13.0 prep (#26833)

* chore: 12.13.0 release (#26834)

* chore: 12.13.0 changelog fix

* remove pending, bump version

* fix typo

* chore: release @cypress/vite-plugin-cypress-esm-v1.0.1

[skip ci]

* chore: Implement runSpec mutation (#26782)

* chore: replace gitter badge with discord on readme (#26771)

* chore: add GraphQL mutation for sending system notifications via Electron (#26773)

* fix: upgrade typescript from 4.7.4 to 4.9.5 (#26826)

Snyk has created this PR to upgrade typescript from 4.7.4 to 4.9.5.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/cypress-opensource/project/d5b36925-e6ee-455d-9649-6560a9aca413?utm_source=github&utm_medium=referral&page=upgrade-pr

* test: fix 2 broken tests for Windows (#26854)

* Update stale_issues_and_pr_cleanup.yml

Upped the number of operations per run.  Have been manually doing that so this job can get through all the issues in the repo with no problems.

* chore(dep): [Snyk] Upgrade vite from 2.9.13 to 2.9.15 (#26830)

Co-authored-by: Ben M <benm@cypress.io>

* Update triage_add_to_project.yml

* chore: fix minor background color styling in debug results component (#26887)

* Update stale_issues_and_pr_cleanup.yml

stalebot was incorrectly configured to run in debug mode.  I have updated the default to run in normal mode when running scheduled

* chore: Deprecate @cypress/xpath package (#26893)

* chore: add telemetry realworld app (#26896)

* chore: capture telemetry for realworld app maybe

* idk what i was doing

* setup record key and telemetry

* testing

* override project id

* some times we just need a little context.

* Adding tests

* Adding comment

* chore(deps): update dependency find-process to v1.4.7 🌟 (#26906)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>

* chore(deps): update dependency firefox-profile to v4.3.2 🌟 (#26912)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>

* chore: add browser state action for debug (#26884)

* chore: add browser state action for debug (#26763)

* Address PR comments
- remove unneeded async and test context
- genericize openProject function

* Revert route change, update spec description

* chore: replace gift devDep with simple-git (#26728)

* chore: replace arg devDep with minimist; remove unused shx devDep (#26727)

* chore: enable caching for lint task (#26791)

* chore: remove old performance reporting (#26920)

* chore: remove old performance reporting

* remove libhoney dep

* try this

* build and build snapshots if deps are out of date

* foiled by a comma

* freaking comma

* no snapshots maybe ugh

* ignore engines instead

* don't need this

* remove rename support file step

* chore: update Snyk to scan all projects (#26867)

* SEC-544 chore: [Snyk] Update Snyk flag in Git actn

* Update snyk_sca_scan.yaml

Removed --debug switch from the test command

---------

Co-authored-by: brady-cypressio <90723145+brady-cypressio@users.noreply.github.com>

* chore: skip problematic component tests that fail on contributor PRs (#26924)

* chore: omit unused circle variables that cause contributor PR issues (#26935)

* chore: make git message warnings remain dismissable (#26812)

* feat: make git message warnings remain dismissable

* chore: update CHANGELOG

* chore: update CHANGELOG

* chore: remove unneeded code

* chore: update BannerId types

* chore: fix queryies

* chore: clean up PR

* chore: move TrackedWarning to frontend-shared

* chore: update import

* ref: move TrackedWarning to TrackedBanner

* chore: udpate CHANGELOG

* fix: update TrackedBanner to parse markdown message

* chore: set TrackedBanner default message prop

* chore: update RunsContainer

* chore: add missing tests and update alert type

---------

Co-authored-by: Stokes Player <stokes@cypress.io>

* chore: replace fast-glob with globby; remove unneeded getenv dep (#26730)

* fix: update angular dep min versions (#26908)

* fix: update angular dep min versions

* chore: update CHANGELOG

* chore: add line break to changelog

* chore: update changelog pending release date

* chore: remove whitespace

* fix: upgrade typescript from 4.2.3 to 4.9.5 (#26858)

Snyk has created this PR to upgrade typescript from 4.2.3 to 4.9.5.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/cypress-opensource/project/5fdaebf8-b115-41d1-a2d9-857261769179?utm_source=github&utm_medium=referral&page=upgrade-pr

Co-authored-by: Bill Glesias <bglesias@gmail.com>

* chore: Update v8 snapshot cache (#26762)

Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com>
Co-authored-by: Ryan Manuel <ryanm@cypress.io>

* feat: Implement testing type switch promos (#26894)

* feat: Implement testing type switch promos

* Add tests, changelog entry

* Add tests

* Fix button styling

* Styling fixes, add framework links

* Add missing testId

* run ci

* Fix spec

* chore: updating v8 snapshot cache

* chore: updating v8 snapshot cache

* chore: updating v8 snapshot cache

* Fix styling issues

* Resolve code review findings

* Fix issue with yarn.lock
* Fix extra padding at bottom of promo
* Add tests for utm params
* Add test for switching testing type when both configured
* Fix changelog version

* Address review comments

* Widen promo when no image defined
* Prevent flash of promo before query resolves
* Reduce top margin

* reduce size of text box to match latest figma

* update button style to match figma

* increase width at which we collapse sidenav

* add short versions of the headings

* remove skeletons from header

* avoid extra height

* adjustments for column alignment

* fix flaky test

* update tests for responsive text changes

* update changelog

* restore spacing between header items

* avoid occasional flash of promo on page load

* update text handling

* fix types and tests

* Update packages/app/src/specs/SpecsList.vue

Co-authored-by: Stokes Player <stokes@cypress.io>

* updated final e2e bullet

* fix question mark icon flashing

* text formatting

* remove superfluous snapshot [skip ci]

---------

Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com>
Co-authored-by: marktnoonan <mark@cypress.io>
Co-authored-by: astone123 <adams@cypress.io>
Co-authored-by: Stokes Player <stokes@cypress.io>
Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>

* chore: release internal-scripts-v1.0.0

[skip ci]

* chore: fix changelog links (#26948)

* chore: 12.14.0 release (#26950)

* chore: Update Chrome (stable) to 114.0.5735.106 and Chrome (beta) to 115.0.5790.13 (#26650)

* chore: bump cache version (#26952)

Co-authored-by: Ryan Manuel <ryanm@cypress.io>

* chore: move release date (#26958)

* chore(deps): update dependency @antfu/utils to ^0.7.0 [security] (#26923)

* chore: fix base error styling (#26954)

* chore: remove low value percy snapshots (#26934)

* chore: remove low value percy snapshots

* chore: remove more low value percy snapshots [run ci]

* chore: remove more low value percy snapshots

* remove additional snapshots

* reduce snapshots

* fix types

---------

Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>

* chore: changelog updates (#26964)

* chore: stabilize side navigation bar during loading and switching testing types (#26953)

* fix: log video path if exists, regardless of compression (#26813)

* chore: print the video path whether or not compression is on or fails

* chore: fix video replacement regex

* chore: add bugfix entry

* feat: allow users to pass true to videoCompression config and only a… (#26810)

* chore: allow users to pass true to videoCompression config and only allow valudes 1-51 inclusively to be passed in

* run ci

* chore: allow zero to be option for CRF as we will coerve it to false and skip compression to have a lossless video, which has the same effect

* Update cli/CHANGELOG.md

* chore: update videoCompression types

* chore: update changelog

* Update cli/CHANGELOG.md

* Update cli/types/cypress.d.ts

Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com>

* Update packages/config/src/validation.ts

Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com>

* chore: update config snapshots

* Update packages/config/test/validation.spec.ts

Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com>

* chore: add system test on videoCompression=true coersion

* chore: document 0 as being false and not a valid CRF option for cypress video compression and make CRF valid values 1-51

* chore: fix types

* chore: fix types

* chore: fix change to log as feature and not bugfix

* chore: fix server side unit tests

---------

Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com>

* chore: trigger mac/linux/windows binary builds and v8 snapshot cache update tests

* chore: updating v8 snapshot cache

* chore: updating v8 snapshot cache

* chore: updating v8 snapshot cache

* chore: fix possible bad merge from mismatched snapshot in CLOUD_AUTO_CANCEL_MISMATCH test

* chore: fix possible bad merge from mismatched snapshot in record_spec system test

* chore: updating v8 snapshot cache

* chore: updating v8 snapshot cache

* chore: updating v8 snapshot cache

---------

Co-authored-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com>
Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Adam Stone-Lord <adams@cypress.io>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Matt Schile <mschile@cypress.io>
Co-authored-by: Mahdi Khashan <58775404+mahdikhashan@users.noreply.github.com>
Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com>
Co-authored-by: elevatebart <bart@cypress.io>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: cypress-bot[bot] <+cypress-bot[bot]@users.noreply.github.com>
Co-authored-by: Ryan Manuel <ryanm@cypress.io>
Co-authored-by: Ben M <benm@cypress.io>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Stokes Player <stokes@cypress.io>
Co-authored-by: Mike Plummer <mikep@cypress.io>
Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>
Co-authored-by: Luis Furtado <46112985+luis-furtado@users.noreply.github.com>
Co-authored-by: Matt Henkes <mjhenkes@gmail.com>
Co-authored-by: Brian Mann <brian.mann86@gmail.com>
Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com>
Co-authored-by: Jordan <jordan@jpdesigning.com>
Co-authored-by: Stokes Player <stokes.player@gmail.com>
Co-authored-by: Dave Kasper <dave.m.kasper@gmail.com>
Co-authored-by: Mark Noonan <mark@cypress.io>
Co-authored-by: Ely Lucas <ely@meta-tek.net>
Co-authored-by: Snyk bot <snyk-bot@snyk.io>
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
Co-authored-by: cypresschris <96069059+cypresschris@users.noreply.github.com>
Co-authored-by: brady-cypressio <90723145+brady-cypressio@users.noreply.github.com>
This commit is contained in:
Bill Glesias
2023-06-12 09:54:26 -04:00
committed by GitHub
parent 9a9ecacfeb
commit 458db1cd02
465 changed files with 11262 additions and 23716 deletions

View File

@@ -1,3 +1,3 @@
# Bump this version to force CI to re-create the cache from scratch.
04-19-22
06-07-23

View File

@@ -30,7 +30,7 @@ mainBuildFilters: &mainBuildFilters
- /^release\/\d+\.\d+\.\d+$/
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- 'update-v8-snapshot-cache-on-develop'
- 'ryanm/feat/unify-cdp-approach-in-electron'
- 'billg/v13-merge/6-8-23'
# usually we don't build Mac app - it takes a long time
# but sometimes we want to really confirm we are doing the right thing
@@ -41,7 +41,7 @@ macWorkflowFilters: &darwin-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'ryanm/feat/unify-cdp-approach-in-electron', << pipeline.git.branch >> ]
- equal: [ 'billg/v13-merge/6-8-23', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -52,7 +52,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'ryanm/feat/unify-cdp-approach-in-electron', << pipeline.git.branch >> ]
- equal: [ 'billg/v13-merge/6-8-23', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -72,7 +72,7 @@ windowsWorkflowFilters: &windows-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'ryanm/feat/unify-cdp-approach-in-electron', << pipeline.git.branch >> ]
- equal: [ 'billg/v13-merge/6-8-23', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -139,7 +139,7 @@ commands:
- run:
name: Check current branch to persist artifacts
command: |
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "update-v8-snapshot-cache-on-develop" && "$CIRCLE_BRANCH" != "ryanm/feat/unify-cdp-approach-in-electron" ]]; then
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "update-v8-snapshot-cache-on-develop" && "$CIRCLE_BRANCH" != "billg/v13-merge/6-8-23" ]]; then
echo "Not uploading artifacts or posting install comment for this branch."
circleci-agent step halt
fi
@@ -282,9 +282,6 @@ commands:
name: Restore cache state, to check for known modules cache existence
keys:
- v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-state-of-system-tests-projects-node-modules-cache-{{ checksum "system_tests_cache_key" }}
- run:
name: Send root honeycomb event for this CI build
command: cd system-tests/scripts && node ./send-root-honeycomb-event.js
- run:
name: Bail if specific cache exists
command: |
@@ -576,14 +573,15 @@ commands:
# To make `circleci tests` work correctly, we need to step into the package folder.
cd packages/<<parameters.package>>
GLOB="cypress/e2e/**/*cy.*"
if [[ <<parameters.type>> == 'ct' ]]; then
# component tests are located side by side with the source codes.
GLOB="src/**/*cy.*"
# for the app component tests, ignore specs that are known to cause failures on contributor PRs (see https://discuss.circleci.com/t/how-to-exclude-certain-files-from-circleci-test-globbing/41028)
TESTFILES=$(find src -regextype posix-extended -name '*.cy.*' -not -regex '.*(FileMatch|PromoAction|SelectorPlayground).cy.*' | circleci tests split --total=$CIRCLE_NODE_TOTAL)
else
GLOB="cypress/e2e/**/*cy.*"
TESTFILES=$(circleci tests glob "$GLOB" | circleci tests split --total=$CIRCLE_NODE_TOTAL)
fi
TESTFILES=$(circleci tests glob "$GLOB" | circleci tests split --total=$CIRCLE_NODE_TOTAL)
echo "Test files for this machine are $TESTFILES"
# To run the `yarn` command, we need to walk out of the package folder.
@@ -752,7 +750,7 @@ commands:
command:
description: Test command to run to start Cypress tests
type: string
default: "yarn cypress:run"
default: "CYPRESS_INTERNAL_ENABLE_TELEMETRY=1 CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY CYPRESS_PROJECT_ID=ypt4pf yarn cypress:run"
# if the repo to clone and test is a monorepo, you can
# run tests inside a specific subfolder
folder:
@@ -822,7 +820,7 @@ commands:
name: Run tests using browser "<<parameters.browser>>"
working_directory: /tmp/<<parameters.repo>>/<<parameters.folder>>
command: |
<<parameters.command>> -- --browser <<parameters.browser>>
<<parameters.command>> --browser <<parameters.browser>> --record false
- unless:
condition: <<parameters.browser>>
steps:
@@ -839,7 +837,7 @@ commands:
- run:
name: Run tests using browser "<<parameters.browser>>"
working_directory: /tmp/<<parameters.repo>>
command: <<parameters.command>> -- --browser <<parameters.browser>>
command: <<parameters.command>> --browser <<parameters.browser>> --record false
- unless:
condition: <<parameters.browser>>
steps:
@@ -1944,20 +1942,6 @@ jobs:
command: yarn workspace @cypress/mount-utils build
- store-npm-logs
npm-xpath:
<<: *defaults
resource_class: small
steps:
- restore_cached_workspace
- run:
name: Run tests
command: yarn workspace @cypress/xpath cy:run
- store_test_results:
path: npm/xpath/test_results
- store_artifacts:
path: npm/xpath/test_results
- store-npm-logs
npm-grep:
<<: *defaults
resource_class: small
@@ -2050,20 +2034,13 @@ jobs:
command: rm -rf cypress.json
- run:
name: Install prod dependencies
command: yarn --production
command: yarn --production --ignore-engines
working_directory: /tmp/cypress-example-kitchensink
- run:
name: Example server
command: yarn start
working_directory: /tmp/cypress-example-kitchensink
background: true
- run:
name: Rename support file
working_directory: /tmp/cypress-example-kitchensink
command: |
if [[ -f cypress/support/index.js ]]; then
mv cypress/support/index.js cypress/support/e2e.js
fi
- run:
name: Run Kitchensink example project
command: |
@@ -2767,6 +2744,7 @@ linux-x64-workflow: &linux-x64-workflow
requires:
- create-build-artifacts
- test-binary-against-cypress-realworld-app:
context: test-runner:cypress-record-key
<<: *mainBuildFilters
requires:
- create-build-artifacts

View File

@@ -57,7 +57,6 @@ module.exports = {
rules: {
'no-restricted-properties': 'off',
'no-restricted-syntax': 'off',
'no-console': 'off',
},
},
],

View File

@@ -16,7 +16,7 @@ jobs:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setting up Node
uses: actions/setup-node@v3
with:
@@ -27,6 +27,6 @@ jobs:
- name: Perform SCA Scan
continue-on-error: false
run: |
snyk test --yarn-workspaces --strict-out-of-sync=false --detection-depth=6 --exclude=docker,Dockerfile --severity-threshold=critical
snyk test --all-projects --strict-out-of-sync=false --detection-depth=6 --exclude=docker,Dockerfile --severity-threshold=critical
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

View File

@@ -13,7 +13,7 @@ jobs:
Snyk_SAST_Scan :
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: snyk/actions/setup@master
- name: Perform Static Analysis Test
continue-on-error: true

View File

@@ -6,6 +6,10 @@ on:
description: 'debug-only'
required: false
default: false
max-operations-per-run:
description: 'max operations per run'
required: false
default: 3000
days-before-stale:
description: 'days-before-stale'
required: false
@@ -28,7 +32,8 @@ permissions:
issues: write
pull-requests: write
env:
DEFAULT_DEBUG_ONLY: true
DEFAULT_DEBUG_ONLY: false
DEFAULT_MAX_OPS: 3000
DEFAULT_DAYS_BEFORE_STALE: 180
DEFAULT_DAYS_BEFORE_CLOSE: 14
DEFAULT_EXEMPT_ISSUE_LABELS: 'type: feature,type: enhancement,routed-to-e2e,routed-to-ct,routed-to-tools,routed-to-cloud,prevent-stale,triaged'
@@ -37,7 +42,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v7
- uses: actions/stale@v8
with:
days-before-stale: ${{ github.event.inputs.days-before-stale || env.DEFAULT_DAYS_BEFORE_STALE }}
days-before-close: ${{ github.event.inputs.days-before-close || env.DEFAULT_DAYS_BEFORE_CLOSE }}
@@ -50,5 +55,6 @@ jobs:
exempt-issue-labels: ${{ github.event.inputs.exempt-issue-labels || env.DEFAULT_EXEMPT_ISSUE_LABELS }}
exempt-pr-labels: ${{ github.event.inputs.exempt-pr-labels || env.DEFAULT_EXEMPT_PR_LABELS }}
exempt-all-milestones: true
operations-per-run: 400 #keeping this a bit higher because it processes newest tickets to oldest
operations-per-run: ${{ github.event.inputs.max-operations-per-run || env.DEFAULT_MAX_OPS }} #keeping this a bit higher because it processes newest tickets to oldest
debug-only: ${{ github.event.inputs.debug-only || env.DEFAULT_DEBUG_ONLY }}
repo-token: ${{ secrets.TRIAGE_BOARD_TOKEN }}

View File

@@ -6,6 +6,10 @@ on:
secrets:
ADD_TO_TRIAGE_BOARD_TOKEN:
required: true
TRIAGE_BOARD_TOKEN:
required: true
WORKFLOW_DEPLOY_KEY:
required: true
issues:
types:
- opened
@@ -41,3 +45,24 @@ jobs:
with:
project-url: https://github.com/orgs/${{github.repository_owner}}/projects/${{env.PROJECT_NUMBER}}
github-token: ${{ secrets.ADD_TO_TRIAGE_BOARD_TOKEN }}
add-contributor-pr-comment:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
repository: 'cypress-io/release-automations'
ref: 'master'
ssh-key: ${{ secrets.WORKFLOW_DEPLOY_KEY }}
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 'lts/*'
- name: Run comment_workflow.js Script
uses: actions/github-script@v6
with:
github-token: ${{ secrets.TRIAGE_BOARD_TOKEN }}
script: |
const script = require('./scripts/triage/add_contributing_comment.js')
await script.addContributingComment(github, context);

View File

@@ -22,7 +22,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
node-version: 'lts/*'
- name: Run comment_workflow.js Script
uses: actions/github-script@v6
with:

View File

@@ -10,7 +10,7 @@ jobs:
BASE_BRANCH: develop
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.BOT_GITHUB_ACTION_TOKEN }}
@@ -40,13 +40,13 @@ jobs:
env:
BRANCH_NAME: update-chrome-stable-from-${{ steps.get-versions.outputs.current_stable_version }}-beta-from-${{ steps.get-versions.outputs.current_beta_version }}
run: |
echo "::set-output name=branch_name::${{ env.BRANCH_NAME }}"
echo "::set-output name=branch_exists::$(git show-ref --verify --quiet refs/remotes/origin/${{ env.BRANCH_NAME }} && echo 'true')"
echo "branch_name=${{ env.BRANCH_NAME }}" >> $GITHUB_OUTPUT
echo "branch_exists=$(git show-ref --verify --quiet refs/remotes/origin/${{ env.BRANCH_NAME }} && echo 'true')" >> $GITHUB_OUTPUT
- name: Check need for PR or branch update
id: check-need-for-pr
run: |
echo "::set-output name=needs_pr::${{ steps.get-versions.outputs.has_update == 'true' && steps.check-branch.outputs.branch_exists != 'true' }}"
echo "::set-output name=needs_branch_update::${{ steps.get-versions.outputs.has_update == 'true' && steps.check-branch.outputs.branch_exists == 'true' }}"
echo "needs_pr=${{ steps.get-versions.outputs.has_update == 'true' && steps.check-branch.outputs.branch_exists != 'true' }}" >> $GITHUB_OUTPUT
echo "needs_branch_update=${{ steps.get-versions.outputs.has_update == 'true' && steps.check-branch.outputs.branch_exists == 'true' }}" >> $GITHUB_OUTPUT
## Update available and a branch/PR already exists
- name: Checkout existing branch
if: ${{ steps.check-need-for-pr.outputs.needs_branch_update == 'true' }}

2
.gitignore vendored
View File

@@ -78,8 +78,6 @@ system-tests/lib/fixtureDirs.ts
# from npm/webpack-dev-server
/npm/webpack-dev-server/cypress/videos
# from npm/xpath
/npm/xpath/cypress/videos
# from npm/grep
/npm/grep/cypress/videos

View File

@@ -14,4 +14,3 @@
- [`@cypress/webpack-batteries-included-preprocessor`](https://github.com/cypress-io/cypress/blob/develop/npm/webpack-batteries-included-preprocessor/CHANGELOG.md)
- [`@cypress/webpack-dev-server`](https://github.com/cypress-io/cypress/blob/develop/npm/webpack-dev-server/CHANGELOG.md)
- [`@cypress/webpack-preprocessor`](https://github.com/cypress-io/cypress/blob/develop/npm/webpack-preprocessor/CHANGELOG.md)
- [`@cypress/xpath`](https://github.com/cypress-io/cypress/blob/develop/npm/xpath/CHANGELOG.md)

View File

@@ -197,7 +197,6 @@ Here is a list of the npm packages in this repository:
| [webpack-batteries-included-preprocessor](./npm/webpack-batteries-included-preprocessor) | `@cypress/webpack-batteries-included-preprocessor` | Cypress preprocessor for bundling JavaScript via webpack with dependencies included and support for various ES features, TypeScript, and CoffeeScript. |
| [webpack-dev-server](./npm/webpack-dev-server) | `@cypress/webpack-dev-server` | Webpack powered dev server for Component Testing. |
| [webpack-preprocessor](./npm/webpack-preprocessor) | `@cypress/webpack-preprocessor` | Cypress preprocessor for bundling JavaScript via webpack. |
| [xpath](./npm/xpath) | `@cypress/xpath` | Adds XPath command to Cypress.io test runner |
We try to tag all issues with a `pkg/` or `npm/` tag describing the appropriate package the work is required in. For public packages, we use their qualified package name: For example, issues relating to the webpack preprocessor are tagged under [`npm: @cypress/webpack-preprocessor`](https://github.com/cypress-io/cypress/labels/npm%3A%20%40cypress%2Fwebpack-preprocessor) label and issues related to the `driver` package are tagged with the [`pkg/driver`](https://github.com/cypress-io/cypress/labels/pkg%2Fdriver) label.
@@ -205,7 +204,7 @@ We try to tag all issues with a `pkg/` or `npm/` tag describing the appropriate
You must have the following installed on your system to contribute locally:
- [`Node.js`](https://nodejs.org/en/) (See the root [.node-version](.node-version) file for minimum version requirements. You can use [avn](https://github.com/wbyoung/avn) to automatically switch to the right version of Node.js for this repo.)
- [`Node.js`](https://nodejs.org/en/) (See the root [.node-version](.node-version) file for the required version. You can find a list of tools on [node-version-usage](https://github.com/shadowspawn/node-version-usage) to switch the version of [`Node.js`](https://nodejs.org/en/) based on [.node-version](.node-version).)
- [`yarn`](https://yarnpkg.com/en/docs/install)
- [`python`](https://www.python.org/downloads/) (since we use `node-gyp`. See their [repo](https://github.com/nodejs/node-gyp) for Python version requirements.)

View File

@@ -28,8 +28,8 @@
<a href="https://www.npmjs.com/package/cypress">
<img src="https://img.shields.io/npm/dm/cypress.svg" alt="npm"/>
</a>
<a href="https://gitter.im/cypress-io/cypress">
<img src="https://img.shields.io/gitter/room/cypress-io/cypress.svg" alt="Gitter chat"/>
<a href="https://on.cypress.io/discord">
<img src="https://img.shields.io/badge/chat-on%20Discord-brightgreen" alt="Discord chat"/>
</a>
<a href="https://stackshare.io/cypress">
<img src="https://img.stackshare.io/misc/follow-on-stackshare-badge.svg" alt="StackShare"/>

View File

@@ -1,5 +1,5 @@
{
"chrome:beta": "113.0.5672.63",
"chrome:stable": "112.0.5615.165",
"chrome:beta": "115.0.5790.13",
"chrome:stable": "114.0.5735.106",
"chrome:minimum": "64.0.3282.0"
}

View File

@@ -1,6 +1,10 @@
**/__snapshots__
/build
# do not lint package.json, it incorrect re-orders the `exports`
# https://github.com/cypress-io/cypress/pull/26630
package.json
# cli/types is linted by tslint/dtslint
/types

View File

@@ -7,18 +7,82 @@ _Released 03/1/2023 (PENDING)_
- The [`cy.readFile()`](/api/commands/readfile) command is now retry-able as a [query command](https://on.cypress.io/retry-ability). This should not affect any tests using it; the functionality is unchanged. However, it can no longer be overwritten using [`Cypress.Commands.overwrite()`](/api/cypress-api/custom-commands#Overwrite-Existing-Commands). Addressed in [#25595](https://github.com/cypress-io/cypress/pull/25595).
## 12.11.1
## 12.14.1
_Released 05/09/2023 (PENDING)_
_Released 06/20/2023 (PENDING)_
**Features:**
- The [`videoCompression`](https://docs.cypress.io/guides/references/configuration#Videos) configuration option now accepts both a boolean or a Constant Rate Factor (CRF) number between `1` and `51`. The `videoCompression` default value is still `32` CRF and when `videoCompression` is set to `true` the default of `32` CRF will be used. Addresses [#26658](https://github.com/cypress-io/cypress/issues/26658).
**Bugfixes:**
- Fixed an issue where video output was not being logged to the console when `videoCompression` was turned off. Videos will now log to the terminal regardless of the compression value. Addresses [#25945](https://github.com/cypress-io/cypress/issues/25945).
## 12.14.0
_Released 06/07/2023_
**Features:**
- A new testing type switcher has been added to the Spec Explorer to make it easier to move between E2E and Component Testing. An informational overview of each type is displayed if it hasn't already been configured to help educate and onboard new users to each testing type. Addresses [#26448](https://github.com/cypress-io/cypress/issues/26448), [#26836](https://github.com/cypress-io/cypress/issues/26836) and [#26837](https://github.com/cypress-io/cypress/issues/26837).
**Bugfixes:**
- Fixed an issue to now correctly detect Angular 16 dependencies
([@angular/cli](https://www.npmjs.com/package/@angular/cli),
[@angular-devkit/build-angular](https://www.npmjs.com/package/@angular-devkit/build-angular),
[@angular/core](https://www.npmjs.com/package/@angular/core), [@angular/common](https://www.npmjs.com/package/@angular/common),
[@angular/platform-browser-dynamic](https://www.npmjs.com/package/@angular/platform-browser-dynamic))
during Component Testing onboarding. Addresses [#26852](https://github.com/cypress-io/cypress/issues/26852).
- Ensures Git-related messages on the [Runs page](https://docs.cypress.io/guides/core-concepts/cypress-app#Runs) remain dismissed. Addresses [#26808](https://github.com/cypress-io/cypress/issues/26808).
**Dependency Updates:**
- Upgraded [`find-process`](https://www.npmjs.com/package/find-process) from `1.4.1` to `1.4.7` to address this [Synk](https://security.snyk.io/vuln/SNYK-JS-FINDPROCESS-1090284) security vulnerability. Addressed in [#26906](https://github.com/cypress-io/cypress/pull/26906).
- Upgraded [`firefox-profile`](https://www.npmjs.com/package/firefox-profile) from `4.0.0` to `4.3.2` to address security vulnerabilities within sub-dependencies. Addressed in [#26912](https://github.com/cypress-io/cypress/pull/26912).
## 12.13.0
_Released 05/23/2023_
**Features:**
- Adds Git-related messages for the [Runs page](https://docs.cypress.io/guides/core-concepts/cypress-app#Runs) and [Debug page](https://docs.cypress.io/guides/cloud/runs#Debug) when users aren't using Git or there are no recorded runs for the current branch. Addresses [#26680](https://github.com/cypress-io/cypress/issues/26680).
**Bugfixes:**
- Reverted [#26452](https://github.com/cypress-io/cypress/pull/26452) which introduced a bug that prevents users from using End to End with Yarn 3. Fixed in [#26735](https://github.com/cypress-io/cypress/pull/26735). Fixes [#26676](https://github.com/cypress-io/cypress/issues/26676).
- Moved `types` condition to the front of `package.json#exports` since keys there are meant to be order-sensitive. Fixed in [#26630](https://github.com/cypress-io/cypress/pull/26630).
- Fixed an issue where newly-installed dependencies would not be detected during Component Testing setup. Addresses [#26685](https://github.com/cypress-io/cypress/issues/26685).
- Fixed a UI regression that was flashing an "empty" state inappropriately when loading the Debug page. Fixed in [#26761](https://github.com/cypress-io/cypress/pull/26761).
- Fixed an issue in Component Testing setup where TypeScript version 5 was not properly detected. Fixes [#26204](https://github.com/cypress-io/cypress/issues/26204).
**Misc:**
- Updated styling & content of Cypress Cloud slideshows when not logged in or no runs have been recorded. Addresses [#26181](https://github.com/cypress-io/cypress/issues/26181).
- Changed the nomenclature of 'processing' to 'compressing' when terminal video output is printed during a run. Addresses [#26657](https://github.com/cypress-io/cypress/issues/26657).
- Changed the nomenclature of 'Upload Results' to 'Uploading Screenshots & Videos' when terminal output is printed during a run. Addresses [#26759](https://github.com/cypress-io/cypress/issues/26759).
## 12.12.0
_Released 05/09/2023_
**Features:**
- Added a new informational banner to help get started with component testing from an existing end-to-end test suite. Addresses [#26511](https://github.com/cypress-io/cypress/issues/26511).
**Bugfixes:**
- Fixed an issue in Electron where devtools gets out of sync with the DOM occasionally. Addresses [#15932](https://github.com/cypress-io/cypress/issues/15932).
- Updated the Chromium renderer process crash message to be more terse. Addressed in [#26597](https://github.com/cypress-io/cypress/pull/26597).
- Fixed an issue with `CYPRESS_DOWNLOAD_PATH_TEMPLATE` regex to allow multiple replacements. Addresses [#23670](https://github.com/cypress-io/cypress/issues/23670).
- Moved `types` condition to the front of `package.json#exports` since keys there are meant to be order-sensitive. Fixed in [#26630](https://github.com/cypress-io/cypress/pull/26630).
**Dependency Updates:**
- Upgraded [`plist`](https://www.npmjs.com/package/plist) from `3.0.5` to `3.0.6` to address [CVE-2022-26260](https://nvd.nist.gov/vuln/detail/CVE-2022-22912#range-8131646) NVD security vulnerability. Addressed in [#26631](https://github.com/cypress-io/cypress/pull/26631).
- Upgraded [`engine.io`](https://www.npmjs.com/package/engine.io) from `6.2.1` to `6.4.2` to address [CVE-2023-31125](https://github.com/socketio/engine.io/security/advisories/GHSA-q9mw-68c2-j6m5) NVD security vulnerability. Addressed in [#26664](https://github.com/cypress-io/cypress/pull/26664).
- Upgraded [`@vue/test-utils`](https://www.npmjs.com/package/@vue/test-utils) from `2.0.2` to `2.3.2`. Addresses [#26575](https://github.com/cypress-io/cypress/issues/26575).
## 12.11.0
@@ -57,7 +121,6 @@ _Released 04/17/2023_
- Fixed an issue in the onboarding wizard where project framework & bundler would not be auto-detected when opening directly into component testing mode using the `--component` CLI flag. Fixes [#22777](https://github.com/cypress-io/cypress/issues/22777) and [#26388](https://github.com/cypress-io/cypress/issues/26388).
- Updated to use the `SEMAPHORE_GIT_WORKING_BRANCH` [Semphore](https://docs.semaphoreci.com) CI environment variable to correctly associate a Cloud run to the current branch. Previously this was incorrectly associating a run to the target branch. Fixes [#26309](https://github.com/cypress-io/cypress/issues/26309).
- Fix an edge case in Component Testing where a custom `baseUrl` in `tsconfig.json` for Next.js 13.2.0+ is not respected. This was partially fixed in [#26005](https://github.com/cypress-io/cypress/pull/26005), but an edge case was missed. Fixes [#25951](https://github.com/cypress-io/cypress/issues/25951).
- Correctly detect and resolve dependencies when configuring Component Testing in projects using Yarn's [Plug'n'Play feature](https://yarnpkg.com/features/pnp). Fixes [#25960](https://github.com/cypress-io/cypress/issues/25960).
- Fixed an issue where `click` events fired on `.type('{enter}')` did not propagate through shadow roots. Fixes [#26392](https://github.com/cypress-io/cypress/issues/26392).
**Misc:**

View File

@@ -60,3 +60,7 @@ https://download.cypress.io/desktop/0.20.2/OS-ARCH/cypress.zip
exports['desktop url from template with escaped dollar sign wrapped in quote'] = `
https://download.cypress.io/desktop/0.20.2/OS-ARCH/cypress.zip
`
exports['desktop url from template with multiple replacements'] = `
https://download.cypress.io/desktop/0.20.2/OS/ARCH/cypress-0.20.2-OS-ARCH.zip?referrer=https://download.cypress.io/desktop/0.20.2&version=0.20.2
`

View File

@@ -64,10 +64,10 @@ const prepend = (arch, urlPath, version) => {
return pathTemplate
? (
pathTemplate
.replace(/\\?\$\{endpoint\}/, endpoint)
.replace(/\\?\$\{platform\}/, platform)
.replace(/\\?\$\{arch\}/, arch)
.replace(/\\?\$\{version\}/, version)
.replace(/\\?\$\{endpoint\}/g, endpoint)
.replace(/\\?\$\{platform\}/g, platform)
.replace(/\\?\$\{arch\}/g, arch)
.replace(/\\?\$\{version\}/g, version)
)
: `${endpoint}?platform=${platform}&arch=${arch}`
}

View File

@@ -66,7 +66,15 @@
"devDependencies": {
"@babel/cli": "7.13.0",
"@babel/preset-env": "7.13.5",
"@cypress/angular": "0.0.0-development",
"@cypress/grep": "0.0.0-development",
"@cypress/mount-utils": "0.0.0-development",
"@cypress/react": "0.0.0-development",
"@cypress/react18": "0.0.0-development",
"@cypress/sinon-chai": "2.9.1",
"@cypress/svelte": "0.0.0-development",
"@cypress/vue": "0.0.0-development",
"@cypress/vue2": "0.0.0-development",
"@packages/root": "0.0.0-development",
"@types/bluebird": "3.5.33",
"@types/chai": "4.2.15",
@@ -120,47 +128,47 @@
"types": "types",
"exports": {
".": {
"types": "./types/index.d.ts",
"import": "./index.mjs",
"require": "./index.js",
"types": "./types/index.d.ts"
"require": "./index.js"
},
"./vue": {
"types": "./vue/dist/index.d.ts",
"import": "./vue/dist/cypress-vue.esm-bundler.js",
"require": "./vue/dist/cypress-vue.cjs.js",
"types": "./vue/dist/index.d.ts"
"require": "./vue/dist/cypress-vue.cjs.js"
},
"./vue2": {
"types": "./vue2/dist/index.d.ts",
"import": "./vue2/dist/cypress-vue2.esm-bundler.js",
"require": "./vue2/dist/cypress-vue2.cjs.js",
"types": "./vue2/dist/index.d.ts"
"require": "./vue2/dist/cypress-vue2.cjs.js"
},
"./package.json": {
"import": "./package.json",
"require": "./package.json"
},
"./react": {
"types": "./react/dist/index.d.ts",
"import": "./react/dist/cypress-react.esm-bundler.js",
"require": "./react/dist/cypress-react.cjs.js",
"types": "./react/dist/index.d.ts"
"require": "./react/dist/cypress-react.cjs.js"
},
"./react18": {
"types": "./react18/dist/index.d.ts",
"import": "./react18/dist/cypress-react.esm-bundler.js",
"require": "./react18/dist/cypress-react.cjs.js",
"types": "./react18/dist/index.d.ts"
"require": "./react18/dist/cypress-react.cjs.js"
},
"./mount-utils": {
"require": "./mount-utils/dist/index.js",
"types": "./mount-utils/dist/index.d.ts"
"types": "./mount-utils/dist/index.d.ts",
"require": "./mount-utils/dist/index.js"
},
"./angular": {
"types": "./angular/dist/index.d.ts",
"import": "./angular/dist/index.js",
"require": "./angular/dist/index.js",
"types": "./angular/dist/index.d.ts"
"require": "./angular/dist/index.js"
},
"./svelte": {
"types": "./svelte/dist/index.d.ts",
"import": "./svelte/dist/cypress-svelte.esm-bundler.js",
"require": "./svelte/dist/cypress-svelte.cjs.js",
"types": "./svelte/dist/index.d.ts"
"require": "./svelte/dist/cypress-svelte.cjs.js"
}
},
"workspaces": {

View File

@@ -81,6 +81,13 @@ describe('lib/tasks/download', function () {
snapshot('desktop url from template with version', normalize(url))
})
it('returns custom url from template with multiple replacements', () => {
process.env.CYPRESS_DOWNLOAD_PATH_TEMPLATE = '${endpoint}/${platform}/${arch}/cypress-${version}-${platform}-${arch}.zip?referrer=${endpoint}&version=${version}'
const url = download.getUrl('ARCH', '0.20.2')
snapshot('desktop url from template with multiple replacements', normalize(url))
})
it('returns custom url from template with escaped dollar sign', () => {
process.env.CYPRESS_DOWNLOAD_PATH_TEMPLATE = '\\${endpoint}/\\${platform}-\\${arch}/cypress.zip'
const url = download.getUrl('ARCH', '0.20.2')

View File

@@ -3004,10 +3004,13 @@ declare namespace Cypress {
*/
trashAssetsBeforeRuns: boolean
/**
* The quality setting for the video compression, in Constant Rate Factor (CRF). The value can be false to disable compression or a value between 0 and 51, where a lower value results in better quality (at the expense of a higher file size).
* The quality setting for the video compression, in Constant Rate Factor (CRF).
* Enable compression by passing true to use the default CRF of 32.
* Compress at custom CRF by passing a number between 1 and 51, where a lower value results in better quality (at the expense of a higher file size).
* Disable compression by passing false or 0.
* @default 32
*/
videoCompression: number | false
videoCompression: number | boolean
/**
* Whether Cypress will record a video of the test run when running headlessly.
* @default true

View File

@@ -9,7 +9,7 @@ const pluginConfig2: Cypress.PluginConfig = (on, config) => {
config.configFile // $ExpectType string
config.fixturesFolder // $ExpectType string | false
config.screenshotsFolder // $ExpectType string | false
config.videoCompression // $ExpectType number | false
config.videoCompression // $ExpectType number | boolean
config.projectRoot // $ExpectType string
config.version // $ExpectType string
config.testingType // $ExpectType TestingType

View File

@@ -5,8 +5,10 @@
"packages/*",
"npm/*",
"tooling/*",
"system-tests"
"system-tests",
"scripts"
],
"useWorkspaces": true,
"useNx": true,
"version": "0.0.0"
}

View File

@@ -116,6 +116,7 @@ export type MountResponse<T> = {
// 'zone.js/testing' is not properly aliasing `it.skip` but it does provide `xit`/`xspecify`
// Written up under https://github.com/angular/angular/issues/46297 but is not seeing movement
// so we'll patch here pending a fix in that library
// @ts-ignore Ignore so that way we can bypass semantic error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
globalThis.it.skip = globalThis.xit
@Injectable()

View File

@@ -21,10 +21,8 @@
"chalk": "4.1.0",
"cli-highlight": "2.1.10",
"commander": "6.2.1",
"fast-glob": "3.2.7",
"find-up": "5.0.0",
"fs-extra": "^9.1.0",
"glob": "^7.1.6",
"inquirer": "7.3.3",
"ora": "^5.1.0",
"recast": "0.20.4",
@@ -40,7 +38,6 @@
"copy": "0.3.2",
"mocha": "7.1.1",
"mock-fs": "5.1.1",
"shx": "0.3.3",
"snap-shot-it": "7.9.3",
"typescript": "^4.7.4"
},

View File

@@ -1,4 +1,4 @@
const fg = require('fast-glob')
const globby = require('globby')
const fs = require('fs-extra')
const chalk = require('chalk')
const path = require('path')
@@ -11,7 +11,7 @@ program
const srcPath = path.resolve(__dirname, '..', 'src')
const destinationPath = path.resolve(process.cwd(), destination)
const templates = await fg('**/*.template.js', {
const templates = await globby('**/*.template.js', {
cwd: srcPath,
onlyFiles: true,
unique: true,

View File

@@ -0,0 +1,13 @@
# [@cypress/vite-plugin-cypress-esm-v1.0.1](https://github.com/cypress-io/cypress/compare/@cypress/vite-plugin-cypress-esm-v1.0.0...@cypress/vite-plugin-cypress-esm-v1.0.1) (2023-05-23)
### Bug Fixes
* Vite esm plugin issues ([#26714](https://github.com/cypress-io/cypress/issues/26714)) ([38b9526](https://github.com/cypress-io/cypress/commit/38b952622e034928df0d6e5d571e83c22d98ce86))
# @cypress/vite-plugin-cypress-esm-v1.0.0 (2023-05-04)
### Features
* initial release of cypress/vite-plugin-cypress-esm ([#26663](https://github.com/cypress-io/cypress/issues/26663)) ([42d4f83](https://github.com/cypress-io/cypress/commit/42d4f836cf30069a152cb45ac49af736155e7cc1))

View File

@@ -36,9 +36,9 @@ export default defineConfig({
CypressEsm(),
]
}
),
)
}
},
}
}
})
```
@@ -61,6 +61,8 @@ CypressEsm({
})
```
This will exclude modules matching the supplied pattern from being processed by this plugin. It is important to note that the actual import of any matching module into other files/modules will still be processed unless those destinations are themselves excluded via the list.
React is known to have some conflicts with the Proxy implementation that cause problems stubbing internal React functionality. Since it is unlikely you want to stub parts of React itself, it's a good idea to add it to the `ignoreList`.
## Known Issues

View File

@@ -17,7 +17,7 @@ export default defineConfig({
jsxRuntime: 'classic',
}),
CypressEsm({
ignoreList: ['*Immutable*', '*MyAsync*'],
ignoreList: ['**/*ignoreList.cy.ts', '*MyAsync*'],
}),
],
}

View File

@@ -1,6 +1,14 @@
import './fixtures/style.css'
import { add } from './fixtures/add'
import css from './fixtures/style.css?inline'
import svg from './fixtures/image.svg?raw'
it('does not transform non JS assets', () => {
expect(add(1, 2)).to.eq(3)
describe('asset types', () => {
it('does not transform style assets', () => {
expect(css).to.contain('import')
expect(css).not.to.contain('_cypress')
})
it('does not transform image assets', () => {
expect(svg).to.contain('import')
expect(svg).not.to.contain('_cypress')
})
})

View File

@@ -74,4 +74,15 @@ describe('dynamic imports', () => {
cy.wrap(run())
})
it('ignores import-like functions', async () => {
/*
* This test will probably explode due to malformed syntax if the exclusion logic isn't working,
* so the assertion here isn't really necessary but helps mark as a passing test
*/
const importLike = await import('./fixtures/import-like')
expect(importLike.custom_import('abc')).to.eql('123abc')
})
})

View File

@@ -0,0 +1 @@
<!-- Magic comment: import('test') -->

View File

@@ -0,0 +1,5 @@
// Ensure import replacement is not too aggressive
// Should not replace this function name despite invocation looking like `import()`
export const custom_import = (value: string) => {
return `123${value}`
}

View File

@@ -1,3 +1,4 @@
div {
/* Magic comment: import('test') */
background: red;
}

View File

@@ -96,4 +96,16 @@ describe('supports every combination of import syntax in a single file', () => {
// @ts-expect-error
expect(window.sideEffect).to.eq('Side Effect')
})
describe('import-like syntax', () => {
it('should ignore if not prefixed with whitespace or newline', () => {
/*
* This test will probably explode due to malformed syntax if the exclusion logic isn't working,
* so the assertion here isn't really necessary but helps mark as a passing test
*/
const value = ' abc_import abc from "blah"'
expect(value).not.to.contain('cypress')
})
})
})

View File

@@ -0,0 +1,2 @@
declare module '*.css' {}
declare module '*.svg' {}

View File

@@ -19,14 +19,37 @@ interface CypressEsmOptions {
export const CypressEsm = (options?: CypressEsmOptions): Plugin => {
const ignoreList = options?.ignoreList ?? []
const ignoreMatcher = picomatch(ignoreList)
const importOnIgnoreList = (importTarget: string) => {
for (const ignore of ignoreList) {
if (picomatch.matchBase(importTarget, ignore)) {
return true
}
}
/**
* If a module ID is explicitly ignored then bypass our custom mapping on it
*
* @param moduleId
* @returns
*/
const isModuleOnIgnoreList = (moduleId: string) => {
return ignoreMatcher(moduleId)
}
/**
* If an import target is for a non-JS asset then we don't want to map it
* This is typically a dynamically-imported image or data asset
*
* @param importTarget
* @returns
*/
const isNonJsTarget = (importTarget: string) => {
// Strip quotes & semicolons
const sanitizedImportTarget = importTarget.replace(/["';]/gi, '').trim()
// Exclude common extensions for:
// - Images
// - Text/Data/Markup/Markdown files
// - Styles
// Other asset types like audio/video are unlikely to be imported into a JS file thus are not considered here
return /\.(svg|png|jpe?g|gif|tiff|webp|json|md|txt|xml|x?html?|css|less|s[c|a]ss?)(\?|$)/gi.test(sanitizedImportTarget)
}
/**
* Remap static import calls to use the Cypress module cache
*
@@ -48,19 +71,23 @@ export const CypressEsm = (options?: CypressEsmOptions): Plugin => {
const moduleIdentifier = moduleId.replace(/[^a-zA-Z\d]/g, '_')
const importRegex = /import (.+?) from (.*)/g
// Ensure import comes at start of line *or* is prefixed by a space so we don't capture things like
// `Refresh.__hmr_import('')
const importRegex = /(?<=^|\s)import (.+?) from (.*)/g
return code.replace(
importRegex,
(match, importVars: string, importTarget: string) => {
debug(`Mapping import ${counter + 1} in module ${moduleId}`)
let replacement = `import * as cypress_${moduleIdentifier}_${++counter} from ${importTarget}`
if (isNonJsTarget(importTarget)) {
debug(`Import ${importTarget} appears to be an asset and will not be re-mapped`)
if (importOnIgnoreList(importTarget)) {
return match
}
let replacement = `import * as cypress_${moduleIdentifier}_${++counter} from ${importTarget}`
if (!replacement.endsWith(';')) {
replacement += ';'
}
@@ -128,12 +155,14 @@ export const CypressEsm = (options?: CypressEsmOptions): Plugin => {
* __cypressDynamicModule(import("./mod_2")).then(mod => mod)
*/
const mapDynamicImportsToCache = (id: string, code: string) => {
const RE = /(import\((.+?)\))/g
const RE = /((?<=^|\s)import\((.+?)\))/g
return code.replace(
RE,
(match, importVars: string, importTarget: string) => {
if (importOnIgnoreList(importTarget)) {
if (isNonJsTarget(importTarget)) {
debug(`Import ${importTarget} appears to be an asset and will not be re-mapped`)
return match
}
@@ -149,10 +178,22 @@ export const CypressEsm = (options?: CypressEsmOptions): Plugin => {
name: 'cypress:mocks',
enforce: 'post',
transform (code, id, options) {
// Process all files to remap imports
// TODO: Restrict to JS files only? Any potential for .mjs etc?
if (isModuleOnIgnoreList(id)) {
debug(`Ignoring module ${id} due to ignoreList`)
return
}
if (isNonJsTarget(id)) {
debug(`Module ${id} appears to be an asset, ignoring`)
return
}
// Process all files to remap static imports
let transformedCode = mapImportsToCache(id, code)
// ...and dynamic imports
transformedCode = mapDynamicImportsToCache(id, transformedCode)
return {

View File

@@ -38,7 +38,6 @@
"cypress": "0.0.0-development",
"dependency-check": "2.9.1",
"deps-ok": "1.4.1",
"fast-glob": "3.1.1",
"find-webpack": "1.5.0",
"fs-extra": "^10.1.0",
"mocha": "^7.1.0",

View File

@@ -1,11 +1,11 @@
const { runTest } = require('./helpers')
const path = require('path')
const glob = require('fast-glob')
const globby = require('globby')
describe('can test', async () => {
// runs every test in cypress/tests/e2e as its own test
// the comment above the test will determine the assertion on the results
glob.sync(path.join(__dirname, '../../cypress/tests/e2e/**/*'))
globby.sync(path.join(__dirname, '../../cypress/tests/e2e/**/*'))
.map((v) => {
const filename = path.relative(process.cwd(), v)

View File

@@ -1,3 +0,0 @@
module.exports = {
...require('../../.releaserc'),
}

View File

@@ -1,13 +0,0 @@
# [@cypress/xpath-v2.0.3](https://github.com/cypress-io/cypress/compare/@cypress/xpath-v2.0.2...@cypress/xpath-v2.0.3) (2022-10-26)
### Bug Fixes
* **xpath:** update xpath main path ([#24259](https://github.com/cypress-io/cypress/issues/24259)) ([edf99c4](https://github.com/cypress-io/cypress/commit/edf99c41d6031c7a72ad2258f4fd29231823790c))
# [@cypress/xpath-v2.0.2](https://github.com/cypress-io/cypress/compare/@cypress/xpath-v2.0.1...@cypress/xpath-v2.0.2) (2022-09-29)
### Bug Fixes
* release svelte ([b86403f](https://github.com/cypress-io/cypress/commit/b86403fcbcc85ce5be1ca96bbf42357dd24c07dd))

View File

@@ -1,82 +1,3 @@
# @cypress/xpath
> Adds XPath command to [Cypress.io](https://www.cypress.io) test runner
## Install with npm
```shell
npm install -D @cypress/xpath
```
## Install with Yarn
```shell
yarn add @cypress/xpath --dev
```
Then include in your project's [support file](https://on.cypress.io/support-file)
```js
require('@cypress/xpath');
```
## Use
After installation your `cy` object will have `xpath` command.
```js
it('finds list items', () => {
cy.xpath('//ul[@class="todo-list"]//li').should('have.length', 3);
});
```
You can also chain `xpath` off of another command.
```js
it('finds list items', () => {
cy.xpath('//ul[@class="todo-list"]').xpath('./li').should('have.length', 3);
});
```
As with other cy commands, it is scoped by `cy.within()`.
```js
it('finds list items', () => {
cy.xpath('//ul[@class="todo-list"]').within(() => {
cy.xpath('./li').should('have.length', 3);
});
});
```
**note:** you can test XPath expressions from DevTools console using `$x(...)` function, for example `$x('//div')` to find all divs.
See [cypress/e2e/spec.cy.js](cypress/e2e/spec.cy.js)
## Beware the XPath // trap
In XPath the expression // means something very specific, and it might not be what you think. Contrary to common belief, // means "anywhere in the document" not "anywhere in the current context". As an example:
```js
cy.xpath('//body').xpath('//script');
```
You might expect this to find all script tags in the body, but actually, it finds all script tags in the entire document, not only those in the body! What you're looking for is the .// expression which means "any descendant of the current node":
```js
cy.xpath('//body').xpath('.//script');
```
The same thing goes for within:
```js
cy.xpath('//body').within(() => {
cy.xpath('.//script');
});
```
For more, see [Intelligent Code Completion](https://on.cypress.io/intellisense)
## License
This project is licensed under the terms of the [MIT license](/LICENSE.md).
> @cypress/xpath has been deprecated and is no longer supported.

View File

@@ -1,12 +0,0 @@
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
excludeSpecPattern: '*.html',
supportFile: 'cypress/support/e2e.js',
},
component: {
excludeSpecPattern: '*.html',
supportFile: 'cypress/support/e2e.js',
},
})

View File

@@ -1,26 +0,0 @@
<body>
<main>
<h1>cypress-xpath</h1>
<button id="first-button">Click me</button>
<div>
<input id="name" type="text" placeholder="Your name?" />
<span id="greeting"></span>
</div>
</main>
<script>
document.getElementById('first-button').addEventListener('click', () => {
window.alert('you clicked first button')
})
setTimeout(() => {
document
.querySelector('main')
.insertAdjacentHTML(
'afterend',
'<div id="inserted">inserted text</div>'
)
}, 1000)
document.getElementById('name').addEventListener('input', e => {
document.getElementById('greeting').innerText = `Hello, ${e.target.value}`
})
</script>
</body>

View File

@@ -1,183 +0,0 @@
/// <reference types="cypress" />
/// <reference path="../../src/index.d.ts" />
describe('cypress-xpath', () => {
it('adds xpath command', () => {
expect(cy).property('xpath').to.be.a('function')
})
context('elements', () => {
beforeEach(() => {
cy.visit('cypress/e2e/index.html')
})
it('finds h1', () => {
cy.xpath('//h1').should('have.length', 1)
})
it('returns jQuery wrapped elements', () => {
cy.xpath('//h1').then((el$) => {
expect(el$).to.have.property('jquery')
})
})
it('returns primitives as is', () => {
cy.xpath('string(//h1)').then((el$) => {
expect(el$).to.not.have.property('jquery')
})
})
it('provides jQuery wrapped elements to assertions', () => {
cy.xpath('//h1').should((el$) => {
expect(el$).to.have.property('jquery')
})
})
it('gets h1 text', () => {
cy.xpath('//h1/text()')
.its('0.textContent')
.should('equal', 'cypress-xpath')
})
it('retries until element is inserted', () => {
// the element will be inserted after 1 second
cy.xpath('string(//*[@id="inserted"])').should('equal', 'inserted text')
})
describe('chaining', () => {
it('finds h1 within main', () => {
// first assert that h1 doesn't exist as a child of the implicit document subject
cy.xpath('./h1').should('not.exist')
cy.xpath('//main').xpath('./h1').should('exist')
})
it('finds body outside of main when succumbing to // trap', () => {
// first assert that body doesn't actually exist within main
cy.xpath('//main').xpath('.//body').should('not.exist')
cy.xpath('//main').xpath('//body').should('exist')
})
it('finds h1 within document', () => {
cy.document().xpath('//h1').should('exist')
})
it('throws when subject is more than a single element', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.eq(
'xpath() can only be called on a single element. Your subject contained 2 elements.',
)
done()
})
cy.get('main, div').xpath('foo')
})
})
describe('within()', () => {
it('finds h1 within within-subject', () => {
// first assert that h1 doesn't exist as a child of the implicit document subject
cy.xpath('./h1').should('not.exist')
cy.xpath('//main').within(() => {
cy.xpath('./h1').should('exist')
})
})
it('finds body outside of within-subject when succumbing to // trap', () => {
// first assert that body doesn't actually exist within main
cy.xpath('//main').within(() => {
cy.xpath('.//body').should('not.exist')
})
cy.xpath('//main').within(() => {
cy.xpath('//body').should('exist')
})
})
})
describe('primitives', () => {
it('counts h1 elements', () => {
cy.xpath('count(//h1)').should('equal', 1)
})
it('returns h1 text content', () => {
cy.xpath('string(//h1)').should('equal', 'cypress-xpath')
})
it('returns boolean', () => {
cy.xpath('boolean(//h1)').should('be.true')
cy.xpath('boolean(//h2)').should('be.false')
})
})
describe('typing', () => {
it('works on text input', () => {
cy.xpath('//*[@id="name"]').type('World')
cy.contains('span#greeting', 'Hello, World')
})
})
describe('clicking', () => {
it('on button', () => {
// this button invokes window.alert when clicked
const alert = cy.stub()
cy.on('window:alert', alert)
cy.xpath('//*[@id="first-button"]')
.click()
.then(() => {
expect(alert).to.have.been.calledOnce
})
})
})
})
context('logging', () => {
beforeEach(() => {
cy.visit('cypress/e2e/index.html')
})
it('should log by default', () => {
cy.spy(Cypress, 'log').log(false)
cy.xpath('//h1').then(() => {
expect(Cypress.log).to.be.calledWithMatch({ name: 'xpath' })
})
})
it('logs the selector when not found', (done) => {
cy.xpath('//h1') // does exist
cy.on('fail', (e) => {
const isExpectedErrorMessage = (message) => {
return message.includes('Timed out retrying') &&
message.includes(
'Expected to find element: `//h2`, but never found it.',
)
}
if (!isExpectedErrorMessage(e.message)) {
console.error('Cypress test failed with an unexpected error message')
console.error(e)
return done(e)
}
// no errors, the error message for not found selector is correct
done()
})
cy.xpath('//h2', { timeout: 100 }) // does not exist
})
it('should not log when provided log: false', () => {
cy.spy(Cypress, 'log').log(false)
cy.xpath('//h1', { log: false }).then(() => {
expect(Cypress.log).to.not.be.calledWithMatch({ name: 'xpath' })
})
})
})
})

View File

@@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -1,16 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
import '../../src'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 KiB

View File

@@ -1,33 +0,0 @@
{
"name": "@cypress/xpath",
"version": "0.0.0-development",
"description": "Adds XPath command to Cypress.io test runner",
"main": "src",
"scripts": {
"lint": "eslint . --ext .ts,.js",
"cy:run": "node ../../scripts/cypress.js run --e2e",
"cy:open": "node ../../scripts/cypress.js open --e2e --project ${PWD}"
},
"files": [
"src"
],
"types": "src",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/cypress-io/cypress.git"
},
"homepage": "https://github.com/cypress-io/cypress/tree/develop/npm/xpath#readme",
"author": "Cypress Tools Team",
"bugs": {
"url": "https://github.com/cypress-io/cypress/issues"
},
"keywords": [
"cypress",
"cypress-io",
"xpath"
],
"publishConfig": {
"access": "public"
}
}

View File

@@ -1,16 +0,0 @@
/// <reference types="cypress" />
declare namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
/**
* Get one or more DOM elements by an XPath selector.
* **Note:** you can test XPath expressions from DevTools console using $x(...) function, for example $x('//div') to find all divs.
* @see https://github.com/cypress-io/cypress-xpath
* @example
* cy.xpath(`//ul[@class="todo-list"]//li`)
* .should('have.length', 3)
*/
xpath<E extends Node = HTMLElement>(selector: string, options?: Partial<Loggable & Timeoutable>): Chainable<JQuery<E>>
}
}

View File

@@ -1,165 +0,0 @@
/* eslint-disable no-redeclare */
/// <reference types="cypress" />
/**
* Adds XPath support to Cypress using a custom command.
*
* @see https://devhints.io/xpath
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_using_XPath_in_JavaScript
* @example
```js
it('finds list items', () => {
cy.xpath('//ul[@class="todo-list"]//li')
.should('have.length', 3)
})
```
*/
const xpath = (subject, selector, options = {}) => {
/* global XPathResult */
const isNumber = (xpathResult) => {
return xpathResult.resultType === XPathResult.NUMBER_TYPE
}
const numberResult = (xpathResult) => xpathResult.numberValue
const isString = (xpathResult) => {
return xpathResult.resultType === XPathResult.STRING_TYPE
}
const stringResult = (xpathResult) => xpathResult.stringValue
const isBoolean = (xpathResult) => {
return xpathResult.resultType === XPathResult.BOOLEAN_TYPE
}
const booleanResult = (xpathResult) => xpathResult.booleanValue
const isPrimitive = (x) => {
return Cypress._.isNumber(x) || Cypress._.isString(x) || Cypress._.isBoolean(x)
}
// options to log later
const log = {
name: 'xpath',
message: selector,
}
if (Cypress.dom.isElement(subject) && subject.length > 1) {
throw new Error(
`xpath() can only be called on a single element. Your subject contained ${
subject.length
} elements.`,
)
}
const getValue = () => {
let nodes = []
let contextNode
let withinSubject = cy.state('withinSubject')
if (Cypress.dom.isElement(subject)) {
contextNode = subject[0]
} else if (Cypress.dom.isDocument(subject)) {
contextNode = subject
} else if (withinSubject) {
contextNode = withinSubject[0]
} else {
contextNode = cy.state('window').document
}
let iterator = (contextNode.ownerDocument || contextNode).evaluate(
selector,
contextNode,
)
if (isNumber(iterator)) {
const result = numberResult(iterator)
log.consoleProps = () => {
return {
XPath: selector,
type: 'number',
result,
}
}
return result
}
if (isString(iterator)) {
const result = stringResult(iterator)
log.consoleProps = () => {
return {
XPath: selector,
type: 'string',
result,
}
}
return result
}
if (isBoolean(iterator)) {
const result = booleanResult(iterator)
log.consoleProps = () => {
return {
XPath: selector,
type: 'boolean',
result,
}
}
return result
}
try {
let node = iterator.iterateNext()
while (node) {
nodes.push(node)
node = iterator.iterateNext()
}
log.consoleProps = () => {
return {
XPath: selector,
result: nodes.length === 1 ? nodes[0] : nodes,
}
}
return nodes
} catch (e) {
console.error('Document tree modified during iteration', e)
return null
}
}
const resolveValue = () => {
return Cypress.Promise.try(getValue).then((value) => {
if (!isPrimitive(value)) {
value = Cypress.$(value)
// Add the ".selector" property because Cypress uses it for error messages
value.selector = selector
}
return cy.verifyUpcomingAssertions(value, options, {
onRetry: resolveValue,
})
})
}
return resolveValue().then((value) => {
if (options.log !== false) {
// TODO set found elements on the command log?
Cypress.log(log)
}
return value
})
}
Cypress.Commands.add(
'xpath',
{ prevSubject: ['optional', 'element', 'document'] },
xpath,
)

48
nx.json Normal file
View File

@@ -0,0 +1,48 @@
{
"tasksRunnerOptions": {
"default": {
"runner": "nx-cloud",
"options": {
"cacheableOperations": [
"lint"
],
"accessToken": "ZmNlNjA0YzAtNTM1NS00MDIwLWFlMWItNWYxYzNiMjQ4N2VkfHJlYWQtb25seQ=="
}
}
},
"targetDefaults": {
"lint": {
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.js"
]
},
"build": {
"dependsOn": [
"^build"
]
},
"build-prod": {
"dependsOn": [
"^build-prod"
]
}
},
"namedInputs": {
"sharedGlobals": [],
"default": [
"{projectRoot}/**/*",
"sharedGlobals"
],
"production": [
"default",
"!{projectRoot}/**/*.spec.ts",
"!{projectRoot}/**/*.md",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/.eslintrc.json",
"!{projectRoot}/.mocharc.{js,json}",
"!{projectRoot/cypress.config.{ts,js}",
"!{projectRoot/**/*.cy.ts"
]
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "cypress",
"version": "12.11.0",
"version": "12.14.0",
"description": "Cypress is a next generation front end testing tool built for the modern web",
"private": true,
"scripts": {
@@ -13,7 +13,7 @@
"binary-upload": "node ./scripts/binary.js upload",
"binary-zip": "node ./scripts/binary.js zip",
"build": "yarn build-npm-modules && lerna run build --stream --no-bail --ignore create-cypress-tests --ignore cypress --ignore \"'@packages/{runner}'\" --ignore \"'@cypress/{angular,react,react18,vue,vue2,mount-utils,svelte}'\" && node ./cli/scripts/post-build.js && lerna run build --stream --scope create-cypress-tests",
"build-npm-modules": "lerna run build --scope cypress --scope @cypress/mount-utils && lerna run build --scope \"'@cypress/{angular,react,react18,vue,vue2,svelte}'\"",
"build-npm-modules": "lerna run build --scope cypress --scope @cypress/mount-utils --scope @cypress/react && lerna run build --scope \"'@cypress/{angular,react18,vue,vue2,svelte}'\"",
"build-prod": "lerna run build-prod-ui --stream && lerna run build-prod --stream --ignore create-cypress-tests && node ./cli/scripts/post-build.js && lerna run build-prod --stream --scope create-cypress-tests --scope",
"build-v8-snapshot-dev": "node --max-old-space-size=8192 tooling/v8-snapshot/scripts/setup-v8-snapshot-in-cypress.js --env=dev",
"build-v8-snapshot-prod": "node --max-old-space-size=8192 tooling/v8-snapshot/scripts/setup-v8-snapshot-in-cypress.js",
@@ -41,7 +41,7 @@
"ensure-deps": "./scripts/ensure-dependencies.sh",
"get-next-version": "node scripts/get-next-version.js",
"postinstall": "node ./scripts/run-postInstall.js",
"lint": "lerna run lint --no-bail --concurrency 2 && eslint --ext .js,.ts,.json, scripts",
"lint": "lerna run lint --no-bail --concurrency 2",
"prepare-release-artifacts": "node ./scripts/prepare-release-artifacts.js",
"npm-release": "node scripts/npm-release.js",
"prestart": "yarn ensure-deps",
@@ -85,6 +85,7 @@
"@graphql-tools/delegate": "8.2.1",
"@graphql-tools/utils": "8.2.3",
"@graphql-tools/wrap": "8.1.1",
"@nrwl/nx-cloud": "16.0.5",
"@octokit/auth-app": "3.6.1",
"@octokit/core": "3.6.0",
"@percy/cli": "1.2.0",
@@ -119,7 +120,6 @@
"@typescript-eslint/eslint-plugin": "4.18.0",
"@typescript-eslint/parser": "4.18.0",
"@urql/introspection": "^0.3.0",
"arg": "4.1.2",
"ascii-table": "0.0.9",
"autobarrel": "^1.1.0",
"aws-sdk": "2.814.0",
@@ -158,7 +158,6 @@
"filesize": "4.1.2",
"fs-extra": "9.1.0",
"getenv": "^1.0.0",
"gift": "0.10.2",
"glob": "7.1.6",
"got": "11.8.5",
"graphql": "^15.5.1",
@@ -174,7 +173,7 @@
"inquirer": "3.3.0",
"inquirer-confirm": "2.0.3",
"lazy-ass": "1.6.0",
"lerna": "3.22.1",
"lerna": "5.4.3",
"lint-staged": "11.1.2",
"listr2": "3.8.3",
"lodash": "^4.17.21",
@@ -195,7 +194,6 @@
"semantic-release-monorepo": "7.0.3",
"semver": "7.3.2",
"shelljs": "0.8.5",
"shx": "0.3.3",
"sinon": "7.3.2",
"snap-shot-it": "7.9.3",
"start-server-and-test": "1.10.8",
@@ -246,7 +244,8 @@
"packages/*",
"npm/*",
"tooling/*",
"system-tests"
"system-tests",
"scripts"
],
"nohoist": [
"**/webpack-preprocessor/babel-loader",

View File

@@ -1,7 +1,7 @@
import type { SinonStub } from 'sinon'
import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json'
import { getPathForPlatform } from '../../src/paths'
import { snapshotAUTPanel } from './support/snapshot-aut-panel'
// import { snapshotAUTPanel } from './support/snapshot-aut-panel'
describe('Cypress In Cypress CT', { viewportWidth: 1500, defaultCommandTimeout: 10000 }, () => {
context('default config', () => {
@@ -24,19 +24,22 @@ describe('Cypress In Cypress CT', { viewportWidth: 1500, defaultCommandTimeout:
cy.contains('Canary').should('be.visible')
cy.findByTestId('viewport').click()
snapshotAUTPanel('browsers open')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('browsers open')
cy.contains('Canary').should('be.hidden')
cy.contains('The viewport determines the width and height of your application under test. By default the viewport will be 500px by 500px for component testing.')
.should('be.visible')
snapshotAUTPanel('viewport info open')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('viewport info open')
cy.get('body').click()
cy.findByTestId('playground-activator').click()
cy.findByTestId('playground-selector').clear().type('[data-cy-root]')
snapshotAUTPanel('cy.get selector')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('cy.get selector')
cy.findByTestId('playground-num-elements').contains('1 match')
@@ -50,7 +53,8 @@ describe('Cypress In Cypress CT', { viewportWidth: 1500, defaultCommandTimeout:
cy.findByTestId('playground-selector').clear().type('Component Test')
snapshotAUTPanel('cy.contains selector')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('cy.contains selector')
cy.findByTestId('playground-num-elements').contains('1 match')

View File

@@ -1,5 +1,5 @@
import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json'
import { snapshotAUTPanel } from './support/snapshot-aut-panel'
// import { snapshotAUTPanel } from './support/snapshot-aut-panel'
import { getPathForPlatform } from '../../src/paths'
describe('Cypress In Cypress E2E', { viewportWidth: 1500, defaultCommandTimeout: 10000 }, () => {
@@ -28,7 +28,8 @@ describe('Cypress In Cypress E2E', { viewportWidth: 1500, defaultCommandTimeout:
.focus()
.type('{esc}')
snapshotAUTPanel('browsers open')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('browsers open')
cy.contains('Canary').should('be.hidden')
@@ -36,14 +37,16 @@ describe('Cypress In Cypress E2E', { viewportWidth: 1500, defaultCommandTimeout:
cy.contains('The viewport determines the width and height of your application under test. By default the viewport will be 1000px by 660px for end-to-end testing.')
.should('be.visible')
snapshotAUTPanel('viewport info open')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('viewport info open')
cy.get('body').click()
cy.findByTestId('playground-activator').click()
cy.findByTestId('playground-selector').clear().type('li')
snapshotAUTPanel('cy.get selector')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('cy.get selector')
cy.findByTestId('playground-num-elements').contains('3 matches')
@@ -64,7 +67,8 @@ describe('Cypress In Cypress E2E', { viewportWidth: 1500, defaultCommandTimeout:
cy.findByTestId('playground-selector').clear().type('Item 1')
snapshotAUTPanel('cy.contains selector')
// TODO: restore when Percy CSS is fixed. See https://github.com/cypress-io/cypress/issues/23435
// snapshotAUTPanel('cy.contains selector')
cy.findByTestId('playground-num-elements').contains('1 match')

View File

@@ -395,4 +395,37 @@ describe('Cypress in Cypress', { viewportWidth: 1500, defaultCommandTimeout: 100
expect(ctx.actions.project.initializeActiveProject).to.be.called
})
})
describe('runSpec mutation', () => {
it('should trigger expected spec from POST', () => {
startAtSpecsPage('e2e')
cy.contains('E2E specs').should('be.visible')
cy.withCtx(async (ctx) => {
const url = `http://127.0.0.1:${ctx.gqlServerPort}/__launchpad/graphql?`
const payload = `{"query":"mutation{\\nrunSpec(specPath:\\"cypress/e2e/dom-content.spec.js\\"){\\n__typename\\n... on RunSpecResponse{\\ntestingType\\nbrowser{\\nid\\nname\\n}\\nspec{\\nid\\nname\\n}\\n}\\n}\\n}","variables":null}`
ctx.coreData.app.browserStatus = 'open'
/*
Note: If this test starts failing, this fetch is the likely culprit.
Validate the GQL payload above is still valid by logging the fetch response JSON
*/
await ctx.util.fetch(
url,
{
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: payload,
},
)
})
cy.contains('Dom Content').should('be.visible')
})
})
})

View File

@@ -55,12 +55,6 @@ describe('cloud debug test filtering', () => {
cy.get('@reporterPanel').then((el) => el.width(500))
cy.get('@reporterPanel').percySnapshot('wide')
cy.get('@reporterPanel').then((el) => el.width(350))
cy.get('@reporterPanel').percySnapshot('medium')
cy.get('@reporterPanel').then((el) => el.width(250))
cy.get('@reporterPanel').percySnapshot('narrow')
cy.get('@reporterPanel').then((el) => el.width(150))
cy.get('@reporterPanel').percySnapshot('skinny')
})

View File

@@ -2,6 +2,10 @@ import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json'
import type { SinonStub } from 'sinon'
function moveToRunsPage (): void {
cy.withCtx((ctx, o) => {
o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch')
})
cy.findByTestId('sidebar-link-runs-page').click()
cy.findByTestId('app-header-bar').findByText('Runs').should('be.visible')
cy.findByTestId('runs-container').should('be.visible')
@@ -34,6 +38,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
cy.scaffoldProject('component-tests')
cy.openProject('component-tests')
cy.startAppServer('component')
cy.withCtx((ctx, o) => {
o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch')
})
})
it('resolves the runs page', () => {
@@ -99,7 +106,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
moveToRunsPage()
cy.contains('a', 'OVERLIMIT').click()
cy.withCtx((ctx) => {
cy.withCtx((ctx, o) => {
expect((ctx.actions.electron.openExternal as SinonStub).lastCall.lastArg).to.contain('http://dummy.cypress.io/runs/4')
})
})
@@ -315,6 +322,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
cy.withCtx(async (ctx, o) => {
o.sinon.spy(ctx.cloud, 'executeRemoteGraphQL')
o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch')
const config = await ctx.project.getConfig()
expect(config.projectId).to.not.equal('newProjectId')
@@ -323,7 +331,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
moveToRunsPage()
cy.findByText(defaultMessages.runs.connect.buttonProject).click()
cy.contains('button', defaultMessages.runs.connect.modal.selectProject.createProject).click()
cy.findByText(defaultMessages.runs.connectSuccessAlert.title, { timeout: 10000 }).should('be.visible')
cy.findByText(defaultMessages.runs.connectSuccessAlert.title, { timeout: 10000 }).scrollIntoView().should('be.visible')
cy.withCtx(async (ctx) => {
const config = await ctx.project.getConfig()
@@ -577,7 +585,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
})
})
context('Runs - No Runs', () => {
context('Runs - No Runs', { viewportWidth: 1280 }, () => {
it('when no runs and not connected, shows connect to Cypress Cloud button', () => {
cy.scaffoldProject('component-tests')
cy.openProject('component-tests', ['--config-file', 'cypressWithoutProjectId.config.js'])
@@ -602,7 +610,6 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
it('displays how to record prompt when connected and no runs in Component Testing', () => {
scaffoldTestingTypeAndVisitRunsPage('component')
cy.contains(defaultMessages.runs.empty.title).should('be.visible')
cy.contains(defaultMessages.runs.empty.description).should('be.visible')
cy.findByDisplayValue('npx cypress run --component --record --key 2aaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa').should('be.visible')
})
@@ -610,7 +617,6 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
scaffoldTestingTypeAndVisitRunsPage('e2e')
cy.contains(defaultMessages.runs.empty.title).should('be.visible')
cy.contains(defaultMessages.runs.empty.description).should('be.visible')
cy.findByDisplayValue('npx cypress run --record --key 2aaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa').should('be.visible')
})
@@ -759,6 +765,10 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
})
it('should remove the alert warning if the app reconnects to the internet', () => {
cy.withCtx((ctx, o) => {
o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch')
})
cy.loginUser()
cy.visitApp()
cy.wait(1000)

View File

@@ -41,7 +41,7 @@ describe('App: Spec List (E2E)', () => {
})
cy.visitApp()
cy.contains('E2E specs')
cy.verifyE2ESelected()
}
const clearSearchAndType = (search: string) => {
@@ -67,10 +67,6 @@ describe('App: Spec List (E2E)', () => {
cy.findByTestId('app-header-bar').findByText('Specs').should('be.visible')
})
it('shows the "E2E specs" label as the header for the Spec Name column', () => {
cy.findByTestId('specs-testing-type-header').should('contain', 'E2E specs')
})
it('shows a git status for each spec', () => {
cy.findAllByTestId('git-info-row').each((row) => {
cy.wrap(row).find('svg').should('have.length', 1)
@@ -85,6 +81,18 @@ describe('App: Spec List (E2E)', () => {
cy.findAllByTestId('spec-item').should('contain', 'dom-content.spec.js')
})
it('lists files after folders when in same directory', () => {
cy.findAllByTestId('row-directory-depth-2').first().click()
const rowId = getPathForPlatform('speclist-cypress/e2e/admin_users/').replaceAll('\\', '\\\\')
cy.get(`[id="${rowId}"]`)
.next()
.should('contain', 'admin.user')
.next()
.should('contain', 'admin_users_list.spec.js')
})
it('opens the "Create new spec" modal after clicking the "New specs" button', () => {
cy.findByTestId('standard-modal').should('not.exist')
cy.findByTestId('new-spec-button').click()

View File

@@ -93,7 +93,7 @@ describe('App: Spec List - Flaky Indicator', () => {
})
cy.visitApp()
cy.contains('E2E specs')
cy.verifyE2ESelected()
})
it('shows the "Flaky" badge on specs considered flaky', () => {

View File

@@ -0,0 +1,95 @@
describe('App: Spec List Testing Type Switcher', () => {
context('ct unconfigured', () => {
beforeEach(() => {
cy.scaffoldProject('cypress-in-cypress')
cy.openProject('cypress-in-cypress')
cy.withCtx(async (ctx, o) => {
const config = await ctx.file.readFileInProject('cypress.config.js')
const newCypressConfig = config.replace(`component:`, `_component:`)
await ctx.actions.file.writeFileInProject('cypress.config.js', newCypressConfig)
})
cy.startAppServer('e2e')
cy.visitApp()
cy.verifyE2ESelected()
})
it('switches testing types', () => {
cy.findByTestId('testing-type-switch').within(() => {
cy.findByText('Component').click()
})
cy.verifyCtSelected()
cy.contains('Component testing is not set up for this project')
cy.findByTestId('testing-type-setup-button').should('be.visible')
})
})
context('e2e unconfigured', () => {
beforeEach(() => {
cy.scaffoldProject('cypress-in-cypress')
cy.openProject('cypress-in-cypress')
cy.withCtx(async (ctx, o) => {
const config = await ctx.file.readFileInProject('cypress.config.js')
const newCypressConfig = config.replace(`e2e:`, `_e2e:`)
await ctx.actions.file.writeFileInProject('cypress.config.js', newCypressConfig)
})
cy.startAppServer('component')
cy.visitApp()
cy.verifyCtSelected()
})
it('switches testing types', () => {
cy.findByTestId('testing-type-switch').within(() => {
cy.findByText('E2E').click()
})
cy.contains('End-to-end testing is not set up for this project')
cy.findByTestId('testing-type-setup-button').should('be.visible')
})
})
context('both testing types configured', () => {
beforeEach(() => {
cy.scaffoldProject('cypress-in-cypress')
cy.findBrowsers()
cy.openProject('cypress-in-cypress')
cy.startAppServer('component')
cy.visitApp()
cy.verifyCtSelected()
})
it('displays expected switch content', () => {
cy.findByTestId('unconfigured-icon').should('not.exist')
cy.withCtx((ctx, o) => {
o.sinon.stub(ctx.actions.project, 'setAndLoadCurrentTestingType')
o.sinon.stub(ctx.actions.project, 'reconfigureProject').resolves()
})
cy.findByTestId('testing-type-switch').within(() => {
cy.findByText('E2E').click()
})
cy.verifyE2ESelected()
cy.withCtx((ctx) => {
expect(ctx.coreData.app.relaunchBrowser).eq(true)
expect(ctx.actions.project.setAndLoadCurrentTestingType).to.have.been.calledWith('e2e')
expect(ctx.actions.project.reconfigureProject).to.have.been.called
})
})
})
})

View File

@@ -16,3 +16,21 @@ beforeEach(() => {
// @ts-ignore - dynamically defined during tests using
expect(window.top?.getEventManager().autDestroyedCount).to.be.undefined
})
function e2eTestingTypeIsSelected () {
cy.findByTestId('specs-testing-type-header').within(() => {
cy.findByTestId('testing-type-switch').contains('button', 'E2E').should('have.attr', 'aria-selected', 'true')
cy.findByTestId('testing-type-switch').contains('button', 'Component').should('not.have.attr', 'aria-selected')
})
}
Cypress.Commands.add('verifyE2ESelected', e2eTestingTypeIsSelected)
function ctTestingTypeIsSelected () {
cy.findByTestId('specs-testing-type-header').within(() => {
cy.findByTestId('testing-type-switch').contains('button', 'E2E').should('not.have.attr', 'aria-selected')
cy.findByTestId('testing-type-switch').contains('button', 'Component').should('have.attr', 'aria-selected', 'true')
})
}
Cypress.Commands.add('verifyCtSelected', ctTestingTypeIsSelected)

View File

@@ -18,6 +18,8 @@ declare global {
*
*/
waitForSpecToFinish(expectedResults?: ExpectedResults, timeout?: number): void
verifyE2ESelected(): void
verifyCtSelected(): void
}
}
}

View File

@@ -699,7 +699,7 @@ describe('Growth Prompts Can Open Automatically', () => {
)
cy.visitApp()
cy.contains('E2E specs')
cy.verifyE2ESelected()
cy.wait(1000)
cy.contains('Configure CI').should('be.visible')
})
@@ -717,7 +717,7 @@ describe('Growth Prompts Can Open Automatically', () => {
)
cy.visitApp()
cy.contains('E2E specs')
cy.verifyE2ESelected()
cy.wait(1000)
cy.contains('Configure CI').should('not.exist')
})

View File

@@ -20,8 +20,10 @@
},
"dependencies": {},
"devDependencies": {
"@cypress-design/vue-icon": "0.20.0",
"@cypress-design/vue-statusicon": "0.3.0",
"@cypress-design/vue-button": "^0.10.1",
"@cypress-design/vue-icon": "^0.23.1",
"@cypress-design/vue-statusicon": "^0.4.7",
"@cypress-design/vue-tabs": "^0.5.1",
"@graphql-typed-document-node/core": "^3.1.0",
"@headlessui/vue": "1.4.0",
"@iconify/iconify": "2.1.2",
@@ -30,7 +32,7 @@
"@intlify/unplugin-vue-i18n": "0.10.0",
"@packages/frontend-shared": "0.0.0-development",
"@packages/telemetry": "0.0.0-development",
"@percy/cypress": "^3.1.0",
"@percy/cypress": "^3.1.2",
"@popperjs/core": "2.11.6",
"@testing-library/cypress": "9.0.0",
"@types/faker": "5.5.8",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,68 @@
<svg viewBox="0 0 468 284" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_918_2840)">
<rect width="468" height="284" rx="6" fill="white" />
<rect width="468" height="64" fill="#F3F4FA" />
<path
d="M18 38V26C18 25.4477 18.4477 25 19 25H29C29.5523 25 30 25.4477 30 26V38C30 38.5523 29.5523 39 29 39H19C18.4477 39 18 38.5523 18 38Z"
fill="#E1E3ED" />
<path
d="M21 32H24M21 29H27M21 35H26M29 25L19 25C18.4477 25 18 25.4477 18 26V38C18 38.5523 18.4477 39 19 39H29C29.5523 39 30 38.5523 30 38V26C30 25.4477 29.5523 25 29 25Z"
stroke="#9095AD" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M44.25 38.1562C41.9453 38.1562 40.4844 36.5156 40.4844 33.9297V33.9219C40.4844 31.3594 41.9766 29.7188 44.2344 29.7188C46.2578 29.7188 47.4531 31.0625 47.625 32.4531L47.6328 32.5156H46.3047L46.2891 32.4531C46.0859 31.6406 45.4297 30.9219 44.2344 30.9219C42.8203 30.9219 41.875 32.0938 41.875 33.9375V33.9453C41.875 35.8359 42.8438 36.9531 44.25 36.9531C45.3594 36.9531 46.0703 36.3281 46.2969 35.4219L46.3125 35.3594H47.6484L47.6406 35.4141C47.4219 36.9609 46.0859 38.1562 44.25 38.1562ZM49.6797 40.7344C49.4141 40.7344 49.125 40.7031 48.9531 40.6719V39.5625C49.0703 39.5859 49.2266 39.6094 49.3906 39.6094C50.25 39.6094 50.7266 39.3906 51.0547 38.4688L51.2188 38.0078L48.2031 29.875H49.6562L51.8984 36.6406H51.9297L54.1797 29.875H55.6094L52.4375 38.5078C51.8594 40.0625 51.1484 40.7344 49.6797 40.7344ZM56.6797 40.7344V29.875H58.0391V31.25H58.0703C58.5781 30.3047 59.4844 29.7188 60.6484 29.7188C62.7266 29.7188 64.1016 31.375 64.1016 33.9375V33.9453C64.1016 36.5078 62.7109 38.1562 60.6719 38.1562C59.5234 38.1562 58.5781 37.5781 58.0703 36.6406H58.0391V40.7344H56.6797ZM60.3828 36.9531C61.8203 36.9531 62.7109 35.7969 62.7109 33.9453V33.9375C62.7109 32.0703 61.8203 30.9219 60.3828 30.9219C59.0078 30.9219 58.0312 32.1172 58.0312 33.9375V33.9453C58.0312 35.7578 59.0156 36.9531 60.3828 36.9531ZM65.4766 38V29.875H66.8359V31.25H66.8672C67.1406 30.3125 67.8438 29.7188 68.7578 29.7188C68.9922 29.7188 69.1953 29.7578 69.3047 29.7734V31.0938C69.1953 31.0547 68.9062 31.0156 68.5781 31.0156C67.5234 31.0156 66.8359 31.75 66.8359 32.9844V38H65.4766ZM73.3672 38.1562C71.0312 38.1562 69.625 36.5234 69.625 33.9688V33.9609C69.625 31.4453 71.0625 29.7188 73.2812 29.7188C75.5 29.7188 76.8516 31.3672 76.8516 33.8047V34.3047H71C71.0312 35.9766 71.9531 36.9531 73.3984 36.9531C74.4297 36.9531 75.1562 36.4375 75.3906 35.7422L75.4141 35.6719H76.75L76.7344 35.75C76.4688 37.0938 75.1406 38.1562 73.3672 38.1562ZM73.2734 30.9219C72.0938 30.9219 71.1719 31.7266 71.0234 33.2422H75.4688C75.3359 31.6641 74.4609 30.9219 73.2734 30.9219ZM81.1094 38.1562C79.1953 38.1562 78.0391 37.1797 77.875 35.7266L77.8672 35.6562H79.2266L79.2422 35.7344C79.4062 36.5469 80.0078 37.0234 81.1172 37.0234C82.2188 37.0234 82.875 36.5625 82.875 35.8281V35.8203C82.875 35.2344 82.5703 34.9062 81.6484 34.6797L80.3594 34.3672C78.8281 34 78.0859 33.2891 78.0859 32.1172V32.1094C78.0859 30.7109 79.3125 29.7188 81.0703 29.7188C82.8516 29.7188 83.9844 30.7578 84.0859 32.1172L84.0938 32.2188H82.7969L82.7891 32.1641C82.6797 31.375 82.0781 30.8516 81.0703 30.8516C80.0859 30.8516 79.4766 31.3281 79.4766 32.0469V32.0547C79.4766 32.6094 79.8438 32.9922 80.7422 33.2109L82.0312 33.5234C83.6719 33.9219 84.2656 34.5703 84.2656 35.7266V35.7344C84.2656 37.1562 82.9219 38.1562 81.1094 38.1562ZM88.5625 38.1562C86.6484 38.1562 85.4922 37.1797 85.3281 35.7266L85.3203 35.6562H86.6797L86.6953 35.7344C86.8594 36.5469 87.4609 37.0234 88.5703 37.0234C89.6719 37.0234 90.3281 36.5625 90.3281 35.8281V35.8203C90.3281 35.2344 90.0234 34.9062 89.1016 34.6797L87.8125 34.3672C86.2812 34 85.5391 33.2891 85.5391 32.1172V32.1094C85.5391 30.7109 86.7656 29.7188 88.5234 29.7188C90.3047 29.7188 91.4375 30.7578 91.5391 32.1172L91.5469 32.2188H90.25L90.2422 32.1641C90.1328 31.375 89.5312 30.8516 88.5234 30.8516C87.5391 30.8516 86.9297 31.3281 86.9297 32.0469V32.0547C86.9297 32.6094 87.2969 32.9922 88.1953 33.2109L89.4844 33.5234C91.125 33.9219 91.7188 34.5703 91.7188 35.7266V35.7344C91.7188 37.1562 90.375 38.1562 88.5625 38.1562ZM96.7266 26.7266L93.5469 40.7344H92.25L95.4297 26.7266H96.7266ZM100.945 38.1562C98.6094 38.1562 97.2031 36.5234 97.2031 33.9688V33.9609C97.2031 31.4453 98.6406 29.7188 100.859 29.7188C103.078 29.7188 104.43 31.3672 104.43 33.8047V34.3047H98.5781C98.6094 35.9766 99.5312 36.9531 100.977 36.9531C102.008 36.9531 102.734 36.4375 102.969 35.7422L102.992 35.6719H104.328L104.312 35.75C104.047 37.0938 102.719 38.1562 100.945 38.1562ZM100.852 30.9219C99.6719 30.9219 98.75 31.7266 98.6016 33.2422H103.047C102.914 31.6641 102.039 30.9219 100.852 30.9219ZM105.836 38V37.0312L109.805 32.8906C111.328 31.3047 111.68 30.6953 111.68 29.7578V29.7422C111.672 28.5938 110.805 27.7656 109.578 27.7656C108.172 27.7656 107.125 28.7344 107.125 29.9453V29.9844H105.766V29.9375C105.766 27.9844 107.453 26.5391 109.555 26.5391C111.594 26.5391 113.086 27.9062 113.086 29.6719V29.6875C113.086 30.9219 112.516 31.8516 110.445 33.9688L107.766 36.7188V36.75H113.273V38H105.836ZM118.211 38.1562C115.875 38.1562 114.469 36.5234 114.469 33.9688V33.9609C114.469 31.4453 115.906 29.7188 118.125 29.7188C120.344 29.7188 121.695 31.3672 121.695 33.8047V34.3047H115.844C115.875 35.9766 116.797 36.9531 118.242 36.9531C119.273 36.9531 120 36.4375 120.234 35.7422L120.258 35.6719H121.594L121.578 35.75C121.312 37.0938 119.984 38.1562 118.211 38.1562ZM118.117 30.9219C116.938 30.9219 116.016 31.7266 115.867 33.2422H120.312C120.18 31.6641 119.305 30.9219 118.117 30.9219ZM126.664 26.7266L123.484 40.7344H122.188L125.367 26.7266H126.664Z"
fill="#747994" />
<path
d="M127.203 38L131.305 26.7266H133.195L137.289 38H135.453L134.422 34.9531H130.078L129.039 38H127.203ZM132.234 28.5938L130.547 33.5469H133.945L132.266 28.5938H132.234ZM140.883 38.1641C139.078 38.1641 138.047 37 138.047 35.1094V29.7812H139.734V34.7812C139.734 36.0234 140.312 36.7109 141.484 36.7109C142.672 36.7109 143.438 35.8594 143.438 34.5781V29.7812H145.133V38H143.438V36.7656H143.398C142.969 37.5938 142.133 38.1641 140.883 38.1641ZM149.688 38.1641C148.062 38.1641 147.281 37.4766 147.281 35.8359V31.125H146.102V29.7812H147.281V27.6406H149.008V29.7812H150.547V31.125H149.008V35.7344C149.008 36.5703 149.383 36.8203 150.094 36.8203C150.273 36.8203 150.422 36.8047 150.547 36.7891V38.0938C150.352 38.125 150.031 38.1641 149.688 38.1641ZM152.008 38V26.7266H153.695V31.1328H153.734C154.172 30.1797 155.055 29.625 156.281 29.625C158.039 29.625 159.195 30.9375 159.195 32.9219V38H157.508V33.2422C157.508 31.8828 156.82 31.0703 155.633 31.0703C154.469 31.0703 153.695 31.9609 153.695 33.2422V38H152.008Z"
fill="#2E3247" />
<path
d="M161.68 38.1016C161.273 38.1016 160.953 37.7812 160.953 37.375C160.953 36.9688 161.273 36.6484 161.68 36.6484C162.086 36.6484 162.406 36.9688 162.406 37.375C162.406 37.7812 162.086 38.1016 161.68 38.1016ZM167.039 38.1484C165.195 38.1484 164.016 37.1641 163.859 35.7266L163.852 35.6562H164.883L164.898 35.7266C165.062 36.6641 165.82 37.2734 167.047 37.2734C168.273 37.2734 169.055 36.7109 169.055 35.8594V35.8516C169.055 35.1484 168.664 34.7656 167.578 34.5078L166.352 34.2109C164.82 33.8438 164.086 33.1719 164.086 32.0469V32.0391C164.086 30.6875 165.281 29.7266 166.977 29.7266C168.711 29.7266 169.82 30.7344 169.953 32.1328L169.961 32.2188H168.969L168.961 32.1641C168.828 31.2188 168.109 30.6016 166.977 30.6016C165.875 30.6016 165.141 31.1719 165.141 32V32.0078C165.141 32.6562 165.578 33.0703 166.648 33.3281L167.875 33.6172C169.492 34.0078 170.109 34.6406 170.109 35.7812V35.7891C170.109 37.1719 168.82 38.1484 167.039 38.1484ZM171.5 40.7344V29.875H172.531V31.5938H172.562C173.016 30.4922 174.016 29.7266 175.32 29.7266C177.383 29.7266 178.766 31.3984 178.766 33.9375V33.9453C178.766 36.4922 177.375 38.1484 175.336 38.1484C174.039 38.1484 173.008 37.3906 172.562 36.3047H172.531V40.7344H171.5ZM175.141 37.2266C176.703 37.2266 177.711 35.9375 177.711 33.9453V33.9375C177.711 31.9297 176.703 30.6484 175.141 30.6484C173.609 30.6484 172.531 31.9688 172.531 33.9375V33.9453C172.531 35.9062 173.617 37.2266 175.141 37.2266ZM183.445 38.1484C181.164 38.1484 179.75 36.5312 179.75 33.9609V33.9531C179.75 31.4062 181.188 29.7266 183.359 29.7266C185.531 29.7266 186.898 31.3516 186.898 33.7812V34.1875H180.797C180.828 36.125 181.867 37.2266 183.469 37.2266C184.664 37.2266 185.492 36.625 185.758 35.7422L185.773 35.6719H186.797L186.781 35.75C186.5 37.1406 185.203 38.1484 183.445 38.1484ZM183.352 30.6484C181.969 30.6484 180.938 31.6406 180.812 33.3672H185.859C185.742 31.5938 184.742 30.6484 183.352 30.6484ZM191.57 38.1484C189.312 38.1484 187.875 36.5156 187.875 33.9297V33.9219C187.875 31.3672 189.336 29.7266 191.562 29.7266C193.453 29.7266 194.68 30.9531 194.883 32.3516L194.891 32.4219H193.875L193.859 32.3594C193.633 31.4062 192.828 30.6484 191.562 30.6484C189.977 30.6484 188.938 31.9219 188.938 33.9375V33.9453C188.938 35.9922 189.992 37.2266 191.57 37.2266C192.781 37.2266 193.617 36.5312 193.859 35.5156L193.875 35.4531H194.898L194.891 35.5156C194.648 37.0312 193.344 38.1484 191.57 38.1484ZM196.82 38.1016C196.414 38.1016 196.094 37.7812 196.094 37.375C196.094 36.9688 196.414 36.6484 196.82 36.6484C197.227 36.6484 197.547 36.9688 197.547 37.375C197.547 37.7812 197.227 38.1016 196.82 38.1016ZM199.977 28.4062C199.602 28.4062 199.289 28.1016 199.289 27.7188C199.289 27.3359 199.602 27.0391 199.977 27.0391C200.359 27.0391 200.664 27.3359 200.664 27.7188C200.664 28.1016 200.359 28.4062 199.977 28.4062ZM198.156 40.7422C198.07 40.7422 197.992 40.7422 197.906 40.7344V39.8203H198.117C199.086 39.8203 199.461 39.4766 199.461 38.5V29.875H200.492V38.4766C200.492 40.0391 199.766 40.7422 198.156 40.7422ZM205.148 38.1484C203.305 38.1484 202.125 37.1641 201.969 35.7266L201.961 35.6562H202.992L203.008 35.7266C203.172 36.6641 203.93 37.2734 205.156 37.2734C206.383 37.2734 207.164 36.7109 207.164 35.8594V35.8516C207.164 35.1484 206.773 34.7656 205.688 34.5078L204.461 34.2109C202.93 33.8438 202.195 33.1719 202.195 32.0469V32.0391C202.195 30.6875 203.391 29.7266 205.086 29.7266C206.82 29.7266 207.93 30.7344 208.062 32.1328L208.07 32.2188H207.078L207.07 32.1641C206.938 31.2188 206.219 30.6016 205.086 30.6016C203.984 30.6016 203.25 31.1719 203.25 32V32.0078C203.25 32.6562 203.688 33.0703 204.758 33.3281L205.984 33.6172C207.602 34.0078 208.219 34.6406 208.219 35.7812V35.7891C208.219 37.1719 206.93 38.1484 205.148 38.1484Z"
fill="#747994" />
<g clip-path="url(#clip1_918_2840)">
<rect x="217" y="20" width="39" height="24" rx="4" fill="white" />
<path d="M227 29L233 35M233 29L227 35" stroke="#E45770" stroke-width="2" stroke-linecap="round" />
<path
d="M244.211 37.1641C242.105 37.1641 240.731 36.0156 240.595 34.4092L240.588 34.3203H242.058L242.064 34.3955C242.16 35.2705 242.987 35.8857 244.211 35.8857C245.414 35.8857 246.228 35.2158 246.228 34.2588V34.2451C246.228 33.1309 245.421 32.5088 244.102 32.5088H242.905V31.3193H244.061C245.188 31.3193 245.954 30.6562 245.954 29.7402V29.7266C245.954 28.7764 245.312 28.2227 244.197 28.2227C243.104 28.2227 242.338 28.7969 242.242 29.7129L242.235 29.7744H240.8L240.807 29.7061C240.957 28.0586 242.27 26.9717 244.197 26.9717C246.159 26.9717 247.444 28.0107 247.444 29.5283V29.542C247.444 30.7656 246.569 31.5859 245.366 31.8389V31.873C246.815 32.0029 247.786 32.8779 247.786 34.2588V34.2725C247.786 35.9609 246.303 37.1641 244.211 37.1641Z"
fill="#5A5F7A" />
<rect x="217.5" y="20.5" width="38" height="23" rx="3.5" stroke="#E1E3ED" />
</g>
<rect x="216" y="19" width="41" height="26" rx="5" stroke="#A06CE4" stroke-width="2" />
<rect x="347" y="20" width="105" height="24" rx="12" fill="#E1E3ED" />
<rect x="0.5" y="63.5" width="467" height="55" fill="white" />
<circle cx="24" cy="91" r="7" fill="#F3F4FA" />
<rect x="40" y="83" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 88L85.5 91L82.5 94" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="83" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="63.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="118.5" width="467" height="55" fill="white" />
<circle cx="24" cy="146" r="7" fill="#F3F4FA" />
<rect x="40" y="138" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 143L85.5 146L82.5 149" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="138" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="118.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="173.5" width="467" height="55" fill="white" />
<circle cx="24" cy="201" r="7" fill="#F3F4FA" />
<rect x="40" y="193" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 198L85.5 201L82.5 204" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="193" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="173.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="228.5" width="467" height="55" fill="white" />
<circle cx="24" cy="256" r="7" fill="#F3F4FA" />
<rect x="40" y="248" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 253L85.5 256L82.5 259" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="248" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="228.5" width="467" height="55" stroke="#E1E3ED" />
</g>
<rect x="0.5" y="0.5" width="467" height="283" rx="5.5" stroke="#E1E3ED" />
<defs>
<clipPath id="clip0_918_2840">
<rect width="468" height="284" rx="6" fill="white" />
</clipPath>
<clipPath id="clip1_918_2840">
<rect x="217" y="20" width="39" height="24" rx="4" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,52 @@
<svg viewBox="0 0 468 284" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_918_6671)">
<rect x="0.5" y="0.5" width="467" height="63" fill="#F3F4FA" />
<circle cx="23" cy="32" r="7" fill="#D0D2E0" />
<rect x="38" y="24" width="227" height="16" rx="8" fill="#E1E3ED" />
<rect x="333.5" y="16.5" width="118" height="31" rx="3.5" fill="white" />
<rect x="333.5" y="16.5" width="118" height="31" rx="3.5" stroke="#E1E3ED" />
<path
d="M356.322 32.424L349.765 36.5219C349.432 36.73 349 36.4906 349 36.0979V27.9021C349 27.5094 349.432 27.27 349.765 27.4781L356.322 31.576C356.635 31.7718 356.635 32.2282 356.322 32.424Z"
fill="#D0D2E0" stroke="#4956E3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M369.909 37V27.1357H373.737C375.754 27.1357 377.025 28.3047 377.025 30.1572V30.1709C377.025 31.5107 376.294 32.5771 375.111 32.9805L377.319 37H375.556L373.546 33.2129H371.44V37H369.909ZM371.44 31.9551H373.587C374.77 31.9551 375.446 31.3057 375.446 30.1846V30.1709C375.446 29.0771 374.722 28.4209 373.546 28.4209H371.44V31.9551ZM380.778 37.1436C379.199 37.1436 378.297 36.125 378.297 34.4707V29.8086H379.773V34.1836C379.773 35.2705 380.279 35.8721 381.305 35.8721C382.344 35.8721 383.014 35.127 383.014 34.0059V29.8086H384.497V37H383.014V35.9199H382.979C382.604 36.6445 381.872 37.1436 380.778 37.1436ZM385.96 37V29.8086H387.437V30.8955H387.471C387.847 30.1641 388.585 29.6719 389.672 29.6719C391.251 29.6719 392.16 30.6904 392.16 32.3447V37H390.677V32.625C390.677 31.5449 390.171 30.9365 389.146 30.9365C388.106 30.9365 387.437 31.6885 387.437 32.8096V37H385.96ZM396.863 37V30.9844H395.872V29.8086H396.863V29.043C396.863 27.6484 397.52 26.9922 398.982 26.9922C399.283 26.9922 399.611 27.0195 399.81 27.0537V28.1475C399.666 28.127 399.481 28.1133 399.297 28.1133C398.634 28.1133 398.319 28.4346 398.319 29.0703V29.8086H399.782V30.9844H398.347V37H396.863ZM402.66 37.1299C401.225 37.1299 400.261 36.248 400.261 34.9561V34.9424C400.261 33.6914 401.231 32.9258 402.934 32.8232L404.889 32.707V32.167C404.889 31.374 404.376 30.8955 403.46 30.8955C402.605 30.8955 402.079 31.2988 401.956 31.873L401.942 31.9346H400.548L400.555 31.8594C400.657 30.6221 401.73 29.6719 403.501 29.6719C405.258 29.6719 406.372 30.6016 406.372 32.0439V37H404.889V35.8652H404.861C404.444 36.6377 403.61 37.1299 402.66 37.1299ZM401.751 34.9219C401.751 35.5508 402.271 35.9473 403.063 35.9473C404.103 35.9473 404.889 35.2432 404.889 34.3066V33.7461L403.132 33.8555C402.243 33.9102 401.751 34.2998 401.751 34.9082V34.9219ZM408.607 28.7012C408.129 28.7012 407.746 28.3184 407.746 27.8535C407.746 27.3818 408.129 26.999 408.607 26.999C409.093 26.999 409.469 27.3818 409.469 27.8535C409.469 28.3184 409.093 28.7012 408.607 28.7012ZM407.869 37V29.8086H409.346V37H407.869ZM410.925 37V27.1357H412.401V37H410.925ZM416.366 37.1436C414.787 37.1436 413.885 36.125 413.885 34.4707V29.8086H415.361V34.1836C415.361 35.2705 415.867 35.8721 416.893 35.8721C417.932 35.8721 418.602 35.127 418.602 34.0059V29.8086H420.085V37H418.602V35.9199H418.567C418.191 36.6445 417.46 37.1436 416.366 37.1436ZM421.548 37V29.8086H423.024V31.0391H423.059C423.291 30.1982 423.893 29.6719 424.713 29.6719C424.925 29.6719 425.109 29.7061 425.226 29.7266V31.1006C425.109 31.0527 424.85 31.0186 424.562 31.0186C423.612 31.0186 423.024 31.6406 423.024 32.7139V37H421.548ZM428.896 37.1436C426.784 37.1436 425.506 35.7012 425.506 33.4316V33.4248C425.506 31.1758 426.805 29.6719 428.821 29.6719C430.838 29.6719 432.075 31.1211 432.075 33.2812V33.7803H426.982C427.01 35.1406 427.755 35.9336 428.931 35.9336C429.806 35.9336 430.387 35.4824 430.571 34.9424L430.592 34.8877H431.993L431.979 34.9629C431.747 36.1045 430.64 37.1436 428.896 37.1436ZM428.828 30.8818C427.871 30.8818 427.133 31.5312 427.003 32.7344H430.612C430.489 31.4902 429.792 30.8818 428.828 30.8818ZM435.917 37.1436C434.119 37.1436 433.066 36.2549 432.916 34.9424L432.909 34.8809H434.372L434.386 34.9492C434.522 35.6123 435.015 36.002 435.924 36.002C436.812 36.002 437.346 35.6328 437.346 35.0518V35.0449C437.346 34.5801 437.086 34.3135 436.313 34.1289L435.138 33.8623C433.771 33.5479 433.094 32.8916 433.094 31.8457V31.8389C433.094 30.5537 434.215 29.6719 435.869 29.6719C437.571 29.6719 438.597 30.6221 438.672 31.8457L438.679 31.9277H437.291L437.284 31.8799C437.195 31.251 436.703 30.8135 435.869 30.8135C435.076 30.8135 434.577 31.1895 434.577 31.7637V31.7705C434.577 32.2148 434.871 32.5156 435.644 32.7002L436.812 32.9668C438.282 33.3086 438.843 33.8896 438.843 34.9219V34.9287C438.843 36.2412 437.612 37.1436 435.917 37.1436Z"
fill="#4956E3" />
<rect x="332" y="15" width="121" height="34" rx="5" stroke="#A06CE4" stroke-width="2" />
<rect x="0.5" y="0.5" width="467" height="63" stroke="#E1E3ED" />
<rect width="468" height="221" transform="translate(0 63)" fill="white" />
<rect x="0.5" y="63.5" width="467" height="55" fill="white" />
<circle cx="24" cy="91" r="7" fill="#F3F4FA" />
<rect x="40" y="83" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 88L85.5 91L82.5 94" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="83" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="63.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="118.5" width="467" height="55" fill="white" />
<circle cx="24" cy="146" r="7" fill="#F3F4FA" />
<rect x="40" y="138" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 143L85.5 146L82.5 149" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="138" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="118.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="173.5" width="467" height="55" fill="white" />
<circle cx="24" cy="201" r="7" fill="#F3F4FA" />
<rect x="40" y="193" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 198L85.5 201L82.5 204" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="193" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="173.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="228.5" width="467" height="55" fill="white" />
<circle cx="24" cy="256" r="7" fill="#F3F4FA" />
<rect x="40" y="248" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 253L85.5 256L82.5 259" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="248" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="228.5" width="467" height="55" stroke="#E1E3ED" />
</g>
<rect x="0.5" y="0.5" width="467" height="283" rx="5.5" stroke="#E1E3ED" />
<defs>
<clipPath id="clip0_918_6671">
<rect width="468" height="284" rx="6" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,91 @@
<svg viewBox="0 0 468 284" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_918_3488)">
<rect width="468" height="64" fill="#F3F4FA" />
<circle cx="23" cy="32" r="7" fill="#D0D2E0" />
<rect x="38" y="24" width="227" height="16" rx="8" fill="#E1E3ED" />
<rect x="347" y="20" width="105" height="24" rx="12" fill="#E1E3ED" />
<rect width="468" height="221" transform="translate(0 63)" fill="white" />
<circle cx="24" cy="91" r="7" fill="#E45770" />
<path d="M22 89L26 93M26 89L22 93" stroke="white" stroke-width="2" stroke-linecap="round" />
<path
d="M40.1953 97L44.3906 85.7266H45.7812L49.9688 97H48.4922L47.3516 93.7734H42.8125L41.6719 97H40.1953ZM45.0703 87.4141L43.2422 92.5781H46.9297L45.1016 87.4141H45.0703ZM53.5938 97.1562C51.8125 97.1562 50.7812 96 50.7812 94.1484V88.875H52.1406V93.9062C52.1406 95.2266 52.7578 95.9531 54.0078 95.9531C55.2891 95.9531 56.125 95.0391 56.125 93.6562V88.875H57.4844V97H56.125V95.8438H56.0938C55.6562 96.6016 54.8281 97.1562 53.5938 97.1562ZM61.8984 97.1562C60.4062 97.1562 59.6719 96.4844 59.6719 94.9297V90H58.4844V88.875H59.6719V86.6797H61.0781V88.875H62.625V90H61.0781V94.9219C61.0781 95.7891 61.4609 96.0312 62.1875 96.0312C62.3516 96.0312 62.5078 96.0078 62.625 96V97.1016C62.4531 97.125 62.1641 97.1562 61.8984 97.1562ZM64.1562 97V85.7266H65.5156V90.1719H65.5469C65.9844 89.2578 66.8672 88.7188 68.0781 88.7188C69.8047 88.7188 70.9844 90.0547 70.9844 92.0234V97H69.625V92.2578C69.625 90.7891 68.875 89.9219 67.6094 89.9219C66.3516 89.9219 65.5156 90.875 65.5156 92.2578V97H64.1562Z"
fill="#5A5F7A" />
<path d="M82.5 88L85.5 91L82.5 94" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96.5" y="75.5" width="70" height="31" rx="3.5" fill="white" />
<rect x="96.5" y="75.5" width="70" height="31" rx="3.5" stroke="#E1E3ED" />
<path d="M123 86C123 84.8954 122.105 84 121 84H111C109.895 84 109 84.8954 109 86V87H123V86Z" fill="#D0D2E0" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M123 86C123 84.8954 122.105 84 121 84H111C109.895 84 109 84.8954 109 86V87H123V86Z" fill="#D0D2E0" />
<path
d="M109 87V96C109 97.1046 109.895 98 111 98H121C122.105 98 123 97.1046 123 96V87M109 87V86C109 84.8954 109.895 84 111 84H121C122.105 84 123 84.8954 123 86V87M109 87H123"
stroke="#4956E3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M112.5 90C112.224 90 112 90.2239 112 90.5C112 90.7761 112.224 91 112.5 91V90ZM113.5 91H114V90H113.5V91ZM112.5 92C112.224 92 112 92.2239 112 92.5C112 92.7761 112.224 93 112.5 93V92ZM114 93H114.5V92H114V93ZM112.5 94C112.224 94 112 94.2239 112 94.5C112 94.7761 112.224 95 112.5 95V94ZM115.5 95H116V94H115.5V95ZM115.5 92H115V93H115.5V92ZM117 93C117.276 93 117.5 92.7761 117.5 92.5C117.5 92.2239 117.276 92 117 92V93ZM117 94H116.5V95H117V94ZM119 95C119.276 95 119.5 94.7761 119.5 94.5C119.5 94.2239 119.276 94 119 94V95ZM115 90H114.5V91H115V90ZM116 91H116.5V90H116V91ZM117.5 90H117V91H117.5V90ZM119.5 91C119.776 91 120 90.7761 120 90.5C120 90.2239 119.776 90 119.5 90V91ZM112.5 91H113.5V90H112.5V91ZM112.5 93H114V92H112.5V93ZM112.5 95H115.5V94H112.5V95ZM115.5 93H117V92H115.5V93ZM117 95H119V94H117V95ZM115 91H116V90H115V91ZM117.5 91H119.5V90H117.5V91Z"
fill="#1B1E2E" />
<path
d="M132.909 96V86.1357H134.44V94.6807H139.034V96H132.909ZM143.081 96.1436C141.017 96.1436 139.67 94.7148 139.67 92.4043V92.3906C139.67 90.0938 141.03 88.6719 143.074 88.6719C145.125 88.6719 146.492 90.0869 146.492 92.3906V92.4043C146.492 94.7217 145.139 96.1436 143.081 96.1436ZM143.088 94.9062C144.243 94.9062 144.981 93.9902 144.981 92.4043V92.3906C144.981 90.8184 144.229 89.9092 143.074 89.9092C141.939 89.9092 141.181 90.8184 141.181 92.3906V92.4043C141.181 93.9971 141.933 94.9062 143.088 94.9062ZM150.785 98.5361C148.939 98.5361 147.771 97.6816 147.552 96.5811L147.545 96.5195H149.008L149.035 96.5742C149.233 97.0322 149.855 97.3467 150.778 97.3467C151.954 97.3467 152.604 96.7178 152.604 95.7129V94.7285H152.569C152.159 95.5078 151.339 96.0068 150.307 96.0068C148.502 96.0068 147.312 94.5918 147.312 92.3496V92.3428C147.312 90.0869 148.516 88.6719 150.341 88.6719C151.353 88.6719 152.146 89.2188 152.569 90.0322H152.604V88.8086H154.087V95.8018C154.087 97.4424 152.815 98.5361 150.785 98.5361ZM150.724 94.8037C151.852 94.8037 152.604 93.8535 152.604 92.3701V92.3633C152.604 90.8867 151.845 89.9365 150.724 89.9365C149.555 89.9365 148.823 90.8799 148.823 92.3633V92.3701C148.823 93.874 149.555 94.8037 150.724 94.8037Z"
fill="#4956E3" />
<rect x="95" y="74" width="73" height="34" rx="5" stroke="#A06CE4" stroke-width="2" />
<rect x="175.5" y="75.5" width="117" height="31" rx="3.5" fill="white" />
<rect x="175.5" y="75.5" width="117" height="31" rx="3.5" stroke="#E1E3ED" />
<g clip-path="url(#clip1_918_3488)">
<path
d="M188 97C188 97.5523 188.448 98 189 98H201C201.552 98 202 97.5523 202 97V95L199.5 92.5L197 95L192.5 90.5L188 95V97Z"
fill="#D0D2E0" />
<path
d="M199 88C199 88.5523 198.552 89 198 89C197.448 89 197 88.5523 197 88C197 87.4477 197.448 87 198 87C198.552 87 199 87.4477 199 88Z"
fill="#D0D2E0" />
<path
d="M192.5 90.5L193.207 89.7929C192.817 89.4024 192.183 89.4024 191.793 89.7929L192.5 90.5ZM197 95L196.293 95.7071C196.683 96.0976 197.317 96.0976 197.707 95.7071L197 95ZM199.5 92.5L200.207 91.7929C199.817 91.4024 199.183 91.4024 198.793 91.7929L199.5 92.5ZM201 83H189V85H201V83ZM189 97V95H187V97H189ZM189 95V85H187V95H189ZM188.707 95.7071L193.207 91.2071L191.793 89.7929L187.293 94.2929L188.707 95.7071ZM191.793 91.2071L196.293 95.7071L197.707 94.2929L193.207 89.7929L191.793 91.2071ZM197.707 95.7071L200.207 93.2071L198.793 91.7929L196.293 94.2929L197.707 95.7071ZM203 97V95H201V97H203ZM203 95V85H201V95H203ZM198.793 93.2071L201.293 95.7071L202.707 94.2929L200.207 91.7929L198.793 93.2071ZM189 99H201V97H189V99ZM198 88V90C199.105 90 200 89.1046 200 88H198ZM198 88H196C196 89.1046 196.895 90 198 90V88ZM198 88V86C196.895 86 196 86.8954 196 88H198ZM198 88H200C200 86.8954 199.105 86 198 86V88ZM201 85V85H203C203 83.8954 202.105 83 201 83V85ZM201 97V99C202.105 99 203 98.1046 203 97H201ZM189 83C187.895 83 187 83.8954 187 85H189L189 85V83ZM187 97C187 98.1046 187.895 99 189 99V97H187Z"
fill="#4956E3" />
</g>
<path
d="M215.272 96.1641C213.058 96.1641 211.595 95.1113 211.472 93.375L211.465 93.2725H212.955L212.969 93.3613C213.105 94.2705 214.015 94.8379 215.334 94.8379C216.653 94.8379 217.487 94.2432 217.487 93.3203V93.3135C217.487 92.5205 216.947 92.0898 215.642 91.8027L214.568 91.5771C212.634 91.167 211.697 90.2783 211.697 88.8154V88.8086C211.704 87.127 213.188 85.9717 215.272 85.9717C217.33 85.9717 218.738 87.0928 218.841 88.7471L218.848 88.8633H217.357L217.351 88.7676C217.214 87.8516 216.421 87.2979 215.252 87.2979C214.028 87.3047 213.249 87.8857 213.249 88.7471V88.7539C213.249 89.4922 213.81 89.9434 215.04 90.21L216.12 90.4355C218.157 90.8662 219.032 91.6934 219.032 93.2178V93.2246C219.032 95.0225 217.61 96.1641 215.272 96.1641ZM223.325 96.1436C221.227 96.1436 219.914 94.7012 219.914 92.3975V92.3906C219.914 90.1143 221.254 88.6719 223.305 88.6719C225.157 88.6719 226.278 89.8613 226.401 91.2148L226.408 91.2627H225L224.986 91.208C224.829 90.5039 224.282 89.9092 223.318 89.9092C222.17 89.9092 221.425 90.8662 221.425 92.4043V92.4111C221.425 93.9834 222.184 94.9062 223.325 94.9062C224.234 94.9062 224.815 94.3799 224.993 93.6006L225 93.5459H226.422L226.415 93.5938C226.258 95.0361 225.055 96.1436 223.325 96.1436ZM227.468 96V88.8086H228.944V90.0391H228.979C229.211 89.1982 229.812 88.6719 230.633 88.6719C230.845 88.6719 231.029 88.7061 231.146 88.7266V90.1006C231.029 90.0527 230.77 90.0186 230.482 90.0186C229.532 90.0186 228.944 90.6406 228.944 91.7139V96H227.468ZM234.816 96.1436C232.704 96.1436 231.426 94.7012 231.426 92.4316V92.4248C231.426 90.1758 232.725 88.6719 234.741 88.6719C236.758 88.6719 237.995 90.1211 237.995 92.2812V92.7803H232.902C232.93 94.1406 233.675 94.9336 234.851 94.9336C235.726 94.9336 236.307 94.4824 236.491 93.9424L236.512 93.8877H237.913L237.899 93.9629C237.667 95.1045 236.56 96.1436 234.816 96.1436ZM234.748 89.8818C233.791 89.8818 233.053 90.5312 232.923 91.7344H236.532C236.409 90.4902 235.712 89.8818 234.748 89.8818ZM242.213 96.1436C240.101 96.1436 238.822 94.7012 238.822 92.4316V92.4248C238.822 90.1758 240.121 88.6719 242.138 88.6719C244.154 88.6719 245.392 90.1211 245.392 92.2812V92.7803H240.299C240.326 94.1406 241.071 94.9336 242.247 94.9336C243.122 94.9336 243.703 94.4824 243.888 93.9424L243.908 93.8877H245.31L245.296 93.9629C245.063 95.1045 243.956 96.1436 242.213 96.1436ZM242.145 89.8818C241.188 89.8818 240.449 90.5312 240.319 91.7344H243.929C243.806 90.4902 243.108 89.8818 242.145 89.8818ZM246.54 96V88.8086H248.017V89.8955H248.051C248.427 89.1641 249.165 88.6719 250.252 88.6719C251.831 88.6719 252.74 89.6904 252.74 91.3447V96H251.257V91.625C251.257 90.5449 250.751 89.9365 249.726 89.9365C248.687 89.9365 248.017 90.6885 248.017 91.8096V96H246.54ZM256.862 96.1436C255.064 96.1436 254.012 95.2549 253.861 93.9424L253.854 93.8809H255.317L255.331 93.9492C255.468 94.6123 255.96 95.002 256.869 95.002C257.758 95.002 258.291 94.6328 258.291 94.0518V94.0449C258.291 93.5801 258.031 93.3135 257.259 93.1289L256.083 92.8623C254.716 92.5479 254.039 91.8916 254.039 90.8457V90.8389C254.039 89.5537 255.16 88.6719 256.814 88.6719C258.517 88.6719 259.542 89.6221 259.617 90.8457L259.624 90.9277H258.236L258.229 90.8799C258.141 90.251 257.648 89.8135 256.814 89.8135C256.021 89.8135 255.522 90.1895 255.522 90.7637V90.7705C255.522 91.2148 255.816 91.5156 256.589 91.7002L257.758 91.9668C259.228 92.3086 259.788 92.8896 259.788 93.9219V93.9287C259.788 95.2412 258.558 96.1436 256.862 96.1436ZM260.991 96V86.1357H262.468V89.9912H262.502C262.885 89.1572 263.657 88.6719 264.73 88.6719C266.269 88.6719 267.28 89.8203 267.28 91.5566V96H265.804V91.8369C265.804 90.6475 265.202 89.9365 264.163 89.9365C263.145 89.9365 262.468 90.7158 262.468 91.8369V96H260.991ZM271.806 96.1436C269.741 96.1436 268.395 94.7148 268.395 92.4043V92.3906C268.395 90.0938 269.755 88.6719 271.799 88.6719C273.85 88.6719 275.217 90.0869 275.217 92.3906V92.4043C275.217 94.7217 273.863 96.1436 271.806 96.1436ZM271.812 94.9062C272.968 94.9062 273.706 93.9902 273.706 92.4043V92.3906C273.706 90.8184 272.954 89.9092 271.799 89.9092C270.664 89.9092 269.905 90.8184 269.905 92.3906V92.4043C269.905 93.9971 270.657 94.9062 271.812 94.9062ZM278.881 96.1436C277.459 96.1436 276.775 95.542 276.775 94.1064V89.9844H275.743V88.8086H276.775V86.9355H278.286V88.8086H279.633V89.9844H278.286V94.0176C278.286 94.749 278.614 94.9678 279.236 94.9678C279.394 94.9678 279.523 94.9541 279.633 94.9404V96.082C279.462 96.1094 279.182 96.1436 278.881 96.1436Z"
fill="#4956E3" />
<rect x="174" y="74" width="120" height="34" rx="5" stroke="#A06CE4" stroke-width="2" />
<rect x="301.5" y="75.5" width="82" height="31" rx="3.5" fill="white" />
<rect x="301.5" y="75.5" width="82" height="31" rx="3.5" stroke="#E1E3ED" />
<path
d="M323 86H316C314.895 86 314 86.8954 314 88V94C314 95.1046 314.895 96 316 96H323C324.105 96 325 95.1046 325 94V93.5L328 95V87L325 88.5V88C325 86.8954 324.105 86 323 86Z"
fill="#C5C9FD" stroke="#4956E3" stroke-width="2" stroke-linejoin="round" />
<g style="mix-blend-mode:darken">
<path d="M324.5 88L324.5 94" stroke="#6470F3" stroke-linecap="round" stroke-linejoin="round" />
</g>
<path
d="M340.691 96L337.178 86.1357H338.825L341.519 94.2979H341.553L344.246 86.1357H345.894L342.38 96H340.691ZM347.432 87.7012C346.953 87.7012 346.57 87.3184 346.57 86.8535C346.57 86.3818 346.953 85.999 347.432 85.999C347.917 85.999 348.293 86.3818 348.293 86.8535C348.293 87.3184 347.917 87.7012 347.432 87.7012ZM346.693 96V88.8086H348.17V96H346.693ZM352.381 96.1436C350.549 96.1436 349.373 94.6943 349.373 92.4043V92.3975C349.373 90.1074 350.562 88.6719 352.367 88.6719C353.386 88.6719 354.206 89.1846 354.637 90.0322H354.664V86.1357H356.147V96H354.664V94.7832H354.637C354.206 95.624 353.413 96.1436 352.381 96.1436ZM352.771 94.8721C353.885 94.8721 354.671 93.9014 354.671 92.4043V92.3975C354.671 90.9072 353.878 89.9365 352.771 89.9365C351.608 89.9365 350.884 90.8799 350.884 92.3975V92.4043C350.884 93.9355 351.602 94.8721 352.771 94.8721ZM360.734 96.1436C358.622 96.1436 357.344 94.7012 357.344 92.4316V92.4248C357.344 90.1758 358.643 88.6719 360.659 88.6719C362.676 88.6719 363.913 90.1211 363.913 92.2812V92.7803H358.82C358.848 94.1406 359.593 94.9336 360.769 94.9336C361.644 94.9336 362.225 94.4824 362.409 93.9424L362.43 93.8877H363.831L363.817 93.9629C363.585 95.1045 362.478 96.1436 360.734 96.1436ZM360.666 89.8818C359.709 89.8818 358.971 90.5312 358.841 91.7344H362.45C362.327 90.4902 361.63 89.8818 360.666 89.8818ZM368.151 96.1436C366.087 96.1436 364.74 94.7148 364.74 92.4043V92.3906C364.74 90.0938 366.101 88.6719 368.145 88.6719C370.195 88.6719 371.562 90.0869 371.562 92.3906V92.4043C371.562 94.7217 370.209 96.1436 368.151 96.1436ZM368.158 94.9062C369.313 94.9062 370.052 93.9902 370.052 92.4043V92.3906C370.052 90.8184 369.3 89.9092 368.145 89.9092C367.01 89.9092 366.251 90.8184 366.251 92.3906V92.4043C366.251 93.9971 367.003 94.9062 368.158 94.9062Z"
fill="#4956E3" />
<rect x="300" y="74" width="85" height="34" rx="5" stroke="#A06CE4" stroke-width="2" />
<rect x="0.5" y="63.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="118.5" width="467" height="55" fill="white" />
<circle cx="24" cy="146" r="7" fill="#F3F4FA" />
<rect x="40" y="138" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 143L85.5 146L82.5 149" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="138" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="118.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="173.5" width="467" height="55" fill="white" />
<circle cx="24" cy="201" r="7" fill="#F3F4FA" />
<rect x="40" y="193" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 198L85.5 201L82.5 204" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="193" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="173.5" width="467" height="55" stroke="#E1E3ED" />
<rect x="0.5" y="228.5" width="467" height="55" fill="white" />
<circle cx="24" cy="256" r="7" fill="#F3F4FA" />
<rect x="40" y="248" width="32" height="16" rx="8" fill="#F3F4FA" />
<path d="M82.5 253L85.5 256L82.5 259" stroke="#D0D2E0" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<rect x="96" y="248" width="284" height="16" rx="8" fill="#F3F4FA" />
<rect x="0.5" y="228.5" width="467" height="55" stroke="#E1E3ED" />
</g>
<rect x="0.5" y="0.5" width="467" height="283" rx="5.5" stroke="#E1E3ED" />
<defs>
<clipPath id="clip0_918_3488">
<rect width="468" height="284" rx="6" fill="white" />
</clipPath>
<clipPath id="clip1_918_3488">
<rect width="16" height="16" fill="white" transform="translate(187 83)" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -14,19 +14,19 @@ describe('initial', () => {
})
describe('testIsolationBlankPage', () => {
it('works', () => {
beforeEach(() => {
getContainerEl()!.innerHTML = testIsolationBlankPage()
cy.get('[data-cy="cypress-logo"]')
cy.get('[data-cy="text"]').should('have.text', 'Default blank page')
cy.get('[data-cy="subtext"]').should('have.text', 'This page was cleared by navigating to about:blank.All active session data (cookies, localStorage and sessionStorage) across all domains are cleared.')
})
it('works', () => {
cy.percySnapshot()
})
it('works with small viewport', () => {
cy.viewport(200, 500)
getContainerEl()!.innerHTML = testIsolationBlankPage()
cy.percySnapshot()
})
@@ -35,13 +35,15 @@ describe('testIsolationBlankPage', () => {
describe('visitFailure', () => {
it('works', () => {
getContainerEl()!.innerHTML = visitFailure({ url: 'http://foo.cypress.io' })
cy.percySnapshot()
})
it('works with details', () => {
getContainerEl()!.innerHTML = visitFailure({ url: 'http://foo.cypress.io', status: 404, statusText: 'Not Found', contentType: 'text/html' })
cy.get('p').contains('Sorry, we could not load:')
cy.get('a').contains('http://foo.cypress.io').should('have.attr', 'href', 'http://foo.cypress.io')
cy.get('p').contains('404 - Not Found (text/html)')
cy.percySnapshot()
})
})

View File

@@ -10,48 +10,33 @@
leave-active-class="transition duration-300 ease-in absolute"
leave-to-class="opacity-0 absolute"
>
<component
:is="current.component"
v-bind="current.props"
<slot
:key="step"
name="default"
:step="step"
:total-steps="steps.length"
:increment-step="incrementStep"
:decrement-step="decrementStep"
:go-back="decrement"
:go-forward="increment"
:reset="reset"
/>
</transition>
</div>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { computed } from 'vue'
import type { Component } from 'vue'
import { ref } from 'vue'
export type SlideshowStep = {
component: Component
props: Record<string, any>
const step = ref(0)
const decrement = () => {
step.value--
}
const props = defineProps<{
modelValue: number
steps: SlideshowStep[]
}>()
const emit = defineEmits(['update:modelValue', 'slideshowComplete'])
const step = useVModel(props, 'modelValue', emit)
const current = computed(() => props.steps[step.value])
const incrementStep = () => {
const nextStep = step.value + 1
if (nextStep < props.steps.length) {
step.value = nextStep
} else {
step.value = 0
emit('slideshowComplete')
}
const increment = () => {
step.value++
}
const reset = () => {
step.value = 0
}
const decrementStep = () => step.value -= 1
</script>

View File

@@ -9,8 +9,6 @@ describe('<SpecPatterns />', () => {
cy.get('[data-cy="spec-pattern"]').contains('cypress/e2e/**/*.cy.{js,jsx,ts,tsx}')
cy.get('[data-cy="file-match-indicator"]').contains('50 matches')
cy.percySnapshot()
})
it('renders component spec pattern', () => {

View File

@@ -0,0 +1,126 @@
import Promo from './Promo.vue'
import PromoCard from './PromoCard.vue'
import PromoAction from './PromoAction.vue'
import PromoHeader from './PromoHeader.vue'
import { IconActionRestart, IconChevronRightSmall } from '@cypress-design/vue-icon'
import { Promo_PromoSeenDocument } from '../../generated/graphql-test'
describe('<Promo />', () => {
const renderPromo = () => {
const recordEvent = cy.stub().as('recordEvent')
cy.stubMutationResolver(Promo_PromoSeenDocument, (defineResult, args) => {
recordEvent(args)
return defineResult({ recordEvent: true })
})
cy.mount(
<Promo
campaign="_campaign_"
medium="_medium_"
>
{{
header: () => (
<PromoHeader title="Title!">
{{
description: () => (
<h2>Description...</h2>
),
content: () => (
<p>_content_</p>
),
}}
</PromoHeader>
),
cards: ({ step, goForward, reset }) => {
if (step === 0) {
return (
<PromoCard
title="Card #1"
body="Card Description"
>
{{
image: () => (
<div>Image</div>
),
action: () => (
<PromoAction
action={goForward}
left-label="1 of 2"
right-label="Next"
right-icon={IconChevronRightSmall}
/>
),
}}
</PromoCard>
)
}
if (step === 1) {
return (
<PromoCard
title="Card #2"
body="Card Description"
>
{{
image: () => (
<div>Image</div>
),
action: () => (
<PromoAction
action={reset}
right-label="Reset"
left-icon={IconActionRestart}
/>
),
}}
</PromoCard>
)
}
return null
},
}}
</Promo>,
)
}
beforeEach(() => {
renderPromo()
})
it('renders properly on narrow viewport', { viewportWidth: 600 }, () => {
cy.percySnapshot()
})
it('renders properly on wide viewport', { viewportWidth: 1280 }, () => {
cy.percySnapshot()
})
it('records event on initial render', () => {
cy.get('@recordEvent').should('have.been.calledOnce')
cy.get('@recordEvent').should('have.been.calledWith', {
campaign: '_campaign_',
medium: '_medium_',
cohort: null,
messageId: Cypress.sinon.match.string,
})
})
describe('controls', () => {
it('handles `goForward`', () => {
cy.contains('Card #1').should('be.visible')
cy.findByTestId('promo-action-control').click()
cy.contains('Card #2').should('be.visible')
})
it('handles `reset`', () => {
cy.findByTestId('promo-action-control').click()
cy.contains('Card #2').should('be.visible')
cy.findByTestId('promo-action-control').should('contain.text', 'Reset')
cy.findByTestId('promo-action-control').click()
cy.contains('Card #1').should('be.visible')
})
})
})

View File

@@ -0,0 +1,72 @@
<template>
<div class="flex flex-col items-center border border-gray-100 rounded-lg shadow-[0_0_20px_rgba(0,0,0,0.08)]">
<slot name="header" />
<Slideshow>
<template #default="{ step, goBack, goForward, reset }">
<slot
name="cards"
:step="step"
:go-back="goBack"
:go-forward="goForward"
:reset="reset"
/>
</template>
</Slideshow>
</div>
</template>
<script lang="ts" setup>
import Slideshow from '../../components/Slideshow.vue'
import { gql, useMutation, useQuery } from '@urql/vue'
import { nanoid } from 'nanoid'
import { PromoDocument, Promo_PromoSeenDocument } from '../../generated/graphql'
gql`
fragment _Promo on Query {
currentProject {
id
savedState
}
}
`
gql`
query Promo {
..._Promo
}
`
gql`
mutation Promo_PromoSeen($campaign: String!, $messageId: String!, $medium: String!, $cohort: String) {
recordEvent(campaign: $campaign, messageId: $messageId, medium: $medium, cohort: $cohort)
}
`
const props = defineProps<{
campaign: string
medium: string
cohort?: string
instanceId?: string
}>()
const promoSeenMutation = useMutation(Promo_PromoSeenDocument)
const promoInstanceId = props.instanceId || nanoid()
useQuery({ query: PromoDocument })
.then((queryResult) => {
const value = queryResult.data.value
if (value?.currentProject?.savedState) {
// This is the first time the user is seeing the slideshow within this context (props.slideshowCampaign)
promoSeenMutation.executeMutation({
campaign: props.campaign,
medium: props.medium,
cohort: props.cohort ?? null,
messageId: promoInstanceId,
})
}
})
</script>

View File

@@ -0,0 +1,43 @@
import PromoAction from './PromoAction.vue'
import { IconChevronRightSmall, IconActionRestart } from '@cypress-design/vue-icon'
describe('<PromoAction />', () => {
it('left label, right icon', () => {
const action = cy.stub().as('action')
cy.mount(
<PromoAction
action={action}
leftLabel="1 of 3"
rightLabel="Next"
rightIcon={IconChevronRightSmall}
class="m-[8px]"
/>,
)
cy.get('@action').should('not.have.been.called')
cy.findByTestId('promo-action-control').click()
cy.get('@action').should('have.been.calledOnce')
})
it('left icon, right label', () => {
const action = cy.stub().as('action')
cy.mount(
<PromoAction
action={action}
leftIcon={IconActionRestart}
rightLabel="Reset"
class="m-[8px]"
/>,
)
cy.get('@action').should('not.have.been.called')
cy.findByTestId('promo-action-control').click()
cy.get('@action').should('have.been.calledOnce')
})
})

View File

@@ -0,0 +1,47 @@
<template>
<div
data-cy="promo-action"
class="flex flex-row items-center rounded"
>
<div class="text-sm rounded-l bg-gray-50 border border-r-0 border-gray-100 flex flex-row px-[12px] py-[6px] items-center justify-center h-full">
<component
:is="leftIcon"
v-if="leftIcon"
class="icon-dark-gray-500 icon-light-gray-200 my-[2px]"
/>
<span class="text-purple-500 whitespace-nowrap">
{{ leftLabel }}
</span>
</div>
<Button
data-cy="promo-action-control"
variant="outline-light"
size="32"
class="rounded-l-none"
@click="action"
>
{{ rightLabel }}
<component
:is="rightIcon"
v-if="rightIcon"
/>
</Button>
</div>
</template>
<script lang="ts" setup>
import type { Component } from 'vue'
import Button from '@cypress-design/vue-button'
interface PromoActionType {
action?: () => void
leftIcon?: Component
leftLabel?: string
rightLabel?: string
rightIcon?: Component
}
defineProps<PromoActionType>()
</script>

View File

@@ -0,0 +1,54 @@
<template>
<div
class="p-[40px]"
:class="gridClasses"
>
<div>
<h2 class="text-xl font-semibold text-gray-900">
{{ title }}
</h2>
<p class="text-gray-700">
{{ body }}
</p>
<slot name="content" />
</div>
<div
v-if="slots.image"
class="row-end-[span_2] xl:col-start-2"
>
<slot name="image" />
</div>
<div
v-if="slots.action"
class="self-end"
>
<slot name="action" />
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, useSlots } from 'vue'
defineProps<{
title: string
body: string
}>()
const slots = useSlots()
const gridClasses = computed(() => {
const classes = ['grid', 'grid-cols-[480px]', 'gap-y-[16px]']
// If `image` is defined then lay out side-by-side on xl viewport,
// otherwise it should flow vertically
if (slots.image) {
classes.push('xl:grid-cols-[300px_470px]', 'gap-x-[100px]')
} else {
classes.push('xl:grid-cols-[744px]')
}
return classes
})
</script>

View File

@@ -0,0 +1,17 @@
import PromoHeader from './PromoHeader.vue'
import Button from '@cypress-design/vue-button'
describe('<PromoHeader />', () => {
it('renders', () => {
cy.mount(
<PromoHeader
title="I am a test header"
v-slots={{
description: () => <p>Description of this header</p>,
control: () => <Button>Test Button</Button>,
content: () => <div>Test Content</div>,
}}
/>,
)
})
})

View File

@@ -0,0 +1,43 @@
<template>
<div class="flex flex-col bg-gray-50 border-gray-100 py-[16px] px-[24px] rounded-t-[8px] gap-16px items-start w-full">
<div class="flex flex-col xl:flex-row w-full items-start xl:items-center gap-[16px]">
<div class="flex flex-col flex-grow justify-center">
<div
data-cy="promo-header-title"
class="font-md font-medium"
>
{{ title }}
</div>
<div
v-if="slots.description"
data-cy="promo-header-description"
class="text-sm font-normal"
>
<slot name="description" />
</div>
</div>
<div
v-if="slots.control"
>
<slot name="control" />
</div>
</div>
<div
v-if="slots.content"
class="pt-[24px] w-full"
>
<slot name="content" />
</div>
</div>
</template>
<script lang="ts" setup>
import { useSlots } from 'vue'
const slots = useSlots()
withDefaults(defineProps<{
title: string
}>(), {})
</script>

View File

@@ -1,6 +1,6 @@
import { gql, useSubscription } from '@urql/vue'
import { Debug_RelevantRuns_SubscriptionDocument, Sidebar_RelevantRuns_SubscriptionDocument } from '@packages/app/src/generated/graphql'
import { useLoginConnectStore } from '@packages/frontend-shared/src/store/login-connect-store'
import { useUserProjectStatusStore } from '@packages/frontend-shared/src/store/user-project-status-store'
import { computed } from 'vue'
import { uniq } from 'lodash'
@@ -43,10 +43,10 @@ gql`
`
export function useRelevantRun (location: 'SIDEBAR' | 'DEBUG') {
const loginConnectStore = useLoginConnectStore()
const userProjectStatusStore = useUserProjectStatusStore()
const shouldPause = computed(() => {
return !loginConnectStore.project.isProjectConnected
return !userProjectStatusStore.project.isProjectConnected
})
//Switch the subscription query depending on where it was registered from

View File

@@ -0,0 +1,119 @@
import { UseTestingType_ActivateTestingTypeDocument } from '../generated/graphql'
import { useTestingType } from './useTestingType'
import type { FunctionalComponent } from 'vue'
describe('useTestingType', () => {
type ComposableWrapperProps<R> = { useComposable: () => R, callback: (result: R) => void }
const ComposableWrapper: FunctionalComponent<ComposableWrapperProps<unknown>> = <R, >({ useComposable, callback }: ComposableWrapperProps<R>) => {
const result = useComposable()
callback(result)
return <div>Composable</div>
}
const mountComposable = (composable: () => any) => {
const callback = cy.stub().as('callback')
cy.mount({
name: 'composable',
render () {
return (
<ComposableWrapper useComposable={composable} callback={callback} />
)
},
})
return cy.get('@callback').should('have.been.called').then((cb) => {
return cy.wrap(callback.getCall(callback.callCount - 1).args[0]).as('result')
})
}
beforeEach(() => {
const activateTestingTypeStub = cy.stub().as('activateTestingType')
cy.stubMutationResolver(UseTestingType_ActivateTestingTypeDocument, (defineResult, args) => {
activateTestingTypeStub()
return defineResult({ switchTestingTypeAndRelaunch: true })
})
cy.gqlStub.Query.currentProject = {
id: 'abc123',
currentTestingType: 'e2e',
isCTConfigured: false,
isE2EConfigured: false,
} as any
})
it('supplies expected query data', () => {
mountComposable(useTestingType).then((value) => {
const result = value as unknown as ReturnType<typeof useTestingType>
expect(result.activeTestingType.value).to.eql('e2e')
expect(result.isCTConfigured.value).to.eql(false)
expect(result.isE2EConfigured.value).to.eql(false)
expect(result.viewedTestingType.value).to.eql('e2e')
})
})
describe('viewTestingType', () => {
context('target mode is not configured', () => {
beforeEach(() => {
cy.gqlStub.Query.currentProject = {
id: 'abc123',
currentTestingType: 'e2e',
isCTConfigured: false,
} as any
})
it('should toggle viewed mode', () => {
mountComposable(useTestingType).then((value) => {
const result = value as unknown as ReturnType<typeof useTestingType>
expect(result.viewedTestingType.value).to.eql('e2e')
result.viewTestingType('component')
expect(result.viewedTestingType.value).to.eql('component')
})
})
})
context('target mode is configured', () => {
beforeEach(() => {
cy.gqlStub.Query.currentProject = {
id: 'abc123',
currentTestingType: 'e2e',
isE2EConfigured: true,
isCTConfigured: true,
} as any
})
it('should toggle active mode if not active mode', () => {
mountComposable(useTestingType).then((value) => {
const result = value as unknown as ReturnType<typeof useTestingType>
expect(result.viewedTestingType.value).to.eql('e2e')
result.viewTestingType('component')
})
cy.get('@activateTestingType').should('have.been.calledOnce')
})
it('should toggle viewed mode if active mode', () => {
mountComposable(useTestingType).then((value) => {
const result = value as unknown as ReturnType<typeof useTestingType>
expect(result.viewedTestingType.value).to.eql('e2e')
result.viewTestingType('e2e')
})
cy.get('@activateTestingType').should('not.have.been.called')
})
})
})
})

View File

@@ -0,0 +1,72 @@
import { useMutation, useQuery, gql } from '@urql/vue'
import { computed, ref, watchEffect } from 'vue'
import { UseTestingType_TestingTypeDocument, UseTestingType_ActivateTestingTypeDocument } from '../generated/graphql'
gql`
query UseTestingType_TestingType {
currentProject {
id
currentTestingType
isCTConfigured
isE2EConfigured
}
}
`
gql`
mutation UseTestingType_ActivateTestingType($testingType: TestingTypeEnum!) {
switchTestingTypeAndRelaunch(testingType: $testingType)
}
`
export function useTestingType () {
const query = useQuery({ query: UseTestingType_TestingTypeDocument })
const activateTestingTypeMutation = useMutation(UseTestingType_ActivateTestingTypeDocument)
const viewedTestingType = ref<'e2e' | 'component' | null>(null)
const activeTestingType = computed(() => query.data.value?.currentProject?.currentTestingType)
const isCTConfigured = computed(() => query.data.value?.currentProject?.isCTConfigured)
const isE2EConfigured = computed(() => query.data.value?.currentProject?.isE2EConfigured)
const showTestingTypePromo = computed(() => {
// confirm required data has resolved from other computed values
if (isE2EConfigured.value === undefined && isCTConfigured.value === undefined) {
return false
}
return (viewedTestingType.value === 'e2e' && isE2EConfigured.value === false) ||
(viewedTestingType.value === 'component' && isCTConfigured.value === false)
})
// Initialize 'viewed' testing type when query first resolves
watchEffect(() => {
if (!!activeTestingType.value && !viewedTestingType.value) {
viewedTestingType.value = activeTestingType.value
}
})
async function activateTestingType (testingType: 'e2e' | 'component') {
return await activateTestingTypeMutation.executeMutation({ testingType })
}
async function viewTestingType (testingType: 'e2e' | 'component') {
const switchingBackToActiveMode = testingType === activeTestingType.value
const targetModeIsConfigured = testingType === 'e2e' && isE2EConfigured.value || testingType === 'component' && isCTConfigured.value
if (!switchingBackToActiveMode && targetModeIsConfigured) {
await activateTestingType(testingType)
} else {
viewedTestingType.value = testingType
}
}
return {
activeTestingType,
viewedTestingType,
isCTConfigured,
isE2EConfigured,
showTestingTypePromo,
viewTestingType,
activateTestingType,
}
}

View File

@@ -1,10 +1,9 @@
import { DebugSpecListGroupsFragment, DebugSpecListSpecFragment, DebugSpecListTestsFragment, DebugSpecsFragment, DebugSpecsFragmentDoc, UseCohorts_DetermineCohortDocument } from '../generated/graphql-test'
import DebugContainer from './DebugContainer.vue'
import { defaultMessages } from '@cy/i18n'
import { useLoginConnectStore } from '@packages/frontend-shared/src/store/login-connect-store'
import { useUserProjectStatusStore } from '@packages/frontend-shared/src/store/user-project-status-store'
import { specsList } from './utils/DebugMapping'
import { CloudRunStubs, createCloudRun } from '@packages/graphql/test/stubCloudTypes'
import { DEBUG_SLIDESHOW } from './utils/constants'
import type { CloudRun, CloudSpecRun, CloudTestResult } from '@packages/graphql/src/gen/test-cloud-graphql-types.gen'
const DebugSpecVariableTypes = {
@@ -29,19 +28,12 @@ describe('<DebugContainer />', () => {
describe('empty states', () => {
const validateEmptyState = (expectedMessages: string[]) => {
cy.stubMutationResolver(UseCohorts_DetermineCohortDocument, (defineResult) => {
return defineResult({ determineCohort: { __typename: 'Cohort', name: DEBUG_SLIDESHOW.id, cohort: 'A' } })
return defineResult({ determineCohort: { __typename: 'Cohort', name: 'iatr_debug_slideshow', cohort: 'A' } })
})
cy.mountFragment(DebugSpecsFragmentDoc, {
variableTypes: DebugSpecVariableTypes,
variables: defaultVariables,
onResult: (res) => {
if (res.currentProject) {
res.currentProject.savedState = {
debugSlideshowComplete: true,
}
}
},
render: (gqlVal) => <DebugContainer gql={gqlVal} />,
})
@@ -51,65 +43,92 @@ describe('<DebugContainer />', () => {
}
it('shows not logged in', () => {
const loginConnectStore = useLoginConnectStore()
const userProjectStatusStore = useUserProjectStatusStore()
loginConnectStore.setHasInitiallyLoaded()
userProjectStatusStore.setHasInitiallyLoaded()
userProjectStatusStore.setProjectFlag('isUsingGit', true)
validateEmptyState([defaultMessages.debugPage.emptyStates.connectToCypressCloud, defaultMessages.debugPage.emptyStates.debugDirectlyInCypress, defaultMessages.debugPage.emptyStates.notLoggedInTestMessage])
validateEmptyState([defaultMessages.debugPage.emptyStates.connectToCypressCloud, defaultMessages.debugPage.emptyStates.connect.title, defaultMessages.debugPage.emptyStates.connect.description])
cy.findByRole('button', { name: 'Connect to Cypress Cloud' }).should('be.visible')
})
it('is logged in with no project', () => {
const loginConnectStore = useLoginConnectStore()
const userProjectStatusStore = useUserProjectStatusStore()
loginConnectStore.setUserFlag('isLoggedIn', true)
loginConnectStore.setProjectFlag('isProjectConnected', false)
loginConnectStore.setHasInitiallyLoaded()
userProjectStatusStore.setUserFlag('isLoggedIn', true)
userProjectStatusStore.setProjectFlag('isProjectConnected', false)
userProjectStatusStore.setProjectFlag('isUsingGit', true)
userProjectStatusStore.setHasInitiallyLoaded()
validateEmptyState([defaultMessages.debugPage.emptyStates.debugDirectlyInCypress, defaultMessages.debugPage.emptyStates.reviewRerunAndDebug, defaultMessages.debugPage.emptyStates.noProjectTestMessage])
validateEmptyState([defaultMessages.debugPage.emptyStates.connect.title, defaultMessages.debugPage.emptyStates.connect.description])
cy.findByRole('button', { name: 'Connect a Cypress Cloud project' }).should('be.visible')
})
it('has no runs', () => {
const loginConnectStore = useLoginConnectStore()
const userProjectStatusStore = useUserProjectStatusStore()
loginConnectStore.setUserFlag('isLoggedIn', true)
loginConnectStore.setProjectFlag('isProjectConnected', true)
loginConnectStore.setHasInitiallyLoaded()
userProjectStatusStore.setUserFlag('isLoggedIn', true)
userProjectStatusStore.setProjectFlag('isProjectConnected', true)
userProjectStatusStore.setProjectFlag('isUsingGit', true)
userProjectStatusStore.setHasInitiallyLoaded()
cy.mountFragment(DebugSpecsFragmentDoc, {
variableTypes: DebugSpecVariableTypes,
variables: defaultVariables,
render: (gqlVal) => <DebugContainer gql={gqlVal} />,
})
validateEmptyState([defaultMessages.debugPage.emptyStates.recordYourFirstRun, defaultMessages.debugPage.emptyStates.almostThere, defaultMessages.debugPage.emptyStates.noRunsTestMessage])
validateEmptyState([defaultMessages.debugPage.emptyStates.noRuns.title])
cy.findByDisplayValue('npx cypress run --record --key 2aaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa').should('be.visible')
})
it('errors', () => {
const loginConnectStore = useLoginConnectStore()
it('is not using git', () => {
const userProjectStatusStore = useUserProjectStatusStore()
loginConnectStore.setUserFlag('isLoggedIn', true)
loginConnectStore.setProjectFlag('isProjectConnected', true)
loginConnectStore.setHasInitiallyLoaded()
userProjectStatusStore.setUserFlag('isLoggedIn', true)
userProjectStatusStore.setProjectFlag('isProjectConnected', true)
userProjectStatusStore.setProjectFlag('isUsingGit', false)
userProjectStatusStore.setHasInitiallyLoaded()
cy.mountFragment(DebugSpecsFragmentDoc, {
variableTypes: DebugSpecVariableTypes,
variables: defaultVariables,
render: (gqlVal) => <DebugContainer gql={gqlVal} showError={true} />,
render: (gqlVal) => <DebugContainer gql={gqlVal} />,
})
cy.findByTestId('debug-empty').should('not.exist')
cy.findByTestId('debug-alert').should('be.visible')
cy.findByTestId('debug-empty-title').should('contain.text', 'Git repository not detected')
})
it('has no runs for the current branch', () => {
const { setUserFlag, setProjectFlag, cloudStatusMatches, setHasInitiallyLoaded } = useUserProjectStatusStore()
setUserFlag('isLoggedIn', true)
setUserFlag('isMemberOfOrganization', true)
setProjectFlag('isProjectConnected', true)
setProjectFlag('hasNoRecordedRuns', true)
setProjectFlag('hasNonExampleSpec', true)
setProjectFlag('isConfigLoaded', true)
setProjectFlag('isUsingGit', true)
setHasInitiallyLoaded()
cy.mountFragment(DebugSpecsFragmentDoc, {
variableTypes: DebugSpecVariableTypes,
variables: defaultVariables,
render: (gqlVal) => <DebugContainer gql={gqlVal} />,
})
expect(cloudStatusMatches('needsRecordedRun')).equals(true)
cy.contains('No runs found for your branch')
})
})
describe('run states', { viewportWidth: 900 }, () => {
beforeEach(() => {
const loginConnectStore = useLoginConnectStore()
const userProjectStatusStore = useUserProjectStatusStore()
loginConnectStore.setUserFlag('isLoggedIn', true)
loginConnectStore.setProjectFlag('isProjectConnected', true)
loginConnectStore.setHasInitiallyLoaded()
userProjectStatusStore.setUserFlag('isLoggedIn', true)
userProjectStatusStore.setProjectFlag('isProjectConnected', true)
userProjectStatusStore.setProjectFlag('isUsingGit', true)
userProjectStatusStore.setHasInitiallyLoaded()
})
function mountTestRun (runName: string) {
@@ -150,10 +169,10 @@ describe('<DebugContainer />', () => {
it('renders', () => {
mountTestRun('allSkipped')
cy.findByTestId('collapsible').should('be.visible')
cy.contains('h3', 'Incomplete')
cy.contains('The browser server never connected.').should('be.visible')
cy.contains('2 of 3 specs skipped').should('be.visible')
cy.percySnapshot()
})
})
@@ -161,9 +180,9 @@ describe('<DebugContainer />', () => {
it('renders', () => {
mountTestRun('noTests')
cy.findByTestId('collapsible').should('be.visible')
cy.contains('h3', 'Incomplete')
cy.contains('Run has no tests').should('be.visible')
cy.percySnapshot()
})
})
@@ -171,46 +190,37 @@ describe('<DebugContainer />', () => {
it('renders with CI information', () => {
mountTestRun('timedOutWithCi')
cy.findByTestId('collapsible').should('be.visible')
cy.contains('h3', 'Incomplete')
cy.contains('Circle CI #1234').should('have.attr', 'href', 'https://circleci.com').should('be.visible')
cy.contains('Archive this run to remove it').should('be.visible')
cy.percySnapshot()
})
it('renders without CI information', () => {
mountTestRun('timedOutWithoutCi')
cy.findByTestId('collapsible').should('be.visible')
cy.contains('h3', 'Incomplete')
cy.contains('Circle CI #1234').should('not.exist')
cy.contains('Archive this run to remove it').should('be.visible')
cy.percySnapshot()
})
})
context('over limit', () => {
it('handled usage exceeded', () => {
mountTestRun('overLimit')
cy.findByRole('link', { name: 'Contact admin' }).should('be.visible').should('have.attr', 'href', 'http://localhost:3000?utmMedium=Debug+Tab&utmSource=Binary%3A+Launchpad')
cy.percySnapshot()
})
it('handles retention exceeded', () => {
mountTestRun('overLimitRetention')
cy.findByRole('link', { name: 'Contact admin' }).should('be.visible').should('have.attr', 'href', 'http://localhost:3000?utmMedium=Debug+Tab&utmSource=Binary%3A+Launchpad')
cy.percySnapshot()
})
it('does not show passing message if run is hidden', () => {
mountTestRun('overLimitPassed')
cy.contains('Well Done!').should('not.exist')
cy.contains('All your tests passed.').should('not.exist')
cy.findByRole('link', { name: 'Contact admin' }).should('be.visible').should('have.attr', 'href', 'http://localhost:3000?utmMedium=Debug+Tab&utmSource=Binary%3A+Launchpad')
})
})
@@ -229,14 +239,15 @@ describe('<DebugContainer />', () => {
})
describe('when logged in and connected', () => {
let loginConnectStore
let userProjectStatusStore
beforeEach(() => {
loginConnectStore = useLoginConnectStore()
userProjectStatusStore = useUserProjectStatusStore()
loginConnectStore.setUserFlag('isLoggedIn', true)
loginConnectStore.setProjectFlag('isProjectConnected', true)
loginConnectStore.setHasInitiallyLoaded()
userProjectStatusStore.setUserFlag('isLoggedIn', true)
userProjectStatusStore.setProjectFlag('isProjectConnected', true)
userProjectStatusStore.setProjectFlag('isUsingGit', true)
userProjectStatusStore.setHasInitiallyLoaded()
})
it('renders running run', () => {

View File

@@ -4,18 +4,22 @@
<NoInternetConnection v-if="!online">
{{ t('launchpadErrors.noInternet.connectProject') }}
</NoInternetConnection>
<DebugLoading v-else-if="!loginConnectStore.hasInitiallyLoaded || loginConnectStore.project.isProjectConnected && isLoading" />
<DebugError
v-else-if="showError"
/>
<DebugLoading v-else-if="!userProjectStatusStore.hasInitiallyLoaded || userProjectStatusStore.project.isProjectConnected && isLoading" />
<DebugNotLoggedIn
v-else-if="!loginConnectStore.user.isLoggedIn"
v-else-if="!userProjectStatusStore.user.isLoggedIn"
data-cy="debug-empty"
/>
<DebugNoProject
v-else-if="!loginConnectStore.project.isProjectConnected"
v-else-if="!userProjectStatusStore.project.isProjectConnected"
data-cy="debug-empty"
/>
<DebugError
v-else-if="!userProjectStatusStore.project.isUsingGit"
/>
<DebugBranchError
v-else-if="cloudStatusMatches('needsRecordedRun')"
/>
<DebugNoRuns
v-else-if="!run"
data-cy="debug-empty"
@@ -85,7 +89,7 @@
import { gql } from '@urql/vue'
import { computed } from 'vue'
import type { CloudRunStatus, DebugSpecsFragment, TestingTypeEnum } from '../generated/graphql'
import { useLoginConnectStore } from '@packages/frontend-shared/src/store/login-connect-store'
import { useUserProjectStatusStore } from '@packages/frontend-shared/src/store/user-project-status-store'
import NoInternetConnection from '@packages/frontend-shared/src/components/NoInternetConnection.vue'
import DebugLoading from '../debug/empty/DebugLoading.vue'
import DebugPageHeader from './DebugPageHeader.vue'
@@ -97,6 +101,7 @@ import DebugNotLoggedIn from './empty/DebugNotLoggedIn.vue'
import DebugNoProject from './empty/DebugNoProject.vue'
import DebugNoRuns from './empty/DebugNoRuns.vue'
import DebugError from './empty/DebugError.vue'
import DebugBranchError from './empty/DebugBranchError.vue'
import DebugSpecLimitBanner from './DebugSpecLimitBanner.vue'
import DebugRunNavigation from './DebugRunNavigation.vue'
import { specsList } from './utils/DebugMapping'
@@ -184,14 +189,11 @@ fragment DebugSpecs on Query {
}
currentTestingType
}
..._DebugEmptyView
}
`
const props = withDefaults(defineProps<{
gql?: DebugSpecsFragment
// This prop is just to stub the error state for now
showError?: boolean
isLoading?: boolean
commitsAhead?: number
online?: boolean
@@ -205,7 +207,9 @@ const props = withDefaults(defineProps<{
currentCommitInfo: undefined,
})
const loginConnectStore = useLoginConnectStore()
const userProjectStatusStore = useUserProjectStatusStore()
const { cloudStatusMatches } = userProjectStatusStore
const cloudProject = computed(() => {
return props.gql?.currentProject?.cloudProject?.__typename === 'CloudProject'

View File

@@ -123,8 +123,6 @@ describe('<DebugFailedTest/>', () => {
.and('match', /utm_campaign/)
.and('match', /utm_source/)
})
cy.percySnapshot()
})
it('contains multiple titleParts segments', { viewportWidth: 1200 }, () => {
@@ -139,8 +137,6 @@ describe('<DebugFailedTest/>', () => {
))
assertRowContents(multipleTitleParts)
cy.percySnapshot()
})
it('tests multiple groups', { viewportWidth: 1200 }, () => {

View File

@@ -98,7 +98,6 @@ describe('<DebugPageHeader />', {
})
cy.findByTestId(`debug-runNumber-${status}`).should('be.visible')
cy.percySnapshot()
})
})

View File

@@ -9,8 +9,6 @@ describe('<DebugPendingRunCounts />', () => {
)
cy.contains('2 of 20').should('be.visible')
cy.percySnapshot()
})
it('renders counts of zeros input is undefined', () => {
@@ -21,7 +19,5 @@ describe('<DebugPendingRunCounts />', () => {
)
cy.contains('0 of 0').should('be.visible')
cy.percySnapshot()
})
})

View File

@@ -4,9 +4,8 @@ describe('<DebugPendingRunSplash />', () => {
it('renders as expected', () => {
cy.mount(<DebugPendingRunSplash/>)
cy.contains('Failures will be displayed here')
cy.percySnapshot()
cy.findByTestId('title').contains('Testing in progress...')
cy.findByTestId('splash-subtitle').contains('Failures will be displayed here')
})
it('renders scheduled to complete message', () => {
@@ -14,7 +13,5 @@ describe('<DebugPendingRunSplash />', () => {
cy.contains('Scheduled to complete...')
cy.findByTestId('splash-subtitle').should('not.exist')
cy.percySnapshot()
})
})

View File

@@ -17,8 +17,6 @@ describe('<DebugResults />', () => {
cy.get(`[title=${defaultMessages.runs.results.pending}]`).should('contain.text', cloudRun.totalPending)
})
})
cy.percySnapshot()
})
})

View File

@@ -1,6 +1,6 @@
<template>
<div
class="flex gap-[8px] items-center"
class="flex gap-[8px] items-center bg-transparent"
data-cy="debug-results-holder"
>
<ResultCounts

View File

@@ -241,8 +241,6 @@ describe('<DebugRunNavigation />', () => {
cy.contains('We found more than 100 runs.').should('be.visible')
cy.findByRole('link', { name: 'Go to Cypress Cloud to see all runs' }).should('be.visible').should('have.attr', 'href', 'https://cloud.cypress.io/projects/ypt4pf/?utm_medium=Debug+Tab&utm_campaign=Run+Navigation+Limit&utm_source=Binary%3A+Launchpad')
cy.percySnapshot()
})
describe('Switch to latest run button', () => {

Some files were not shown because too many files have changed in this diff Show More