Files

148 lines
4.8 KiB
JavaScript
Raw Permalink Normal View History

import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import fs from 'fs';
import os from 'os';
import path from 'path';
import { activateLinearAuth, getLinearAuth, setLinearAuth } from './auth.js';
import {
getLinearMappingFilePath,
mergeLinearMappingView,
readStoredLinearMapping,
resolveMappedProjectPath,
setStoredLinearMapping,
} from './mapping.js';
const makeTempDir = () => fs.mkdtempSync(path.join(os.tmpdir(), 'openchamber-linear-mapping-'));
describe('Linear project mapping storage', () => {
let dataDir;
let previousDataDir;
beforeEach(() => {
previousDataDir = process.env.OPENCHAMBER_DATA_DIR;
dataDir = makeTempDir();
process.env.OPENCHAMBER_DATA_DIR = dataDir;
});
afterEach(() => {
if (previousDataDir === undefined) {
delete process.env.OPENCHAMBER_DATA_DIR;
} else {
process.env.OPENCHAMBER_DATA_DIR = previousDataDir;
}
fs.rmSync(dataDir, { recursive: true, force: true });
});
it('treats a missing file as empty mapping, not a failure', () => {
expect(fs.existsSync(getLinearMappingFilePath())).toBe(false);
expect(readStoredLinearMapping()).toEqual({
defaultProjectPath: null,
teamProjectPaths: {},
});
});
it('round-trips a default project and per-team paths', () => {
const written = setStoredLinearMapping({
defaultProjectPath: '/Users/ada/openchamber',
teamProjectPaths: {
'team-eng': '/Users/ada/eng',
'team-empty': ' ',
},
});
expect(written).toEqual({
defaultProjectPath: '/Users/ada/openchamber',
teamProjectPaths: { 'team-eng': '/Users/ada/eng' },
});
expect(readStoredLinearMapping()).toEqual(written);
expect(fs.statSync(getLinearMappingFilePath()).mode & 0o777).toBe(0o600);
});
it('replaces the previous mapping on write', () => {
setStoredLinearMapping({
defaultProjectPath: '/old',
teamProjectPaths: { 'team-eng': '/eng' },
});
const next = setStoredLinearMapping({
defaultProjectPath: null,
teamProjectPaths: {},
});
expect(next).toEqual({ defaultProjectPath: null, teamProjectPaths: {} });
expect(readStoredLinearMapping()).toEqual(next);
});
it('keeps tokens when a mapping write is rejected', () => {
setLinearAuth({
accessToken: 'access-keep',
refreshToken: 'refresh-keep',
expiresAt: Date.now() + 60_000,
});
setStoredLinearMapping({
defaultProjectPath: '/keep',
teamProjectPaths: { 'team-eng': '/eng' },
});
expect(() => setStoredLinearMapping(null)).toThrow(/object/);
expect(readStoredLinearMapping()).toEqual({
defaultProjectPath: '/keep',
teamProjectPaths: { 'team-eng': '/eng' },
});
expect(getLinearAuth().accessToken).toBe('access-keep');
});
it('rejects a malformed mapping file instead of treating it as empty', () => {
fs.writeFileSync(getLinearMappingFilePath(), '{not-json', 'utf8');
expect(() => readStoredLinearMapping()).toThrow(/malformed/);
});
it('merges live teams onto stored paths and resolves team then default', () => {
const stored = {
defaultProjectPath: '/default',
teamProjectPaths: { 'team-eng': '/eng' },
};
const view = mergeLinearMappingView(stored, [
{ id: 'team-eng', key: 'ENG', name: 'Engineering' },
{ id: 'team-des', key: 'DES', name: 'Design' },
]);
expect(view).toEqual({
defaultProjectPath: '/default',
teams: [
{ id: 'team-eng', key: 'ENG', name: 'Engineering', projectPath: '/eng' },
{ id: 'team-des', key: 'DES', name: 'Design', projectPath: null },
],
});
expect(resolveMappedProjectPath(view, { id: 'team-eng', key: 'ENG' })).toBe('/eng');
expect(resolveMappedProjectPath(view, { id: 'team-des', key: 'DES' })).toBe('/default');
expect(resolveMappedProjectPath(view, null)).toBe('/default');
});
it('keeps mapping slices isolated per workspace', () => {
setLinearAuth({
accessToken: 'access-a',
user: { id: 'user-a', name: 'Ada' },
organization: { id: 'org-a', name: 'Alpha', urlKey: 'alpha' },
});
setStoredLinearMapping({
defaultProjectPath: '/alpha',
teamProjectPaths: { 'team-a': '/alpha-eng' },
});
setLinearAuth({
accessToken: 'access-b',
user: { id: 'user-b', name: 'Ben' },
organization: { id: 'org-b', name: 'Beta', urlKey: 'beta' },
});
setStoredLinearMapping({
defaultProjectPath: '/beta',
teamProjectPaths: {},
});
expect(readStoredLinearMapping()).toEqual({
defaultProjectPath: '/beta',
teamProjectPaths: {},
});
expect(activateLinearAuth('org-a')).toBe(true);
expect(readStoredLinearMapping()).toEqual({
defaultProjectPath: '/alpha',
teamProjectPaths: { 'team-a': '/alpha-eng' },
});
});
});