diff --git a/README.md b/README.md index 3c9bf8c..d7854e8 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,7 @@ npx cypress run --project ./e2e You can run your [factory_bot](https://github.com/thoughtbot/factory_bot) directly as well +then in Cypress ```js // spec/cypress/e2e/simple.cy.js describe('My First Test', () => { @@ -195,6 +196,32 @@ describe('My First Test', () => { }) }) ``` + +then in Playwright +```js +const { test, expect, request } = require('@playwright/test'); + +test.describe('My First Test', () => { + test('visit root', async ({ page }) => { + // This calls to the backend to prepare the application state + await appFactories([ + ['create_list', 'post', 10], + ['create', 'post', { title: 'Hello World' }], + ['create', 'post', 'with_comments', { title: 'Factory_bot Traits here' }] + ]); + + // Visit the application under test + await page.goto('/'); + + await expect(page).toHaveText('Hello World'); + + // Accessing result + const records = await appFactories([['create', 'invoice', { paid: false }]]); + await page.goto(`/invoices/${records[0].id}`); + }); +}); +``` + You can check the [association docs](docs/factory_bot_associations.md) on more ways to setup association with the correct data. 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(() => { }); ``` +add the following file to Playwright +```js +// test/playwright/support/on-rails.js +async function appCommands(body) { + const context = await request.newContext(); + const response = await context.post('/__e2e__/command', { + data: body, + headers: { + 'Content-Type': 'application/json' + } + }); + + if (response.status() !== 201) { + const responseBody = await response.text(); + throw new Error(`Expected status 201 but got ${response.status()} - ${responseBody}`); + } + + return response.json(); +} + +async function app(name, commandOptions = {}) { + const body = await appCommands({ name, options: commandOptions }); + return body[0]; +} + +async function appScenario(name, options = {}) { + const body = { name: `scenarios/${name}`, options }; + const result = await appCommands(body); + return result[0]; +} + +async function appFactories(options) { + return app('factory_bot', options); +} + +async function clean() { + await app('clean'); +} +``` + ## API Prefix If your Rails server is exposed under a proxy, typically https://my-local.dev/api, you can use the `api_prefix` option. diff --git a/docs/authentication.md b/docs/authentication.md index d568484..d5dc142 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -51,3 +51,33 @@ cy.forceLogin() cy.forceLogin({redirect_to: '/profile'}) cy.forceLogin({email: 'someuser@mail.com'}) ``` + +In `playwright/support/on-rails.js`: + +```js +async function forceLogin(page, { email, redirect_to = '/' }) { + // Validate inputs + if (typeof email !== 'string' || typeof redirect_to !== 'string') { + throw new Error('Invalid input: email and redirect_to must be non-empty strings'); + } + + const response = await page.request.post('/__e2e__/force_login', { + data: { email: email, redirect_to: redirect_to }, + headers: { 'Content-Type': 'application/json' } + }); + + // Handle response based on status code + if (response.ok()) { + await page.goto(redirect_to); + } else { + // Throw an exception for specific error statuses + throw new Error(`Login failed with status: ${response.status()}`); + } +} +``` + +Examples of usage in Playwright specs: +```js +await forceLogin(page, { email: 'someuser@mail.com', redirect_to: '/profile' }); + +``` \ No newline at end of file diff --git a/docs/factory_bot_associations.md b/docs/factory_bot_associations.md index 0ab7474..846ad2a 100644 --- a/docs/factory_bot_associations.md +++ b/docs/factory_bot_associations.md @@ -54,6 +54,15 @@ cy.appFactories([['create', 'author']]).then((records) => { }) ``` +then in Playwright +There are a few ways you can set up associations with the correct data using Playwright and FactoryBot. +```js +const records = await appFactories([['create', 'author', { name: 'James' }]], context); +await appFactories([['create', 'post', { title: 'Playwright is cool', author_id: records[0].id }]], context); +// 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. +``` + + ## 2. Using transient attributes ```rb @@ -81,6 +90,11 @@ cy.appFactories([['create', 'post', { title: 'Cypress is cool', author_name: 'Ja cy.appFactories([['create', 'post']]) ``` +then in Playwright +```js +const records = await appFactories([['create', 'post', { title: 'Playwright is cool', author_name: 'James' }]]); +``` + ## 3. Using Nested Attributes ```rb