mirror of
https://github.com/nexu-io/open-design.git
synced 2026-09-20 06:15:06 +08:00
50c15417a9
Enable completion sound and desktop notifications for fresh configurations while preserving saved opt-outs. Activate browser audio and permission flows only from the first real task submission gesture. Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com>
72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { fireEvent } from '@testing-library/react';
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import {
|
|
armCompletionFeedbackOnFirstGesture,
|
|
notifyCompletionFeedbackGesture,
|
|
type CompletionFeedbackActivationResult,
|
|
} from '../../src/utils/notifications';
|
|
|
|
const BASE_CONFIG = {
|
|
soundEnabled: true,
|
|
successSoundId: 'ding',
|
|
failureSoundId: 'buzz',
|
|
desktopEnabled: true,
|
|
};
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe('armCompletionFeedbackOnFirstGesture', () => {
|
|
it('waits for the first task submission, then primes audio and requests permission once', async () => {
|
|
const resume = vi.fn().mockResolvedValue(undefined);
|
|
class MockAudioContext {
|
|
state: AudioContextState = 'suspended';
|
|
resume = resume;
|
|
}
|
|
const requestPermission = vi.fn().mockResolvedValue('granted');
|
|
class MockNotification {
|
|
static permission: NotificationPermission = 'default';
|
|
static requestPermission = requestPermission;
|
|
}
|
|
vi.stubGlobal('AudioContext', MockAudioContext);
|
|
vi.stubGlobal('Notification', MockNotification);
|
|
const onResult = vi.fn<(result: CompletionFeedbackActivationResult) => void>();
|
|
|
|
const dispose = armCompletionFeedbackOnFirstGesture(BASE_CONFIG, onResult);
|
|
fireEvent.pointerDown(window);
|
|
expect(resume).not.toHaveBeenCalled();
|
|
expect(requestPermission).not.toHaveBeenCalled();
|
|
|
|
notifyCompletionFeedbackGesture();
|
|
notifyCompletionFeedbackGesture();
|
|
await vi.waitFor(() => expect(onResult).toHaveBeenCalledWith({ desktopPermission: 'granted' }));
|
|
|
|
expect(resume).toHaveBeenCalledTimes(1);
|
|
expect(requestPermission).toHaveBeenCalledTimes(1);
|
|
dispose();
|
|
});
|
|
|
|
it('reports a denied permission so the caller can turn the persisted switch off', async () => {
|
|
const requestPermission = vi.fn().mockResolvedValue('denied');
|
|
class MockNotification {
|
|
static permission: NotificationPermission = 'default';
|
|
static requestPermission = requestPermission;
|
|
}
|
|
vi.stubGlobal('Notification', MockNotification);
|
|
const onResult = vi.fn<(result: CompletionFeedbackActivationResult) => void>();
|
|
|
|
const dispose = armCompletionFeedbackOnFirstGesture(
|
|
{ ...BASE_CONFIG, soundEnabled: false },
|
|
onResult,
|
|
);
|
|
notifyCompletionFeedbackGesture();
|
|
await vi.waitFor(() => expect(onResult).toHaveBeenCalledWith({ desktopPermission: 'denied' }));
|
|
|
|
dispose();
|
|
});
|
|
});
|