Files
RenewCMS/web/src/components/__tests__/InviteUserModal.spec.ts
T

74 lines
1.9 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest'
import { flushPromises, mount, type VueWrapper } from '@vue/test-utils'
import uiPlugin from '@nuxt/ui/vue-plugin'
import inviteEmailCases from '../../../../test/testdata/invite_emails.json'
import InviteUserModal from '../InviteUserModal.vue'
const INVALID_EMAIL = 'Enter a full email address, like name@example.com.'
const inviteUser = vi.fn()
vi.mock('@/composables/useUsers', () => ({
useUsers: () => ({ inviteUser }),
}))
let wrapper: VueWrapper | null = null
function emailInput() {
return document.body.querySelector<HTMLInputElement>('input[placeholder="name@example.com"]')!
}
function dialogText() {
return document.body.querySelector('[role="dialog"]')?.textContent ?? ''
}
function dispatch(element: HTMLElement, type: string) {
element.dispatchEvent(new Event(type, { bubbles: true }))
}
async function mountOpenModal() {
wrapper = mount(InviteUserModal, {
attachTo: document.body,
props: { open: true },
global: { plugins: [uiPlugin] },
})
await flushPromises()
}
function clickSend() {
const send = [...document.body.querySelectorAll('button')].find(
(button) => button.textContent?.trim() === 'Send invite',
)!
send.click()
return flushPromises()
}
afterEach(() => {
wrapper?.unmount()
wrapper = null
document.body.innerHTML = ''
inviteUser.mockReset()
})
describe('Invite modal email rule', () => {
it.each(inviteEmailCases)('gives "$email" the shared verdict (valid: $valid)', async (row) => {
inviteUser.mockResolvedValue({ id: 1 })
await mountOpenModal()
const input = emailInput()
input.value = row.email
dispatch(input, 'input')
dispatch(input, 'blur')
await flushPromises()
await clickSend()
if (row.valid) {
expect(dialogText()).not.toContain(INVALID_EMAIL)
expect(inviteUser).toHaveBeenCalledTimes(1)
} else {
expect(dialogText()).toContain(INVALID_EMAIL)
expect(inviteUser).not.toHaveBeenCalled()
}
})
})