Invite a member and join
An owner invites a member by email, and the member joins and sees the project.
This example uses Parcel, a demo store at parcel.example.com. Parcel is a demo project, not a customer.
Two people take part. The owner invites a member by email. The member accepts from the email and sees the Parcel project.
Before you start Link to Before you start
Each person needs a test account. Add both under Re:agent uses, in Test accounts.
| Name | Kind | Address |
|---|---|---|
| owner | Password | owner@parcel.example.com, with its password |
| member | With an email code or link | Rehearsal makes one, such as parcel-member@inbox.rehearsal.dev |
The member needs an account that signs in with an email code or link, because the invitation must reach its test inbox. An account with a password gets an address only when its code after the password is sent by email.
Ask Re:agent Link to Ask Re:agent
Open Re:agent and type: "Check that an invited member can join Parcel and see the project. The owner sends the invitation."
What Re:agent does Link to What Re:agent does
Re:agent opens a browser for each person, as flows with more than one person describes. Each line below is a row in the chat, in the app's own words. What follows a dot is the detail the chat shows beside the row.
- Checked your projects
- Listed 2 test accounts
In the owner's browser:
- Opened a browser on parcel.example.com as owner
- Opened parcel.example.com/sign-in
- Filled Email ·
owner@parcel.example.com - Filled Password
- Clicked Sign in
- Clicked Members
- Clicked Invite a member
- Filled Email ·
parcel-member@inbox.rehearsal.dev - Chose an option in Role · Member
- Clicked Send invitation
- Read the page · Invitation sent
In the member's browser:
- Opened a browser on parcel.example.com as member
- Read the test inbox · 1 message
- Opened parcel.example.com/invite
- Filled Name · Mira Okafor
- Clicked Accept invitation
- Read the page · Parcel
The last row is Saved the flow.
Re:agent never sees the owner's password. It types {{password}}, and Rehearsal fills in the real one. The link from the email is written down as {{link}}.
Then a card in the chat follows the new test. It moves through Flow saved, Test written, First run passed and Verified in a fresh browser.
The test Link to The test
Rehearsal writes a Playwright test from the saved flow. It looks like this, with a browser for each person.
import { expect, test } from '@playwright/test';import { participant } from '@rehearsal/codegen/runtime';test('Invited member can join and see the project', async ({ browser }) => { const owner = await participant(browser, 'owner'); const member = await participant(browser, 'member'); try { await test.step('Sign in as the owner', async () => { await owner.page.goto('/sign-in'); await owner.page.getByLabel('Email').fill('owner@parcel.example.com'); await owner.page.getByLabel('Password').fill(owner.password()); await owner.page.getByRole('button', { name: 'Sign in' }).click(); await owner.page.waitForURL('**/projects'); }); await test.step('Invite the member', async () => { await owner.page.getByRole('link', { name: 'Members' }).click(); await owner.page.getByRole('button', { name: 'Invite a member' }).click(); await owner.page.getByLabel('Email').fill('parcel-member@inbox.rehearsal.dev'); await owner.page.getByLabel('Role').selectOption('Member'); await owner.page.getByRole('button', { name: 'Send invitation' }).click(); }); await test.step('Check the invitation is listed', async () => { await expect(owner.page.getByText('parcel-member@inbox.rehearsal.dev')) .toBeVisible(); }); await test.step('Open the invitation as the member', async () => { const email = await member.latestEmail({ subject: 'invited' }); await member.page.goto(email.links[0]); }); await test.step('Accept the invitation', async () => { await member.page.getByLabel('Name').fill('Mira Okafor'); await member.page.getByRole('button', { name: 'Accept invitation' }).click(); await member.page.waitForURL('**/projects'); }); await test.step('Check the member sees the Parcel project', async () => { await expect(member.page.getByRole('link', { name: 'Parcel' })).toBeVisible(); }); } finally { await owner.close(); await member.close(); }});owner.password() reads the password when the test runs. member.latestEmail() waits for the invitation in the member's test inbox. Neither value is in the file.
The member's address stays the same on every run. If your app rejects a second invitation to it, ask Re:agent to end the flow by removing the member.
Run it Link to Run it
Press Run now on the card in the chat, or Run on the test's row in Tests. From the terminal:
rehearsal runs start --test <test-id>rehearsal runs wait <run-id>The test uses two browsers and still counts as one test run.
Next steps Link to Next steps
- Read how Re:agent creates a test in the chat.
- Run tests from the terminal and read their results.
- Try a flow with one person: Sign up with an email code.