Files
AFFiNE-Mirror/packages/frontend/apps/electron/test/helper/utils.spec.ts
DarkSky bcf2a51d41 feat(native): record encoding (#14188)
fix #13784 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Start/stop system or meeting recordings with Ogg/Opus artifacts and
native start/stop APIs; workspace backup recovery.

* **Refactor**
* Simplified recording lifecycle and UI flows; native runtime now
orchestrates recording/processing and reporting.

* **Bug Fixes**
* Stronger path validation, safer import/export dialogs, consistent
error handling/logging, and retry-safe recording processing.

* **Chores**
* Added cross-platform native audio capture and Ogg/Opus encoding
support.

* **Tests**
* New unit, integration, and e2e tests for recording, path guards,
dialogs, and workspace recovery.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-03-22 02:50:14 +08:00

108 lines
3.2 KiB
TypeScript

import { randomUUID } from 'node:crypto';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { afterEach, describe, expect, test } from 'vitest';
import {
assertPathComponent,
normalizeWorkspaceIdForPath,
resolveExistingPathInBase,
resolvePathInBase,
} from '../../src/shared/utils';
const tmpDir = path.join(os.tmpdir(), `affine-electron-utils-${randomUUID()}`);
afterEach(async () => {
await fs.rm(tmpDir, { recursive: true, force: true });
});
describe('path guards', () => {
test('resolvePathInBase blocks sibling-prefix escapes', () => {
const baseDir = path.join(tmpDir, 'recordings');
expect(() =>
resolvePathInBase(baseDir, '../recordings-evil/file.opus', {
label: 'directory',
})
).toThrow('Invalid directory');
});
test.runIf(process.platform !== 'win32')(
'resolveExistingPathInBase rejects symlink escapes',
async () => {
const baseDir = path.join(tmpDir, 'recordings');
const outsideDir = path.join(tmpDir, 'outside');
const outsideFile = path.join(outsideDir, 'secret.txt');
const linkPath = path.join(baseDir, '1234567890abcdef.blob');
await fs.mkdir(baseDir, { recursive: true });
await fs.mkdir(outsideDir, { recursive: true });
await fs.writeFile(outsideFile, 'secret');
await fs.symlink(outsideFile, linkPath);
await expect(
resolveExistingPathInBase(baseDir, linkPath, {
label: 'recording filepath',
})
).rejects.toThrow('Invalid recording filepath');
}
);
test('resolveExistingPathInBase falls back for missing descendants', async () => {
const baseDir = path.join(tmpDir, 'recordings');
await fs.mkdir(baseDir, { recursive: true });
const missingPath = path.join(
await fs.realpath(baseDir),
'pending',
'recording.opus'
);
await expect(
resolveExistingPathInBase(baseDir, missingPath, {
label: 'recording filepath',
})
).resolves.toBe(path.resolve(missingPath));
});
test.runIf(process.platform !== 'win32')(
'resolveExistingPathInBase preserves non-missing realpath errors',
async () => {
const baseDir = path.join(tmpDir, 'recordings');
const loopPath = path.join(baseDir, 'loop.opus');
await fs.mkdir(baseDir, { recursive: true });
await fs.symlink(path.basename(loopPath), loopPath);
await expect(
resolveExistingPathInBase(baseDir, loopPath, {
label: 'recording filepath',
})
).rejects.toMatchObject({ code: 'ELOOP' });
}
);
test.each(['../../escape', 'nested/id'])(
'assertPathComponent rejects invalid workspace id %s',
input => {
expect(() => assertPathComponent(input, 'workspace id')).toThrow(
'Invalid workspace id'
);
}
);
test.each([
{ input: 'legacy:id*with?reserved.', expected: 'legacy_id_with_reserved' },
{ input: 'safe-workspace', expected: 'safe-workspace' },
])(
'normalizeWorkspaceIdForPath maps $input to $expected on Windows',
({ input, expected }) => {
expect(normalizeWorkspaceIdForPath(input, { windows: true })).toBe(
expected
);
}
);
});