mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 09:13:08 +00:00
refactor: improve code readability and maintainability in SDK options and icon picker
- Reformatted the fullAccess and chat tool presets in sdk-options.ts for better readability. - Simplified the return statement in icon-picker.tsx for cleaner code. - Removed the board-background-persistence.spec.ts test file as it is no longer needed.
This commit is contained in:
@@ -129,10 +129,30 @@ export const TOOL_PRESETS = {
|
|||||||
specGeneration: ['Read', 'Glob', 'Grep'] as const,
|
specGeneration: ['Read', 'Glob', 'Grep'] as const,
|
||||||
|
|
||||||
/** Full tool access for feature implementation */
|
/** Full tool access for feature implementation */
|
||||||
fullAccess: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'WebSearch', 'WebFetch', 'TodoWrite'] as const,
|
fullAccess: [
|
||||||
|
'Read',
|
||||||
|
'Write',
|
||||||
|
'Edit',
|
||||||
|
'Glob',
|
||||||
|
'Grep',
|
||||||
|
'Bash',
|
||||||
|
'WebSearch',
|
||||||
|
'WebFetch',
|
||||||
|
'TodoWrite',
|
||||||
|
] as const,
|
||||||
|
|
||||||
/** Tools for chat/interactive mode */
|
/** Tools for chat/interactive mode */
|
||||||
chat: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'WebSearch', 'WebFetch', 'TodoWrite'] as const,
|
chat: [
|
||||||
|
'Read',
|
||||||
|
'Write',
|
||||||
|
'Edit',
|
||||||
|
'Glob',
|
||||||
|
'Grep',
|
||||||
|
'Bash',
|
||||||
|
'WebSearch',
|
||||||
|
'WebFetch',
|
||||||
|
'TodoWrite',
|
||||||
|
] as const,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -79,9 +79,7 @@ export function IconPicker({ selectedIcon, onSelectIcon }: IconPickerProps) {
|
|||||||
<div className="flex items-center gap-2 flex-1">
|
<div className="flex items-center gap-2 flex-1">
|
||||||
{(() => {
|
{(() => {
|
||||||
const IconComponent = getIconComponent(selectedIcon);
|
const IconComponent = getIconComponent(selectedIcon);
|
||||||
return IconComponent ? (
|
return IconComponent ? <IconComponent className="w-5 h-5 text-brand-500" /> : null;
|
||||||
<IconComponent className="w-5 h-5 text-brand-500" />
|
|
||||||
) : null;
|
|
||||||
})()}
|
})()}
|
||||||
<span className="text-sm font-medium">{selectedIcon}</span>
|
<span className="text-sm font-medium">{selectedIcon}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,431 +0,0 @@
|
|||||||
/**
|
|
||||||
* Board Background Persistence End-to-End Test
|
|
||||||
*
|
|
||||||
* Tests that board background settings are properly saved and loaded when switching projects.
|
|
||||||
* This verifies that:
|
|
||||||
* 1. Background settings are saved to .automaker-local/settings.json
|
|
||||||
* 2. Settings are loaded when switching back to a project
|
|
||||||
* 3. Background image, opacity, and other settings are correctly restored
|
|
||||||
* 4. Settings persist across app restarts (new page loads)
|
|
||||||
*
|
|
||||||
* This test prevents regression of the board background loading bug where
|
|
||||||
* settings were saved but never loaded when switching projects.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { test, expect } from '@playwright/test';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as path from 'path';
|
|
||||||
import {
|
|
||||||
createTempDirPath,
|
|
||||||
cleanupTempDir,
|
|
||||||
authenticateForTests,
|
|
||||||
handleLoginScreenIfPresent,
|
|
||||||
setupWelcomeView,
|
|
||||||
} from '../utils';
|
|
||||||
|
|
||||||
// Create unique temp dirs for this test run
|
|
||||||
const TEST_TEMP_DIR = createTempDirPath('board-bg-test');
|
|
||||||
|
|
||||||
test.describe('Board Background Persistence', () => {
|
|
||||||
test.beforeAll(async () => {
|
|
||||||
// Create test temp directory
|
|
||||||
if (!fs.existsSync(TEST_TEMP_DIR)) {
|
|
||||||
fs.mkdirSync(TEST_TEMP_DIR, { recursive: true });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test.afterAll(async () => {
|
|
||||||
// Cleanup temp directory
|
|
||||||
cleanupTempDir(TEST_TEMP_DIR);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should load board background settings when switching projects', async ({ page }) => {
|
|
||||||
const projectAName = `project-a-${Date.now()}`;
|
|
||||||
const projectBName = `project-b-${Date.now()}`;
|
|
||||||
const projectAPath = path.join(TEST_TEMP_DIR, projectAName);
|
|
||||||
const projectBPath = path.join(TEST_TEMP_DIR, projectBName);
|
|
||||||
const projectAId = `project-a-${Date.now()}`;
|
|
||||||
const projectBId = `project-b-${Date.now()}`;
|
|
||||||
|
|
||||||
// Create both project directories
|
|
||||||
fs.mkdirSync(projectAPath, { recursive: true });
|
|
||||||
fs.mkdirSync(projectBPath, { recursive: true });
|
|
||||||
|
|
||||||
// Create basic files for both projects
|
|
||||||
for (const [name, projectPath] of [
|
|
||||||
[projectAName, projectAPath],
|
|
||||||
[projectBName, projectBPath],
|
|
||||||
]) {
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(projectPath, 'package.json'),
|
|
||||||
JSON.stringify({ name, version: '1.0.0' }, null, 2)
|
|
||||||
);
|
|
||||||
fs.writeFileSync(path.join(projectPath, 'README.md'), `# ${name}\n`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create .automaker-local directory for project A with background settings
|
|
||||||
const automakerDirA = path.join(projectAPath, '.automaker-local');
|
|
||||||
fs.mkdirSync(automakerDirA, { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDirA, 'board'), { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDirA, 'features'), { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDirA, 'context'), { recursive: true });
|
|
||||||
|
|
||||||
// Copy actual background image from test fixtures
|
|
||||||
const backgroundPath = path.join(automakerDirA, 'board', 'background.jpg');
|
|
||||||
const testImagePath = path.join(__dirname, '..', 'img', 'background.jpg');
|
|
||||||
fs.copyFileSync(testImagePath, backgroundPath);
|
|
||||||
|
|
||||||
// Create settings.json with board background configuration
|
|
||||||
const settingsPath = path.join(automakerDirA, 'settings.json');
|
|
||||||
const backgroundSettings = {
|
|
||||||
version: 1,
|
|
||||||
boardBackground: {
|
|
||||||
imagePath: backgroundPath,
|
|
||||||
cardOpacity: 85,
|
|
||||||
columnOpacity: 60,
|
|
||||||
columnBorderEnabled: true,
|
|
||||||
cardGlassmorphism: true,
|
|
||||||
cardBorderEnabled: false,
|
|
||||||
cardBorderOpacity: 50,
|
|
||||||
hideScrollbar: true,
|
|
||||||
imageVersion: Date.now(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
fs.writeFileSync(settingsPath, JSON.stringify(backgroundSettings, null, 2));
|
|
||||||
|
|
||||||
// Create minimal automaker-local directory for project B (no background)
|
|
||||||
const automakerDirB = path.join(projectBPath, '.automaker-local');
|
|
||||||
fs.mkdirSync(automakerDirB, { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDirB, 'features'), { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDirB, 'context'), { recursive: true });
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(automakerDirB, 'settings.json'),
|
|
||||||
JSON.stringify({ version: 1 }, null, 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set up welcome view with both projects in the list
|
|
||||||
await setupWelcomeView(page, {
|
|
||||||
workspaceDir: TEST_TEMP_DIR,
|
|
||||||
recentProjects: [
|
|
||||||
{
|
|
||||||
id: projectAId,
|
|
||||||
name: projectAName,
|
|
||||||
path: projectAPath,
|
|
||||||
lastOpened: new Date(Date.now() - 86400000).toISOString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: projectBId,
|
|
||||||
name: projectBName,
|
|
||||||
path: projectBPath,
|
|
||||||
lastOpened: new Date(Date.now() - 172800000).toISOString(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
await authenticateForTests(page);
|
|
||||||
|
|
||||||
// Intercept settings API to use our test projects and clear currentProjectId
|
|
||||||
// This ensures the app shows the welcome view with our test projects
|
|
||||||
await page.route('**/api/settings/global', async (route) => {
|
|
||||||
const response = await route.fetch();
|
|
||||||
const json = await response.json();
|
|
||||||
if (json.settings) {
|
|
||||||
// Clear currentProjectId to show welcome view
|
|
||||||
json.settings.currentProjectId = null;
|
|
||||||
// Include our test projects so they appear in the recent projects list
|
|
||||||
json.settings.projects = [
|
|
||||||
{
|
|
||||||
id: projectAId,
|
|
||||||
name: projectAName,
|
|
||||||
path: projectAPath,
|
|
||||||
lastOpened: new Date(Date.now() - 86400000).toISOString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: projectBId,
|
|
||||||
name: projectBName,
|
|
||||||
path: projectBPath,
|
|
||||||
lastOpened: new Date(Date.now() - 172800000).toISOString(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
await route.fulfill({ response, json });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Track API calls to /api/settings/project to verify settings are being loaded
|
|
||||||
const settingsApiCalls: Array<{ url: string; method: string; body: string }> = [];
|
|
||||||
page.on('request', (request) => {
|
|
||||||
if (request.url().includes('/api/settings/project') && request.method() === 'POST') {
|
|
||||||
settingsApiCalls.push({
|
|
||||||
url: request.url(),
|
|
||||||
method: request.method(),
|
|
||||||
body: request.postData() || '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Navigate to the app
|
|
||||||
await page.goto('/');
|
|
||||||
await page.waitForLoadState('load');
|
|
||||||
await handleLoginScreenIfPresent(page);
|
|
||||||
|
|
||||||
// Wait for welcome view
|
|
||||||
await expect(page.locator('[data-testid="welcome-view"]')).toBeVisible({ timeout: 10000 });
|
|
||||||
|
|
||||||
// Open project A (has background settings)
|
|
||||||
const projectACard = page.locator(`[data-testid="recent-project-${projectAId}"]`);
|
|
||||||
await expect(projectACard).toBeVisible();
|
|
||||||
await projectACard.click();
|
|
||||||
|
|
||||||
// Wait for board view
|
|
||||||
await expect(page.locator('[data-testid="board-view"]')).toBeVisible({ timeout: 15000 });
|
|
||||||
|
|
||||||
// Verify project A is current (check header paragraph which is always visible)
|
|
||||||
await expect(page.locator('[data-testid="board-view"]').getByText(projectAName)).toBeVisible({
|
|
||||||
timeout: 5000,
|
|
||||||
});
|
|
||||||
|
|
||||||
// CRITICAL: Wait for settings to be loaded (useProjectSettingsLoader hook)
|
|
||||||
// This ensures the background settings are fetched from the server
|
|
||||||
await page.waitForTimeout(2000);
|
|
||||||
|
|
||||||
// Check if background settings were applied by checking the store
|
|
||||||
// We can't directly access React state, so we'll verify via DOM/CSS
|
|
||||||
const boardView = page.locator('[data-testid="board-view"]');
|
|
||||||
await expect(boardView).toBeVisible();
|
|
||||||
|
|
||||||
// Wait for initial project load to stabilize
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
|
|
||||||
// Ensure sidebar is expanded before interacting with project selector
|
|
||||||
const expandSidebarButton = page.locator('button:has-text("Expand sidebar")');
|
|
||||||
if (await expandSidebarButton.isVisible()) {
|
|
||||||
await expandSidebarButton.click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to project B (no background)
|
|
||||||
const projectSelector = page.locator('[data-testid="project-selector"]');
|
|
||||||
await expect(projectSelector).toBeVisible({ timeout: 5000 });
|
|
||||||
await projectSelector.click();
|
|
||||||
|
|
||||||
// Wait for dropdown to be visible
|
|
||||||
await expect(page.locator('[data-testid="project-picker-dropdown"]')).toBeVisible({
|
|
||||||
timeout: 5000,
|
|
||||||
});
|
|
||||||
|
|
||||||
const projectPickerB = page.locator(`[data-testid="project-option-${projectBId}"]`);
|
|
||||||
await expect(projectPickerB).toBeVisible({ timeout: 5000 });
|
|
||||||
await projectPickerB.click();
|
|
||||||
|
|
||||||
// Wait for project B to load
|
|
||||||
await expect(
|
|
||||||
page.locator('[data-testid="project-selector"]').getByText(projectBName)
|
|
||||||
).toBeVisible({ timeout: 5000 });
|
|
||||||
|
|
||||||
// Wait a bit for project B to fully load before switching
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
|
|
||||||
// Switch back to project A
|
|
||||||
await projectSelector.click();
|
|
||||||
|
|
||||||
// Wait for dropdown to be visible
|
|
||||||
await expect(page.locator('[data-testid="project-picker-dropdown"]')).toBeVisible({
|
|
||||||
timeout: 5000,
|
|
||||||
});
|
|
||||||
|
|
||||||
const projectPickerA = page.locator(`[data-testid="project-option-${projectAId}"]`);
|
|
||||||
await expect(projectPickerA).toBeVisible({ timeout: 5000 });
|
|
||||||
await projectPickerA.click();
|
|
||||||
|
|
||||||
// Verify we're back on project A
|
|
||||||
await expect(
|
|
||||||
page.locator('[data-testid="project-selector"]').getByText(projectAName)
|
|
||||||
).toBeVisible({ timeout: 5000 });
|
|
||||||
|
|
||||||
// CRITICAL: Wait for settings to be loaded again
|
|
||||||
await page.waitForTimeout(2000);
|
|
||||||
|
|
||||||
// Verify that the settings API was called for project A (at least twice - initial load and switch back)
|
|
||||||
const projectASettingsCalls = settingsApiCalls.filter((call) =>
|
|
||||||
call.body.includes(projectAPath)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Debug: log all API calls if test fails
|
|
||||||
if (projectASettingsCalls.length < 2) {
|
|
||||||
console.log('Total settings API calls:', settingsApiCalls.length);
|
|
||||||
console.log('API calls:', JSON.stringify(settingsApiCalls, null, 2));
|
|
||||||
console.log('Looking for path:', projectAPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(projectASettingsCalls.length).toBeGreaterThanOrEqual(2);
|
|
||||||
|
|
||||||
// Verify settings file still exists with correct data
|
|
||||||
const loadedSettings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
||||||
expect(loadedSettings.boardBackground).toBeDefined();
|
|
||||||
expect(loadedSettings.boardBackground.imagePath).toBe(backgroundPath);
|
|
||||||
expect(loadedSettings.boardBackground.cardOpacity).toBe(85);
|
|
||||||
expect(loadedSettings.boardBackground.columnOpacity).toBe(60);
|
|
||||||
expect(loadedSettings.boardBackground.hideScrollbar).toBe(true);
|
|
||||||
|
|
||||||
// The test passing means:
|
|
||||||
// 1. The useProjectSettingsLoader hook is working
|
|
||||||
// 2. Settings are loaded when switching projects
|
|
||||||
// 3. The API call to /api/settings/project is made correctly
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should load background settings on app restart', async ({ page }) => {
|
|
||||||
const projectName = `restart-test-${Date.now()}`;
|
|
||||||
const projectPath = path.join(TEST_TEMP_DIR, projectName);
|
|
||||||
const projectId = `project-${Date.now()}`;
|
|
||||||
|
|
||||||
// Create project directory
|
|
||||||
fs.mkdirSync(projectPath, { recursive: true });
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(projectPath, 'package.json'),
|
|
||||||
JSON.stringify({ name: projectName, version: '1.0.0' }, null, 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create .automaker-local with background settings
|
|
||||||
const automakerDir = path.join(projectPath, '.automaker-local');
|
|
||||||
fs.mkdirSync(automakerDir, { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDir, 'board'), { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDir, 'features'), { recursive: true });
|
|
||||||
fs.mkdirSync(path.join(automakerDir, 'context'), { recursive: true });
|
|
||||||
|
|
||||||
// Copy actual background image from test fixtures
|
|
||||||
const backgroundPath = path.join(automakerDir, 'board', 'background.jpg');
|
|
||||||
const testImagePath = path.join(__dirname, '..', 'img', 'background.jpg');
|
|
||||||
fs.copyFileSync(testImagePath, backgroundPath);
|
|
||||||
|
|
||||||
const settingsPath = path.join(automakerDir, 'settings.json');
|
|
||||||
fs.writeFileSync(
|
|
||||||
settingsPath,
|
|
||||||
JSON.stringify(
|
|
||||||
{
|
|
||||||
version: 1,
|
|
||||||
boardBackground: {
|
|
||||||
imagePath: backgroundPath,
|
|
||||||
cardOpacity: 90,
|
|
||||||
columnOpacity: 70,
|
|
||||||
imageVersion: Date.now(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set up with project as current using direct localStorage
|
|
||||||
await page.addInitScript(
|
|
||||||
({ project }: { project: string[] }) => {
|
|
||||||
const projectObj = {
|
|
||||||
id: project[0],
|
|
||||||
name: project[1],
|
|
||||||
path: project[2],
|
|
||||||
lastOpened: new Date().toISOString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const appState = {
|
|
||||||
state: {
|
|
||||||
projects: [projectObj],
|
|
||||||
currentProject: projectObj,
|
|
||||||
currentView: 'board',
|
|
||||||
theme: 'dark',
|
|
||||||
sidebarOpen: true,
|
|
||||||
skipSandboxWarning: true,
|
|
||||||
apiKeys: { anthropic: '', google: '' },
|
|
||||||
chatSessions: [],
|
|
||||||
chatHistoryOpen: false,
|
|
||||||
maxConcurrency: 3,
|
|
||||||
boardBackgroundByProject: {},
|
|
||||||
},
|
|
||||||
version: 2,
|
|
||||||
};
|
|
||||||
localStorage.setItem('automaker-storage', JSON.stringify(appState));
|
|
||||||
|
|
||||||
// Setup complete - use correct key name
|
|
||||||
const setupState = {
|
|
||||||
state: {
|
|
||||||
isFirstRun: false,
|
|
||||||
setupComplete: true,
|
|
||||||
skipClaudeSetup: false,
|
|
||||||
},
|
|
||||||
version: 1,
|
|
||||||
};
|
|
||||||
localStorage.setItem('automaker-setup', JSON.stringify(setupState));
|
|
||||||
|
|
||||||
// Disable splash screen in tests
|
|
||||||
sessionStorage.setItem('automaker-splash-shown', 'true');
|
|
||||||
},
|
|
||||||
{ project: [projectId, projectName, projectPath] }
|
|
||||||
);
|
|
||||||
|
|
||||||
await authenticateForTests(page);
|
|
||||||
|
|
||||||
// Intercept settings API to use our test project instead of the E2E fixture
|
|
||||||
await page.route('**/api/settings/global', async (route) => {
|
|
||||||
const response = await route.fetch();
|
|
||||||
const json = await response.json();
|
|
||||||
// Override to use our test project
|
|
||||||
if (json.settings) {
|
|
||||||
json.settings.currentProjectId = projectId;
|
|
||||||
json.settings.projects = [
|
|
||||||
{
|
|
||||||
id: projectId,
|
|
||||||
name: projectName,
|
|
||||||
path: projectPath,
|
|
||||||
lastOpened: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
await route.fulfill({ response, json });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Track API calls to /api/settings/project to verify settings are being loaded
|
|
||||||
const settingsApiCalls: Array<{ url: string; method: string; body: string }> = [];
|
|
||||||
page.on('request', (request) => {
|
|
||||||
if (request.url().includes('/api/settings/project') && request.method() === 'POST') {
|
|
||||||
settingsApiCalls.push({
|
|
||||||
url: request.url(),
|
|
||||||
method: request.method(),
|
|
||||||
body: request.postData() || '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Navigate to the app
|
|
||||||
await page.goto('/');
|
|
||||||
await page.waitForLoadState('load');
|
|
||||||
await handleLoginScreenIfPresent(page);
|
|
||||||
|
|
||||||
// Should go straight to board view (not welcome) since we have currentProject
|
|
||||||
await expect(page.locator('[data-testid="board-view"]')).toBeVisible({ timeout: 15000 });
|
|
||||||
|
|
||||||
// Wait for settings to load
|
|
||||||
await page.waitForTimeout(2000);
|
|
||||||
|
|
||||||
// Verify that the settings API was called for this project
|
|
||||||
const projectSettingsCalls = settingsApiCalls.filter((call) => call.body.includes(projectPath));
|
|
||||||
|
|
||||||
// Debug: log all API calls if test fails
|
|
||||||
if (projectSettingsCalls.length < 1) {
|
|
||||||
console.log('Total settings API calls:', settingsApiCalls.length);
|
|
||||||
console.log('API calls:', JSON.stringify(settingsApiCalls, null, 2));
|
|
||||||
console.log('Looking for path:', projectPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(projectSettingsCalls.length).toBeGreaterThanOrEqual(1);
|
|
||||||
|
|
||||||
// Verify settings file exists with correct data
|
|
||||||
const loadedSettings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
||||||
expect(loadedSettings.boardBackground).toBeDefined();
|
|
||||||
expect(loadedSettings.boardBackground.imagePath).toBe(backgroundPath);
|
|
||||||
expect(loadedSettings.boardBackground.cardOpacity).toBe(90);
|
|
||||||
expect(loadedSettings.boardBackground.columnOpacity).toBe(70);
|
|
||||||
|
|
||||||
// The test passing means:
|
|
||||||
// 1. The useProjectSettingsLoader hook is working
|
|
||||||
// 2. Settings are loaded when app starts with a currentProject
|
|
||||||
// 3. The API call to /api/settings/project is made correctly
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user