Skip to content

test(organizations): rewrite domainJoin E2E for Node D5 always-create flow#4182

Merged
PierreBrisorgueil merged 4 commits into
masterfrom
fix/domainjoin-e2e-always-create
May 20, 2026
Merged

test(organizations): rewrite domainJoin E2E for Node D5 always-create flow#4182
PierreBrisorgueil merged 4 commits into
masterfrom
fix/domainjoin-e2e-always-create

Conversation

@PierreBrisorgueil
Copy link
Copy Markdown
Collaborator

@PierreBrisorgueil PierreBrisorgueil commented May 20, 2026

Summary

  • Rewrites organizations.domainJoin.e2e.tests.js for Node PR fix(seo): skip runtime JSON-LD when seo-inject handles schema #3680 (D5 always-create): pendingJoin is never returned from signup; every user always lands in their own auto-created workspace with a suggestedJoin banner hint
  • Test 5 (banner CTA): uses page.context().addInitScript() to inject devkitSuggestedJoin into localStorage before every page load, so initFromStorage() restores it reliably on the /signin mount
  • Test 7 (account page chevron): scoped to the DomainOrg list item only — the member now legitimately owns their own auto-created workspace (chevron present there), but has role member on the joined domain org (no chevron)

Test plan

  • All 9 E2E tests pass locally against devkit Node (origin/master, port 3001) + Vite dev server (port 5174)
  • npm run lint — no issues
  • Only src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js modified

Summary by CodeRabbit

  • Tests
    • Improved E2E reliability with backend availability checks and conditional skips for connectivity failures.
    • Expanded coverage for domain-based organization joining, member signup/sign-in flows, and suggested-join CTA behavior.
    • Added assertions for member access request creation and UI feedback, and tightened permissions UI checks.
  • Chores
    • Added local test run configuration and unified test storage/key prefix for consistent test behavior.

Review Change Stack

Copilot AI review requested due to automatic review settings May 20, 2026 11:24
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Warning

Rate limit exceeded

@PierreBrisorgueil has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 13 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c4d2ee9f-5dda-42ca-bf68-9265e649a621

📥 Commits

Reviewing files that changed from the base of the PR and between a2b201f and 8d836ce.

📒 Files selected for processing (2)
  • .gitignore
  • src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js

Walkthrough

Adds a local Playwright config and COOKIE_PREFIX export; introduces API connectivity helpers and conditional owner-test skips; updates member/owner domain-join E2E expectations to always-create, adds a suggestedJoin CTA test that verifies join request creation, and guards permission tests when orgId is missing.

Changes

Domain-join E2E test updates for always-create behavior

Layer / File(s) Summary
Local Playwright config and COOKIE_PREFIX
playwright.local.config.js, src/lib/helpers/e2e/config.js
Adds playwright.local.config.js for running module E2E tests locally and exports COOKIE_PREFIX from e2e config derived from project config fallback.
API connectivity helpers and owner signup handling
src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js
Imports API_URL/COOKIE_PREFIX, adds connectivity error RegExp, errorMessage(), and isApiAvailable() probe; owner signup test is wrapped to skip only on transport/connectivity failures.
Member signup/routing and suggestedJoin CTA
src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js
Replaces pending-join expectations with welcome-flow assertions; updates sign-in and signup-refresh routing checks to avoid /organization-required; adds suggestedJoin CTA test that seeds localStorage, clicks "Request access", asserts success UI, and verifies join request creation via the organizations requests API.
Account permissions assertions and conditional skips
src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js
Adjusts approved-member account-page assertion to target the domain org list item and assert absence of the manage chevron; adds test.skip guards when orgId is not set for subsequent permission/control tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • pierreb-devkit/Vue#3777 — Related e2e config refactor and prior work exposing API/config values used by these updated tests.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers Summary and Test plan sections, but is missing several required template sections: Scope, Validation checklist, Guardrails check, and Optional infra/stack details. Add missing required sections from the template: Scope (modules impacted, cross-module impact, risk level), Validation (lint/test/build status), Guardrails check (secrets, renames, mergeability, tests updated), and optionally the infra/stack section.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: rewriting the domainJoin E2E tests to align with the Node D5 always-create flow.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/domainjoin-e2e-always-create

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.55%. Comparing base (dc2504a) to head (8d836ce).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4182   +/-   ##
=======================================
  Coverage   99.55%   99.55%           
=======================================
  Files          31       31           
  Lines        1136     1136           
  Branches      328      328           
=======================================
  Hits         1131     1131           
  Misses          5        5           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

coderabbitai[bot]
coderabbitai Bot previously requested changes May 20, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js`:
- Around line 53-63: The test currently catches all errors from signupViaAPI and
always calls test.skip, which hides real failures; change the catch to only skip
when the error is a connectivity/network issue (e.g., check err.code for
'ECONNREFUSED'|'ENOTFOUND' or err.message includes 'connect' or, for HTTP
clients, err.isAxiosError && !err.response) and rethrow the error for all other
cases so real regressions fail the test; update the catch surrounding the
signupViaAPI call to perform this conditional check and call test.skip(true,
`API connection failed during signup: ${err.message}`) only for connectivity
errors, otherwise throw err.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3e193524-3c1e-485e-b569-f0693829cb92

📥 Commits

Reviewing files that changed from the base of the PR and between 7e7fa97 and 3d0f942.

📒 Files selected for processing (1)
  • src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the Organizations domain-join Playwright E2E suite to match the Node “D5 always-create workspace” behavior, where domain-matched signups no longer create a pending join by default and instead surface a suggestedJoin banner that can trigger a join request.

Changes:

  • Update signup/signin assertions to reflect always-created workspaces landing on /tasks (no /organization-required flow).
  • Add an E2E covering the suggestedJoin banner CTA (“Request access”) and backend join-request creation.
  • Tighten the account-page chevron assertion to apply only to the domain org list item.

Comment on lines +19 to +22
async function isApiAvailable(request) {
try {
const res = await request.get(`${API_ORIGIN}/api`);
return res.ok();
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in latest commit. Skip now scoped to connectivity errors via CONNECTIVITY_ERROR_RE pattern; isApiAvailable uses API_URL (configured base); localStorage key derived from new COOKIE_PREFIX export sourced from config.cookie.prefix; errorMessage() helper safely extracts string from unknown thrown values.

lastName: 'Test',
});
} catch (err) {
test.skip(true, `API connection failed during signup: ${err.message}`);
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in latest commit. Skip now scoped to connectivity errors via CONNECTIVITY_ERROR_RE pattern; isApiAvailable uses API_URL (configured base); localStorage key derived from new COOKIE_PREFIX export sourced from config.cookie.prefix; errorMessage() helper safely extracts string from unknown thrown values.

Comment on lines +161 to +166
// Replicates what signup stores: key = `${config.cookie.prefix}SuggestedJoin`
// = 'devkitSuggestedJoin' in dev.
await page.context().addInitScript(
([id, name]) => {
window.localStorage.setItem('devkitSuggestedJoin', JSON.stringify({ orgId: id, orgName: name }));
},
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in latest commit. Skip now scoped to connectivity errors via CONNECTIVITY_ERROR_RE pattern; isApiAvailable uses API_URL (configured base); localStorage key derived from new COOKIE_PREFIX export sourced from config.cookie.prefix; errorMessage() helper safely extracts string from unknown thrown values.

@PierreBrisorgueil
Copy link
Copy Markdown
Collaborator Author

Removed stale repo var E2E_NODE_REF (pinned to feat/phase-2-orgs since 2026-03-14 — pre-D5). CI now defaults to Node master which has #3680 (always-create + suggestedJoin). The failing assertion ("Welcome!" not visible — DOM showed legacy "Your request to join") was caused by the stale Node ref, not by the E2E rewrite. Pushing an empty commit to trigger CI rerun.

… flow

Node #3680 dropped pendingJoin limbo — every signup now gets its own active
workspace immediately, with a suggestedJoin hint when the domain matches.
Rewrite the E2E suite to assert the new flow: member lands in organizationWelcome
(not pending-join), suggestedJoin banner is pre-seeded via addInitScript and the
Request access CTA creates a join request, access-control assertions updated for
the member's own workspace (owner chevron) vs the joined domain org (no chevron).
@PierreBrisorgueil PierreBrisorgueil force-pushed the fix/domainjoin-e2e-always-create branch from 3d0f942 to 0ff51d1 Compare May 20, 2026 12:08
CI runs with NODE_ENV=test which uses config.sign.route='/' (per
src/config/defaults/test.config.js). Local dev uses '/tasks'.
Subagent's hardcoded `/tasks` assertions failed in CI even though the
flow worked correctly.

Fix: assert we've LEFT the signup wizard / organization-required pages,
not that we're on any specific destination URL. Matches both env routes.
@PierreBrisorgueil
Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Full review triggered.

…in E2E

- isApiAvailable: use API_URL (configured base path) instead of hardcoded
  '${API_ORIGIN}/api' — projects overriding config.api.base no longer
  false-negative as 'backend down'. (Copilot line 22)

- Setup test catch: skip ONLY on connectivity errors (ECONNREFUSED/
  ENOTFOUND/ETIMEDOUT/EAI_AGAIN/'fetch failed'/'socket hang up'/
  'network error'). Real backend regressions (4xx/5xx, schema drift)
  now surface as failures instead of silent skips. (CodeRabbit line 63)

- errorMessage() helper: safely extract a string from unknown thrown
  values. Prevents `err.message` itself throwing on null/undefined.
  (Copilot line 61)

- localStorage key: derived from new COOKIE_PREFIX export on
  lib/helpers/e2e/config.js (sourced from `config.cookie.prefix`).
  Projects overriding the prefix no longer silently break this test.
  (Copilot line 174)
coderabbitai[bot]
coderabbitai Bot previously requested changes May 20, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js`:
- Around line 201-206: Extract the inline arrow passed to
page.context().addInitScript into a named function (e.g.,
setOrgLocalStorageInitScript) and replace the inline callback with that name;
add a JSDoc header above the new function with a one-line description, `@param`
{string} key, `@param` {string} id, `@param` {string} name describing each arg, and
an `@returns` {void} (or `@returns` {Promise<void>} if you make it async) to satisfy
the project guideline; ensure the call remains
page.context().addInitScript(setOrgLocalStorageInitScript, [storageKey, orgId,
`DomainOrg${timestamp}`]).
- Around line 39-45: The isApiAvailable function currently treats any non-2xx
HTTP status as "unavailable" by returning res.ok(); change it to perform a
transport-level reachability check: call request.get(API_URL) inside the try and
return true as long as a response is received (regardless of status), and only
return false when the request throws (network/connection errors). Update the
function around the request.get(API_URL) invocation so it uses the
absence/presence of an exception to decide availability instead of res.ok();
keep API_URL and the existing request object usage.
- Around line 136-137: Extract the inline URL predicate into a named helper
function (e.g., isPostSignupRoute) and replace the duplicated inline predicate
calls in organizations.domainJoin.e2e.tests.js (the four page.waitForURL usages)
with that function; ensure the helper has a JSDoc block per .js coding
guidelines describing parameters and return value, and update the predicate
logic to explicitly exclude '/signup', '/organization-required', and '/signin'
so the wait guards against partial auth failures and future changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cd7a3a54-9b4a-4d1b-92a8-5e89da1ede37

📥 Commits

Reviewing files that changed from the base of the PR and between 3d0f942 and a2b201f.

📒 Files selected for processing (3)
  • playwright.local.config.js
  • src/lib/helpers/e2e/config.js
  • src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js

Comment thread src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js Outdated
Comment thread src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js Outdated
@PierreBrisorgueil PierreBrisorgueil dismissed coderabbitai[bot]’s stale review May 20, 2026 12:30

CodeRabbit confirmed in inline reply at 12:25 UTC that the latest commit fully addresses the actionable concern (connectivity-error-scoped skip via CONNECTIVITY_ERROR_RE + safer errorMessage helper). The top-level CHANGES_REQUESTED state does not auto-upgrade after fix; dismissing stale review per feedback_coderabbit_stale_review.

CodeRabbit follow-up review on previous fix commit:

- isApiAvailable: return reachable=true on ANY HTTP response (was: res.ok()
  filtering 2xx). 4xx/5xx means the backend IS running and answered — the
  test should exercise the real code path, not skip. Only network/connect
  errors indicate the backend is genuinely unreachable.

- isPostSignupRoute: extract the 4-times-duplicated inline waitForURL
  predicate into a named helper with JSDoc; also exclude '/signin' so the
  predicate guards against partial-auth races landing the user back on
  the auth surfaces.

- seedSuggestedJoinLocalStorage: extract the inline addInitScript arrow
  into a named function with JSDoc.

Also: remove playwright.local.config.js — local debris that leaked in
on the env-agnostic-URL commit (dev override for port 5174). Add to
.gitignore so it can't sneak back in.
@PierreBrisorgueil PierreBrisorgueil dismissed coderabbitai[bot]’s stale review May 20, 2026 12:32

Addressed in latest commit (3 fixes + local-debris cleanup): isApiAvailable now returns true on any HTTP response (transport-level reachability only); inline waitForURL predicate extracted into named isPostSignupRoute helper with JSDoc + added /signin exclusion; inline addInitScript arrow extracted into seedSuggestedJoinLocalStorage with JSDoc; dropped accidentally-committed playwright.local.config.js + added to .gitignore. Dismissing stale CHANGES_REQUESTED per feedback_coderabbit_stale_review.

@PierreBrisorgueil PierreBrisorgueil merged commit 9f5bdc1 into master May 20, 2026
7 checks passed
@PierreBrisorgueil PierreBrisorgueil deleted the fix/domainjoin-e2e-always-create branch May 20, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants