feat(sc-44545): make registration discoverable on login page#3370
Conversation
Selecting a path filter on a text search (e.g. filtering "מעל" to Psalms)
returned no results and a 500 from /api/search-wrapper. The search page
sends text filters with agg_type=None, relying on the documented contract
that make_filter() supplies the default field ("path") for that query type.
Commit 1252655 ("keyword-search-in-connected-refs") tightened the text
branch from `if type == "text":` to `if type == "text" and agg_type == "path":`
so a new non-path text agg_type (linked_refs) could use a Term filter. That
routed the agg_type=None default into `Term(**{None: agg_key})`, which raises
TypeError: keywords must be strings -> HTTP 500, breaking all text path
filters (both URL-applied and clicked).
Honor the None default again by matching `agg_type in (None, "path")`, which
fixes URL-load, in-app click, and the empty-filter_fields fallback, while
preserving the Term path for linked_refs and all sheet filters.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Spec for making the path to registration discoverable on the login page: reusable Django include partial, placement under the H1, blue+underlined link styling, EN/HE copy from the story. Documents why a React migration was rejected for this story and how the design leaves a seam for SC-44544. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l vars
- Figma (file 2WflG98PDhWQ7OKrDkaCPb, node 35:425) is source of truth for
layout/styling/CSS + dev-mode notes; story stays authoritative for strings
(they agree). Pulled exact specs from 35:430 and all three annotation notes.
- Corrected link color to --sefaria-blue (#18345D, Figma Semantic/Text/Link),
SemiBold 600, underlined, 4px gap; prompt --darker-grey (#575757). No hex.
- CSS uses general vars from color-palette.css in global static.css (no global
PostCSS; it is CSS-modules-only for the React bundle).
- Django 6.0.4: resolve register URL via {% url ... as %} + {% include with %}.
- Added mobile + Hebrew/RTL coverage to testing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 bite-sized tasks (TDD-adapted for template/CSS): update HAM-A003 E2E selector, create reusable partial, wire into login.html + remove old link, add Figma-sourced scoped CSS via general vars, end-to-end visual/behavior verification (EN/HE/mobile + register regression + next preservation). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📊 Code Quality Score: 16/100
Was this score accurate? 👍 Yes · 👎 No Scored by GitVelocity · How are scores calculated? |
…date-login-page-to-handle-anon-la-candidates
Master's url() (django.conf.urls.url, removed in Django 4.0) breaks URLConf load on Django 6 -> NameError -> /healthz-rollout 500 -> cauldron web pod never ready. Folded here so this PR's cauldron image builds clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ontrols, responsive)
There was a problem hiding this comment.
Pull request overview
This PR aims to make the registration path more discoverable from the server-rendered /login page by introducing a reusable cross-flow navigation partial and updating styling/tests accordingly. It also includes additional unrelated backend/search and URL routing changes that expand scope beyond the stated “login page only”.
Changes:
- Add a reusable bilingual login/register cross-flow nav partial and include it directly under the login title.
- Update global CSS to style the new prompt/link (and additionally adjust login form layout).
- Update Playwright mobile E2E selector for the new “Sign Up” link; add a search regression fix + test; refactor some URL patterns to
re_path.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| templates/registration/login.html | Includes new cross-flow nav under the H1; removes old bottom registration link; tweaks form markup. |
| templates/registration/_cross_flow_nav.html | New reusable EN/HE prompt + inline link partial that preserves ?next=. |
| static/css/static.css | Adds .registration-prompt styles and additional login layout rules. |
| e2e-tests/mobile web/auth-flow.spec.ts | Updates HAM-A003 to click the new “Sign Up” link scoped to #login. |
| sefaria/helper/search.py | Treats agg_type=None as default text path filter to avoid Term(**{None: ...}) crash. |
| sefaria/helper/tests/search_test.py | Adds regression test for default text filter agg type behavior. |
| sites/sefaria/urls.py | Replaces url(...) usages with re_path(...) for static routes. |
| docs/superpowers/specs/2026-06-02-login-cross-flow-nav-design.md | Adds detailed design spec documenting the approach and styling tokens. |
| docs/superpowers/plans/2026-06-02-login-cross-flow-nav.md | Adds implementation plan/checklist for the change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Static and Semi Static Content | ||
| site_urlpatterns = [ | ||
| url(r'^metrics/?$', reader_views.metrics), | ||
| url(r'^digitized-by-sefaria/?$', reader_views.digitized_by_sefaria), | ||
| url(r'^(favicon\.ico|apple-touch-icon\.png|favicon\.svg)/?$', reader_views.module_favicon), | ||
| url(r'^(?P<filename>site\.webmanifest|manifest\.json)/?$', reader_views.dynamic_manifest), | ||
| url(r'^apple-app-site-association/?$', reader_views.apple_app_site_association), | ||
| url(r'^\.well-known/apple-app-site-association/?$', reader_views.apple_app_site_association), | ||
| url(r'^\.well-known/assetlinks.json/?$', reader_views.android_asset_links_json), | ||
| url(r'^llms\.txt/?$', reader_views.serve_llms_txt), | ||
| url(r'^(%s)/?$' % "|".join(static_pages), reader_views.serve_static), | ||
| url(r'^(%s)/?$' % "|".join(static_pages_by_lang), reader_views.serve_static_by_lang), | ||
| url(r'^healthz/?$', reader_views.application_health_api), # this oddly is returning 'alive' when it's not. is k8s jumping in the way? | ||
| url(r'^health-check/?$', reader_views.application_health_api), | ||
| url(r'^healthz-rollout/?$', reader_views.rollout_health_api), | ||
| re_path(r'^metrics/?$', reader_views.metrics), | ||
| re_path(r'^digitized-by-sefaria/?$', reader_views.digitized_by_sefaria), | ||
| re_path(r'^(favicon\.ico|apple-touch-icon\.png|favicon\.svg)/?$', reader_views.module_favicon), | ||
| re_path(r'^(?P<filename>site\.webmanifest|manifest\.json)/?$', reader_views.dynamic_manifest), | ||
| re_path(r'^apple-app-site-association/?$', reader_views.apple_app_site_association), | ||
| re_path(r'^\.well-known/apple-app-site-association/?$', reader_views.apple_app_site_association), | ||
| re_path(r'^\.well-known/assetlinks.json/?$', reader_views.android_asset_links_json), | ||
| re_path(r'^llms\.txt/?$', reader_views.serve_llms_txt), | ||
| re_path(r'^(%s)/?$' % "|".join(static_pages), reader_views.serve_static), | ||
| re_path(r'^(%s)/?$' % "|".join(static_pages_by_lang), reader_views.serve_static_by_lang), | ||
| re_path(r'^healthz/?$', reader_views.application_health_api), # this oddly is returning 'alive' when it's not. is k8s jumping in the way? | ||
| re_path(r'^health-check/?$', reader_views.application_health_api), | ||
| re_path(r'^healthz-rollout/?$', reader_views.rollout_health_api), |
- Scope #login layout rules under #login.registrationContent so they don't leak into other templates that use id="login" (translate_campaign). - Remove literal space before the cross-flow link so the 4px CSS margin (RTL-safe) controls the gap, matching Figma. Addresses Copilot review comments on PR #3370. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…date-login-page-to-handle-anon-la-candidates
Anon users who click the Library Assistant promo CTA were enrolled in the experiment only after a second 'Join' click post-login. Route the promo's login/register ?next= through a new /enable-library-assistant landing view: once auth completes the user lands there, is enrolled in the experiments whitelist (reusing _set_user_experiments), and is redirected back to where they were. The assistant then appears on reload with no extra click. - New view enable_library_assistant: same-host-validated redirect, forwards the register welcome flag, bounces anon hits to login. - Banner anon CTAs now target the opt-in landing via nested ?next=. - Normal (non-promo) logins are unaffected. - Tests cover enroll+redirect, anon->login, offsite-next fallback, welcome forwarding, default, and idempotency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Source files shouldn't carry Shortcut story IDs (branch/commit refs are enough). Replicated on the login-page branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Source files shouldn't carry Shortcut story IDs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Skip Library Assistant enrollment when the browser reports a cross-site request (Sec-Fetch-Site), so a cross-site <img> can't silently enroll a logged-in user; the real same-origin post-login redirect is unaffected. Add tests for protocol-relative next, welcome appended to an existing query string, and the cross-site skip; assert no duplicate settings row. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/ork multi-agent review — verdict: COMMENT (no blockers)Reviewed security, correctness, accessibility, i18n/RTL, and test correctness. All clear:
Noted (conscious tradeoff, not changed): the partial has no literal whitespace between prompt and link — the 4px gap is the CSS 🤖 review run via ork-style parallel agents |
…nto feature/sc-44545/update-login-page-to-handle-anon-la-candidates
… design spec files
…ndidates' into feature/sc-44544/la-promo-change-opt-in-behavior-for-non
…e-opt-in-behavior-for-non feat(sc-44544): auto opt-in to Library Assistant after promo-driven auth
…nto feature/sc-44545/update-login-page-to-handle-anon-la-candidates
…ndidates' of https://github.com/Sefaria/Sefaria-Project into feature/sc-44545/update-login-page-to-handle-anon-la-candidates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nto feature/sc-44545/update-login-page-to-handle-anon-la-candidates
…nto feature/sc-44545/update-login-page-to-handle-anon-la-candidates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nto feature/sc-44545/update-login-page-to-handle-anon-la-candidates
📊 Code Quality Score: 34/100
Was this score accurate? 👍 Yes · 👎 No Scored by GitVelocity · How are scores calculated? |
HAM-A003 (mobile auth-flow): the login page's registration call-to-action changed in #3370 — the link is now "Sign Up" ("Don't have an account? Sign Up", rendered by registration/_cross_flow_nav.html), not "Create a new account". Update the locator and test title to match. VBM-002 (Voices /history bookmarking): the Voices /history page crashes on render (TypeError reading 'trim' in ProfilePic) when the account's history contains a row for a since-deleted sheet with no ownerName, blanking the whole page so .savedHistoryList never appears. Add clearReadingHistory() to VoicesBookmarksPage and call it before seeding: it toggles the account's reading_history setting off->on via /api/profile/sync, which makes the server run delete_user_history(exclude_saved=True) — wiping reading history while preserving /saved. The settings time_stamp must strictly exceed the stored one (persists across runs on the shared account), so the helper reads the current stamp and sends strictly-greater values.
…new tagging system (Sefaria#3456) * Overwrite e2e-tests with origin/playwright-mdl content * chore: update Playwright configuration * feat: starting to refractor the self contained MDL tests to align with the rests of the POM tests. * feat: Enhance module header interactions and language handling - Improved dropdown interaction by ensuring overlays are dismissed before clicking. - Added special handling for language selection in dropdowns, utilizing URL-based strategies. - Updated utility functions to simplify modal and popup dismissals using a click-if-visible approach. - Refactored language change logic to prioritize cookie setting and URL navigation. - Updated Playwright configuration to allow dynamic base URLs via environment variables for better test flexibility. * refactor: streamline modal handling by consolidating hide functions * refactor: simplify language verification logic in toggleLanguage function * feat: add tests for trending topics functionality in Voices module * feat: add VALID_TOPICS constant and improve module button navigation handling in Voices tests * feat: add cross-module redirect tests for Library to Voices and no-redirect loops in Voices module; update selectors and dependencies * feat: enhance cross-module redirect tests and improve navigation handling; add gotoOrThrow utility for better error handling * feat: implement cross-subdomain cookie handling for improved storage state management * feat: rename browser test configurations for clarity and consistency; update test directories for modularization tests * feat: refactor module URLs to use environment variable for sandbox domain; update tests for consistency across modules * feat: add cross-module login scenarios and improve user menu handling; refactor module URLs to use environment variable * feat: enhance cross-module login tests and update user menu selectors; add new test scripts for browser compatibility * feat: enhance cross-module redirect tests; add response status checks and update module selectors * feat: Fix auth context sharing in goToPageWithUser Add auth cookies to provided context instead of creating separate browser context. This ensures fixture pages inherit authentication state, fixing test isolation issues where tests would fail with language/domain mismatches when run as part of full suite. Backward compatible with existing test patterns. * feat: enhance cross-module login scenarios; add explicit wait for profile picture visibility after login * feat: update profile redirect test to use 'qa-automation' user * feat: update module URLs to support English and Hebrew versions; refactor tests and constants accordingly * feat: implement Help Sheet to Zendesk redirects tests for English and Hebrew versions; add redirect mappings * feat: Create the first of many sanity tests. Added two new pages to thew page objecvt modal for profile page and edit profilepage. * feat: removing console logs on first sanity tests * feat(Sheets Sanity): Created a Sanity test that checks the lifecycle of sheet creation. Fixed old Selectors and moved log out to end. * docs: Add comprehensive documentation for the e2e Sanity Test Suite, detailing core, user flow, sheet workflow, and cross-module redirect tests. * feat: removing old files * feat: add Sanity test 3; Search bar verification and results * feat: path sheet workflow tests to add images and youtube videos and verify it works * refractor: fix wait times and configuration to handle bigger load on tests * refactor: sanity tests - update load state waits to 'domcontentloaded' for improved performance and reliability * feat: remove the temporary go live folder for testing in sanity * feat: moved cross module redirect tests out of misc/ directory back into the main sanity tests as a non temp test * feat: enhance user login checks with debug logging and improved wait states * feat: add TIMEOUT_MULTIPLIER env variable with t() helper for e2e tests * feat: apply TIMEOUT_MULTIPLIER t() wrapper to all page objects * feat: Implement mobile E2E testing infrastructure including constants, documentation, and a hamburger menu sanity test. * feat(e2e): apply TIMEOUT_MULTIPLIER t() wrapper to all spec files Wrap all timeout values and waitForTimeout() calls in spec files with the t() helper function so they respect TIMEOUT_MULTIPLIER. Files updated: - Sanity: cross-module-login, user-flow-sanity, sheet-workflow-sanity, search-sanity, cross-module-redirects - Tests: regression-tests, sheet-editor-resource-panel, sheetEditor, autosave - Voices: trending-topics, header - Library: header - Misc: help-sheet-redirects - Mobile: mobile-hamburger-sanity * docs(e2e): add TIMEOUT_MULTIPLIER documentation to README - Added 'Timeout Multiplier' subsection under Environment Setup - Updated Configuration Reference with accurate timeout values - Included usage examples showing correct t() wrapper pattern * feat: remove old mobile web testing plan and implementation (working on a better ne, needed a fresh start) * feat: rename voices and library folder. Harden goToPageWithLang function. and remove old outdated tests to pave way for new * feat(e2e): add Library Texts Tree Traversal tests for Tanach * docs(e2e): rewrite READM and fix SANITY.md * feat(e2e): implement Library Assistant end-to-end tests and related configurations like POM and new account that has LA enabled * feat(e2e): add negative coverage tests for Library Assistant visibility and enhance page object with expectNotPresent method * feat(e2e): add tests for Library Assistant header menu and responsive behavior * feat(e2e): update Library Assistant tests for running on firefox and safari Co-authored-by: Copilot <copilot@github.com> * refactor(e2e): remove unused browser configurations from Playwright setup ('all') * chore(env): update example.env with comments for clarity on adding a user for Library Assistant * refactor(e2e): streamline search and user flow tests by removing redundant code and enhancing modal handling. Sanity Tests are now reliable and consitent * fix(e2e): harden header new-tab test and modal-dismiss loop against parallel-run flakes, reduces time for dismissing popups * fix(e2e): update footer link URLs for About and Help sections to ensure correct navigation behavior * fix(e2e): replace 'networkidle' with 'domcontentloaded' for improved page load handling in header and navigation tests * fix(e2e): replace 'networkidle' with 'domcontentloaded' for improved page load handling across various tests * fix(e2e): make the header spec tests have more conistency in what they are clicking. Archive trendin topics test * fix(e2e): fix timing issue with modal popup * feat(e2e): add tests for Terms and Privacy Policy links in sidebar footer * fix(e2e): update regex patterns for footer link hrefs to improve matching * feat(e2e-mobile): Add mobile hamburger menu tests and page object implementation part 1. * feat(e2e-mobile): Implement mobile authentication flow tests and enhance mobile hamburger functionality * feat(e2e): Add end-to-end tests for Resource Panel features - Introduce a new page object for the Resource Panel to encapsulate interactions and assertions related to the panel's UI components and behaviors. * feat(e2e): Update header menu test to include 'Settings' item for staff users * rename(e2e): rename mobile folder to mobiel web for clarity * feat(e2e-mobile): Add mobile hamburger menu and authentication flow tests back in under new folder name * feat(e2e): Resource Panel Part 2 — 13 new spec files covering RP-060 → RP-212 (42 tests across Connections List, Text List, Topics, Web Pages, Sheets, Manuscripts, Notes, Add to Sheet, Share, Search in Text, Feedback, Guide, Hebrew UI) Extends the POM with helpers for every new mode and brings the Resource Panel suite from 37 to 79 tests, all passing against real production data with zero skips. * refactor(e2e): move auth to globalSetup; eliminate per-worker login races Replace the per-test "log in lazily and write auth_*.json on first call" pattern with a one-time globalSetup that logs every account in once before any worker starts and writes a read-only storage-state file per profile. Workers only ever read those files thereafter, so the file-write race that caused auth-gated tests to flake on every full-parallel run is now structurally impossible. Also fixes missing awaits in loginAs, a single-cookie clear in expireLogoutCookie, a redundant double-navigation in goToPageWithUser, and removes the BROWSER_SETTINGS.english/.hebrew footguns plus their now-unused helpers. * test(e2e): introduce two-layer overlay suppression and fix sanity-suite flakes Strapi-driven banners (Sustainer modal et al.) are now suppressed at context level via `installOverlaySuppression` — `addInitScript` short-circuits `modal_*`/`banner_*` localStorage reads, `context.route` empties the `/api/strapi/graphql-cache` payload, and a `cookiesNotificationAccepted=1` cookie is pre-seeded; `hideAllModalsAndPopups` is now a slim parallel click-fallback for the remaining non-Strapi overlays. Also: Sanity 7's logout now uses `enAdmin` so it stops invalidating the `enUser` session that sheet-workflow-sanity depends on, Sanity 9e waits for the SPA URL update instead of `domcontentloaded`, RP-190's `hasGuideButton` timeout was bumped from 3s to 15s, 102 redundant `hideAllModalsAndPopups` calls were dropped across 28 spec files, and 6 stale Zendesk slugs in `helpDeskLinksConstants.ts` were refreshed — all six chrome projects now pass 261/261 at full parallelism. * fix(e2e): change playwright mobile config setup to use mobile web folder instead of mobile * refractor(e2e): change playwright.mobile.config to playwright.mobileweb.config for consistency * docs(e2e): enhance README and comments with details on destructive auth tests and session management * feat(e2e): Add end-to-end tests for Voices Topics landing and topic pages - Implement `voices-topics-landing.spec.ts` to test the Trending Topics sidebar on the landing page, ensuring it lists 5–15 topics and each is navigable. - Create `voices-topics.spec.ts` for comprehensive end-to-end tests on individual topic pages, covering content display, language support, sheet interactions, and navigation. - Introduce `voicesTopicPage.ts` as a Page Object Model (POM) for the Voices topic page, encapsulating methods for interacting with the page elements and assertions. * feat(e2e): Enhance user menu interaction for logged-in state and improve locator precision * feat(e2e): Improve Guided Learning button visibility checks and increase timeout for full-parallel load * feat(e2e): Update share URL checks to be case-insensitive for sandbox compatibility * feat(e2e): Remove unused cookieObject and enhance cookie domain handling for cross-subdomain tests * docs(e2e): production rewrite of README handbook + fix stale sub-doc references README.md: rewrite as a humans-first handbook with a front-loaded quick start, a README-vs-CLAUDE doc map, and a utils.ts catalogue. Correct page-object count (20), complete the PageManager accessor list, fix mobile/ -> mobile web/ paths, remove the obsolete chrome-all/firefox-all/safari-all troubleshooting entry, re-point canonical exemplars to resourcePanelPage/voicesTopicPage + the Resource Panel/Voices Topics specs, document fixtures/ and archived-tests/, and switch the TOC to lint-clean auto-generated heading anchors. assistant/README.md: drop the nonexistent ai-chatbot.csv references; correct the coverage from 10 to the real 16 behavioral + 4 LA-NEG tests; refresh the TODO. mobile web/README.md: fix the self-referencing mobile/ paths -> mobile web/. Voices Topics + Resource Panel READMEs: fix the broken mobile/ link and remove references to the .claude/ scratch directory and its test-plan CSVs. * fix(e2e): repair broken package.json playwright test scripts The test:* aliases referenced an old project-naming scheme (chromium / library / voices / misc / webkit-library) that no longer exists in playwright.config.ts. Point them at the real project names (chrome-* / firefox-* / safari-*), drop the unmappable generic browser aliases, and add aliases for the newer suites (sanity, assistant, resource-panel, voices-topics) plus the mobile config. * docs(e2e): rename Sanity/SANITY.md to README.md for folder consistency * docs(e2e): add per-folder READMEs and modernize the Sanity guide Every meaningful subfolder now has an onboarding doc: - pages/README.md — page-object index: canonical models (resourcePanelPage, voicesTopicPage), every pm.onX() accessor, and legacy/orphan markers - library/, voices/, Misc/ — per-folder guides (scope, ID schemes, baseURL) - Full testing by Feature/README.md — index of the deep feature suites - archived-tests/README.md — why specs are archived and how to run them locally Sanity/README.md (renamed from SANITY.md in the prior commit): rewritten into the house style (ID tables, per-spec detail, architecture, gotchas incl. the Sanity 7 -> enAdmin destructive-auth constraint). Root README directory map + Related-docs updated to surface the new docs and the Sanity README rename. * docs(e2e): commit CLAUDE.md handbook for the test suite Un-ignore e2e-tests/CLAUDE.md and add it to the repo so the prescriptive rules for writing tests, extending page objects, and auditing existing code are version-controlled alongside the suite. The global CLAUDE.md ignore rule is preserved with a negation so only the e2e-tests handbook is opted in. * fix(e2e): harden RP-056 lexicon invalid-entry assertion for local runs Scope the assertion to the autocomplete widget's own `.dictionary-toc-autocomplete` class instead of `.connectionsPanel` (so it holds when jQuery UI mounts the dropdown on <body>), and skip the Enter press that could close the dropdown before assertion. * test(e2e): cut artifact overhead and add local retry to stabilize flaky runs Resource Panel tests (RP-053, RP-122, RP-123) intermittently hit the 50s timeout under full parallelism (8 workers): a starved worker stalled on context.newPage()/panel rendering, and the forced teardown left half-written trace files (the ENOENT artifact errors). All three pass in isolation in 5-7s, confirming flake-not-bug. - video: retain-on-failure -> off. retain-on-failure records video for every test then discards on pass; pure overhead and redundant with the trace. - trace: retain-on-failure -> on-first-retry. No artifacts on the happy path; a full trace is still captured when a failed test is retried. - retries (desktop): 0 -> 1 locally so a starvation blip self-heals. CI keeps 2. Mobile config already retried locally; only its video/trace were updated. Full chrome-resource-panel suite: 79 passed, 0 retries, 3.4m -> 1.1m. * feat(e2e): add Hebrew Library Assistant suite + fix MDL auth for logged-in .il The Library Assistant chatbot is now bilingual, so mirror the English LA coverage in Hebrew. Verified every label against the LIVE deployed component (the source i18n catalog differed from prod), and reworked the auth layer to support a logged-in session on the Hebrew (.org.il) domain. * fix(e2e): update user menu interaction to handle React re-renders and ensure dropdown visibility * feat(e2e): add Library Topics test suite (LIB-001 → LIB-029) * feat(e2e): enhance header tests for logged-in users and update user menu items * fix(e2e): improve error handling and messaging for login failures in global setup * test(e2e): add Voices Bookmarks & History suite (VBM-001 → VBM-010) Sheet-page Save menu, /saved list, and /history bookmarking on the Voices module. Adds VoicesBookmarksPage POM, three specs, disjoint test sheets, README, and chrome/firefox/safari-voices-bookmarks projects. 10 tests, stable at full parallelism. * fix(e2e): Update folder name of Voices Bookmarks History to Voices Bookmarks (Saved) and History for clarity * feat(e2e): make Sanity suite tag-scoped via @sanity instead of folder-scoped Sanity membership was tied to the Sanity/ folder, so adding a release-gate test that lives elsewhere meant copy/pasting it. Make the chrome/firefox/ safari-sanity projects tag-scoped instead: testDir './e2e-tests' + grep /@sanity/, so they run every test tagged { tag: '@sanity' } anywhere in the tree. This is safe with a single baseURL because the suite navigates to absolute MODULE_URLS, never relative paths. * feat(e2e): add @sanity tag to Resource Panel tests and update README for clarity on test execution * feat(e2e): change user-flow to user-menu for clairty * refactor(e2e): remove @sanity tag from describe blocks for cross-module tests and tag some individually * refactor(e2e): make Sanity tag-scoped and relocate specs to feature folders Sanity membership was tied to the Sanity/ folder. Make it a property of the test instead: the *-sanity projects now scan the whole tree and run every test tagged { tag: '@sanity' } (testDir './e2e-tests' + grep /@sanity/), so a release-gate test lives in its feature folder and joins the suite via the tag. Relocate the five former Sanity specs to where they belong and renumber their IDs; @sanity tags travel with them, so the tagged run is unchanged (32 tests): - search-sanity -> Full testing by Feature/Search/search.spec.ts (SRCH-001..006) - user-menu-sanity -> Full testing by Feature/User Menu/user-menu.spec.ts (UMN-001..007) - cross-module-login -> Full testing by Feature/Cross-Module/login.spec.ts (XMOD-L01..L09) - cross-module-redirects -> Full testing by Feature/Cross-Module/redirects.spec.ts (XMOD-R01..R17) - sheet-workflow -> voices/sheet-lifecycle.spec.ts (SHT-001..010) * fix(e2e): stabilize SRCH-002/005 search-submit with web-first toHaveURL Both 'submit search and get results' tests flaked on navigation timing: - SRCH-002 asserted page.url() right after a fixed waitForTimeout, racing the search navigation (received /texts instead of /search?q=...). - SRCH-005 used page.waitForURL, which waits for the 'load' event by default; the Voices search SPA's load can lag past 15s even though the URL is correct. Replace both with a web-first expect(page).toHaveURL(...) assertion, which polls the URL and does not depend on the load event firing. Verified stable: each test passed 3x with retries off. * fix(e2e): harden UMN-002/SHT-001 navigation waits with toHaveURL Both used page.waitForURL after a client-side (SPA) route change, which waits for the 'load' event by default — the same root cause as the SRCH-005 flake (URL is correct well before 'load' fires on Sefaria's SPAs). - UMN-002: profile nav via the user menu - SHT-001: sheet creation via the Create button Swap both to a web-first expect(page).toHaveURL(...) that polls the URL without depending on 'load'. Verified: each passed 3x with retries off. * fix(e2e): harden remaining click-nav waits with web-first toHaveURL Suite-wide sweep for the same root cause as the SRCH-005 flake (asserting on a URL that's reached by a client-side SPA route change before waiting on it web-first). Three more genuine matches: - SRCH-001 / SRCH-004: suggestion click then waitForLoadState + sync url.toMatch - MOD-H014: Create-button click then waitForURL (waits for the 'load' event) Replace all with expect(page).toHaveURL(...). Verified: SRCH-001/004 6x, MOD-H014 3x, all passing with retries off. Swept the rest of the suite and cleared the others: the voices/sidebar Create & Learn-More asserts go through handleClickNavigation (awaits navigation/popup), the Library Topics LIB-024 ref-link nav is a real document load via the canonical Promise.all pattern, and the cross-module XMOD sync-url asserts follow awaited page.goto()s. * test(e2e): expand @sanity coverage (+75 tests, mobile-sanity project) * ocs(e2e): clarify run-via-project + document mobile sanity * feat(e2e): rename voices in archived tests to do not run on prod for clarity * fix(e2e): repair HAM-A003 and VBM-002 failures HAM-A003 (mobile auth-flow): the login page's registration call-to-action changed in Sefaria#3370 — the link is now "Sign Up" ("Don't have an account? Sign Up", rendered by registration/_cross_flow_nav.html), not "Create a new account". Update the locator and test title to match. VBM-002 (Voices /history bookmarking): the Voices /history page crashes on render (TypeError reading 'trim' in ProfilePic) when the account's history contains a row for a since-deleted sheet with no ownerName, blanking the whole page so .savedHistoryList never appears. Add clearReadingHistory() to VoicesBookmarksPage and call it before seeding: it toggles the account's reading_history setting off->on via /api/profile/sync, which makes the server run delete_user_history(exclude_saved=True) — wiping reading history while preserving /saved. The settings time_stamp must strictly exceed the stored one (persists across runs on the shared account), so the helper reads the current stamp and sends strictly-greater values. * fix(e2e): make Voices Bookmarks tests module-pinned and history-render robust VBM-001/005/006 failed under chrome-sanity (baseURL=LIBRARY) while passing under chrome-bookmarks (baseURL=VOICES): the POM navigated with relative page.goto('/saved' | '/history' | '/sheets/<id>'), which resolve against the running project's baseURL, so under sanity they landed on the Library module and the Voices /saved entries were absent. Pin navigation to absolute Voices URLs (voicesBase) so the suite is correct regardless of project baseURL. VBM-002: replace the unreliable clearReadingHistory() helper. The reading_history toggle does not durably clear history on the shared QA account — the server-side delete is inconsistent and the client re-syncs its cached history back — so /history kept crashing on accumulated deleted-sheet rows (ProfilePic throws on a missing ownerName, blanking the page). Instead sanitize the user_history responses at the network layer (page.route): fetch the real response and drop only the un-renderable rows (a sheet item with no ownerName). Real data, including the seeded target row, passes through and the bookmark toggle + /saved checks still hit the real backend. * fix(e2e): protect all Voices Bookmarks list navigations from the ProfilePic crash The /saved page is the same UserHistoryPanel/SheetBlock/ProfilePic render as /history, on the same shared QA account — so the undefined-ownerName crash that blanked /history can blank /saved too the moment a saved sheet's author is deleted. Centralize the user_history response sanitizer: gotoSaved and gotoHistory both call it (idempotent, registered once per page), so every VBM list navigation is covered, not just VBM-002. Drop the now-redundant explicit call in history-page.spec.ts. --------- Co-authored-by: Copilot <copilot@github.com>
Story
SC-44545 — Update login page to handle anon LA candidates who don't have an account (epic: Library Assistant System and UX)
As part of simplifying the LA promo (logged-out users get a single "Log in to Try" entry point), the login page must make the path to registration hard to miss.
Changes
templates/registration/_cross_flow_nav.html— reusable bilingual "prompt + inline link" line (EN/HE), preserves?next=.login.html— cross-flow link moved directly under the "Log in to Sefaria" title (was an easy-to-miss link at the bottom); old "Create a new account" link removed. Uses Django 6{% url … as %}+{% include … with %}.static/css/static.css— scoped.registration-promptstyling from the Figma design (node35:430): prompt--darker-grey, link--sefaria-blueSemiBold underlined, 4px RTL-safe gap. General CSS vars, no hardcoded hex.auth-flow.spec.ts— HAM-A003 updated to select the new "Sign Up" link (scoped to#login).Copy (source of truth = story): EN
Don't have an account? Sign Up· HEאין לכם חשבון? להרשמה.Design docs
docs/superpowers/specs/2026-06-02-login-cross-flow-nav-design.mddocs/superpowers/plans/2026-06-02-login-cross-flow-nav.mdFigma (source of truth for layout/CSS): https://www.figma.com/design/2WflG98PDhWQ7OKrDkaCPb/Login---Registration-Wireframes?node-id=35-420
Scope
Login page only. SC-44544 (backend auto-enroll into the experiment on auth) is a separate story; this design leaves the partial as a clean seam for it.
Test plan
Preview cauldron (feature mode): https://sc-44545-login.cauldron.sefaria.org
/login?next=/texts→ link href is/register?next=/textsregister.htmllinks visually unchanged🤖 Generated with Claude Code