This commit is contained in:
@@ -69,8 +69,10 @@ test('create a custom piece from the sidebar, then edit + save it via the editor
|
||||
await nameInput.fill(pieceName);
|
||||
await nameInput.press('Enter');
|
||||
|
||||
// The new custom piece appears in the sidebar list.
|
||||
await expect(page.getByText(pieceName, { exact: false })).toBeVisible({ timeout: 15_000 });
|
||||
// The new custom piece appears in the sidebar list AND is auto-selected, so
|
||||
// its name also shows in the editor header (PieceEditor.tsx's <h2>) —
|
||||
// scope to the sidebar row button to avoid a strict-mode double match.
|
||||
await expect(page.getByRole('button', { name: pieceName })).toBeVisible({ timeout: 15_000 });
|
||||
|
||||
// It was persisted as a custom piece (the endpoint the page reads returns
|
||||
// { pieces: [...] } with custom:true on user pieces).
|
||||
@@ -88,6 +90,10 @@ test('create a custom piece from the sidebar, then edit + save it via the editor
|
||||
await page.getByRole('button', { name: 'YAML' }).click();
|
||||
const yaml = page.locator('textarea').first();
|
||||
await expect(yaml).toBeVisible({ timeout: 15_000 });
|
||||
// Terminal moves go through the `complete` tool, not rules[].next (which
|
||||
// only accepts other movement names / WAIT_SUBTASKS — see
|
||||
// docs/movement-control-flow-tools.md). Tool/edit access is a workspace tool
|
||||
// policy setting now, not a piece field (allowed_tools/edit are removed).
|
||||
const edited = [
|
||||
`name: ${pieceName}`,
|
||||
'description: edited by e2e',
|
||||
@@ -95,14 +101,10 @@ test('create a custom piece from the sidebar, then edit + save it via the editor
|
||||
'initial_movement: execute',
|
||||
'movements:',
|
||||
' - name: execute',
|
||||
' edit: true',
|
||||
' persona: worker',
|
||||
" instruction: 'do the thing'",
|
||||
' allowed_tools: [Read, Write, Edit]',
|
||||
' default_next: COMPLETE',
|
||||
' rules:',
|
||||
" - condition: '完了'",
|
||||
' next: COMPLETE',
|
||||
' rules: []',
|
||||
'',
|
||||
].join('\n');
|
||||
await yaml.fill(edited);
|
||||
@@ -125,10 +127,15 @@ test('create a custom piece from the sidebar, then edit + save it via the editor
|
||||
expect(fatalErrors, `fatal errors:\n${fatalErrors.join('\n')}`).toEqual([]);
|
||||
});
|
||||
|
||||
// Negative/visibility: built-in pieces are not deletable and the editor renders
|
||||
// them read-only (no Save/Delete footer). 'chat' is a built-in piece always
|
||||
// present. Selecting it shows the read-only badge instead of the editable footer.
|
||||
test('a built-in piece opens read-only (no Save, no Delete)', async ({ page }) => {
|
||||
// Negative/visibility: built-in pieces are never deletable, by anyone
|
||||
// (PieceEditor.tsx: Delete is gated on effectiveSource !== 'builtin', with no
|
||||
// admin exception). The readonly badge/footer gate, by contrast, is
|
||||
// `!isAdmin && (builtin || global-custom)` — and with auth disabled the E2E
|
||||
// synthetic user is always admin (App.tsx: isAdmin = auth.mode ===
|
||||
// 'authenticated' ? user.role === 'admin' : true), so admins CAN edit
|
||||
// (Save) built-in pieces here; only non-admins get the true read-only view.
|
||||
// 'chat' is a built-in piece always present.
|
||||
test('a built-in piece opens editable for admin (no Delete, Save appears once dirty)', async ({ page }) => {
|
||||
const fatalErrors = trackFatalErrors(page);
|
||||
|
||||
await page.goto('/ui?page=pieces');
|
||||
@@ -137,11 +144,13 @@ test('a built-in piece opens read-only (no Save, no Delete)', async ({ page }) =
|
||||
// Open the built-in 'chat' piece from the Default Pieces section.
|
||||
await page.getByRole('button', { name: /chat/i }).first().click();
|
||||
|
||||
// The editor marks it read-only (PieceEditor renders the readonly badge and
|
||||
// omits the editable footer's Save button for built-ins).
|
||||
await expect(page.getByText(/read-?only/i).first()).toBeVisible({ timeout: 15_000 });
|
||||
await expect(page.getByRole('button', { name: 'Save' })).toHaveCount(0);
|
||||
// No readonly badge (this session is admin) and no Delete (built-ins are
|
||||
// never deletable), but the editable footer with Save is present.
|
||||
const saveBtn = page.getByRole('button', { name: 'Save' });
|
||||
await expect(saveBtn).toBeVisible({ timeout: 15_000 });
|
||||
await expect(page.getByText(/read-?only/i)).toHaveCount(0);
|
||||
await expect(page.getByRole('button', { name: 'Delete' })).toHaveCount(0);
|
||||
await expect(saveBtn).toBeDisabled();
|
||||
|
||||
expect(fatalErrors, `fatal errors:\n${fatalErrors.join('\n')}`).toEqual([]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user