import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import NotificationPromptBanner from '@/components/ui/NotificationPromptBanner.vue'
function mountBanner(props = {}) {
return mount(NotificationPromptBanner, {
props: {
open: true,
title: 'Turn on notifications',
text: 'Navi can let you know when a reply is ready.',
acceptText: 'Turn on',
dismissText: 'Not now',
...props,
},
})
}
describe('NotificationPromptBanner', () => {
it('renders nothing while it is closed', () => {
expect(mountBanner({ open: false }).find('.notification-prompt').exists()).toBe(false)
})
it('shows what it was given, and both answers', () => {
const wrapper = mountBanner()
expect(wrapper.find('.notification-prompt-title').text()).toBe('Turn on notifications')
expect(wrapper.find('.notification-prompt-text').text())
.toBe('Navi can let you know when a reply is ready.')
expect(wrapper.findAll('button').map(button => button.text()))
.toEqual(['Turn on', 'Not now'])
expect(wrapper.find('i.ph-bell').exists()).toBe(true)
})
it('reports the answer from the click itself, with nothing in between', () => {
// The whole point of the button: the browser only shows its own prompt if
// the gesture is still live when the handler runs, so the emit must not
// wait on anything.
const wrapper = mountBanner()
const [accept] = wrapper.findAll('button')
accept.element.click()
expect(wrapper.emitted('accept')).toHaveLength(1)
expect(wrapper.emitted('dismiss')).toBeUndefined()
})
it('reports the second answer too', async () => {
const wrapper = mountBanner()
const [, dismiss] = wrapper.findAll('button')
await dismiss.trigger('click')
expect(wrapper.emitted('dismiss')).toHaveLength(1)
expect(wrapper.emitted('accept')).toBeUndefined()
})
it('closes both answers while an answer is in flight', () => {
const wrapper = mountBanner({ busy: true })
for (const button of wrapper.findAll('button')) {
expect(button.attributes('disabled')).toBeDefined()
}
})
it('announces itself by the title it was given', () => {
const wrapper = mountBanner()
const region = wrapper.find('[role="region"]')
expect(region.attributes('aria-label')).toBe('Turn on notifications')
expect(region.attributes('aria-live')).toBe('polite')
})
it('lets the caller replace the body and the actions', () => {
const wrapper = mount(NotificationPromptBanner, {
props: { open: true, title: 'Turn on notifications' },
slots: { default: '<b>your own words</b>', actions: '<button>only one</button>' },
})
expect(wrapper.find('.notification-prompt-text').html()).toContain('your own words')
expect(wrapper.findAll('button').map(button => button.text())).toEqual(['only one'])
})
})