Skip to content

Commit b8679b7

Browse files
author
StackMemory Bot (CLI)
committed
test(coverage): add tests for feature-flags, compression, error-utils
67 new tests covering 3 more untested modules: - feature-flags.ts: isLocalOnly, isFeatureEnabled, getFeatureFlags with env var combinations - compression.ts: gzip/brotli round-trips, compressionRatio, detectCompressionType, chooseOptimalCompression - error-utils.ts: safeExecute, extractError, isNetworkError, createApiError, assertCondition, withDatabaseErrorHandling
1 parent 9ce5d72 commit b8679b7

3 files changed

Lines changed: 536 additions & 0 deletions

File tree

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { describe, it, expect, afterEach } from 'vitest';
2+
import {
3+
isLocalOnly,
4+
isFeatureEnabled,
5+
getFeatureFlags,
6+
} from '../feature-flags.js';
7+
8+
const ENV_KEYS = [
9+
'STACKMEMORY_LOCAL',
10+
'LOCAL_ONLY',
11+
'STACKMEMORY_LINEAR',
12+
'LINEAR_API_KEY',
13+
'LINEAR_OAUTH_TOKEN',
14+
'STACKMEMORY_AI',
15+
'ANTHROPIC_API_KEY',
16+
'OPENAI_API_KEY',
17+
'STACKMEMORY_SKILLS',
18+
'STACKMEMORY_RALPH',
19+
'STACKMEMORY_MULTI_PROVIDER',
20+
];
21+
22+
describe('feature-flags', () => {
23+
const saved: Record<string, string | undefined> = {};
24+
25+
afterEach(() => {
26+
// Restore all env vars
27+
for (const key of ENV_KEYS) {
28+
if (saved[key] !== undefined) {
29+
process.env[key] = saved[key];
30+
} else {
31+
delete process.env[key];
32+
}
33+
}
34+
});
35+
36+
function clearEnv() {
37+
for (const key of ENV_KEYS) {
38+
saved[key] = process.env[key];
39+
delete process.env[key];
40+
}
41+
}
42+
43+
describe('isLocalOnly', () => {
44+
it('returns false by default', () => {
45+
clearEnv();
46+
expect(isLocalOnly()).toBe(false);
47+
});
48+
49+
it('returns true for STACKMEMORY_LOCAL=true', () => {
50+
clearEnv();
51+
process.env['STACKMEMORY_LOCAL'] = 'true';
52+
expect(isLocalOnly()).toBe(true);
53+
});
54+
55+
it('returns true for STACKMEMORY_LOCAL=1', () => {
56+
clearEnv();
57+
process.env['STACKMEMORY_LOCAL'] = '1';
58+
expect(isLocalOnly()).toBe(true);
59+
});
60+
61+
it('returns true for LOCAL_ONLY=true', () => {
62+
clearEnv();
63+
process.env['LOCAL_ONLY'] = 'true';
64+
expect(isLocalOnly()).toBe(true);
65+
});
66+
});
67+
68+
describe('isFeatureEnabled', () => {
69+
it('core is always enabled', () => {
70+
clearEnv();
71+
expect(isFeatureEnabled('core')).toBe(true);
72+
});
73+
74+
it('core is enabled even in local-only mode', () => {
75+
clearEnv();
76+
process.env['STACKMEMORY_LOCAL'] = 'true';
77+
expect(isFeatureEnabled('core')).toBe(true);
78+
});
79+
80+
it('external features disabled in local-only mode', () => {
81+
clearEnv();
82+
process.env['STACKMEMORY_LOCAL'] = 'true';
83+
process.env['LINEAR_API_KEY'] = 'lin_api_test';
84+
expect(isFeatureEnabled('linear')).toBe(false);
85+
});
86+
87+
it('linear enabled with API key', () => {
88+
clearEnv();
89+
process.env['LINEAR_API_KEY'] = 'lin_api_test';
90+
expect(isFeatureEnabled('linear')).toBe(true);
91+
});
92+
93+
it('linear enabled with OAuth token', () => {
94+
clearEnv();
95+
process.env['LINEAR_OAUTH_TOKEN'] = 'token';
96+
expect(isFeatureEnabled('linear')).toBe(true);
97+
});
98+
99+
it('linear disabled when explicitly set to false', () => {
100+
clearEnv();
101+
process.env['LINEAR_API_KEY'] = 'lin_api_test';
102+
process.env['STACKMEMORY_LINEAR'] = 'false';
103+
expect(isFeatureEnabled('linear')).toBe(false);
104+
});
105+
106+
it('skills enabled with env var', () => {
107+
clearEnv();
108+
process.env['STACKMEMORY_SKILLS'] = 'true';
109+
expect(isFeatureEnabled('skills')).toBe(true);
110+
});
111+
112+
it('skills disabled by default', () => {
113+
clearEnv();
114+
expect(isFeatureEnabled('skills')).toBe(false);
115+
});
116+
117+
it('ralph enabled by default', () => {
118+
clearEnv();
119+
expect(isFeatureEnabled('ralph')).toBe(true);
120+
});
121+
122+
it('ralph disabled explicitly', () => {
123+
clearEnv();
124+
process.env['STACKMEMORY_RALPH'] = 'false';
125+
expect(isFeatureEnabled('ralph')).toBe(false);
126+
});
127+
128+
it('multiProvider disabled by default', () => {
129+
clearEnv();
130+
expect(isFeatureEnabled('multiProvider')).toBe(false);
131+
});
132+
133+
it('multiProvider enabled with env var', () => {
134+
clearEnv();
135+
process.env['STACKMEMORY_MULTI_PROVIDER'] = 'true';
136+
expect(isFeatureEnabled('multiProvider')).toBe(true);
137+
});
138+
});
139+
140+
describe('getFeatureFlags', () => {
141+
it('returns all flags', () => {
142+
clearEnv();
143+
const flags = getFeatureFlags();
144+
expect(flags.core).toBe(true);
145+
expect(flags).toHaveProperty('linear');
146+
expect(flags).toHaveProperty('aiSummaries');
147+
expect(flags).toHaveProperty('skills');
148+
expect(flags).toHaveProperty('ralph');
149+
expect(flags).toHaveProperty('multiProvider');
150+
});
151+
152+
it('all external features disabled in local mode', () => {
153+
clearEnv();
154+
process.env['STACKMEMORY_LOCAL'] = 'true';
155+
const flags = getFeatureFlags();
156+
expect(flags.core).toBe(true);
157+
expect(flags.linear).toBe(false);
158+
expect(flags.aiSummaries).toBe(false);
159+
expect(flags.skills).toBe(false);
160+
expect(flags.ralph).toBe(false);
161+
expect(flags.multiProvider).toBe(false);
162+
});
163+
});
164+
});

0 commit comments

Comments
 (0)