Skip to content

Commit fd68007

Browse files
authored
Added Playwright examples to the documentation (#164)
* added playwright examples * removed incorrect comment * corrections to RabbitAI's comment
1 parent 7dc7581 commit fd68007

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

README.md

+67
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ npx cypress run --project ./e2e
172172

173173
You can run your [factory_bot](https://github.com/thoughtbot/factory_bot) directly as well
174174

175+
then in Cypress
175176
```js
176177
// spec/cypress/e2e/simple.cy.js
177178
describe('My First Test', () => {
@@ -195,6 +196,32 @@ describe('My First Test', () => {
195196
})
196197
})
197198
```
199+
200+
then in Playwright
201+
```js
202+
const { test, expect, request } = require('@playwright/test');
203+
204+
test.describe('My First Test', () => {
205+
test('visit root', async ({ page }) => {
206+
// This calls to the backend to prepare the application state
207+
await appFactories([
208+
['create_list', 'post', 10],
209+
['create', 'post', { title: 'Hello World' }],
210+
['create', 'post', 'with_comments', { title: 'Factory_bot Traits here' }]
211+
]);
212+
213+
// Visit the application under test
214+
await page.goto('/');
215+
216+
await expect(page).toHaveText('Hello World');
217+
218+
// Accessing result
219+
const records = await appFactories([['create', 'invoice', { paid: false }]]);
220+
await page.goto(`/invoices/${records[0].id}`);
221+
});
222+
});
223+
```
224+
198225
You can check the [association docs](docs/factory_bot_associations.md) on more ways to setup association with the correct data.
199226

200227
In some cases, using static Cypress fixtures may not provide sufficient flexibility when mocking HTTP response bodies. It's possible to use `FactoryBot.build` to generate Ruby hashes that can then be used as mock JSON responses:
@@ -509,6 +536,46 @@ beforeEach(() => {
509536
});
510537
```
511538

539+
add the following file to Playwright
540+
```js
541+
// test/playwright/support/on-rails.js
542+
async function appCommands(body) {
543+
const context = await request.newContext();
544+
const response = await context.post('/__e2e__/command', {
545+
data: body,
546+
headers: {
547+
'Content-Type': 'application/json'
548+
}
549+
});
550+
551+
if (response.status() !== 201) {
552+
const responseBody = await response.text();
553+
throw new Error(`Expected status 201 but got ${response.status()} - ${responseBody}`);
554+
}
555+
556+
return response.json();
557+
}
558+
559+
async function app(name, commandOptions = {}) {
560+
const body = await appCommands({ name, options: commandOptions });
561+
return body[0];
562+
}
563+
564+
async function appScenario(name, options = {}) {
565+
const body = { name: `scenarios/${name}`, options };
566+
const result = await appCommands(body);
567+
return result[0];
568+
}
569+
570+
async function appFactories(options) {
571+
return app('factory_bot', options);
572+
}
573+
574+
async function clean() {
575+
await app('clean');
576+
}
577+
```
578+
512579
## API Prefix
513580

514581
If your Rails server is exposed under a proxy, typically https://my-local.dev/api, you can use the `api_prefix` option.

docs/authentication.md

+30
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,33 @@ cy.forceLogin()
5151
cy.forceLogin({redirect_to: '/profile'})
5252
cy.forceLogin({email: '[email protected]'})
5353
```
54+
55+
In `playwright/support/on-rails.js`:
56+
57+
```js
58+
async function forceLogin(page, { email, redirect_to = '/' }) {
59+
// Validate inputs
60+
if (typeof email !== 'string' || typeof redirect_to !== 'string') {
61+
throw new Error('Invalid input: email and redirect_to must be non-empty strings');
62+
}
63+
64+
const response = await page.request.post('/__e2e__/force_login', {
65+
data: { email: email, redirect_to: redirect_to },
66+
headers: { 'Content-Type': 'application/json' }
67+
});
68+
69+
// Handle response based on status code
70+
if (response.ok()) {
71+
await page.goto(redirect_to);
72+
} else {
73+
// Throw an exception for specific error statuses
74+
throw new Error(`Login failed with status: ${response.status()}`);
75+
}
76+
}
77+
```
78+
79+
Examples of usage in Playwright specs:
80+
```js
81+
await forceLogin(page, { email: '[email protected]', redirect_to: '/profile' });
82+
83+
```

docs/factory_bot_associations.md

+14
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ cy.appFactories([['create', 'author']]).then((records) => {
5454
})
5555
```
5656

57+
then in Playwright
58+
There are a few ways you can set up associations with the correct data using Playwright and FactoryBot.
59+
```js
60+
const records = await appFactories([['create', 'author', { name: 'James' }]], context);
61+
await appFactories([['create', 'post', { title: 'Playwright is cool', author_id: records[0].id }]], context);
62+
// Note: These Playwright examples demonstrate asynchronous interactions with the server for setting up data associations. Ensure that your environment is configured to handle these async operations.
63+
```
64+
65+
5766
## 2. Using transient attributes
5867

5968
```rb
@@ -81,6 +90,11 @@ cy.appFactories([['create', 'post', { title: 'Cypress is cool', author_name: 'Ja
8190
cy.appFactories([['create', 'post']])
8291
```
8392

93+
then in Playwright
94+
```js
95+
const records = await appFactories([['create', 'post', { title: 'Playwright is cool', author_name: 'James' }]]);
96+
```
97+
8498
## 3. Using Nested Attributes
8599

86100
```rb

0 commit comments

Comments
 (0)