mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-23 00:41:36 +00:00
- Introduced a new job `validate` in the GitHub Actions workflow to validate the desktop package. - Added steps for checking out the repository, setting up Node.js, installing dependencies, type checking, and running unit tests. - Updated the `package` job to depend on the `validate` job. chore: update package-lock.json and package.json for vitest integration - Added `vitest` as a development dependency in `package.json`. - Updated `typecheck` script to include a new TypeScript configuration for vitest. - Updated `package-lock.json` to reflect the new dependencies. refactor: modularize runtime path handling in main process - Created a new module `runtime-paths.ts` to handle static path normalization and request handling. - Refactored `main.ts` to utilize the new `normalizeStaticPath`, `getRequestedPath`, and `getPackagedRendererEntry` functions. test: add unit tests for runtime path utilities - Implemented tests for `normalizeStaticPath`, `getRequestedPath`, and `getPackagedRendererEntry` using Vitest. - Ensured coverage for directory traversal attempts and null-byte paths. chore: configure Vitest for testing - Added `vitest.config.ts` for Vitest configuration. - Created `tsconfig.vitest.json` to include types for Vitest in TypeScript compilation. Co-authored-by: Copilot <copilot@github.com>
61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
|
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
getPackagedRendererEntry,
|
|
getRequestedPath,
|
|
normalizeStaticPath,
|
|
} from '../src/main/runtime-paths.js';
|
|
|
|
describe('normalizeStaticPath', () => {
|
|
let rootDir: string;
|
|
|
|
beforeEach(() => {
|
|
rootDir = mkdtempSync(path.join(os.tmpdir(), 'gitnexus-desktop-static-'));
|
|
writeFileSync(path.join(rootDir, 'index.html'), '<html></html>');
|
|
writeFileSync(path.join(rootDir, 'asset.js'), 'console.log("ok");');
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(rootDir, { force: true, recursive: true });
|
|
});
|
|
|
|
it('rejects directory traversal attempts', () => {
|
|
expect(normalizeStaticPath(rootDir, '/../../etc/passwd')).toBeNull();
|
|
});
|
|
|
|
it('rejects null-byte paths', () => {
|
|
expect(normalizeStaticPath(rootDir, '/\0asset.js')).toBeNull();
|
|
});
|
|
|
|
it('returns a real asset path when the file exists', () => {
|
|
expect(normalizeStaticPath(rootDir, '/asset.js')).toBe(path.join(rootDir, 'asset.js'));
|
|
});
|
|
|
|
it('falls back to index.html for extensionless routes', () => {
|
|
expect(normalizeStaticPath(rootDir, '/desktop')).toBe(path.join(rootDir, 'index.html'));
|
|
});
|
|
});
|
|
|
|
describe('getRequestedPath', () => {
|
|
it('returns null for malformed percent-encoding', () => {
|
|
expect(getRequestedPath('/%GG')).toBeNull();
|
|
});
|
|
|
|
it('returns null for decoded null bytes', () => {
|
|
expect(getRequestedPath('/%00')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getPackagedRendererEntry', () => {
|
|
it('resolves the packaged renderer relative to dist/main', () => {
|
|
const rendererEntry = getPackagedRendererEntry(path.join('dist', 'main'));
|
|
|
|
expect(path.normalize(rendererEntry)).toBe(
|
|
path.normalize(path.join('dist', 'renderer', 'index.html')),
|
|
);
|
|
});
|
|
});
|