Skip to content

🎨 Palette: add ARIA loading status to Loader#359

Open
daggerstuff wants to merge 6 commits intostagingfrom
palette/ux-loader-a11y-12345-18377366236368127758
Open

🎨 Palette: add ARIA loading status to Loader#359
daggerstuff wants to merge 6 commits intostagingfrom
palette/ux-loader-a11y-12345-18377366236368127758

Conversation

@daggerstuff
Copy link
Copy Markdown
Owner

@daggerstuff daggerstuff commented Apr 2, 2026

💡 What: Added role="status" and a visually hidden <span class="sr-only">Loading...</span> to Loader.astro.
🎯 Why: To ensure screen readers announce the loading state correctly when the component is rendered.
📸 Before/After: The visual loader pulses identically before and after the change; the improvement is purely in the hidden DOM structure for assistive technologies.
♿ Accessibility: Improved screen reader announcements for background loading actions by providing explicit status roles and text.


PR created automatically by Jules for task 18377366236368127758 started by @daggerstuff

Summary by Sourcery

Enhancements:

  • Expose the Loader container as an ARIA status region with an explicit loading label and hidden text for assistive technologies.

Summary by cubic

Added ARIA loading status to Loader.astro by setting role="status", aria-label="Loading", and a visually hidden "Loading..." so screen readers announce the loading state.
Fixed Playwright CI by pointing testDir to ./tests/browser, setting use.baseURL to process.env.BASE_URL || 'http://localhost:4321', and updating the workflow to export BASE_URL=http://localhost:4321.

Written for commit c68335e. Summary will update on new commits.

Summary by CodeRabbit

  • Chores
    • Updated test discovery to use the browser tests directory instead of the legacy e2e folder.
    • Set the default test server endpoint to http://localhost:4321, with optional override via an environment variable.
    • Aligned CI/browser test job to use the same default test server endpoint.

Co-authored-by: daggerstuff <261005129+daggerstuff@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings April 2, 2026 11:07
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pixelated Ready Ready Preview, Comment Apr 2, 2026 5:13pm

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 2, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds ARIA live status semantics and screen-reader-only loading text to the Loader component without changing its visual behavior.

File-Level Changes

Change Details Files
Enhance Loader component with ARIA status semantics and hidden accessible loading text.
  • Add role="status" to the Loader container to expose it as a status region to assistive technologies.
  • Add aria-label="Loading" on the Loader container to provide an accessible name for the status.
  • Insert a visually hidden Loading... inside the Loader so screen readers announce the loading state textually.
src/components/widgets/Loader.astro

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

Playwright test configuration and CI workflow updated: test discovery directory changed to ./tests/browser; Playwright use.baseURL now reads process.env.BASE_URL || 'http://localhost:4321'; CI workflow BASE_URL adjusted to http://localhost:4321.

Changes

Cohort / File(s) Summary
Playwright Configuration
playwright.config.ts
testDir changed from ./e2e./tests/browser. Enabled use.baseURL as `process.env.BASE_URL
CI Workflow
.github/workflows/browser-tests.yml
Updated workflow BASE_URL environment variable from http://localhost:4323http://localhost:4321.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • CharlieHelps

Poem

🐰 I hopped from old paths to new,
Tests chase me where the breezes blew.
BASE_URL set, four-three-two-one—
I munch a carrot, now it's done. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title references 'add ARIA loading status to Loader' but the actual changes primarily concern Playwright configuration (testDir, baseURL) and CI workflow updates; the Loader.astro accessibility changes are not evident in the provided summaries. Revise the title to accurately reflect the main changes: 'Fix Playwright configuration and CI workflow for browser tests' or include both accessibility and test configuration updates.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch palette/ux-loader-a11y-12345-18377366236368127758

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.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Using both role="status" and an aria-label plus visible DOM text can be redundant; consider removing the aria-label and letting the visually hidden Loading... span provide the accessible name for the status region.
  • Confirm that the sr-only utility is defined to follow common visually-hidden patterns (e.g., Tailwind’s) so that the Loading... text is reliably hidden visually while remaining available to assistive technologies.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Using both `role="status"` and an `aria-label` plus visible DOM text can be redundant; consider removing the `aria-label` and letting the visually hidden `Loading...` span provide the accessible name for the status region.
- Confirm that the `sr-only` utility is defined to follow common visually-hidden patterns (e.g., Tailwind’s) so that the `Loading...` text is reliably hidden visually while remaining available to assistive technologies.

## Individual Comments

### Comment 1
<location path="src/components/widgets/Loader.astro" line_range="10-15" />
<code_context>
 <div
   {style}
   class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
+  role="status"
+  aria-label="Loading"
 >
+  <span class="sr-only">Loading...</span>
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Avoid redundant ARIA labelling when there is already visible (or sr-only) text content.

With the added `<span class="sr-only">Loading...</span>`, the `aria-label="Loading"` on the `role="status"` container is now redundant and may cause duplicate announcements in some screen readers. The text node inside the status region is enough—please remove the `aria-label` and rely on the sr-only text.

```suggestion
<div
  {style}
  class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
  role="status"
>
```
</issue_to_address>

Fix all in Cursor


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 10 to 15
<div
{style}
class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
role="status"
aria-label="Loading"
>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): Avoid redundant ARIA labelling when there is already visible (or sr-only) text content.

With the added <span class="sr-only">Loading...</span>, the aria-label="Loading" on the role="status" container is now redundant and may cause duplicate announcements in some screen readers. The text node inside the status region is enough—please remove the aria-label and rely on the sr-only text.

Suggested change
<div
{style}
class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
role="status"
aria-label="Loading"
>
<div
{style}
class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
role="status"
>

Fix in Cursor

Copy link
Copy Markdown

@charliecreates charliecreates bot left a comment

Choose a reason for hiding this comment

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

Accessibility is improved, but the current implementation likely duplicates announcements by combining aria-label with a hidden Loading... node inside a role="status" region. Also, the decorative pulsing dots should be aria-hidden to avoid potential AT noise.

Additional notes (1)
  • Maintainability | src/components/widgets/Loader.astro:17-19
    The three pulsing dots are purely decorative. Marking them aria-hidden="true" reduces the chance they get surfaced as noisy/meaningless content in certain screen reader modes, while the status text remains the only announced content.
Summary of changes

Loader accessibility improvements

  • Added role="status" to the Loader wrapper to expose a live status region to assistive tech.
  • Added an accessible loading label via aria-label="Loading".
  • Added visually hidden text (<span class="sr-only">Loading...</span>) so screen readers have explicit content to announce.

Comment on lines 10 to 17
<div
{style}
class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
role="status"
aria-label="Loading"
>
<span class="sr-only">Loading...</span>
<div
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

role="status" already causes the element’s content to be announced (implicit aria-live="polite"). With both aria-label="Loading" and a hidden text node (Loading...), some AT/browser combos can announce duplicated or inconsistent output. Prefer a single source of truth: either keep the hidden text and drop aria-label, or keep aria-label and drop the hidden span.

Suggestion

Pick one accessible name strategy to avoid double announcements. For example, keep the hidden text and remove the label (and optionally add aria-busy):

<div
  {style}
  class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
  role="status"
  aria-busy="true"
>
  <span class="sr-only">Loading...</span>
  ...
</div>

Reply with "@CharlieHelps yes please" if you’d like me to add a commit with this change.

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 the current code and only fix it if needed.

Inline comments:
In `@src/components/widgets/Loader.astro`:
- Around line 14-16: The Loader.astro component currently hard-codes the
user-facing strings in the aria-label and the screen-reader span; replace those
with i18n lookups (e.g., use your app's translation helper such as a
`t`/`translate` function or injected `i18n` prop) so both the aria-label and the
<span class="sr-only"> content call the translation key (e.g., "loading")
instead of literal "Loading"/"Loading..."; also add the corresponding
translation key to your locale resources and ensure Loader.astro imports or
receives the translation helper used across the app.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 72b4726d-9eb4-434e-bcaa-ae37207f62d2

📥 Commits

Reviewing files that changed from the base of the PR and between 9333c1a and 2b4a2b6.

📒 Files selected for processing (1)
  • src/components/widgets/Loader.astro

Comment on lines +14 to +16
aria-label="Loading"
>
<span class="sr-only">Loading...</span>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Localize loader announcement text instead of hard-coding English.

Line 14 and Line 16 hard-code user-facing text ("Loading" / "Loading..."), which will not be translated in non-English locales.

Suggested direction
 interface Props {
   style?: string
   class?: string
+  loadingLabel: string
 }

-const { style, class: className } = Astro.props
+const { style, class: className, loadingLabel } = Astro.props
 ---
@@
-  aria-label="Loading"
+  aria-label={loadingLabel}
 >
-  <span class="sr-only">Loading...</span>
+  <span class="sr-only">{loadingLabel}</span>

As per coding guidelines, "Do not hard-code user-facing strings in components; use i18n for internationalization".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
aria-label="Loading"
>
<span class="sr-only">Loading...</span>
interface Props {
style?: string
class?: string
loadingLabel: string
}
const { style, class: className, loadingLabel } = Astro.props
---
<div
class={cn("animate-spin", className)}
style={style}
role="status"
aria-label={loadingLabel}
>
<span class="sr-only">{loadingLabel}</span>
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/widgets/Loader.astro` around lines 14 - 16, The Loader.astro
component currently hard-codes the user-facing strings in the aria-label and the
screen-reader span; replace those with i18n lookups (e.g., use your app's
translation helper such as a `t`/`translate` function or injected `i18n` prop)
so both the aria-label and the <span class="sr-only"> content call the
translation key (e.g., "loading") instead of literal "Loading"/"Loading...";
also add the corresponding translation key to your locale resources and ensure
Loader.astro imports or receives the translation helper used across the app.

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

This PR improves the accessibility semantics of the Loader widget by exposing a screen-reader friendly loading announcement when the component is rendered.

Changes:

  • Added role="status" to the loader container to expose it as a live status region.
  • Added a visually-hidden “Loading...” label intended for assistive technologies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

{style}
class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
role="status"
aria-label="Loading"
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

role="status" announcements are typically based on the element’s text content; adding both aria-label="Loading" and a visible-to-SR text node (<span class="sr-only">Loading...</span>) can lead to redundant/duplicative announcements in some screen readers. Consider dropping aria-label and relying on the sr-only text (matching existing role="status" usage elsewhere in the repo), or keep aria-label but remove the sr-only text so there’s a single source of truth.

Suggested change
aria-label="Loading"

Copilot uses AI. Check for mistakes.

<div
{style}
class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

className is optional in Props, but it’s interpolated directly into the class template literal. If class isn’t passed, ${className} becomes the literal string "undefined" in the rendered class attribute. Consider defaulting className to an empty string when destructuring props (or using className ?? '' in the template) to avoid emitting an unintended class.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/components/widgets/Loader.astro">

<violation number="1" location="src/components/widgets/Loader.astro:14">
P2: Remove `aria-label="Loading"` — the `role="status"` container already has the `<span class="sr-only">Loading...</span>` text node, which provides the accessible name. Having both can cause duplicate announcements in screen readers (e.g., NVDA, VoiceOver) since `aria-label` and the live-region text content are announced independently.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

{style}
class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
role="status"
aria-label="Loading"
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Apr 2, 2026

Choose a reason for hiding this comment

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

P2: Remove aria-label="Loading" — the role="status" container already has the <span class="sr-only">Loading...</span> text node, which provides the accessible name. Having both can cause duplicate announcements in screen readers (e.g., NVDA, VoiceOver) since aria-label and the live-region text content are announced independently.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/widgets/Loader.astro, line 14:

<comment>Remove `aria-label="Loading"` — the `role="status"` container already has the `<span class="sr-only">Loading...</span>` text node, which provides the accessible name. Having both can cause duplicate announcements in screen readers (e.g., NVDA, VoiceOver) since `aria-label` and the live-region text content are announced independently.</comment>

<file context>
@@ -10,7 +10,10 @@ const { style, class: className } = Astro.props
   {style}
   class={`flex items-center justify-center gap-3 h-full w-full ${className}`}
+  role="status"
+  aria-label="Loading"
 >
+  <span class="sr-only">Loading...</span>
</file context>
Fix with Cubic

…overy

Co-authored-by: daggerstuff <261005129+daggerstuff@users.noreply.github.com>
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 the current code and only fix it if needed.

Inline comments:
In `@playwright.config.ts`:
- Line 15: The Playwright config currently sets testDir: './' which causes
discovery of unintended tests; update the testDir value in the Playwright
configuration (the testDir property in the exported config object in
playwright.config.ts) to './tests' so test discovery is limited to the intended
tests suite and aligns with config/playwright.config.ts.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35f5878e-cb87-44ce-ae1c-60269c1b6b7f

📥 Commits

Reviewing files that changed from the base of the PR and between 2b4a2b6 and 4200fc0.

📒 Files selected for processing (1)
  • playwright.config.ts

*/
export default defineConfig({
testDir: './e2e',
testDir: './',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify whether root-level discovery would include test files outside ./tests
# Expected: ideally no output; any output indicates potential unintended pickup.
fd -t f -e ts -e tsx -e js -e jsx -e mjs -e cjs -e mts -e cts \
| rg -n '(\.spec|\.test)\.(ts|tsx|js|jsx|mjs|mts|cjs|cts)$' \
| rg -n -v '^tests/'

Repository: daggerstuff/pixelated

Length of output: 19671


Narrow root Playwright discovery scope to avoid unintended test pickup.

testDir: './' picks up hundreds of test files scattered across src/, src/tests/, src/lib/, src/components/, and other directories, creating inconsistency with config/playwright.config.ts (which uses ./tests). This broadens the scope for direct playwright test runs without explicit --config flag, leading to slower execution and potential for unrelated tests to fail. Change to ./tests to align with the narrower, intentional suite.

Suggested fix
-  testDir: './',
+  testDir: './tests',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
testDir: './',
testDir: './tests',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@playwright.config.ts` at line 15, The Playwright config currently sets
testDir: './' which causes discovery of unintended tests; update the testDir
value in the Playwright configuration (the testDir property in the exported
config object in playwright.config.ts) to './tests' so test discovery is limited
to the intended tests suite and aligns with config/playwright.config.ts.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="playwright.config.ts">

<violation number="1" location="playwright.config.ts:15">
P1: Changing `testDir` from `'./e2e'` to `'./'` causes Playwright to discover every `*.spec.*` / `*.test.*` file in the entire repository (including unit tests under `src/`, `src/lib/`, `src/components/`, etc.), not just the intended end-to-end suite. This will slow CI runs and surface failures from unrelated test files. Restrict the scope back to the e2e directory.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Co-authored-by: daggerstuff <261005129+daggerstuff@users.noreply.github.com>
**What**
- Updated `testDir` in `playwright.config.ts` from `'./e2e'` to `'./tests/browser'`
- Added `baseURL` configuration parsing `process.env.BASE_URL || 'http://localhost:4321'`
- Updated `BASE_URL` environment variable to point to port 4321 instead of 4323 in `.github/workflows/browser-tests.yml`

**Why**
The GitHub Action 'Run Browser Tests' was failing for two sequential reasons:
1. Playwright was throwing `Error: No tests found` because the CI workflow was targeting test files inside `tests/browser/` but the Playwright configuration explicitly restricted test discovery to the `./e2e` directory.
2. After test discovery was resolved, Playwright was encountering `net::ERR_CONNECTION_REFUSED` connecting to `http://localhost:4323`. This occurred because Astro's preview server ignores `--port 4323` passed as extra arguments through pnpm (`pnpm run preview -- --port 4323`) and defaults to port 4321 instead.

By setting the `BASE_URL` to `http://localhost:4321` (which is explicitly where the CI logs show the Astro node preview server listening) and correcting the `testDir` resolution path, the Playwright tests can now successfully run and hit the active preview server.

Co-authored-by: daggerstuff <261005129+daggerstuff@users.noreply.github.com>
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/browser-tests.yml">

<violation number="1" location=".github/workflows/browser-tests.yml:75">
P1: `BASE_URL` now points to port 4321, but the preview server still runs on 4323, so the browser tests will hit a non-existent server. Align the base URL with the preview port (or update the preview port consistently).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

**What**
- Updated `testDir` in `playwright.config.ts` from `'./e2e'` to `'./tests/browser'`
- Added `baseURL` configuration parsing `process.env.BASE_URL || 'http://localhost:4321'`
- Updated `BASE_URL` environment variable to point to port 4321 instead of 4323 in `.github/workflows/browser-tests.yml`

**Why**
The GitHub Action 'Run Browser Tests' was failing for two sequential reasons:
1. Playwright was throwing `Error: No tests found` because the CI workflow was targeting test files inside `tests/browser/` but the Playwright configuration explicitly restricted test discovery to the `./e2e` directory.
2. After test discovery was resolved, Playwright was encountering `net::ERR_CONNECTION_REFUSED` connecting to `http://localhost:4323`. This occurred because Astro's preview server ignores `--port 4323` passed as extra arguments through pnpm (`pnpm run preview -- --port 4323`) and defaults to port 4321 instead.

By setting the `BASE_URL` to `http://localhost:4321` (which is explicitly where the CI logs show the Astro node preview server listening) and correcting the `testDir` resolution path, the Playwright tests can now successfully run and hit the active preview server.

Co-authored-by: daggerstuff <261005129+daggerstuff@users.noreply.github.com>
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/browser-tests.yml (1)

62-76: ⚠️ Potential issue | 🔴 Critical

Port mismatch: preview server runs on 4323, but BASE_URL points to 4321.

Line 63 starts the preview server on port 4323, but line 75 sets BASE_URL to http://localhost:4321. Playwright will attempt to connect to port 4321 where nothing is listening, causing all tests to fail.

Align both to the same port:

🐛 Proposed fix: change preview server port to 4321
       - name: Start preview server in background
-        run: pnpm run preview -- --port 4323 &
+        run: pnpm run preview -- --port 4321 &
         shell: bash

Alternatively, keep the server on 4323 and revert the BASE_URL change:

🐛 Alternative fix: keep BASE_URL at 4323
-          export BASE_URL=http://localhost:4321
+          export BASE_URL=http://localhost:4323
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/browser-tests.yml around lines 62 - 76, The preview server
is started with "pnpm run preview -- --port 4323" but the Playwright tests use
BASE_URL=http://localhost:4321; update one so both use the same port—either
change the preview command to use --port 4321 or change the BASE_URL value to
http://localhost:4323—ensure the "Start preview server in background" command
and the BASE_URL environment variable are aligned so Playwright connects to the
running server.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/browser-tests.yml:
- Around line 62-76: The preview server is started with "pnpm run preview --
--port 4323" but the Playwright tests use BASE_URL=http://localhost:4321; update
one so both use the same port—either change the preview command to use --port
4321 or change the BASE_URL value to http://localhost:4323—ensure the "Start
preview server in background" command and the BASE_URL environment variable are
aligned so Playwright connects to the running server.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 018a6a08-fe63-46e6-9d29-2822558d22b4

📥 Commits

Reviewing files that changed from the base of the PR and between 0d6b6c8 and 8453764.

📒 Files selected for processing (1)
  • .github/workflows/browser-tests.yml

Co-authored-by: daggerstuff <261005129+daggerstuff@users.noreply.github.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 3, 2026

Deployment failed with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/daggers-projects-26434d0b?upgradeToPro=build-rate-limit

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="playwright.config.ts">

<violation number="1">
P2: testDir now points to ./e2e, which skips the existing Playwright suite under tests/browser. This reduces test coverage to a single example spec.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

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