mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
Merge pull request #3125 from deepseek-harness/worktree/composer-editable-gate
test(web): gate composer gestures on the editable attribute
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
||||
assertFinalWorkspaceSnapshot, assertFixtureInventory, fixtureUserPrompts, launchWebScaffold, recordFixture,
|
||||
watchConsole, webSnapshotMode, type WebScaffold,
|
||||
} from './scaffold.ts'
|
||||
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
|
||||
import { connectFreshWorkspace, newEnglishPage, saveFailureShot, writeComposerDraft } from './support.ts'
|
||||
|
||||
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/permission-policy-context', import.meta.url))
|
||||
const FIXTURE = fileURLToPath(new URL('../../../snapshots/web/permission-policy-context/session.jsonl', import.meta.url))
|
||||
@@ -97,23 +97,23 @@ describe('web e2e: current sandbox policy reaches the model before tools', () =>
|
||||
const input = page.locator('[data-composer-input][contenteditable="true"]').first()
|
||||
let sessionId: Awaited<ReturnType<WebScaffold['whenTurnSettled']>> | undefined
|
||||
for (const [index, preset] of ['read-only', 'danger-full-access', 'workspace-write'].entries()) {
|
||||
await input.fill(`/permission ${preset}`)
|
||||
await writeComposerDraft(page, input, `/permission ${preset}`)
|
||||
await input.press('Enter')
|
||||
await page.getByRole('button', { name: `Access mode, current: ${PRESET_LABELS[index]}` })
|
||||
.waitFor({ timeout: 10_000 })
|
||||
|
||||
const settled = scaffold.whenTurnSettled()
|
||||
await input.fill(PROMPTS[index] as string)
|
||||
await writeComposerDraft(page, input, PROMPTS[index] as string)
|
||||
await input.press('Enter')
|
||||
sessionId = await settled
|
||||
await input.waitFor({ timeout: 10_000 })
|
||||
}
|
||||
|
||||
await input.fill('/permission read-only')
|
||||
await writeComposerDraft(page, input, '/permission read-only')
|
||||
await input.press('Enter')
|
||||
await page.getByRole('button', { name: 'Access mode, current: Read Only' }).waitFor({ timeout: 10_000 })
|
||||
const settled = scaffold.whenTurnSettled()
|
||||
await input.fill(PROMPTS[3])
|
||||
await writeComposerDraft(page, input, PROMPTS[3])
|
||||
await input.press('Enter')
|
||||
sessionId = await settled
|
||||
|
||||
|
||||
@@ -117,6 +117,15 @@ export async function connectFreshWorkspaceZh(page: Page, root: string, name = '
|
||||
* selection, and the batched edit lands on a null selection and is silently
|
||||
* dropped, leaving the previous draft in place. Real keystrokes leave room for
|
||||
* `selectionchange` between keys, which is also what a user's typing does.
|
||||
*
|
||||
* Waits for the surface to be editable first. While the input machine is
|
||||
* adjudicating or submitting a send — and in every locked state (removed
|
||||
* session, no workspace, an owner block) — the composer renders read-only
|
||||
* with `contenteditable="false"` on the same element. `fill()` throws
|
||||
* immediately on that element, and `isEnabled()` reports `true` for a
|
||||
* `<div>` regardless of the attribute — so a gesture directly after a
|
||||
* submit must gate on the attribute, not on enablement. A running turn by
|
||||
* itself keeps the composer editable (that is what queueing types into).
|
||||
* @param page - the page under test.
|
||||
* @param input - the `[data-composer-input]` surface locator.
|
||||
* @param text - the replacement draft; `''` clears the draft. Must not
|
||||
@@ -127,6 +136,7 @@ export async function writeComposerDraft(
|
||||
input: ReturnType<Page['locator']>,
|
||||
text: string,
|
||||
): Promise<void> {
|
||||
await input.and(page.locator('[contenteditable="true"]')).waitFor({ timeout: 15_000 })
|
||||
await input.click()
|
||||
await page.keyboard.press('ControlOrMeta+A')
|
||||
if (text === '') await page.keyboard.press('Backspace')
|
||||
|
||||
Reference in New Issue
Block a user