# E2E test report (agent-friendly)

Plain-markdown digest of the Playwright e2e run, generated for AI agents. The interactive HTML report (screenshots, videos, traces) is served from this same deployment root.

- Commit: b02162fe372d98af6decf6ce1fe36179736bbaa8
- Workflow run: https://github.com/sanity-io/plugins/actions/runs/31493404380
- Summary: 25 passed, 1 failed, 0 flaky, 0 skipped

## ❌ chromium › media/media.spec.ts › sanity-plugin-media › edits asset title from the Media library and saves

- Location: `tests/media/media.spec.ts:14:3`
- Browser (Playwright project): chromium
- Status: failed (3 attempts, all failed)

### Error (attempt 3 of 3)

```
Error: locator.fill: Error: strict mode violation: getByPlaceholder('Search') resolved to 2 elements:
    1) <input value="" type="text" data-as="input" data-scheme="light" data-tone="default" placeholder="Search" class="Input-sc-ceualg-4 cLewYt"/> aka getByRole('textbox', { name: 'Search' })
    2) <input value="" type="text" data-as="input" data-scheme="light" data-tone="default" class="Input-sc-ceualg-4 cLewYt" placeholder="Search document types" data-testid="new-document-button-search-input"/> aka getByTestId('new-document-button-search-input')

Call log:
  - waiting for getByPlaceholder('Search')

    at searchMediaAssets (/home/runner/work/plugins/plugins/e2e/helpers/media/media.ts:68:16)
    at /home/runner/work/plugins/plugins/e2e/tests/media/media.spec.ts:21:13

   at ../helpers/media/media.ts:68

  66 | export async function searchMediaAssets(page: Page, query: string): Promise<void> {
  67 |   const search = page.getByPlaceholder('Search')
> 68 |   await search.fill(query)
     |                ^
  69 | }
  70 |
  71 | export function mediaAssetCard(page: Page, assetId: string) {
```

### Page snapshot at the moment of failure

# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: media/media.spec.ts >> sanity-plugin-media >> edits asset title from the Media library and saves
- Location: tests/media/media.spec.ts:14:3

# Error details

```
Error: locator.fill: Error: strict mode violation: getByPlaceholder('Search') resolved to 2 elements:
    1) <input value="" type="text" data-as="input" data-scheme="light" data-tone="default" placeholder="Search" class="Input-sc-ceualg-4 cLewYt"/> aka getByRole('textbox', { name: 'Search' })
    2) <input value="" type="text" data-as="input" data-scheme="light" data-tone="default" class="Input-sc-ceualg-4 cLewYt" placeholder="Search document types" data-testid="new-document-button-search-input"/> aka getByTestId('new-document-button-search-input')

Call log:
  - waiting for getByPlaceholder('Search')

```

# Page snapshot

```yaml
- generic [ref=e2]:
  - generic [ref=e3]:
    - generic [ref=e6]:
      - generic [ref=e7]:
        - generic [ref=e9]:
          - link [ref=e10] [cursor=pointer]:
            - /url: /chromium
            - img [ref=e15]:
              - generic [ref=e17]: C
          - button "Chromium" [ref=e19]
        - button "Create new document" [ref=e32]
        - button "Open search" [ref=e40]
      - generic [ref=e49]:
        - generic [ref=e50]:
          - link "Structure" [ref=e51] [cursor=pointer]:
            - /url: /chromium/structure
          - link "Media" [ref=e58] [cursor=pointer]:
            - /url: /chromium/media
          - link "Releases" [ref=e65] [cursor=pointer]:
            - /url: /chromium/releases
        - button [disabled] [ref=e74]
      - generic [ref=e83]:
        - generic [ref=e84]:
          - link [ref=e85]:
            - /url: /chromium/releases
          - generic [ref=e92]: Drafts
          - button [ref=e98]
        - button [ref=e106]
        - button "Global presence" [ref=e114]
        - button "Help and resources" [ref=e122]
        - button [ref=e132]:
          - generic "e2e-robot-dev (Robot)" [ref=e134]: eR
    - 'button "Browse Assets Upload assets Add filter Toggle folders panel Last created: Newest first Tags e2e-media-2da64d09-b8bf-4425-b15a-5eec595f9e58.png Tags No tags" [ref=e145]':
      - generic [ref=e147]:
        - generic [ref=e149]:
          - generic [ref=e150]: Browse Assets
          - button "Upload assets" [ref=e157]
        - generic [ref=e169]:
          - generic [ref=e172]:
            - textbox "Search" [ref=e177]
            - button "Add filter" [ref=e182]
          - generic [ref=e194]:
            - generic [ref=e196]:
              - button "Toggle folders panel" [ref=e199]
              - generic [ref=e207]:
                - button [ref=e209]
                - button [ref=e217]
            - generic [ref=e224]:
              - 'button "Last created: Newest first" [ref=e225]'
              - button "Tags" [ref=e237]
        - generic [ref=e251]:
          - generic [ref=e259]:
            - generic [ref=e260] [cursor=pointer]
            - generic [ref=e263] [cursor=pointer]:
              - generic:
                - checkbox [disabled]
              - generic [ref=e264]: e2e-media-2da64d09-b8bf-4425-b15a-5eec595f9e58.png
          - generic [ref=e270]:
            - generic [ref=e271]:
              - generic [ref=e272]: Tags
              - button [ref=e277]
            - emphasis [ref=e287]: No tags
  - list
```

# Test source

```ts
  1  | import {randomUUID} from 'node:crypto'
  2  | 
  3  | import {expect, type Page} from '@playwright/test'
  4  | 
  5  | import {createE2EClient} from '../e2eClient.js'
  6  | import {loadE2eEnvFiles, resolveE2eEnv} from '../env.js'
  7  | 
  8  | loadE2eEnvFiles()
  9  | 
  10 | /** 1×1 PNG */
  11 | const TINY_PNG = Buffer.from(
  12 |   'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==',
  13 |   'base64',
  14 | )
  15 | 
  16 | export type SeededMediaAsset = {
  17 |   id: string
  18 |   filename: string
  19 | }
  20 | 
  21 | function datasetForProject(projectName: string | undefined): string {
  22 |   const env = resolveE2eEnv()
  23 |   if (projectName === 'firefox') return env.datasetFirefox
  24 |   return env.datasetChromium
  25 | }
  26 | 
  27 | /** Upload a tiny image asset for Media tool e2e coverage. */
  28 | export async function seedMediaImage(projectName: string | undefined): Promise<SeededMediaAsset> {
  29 |   const client = createE2EClient(datasetForProject(projectName))
  30 |   const filename = `e2e-media-${randomUUID()}.png`
  31 | 
  32 |   const asset = await client.assets.upload('image', TINY_PNG, {
  33 |     filename,
  34 |     contentType: 'image/png',
  35 |   })
  36 | 
  37 |   return {id: asset._id, filename}
  38 | }
  39 | 
  40 | export async function deleteMediaAsset(
  41 |   projectName: string | undefined,
  42 |   assetId: string,
  43 | ): Promise<void> {
  44 |   const client = createE2EClient(datasetForProject(projectName))
  45 |   await client.delete(assetId).catch(() => undefined)
  46 | }
  47 | 
  48 | export async function getMediaAssetTitle(
  49 |   projectName: string | undefined,
  50 |   assetId: string,
  51 | ): Promise<string | undefined> {
  52 |   const client = createE2EClient(datasetForProject(projectName))
  53 |   const doc = await client.getDocument<{title?: string}>(assetId)
  54 |   return doc?.title
  55 | }
  56 | 
  57 | /** Open the Media tool (relative to workspace baseURL). */
  58 | export async function openMediaTool(page: Page): Promise<void> {
  59 |   await page.goto('media')
  60 |   await expect(page.getByTestId('studio-navbar')).toBeVisible()
  61 |   await expect(page.getByTestId('media-browser')).toBeVisible()
  62 |   await expect(page.getByText('Browse Assets')).toBeVisible()
  63 | }
  64 | 
  65 | /** Filter the asset grid so a freshly seeded upload is easy to find. */
  66 | export async function searchMediaAssets(page: Page, query: string): Promise<void> {
  67 |   const search = page.getByPlaceholder('Search')
> 68 |   await search.fill(query)
     |                ^ Error: locator.fill: Error: strict mode violation: getByPlaceholder('Search') resolved to 2 elements:
  69 | }
  70 | 
  71 | export function mediaAssetCard(page: Page, assetId: string) {
  72 |   return page.getByTestId(`media-asset-card-${assetId}`)
  73 | }
  74 | 
  75 | export function assetDetailsDialog(page: Page) {
  76 |   return page.getByRole('dialog', {name: /asset details/i})
  77 | }
  78 | 
```

### Other attachments (available in the HTML report at this deployment root)

- video (video/webm)


## How to reproduce locally

From the repository root:

```sh
SANITY_E2E_PROJECT_ID=a1psl692 \
SANITY_E2E_BASE_URL=https://plugins-e2e-test-studio-k195hyfkt.sanity.dev \
SANITY_E2E_DATASET_CHROMIUM=pr-1867-chromium-31493404380 \
SANITY_E2E_DATASET_FIREFOX=pr-1867-firefox-31493404380 \
pnpm test:e2e \
  tests/media/media.spec.ts
```
