Release: develop -> main - #1390
Merged
Merged
Conversation
* Scope develop PR tests and e2e, and honour ci:full Jest uses --findRelatedTests on changed src and functions files. The former head_ref job skip is gone. Docs-only e2e PRs with safe paths bring up no stack. The ci:full label forces full tests and e2e. * Align docs with scoped e2e and listen for base retargets CONTRIBUTING, the e2e README and test-architecture describe mode=none and ci:full. The workflows also run on edited so a retarget onto main re-evaluates the full-run rule. * Spell out remaining CI-scope exceptions in the docs Markdown format check stays full. E2E has no partial mode; docs-only skip applies only to safe-path documentation that does not touch e2e-stack. * docs: name workflow_dispatch and unsafe paths as e2e full triggers * Align e2e full-run trigger lists and fix Markdown formatting The three docs now name the same e2e full triggers as the workflow. Prettier accepts the layer table in docs/test-architecture.md. * Treat setupTests as infra and skip e2e prep on docs-only src/setupTests.ts is loaded by Jest for every suite, so a change there must force the full test run. Docs-only e2e jobs no longer check out the API or type-check the harness.
github-actions
Bot
requested review from
TaprootFreak and
davidleomay
as code owners
August 13, 2026 15:00
…1392) * Reject pull requests into main that are not from develop GitHub cannot restrict the source branch natively. This required check allows only this repository's develop branch to target main. * Fail closed when pull_request head metadata is empty Empty strings pass set -u. Without this check a missing repo name plus head ref develop would accept the pull request.
* Collapse the two IBAN switch controls into one cycle button The payment-details IBAN row showed a collection-account SWAP toggle and a provider BANK toggle side by side whenever both alternatives existed. Customers only need one control: a single SWAP button now walks personal → collection (when offered) → the other personal-IBAN provider (when offered). Collection stays a local display change; a provider step still requests a fresh quote. * Keep the IBAN cycle helper private to the payment component The provider callback now lives on the discriminated switch target, so the unreachable exported fail-closed throw is gone. Tests cover the cycle only through PaymentInformationContent. * Guard the buy payment details against a second IBAN switch The full-stack /buy and /buy/info flows already reach Payment Information. They now also assert that at most one IBAN switch button is rendered, so the two-control regression cannot land again even when this stack does not seed a personal-IBAN provider. * Refresh provider-toggle baselines for the single SWAP control The Frick and Yapeal payment-details screenshots now show one SWAP button instead of the previous SWAP plus bank icons. Collection-only baselines are unchanged.
* test: cover the CAMT.053 statement builder at 100% Add a unit spec for credit/debit layout, address fields, XML escaping, IBAN normalisation and amount formatting. * test: tighten CAMT.053 builder assertions after review Restore the crypto global after each case, assert the entry direction inside Ntry, lock IBAN slots on each side, and cover a debit address. * test: assert CAMT.053 direction, dates and amount copies Pin TxDtls direction counts, the account-header IBAN, BookgDt versus ValDt, and the three amount interpolations. * test: pin CAMT.053 amount slots to Ntry, TxAmt and balances Assert the formatted amount inside TxAmt and keep two zero-value opening and closing balances.
* feat(realunit): let staff deactivate buy quotes from the quotes UI SUPPORT can open /realunit/quotes and deactivate a buy quote. Confirm payment stays hidden for SUPPORT and for already deactivated quotes. * test(realunit): handbook quotes variants and Support deactivate e2e Add the visual quotes spec and metadata entry, and make the Support e2e-stack case click Deactivate through to completion. * docs(handbook): describe RealUnit quote deactivate variants in German Handbook metadata descriptions are German; keep the product title. * test(e2e): fill required columns when seeding a WaitingForPayment buy quote TypeORM synchronize rejects the insert without routeId, sourceId, payment methods, rates and isValid. * test(e2e): seed loc REALU on Sepolia and click Confirm exactly The deactivate flow must look up the Sepolia Token REALU row so getAdminQuotes returns the seeded quote. Overlay Confirm uses an exact name match so it does not collide with Confirm Payment Received. * test(e2e): pin handbook quote screenshots to English lang=en keeps selectors and baselines stable regardless of the admin account language. * test(e2e): commit RealUnit quote handbook baselines Encode the session JWT in the quote screenshot gotos so the token survives the query string, and add the four chromium-darwin baselines for list, active detail, deactivate overlay, and deactivated detail. * test(e2e): add Support-only quote deactivate handbook variant Cover the missing-session confirm-payment branch and snapshot the Support detail view that shows Deactivate without Confirm Payment. * fix(realunit): serialize quote confirm and deactivate actions Keep a single pending overlay so staff cannot confirm and deactivate the same quote at once. Cover the quote DTO helper and require deactivatedAt in the stack deactivate tests. * fix(ci): check out the private API with a deploy key The default GITHUB_TOKEN of this public repository cannot fetch DFXswiss/api, so Checkout API failed as "repository not found" and skipped the suite. Use the read-only deploy key in E2E_API_CHECKOUT_KEY. * fix(ci): do not persist the API deploy key after checkout Later job steps only need the working tree. Leaving the key in api-repo git config would let them reach the private API repo. * fix(realunit): return to the quotes list after deactivate navigate(-1) leaves a deep-linked detail page on about:blank. Staff after confirm or deactivate go to /realunit/quotes.
* Describe adding a wallet address on /account-merge The confirmation page no longer says two accounts are being merged. It matches the confirmation mail: a wallet address is added to the existing account. * Keep Full-stack E2E green when the API deploy key is missing Fork pull requests do not receive E2E_API_CHECKOUT_KEY. Detect the empty secret so the job still runs and skips the private checkout instead of failing as repository not found. --------- Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
…1409) The support form no longer collects email. After verification the customer returns via the stored origin; cancel and merge-OK drop that path so it cannot come back on a later visit. Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
TaprootFreak
previously approved these changes
Aug 18, 2026
…pup (#1411) * Open the invoice PDF from /tx without a post-await popup Reserve a tab on the Open invoice click so iOS Safari can show the PDF after the invoice PUT. Hide the button unless the row is a completed Buy in CHF or EUR. * Lock Open invoice with e2e and a jsdom-safe PDF stub Add full-stack tests that fail if the invoice tab is opened after the PUT, if the button shows on pending or sell rows, or if an API error is swallowed. Stub URL.createObjectURL on jsdom the same way the export tests already do. * Reserve a tab for Open receipt and buy-QR PDF Invoice Same click-then-PUT/GET pattern as Open invoice, so iOS Safari can show the PDF after the request. Fixes the leftover list receipt and buy-QR buttons. * Cover stale buy-QR success with a live reserved preview A mode change while the invoice request is in flight must close the reserved tab and must not assign a blob URL. * Give the pending-buy invoice row its own buy route createTransaction would otherwise POST /v1/buy again for the same user and get HTTP 409 Buy route already exists. * Cover the Open receipt error path at the unit layer The reserved-tab close on a rejected receipt request is unit-testable, same as Open invoice. Also lock the live-preview success assignment. --------- Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
…pdowns (#1410) * Use the logged-in staff verified name instead of clerk dropdowns Staff already have a mandatory verifiedName. Self-identification selects on compliance and support forms now send that name and no longer ask the clerk to pick themselves from a list. * Fix stale staff name after account change and declare coverage Clear the verified name while another account is loading, and stop mirroring Freigabe processedBy in local state. Add save-disabled tests, translations, and the e2e identity stub declaration. * Match My tickets by verified name or mapped clerk Assigned clerk initials and the name written on send can differ. The overview now treats either identity as mine and shows loading or error instead of a false empty state. * Reset mapped clerk identity when the staff account changes The My tickets mapping must not keep a previous account's clerk name across a session switch. * Drop unused clerks dependency from issue loaders The clerk list no longer seeds the message author, so reloading the issue whenever clerks arrive was leftover work. * Reuse the staff-name copy for send errors and load failures Issue send guards now share STAFF_NAME_MISSING, and the overview load error uses the same translated message as the rest of staff UI. * Load staff identity from the clerk endpoint, not the user dump The read-only name still comes from the logged-in account. Prefer GET support/issue/clerk (or the RealUnit twin) and only fall back to the user-data payload when that call is empty or missing. * Note why a failed clerk lookup falls back to userData * Align staff-identity layout, wrap a long line, and mock GET clerk * Move the missing-name hint out of the message compose row * Add before/after screenshots of the staff-identity UI change Review images of Editor, message author, assignment, and the missing-name hint. * Ignore Enter while the staff author name is still loading The Send button is already disabled in that state. Enter in the compose box was calling send anyway and showing a sticky missing-name error. * Key the staff-name cache by account and role The loader picks support vs RealUnit from the session role. Caching only on account reused the first endpoint after a role change. * Show the current staff-identity screens instead of before/after pairs Review images of the live controls as they look after the change: read-only author, read-only Editor, and the missing-name hint. * Keep only the two staff-identity screenshots Drop the error-state mock and the now-suffix names. The remaining images are the support issue screen and the compliance editor. --------- Co-authored-by: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
…ge (#1407) * Open assign, refund and support on the public TX status page Buttons on /tx/T… no longer redirect to login. Assign and refund use UID guest endpoints; the support form accepts a tx query param so a ticket can be filed without a session. * Keep the tx query param after the URL is cleaned Snapshot tx at mount so clearing the query string cannot re-enable the login guard or wipe the prefilled transaction. Guest refund renders without a numeric transaction id. * Hide logged-in refund dropdowns on the guest path Guest refunds always use free-text IBAN and address fields so leftover bank-account context after a previous session cannot open the dropdown. * Keep public TX mail links working when a session is already open Assign, refund and support on a T/Q status URL always use the guest capability path so a logged-in session cannot block or widen the action. * Drop unused within import from the refund tests ESLint treats the leftover import as a warning and CI fails at max-warnings 0. * Wire the guest refund mock in the list/txinfo suite T/Q refund now always calls getRefund. The list suite still stubbed that as a bare jest.fn, so the form never left the spinner. * Refresh status checks for the feature-branch pull request The previous head still carried a Full-stack E2E run from the closed develop-targeted fork PR. This branch is not develop, so that workflow does not apply here. * Do not fail full-stack E2E when the API checkout key is missing Fork pull requests do not receive repository secrets. Without the API checkout key the job dies as repository-not-found. Treat a missing key like a documentation-only change: mode=none, job still runs. * Drop unreachable session refund UI from the public TX refund form The refund route only mounts for T/Q UIDs, so the logged-in dropdowns and session refund APIs could never run. Always use the guest form, and expect the full-stack refund test to land on /tx/{uid}. * Drop leftover uid gates on the refund form and cover public assign TransactionRefund only mounts for T/Q, so a second isUid check was dead. The full-stack suite now opens /tx/{uid}/assign and expects the guest assign screen, not the list. * Restore user and session mocks in the tx query-param suite The mail-gate tests clear all mocks. The tx suite must put useUserContext back so the screen can destructure user after #1409. * Use the mail action secret on guest assign and refund URLs The unmatched-deposit mail stays one link: /tx/{uid}/{secret}. Guest assign and refund call the secret APIs; status without a secret does not offer those actions. * Restore JWT refund on the logged-in TX list path * Add handbook screenshots for the mail action-secret TX flow * Drop the unused JWT helper from the guest TX visual spec --------- Co-authored-by: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
The Nest monolith was renamed from DFXswiss/api. README, docs, comments, and the E2E checkout must use the current GitHub path. Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* Match the assign screen title by text, not by heading role The guest assign test added in #1407 asserts the screen title with getByRole('heading'), which never matches: the title comes from useLayoutOptions and renders in the app bar as a plain element. The captured Playwright trace of the failing run shows it as `generic [ref=e10]: Assign transaction`, with no heading role anywhere on the page. The other title assertions in this file already use getByText for exactly that reason. The feature itself works — the same trace shows the guest form rendered, the single buy target preselected and the submit button present, so this was only ever a wrong locator. getByText matches twice here, because the submit button carries the same accessible name (`button "Assign transaction" [ref=e30]`); the app bar precedes the form in the DOM, so first() takes the title. The negative assertion on the next line stays role-based: 'Your Transactions' is a real in-page heading, as the passing list tests at lines 48, 110 and 179 show, so it keeps its meaning. This blocks the DFXswiss/backend release, where it is the last failing check. * Spell out why first() is safe on the exact text locator * Cover the logged-in refund route the registry already claims Fixing the assign locator let the [coverage-gate] project run for the first time on this branch — it is skipped while any earlier spec fails, which is why #5090 never reported it. It then failed: Routes claimed but never opened (1) — the claiming suite must navigate there: - /tx/:id/refund #1407 added /tx/:id/refund to App.tsx and claimed it in specs/registry/transactions.ts, but every refund test navigates the guest variant /tx/:id/:secret/refund. The screen opens on either input — `isRefund = ... && (hasActionSecret || isLoggedIn)` — so the logged-in half was untested and the claimed route never visited. route-coverage.spec.ts says not to weaken or remove a claim to keep the gate green, so this adds the missing navigation as real coverage: open the route with a session and no secret, and assert the refund form renders. * Describe the exact-text matching rule accurately Codex conformance review: the comment explained first() via "the smallest element whose own text nodes match". That is the legacy text= engine's model and is not what makes ancestors safe here. Exact matching resolves to the smallest element whose text is exactly the string, and a wrapping container is never the smallest match — that is the reason, and the comment now says it.
TaprootFreak
approved these changes
Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automatic Release PR
This PR was automatically created after changes were pushed to develop.
Commits: 1 new commit(s)
Checklist