import {applyAreYouSure, ignoreAreYouSure, initGlobalFormDirtyLeaveConfirm, shouldTriggerAreYouSure} from './are-you-sure.ts';
function createForm(fieldsHtml: string, wrapperClass = ''): HTMLFormElement {
document.body.insertAdjacentHTML('beforeend', `
`);
return document.body.lastElementChild!.querySelector('form')!;
}
const field = (form: HTMLFormElement, name: string) => form.elements.namedItem(name) as HTMLInputElement;
function set(field: HTMLInputElement, props: Partial, eventType = 'change') {
Object.assign(field, props);
field.dispatchEvent(new Event(eventType, {bubbles: true}));
}
const isBeforeUnloadPrevented = () => !window.dispatchEvent(new Event('beforeunload', {cancelable: true}));
afterEach(() => document.body.replaceChildren());
test('tracks field changes, clears on submit and reset', () => {
const form = createForm(`
`);
const onDirtyChange = vi.fn();
applyAreYouSure(form, onDirtyChange);
set(field(form, 'title'), {value: 'b'}, 'input');
set(field(form, 'title'), {value: 'c'}, 'input');
set(field(form, 'title'), {value: 'a'}, 'keyup');
set(field(form, 'flag'), {checked: true});
set(field(form, 'flag'), {checked: false});
set(field(form, 'pick'), {value: 'b'});
expect(onDirtyChange.mock.calls).toEqual([[true], [false], [true], [false], [true]]);
expect(shouldTriggerAreYouSure()).toBe(true);
form.addEventListener('submit', (e) => e.preventDefault());
form.dispatchEvent(new SubmitEvent('submit', {cancelable: true}));
expect(shouldTriggerAreYouSure()).toBe(false);
set(field(form, 'title'), {value: 'b'});
form.reset();
expect(shouldTriggerAreYouSure()).toBe(false);
});
test('ignores untracked fields', () => {
const form = createForm(`
`);
applyAreYouSure(form);
form.insertAdjacentHTML('beforeend', '');
for (const input of form.querySelectorAll('input')) set(input, {value: 'b'});
expect(shouldTriggerAreYouSure()).toBe(false);
});
test('applying again resets the baseline', () => {
const form = createForm(`
`);
const oldOnDirtyChange = vi.fn();
const onDirtyChange = vi.fn();
applyAreYouSure(form, oldOnDirtyChange);
set(field(form, 'title'), {value: 'b'});
form.querySelector('.wrapper')!.classList.add('ays-ignore');
applyAreYouSure(form, onDirtyChange);
set(field(form, 'summary'), {value: 'b'});
set(field(form, 'extra'), {value: 'b'});
field(form, 'extra').remove();
set(field(form, 'title'), {value: 'b'});
set(field(form, 'title'), {value: 'a'});
expect(oldOnDirtyChange.mock.calls).toEqual([[true]]);
expect(onDirtyChange.mock.calls).toEqual([[true], [false], [true]]);
});
test('initGlobalFormDirtyLeaveConfirm guards beforeunload', () => {
const signin = createForm('', 'page-content user signin');
initGlobalFormDirtyLeaveConfirm();
set(field(signin, 'user_name'), {value: 'b'});
expect(shouldTriggerAreYouSure()).toBe(false);
signin.parentElement!.remove();
const form = createForm('');
const ignored = createForm('');
ignored.classList.add('ignore-dirty');
initGlobalFormDirtyLeaveConfirm();
set(field(ignored, 'q'), {value: 'b'});
ignored.classList.remove('ignore-dirty');
expect(isBeforeUnloadPrevented()).toBe(false);
set(field(form, 'title'), {value: 'b'});
expect(isBeforeUnloadPrevented()).toBe(true);
form.parentElement!.classList.add('tw-hidden');
expect(isBeforeUnloadPrevented()).toBe(false);
form.parentElement!.classList.remove('tw-hidden');
ignoreAreYouSure(form);
expect(isBeforeUnloadPrevented()).toBe(false);
});