wip: playwright tests - #1833
Draft
papistacoding wants to merge 51 commits into
Draft
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
papistacoding
force-pushed
the
feat-playwright-e2e
branch
from
June 22, 2026 14:33
39fd9cd to
844adc8
Compare
…s, flake hardening
papistacoding
force-pushed
the
feat-playwright-e2e
branch
from
August 23, 2026 23:17
51931e1 to
2ed5efd
Compare
…ked entities An action plan whose priority was never set cannot be updated at all: the history builder copies the empty enum into ActionPlanHistory and its validator rejects "". No field can be edited, and the console shows no error. Documents the reproduction, the exact source lines in core, why clearPriority does not help, and that 48 optional-non-nillable enum fields across 30 schemas share the shape (only action plans verified). Links the seed workaround in exposure-action-plans-crud.spec.ts back to the entry, since that workaround is why the suite no longer covers the NULL case. Signed-off-by: papistacoding <bruno.papista@gmail.com>
The repo rule is no code comments; the seed rationale belongs in CORE-ISSUES.md, which is not part of the split PRs. Signed-off-by: papistacoding <bruno.papista@gmail.com>
Aggregating the flaky set across 13 full-suite runs showed 57 distinct tests had flaked at least once, but 40 of them (70%) in exactly one run — noise, not fragility. Only five were chronic, and those are what this fixes. global-setup: seedRoleUser did a bare waitForURL(/dashboard/, 30s) after login. On expiry it threw, which kills the whole run before a single test executes — two of the last three full runs died here and produced no data at all. It also gave no clue where the browser actually was. It now reports the stuck URL, and that immediately showed the real cause was not the session-cookie bounce but the login failing outright, leaving us on /login where re-navigating is futile. It now re-attempts the login for that case and only re-navigates for the cookie race. automation-workflows (worst offender, 4/13): the deletes verified through the UI list, which serves stale results right after a mutation. Assert through findWorkflowDefinitionId at the API instead, keeping the list check as a secondary. onboarding (3/13 each): both chronic tests walk the whole wizard but only the happy path carried test.slow(). Mark the re-entry test too. automation-templates (3/13): the column-visibility toggle and the header assertion could straddle a re-render. Check current state before toggling and retry the cycle. Latest full suite: 971 passed, 1 failed, 4 flaky — and none of the five chronic tests appear in it. Signed-off-by: papistacoding <bruno.papista@gmail.com>
Audit of every <Button>/<button> in the console against the org-level relations in core's fga/model/generated/crud.fga. Of 265 files invoking mutations, these trigger surfaces reached the backend with no permission check at all: - trust center NDA approve/deny and Approve All, which only ever gated the revoke path - subscriber bulk upload and row delete - campaign launch, cancel, delete, reminders, recipients and the draft setup view - the workflow wizard, both at its own route and where it renders embedded on an empty workflows list - creating a questionnaire from a template, which was also gated on CanCreateTemplate rather than CanCreateAssessment - inline owner/delegate/approver/stakeholder/assignee cells in the controls, policies, procedures, risks and tasks tables The generic table toolbar fell back to org can_edit whenever a page did not pass createPermission, which hid the create button from anyone holding only a <entity>_creator grant. Nine table pages now pass their own relation; every can_create_* includes can_edit, so nobody who could already create loses the button. Campaigns keeps its list readable: a route-level gate on CanCreateCampaign would lock viewers out of the whole section even though can_view_campaign is a distinct relation and the nav shows the entry to every role. The gate sits on the create button and the detail actions instead. Two scope bugs found while wiring this up: - PermissionGate keyed its denial on isSuccess, so a permission-service failure left it neither loading nor successful and rendered the protected children anyway. It now falls back to hasPermission, which fails closed and keeps the impersonation exception. - can_edit_trust_center_nda_request is declared on the organization type, but the NDA page looked for it in a trust-center object-roles response, where it can never appear. Request management now ORs the org-scoped capability with generic trust-center edit. Invite resend is separated from invite deletion: a MEMBER holds can_invite_members and may reissue a member invite, but not manage existing ones, and previously got an empty actions column. Inline cells read their own permission via useCanEditRows rather than threading a flag through the column factories, matching how the rest of the app resolves org roles at the point of use. Signed-off-by: papistacoding <bruno.papista@gmail.com>
All five share one shape: a background refetch remounts the row or the portalled content mid-interaction, which utils/menu.ts already documents as "retry the whole open-then-activate cycle rather than either half". - the task assignee dropdown's open-then-pick cycle now retries as a unit; its options are portalled, so a remount took them with it - member row actions no longer nest a toPass inside another, where the inner budget could swallow the outer one on a single attempt, and removal confirms inside the retry cycle - the evidence bulk-import helper matched name: 'Action' loosely, which went ambiguous once a "Suggested actions" button appeared on the page - delete-account hovers the wrapper span rather than the disabled button: a disabled button swallows pointer events, so the forced hover surfaced the tooltip 3/6 times under load against 6/6 for the wrapper - control objectives retry the create sheet and clean up by id Signed-off-by: papistacoding <bruno.papista@gmail.com>
permissions-matrix.spec.ts drives every org-level create affordance and gated route for owner/admin/member/readonly, backed by a seeded-auth fixture that logs in the harmonize demo users. 237 tests where the audit's gates previously had one assertion between them. Grants are taken from the live backend rather than guessed, and PERMISSIONS.md records what it returns — including two entries that had already produced wrong tests: MEMBER holds can_invite_members, and AUDITOR is not read-only (it creates and deletes evidence, findings and reviews). permissions.spec.ts is corrected accordingly. Surfaces that need state get it: subscribers seed a real row so create and delete can be asserted separately (can_delete_subscriber resolves through full_access, so admin has create but not delete), campaign detail seeds a campaign because its actions read object-level roles, and the inline editors assert the dashed underline by count — it is an absolutely positioned border-only span that toBeVisible treats inconsistently. E2E_SEEDED_ORG_ID joins the declared env list for the lint gate. Signed-off-by: papistacoding <bruno.papista@gmail.com>
The suite only offered per-file runs and count-based sharding, so a failure in one area meant re-running all 1158 tests to confirm a fix. Each product area is now a Playwright project, so `--project=controls` re-runs just that area and still composes with --grep and --shard. Projects are built from a single map in e2e/segments.ts, and the config asserts at load that every spec belongs to exactly one segment. A spec matching no project's testMatch would otherwise never run and say nothing about it; now an unassigned or double-assigned spec fails every Playwright command by name. Signed-off-by: papistacoding <bruno.papista@gmail.com>
ContractTab and its AddContractDialog were never imported anywhere: git log -S ContractTab on vendor-detail-tabs.tsx returns nothing, so the tab was born unreachable in ISS-1663 and only ever touched again by an unrelated sweep. Removing it orphans TableKeyEnum.VENDOR_CONTRACT, which goes with it. Signed-off-by: papistacoding <bruno.papista@gmail.com>
| test('full-page edit mode persists contract fields from the properties sidebar', async ({ page }) => { | ||
| test.slow() | ||
| const name = uniqueName('E2E Vendor edit') | ||
| const billingModel = uniqueName('E2E Billing') |
Cross-checked every gate against core: internal/ent/schema/*.go for the per-entity policy, iam@v0.31.1/entfga/checks.go for what each check does, and fga/model for the relations themselves. entfga.CheckEditAccess runs CheckAccessForEdit for delete operations too, so of the 50 schemas only trustcenterndarequest and workflowobjectref distinguish deletion at all. Four gates were derived from the existence of a can_delete_* relation rather than from the check core invokes, and hid the action from users the backend would allow: - campaign delete now needs object can_edit (CheckEditAccess) - subscriber delete now needs org can_edit (CheckOrgWriteAccess) — can_delete_subscriber resolves only through full_access, so gating on it locked out every admin - trust center document delete now needs object can_edit - trust center subprocessor delete now needs org can_edit Organization delete keeps can_delete: HasOrgMutationAccess is one of the two places that really does require it. CanDeleteSubscriber and CanDeleteTrustCenterSubprocessor lose their last consumers and go with them. Creates were checked the same way and need no change: CheckCreateAccess resolves to can_create_<entity>, which is what the createPermission entries already pass. Signed-off-by: papistacoding <bruno.papista@gmail.com>
Subscribers assert org can_edit rather than can_delete_subscriber: core guards that mutation with CheckOrgWriteAccess and never consults the delete relation, so admin does see the row delete. The old expectation only passed by racing the roles query — it failed on the first attempt and passed on the retry, which is why it read as flaky rather than wrong. The campaign action menu asserts inside role="menu". Cancel, delete and send-test-email are reachable from both the menu and the draft setup view, so page-wide locators matched two elements each and the ambiguity surfaced only once the setup view had painted. Signed-off-by: papistacoding <bruno.papista@gmail.com>
Three of the route layouts gated on a relation core never consults for the mutations behind them. Branding and customer logos required org can_edit. Core admits any trust-center editor: rule.AllowIfTrustCenterEditor checks can_edit on the trust center object and short-circuits to privacy.Allow, and the FGA model reaches editor either from the org through parent_editor or from a direct tuple on the trust center. The org-only gate therefore turned away legitimate editors before the page could run the useAccountRoles check it already has. Both now use TrustCenterEditorGate, which reads the object's roles. The custom domain route required can_create_custom_domain, which is `can_edit or can_edit_custom_domain`, while core guards CustomDomain with CheckOrgWriteAccess — plain org can_edit. A can_edit_custom_domain holder passed the route and then failed every mutation on it. CanCreateCustomDomain loses its last consumer and goes with it. Signed-off-by: papistacoding <bruno.papista@gmail.com>
The domain route now follows CheckOrgWriteAccess and branding and customer logos follow AllowIfTrustCenterEditor, so the matrix labels no longer claim a create relation. Owner and admin still reach all three — they hold the trust center's can_edit through parent_editor — which is why the expectations are unchanged. Signed-off-by: papistacoding <bruno.papista@gmail.com>
Workflows and task creation are no longer gated, route-level gates are replaced by per-affordance checks, and every trust-center surface resolves one edit rule instead of eight. Org deletion returns to the owner check and the email-template editor stops checking a create relation on update. Close the gaps the route gates were hiding: SSO actions, domain verification, FAQ reordering, subprocessor mode switching and trust-center document management. Create gates run through hasPermission so impersonation keeps working, and no longer stop at the button. Signed-off-by: papistacoding <bruno.papista@gmail.com>
Extract the control and evidence create-input construction into pure functions so they can be unit tested away from the form, and give the comment, group-member and status controls the accessible names the suite needs to address them. Signed-off-by: papistacoding <bruno.papista@gmail.com>
Cover the remaining CRUD, bulk-import, bulk-edit and comment flows, and assert the mutations actually fire rather than that a dialog opened. Skip every permission-gating test behind E2E_PERMISSION_GATES so the suite can merge before the gating does, and fix the races that made the suite flaky: a null membership node in roleOf, the router cache serving a stale list, and the loads that outrun a pending permission query. Signed-off-by: papistacoding <bruno.papista@gmail.com>
…te filter keys and page mappers Signed-off-by: papistacoding <bruno.papista@gmail.com>
Keeps filter-storage.test.ts byte-identical to the version the e2e branch created, so the ISS-2398 coverage stays with console-unit-tests while the new validation and quick-filter cases travel with the filter work. Adds make-filter-branch.sh, which builds e2e/split/filter-hardening from origin/main, and drops the duplicate filter manifest from split-prs.sh. Signed-off-by: papistacoding <bruno.papista@gmail.com>
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.
No description provided.