Files
wehub-resource-sync 2114b14ee0
Sync main into demo / sync (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:26 +08:00

127 lines
3.7 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import {
getTasksMRU,
deriveRunningApps,
getActiveTask,
getTaskTopActivity,
getActiveTopActivityId,
getActiveAppId,
} from '../os/taskUtils';
import type { OSState, Task } from '../os/types';
function mkTask(taskId: string, appId: string, lastActiveAt: number, stackSize = 1): Task {
const stack = Array.from({ length: stackSize }, (_, i) => ({
activityId: `${taskId}_act_${i}`,
appId,
initialRoute: '/',
}));
return { taskId, rootAppId: appId, stack, lastActiveAt };
}
function mkState(tasks: Task[], activeTaskId: string | null = null): OSState {
return {
tasks,
activeTaskId,
isLauncherVisible: !activeTaskId,
isRecentsVisible: false,
brightness: 60,
volume: 30,
};
}
describe('getTasksMRU', () => {
it('returns tasks sorted by lastActiveAt descending', () => {
const tasks = [mkTask('t1', 'a', 1), mkTask('t2', 'b', 3), mkTask('t3', 'c', 2)];
const sorted = getTasksMRU(tasks);
expect(sorted.map(t => t.taskId)).toEqual(['t2', 't3', 't1']);
});
it('returns empty array for empty input', () => {
expect(getTasksMRU([])).toEqual([]);
});
it('does not mutate the original array', () => {
const tasks = [mkTask('t1', 'a', 2), mkTask('t2', 'b', 1)];
const copy = [...tasks];
getTasksMRU(tasks);
expect(tasks).toEqual(copy);
});
});
describe('deriveRunningApps', () => {
it('returns unique app IDs in MRU order', () => {
const tasks = [
mkTask('t1', 'wechat', 1),
mkTask('t2', 'settings', 3),
mkTask('t3', 'wechat', 2),
];
expect(deriveRunningApps(tasks)).toEqual(['settings', 'wechat']);
});
it('returns empty for no tasks', () => {
expect(deriveRunningApps([])).toEqual([]);
});
});
describe('getActiveTask', () => {
it('returns the matching task when activeTaskId is set', () => {
const tasks = [mkTask('t1', 'a', 1), mkTask('t2', 'b', 2)];
const state = mkState(tasks, 't2');
expect(getActiveTask(state)?.taskId).toBe('t2');
});
it('returns null when activeTaskId is null', () => {
const state = mkState([mkTask('t1', 'a', 1)], null);
expect(getActiveTask(state)).toBeNull();
});
it('returns null when activeTaskId does not match any task', () => {
const state = mkState([mkTask('t1', 'a', 1)], 'nonexistent');
expect(getActiveTask(state)).toBeNull();
});
});
describe('getTaskTopActivity', () => {
it('returns the last activity in the stack', () => {
const task = mkTask('t1', 'a', 1, 3);
const top = getTaskTopActivity(task);
expect(top?.activityId).toBe('t1_act_2');
});
it('returns null for null/undefined task', () => {
expect(getTaskTopActivity(null)).toBeNull();
expect(getTaskTopActivity(undefined)).toBeNull();
});
it('returns null for task with empty stack', () => {
const task: Task = { taskId: 't1', rootAppId: 'a', stack: [], lastActiveAt: 0 };
expect(getTaskTopActivity(task)).toBeNull();
});
});
describe('getActiveTopActivityId', () => {
it('returns activity ID of the active task top', () => {
const task = mkTask('t1', 'a', 1, 2);
const state = mkState([task], 't1');
expect(getActiveTopActivityId(state)).toBe('t1_act_1');
});
it('returns null when no active task', () => {
const state = mkState([mkTask('t1', 'a', 1)], null);
expect(getActiveTopActivityId(state)).toBeNull();
});
});
describe('getActiveAppId', () => {
it('returns the appId of the top activity of the active task', () => {
const task = mkTask('t1', 'myapp', 1);
const state = mkState([task], 't1');
expect(getActiveAppId(state)).toBe('myapp');
});
it('returns null when no active task', () => {
const state = mkState([], null);
expect(getActiveAppId(state)).toBeNull();
});
});