mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
Merge origin/main into feature/shared-packages
This commit is contained in:
@@ -110,8 +110,8 @@ test.describe("Kanban Responsive Scaling Tests", () => {
|
||||
expect(Math.abs(columnWidth - baseWidth)).toBeLessThan(2);
|
||||
}
|
||||
|
||||
// Column width should be within expected bounds (240px min, 360px max)
|
||||
expect(baseWidth).toBeGreaterThanOrEqual(240);
|
||||
// Column width should be within expected bounds (280px min, 360px max)
|
||||
expect(baseWidth).toBeGreaterThanOrEqual(280);
|
||||
expect(baseWidth).toBeLessThanOrEqual(360);
|
||||
|
||||
// Columns should not overlap (check x positions)
|
||||
@@ -149,9 +149,30 @@ test.describe("Kanban Responsive Scaling Tests", () => {
|
||||
expect(verifiedBox).not.toBeNull();
|
||||
|
||||
if (backlogBox && verifiedBox) {
|
||||
// Calculate the left and right margins
|
||||
const leftMargin = backlogBox.x;
|
||||
const rightMargin = 1600 - (verifiedBox.x + verifiedBox.width);
|
||||
// Get the actual container width (accounting for sidebar)
|
||||
// The board-view container is inside a flex container that accounts for sidebar
|
||||
const containerWidth = await page.evaluate(() => {
|
||||
const boardView = document.querySelector('[data-testid="board-view"]');
|
||||
if (!boardView) return window.innerWidth;
|
||||
const parent = boardView.parentElement;
|
||||
return parent ? parent.clientWidth : window.innerWidth;
|
||||
});
|
||||
|
||||
// Calculate the left and right margins relative to the container
|
||||
// The bounding box x is relative to the viewport, so we need to find where
|
||||
// the container starts relative to the viewport
|
||||
const containerLeft = await page.evaluate(() => {
|
||||
const boardView = document.querySelector('[data-testid="board-view"]');
|
||||
if (!boardView) return 0;
|
||||
const parent = boardView.parentElement;
|
||||
if (!parent) return 0;
|
||||
const rect = parent.getBoundingClientRect();
|
||||
return rect.left;
|
||||
});
|
||||
|
||||
// Calculate margins relative to the container
|
||||
const leftMargin = backlogBox.x - containerLeft;
|
||||
const rightMargin = containerWidth - (verifiedBox.x + verifiedBox.width - containerLeft);
|
||||
|
||||
// The margins should be roughly equal (columns are centered)
|
||||
// Allow for some tolerance due to padding and gaps
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
/**
|
||||
* Settings Marketing Content Toggle Tests
|
||||
*
|
||||
* Tests for the "Hide marketing content" setting in the Appearance section.
|
||||
*/
|
||||
|
||||
import { test, expect } from "@playwright/test";
|
||||
import * as fs from "fs";
|
||||
|
||||
import {
|
||||
waitForNetworkIdle,
|
||||
createTestGitRepo,
|
||||
cleanupTempDir,
|
||||
createTempDirPath,
|
||||
setupProjectWithPathNoWorktrees,
|
||||
navigateToSettings,
|
||||
} from "./utils";
|
||||
|
||||
// Create unique temp dir for this test run
|
||||
const TEST_TEMP_DIR = createTempDirPath("settings-marketing-tests");
|
||||
|
||||
interface TestRepo {
|
||||
path: string;
|
||||
cleanup: () => Promise<void>;
|
||||
}
|
||||
|
||||
// Configure all tests to run serially
|
||||
test.describe.configure({ mode: "serial" });
|
||||
|
||||
test.describe("Settings Marketing Content Tests", () => {
|
||||
let testRepo: TestRepo;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
// Create test temp directory
|
||||
if (!fs.existsSync(TEST_TEMP_DIR)) {
|
||||
fs.mkdirSync(TEST_TEMP_DIR, { recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
// Create a fresh test repo for each test
|
||||
testRepo = await createTestGitRepo(TEST_TEMP_DIR);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
// Cleanup test repo after each test
|
||||
if (testRepo) {
|
||||
await testRepo.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
// Cleanup temp directory
|
||||
cleanupTempDir(TEST_TEMP_DIR);
|
||||
});
|
||||
|
||||
test("should show course promo badge by default", async ({ page }) => {
|
||||
// Setup project without worktrees for simpler testing
|
||||
await setupProjectWithPathNoWorktrees(page, testRepo.path);
|
||||
await page.goto("/");
|
||||
await waitForNetworkIdle(page);
|
||||
|
||||
// Wait for sidebar to load
|
||||
await expect(page.locator('[data-testid="sidebar"]')).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
// Course promo badge should be visible by default
|
||||
const promoBadge = page.locator('[data-testid="course-promo-badge"]');
|
||||
await expect(promoBadge).toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
|
||||
test("should hide course promo badge when setting is enabled", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Setup project
|
||||
await setupProjectWithPathNoWorktrees(page, testRepo.path);
|
||||
await page.goto("/");
|
||||
await waitForNetworkIdle(page);
|
||||
|
||||
// Navigate to settings
|
||||
await navigateToSettings(page);
|
||||
|
||||
// Click on Appearance tab in settings navigation
|
||||
const appearanceTab = page.getByRole("button", { name: /appearance/i });
|
||||
await appearanceTab.click();
|
||||
|
||||
// Find and click the hide marketing content checkbox
|
||||
const hideMarketingCheckbox = page.locator(
|
||||
'[data-testid="hide-marketing-content-checkbox"]'
|
||||
);
|
||||
await expect(hideMarketingCheckbox).toBeVisible({ timeout: 5000 });
|
||||
await hideMarketingCheckbox.click();
|
||||
|
||||
// Navigate back to board to see the sidebar
|
||||
await page.goto("/board");
|
||||
await waitForNetworkIdle(page);
|
||||
|
||||
// Wait for Zustand store to rehydrate from localStorage
|
||||
await page.waitForFunction(() => {
|
||||
const storage = localStorage.getItem('automaker-storage');
|
||||
if (!storage) return false;
|
||||
const parsed = JSON.parse(storage);
|
||||
return parsed.state?.hideMarketingContent === true;
|
||||
});
|
||||
|
||||
// Course promo badge should now be hidden
|
||||
const promoBadge = page.locator('[data-testid="course-promo-badge"]');
|
||||
await expect(promoBadge).not.toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
|
||||
test("should persist hide marketing setting across page reloads", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Setup project
|
||||
await setupProjectWithPathNoWorktrees(page, testRepo.path);
|
||||
await page.goto("/");
|
||||
await waitForNetworkIdle(page);
|
||||
|
||||
// Navigate to settings and enable hide marketing
|
||||
await navigateToSettings(page);
|
||||
|
||||
const appearanceTab = page.getByRole("button", { name: /appearance/i });
|
||||
await appearanceTab.click();
|
||||
|
||||
const hideMarketingCheckbox = page.locator(
|
||||
'[data-testid="hide-marketing-content-checkbox"]'
|
||||
);
|
||||
await hideMarketingCheckbox.click();
|
||||
|
||||
// Reload the page
|
||||
await page.reload();
|
||||
await waitForNetworkIdle(page);
|
||||
|
||||
// Course promo badge should still be hidden after reload
|
||||
const promoBadge = page.locator('[data-testid="course-promo-badge"]');
|
||||
await expect(promoBadge).not.toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
|
||||
test("should show course promo badge again when setting is disabled", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Setup project with hide marketing already enabled via localStorage
|
||||
await page.addInitScript(() => {
|
||||
const state = {
|
||||
state: {
|
||||
hideMarketingContent: true,
|
||||
projects: [],
|
||||
currentProject: null,
|
||||
theme: "dark",
|
||||
sidebarOpen: true,
|
||||
},
|
||||
version: 2,
|
||||
};
|
||||
localStorage.setItem("automaker-storage", JSON.stringify(state));
|
||||
});
|
||||
|
||||
await setupProjectWithPathNoWorktrees(page, testRepo.path);
|
||||
await page.goto("/");
|
||||
await waitForNetworkIdle(page);
|
||||
|
||||
// Verify promo is hidden initially
|
||||
const promoBadge = page.locator('[data-testid="course-promo-badge"]');
|
||||
await expect(promoBadge).not.toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Navigate to settings and disable hide marketing
|
||||
await navigateToSettings(page);
|
||||
|
||||
const appearanceTab = page.getByRole("button", { name: /appearance/i });
|
||||
await appearanceTab.click();
|
||||
|
||||
const hideMarketingCheckbox = page.locator(
|
||||
'[data-testid="hide-marketing-content-checkbox"]'
|
||||
);
|
||||
await hideMarketingCheckbox.click(); // Uncheck
|
||||
|
||||
// Navigate back to board
|
||||
await page.goto("/board");
|
||||
await waitForNetworkIdle(page);
|
||||
|
||||
// Course promo badge should now be visible again
|
||||
await expect(promoBadge).toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
});
|
||||
@@ -799,10 +799,14 @@ test.describe("Worktree Integration Tests", () => {
|
||||
await clickAddFeature(page);
|
||||
|
||||
// Fill in the feature details with the new branch
|
||||
await fillAddFeatureDialog(page, "Feature that should auto-create worktree", {
|
||||
branch: branchName,
|
||||
category: "Testing",
|
||||
});
|
||||
await fillAddFeatureDialog(
|
||||
page,
|
||||
"Feature that should auto-create worktree",
|
||||
{
|
||||
branch: branchName,
|
||||
category: "Testing",
|
||||
}
|
||||
);
|
||||
|
||||
// Confirm
|
||||
await confirmAddFeature(page);
|
||||
@@ -835,7 +839,7 @@ test.describe("Worktree Integration Tests", () => {
|
||||
|
||||
const featureFilePath = path.join(featuresDir, featureDir!, "feature.json");
|
||||
const featureData = JSON.parse(fs.readFileSync(featureFilePath, "utf-8"));
|
||||
|
||||
|
||||
// Verify branch name is stored
|
||||
expect(featureData.branchName).toBe(branchName);
|
||||
|
||||
@@ -900,7 +904,7 @@ test.describe("Worktree Integration Tests", () => {
|
||||
|
||||
let featureFilePath = path.join(featuresDir, featureDir!, "feature.json");
|
||||
let featureData = JSON.parse(fs.readFileSync(featureFilePath, "utf-8"));
|
||||
|
||||
|
||||
// Verify feature was created with the branch name stored
|
||||
expect(featureData.branchName).toBe(branchName);
|
||||
// Verify worktreePath is NOT set (worktrees are created at execution time, not when adding)
|
||||
@@ -1084,7 +1088,9 @@ test.describe("Worktree Integration Tests", () => {
|
||||
// When a worktree is selected, "Use current selected branch" should be selected
|
||||
// and the branch name should be shown in the label
|
||||
const currentBranchLabel = page.locator('label[for="feature-current"]');
|
||||
await expect(currentBranchLabel).toContainText(branchName, { timeout: 5000 });
|
||||
await expect(currentBranchLabel).toContainText(branchName, {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
// Close dialog
|
||||
await page.keyboard.press("Escape");
|
||||
@@ -1275,11 +1281,7 @@ test.describe("Worktree Integration Tests", () => {
|
||||
expect(featureDir).toBeDefined();
|
||||
|
||||
// Read the feature data
|
||||
const featureFilePath = path.join(
|
||||
featuresDir,
|
||||
featureDir!,
|
||||
"feature.json"
|
||||
);
|
||||
const featureFilePath = path.join(featuresDir, featureDir!, "feature.json");
|
||||
const featureData = JSON.parse(fs.readFileSync(featureFilePath, "utf-8"));
|
||||
expect(featureData.status).toBe("backlog");
|
||||
|
||||
@@ -1296,9 +1298,7 @@ test.describe("Worktree Integration Tests", () => {
|
||||
|
||||
// Wait for the feature to move to in_progress column
|
||||
await expect(async () => {
|
||||
const updatedData = JSON.parse(
|
||||
fs.readFileSync(featureFilePath, "utf-8")
|
||||
);
|
||||
const updatedData = JSON.parse(fs.readFileSync(featureFilePath, "utf-8"));
|
||||
expect(updatedData.status).toBe("in_progress");
|
||||
}).toPass({ timeout: 10000 });
|
||||
|
||||
@@ -1911,7 +1911,10 @@ test.describe("Worktree Integration Tests", () => {
|
||||
await apiCreateWorktree(page, testRepo.path, branchName);
|
||||
|
||||
// Add a file and commit in the worktree
|
||||
fs.writeFileSync(path.join(worktreePath, "merge-file.txt"), "merge content");
|
||||
fs.writeFileSync(
|
||||
path.join(worktreePath, "merge-file.txt"),
|
||||
"merge content"
|
||||
);
|
||||
await execAsync("git add merge-file.txt", { cwd: worktreePath });
|
||||
await execAsync('git commit -m "Add file for merge test"', {
|
||||
cwd: worktreePath,
|
||||
@@ -2065,9 +2068,9 @@ test.describe("Worktree Integration Tests", () => {
|
||||
|
||||
// Verify the worktree has the file from develop
|
||||
const worktreePath = getWorktreePath(testRepo.path, "feature/from-develop");
|
||||
expect(
|
||||
fs.existsSync(path.join(worktreePath, "develop-only.txt"))
|
||||
).toBe(true);
|
||||
expect(fs.existsSync(path.join(worktreePath, "develop-only.txt"))).toBe(
|
||||
true
|
||||
);
|
||||
const content = fs.readFileSync(
|
||||
path.join(worktreePath, "develop-only.txt"),
|
||||
"utf-8"
|
||||
@@ -2100,10 +2103,9 @@ test.describe("Worktree Integration Tests", () => {
|
||||
|
||||
// Verify the worktree starts from the same commit as main
|
||||
const worktreePath = getWorktreePath(testRepo.path, "feature/from-head");
|
||||
const { stdout: worktreeHash } = await execAsync(
|
||||
"git rev-parse HEAD~0",
|
||||
{ cwd: worktreePath }
|
||||
);
|
||||
const { stdout: worktreeHash } = await execAsync("git rev-parse HEAD~0", {
|
||||
cwd: worktreePath,
|
||||
});
|
||||
|
||||
// The worktree's initial commit should be the same as main's HEAD
|
||||
// (Since it was just created, we check the parent commit)
|
||||
@@ -2395,9 +2397,9 @@ test.describe("Worktree Integration Tests", () => {
|
||||
let featureData = JSON.parse(fs.readFileSync(featureFilePath, "utf-8"));
|
||||
|
||||
// Initially, the feature should be on main or have no branch set
|
||||
expect(
|
||||
!featureData.branchName || featureData.branchName === "main"
|
||||
).toBe(true);
|
||||
expect(!featureData.branchName || featureData.branchName === "main").toBe(
|
||||
true
|
||||
);
|
||||
|
||||
// The new branch we want to assign
|
||||
const newBranchName = "feature/edited-branch";
|
||||
@@ -2428,7 +2430,7 @@ test.describe("Worktree Integration Tests", () => {
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
// Type the new branch name
|
||||
const commandInput = page.locator('[cmdk-input]');
|
||||
const commandInput = page.locator("[cmdk-input]");
|
||||
await commandInput.fill(newBranchName);
|
||||
|
||||
// Press Enter to select/create the branch
|
||||
@@ -2519,7 +2521,7 @@ test.describe("Worktree Integration Tests", () => {
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
// Type "main" to change to main branch
|
||||
const commandInput = page.locator('[cmdk-input]');
|
||||
const commandInput = page.locator("[cmdk-input]");
|
||||
await commandInput.fill("main");
|
||||
await commandInput.press("Enter");
|
||||
await page.waitForTimeout(200);
|
||||
@@ -2577,7 +2579,7 @@ test.describe("Worktree Integration Tests", () => {
|
||||
await branchInput.click();
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
const commandInput = page.locator('[cmdk-input]');
|
||||
const commandInput = page.locator("[cmdk-input]");
|
||||
await commandInput.fill(existingBranch);
|
||||
await commandInput.press("Enter");
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
Reference in New Issue
Block a user