feat: users row actions "Cancel invite" on Pending rows and "Renew invite" on Expired rows
This commit is contained in:
1 parent
1ece778caf
commit
142325730d
14 files changed
+1156
-35
No files matched your search
+3
-1
@@ -88,7 +88,9 @@ async function readScreen(name: string): Promise<Screen> {
|
||||
if (!reference) {
|
||||
throw new Error(`docs/design/screens/${name}.md has no visual reference line`)
|
||||
}
|
||||
const states = [...markdown.matchAll(/^### (.+)$/gm)].map((match) => match[1]!.trim())
|
||||
const statesStart = markdown.search(/^## States$/m)
|
||||
const statesMarkdown = statesStart === -1 ? markdown : markdown.slice(statesStart)
|
||||
const states = [...statesMarkdown.matchAll(/^### (.+)$/gm)].map((match) => match[1]!.trim())
|
||||
return { name, board: reference[1]!, group: reference[2]!, states }
|
||||
}
|
||||
|
||||
|
||||
+61
-4
@@ -634,6 +634,33 @@ async function openInviteModal(page: Page) {
|
||||
await page.mouse.move(0, 0)
|
||||
}
|
||||
|
||||
function rowActionButton(page: Page, email: string, name: string) {
|
||||
return page
|
||||
.locator('[data-testid="user-row"], [data-testid="user-card"]')
|
||||
.filter({ hasText: email })
|
||||
.getByRole('button', { name, exact: true })
|
||||
}
|
||||
|
||||
async function openCancelInviteDialog(page: Page) {
|
||||
await rowActionButton(page, 'sam.oliveira@renew.example', 'Cancel invite').click()
|
||||
await page.getByRole('alertdialog').waitFor()
|
||||
await page.mouse.move(0, 0)
|
||||
}
|
||||
|
||||
async function confirmCancelInvite(page: Page) {
|
||||
await openCancelInviteDialog(page)
|
||||
await page
|
||||
.getByRole('alertdialog')
|
||||
.getByRole('button', { name: /^Cancel(ling…| invite)$/ })
|
||||
.click()
|
||||
await page.mouse.move(0, 0)
|
||||
}
|
||||
|
||||
async function renewPaulHuberInvite(page: Page) {
|
||||
await rowActionButton(page, 'p.huber@gmail.com', 'Renew invite').click()
|
||||
await page.mouse.move(0, 0)
|
||||
}
|
||||
|
||||
function inviteWith(email: string, response?: ApiMock) {
|
||||
return async (page: Page) => {
|
||||
await openInviteModal(page)
|
||||
@@ -845,10 +872,40 @@ export const visualStates: Record<string, Record<string, VisualState>> = {
|
||||
Default: {
|
||||
path: '/users',
|
||||
api: usersApi(),
|
||||
exception: {
|
||||
maxPercent: 10.5,
|
||||
reason: 'Row actions (Cancel invite, Renew invite) drawn on the board are out of scope for this slice',
|
||||
approvedBy: 'user',
|
||||
},
|
||||
'Cancel invite: confirm': {
|
||||
path: '/users',
|
||||
api: usersApi(),
|
||||
steps: openCancelInviteDialog,
|
||||
},
|
||||
'Cancel invite: sending': {
|
||||
path: '/users',
|
||||
api: usersApi({ 'DELETE /v1/user/invite/2': { status: 204, hang: true } }),
|
||||
steps: confirmCancelInvite,
|
||||
},
|
||||
'Cancel invite: failed': {
|
||||
path: '/users',
|
||||
api: usersApi({ 'DELETE /v1/user/invite/2': { status: 500 } }),
|
||||
steps: async (page) => {
|
||||
await confirmCancelInvite(page)
|
||||
await page.getByText("Couldn't cancel the invite").waitFor()
|
||||
await page.mouse.move(0, 0)
|
||||
},
|
||||
},
|
||||
'Cancel invite: done': { path: '/users', skip: 'clock-sensitive' },
|
||||
'Renew invite: sending': {
|
||||
path: '/users',
|
||||
api: usersApi({ 'POST /v1/user/invite/1/renew': { status: 200, hang: true } }),
|
||||
steps: renewPaulHuberInvite,
|
||||
},
|
||||
'Renew invite: done': { path: '/users', skip: 'clock-sensitive' },
|
||||
'Renew invite: failed': {
|
||||
path: '/users',
|
||||
api: usersApi({ 'POST /v1/user/invite/1/renew': { status: 500 } }),
|
||||
steps: async (page) => {
|
||||
await renewPaulHuberInvite(page)
|
||||
await page.getByText("Couldn't renew the invite").waitFor()
|
||||
await page.mouse.move(0, 0)
|
||||
},
|
||||
},
|
||||
Loading: {
|
||||
|
||||
Reference in new issue
Block a user