112 lines
4.2 KiB
JavaScript
112 lines
4.2 KiB
JavaScript
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||
|
|
import { flushPromises, mount } from '@vue/test-utils';
|
||
|
|
|
||
|
|
import RenderPreview from '../../../resources/js/Components/RenderPreview.vue';
|
||
|
|
|
||
|
|
const BODY = 'Hi {{ name }}, order {{ order_id }} shipped.';
|
||
|
|
const VARIABLES = ['name', 'order_id'];
|
||
|
|
|
||
|
|
/** Replace `navigator.clipboard` for the duration of a test. */
|
||
|
|
const installClipboard = (fail = false) => {
|
||
|
|
const writeText = vi.fn(
|
||
|
|
fail
|
||
|
|
? () => Promise.reject(new Error('Permission denied'))
|
||
|
|
: () => Promise.resolve()
|
||
|
|
);
|
||
|
|
|
||
|
|
vi.stubGlobal('navigator', { clipboard: { writeText } });
|
||
|
|
return writeText;
|
||
|
|
};
|
||
|
|
|
||
|
|
const buttonWithText = (wrapper, text) =>
|
||
|
|
wrapper.findAll('button').find((button) => button.text() === text);
|
||
|
|
|
||
|
|
describe('RenderPreview', () => {
|
||
|
|
afterEach(() => {
|
||
|
|
vi.unstubAllGlobals();
|
||
|
|
vi.useRealTimers();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('shows a hint and no inputs when the prompt has no variables', () => {
|
||
|
|
const wrapper = mount(RenderPreview, {
|
||
|
|
props: { body: 'Static text only.', variables: [] },
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(wrapper.text()).toContain('This prompt has no {{variables}}');
|
||
|
|
expect(wrapper.find('textarea').exists()).toBe(false);
|
||
|
|
expect(wrapper.find('pre').text()).toBe('Static text only.');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders one labelled input per variable', () => {
|
||
|
|
const wrapper = mount(RenderPreview, { props: { body: BODY, variables: VARIABLES } });
|
||
|
|
|
||
|
|
const inputs = wrapper.findAll('textarea');
|
||
|
|
expect(inputs).toHaveLength(2);
|
||
|
|
expect(inputs[0].attributes('id')).toBe('var-name');
|
||
|
|
expect(inputs[1].attributes('id')).toBe('var-order_id');
|
||
|
|
expect(wrapper.text()).toContain('{{name}}');
|
||
|
|
expect(wrapper.text()).toContain('{{order_id}}');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('keeps placeholders until values are entered, then substitutes live', async () => {
|
||
|
|
const wrapper = mount(RenderPreview, { props: { body: BODY, variables: VARIABLES } });
|
||
|
|
|
||
|
|
expect(wrapper.find('pre').text()).toBe(BODY);
|
||
|
|
|
||
|
|
await wrapper.findAll('textarea')[0].setValue('Ada');
|
||
|
|
expect(wrapper.find('pre').text()).toBe('Hi Ada, order {{ order_id }} shipped.');
|
||
|
|
|
||
|
|
await wrapper.findAll('textarea')[1].setValue('42');
|
||
|
|
expect(wrapper.find('pre').text()).toBe('Hi Ada, order 42 shipped.');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('emits "use" with the current values', async () => {
|
||
|
|
const wrapper = mount(RenderPreview, {
|
||
|
|
props: { body: BODY, variables: VARIABLES, useLabel: 'Use prompt (counts usage)' },
|
||
|
|
});
|
||
|
|
|
||
|
|
await wrapper.findAll('textarea')[0].setValue('Ada');
|
||
|
|
await buttonWithText(wrapper, 'Use prompt (counts usage)').trigger('click');
|
||
|
|
|
||
|
|
expect(wrapper.emitted('use')).toHaveLength(1);
|
||
|
|
expect(wrapper.emitted('use')[0]).toEqual([{ name: 'Ada', order_id: '' }]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('disables the use button while busy', () => {
|
||
|
|
const wrapper = mount(RenderPreview, {
|
||
|
|
props: { body: BODY, variables: VARIABLES, busy: true },
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(buttonWithText(wrapper, 'Use prompt').attributes('disabled')).toBeDefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('copies the live preview and shows a transient confirmation', async () => {
|
||
|
|
vi.useFakeTimers();
|
||
|
|
const writeText = installClipboard();
|
||
|
|
const wrapper = mount(RenderPreview, { props: { body: BODY, variables: VARIABLES } });
|
||
|
|
|
||
|
|
await wrapper.findAll('textarea')[0].setValue('Ada');
|
||
|
|
const copyButton = buttonWithText(wrapper, 'Copy preview');
|
||
|
|
await copyButton.trigger('click');
|
||
|
|
await vi.advanceTimersByTimeAsync(0);
|
||
|
|
|
||
|
|
expect(writeText).toHaveBeenCalledWith('Hi Ada, order {{ order_id }} shipped.');
|
||
|
|
expect(copyButton.text()).toBe('✓ Copied');
|
||
|
|
|
||
|
|
await vi.advanceTimersByTimeAsync(1500);
|
||
|
|
expect(copyButton.text()).toBe('Copy preview');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('ignores clipboard failures', async () => {
|
||
|
|
installClipboard(true);
|
||
|
|
const wrapper = mount(RenderPreview, { props: { body: BODY, variables: VARIABLES } });
|
||
|
|
|
||
|
|
await wrapper.findAll('textarea')[0].setValue('Ada');
|
||
|
|
const copyButton = buttonWithText(wrapper, 'Copy preview');
|
||
|
|
await copyButton.trigger('click');
|
||
|
|
await flushPromises();
|
||
|
|
|
||
|
|
expect(copyButton.text()).toBe('Copy preview');
|
||
|
|
});
|
||
|
|
});
|