feat(e2e): run the suite against vue-starter-template, and fix what it exposed - #2677
Maciek Kucmus (mkucmus) wants to merge 34 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Adds non-gating CI coverage for vue-starter-template and adapts the E2E suite to run independently of demo-store content.
Changes:
- Adds a scheduled and PR-triggered starter-template E2E workflow.
- Retags and updates Playwright tests, page objects, selectors, and synchronization.
- Fixes checkout guest validation and listing-filter URL ordering.
Reviewed changes
Copilot reviewed 46 out of 46 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
templates/vue-starter-template/app/pages/wishlist.vue |
Adds empty-wishlist selector. |
templates/vue-starter-template/app/pages/checkout/index.vue |
Fixes guest validation and adds selectors. |
templates/vue-starter-template/app/components/wishlist/ProductTile.vue |
Adds wishlist product selectors. |
templates/vue-starter-template/app/components/LoginForm.vue |
Adds login selectors. |
templates/vue-starter-template/app/components/layout/MiniCart.vue |
Adds mini-cart selectors. |
templates/vue-starter-template/app/components/layout/header/Search.vue |
Adds search selector. |
templates/vue-starter-template/app/components/layout/Header.vue |
Adds account, wishlist, and cart selectors. |
templates/vue-starter-template/app/components/layout/AccountMenu.vue |
Adds account-link selector. |
templates/vue-starter-template/app/components/checkout/ShippingMethods.vue |
Adds shipping-method selector. |
templates/vue-starter-template/app/components/checkout/ProductTile.vue |
Adds cart product selectors. |
templates/vue-starter-template/app/components/checkout/CustomerBaseInfo.vue |
Adds checkout email selector. |
templates/vue-starter-template/app/components/checkout/CustomerAddress.vue |
Adds address-field selectors. |
templates/vue-starter-template/app/components/account/personal/DataForm.vue |
Adds profile-form selectors. |
templates/vue-starter-template/app/components/account/LoginForm.vue |
Adds registration-navigation selector. |
packages/cms-base-layer/app/components/SwProductListingFilters.vue |
Writes filter URLs before fetching. |
apps/e2e-tests/utils/listing.ts |
Adds shared listing helpers. |
apps/e2e-tests/utils/form.ts |
Adds cross-template form helpers. |
apps/e2e-tests/utils/data-helpers.ts |
Adds unique test emails. |
apps/e2e-tests/tests/search.spec.ts |
Makes search tests content-independent. |
apps/e2e-tests/tests/registrationUser.spec.ts |
Updates registration assertions and data. |
apps/e2e-tests/tests/myAccountTests.spec.ts |
Retags account tests and adjusts timeout. |
apps/e2e-tests/tests/login.spec.ts |
Retags login tests. |
apps/e2e-tests/tests/createOrder.spec.ts |
Adapts order scenarios to starter checkout. |
apps/e2e-tests/tests/checkSearch.spec.ts |
Enables generic search-listing tests. |
apps/e2e-tests/tests/checkProductVariants.spec.ts |
Retags variant coverage. |
apps/e2e-tests/tests/checkForSeoUrl.spec.ts |
Uses generic navigation. |
apps/e2e-tests/tests/checkCategory.spec.ts |
Retags category tests. |
apps/e2e-tests/tests/addToWishlist.spec.ts |
Uses isolated wishlist accounts. |
apps/e2e-tests/tests/addToCart.spec.ts |
Adapts wishlist-to-cart coverage. |
apps/e2e-tests/tests/addProductReview.spec.ts |
Documents the unsupported review scenario. |
apps/e2e-tests/README.md |
Documents starter-template E2E execution. |
apps/e2e-tests/playwright.config.ts |
Adjusts Playwright timeouts. |
apps/e2e-tests/page-objects/WishlistPage.ts |
Adds wishlist synchronization and cart action. |
apps/e2e-tests/page-objects/SearchResultPage.ts |
Uses shared listing helpers. |
apps/e2e-tests/page-objects/RegisterPage.ts |
Supports inline starter registration. |
apps/e2e-tests/page-objects/ProductPage.ts |
Adapts variant-cart handling. |
apps/e2e-tests/page-objects/MyAccountPage.ts |
Supports alternate profile navigation. |
apps/e2e-tests/page-objects/LoginPage.ts |
Improves login field synchronization. |
apps/e2e-tests/page-objects/HomePage.ts |
Adds content-independent navigation helpers. |
apps/e2e-tests/page-objects/CheckoutPage.ts |
Supports starter guest checkout. |
apps/e2e-tests/page-objects/CategoryPage.ts |
Uses shared listing helpers. |
apps/e2e-tests/page-objects/CartPage.ts |
Waits correctly for the mini-cart. |
apps/e2e-tests/package.json |
Changes the suite tag to @frontends. |
AGENTS.md |
Updates E2E contributor guidance. |
.github/workflows/e2e-starter-template.yml |
Adds the starter-template CI workflow. |
.changeset/olive-hounds-repeat.md |
Records the listing-filter fix. |
Suppressed comments (1)
apps/e2e-tests/utils/listing.ts:81
- The existing product image is already visible when the URL is pushed, before
changeCurrentPagestarts, so this wait can return with page 1 still rendered. Wait until pagination marks page 2 as current (or otherwise observe the listing response) before continuing.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Stale comment
Security review of
4b7c997(“synchronize”): no medium, high, or critical issues.Checked the new e2e workflow (
contents: read,pull_requestnotpull_request_target, no secrets), SSR/network diagnostics (URLs and status only; artifacts are demo-store traffic), listing-from-URL (query values stay strings; Store API remains the trust boundary), and checkoutguest: !createAccount(password rules apply when creating an account). The earlier CodeQL weak-randomness finding is already fixed withuniquePassword().No prior automation security threads. No inline findings.
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
Stale comment
Security review of
9215075(“synchronize”): no medium, high, or critical issues.New since the last pass is only the build step (
pnpm exec turbo run build --filter=vue-starter-template). That is a static command: no untrusted interpolation, stillpull_request(notpull_request_target),contents: read, and no secrets.Re-checked the rest of the PR: SSR/network diagnostics still log URLs and status only; listing filters keep query values as strings with the Store API as the trust boundary; checkout still derives
guest: !createAccountand validates the password path when creating an account;uniquePassword()remains CSPRNG-backed. Prior automation review had no finding threads to re-open.No inline findings.
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
Patryk Tomczyk (patzick)
left a comment
There was a problem hiding this comment.
Review — changes requested
CI is fully green (13/13, e2e included). One real regression in a published package, the rest are minor/nit.
Blocking
SwProductListingFiltersHorizontal.vue— the rewrittenhasActiveFilternever reports property-group filters as active. Property filters carry the group's own code, not"properties", so the new branch is dead and the changed fallback (return false) drops the behaviour the old fallback provided. Inline comment has the detail.
Non-blocking (inline)
2. CmsElementProductListing.vue — the local limit ref no longer resyncs from the URL, so Back/Forward updates the products but not the "Per Page" select or the skeleton count.
3. CmsElementProductListing.vue — the watcher is now the only fetch path and passes route.query verbatim, so min-price/rating/shipping-free reach the API as strings where they used to be typed; the post-filter branch in useListingFilters became unreachable as a result.
4. changePage/changeLimit scroll while the element they target is being unmounted for the skeleton.
5. ListingPage.checkFirstOptionIn picks a checkbox by page-wide index delta.
6. ListingPage.NON_PROPERTY_FILTERS mixes rendered labels with API codes.
7. checkForSeoUrl.spec.ts — the last assertion lost its wait and is now vacuous.
8. WishlistPage.countEntries() is unused.
9. instrument-ssr.mjs writes synchronously on every successful SSR call, inflating the latency it measures.
Open thread, your call: Maciej D (@mdanilowicz)'s failed-job-check.yml point is still unresolved. With continue-on-error: true and no gate anywhere, a total e2e failure leaves the job green and notifies nobody — the reporting-only trade-off is reasonable, but it should be an explicit team decision rather than an unresolved thread.
Also noting the gap you flagged yourself: three published cms-base-layer components change with no automated coverage of the app most affected. Finding 1 is exactly what that gap lets through.
There was a problem hiding this comment.
Stale comment
Security review of
da17a8a(“synchronize”): no medium, high, or critical issues.Delta since the last pass is review follow-up: the e2e job is now schedule/
workflow_dispatchonly (contents: read, no secrets, static commands),buildCriteriaallowlists listing query keys instead of forwardingroute.queryverbatim, and SSR diagnostics still log URLs/status only. Checkout still derivesguest: !createAccountwith password validation on the account path;uniquePassword()remains CSPRNG-backed.No prior automation security finding threads to re-open. No inline findings.
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
🟡 Changes recommended
The workflow misses its required PR trigger, listing failures can become unhandled rejections, and network statistics are currently inaccurate.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
apps/e2e-tests/scripts/summarise-network.mjs:74
entriesalso containsstorefront-error-pageandstorefront-5xxdocument records, so treating its full length as Store API attempts adds browser error pages as extra API calls; the per-side denominator below has the same problem. Count onlystore-api-*records when deriving API totals.
const attempted = completed + entries.length;
- Files reviewed: 62/62 changed files
- Comments generated: 5
- Review effort level: Balanced
…dle listing rejections
There was a problem hiding this comment.
Stale comment
Security review of
13a1d4ea(“synchronize”): no medium, high, or critical issues.Delta since the last pass is diagnostics and error-handling only: successful Store API responses are the only attempts counted, transport failures are restricted to
store-api-no-response, and listing refetches catch Store API rejections instead of leaving them unhandled. No new sinks.Re-checked the rest of the PR: the e2e job remains schedule/
workflow_dispatchonly (contents: read, no secrets, static commands);buildCriteriastill allowlists listing query keys; checkout still derivesguest: !createAccountwith password validation on the account path; diagnostics still log URLs/status/IPs/trace ids of demo-store traffic, not bodies or credentials;uniquePassword()remains CSPRNG-backed.No prior automation security finding threads to re-open. No inline findings.
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
|
Thanks, this was a useful review. All nine are fixed and on the branch, plus the open question at the end. 1 (blocking). Right, and it was my regression. The fallback is back as you wrote it, comment included. 2. 3. Added a 4. 5. 6. Now matches on 7. Added a wait for the destination listing to render. 8. Dropped. 9. Buffered, flushed on a 2s interval and on exit. While fixing 9 I found two bugs in my own measurement pointing opposite ways: the attempts log counted 4xx and 5xx twice, and On the open thread. Settled by removing the pull_request trigger entirely: the suite is nightly plus manual dispatch. |
There was a problem hiding this comment.
Stale comment
Security review of
c994ac92(“synchronize”): no medium, high, or critical issues.Delta since the last pass is a one-line diagnostics refactor:
summarise-network.mjsreusesapiCalls()for the attempted-count denominator. Counting-only; no new sinks.Re-checked the rest of the PR: the e2e job remains schedule/
workflow_dispatchonly (contents: read, no secrets, static commands);buildCriteria/applyQueryToFiltersstill allowlist listing query keys; checkout still derivesguest: !createAccountwith password validation on the account path; diagnostics still log URLs/status/IPs/trace ids of demo-store traffic, not bodies or credentials;uniquePassword()remains CSPRNG-backed.No prior automation security finding threads to re-open. No inline findings.
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
Stale comment
Security review of
507e32fc(“synchronize”): no medium, high, or critical issues.Delta since the last pass is a Slack mrkdwn path fix in
failed-job-check.yml: the failure link now uses/tree/${head_branch}instead of interpolating the branch as a repo-root path. Same GitHub-controlled values as before (server_url,repository,workflow_run.head_branch); the notifier still only fires forworkflow_runcompletions onmain/prod. Not a new sink.Re-checked the rest of the PR: the e2e job remains schedule/
workflow_dispatchonly (contents: read, no secrets, static commands);buildCriteria/applyQueryToFiltersstill allowlist listing query keys; checkout still derivesguest: !createAccountwith password validation on the account path; diagnostics still log URLs/status/IPs/trace ids of demo-store traffic, not bodies or credentials;uniquePassword()remains CSPRNG-backed.No prior automation security finding threads to re-open. No inline findings.
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
Patryk Tomczyk (patzick)
left a comment
There was a problem hiding this comment.
Re-review — all 9 previous findings addressed
Every item from my last review is fixed, and correctly:
- The blocking one —
hasActiveFilterfallback restored toproperties.size > 0with a comment explaining why it must stay a fallback. ✅ limitnow resyncs from the URL inside the watcher. ✅buildCriteria()normalises query strings to numbers/booleans, drops unknown params, and the unreachablepost-filterbranch plus the unusedsearchCriteriaForRequestexport are gone. Rejections are now caught rather than floating. ✅scrollToListing()waits onuntil(loading).toBe(false). ✅ (Vue's pre-flush scheduler queues the route watcher beforerouter.pushresolves, soloadingis alreadytrueby then — the wait is real, not a no-op.)ListingPagescopes the option to the panel via the newlisting-filter-${filter.code}testid, and matches filter codes instead of localised button text. ✅ Nice generalisation.checkForSeoUrlwaits for the destination to render. ✅countEntries()removed; SSR logging buffered with a timer + exit flush. ✅
And Maciej D (@mdanilowicz)'s failed-job-check.yml thread is resolved properly — continue-on-error dropped, workflow added to the notify list.
Two things from the latest push
-
The docs now contradict the workflow (blocking, two lines). Dropping the
pull_requesttrigger andcontinue-on-errorleftapps/e2e-tests/README.md:27,29andAGENTS.md:131describing behaviour that no longer exists. Inline. -
The harness fixes are unverified. With the PR trigger gone,
E2E Starter Templateno longer runs here — the last run was on9215075, before theListingPagerework, thecheckForSeoUrlwait and the newlisting-filter-*testid. Those are exactly the changes most likely to break the suite, and nothing has exercised them. Aworkflow_dispatchrun onci/e2e-suite-against-starterbefore merge would close it.
The scheduled-only trade-off itself reads as the right call given the Slack notification — just worth confirming the team is happy that the PR titled "run the e2e suite against vue-starter-template" runs nightly rather than per-PR, since #2649 closes with it.
|
Both fixed, and thanks for catching the docs drift. That is exactly the kind of thing the change should not have left behind. 1. Docs. While in there I found one more the review did not name. The README's "To reproduce the CI run locally" block built with 2. Verification. Fair point, and I had the same worry. Dispatched a run on this branch: https://github.com/shopware/frontends/actions/runs/34515297522 I will report the result here either way rather than only if it is green. On the trade-off. Agreed it should be an explicit team call rather than something that slips through with the PR. To be clear about what changed and why: the path filter matched 19 of the last 25 merged PRs at a median of 12 minutes a run, which is the same trade #2706 made for the example builds. #2649 asked for the suite to run in CI, and it does; nightly rather than per-PR, with a Slack notification on failure. If the team would rather have it per-PR, the trigger is three lines and I am happy to put it back. |
|
Dispatch run finished green: https://github.com/shopware/frontends/actions/runs/34515297522 18 passed, 6 flaky, 2 skipped, 0 failed, 13.5 minutes, on That covers what you flagged as unexercised. Two caveats so the number is not read as more than it is. The 6 flaky are the retry-absorbed store-api drops tracked in #2682, not new; the count moves run to run. And the run predates the docs commit above, which is fine since docs cannot affect the suite, but it does mean the green tick is on the code as reviewed rather than on the branch tip. |
There was a problem hiding this comment.
Stale comment
Security review of
288de64e(“synchronize”): no medium, high, or critical issues.Delta since the last pass is documentation only (
AGENTS.md,apps/e2e-tests/README.md): the workflow is described as nightly/workflow_dispatch, and the local repro uses the same turbo build as CI. No new sinks.Re-checked the rest of the PR: the e2e job remains schedule/
workflow_dispatchonly (contents: read, no secrets, static commands).buildCriteria/applyQueryToFiltersstill allowlist listing query keys and coerce numbers/booleans. Checkoutguest: !createAccountis the intended guest-vs-account split. Diagnostics log URLs, status, IPs, and trace ids only. Slack notifier still interpolates GitHubworkflow_runcontext onmain/prodonly.No prior automation security-finding threads to re-open. CodeQL insecure-randomness on
createOrder.spec.tsremains resolved viauniquePassword().Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
Security review of 273fbf71 (“synchronize”): no medium, high, or critical issues.
Delta since the last pass is a merge of main (#2698 CountrySearchSelect, #2700 checkout flow, #2719 changesets v3). Those changes introduce no new sinks here. Checkout still derives guest: !createAccount and applies password rules only on the account path; uniquePassword() remains CSPRNG-backed.
Re-checked the rest of the PR: the e2e job remains schedule/workflow_dispatch only (contents: read, no secrets, static commands). buildCriteria / applyQueryToFilters still allowlist listing query keys and coerce numbers/booleans. Diagnostics log URLs, status, IPs, and trace ids of demo-store traffic, not bodies or credentials. Slack notifier still interpolates GitHub workflow_run context on main/prod only.
No prior automation security-finding threads to re-open. CodeQL insecure-randomness on createOrder.spec.ts remains resolved via uniquePassword().
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
Note
Copilot was unable to run its full agentic suite in this review.
Pull request overview
Copilot reviewed 62 out of 62 changed files in this pull request and generated 3 comments.
Suppressed comments (3)
packages/cms-base-layer/app/composables/useListingFilters.ts:1
- These checks drop valid falsy values (e.g.,
0for min/max price or rating, andfalsefor boolean flags) because they use truthiness. This can cause the URL to lose an explicitly-set filter value and the listing to refetch with different criteria. Use explicit!== undefined/!= nullchecks (and for booleans, check=== trueor presence semantics) when deciding whether to write each field into the query.
packages/cms-base-layer/app/composables/useListingFilters.ts:1 - The shipping-free filter is handled as tri-state elsewhere in this PR (e.g., chips treat it as active when the value is not
undefined), but here it is stored viaBoolean(value)and the reset button uses!!selectedFilters[\"shipping-free\"]. Ifvaluecan be the string'false',Boolean('false')becomestrue(wrong), and if it becomesfalse, the chip logic may still consider it active while the reset button does not. Normalize shipping-free consistently (e.g., store onlytrue | undefined, parse string values explicitly, and alignshowResetFiltersButtonto the same semantics).
packages/cms-base-layer/app/composables/useListingFilters.ts:1 - The shipping-free filter is handled as tri-state elsewhere in this PR (e.g., chips treat it as active when the value is not
undefined), but here it is stored viaBoolean(value)and the reset button uses!!selectedFilters[\"shipping-free\"]. Ifvaluecan be the string'false',Boolean('false')becomestrue(wrong), and if it becomesfalse, the chip logic may still consider it active while the reset button does not. Normalize shipping-free consistently (e.g., store onlytrue | undefined, parse string values explicitly, and alignshowResetFiltersButtonto the same semantics).
| export const NETWORK_LOG = "diagnostics/network-failures.jsonl"; | ||
| export const ATTEMPT_LOG = "diagnostics/store-api-attempts.log"; | ||
|
|
| const record = (entry: Entry) => { | ||
| try { | ||
| mkdirSync(dirname(NETWORK_LOG), { recursive: true }); | ||
| appendFileSync( | ||
| NETWORK_LOG, | ||
| `${JSON.stringify({ | ||
| at: new Date().toISOString(), | ||
| test: testInfo.titlePath.join(" > "), | ||
| ...entry, | ||
| })}\n`, | ||
| ); | ||
| } catch { | ||
| // Diagnostics must never fail a test. | ||
| } | ||
| }; |
| mkdirSync(dirname(ATTEMPT_LOG), { recursive: true }); | ||
| appendFileSync(ATTEMPT_LOG, `${peer?.ipAddress ?? "unknown"}\n`); |
Patryk Tomczyk (patzick)
left a comment
There was a problem hiding this comment.
Approved
Both items from the last round are closed, and my three threads are resolved:
288de64ecorrectsREADME.mdandAGENTS.mdto "nightly and on manual dispatch, not on pull requests" and "nothing is gated, a failure notifies Slack". The local-repro snippet also switched toturbo run build, which matches the workflow. ✅- The
workflow_dispatchrun on507e32fsucceeded, so theListingPagepanel-scoping rework, thecheckForSeoUrlwait and thelisting-filter-${filter.code}testid have all actually executed. ✅
The merge from main shrank this PR usefully: #2700 landed the createAccount / guest: !createAccount rework independently, so checkout/index.vue is down to two data-testid lines here and CustomerBaseInfo.vue to three. The version in main is better than what I reviewed — baseInfoRules makes the password rule conditional on createAccount, so handleRegister can validate the whole form in one check instead of special-casing email. hasActiveFilter's property-group fallback survived the merge intact.
Two follow-ups, neither blocking
-
Worth one more
workflow_dispatchon the merged head before merging. The last e2e run predates the merge, and the merge is exactly what the checkout and address specs drive: #2700 restructuredhandleSaveAddressintohandleRegisterwith anisRegisteringstate and put the whole form behindv-if="!isUserSession", while #2698 reworkedCountrySearchSelect— whichutils/form.ts:selectCountryprobes by tag name. The testids all line up on inspection, so I expect it to pass; it is just cheap certainty on the one thing nothing has exercised. -
Copilot's
fixtures.tspoint is fair.NETWORK_LOGandATTEMPT_LOGare appended at fixed relative paths and never truncated, so locally the second run'ssummarise-network.mjsoutput mixes in the first run's calls and the failure rate stops meaning anything. Harmless on a fresh runner. Truncating once per run (or keying the filename on the run) would fix it — fine as a follow-up.
Still open and yours to close: Maciej D (@mdanilowicz)'s two threads on playwright.config.ts:34 and the @frontends tag name, both already answered.


Description
Adds a workflow that builds
vue-starter-template, serves it withnuxt preview, and runstest:e2eagainst it. Runs nightly and on manual dispatch.Retags the suite from
@vue-demo-storeto@frontends, so the tag names the behaviour rather than one template.Along the way it fixes three defects the suite exposed. Two are in
@shopware/cms-base-layer, a published package, despite the commit subjects reading as test work:changePage,changeLimitand sorting. Applied to both the sidebar and horizontal filter components.guest: true, so a customer who chose to create an account got a guest account and could never sign in.closes #2649
closes #2651
Type of change
Bugfix and new feature (non-breaking)
ToDo's
@shopware/cms-base-layerResult
21 passed, 3 flaky, 2 skipped, 0 failed on CI in 7.4m.
It does not run on pull requests. The path filter it started with matched 19 of the last 25 merged PRs, at a median of 12 minutes a run, which is the same trade #2706 made for the example builds.
Because nothing is gated on it any more, a failure now notifies Slack through
failed-job-check.yml, and the test step no longer usescontinue-on-error(with it, the run concludessuccessand the notifier never fires).Also fixes the branch link in that Slack message, which pointed at
github.com/<repo>/<branch>and 404'd. It affects all seven workflows listed infailed-job-check.yml, not just this one.Every flaky scenario traces to one cause, now filed as #2682: Store API calls that fail without a response. Nitro logs none of it, so this branch adds a collector (
apps/e2e-tests/fixtures.ts) that records every failed call, how long it ran before dying, and any error page the browser was shown. A summary lands in the job page and the raw JSONL in the artifact.That instrumentation corrected two assumptions worth stating. Requests are not hanging: on CI they die at a median of 171ms and none exceeded 8s, so a request timeout would never fire. And about a quarter of what looked like backend failures are
net::ERR_ABORTED, which is the client cancelling in flight, mostly the country combobox firing per keystroke.The classifier itself had two bugs, fixed in
13a1d4ea: it logged a success even on a 4xx or 5xx, and counted 429s, 5xx and error pages as no-response failures. They pulled the rate in opposite directions and the corrected figure is 4.8% rather than 9.5%. The latency numbers above never went through that path and are unaffected. Every CI run on this branch predates the fix, so treat its reported rate as approximate until the first nightly run.Built and served locally rather than pointed at a Vercel preview, so a run tests the branch it runs on. Sets
NUXT_PUBLIC_SHOPWARE_DEV_STOREFRONT_URLbecause the template default is the demo store domain, which the starter's sales channel rejects (#2585).Review follow-up
All four findings addressed.
createAccountis now a model onCustomerBaseInfo, bound from the checkout page. Guest validates email and billing address, account validates the whole base-info form, andguestis derived rather than hardcoded. One spec per mode; the account one signs in over the Store API, which is what proves the customer is not a guest, since a guest cannot sign in at all.@shopware/*dependencies are symlinked intopackages/, so a change in one rebuilds the starter without touching the template. Added the six runtime packages and root dependency metadata.api-genis left out, it is codegen only.data-product-idon the add-to-cart button and the cart line item; the test asserts exactly one line item carries the id the button submitted, rather than checking an image is visible.A second round of nine findings is answered in this comment. All are fixed on the branch, including one real regression it caught in
SwProductListingFiltersHorizontal.vue, where property-group filters stopped rendering as active.What this closes
What is still queued, and why
data-testidattributes were added across 27 files. Itscomm -23check still lists 22 ids, but the check undercounts: it greps only the template directory and only the literaldata-testid=, so it misses 10 ids that live incms-base-layer, one prop default and one dynamic binding. Corrected, the residue is 11, of which only three or four are attributes on components that already exist; the rest are blocked on [E2E] vue-starter-template has no clear-wishlist action, so the scenario stays skipped #2679, [E2E] vue-starter-template renders no product reviews, so the scenario stays skipped #2680 and [CF][Templates] Port the remaining demo-store features to vue-starter-template #2652. Measurement and full breakdown in this comment.apiClientConfigis a documented module option that nothing reads, so a consumer following the published types gets silence. A timeout was tried here and reverted: measured on CI it never fired once.useListingignorescacheableReads, so category listings and search stay on POST. They lose CDN caching and, less obviously, ofetch's automatic retry, which only applies to GET.cacheableReadsis applied by hand at each call site with nothing enforcing completeness. useListing ignores cacheableReads, so listings and search stay on POST #2691 is the symptom.storefrontUrl. The workflow works around it with an env var, the bug remains.Worth a reviewer's attention
Nothing in CI runs e2e against
vue-demo-store, and retagging removed the last demo-store-specific suite. Three published-package files change here (SwProductListingFilters.vue,SwProductListingFiltersHorizontal.vue,SwProductAddToCart.vue) with no automated coverage of the app most affected by them. The reordering matches the convention already used elsewhere in the same package, and no template overrides those components, but that is analysis rather than a test.Also fixes a
--in the e2e README that silently drops arguments under pnpm 11.