# Write Playwright Tests for a Gatsby Site

Yes. An agent builds your Gatsby site, serves the output, writes Playwright tests for the post list, post pages, prev and next links and the feed, and opens a PR.

[Run this on Rush](https://cloud.getrush.ai/run/write-playwright-tests/gatsby/), in a Project that has your repository.

## What the agent does

In a site built from gatsbyjs/gatsby-starter-blog the agent reads `package.json` first: `gatsby` ^5.14.6 with React 18, ten official plugins and transformers including `gatsby-plugin-feed`, `gatsby-plugin-image`, `gatsby-plugin-sharp`, `gatsby-remark-images`, `gatsby-remark-prismjs`, `gatsby-source-filesystem` and `gatsby-transformer-remark`, a `package-lock.json` so `npm` is the package manager, and scripts for `build`, `develop`, `serve`, `clean` and `format`. The `test` script is the starter's placeholder: it prints a reminder to write tests and exits 1. There is no workflow under `.github/`, no test runner, and `.prettierrc` sets `arrowParens: avoid` and `semi: false`, so new files must follow that style.

Then it maps what the build will emit. `gatsby-config.js` points `gatsby-source-filesystem` at `content/blog`, configures `gatsby-remark-images` at 630 pixels wide, and defines the feed with `output: /rss.xml` built from `allMarkdownRemark` sorted by date descending. `gatsby-node.js` creates one page per Markdown post from the same query sorted ascending, passing `previousPostId` and `nextPostId` into `src/templates/blog-post.js`, and sets each post's `slug` from `createFilePath`, so the three posts under `content/blog` become `/hello-world/`, `/my-second-post/` and `/new-beginnings/`. The template renders the title in an `h1` with `itemProp="headline"`, the date formatted `MMMM DD, YYYY`, the HTML body, the `Bio` component and a `nav.blog-post-nav` whose `rel="prev"` and `rel="next"` links appear only when a neighbour exists. `src/pages/index.js` lists posts newest first as `article.post-list-item` with an `h2` link and a `small` date, and `src/pages/404.js` and `src/pages/using-typescript.tsx` are the other routes. `hello-world/index.md` embeds `salty_egg.jpg`, which `gatsby-remark-images` turns into a responsive image wrapper, and `new-beginnings/index.md` sets a `description` that `Seo` puts in the meta tag.

The agent adds `@playwright/test` as a dev dependency with `npm`, writes `playwright.config.js` with a `webServer` that runs `npm run serve` against the finished `public/` directory on the port `gatsby serve` reports, and replaces the placeholder `test` script with `playwright test`. The specs live in a `tests` directory, one per area. The home page lists three posts with New Beginnings first and Hello World last, each heading linking to its slug. A post page has the right `h1`, a date in the configured format, and for Hello World a rendered image inside the article body. Navigation follows `gatsby-node.js`: the oldest post has only a next link, the newest only a previous link, and the middle one both, with `rel` attributes the test asserts on. The `<title>` from `Seo` reads the post title followed by the site title, and the description meta tag uses the frontmatter `description` when there is one and the excerpt when there is not. `GET /rss.xml` answers XML with one `item` per post, and an unknown path renders the 404 page.

The run executes `npm ci`, `npm run build`, `npx playwright install chromium`, then the suite headless until it passes, then `npx prettier --check` on the new files so they match `.prettierrc`. Because every page is static, the tests read the built HTML rather than waiting on hydration, except where a `Link` click must change the page, and the agent writes those with Playwright's navigation waits. It changes nothing under `src/` or `content/`; if a test reveals a real defect in a page, that goes in the pull request description for a separate change.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Write Playwright tests for this Gatsby site that build it, serve the output, and check the pages it generates. Read package.json, gatsby-config.js, gatsby-node.js, src/templates/blog-post.js and src/pages/index.js first: the site builds with npm, posts come from content/blog, and gatsby-node.js creates one page per post with previous and next neighbours. Add @playwright/test as a dev dependency, a playwright.config.js whose webServer runs npm run serve against the built public directory, and replace the placeholder test script with playwright test. Cover the home page listing every post newest first with links to their slugs, one post page with its heading, formatted date and rendered image, the previous and next links on the oldest, newest and a middle post, the document title and description meta tag from the Seo component, GET /rss.xml with one item per post, and the 404 page. Run npm ci, npm run build, playwright install chromium and the suite headless until it passes, then prettier --check on the new files, and open a pull request. Do not change files under src or content.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

The pull request adds `playwright.config.js`, a `tests` directory with one spec per area, `@playwright/test` under `devDependencies`, the replaced `test` script and the updated `package-lock.json`. It changes no page, template, component or post. Its description lists each test with the route it hits and what it asserts, and quotes the Playwright summary from the run.

A reviewer opens the navigation spec first, since it encodes the ordering `gatsby-node.js` produces and would be the first to break when a post is added: it should derive which post is oldest and newest from the content rather than hard-coding slugs, or name the posts it assumes. Then they check that the feed test counts items against the posts in `content/blog`, and that the config runs `npm run serve` against `public/` rather than `gatsby develop`, so the suite tests what a deploy ships.

The session keeps the build log, the Playwright output and every file the agent read before choosing its fixtures. A request to cover the `using-typescript` page or a new tag page is a follow-up message to the same session, and the agent extends the same branch.

## Run it on every pull request

Once the suite exists, run it on every pull request from a GitHub Actions job: `npm ci`, `npm run build`, `npx playwright install --with-deps chromium` and `npm test`. This repository has no workflow yet, and the agent's pull request adds one when the prompt asks for it.

To have an agent write the same suite for each site started from this template, a handler on your server sends this request with the new repository in `resources` whenever one is created, using the repository name as the `Idempotency-Key`, and reads the pull request link from the `run.completed` webhook on the API key.

## Why run it on Rush?

A Gatsby build with image processing is the slow part of writing end-to-end tests: build, serve, run, read the failure, fix a selector, build again. In its own sandbox the agent runs that loop on its own machine with its own Chromium, while your checkout and your `gatsby develop` server stay untouched.

The pull request comes with proof: the build log, the Playwright summary and the transcript showing which posts the agent read before asserting on their titles, dates and neighbours. Several sites built from the same starter can get the request at once, each in its own sandbox.

## Frequently asked questions

### Why run against gatsby serve instead of gatsby develop?

`gatsby serve` serves the `public/` directory a build produced, which is what a deploy ships, including the processed images and the `/rss.xml` the feed plugin writes at build time. `gatsby develop` renders pages on demand and does not write the feed, so a test against it would skip the feed and could pass on pages the build would fail.

### Will it change my pages or posts?

No. The diff is the Playwright config, the tests, the dev dependency, the lockfile and the `test` script that replaced the placeholder. A defect a test uncovers in a template is described in the pull request for a separate change.

### What happens to the tests when I add a post?

The home page and feed tests count posts from `content/blog` rather than assuming three, and the navigation test identifies the oldest and newest post by date, so a new post changes the expected neighbours without editing the tests. The pull request says which assumptions, if any, are fixed to named posts.

### Does it work with yarn or pnpm?

Yes. This repository has a `package-lock.json`, so the agent uses `npm` for the install, the build, the browser install and the lockfile. With a `yarn.lock` or `pnpm-lock.yaml` it uses that tool throughout and keeps that lockfile in the commit.
