mirror of
https://github.com/hectorqin/reader.git
synced 2026-11-11 05:20:54 +08:00
55 lines
2.9 KiB
TypeScript
55 lines
2.9 KiB
TypeScript
import { render } from '../src/shared/ui/render-root.ts';
|
|
// @vitest-environment jsdom
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { act } from 'react';
|
|
import { createElement as h } from 'react';
|
|
import { ReaderIndicators } from '../src/ui/reader-indicators.tsx';
|
|
import type { ChromeState } from '../src/ui/reader-chrome.tsx';
|
|
import { SettingsStore } from '../src/store/settings.ts';
|
|
|
|
const container = document.createElement('div');
|
|
const state = {
|
|
title: '测试书名', chapterLabel: '第二章', pageInChapter: 3, chapterPages: 12, progress: 0.47,
|
|
} as ChromeState;
|
|
const texts = () => Array.from(container.querySelectorAll('span'), el => el.textContent);
|
|
afterEach(() => { act(() => render(null, container)); vi.useRealTimers(); });
|
|
|
|
describe('reading information', () => {
|
|
it('maps all four positions independently and allows hiding each one', () => {
|
|
act(() => render(h(ReaderIndicators, { state: { ...state,
|
|
readoutTopLeft: 'book', readoutTopRight: 'chapter',
|
|
readoutBottomLeft: 'progress', readoutBottomRight: 'none',
|
|
} }), container));
|
|
expect(texts()).toEqual(['测试书名', '第二章', '第3/12页 47%', '']);
|
|
act(() => render(h(ReaderIndicators, { state: { ...state,
|
|
readoutTopLeft: 'none', readoutTopRight: 'none',
|
|
readoutBottomLeft: 'none', readoutBottomRight: 'none',
|
|
} }), container));
|
|
expect(texts()).toEqual(['', '', '', '']);
|
|
expect(container.querySelectorAll('.reading-indicator')).toHaveLength(2);
|
|
});
|
|
|
|
it('refreshes time at the minute boundary and on resume, then cleans up', () => {
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(new Date(2026, 8, 20, 9, 5, 59));
|
|
act(() => render(h(ReaderIndicators, { state }), container));
|
|
expect(texts()[3]).toBe('09:05');
|
|
act(() => { vi.advanceTimersByTime(1000); });
|
|
expect(texts()[3]).toBe('09:06');
|
|
vi.setSystemTime(new Date(2026, 8, 20, 10, 15));
|
|
act(() => { document.dispatchEvent(new Event('visibilitychange')); });
|
|
expect(texts()[3]).toBe('10:15');
|
|
act(() => render(null, container));
|
|
expect(vi.getTimerCount()).toBe(0);
|
|
});
|
|
|
|
it('migrates older preferences and persists each position across store instances', async () => {
|
|
let saved = JSON.stringify({ theme: 'sepia', readoutTopRight: 'invalid' });
|
|
const kv = { get: async () => saved, set: async (_key: string, value: string) => { saved = value; }, remove: async () => {} };
|
|
const store = new SettingsStore(kv);
|
|
expect(await store.load()).toMatchObject({ theme: 'sepia', readoutTopLeft: 'chapter', readoutTopRight: 'none', readoutBottomLeft: 'progress', readoutBottomRight: 'time' });
|
|
await store.update({ readoutTopLeft: 'time', readoutTopRight: 'book', readoutBottomLeft: 'none', readoutBottomRight: 'chapter' });
|
|
expect(await new SettingsStore(kv).load()).toMatchObject({ readoutTopLeft: 'time', readoutTopRight: 'book', readoutBottomLeft: 'none', readoutBottomRight: 'chapter' });
|
|
});
|
|
});
|