Skip to content

Conversation

@webdevcody
Copy link
Collaborator

@webdevcody webdevcody commented Dec 22, 2025

Summary by CodeRabbit

  • Chores
    • Added an automated release workflow for macOS, Windows, and Linux with artifact publishing and version update automation.
  • Tests
    • Reorganized E2E test coverage: added numerous new UI integration tests (agents, context, features, profiles, projects, worktree scenarios) and removed several large legacy test suites to streamline the test matrix.
  • Chores
    • Standardized test setup state versioning for consistency.

✏️ Tip: You can customize this high-level summary in your review settings.

Test User added 2 commits December 22, 2025 14:26
- Introduced a new workflow in release.yml to automate the release process for macOS, Windows, and Linux.
- Added a script (update-version.mjs) to update the version in package.json based on the release tag.
- Configured artifact uploads for each platform and ensured proper version extraction and validation.
@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a GitHub Actions release workflow and a version-update script; reorganizes UI E2E tests by adding many focused Playwright specs and removing several large legacy suites; and updates test fixture/setup state versions from 2 to 0 in multiple test utilities.

Changes

Cohort / File(s) Summary
CI / Release automation
.github/workflows/release.yml
New GitHub Actions release workflow that builds the Electron UI for macOS, Windows, and Linux on release publish, uploads per-OS artifacts, and publishes them to the GitHub Release.
Build utility
apps/ui/scripts/update-version.mjs
New Node.js script to validate and update apps/ui/package.json version (strips leading v, basic semver check, writes updated JSON).
Context E2E tests (added)
apps/ui/tests/context/add-context-image.spec.ts, apps/ui/tests/context/context-file-management.spec.ts, apps/ui/tests/context/delete-context-file.spec.ts
New Playwright tests for importing images, creating/editing markdown context files, and deleting context files (UI interactions + filesystem assertions).
Feature E2E tests (added)
apps/ui/tests/features/add-feature-to-backlog.spec.ts, apps/ui/tests/features/edit-feature.spec.ts, apps/ui/tests/features/feature-manual-review-flow.spec.ts, apps/ui/tests/features/feature-skip-tests-toggle.spec.ts
New Playwright tests covering backlog addition, in-card description editing, manual review verification, and skip-tests badge visibility.
Profiles E2E tests (added/removed)
apps/ui/tests/profiles/profiles-crud.spec.ts, apps/ui/tests/profiles-view.spec.ts
Adds focused profile CRUD test (profiles-crud.spec.ts) and removes the large legacy profiles-view.spec.ts suite.
Agent E2E test (added)
apps/ui/tests/agent/start-new-chat-session.spec.ts
New Playwright test to start a new agent chat session and assert session/message UI state.
Project E2E tests (added/removed/updated)
apps/ui/tests/projects/new-project-creation.spec.ts, apps/ui/tests/projects/open-existing-project.spec.ts, apps/ui/tests/project-creation.spec.ts
Adds new-project-creation.spec.ts (blank project creation); updates import path in open-existing-project.spec.ts; removes legacy project-creation.spec.ts.
Worktree / Git tests (added/removed/changed)
apps/ui/tests/git/worktree-integration.spec.ts, apps/ui/tests/worktree-integration.spec.ts
Adds a focused worktree selector test and removes a large legacy worktree-integration.spec.ts suite.
Removed legacy monolithic suites
apps/ui/tests/context-view.spec.ts, apps/ui/tests/feature-lifecycle.spec.ts, apps/ui/tests/kanban-responsive-scaling.spec.ts, apps/ui/tests/spec-editor-persistence.spec.ts, apps/ui/tests/worktree-integration.spec.ts, apps/ui/tests/project-creation.spec.ts, apps/ui/tests/profiles-view.spec.ts
Deletes several large, legacy Playwright test files covering context view, feature lifecycle, kanban responsive scaling, spec editor persistence, worktree integration, project creation, and profiles view.
Test utility/version updates
apps/ui/tests/utils/git/worktree.ts, apps/ui/tests/utils/project/fixtures.ts, apps/ui/tests/utils/project/setup.ts
Change persisted setupState.version values from 2 to 0 in multiple test setup fixtures to align with default store versioning.
Other test additions
apps/ui/tests/features/*, apps/ui/tests/context/*, apps/ui/tests/profiles/*, apps/ui/tests/git/*, apps/ui/tests/agent/*, apps/ui/tests/projects/*
Multiple new, focused Playwright specs organized by feature area (features, context, profiles, git, agent, projects) replacing or splitting prior monolithic suites.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

Tests, Refactor

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Refactor e2e Tests' is vague and generic, using the non-descriptive term 'refactor' without clarifying what aspects of the e2e test suite were changed or why. Consider a more specific title that describes the primary change, such as 'Reorganize e2e tests into feature-specific modules' or 'Update e2e test file structure and migrate critical tests'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a69611d and d08be3c.

📒 Files selected for processing (1)
  • apps/ui/scripts/update-version.mjs

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @webdevcody, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the UI application's end-to-end test suite, aiming to improve its structure, maintainability, and clarity. The changes involve breaking down large test files into smaller, more focused modules, organizing them by feature, and introducing new tests for specific user flows. Additionally, a new script for version management and minor updates to test setup utilities are included.

Highlights

  • E2E Test Suite Refactoring: The end-to-end test suite has undergone a significant refactoring, moving from large, monolithic test files to a more modular and organized structure. Several existing test files have been removed and replaced with new, focused tests categorized by feature area (e.g., agent, context, features, git, profiles, projects).
  • New Version Update Script: A new utility script, update-version.mjs, has been added to automate the process of updating the apps/ui/package.json version. This script includes basic semantic versioning validation and handles 'v' prefixes.
  • Test Setup State Version Update: Several test utility functions (setupProjectWithPath, setupProjectWithFixture, etc.) have been updated to align the setup-store.ts persist version from 2 to 0. This is a minor internal adjustment for test state management.
  • Granular E2E Tests: New, specific E2E tests have been introduced for various functionalities, including starting new chat sessions, adding/deleting context images and files, managing feature backlog and editing features, verifying manual review flows, checking skip tests badges, and creating new projects.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request significantly refactors the end-to-end tests by breaking down large, monolithic test files into smaller, more focused specs. This is an excellent improvement for maintainability and readability. The new directory structure for tests is also much clearer.

My review focuses on the new test files. I've identified some code duplication in the test setup across several new files and suggest creating a shared helper function to address this. I also found a couple of minor issues with a brittle selector and a loose regex, for which I've provided suggestions.

Overall, this is a great refactoring that will make the e2e test suite easier to manage going forward.

const cleanVersion = version.startsWith('v') ? version.slice(1) : version;

// Validate version format (basic semver check)
if (!/^\d+\.\d+\.\d+/.test(cleanVersion)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The current regex /^\d+\.\d+\.\d+/ for version validation is a bit loose as it only checks the beginning of the string. This would incorrectly validate versions like 1.2.3.4 or 1.2.3-and-more. To ensure the version string strictly follows the X.Y.Z format, you should anchor the regex to the end of the string as well.

Suggested change
if (!/^\d+\.\d+\.\d+/.test(cleanVersion)) {
if (!/^\d+\.\d+\.\d+$/.test(cleanVersion)) {

Comment on lines +27 to +55
test.beforeAll(async () => {
if (!fs.existsSync(TEST_TEMP_DIR)) {
fs.mkdirSync(TEST_TEMP_DIR, { recursive: true });
}

projectPath = path.join(TEST_TEMP_DIR, projectName);
fs.mkdirSync(projectPath, { recursive: true });

fs.writeFileSync(
path.join(projectPath, 'package.json'),
JSON.stringify({ name: projectName, version: '1.0.0' }, null, 2)
);

const automakerDir = path.join(projectPath, '.automaker');
fs.mkdirSync(automakerDir, { recursive: true });
fs.mkdirSync(path.join(automakerDir, 'features'), { recursive: true });
fs.mkdirSync(path.join(automakerDir, 'context'), { recursive: true });
fs.mkdirSync(path.join(automakerDir, 'sessions'), { recursive: true });

fs.writeFileSync(
path.join(automakerDir, 'categories.json'),
JSON.stringify({ categories: [] }, null, 2)
);

fs.writeFileSync(
path.join(automakerDir, 'app_spec.txt'),
`# ${projectName}\n\nA test project for e2e testing.`
);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This beforeAll setup block for creating a test project is duplicated across several new test files (e.g., add-feature-to-backlog.spec.ts, edit-feature.spec.ts, etc.). To improve maintainability and reduce code duplication, consider extracting this logic into a shared helper function in apps/ui/tests/utils/project/setup.ts. The helper could accept options to conditionally create directories like sessions when needed.

const featureId = cardTestId?.replace('kanban-card-', '');

// Collapse the sidebar first to avoid it intercepting clicks
const collapseSidebarButton = page.locator('button:has-text("Collapse sidebar")');
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using has-text for selectors can be brittle as UI text might change. It's more robust to use a data-testid attribute for test-specific element selection. Please consider adding a data-testid to this button, for example data-testid="sidebar-collapse-button", and updating the selector here.

Suggested change
const collapseSidebarButton = page.locator('button:has-text("Collapse sidebar")');
const collapseSidebarButton = page.locator('[data-testid="sidebar-collapse-button"]');

Copy link

@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

♻️ Duplicate comments (3)
apps/ui/tests/features/feature-manual-review-flow.spec.ts (1)

31-77: Same project setup duplication as other feature tests.

This beforeAll setup duplicates the same project structure code found in other feature test files. Consider using the shared helper function suggested in the review of feature-skip-tests-toggle.spec.ts.

For this file, you would call it with a feature in waiting_approval status:

projectPath = await createTestProject(TEST_TEMP_DIR, projectName, {
  features: [
    {
      id: featureId,
      status: 'waiting_approval',
      description: 'Test feature for manual review flow',
    },
  ],
});
apps/ui/tests/features/edit-feature.spec.ts (1)

27-54: Same project setup duplication as other feature tests.

This beforeAll setup duplicates the same project structure code. Refer to the refactoring suggestion in feature-skip-tests-toggle.spec.ts to extract this into a shared helper.

apps/ui/tests/features/add-feature-to-backlog.spec.ts (1)

26-53: Same project setup duplication as other feature tests.

This beforeAll setup duplicates the same project structure code. Refer to the refactoring suggestion in feature-skip-tests-toggle.spec.ts to extract this into a shared helper.

🧹 Nitpick comments (10)
apps/ui/tests/context/context-file-management.spec.ts (2)

28-30: Consider removing the redundant afterEach hook.

Since beforeEach already resets the context directory before each test, the afterEach cleanup is redundant. If cleanup after all tests is desired, use test.afterAll() instead.

🔎 Proposed refactor
-  test.afterEach(async () => {
-    resetContextDirectory();
-  });

33-37: Simplify navigation by removing redundant page load.

The test navigates to / then immediately to /context. Since navigateToContext() already handles navigation to /context with proper waiting, the initial navigation to / is unnecessary and adds overhead.

🔎 Proposed refactor
   await setupProjectWithFixture(page, getFixturePath());
-  await page.goto('/');
-  await waitForNetworkIdle(page);
-
   await navigateToContext(page);
apps/ui/tests/context/delete-context-file.spec.ts (3)

28-30: Consider removing the redundant afterEach hook.

Since beforeEach already resets the context directory before each test, the afterEach cleanup is redundant. If cleanup after all tests is desired, use test.afterAll() instead.

🔎 Proposed refactor
-  test.afterEach(async () => {
-    resetContextDirectory();
-  });

35-39: Simplify navigation by removing redundant page load.

The test navigates to / then immediately to /context. Since navigateToContext() already handles navigation to /context with proper waiting, the initial navigation to / is unnecessary and adds overhead.

🔎 Proposed refactor
   await setupProjectWithFixture(page, getFixturePath());
-  await page.goto('/');
-  await waitForNetworkIdle(page);
-
   await navigateToContext(page);

41-56: Extract duplicated file creation logic into a utility function.

The markdown file creation logic (lines 42-53) is duplicated from context-file-management.spec.ts. This duplication makes maintenance harder if the creation flow changes.

🔎 Proposed refactor

Add this utility function to apps/ui/tests/utils/views/context.ts:

export async function createMarkdownContextFile(
  page: Page,
  filename: string,
  content: string
): Promise<void> {
  await clickElement(page, 'create-markdown-button');
  await page.waitForSelector('[data-testid="create-markdown-dialog"]', { timeout: 5000 });
  
  await fillInput(page, 'new-markdown-name', filename);
  await fillInput(page, 'new-markdown-content', content);
  
  await clickElement(page, 'confirm-create-markdown');
  
  await page.waitForFunction(
    () => !document.querySelector('[data-testid="create-markdown-dialog"]'),
    { timeout: 5000 }
  );
  
  await waitForContextFile(page, filename, 10000);
}

Then use it in both test files:

- await clickElement(page, 'create-markdown-button');
- await page.waitForSelector('[data-testid="create-markdown-dialog"]', { timeout: 5000 });
-
- await fillInput(page, 'new-markdown-name', fileName);
- await fillInput(page, 'new-markdown-content', '# Test File\n\nThis file will be deleted.');
-
- await clickElement(page, 'confirm-create-markdown');
-
- await page.waitForFunction(
-   () => !document.querySelector('[data-testid="create-markdown-dialog"]'),
-   { timeout: 5000 }
- );
-
- // Wait for the file to appear in the list
- await waitForContextFile(page, fileName, 10000);
+ await createMarkdownContextFile(page, fileName, '# Test File\n\nThis file will be deleted.');
apps/ui/tests/context/add-context-image.spec.ts (4)

22-101: Simplify test image creation.

The 80 lines of hardcoded PNG bytes are difficult to maintain and obscure test intent. Consider these alternatives:

  1. Store a test fixture image in the repository (e.g., apps/ui/tests/fixtures/test-image.png)
  2. Use a PNG library like pngjs to generate the image programmatically
  3. Use a simpler format if PNG specifics aren't being tested
🔎 Proposed refactor using a fixture file

Create apps/ui/tests/fixtures/test-image.png (a simple 1x1 image) and simplify the test:

  test.beforeAll(async () => {
-   // Create a simple test image (1x1 red PNG)
    const fixturePath = getFixturePath();
-   testImagePath = path.join(fixturePath, '..', 'test-image.png');
-
-   // Create a minimal PNG (1x1 pixel red image)
-   const pngHeader = Buffer.from([
-     0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
-     // ... (80+ lines of bytes)
-   ]);
-
-   fs.writeFileSync(testImagePath, pngHeader);
+   testImagePath = path.join(__dirname, '..', 'fixtures', 'test-image.png');
  });

Remove the afterAll cleanup since the file is now a permanent fixture:

- test.afterAll(async () => {
-   // Clean up test image
-   if (fs.existsSync(testImagePath)) {
-     fs.unlinkSync(testImagePath);
-   }
- });

107-109: Consider removing the redundant afterEach hook.

Since beforeEach already resets the context directory before each test, the afterEach cleanup is redundant. If cleanup after all tests is desired, use test.afterAll() instead.

🔎 Proposed refactor
-  test.afterEach(async () => {
-    resetContextDirectory();
-  });

119-123: Simplify navigation by removing redundant page load.

The test navigates to / then immediately to /context. Since navigateToContext() already handles navigation to /context with proper waiting, the initial navigation to / is unnecessary and adds overhead.

🔎 Proposed refactor
   await setupProjectWithFixture(page, getFixturePath());
-  await page.goto('/');
-  await waitForNetworkIdle(page);
-
   await navigateToContext(page);

125-133: Consider using consistent timeouts across tests.

This test uses a 15-second timeout for waitForContextFile (line 133), while the other context tests use 10 seconds. Unless image processing specifically requires more time, consider using the standard 10-second timeout for consistency.

🔎 Proposed refactor
- await waitForContextFile(page, fileName, 15000);
+ await waitForContextFile(page, fileName, 10000);
apps/ui/tests/features/edit-feature.spec.ts (1)

97-102: Consider using Playwright's built-in wait instead of hardcoded timeout.

The hardcoded 300ms wait for sidebar animation could be flaky on slower systems or CI environments.

💡 Recommended approach

Replace the hardcoded timeout with a more robust wait condition:

  const collapseSidebarButton = page.locator('button:has-text("Collapse sidebar")');
  if (await collapseSidebarButton.isVisible()) {
    await collapseSidebarButton.click();
-   await page.waitForTimeout(300); // Wait for sidebar animation
+   // Wait for sidebar to actually collapse by checking its state
+   await expect(page.locator('[data-testid="sidebar"]')).toHaveAttribute('data-state', 'collapsed', { timeout: 1000 });
  }

Alternatively, if there's no reliable attribute to check, use a shorter timeout with a comment explaining it's specifically for animation:

await page.waitForTimeout(200); // Brief wait for sidebar collapse animation
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83af319 and a69611d.

📒 Files selected for processing (24)
  • .github/workflows/release.yml
  • apps/ui/scripts/update-version.mjs
  • apps/ui/tests/agent/start-new-chat-session.spec.ts
  • apps/ui/tests/context-view.spec.ts
  • apps/ui/tests/context/add-context-image.spec.ts
  • apps/ui/tests/context/context-file-management.spec.ts
  • apps/ui/tests/context/delete-context-file.spec.ts
  • apps/ui/tests/feature-lifecycle.spec.ts
  • apps/ui/tests/features/add-feature-to-backlog.spec.ts
  • apps/ui/tests/features/edit-feature.spec.ts
  • apps/ui/tests/features/feature-manual-review-flow.spec.ts
  • apps/ui/tests/features/feature-skip-tests-toggle.spec.ts
  • apps/ui/tests/git/worktree-integration.spec.ts
  • apps/ui/tests/kanban-responsive-scaling.spec.ts
  • apps/ui/tests/profiles-view.spec.ts
  • apps/ui/tests/profiles/profiles-crud.spec.ts
  • apps/ui/tests/project-creation.spec.ts
  • apps/ui/tests/projects/new-project-creation.spec.ts
  • apps/ui/tests/projects/open-existing-project.spec.ts
  • apps/ui/tests/spec-editor-persistence.spec.ts
  • apps/ui/tests/utils/git/worktree.ts
  • apps/ui/tests/utils/project/fixtures.ts
  • apps/ui/tests/utils/project/setup.ts
  • apps/ui/tests/worktree-integration.spec.ts
💤 Files with no reviewable changes (7)
  • apps/ui/tests/context-view.spec.ts
  • apps/ui/tests/profiles-view.spec.ts
  • apps/ui/tests/feature-lifecycle.spec.ts
  • apps/ui/tests/spec-editor-persistence.spec.ts
  • apps/ui/tests/kanban-responsive-scaling.spec.ts
  • apps/ui/tests/project-creation.spec.ts
  • apps/ui/tests/worktree-integration.spec.ts
🧰 Additional context used
🧬 Code graph analysis (7)
apps/ui/tests/context/delete-context-file.spec.ts (3)
apps/ui/tests/utils/project/fixtures.ts (3)
  • resetContextDirectory (46-51)
  • setupProjectWithFixture (73-114)
  • getFixturePath (119-121)
apps/ui/tests/utils/navigation/views.ts (1)
  • navigateToContext (22-41)
apps/ui/tests/utils/views/context.ts (3)
  • waitForContextFile (118-125)
  • selectContextFile (131-147)
  • deleteSelectedContextFile (88-93)
apps/ui/tests/profiles/profiles-crud.spec.ts (2)
apps/ui/tests/utils/project/setup.ts (1)
  • setupMockProjectWithProfiles (777-882)
apps/ui/tests/utils/components/toasts.ts (1)
  • waitForSuccessToast (69-85)
apps/ui/tests/git/worktree-integration.spec.ts (1)
apps/ui/tests/utils/git/worktree.ts (6)
  • createTempDirPath (52-55)
  • TestRepo (19-22)
  • createTestGitRepo (72-108)
  • cleanupTempDir (149-153)
  • setupProjectWithPath (316-360)
  • waitForBoardView (477-495)
apps/ui/tests/agent/start-new-chat-session.spec.ts (4)
apps/ui/tests/utils/git/worktree.ts (2)
  • createTempDirPath (52-55)
  • cleanupTempDir (149-153)
.github/scripts/upload-to-r2.js (1)
  • fs (2-2)
apps/ui/tests/utils/project/setup.ts (1)
  • setupRealProject (97-160)
apps/ui/tests/utils/navigation/views.ts (1)
  • navigateToAgent (77-84)
apps/ui/tests/context/context-file-management.spec.ts (3)
apps/ui/tests/utils/project/fixtures.ts (3)
  • resetContextDirectory (46-51)
  • setupProjectWithFixture (73-114)
  • getFixturePath (119-121)
apps/ui/tests/utils/navigation/views.ts (1)
  • navigateToContext (22-41)
apps/ui/tests/utils/views/context.ts (4)
  • waitForContextFile (118-125)
  • waitForFileContentToLoad (152-158)
  • switchToEditMode (164-177)
  • getContextEditorContent (32-35)
apps/ui/tests/features/edit-feature.spec.ts (3)
apps/ui/tests/utils/git/worktree.ts (2)
  • createTempDirPath (52-55)
  • cleanupTempDir (149-153)
apps/ui/tests/utils/project/setup.ts (1)
  • setupRealProject (97-160)
apps/ui/tests/utils/views/board.ts (3)
  • clickAddFeature (98-103)
  • fillAddFeatureDialog (108-153)
  • confirmAddFeature (158-164)
apps/ui/tests/projects/new-project-creation.spec.ts (2)
apps/ui/tests/utils/git/worktree.ts (2)
  • createTempDirPath (52-55)
  • cleanupTempDir (149-153)
apps/ui/tests/utils/project/setup.ts (1)
  • setupWelcomeView (39-86)
🪛 GitHub Actions: Format Check
apps/ui/scripts/update-version.mjs

[error] 1-1: Prettier formatting check failed for 'apps/ui/scripts/update-version.mjs'. Run 'prettier --write' to fix code style issues.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (26)
apps/ui/tests/projects/open-existing-project.spec.ts (1)

14-14: LGTM! Import path correctly updated to shared utilities.

The import path change consolidates test utilities from a local module to a shared parent location (../utils), aligning with the PR's test reorganization. All required functions (createTempDirPath, cleanupTempDir, setupWelcomeView) are properly exported from the utils module index.

apps/ui/tests/context/context-file-management.spec.ts (1)

32-66: Test logic is well-structured.

The test properly covers the happy path for creating and editing a markdown context file with appropriate waits and assertions.

apps/ui/tests/context/delete-context-file.spec.ts (1)

64-73: Verification logic is robust.

The test properly verifies both UI state (file removed from list) and filesystem state (file deleted from disk) with appropriate timeout handling.

apps/ui/tests/context/add-context-image.spec.ts (1)

135-144: Verification approach is solid.

The test properly verifies both UI state and filesystem state with appropriate timeout handling for eventual consistency.

apps/ui/tests/utils/git/worktree.ts (1)

356-356: Consistent version alignment across setup functions.

The version changes are consistent across all three setup functions. This maintains uniformity in test initialization. The same verification requested for fixtures.ts applies here: confirm that setup-store.ts defaults to version 0.

Also applies to: 407-407, 462-462

apps/ui/tests/git/worktree-integration.spec.ts (1)

25-60: Well-structured E2E test with proper lifecycle management.

The test follows good practices:

  • Proper setup and teardown with beforeAll/afterAll hooks
  • Cleanup of temporary resources
  • Appropriate use of test utilities
  • Reasonable timeout values for UI element visibility
apps/ui/tests/profiles/profiles-crud.spec.ts (1)

19-43: Clean profile creation test with good validation.

The test effectively validates the profile creation flow:

  • Starts with zero custom profiles
  • Uses utility functions for form interactions
  • Verifies success via toast notification
  • Confirms profile count increment
apps/ui/tests/utils/project/setup.ts (1)

878-878: Version update aligns with STORE_VERSIONS constant.

The change is consistent with the STORE_VERSIONS.SETUP_STORE constant defined at lines 7-10, which already documents that setup-store defaults to 0. This maintains consistency across the test utilities.

apps/ui/tests/agent/start-new-chat-session.spec.ts (1)

27-89: Thorough test setup with realistic project structure.

The test demonstrates good practices:

  • Creates a complete project directory structure with all necessary subdirectories
  • Includes configuration files (package.json, categories.json, app_spec.txt)
  • Uses real project setup for more realistic testing
  • Validates multiple UI elements to ensure proper session initialization
  • Properly cleans up temporary resources
apps/ui/tests/utils/project/fixtures.ts (1)

110-110: Verify that setup-store.ts defaults to version 0.

The comment is correct. The setup-store.ts persist middleware does not specify a version parameter (lines 173-180 show only name and partialize options), which means zustand defaults to version 0. The fixture correctly sets version: 0 to match this behavior.

apps/ui/scripts/update-version.mjs (4)

1-13: LGTM!

The shebang, imports, and ES module __dirname setup follow standard patterns.


15-21: LGTM!

Argument validation is clear and provides helpful error messages with proper exit codes.


23-24: LGTM!

The logic to strip the 'v' prefix is correct and handles the expected input format.


33-46: LGTM!

The file I/O logic is solid:

  • Path construction correctly resolves to apps/ui/package.json
  • Proper error handling with try-catch
  • Pretty-prints JSON with trailing newline
  • Logs the version change
.github/workflows/release.yml (7)

1-12: LGTM!

The workflow trigger and matrix strategy are correctly configured for cross-platform Electron builds.


14-26: LGTM!

Version extraction logic correctly strips the 'v' prefix and uses the modern GITHUB_OUTPUT approach for setting step outputs.


28-31: LGTM!

The script invocation correctly passes the extracted version to update-version.mjs.


33-36: LGTM!

The setup step appropriately enables lockfile checking for reproducible release builds.


38-53: LGTM!

Build steps are correctly conditioned per OS with appropriate environment variables (e.g., disabling macOS code signing in CI).


55-77: LGTM!

Artifact upload steps correctly use glob patterns and appropriate retention policies. The artifact names are unique per OS, preventing collisions.


79-111: LGTM!

The upload job correctly:

  • Depends on the build job completion
  • Skips draft releases
  • Downloads all OS artifacts
  • Publishes to the GitHub Release using standard patterns
apps/ui/tests/projects/new-project-creation.spec.ts (1)

1-52: Well-structured E2E test for project creation.

The test follows good practices with proper setup/teardown, unique naming for test isolation, and comprehensive verification of both UI state and file system artifacts.

apps/ui/tests/features/feature-skip-tests-toggle.spec.ts (1)

63-106: Test logic is correct and well-structured.

The test properly verifies that the skip tests badge appears by default for newly created features.

apps/ui/tests/features/feature-manual-review-flow.spec.ts (1)

83-118: Manual review flow test is well-implemented.

The test correctly verifies the manual verification button appears for features in waiting_approval status and that clicking it moves the feature to the verified column. Good use of polling assertions with toPass() for handling async UI updates.

apps/ui/tests/features/edit-feature.spec.ts (1)

60-138: Edit feature test is well-structured and comprehensive.

The test properly handles potential click interception issues by collapsing the sidebar and using JavaScript click when needed. Good verification of both the UI update and dialog lifecycle.

apps/ui/tests/features/add-feature-to-backlog.spec.ts (1)

59-84: Add feature to backlog test is clean and effective.

The test follows a straightforward flow and properly verifies the feature appears in the backlog using polling assertions. Well done!

Comment on lines +26 to +31
// Validate version format (basic semver check)
if (!/^\d+\.\d+\.\d+/.test(cleanVersion)) {
console.error(`Error: Invalid version format: ${cleanVersion}`);
console.error('Expected format: X.Y.Z (e.g., 1.2.3)');
process.exit(1);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Strengthen semver validation to reject invalid suffixes.

The regex /^\d+\.\d+\.\d+/ only checks if the version starts with the pattern but doesn't anchor to the end of the string. This would incorrectly accept invalid versions like "1.2.3abc" or "1.2.3-".

🔎 Proposed fix
 // Validate version format (basic semver check)
-if (!/^\d+\.\d+\.\d+/.test(cleanVersion)) {
+if (!/^\d+\.\d+\.\d+$/.test(cleanVersion)) {
   console.error(`Error: Invalid version format: ${cleanVersion}`);
   console.error('Expected format: X.Y.Z (e.g., 1.2.3)');
   process.exit(1);
 }
🤖 Prompt for AI Agents
In apps/ui/scripts/update-version.mjs around lines 26 to 31, the current regex
only anchors the start and will accept invalid suffixes like "1.2.3abc"; update
the validation to anchor the end and use a stricter semver pattern — replace the
regex with a full semver-aware one (for example
/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/) so versions with
invalid trailing characters are rejected, keep the existing error messages and
exit behavior.

Comment on lines +26 to +57
test.describe('Feature Skip Tests Badge', () => {
let projectPath: string;
const projectName = `test-project-${Date.now()}`;

test.beforeAll(async () => {
if (!fs.existsSync(TEST_TEMP_DIR)) {
fs.mkdirSync(TEST_TEMP_DIR, { recursive: true });
}

projectPath = path.join(TEST_TEMP_DIR, projectName);
fs.mkdirSync(projectPath, { recursive: true });

fs.writeFileSync(
path.join(projectPath, 'package.json'),
JSON.stringify({ name: projectName, version: '1.0.0' }, null, 2)
);

const automakerDir = path.join(projectPath, '.automaker');
fs.mkdirSync(automakerDir, { recursive: true });
fs.mkdirSync(path.join(automakerDir, 'features'), { recursive: true });
fs.mkdirSync(path.join(automakerDir, 'context'), { recursive: true });

fs.writeFileSync(
path.join(automakerDir, 'categories.json'),
JSON.stringify({ categories: [] }, null, 2)
);

fs.writeFileSync(
path.join(automakerDir, 'app_spec.txt'),
`# ${projectName}\n\nA test project for e2e testing.`
);
});
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Extract duplicated project setup into shared helper.

The project structure setup in beforeAll (lines 26-57) is nearly identical across multiple test files (feature-skip-tests-toggle.spec.ts, feature-manual-review-flow.spec.ts, edit-feature.spec.ts, add-feature-to-backlog.spec.ts). This violates DRY principles and creates a maintenance burden.

💡 Recommended refactor

Extract this setup logic into a shared utility function in apps/ui/tests/utils/project/setup.ts:

export async function createTestProject(
  tempDir: string,
  projectName: string,
  options?: {
    features?: Array<{ id: string; status: string; description: string }>;
  }
): Promise<string> {
  const projectPath = path.join(tempDir, projectName);
  fs.mkdirSync(projectPath, { recursive: true });

  fs.writeFileSync(
    path.join(projectPath, 'package.json'),
    JSON.stringify({ name: projectName, version: '1.0.0' }, null, 2)
  );

  const automakerDir = path.join(projectPath, '.automaker');
  fs.mkdirSync(automakerDir, { recursive: true });
  fs.mkdirSync(path.join(automakerDir, 'features'), { recursive: true });
  fs.mkdirSync(path.join(automakerDir, 'context'), { recursive: true });

  fs.writeFileSync(
    path.join(automakerDir, 'categories.json'),
    JSON.stringify({ categories: [] }, null, 2)
  );

  fs.writeFileSync(
    path.join(automakerDir, 'app_spec.txt'),
    `# ${projectName}\n\nA test project for e2e testing.`
  );

  // Add features if provided
  if (options?.features) {
    for (const feature of options.features) {
      const featureDir = path.join(automakerDir, 'features', feature.id);
      fs.mkdirSync(featureDir, { recursive: true });
      const featureData = {
        id: feature.id,
        description: feature.description,
        category: 'test',
        status: feature.status,
        skipTests: true,
        model: 'sonnet',
        thinkingLevel: 'none',
        createdAt: new Date().toISOString(),
        branchName: '',
        priority: 2,
      };
      fs.writeFileSync(
        path.join(featureDir, 'feature.json'),
        JSON.stringify(featureData, null, 2)
      );
    }
  }

  return projectPath;
}

Then simplify each test's beforeAll to:

  test.beforeAll(async () => {
    if (!fs.existsSync(TEST_TEMP_DIR)) {
      fs.mkdirSync(TEST_TEMP_DIR, { recursive: true });
    }
-
-   projectPath = path.join(TEST_TEMP_DIR, projectName);
-   fs.mkdirSync(projectPath, { recursive: true });
-
-   fs.writeFileSync(
-     path.join(projectPath, 'package.json'),
-     JSON.stringify({ name: projectName, version: '1.0.0' }, null, 2)
-   );
-
-   const automakerDir = path.join(projectPath, '.automaker');
-   fs.mkdirSync(automakerDir, { recursive: true });
-   fs.mkdirSync(path.join(automakerDir, 'features'), { recursive: true });
-   fs.mkdirSync(path.join(automakerDir, 'context'), { recursive: true });
-
-   fs.writeFileSync(
-     path.join(automakerDir, 'categories.json'),
-     JSON.stringify({ categories: [] }, null, 2)
-   );
-
-   fs.writeFileSync(
-     path.join(automakerDir, 'app_spec.txt'),
-     `# ${projectName}\n\nA test project for e2e testing.`
-   );
+   projectPath = await createTestProject(TEST_TEMP_DIR, projectName);
  });

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/ui/tests/features/feature-skip-tests-toggle.spec.ts around lines 26-57,
the project setup logic is duplicated across multiple test files; extract this
logic into a shared helper (e.g. apps/ui/tests/utils/project/setup.ts) named
createTestProject(tempDir, projectName, options?) that creates the temp project
dir, .automaker tree, package.json, categories.json, app_spec.txt and optionally
creates feature subfolders with feature.json; then replace the beforeAll block
in this file (and the other tests) with a call to
createTestProject(TEST_TEMP_DIR, projectName, { features: [...] }) so tests
reuse the single utility and avoid duplication.

- Removed unnecessary blank lines in the update-version.mjs script for improved readability.
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