feat(core): initial release with 3-tier secret storage
Implements SmartSecret with macOS Keychain, Linux secret-tool, and AES-256-GCM encrypted file fallback backends. Zero runtime dependencies.
This commit is contained in:
94
test/test.ts
Normal file
94
test/test.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import * as smartsecret from '../ts/index.js';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
|
||||
let testDir: string;
|
||||
let instance: smartsecret.SmartSecret;
|
||||
|
||||
tap.test('setup - create temp directory', async () => {
|
||||
testDir = path.join(os.tmpdir(), `smartsecret-test-${Date.now()}`);
|
||||
fs.mkdirSync(testDir, { recursive: true });
|
||||
instance = new smartsecret.SmartSecret({
|
||||
service: 'smartsecret-test',
|
||||
vaultPath: path.join(testDir, 'vault.json'),
|
||||
});
|
||||
});
|
||||
|
||||
tap.test('should report file-encrypted backend type', async () => {
|
||||
const backendType = await instance.getBackendType();
|
||||
// On CI/test environments without keychain, should fall back to file
|
||||
expect(backendType).toEqual('file-encrypted');
|
||||
});
|
||||
|
||||
tap.test('should set and get a secret', async () => {
|
||||
await instance.setSecret('test-account', 'my-secret-value');
|
||||
const result = await instance.getSecret('test-account');
|
||||
expect(result).toEqual('my-secret-value');
|
||||
});
|
||||
|
||||
tap.test('should return null for non-existent secret', async () => {
|
||||
const result = await instance.getSecret('nonexistent');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
tap.test('should overwrite an existing secret', async () => {
|
||||
await instance.setSecret('test-account', 'updated-secret');
|
||||
const result = await instance.getSecret('test-account');
|
||||
expect(result).toEqual('updated-secret');
|
||||
});
|
||||
|
||||
tap.test('should handle special characters in secrets', async () => {
|
||||
const specialSecret = '!@#$%^&*()_+-=[]{}|;:\'",.<>?/\\`~\n\ttabs and newlines';
|
||||
await instance.setSecret('special-chars', specialSecret);
|
||||
const result = await instance.getSecret('special-chars');
|
||||
expect(result).toEqual(specialSecret);
|
||||
});
|
||||
|
||||
tap.test('should handle empty string secrets', async () => {
|
||||
await instance.setSecret('empty-secret', '');
|
||||
const result = await instance.getSecret('empty-secret');
|
||||
expect(result).toEqual('');
|
||||
});
|
||||
|
||||
tap.test('should list accounts', async () => {
|
||||
const accounts = await instance.listAccounts();
|
||||
expect(accounts).toContain('test-account');
|
||||
expect(accounts).toContain('special-chars');
|
||||
expect(accounts).toContain('empty-secret');
|
||||
});
|
||||
|
||||
tap.test('should delete a secret', async () => {
|
||||
const deleted = await instance.deleteSecret('test-account');
|
||||
expect(deleted).toBeTrue();
|
||||
const result = await instance.getSecret('test-account');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
tap.test('should return false when deleting non-existent secret', async () => {
|
||||
const deleted = await instance.deleteSecret('nonexistent');
|
||||
expect(deleted).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should isolate secrets by service', async () => {
|
||||
const otherInstance = new smartsecret.SmartSecret({
|
||||
service: 'other-service',
|
||||
vaultPath: path.join(testDir, 'vault.json'),
|
||||
});
|
||||
|
||||
await otherInstance.setSecret('shared-name', 'other-value');
|
||||
await instance.setSecret('shared-name', 'original-value');
|
||||
|
||||
const otherResult = await otherInstance.getSecret('shared-name');
|
||||
const originalResult = await instance.getSecret('shared-name');
|
||||
|
||||
expect(otherResult).toEqual('other-value');
|
||||
expect(originalResult).toEqual('original-value');
|
||||
});
|
||||
|
||||
tap.test('cleanup - remove temp directory', async () => {
|
||||
fs.rmSync(testDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
Reference in New Issue
Block a user