import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { flushPromises, mount } from '@vue/test-utils' import ScientificNumber from '../../components/ScientificNumber.vue' describe('ScientificNumber copy (4b)', () => { const writeText = vi.fn().mockResolvedValue(undefined) beforeEach(() => { vi.useFakeTimers() Object.defineProperty(navigator, 'clipboard', { value: { writeText }, configurable: true }) }) afterEach(() => { vi.useRealTimers() writeText.mockClear() }) async function copy() { const wrapper = mount(ScientificNumber, { props: { value: 6.022e23, copyable: true } }) await wrapper.find('.mint-sci-number__copy-btn').trigger('click') await flushPromises() return wrapper } it('should name the copy button when copyable', () => { const wrapper = mount(ScientificNumber, { props: { value: 1, copyable: true } }) expect(wrapper.find('.mint-sci-number__copy-btn').attributes('aria-label')).toBe('Copy value') }) it('should write the canonical value to the clipboard when the copy button is clicked', async () => { await copy() expect(writeText).toHaveBeenCalledWith('6.022e23') }) it('should confirm the copied value in text when copy succeeds', async () => { const wrapper = await copy() expect(wrapper.find('.mint-sci-number__copied').text()).toBe('Copied 6.022e23') }) it('should show the check icon when copy succeeds', async () => { const wrapper = await copy() expect(wrapper.find('.mint-sci-number__copy-btn--copied').exists()).toBe(true) }) it('should drop the confirmation when 1.5s have passed', async () => { const wrapper = await copy() vi.advanceTimersByTime(1500) await flushPromises() expect(wrapper.find('.mint-sci-number__copied').exists()).toBe(false) }) }) describe('ScientificNumber exponent (4b)', () => { it('should carry the exponent digits in data-exponent when notation is scientific', () => { const wrapper = mount(ScientificNumber, { props: { value: 6.022e23 } }) expect(wrapper.find('.mint-sci-number__exponent').attributes('data-exponent')).toBe('23') }) it('should render a negative exponent with a true minus sign when the value is small', () => { const wrapper = mount(ScientificNumber, { props: { value: 4.2e-4 } }) expect(wrapper.find('.mint-sci-number__exponent').attributes('data-exponent')).toBe('−4') }) it('should carry a negative exponent with an ASCII hyphen in the hidden copy text when the value is small', () => { const wrapper = mount(ScientificNumber, { props: { value: 6.6e-34 } }) expect(wrapper.find('.mint-sci-number__sr').text()).toBe('^-34') }) it('should hide the raised exponent from assistive tech when notation is scientific', () => { const wrapper = mount(ScientificNumber, { props: { value: 6.022e23 } }) expect(wrapper.find('.mint-sci-number__exponent').attributes('aria-hidden')).toBe('true') }) it('should keep the raised exponent out of the text content when notation is scientific', () => { const wrapper = mount(ScientificNumber, { props: { value: 6.022e23 } }) expect(wrapper.find('.mint-sci-number__exponent').text()).toBe('') }) it('should read as an unambiguous power of ten when notation is scientific', () => { const wrapper = mount(ScientificNumber, { props: { value: 6.022e23 } }) expect(wrapper.text()).toBe('6.022×10^23') }) }) describe('ScientificNumber selection copy (4b)', () => { afterEach(() => { document.getSelection()?.removeAllRanges() document.body.innerHTML = '' }) function selectAndCopy(select: (root: HTMLElement) => Node) { const wrapper = mount(ScientificNumber, { props: { value: 6.022e23, unit: 'mol⁻¹' }, attachTo: document.body, }) const range = document.createRange() range.selectNodeContents(select(wrapper.element as HTMLElement)) document.getSelection()!.addRange(range) const setData = vi.fn() wrapper.trigger('copy', { clipboardData: { setData } }) return setData } it('should copy the canonical value when the selection lies inside the number', () => { const setData = selectAndCopy(root => root) expect(setData).toHaveBeenCalledWith('text/plain', '6.022e23 mol⁻¹') }) it('should leave the clipboard to the browser when the selection extends past the number', () => { const setData = selectAndCopy(root => root.parentElement!) expect(setData).not.toHaveBeenCalled() }) })