Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run
52 lines
2.1 KiB
TypeScript
52 lines
2.1 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import path from 'node:path';
|
|
import { qqDataRoots, qqDataRootsForPid } from '../src/qq-account/paths';
|
|
|
|
const files = vi.hoisted(() => ({ read: vi.fn() }));
|
|
vi.mock('node:fs', () => ({ readFileSync: files.read }));
|
|
const platform = process.platform;
|
|
|
|
beforeEach(() => {
|
|
Object.defineProperty(process, 'platform', { value: 'linux', configurable: true });
|
|
});
|
|
afterEach(() => {
|
|
Object.defineProperty(process, 'platform', { value: platform, configurable: true });
|
|
files.read.mockReset();
|
|
});
|
|
|
|
describe('account data root isolation', () => {
|
|
it('uses the client HOME and honours its XDG configuration', () => {
|
|
files.read.mockReturnValue('HOME=/clients/a\0IGNORED=value\0');
|
|
expect(qqDataRootsForPid(42)).toEqual([path.join('/clients/a', '.config', 'QQ')]);
|
|
files.read.mockReturnValue('HOME=/clients/a\0XDG_CONFIG_HOME=/clients/config\0');
|
|
expect(qqDataRootsForPid(42)).toEqual([path.join('/clients/config', 'QQ')]);
|
|
});
|
|
|
|
it('does not guess a HOME when the client environment has none', () => {
|
|
files.read.mockReturnValue('OTHER=value\0');
|
|
expect(qqDataRootsForPid(42)).toEqual([]);
|
|
});
|
|
|
|
it('reports no root for an exited process', () => {
|
|
files.read.mockImplementation(() => {
|
|
throw Object.assign(new Error('gone'), { code: 'ENOENT' });
|
|
});
|
|
expect(qqDataRootsForPid(42)).toEqual([]);
|
|
});
|
|
|
|
it('surfaces permission failures instead of reading another user directory', () => {
|
|
const error = Object.assign(new Error('denied'), { code: 'EACCES' });
|
|
files.read.mockImplementation(() => {
|
|
throw error;
|
|
});
|
|
expect(() => qqDataRootsForPid(42)).toThrow(error);
|
|
});
|
|
|
|
it('uses only the configured Windows data root', () => {
|
|
Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
|
|
files.read.mockReturnValue('[UserDataSet]\nUserDataSavePath=D:\\QQ\\Tencent Files\n');
|
|
expect(qqDataRoots()).toEqual(['D:\\QQ\\Tencent Files']);
|
|
expect(files.read).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|