1 parent
024f244f52
commit
3071e0d1ef
61 files changed
+7603
-29
No files matched your search
@@ -0,0 +1,49 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { displayPath, groupRecentProjects, renderStartScreen } from '../src/start-screen.ts';
|
||||
import { allowProjectTransition } from '../src/project-transition.ts';
|
||||
|
||||
const recent = (id, year, month, day, name = id) => ({
|
||||
id, path: `C:\\projects\\${id}\\package-project.json`, displayName: name,
|
||||
lastOpenedAt: new Date(year, month - 1, day, 10).getTime() / 1000, available: true,
|
||||
});
|
||||
|
||||
test('recent projects are grouped in local calendar order and searchable by name or path', () => {
|
||||
const projects = [recent('older', 2026, 9, 30), recent('today', 2026, 10, 21), recent('month', 2026, 10, 4), recent('week', 2026, 10, 20, '패키지 도구')];
|
||||
const now = new Date(2026, 9, 21, 18);
|
||||
assert.deepEqual([...groupRecentProjects(projects, '', now).keys()], ['오늘', '이번 주', '이번 달', '이전']);
|
||||
assert.equal([...groupRecentProjects(projects, '패키지', now).values()][0][0].id, 'week');
|
||||
assert.equal([...groupRecentProjects(projects, 'PROJECTS\\month', now).values()][0][0].id, 'month');
|
||||
assert.equal(groupRecentProjects(projects, 'not found', now).size, 0);
|
||||
});
|
||||
|
||||
test('extended Windows paths are displayed without changing their UNC semantics', () => {
|
||||
assert.equal(displayPath('\\\\?\\C:\\apps\\project.json'), 'C:\\apps\\project.json');
|
||||
assert.equal(displayPath('\\\\?\\UNC\\server\\share\\project.json'), '\\\\server\\share\\project.json');
|
||||
});
|
||||
|
||||
test('start screen has left recent projects and right actions without fabricated entries', () => {
|
||||
const base = { projects: [], query: '', busy: false, loading: false, error: '', notice: '', recentError: '', native: true };
|
||||
const empty = renderStartScreen(base);
|
||||
assert.match(empty, /최근 프로젝트가 없습니다/);
|
||||
assert.ok(empty.indexOf('recent-panel') < empty.indexOf('class="start-actions"'));
|
||||
assert.match(empty, /data-action="open"/);
|
||||
assert.match(empty, /data-action="new"/);
|
||||
assert.doesNotMatch(empty, /class="sidebar"/);
|
||||
const unsafe = { ...recent('a', 2026, 10, 21, '<img src=x onerror=alert(1)>'), available: false };
|
||||
const html = renderStartScreen({ ...base, projects: [unsafe] });
|
||||
assert.match(html, /<img/);
|
||||
assert.doesNotMatch(html, /<img src=x/);
|
||||
assert.match(html, /파일을 찾을 수 없습니다/);
|
||||
});
|
||||
|
||||
test('cancel keeps edits, discard does not save, and a save failure prevents closing', async () => {
|
||||
let saves = 0;
|
||||
assert.equal(await allowProjectTransition(true, async () => 'cancel', async () => { saves++; }), false);
|
||||
assert.equal(await allowProjectTransition(true, async () => 'discard', async () => { saves++; }), true);
|
||||
assert.equal(saves, 0);
|
||||
await assert.rejects(allowProjectTransition(true, async () => 'save', async () => { throw new Error('RevisionConflict'); }), /RevisionConflict/);
|
||||
assert.equal(await allowProjectTransition(true, async () => 'save', async () => { saves++; }), true);
|
||||
assert.equal(saves, 1);
|
||||
assert.equal(await allowProjectTransition(false, async () => { throw new Error('should not ask'); }, async () => {}), true);
|
||||
});
|
||||
Reference in new issue
Block a user