Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions src/commands/auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ describe('runConfigure', () => {
const { capture, deps } = makeCapture();
// Pre-existing dev profile — re-running configure interactively must keep it
// (the internal dogfooding flow) without ever prompting for the endpoint.
writeProfile(
await writeProfile(
'dev',
{ apiKey: 'sk-old', apiUrl: 'https://api.example.com:8443' },
{ path: credentialsPath },
Expand Down Expand Up @@ -557,7 +557,7 @@ describe('runConfigure', () => {
it('dogfood-2026-05-25 — --from-env without TESTSPRITE_API_URL inherits existing profile api_url AND validates against it', async () => {
const { capture, deps } = makeCapture();
// Pre-write an existing profile with a custom (non-default) endpoint.
writeProfile(
await writeProfile(
'default',
{ apiKey: 'sk-old', apiUrl: 'https://api.example.com' },
{ path: credentialsPath },
Expand Down Expand Up @@ -605,7 +605,7 @@ describe('runConfigure', () => {

it('dogfood-2026-05-25 — --endpoint-url flag overrides existing profile api_url', async () => {
const { capture, deps } = makeCapture();
writeProfile(
await writeProfile(
'default',
{ apiKey: 'sk-old', apiUrl: 'https://api.example.com' },
{ path: credentialsPath },
Expand Down Expand Up @@ -635,7 +635,7 @@ describe('runConfigure', () => {
it('dogfood-2026-05-25 — no advisory when inherited url equals DEFAULT_API_URL', async () => {
const { capture, deps } = makeCapture();
// Existing profile has the default prod endpoint — no advisory needed.
writeProfile(
await writeProfile(
'default',
{ apiKey: 'sk-old', apiUrl: 'https://api.testsprite.com' },
{ path: credentialsPath },
Expand Down Expand Up @@ -711,7 +711,7 @@ describe('runConfigure', () => {
// An exported-but-empty env var (`export TESTSPRITE_API_URL=`) must not
// short-circuit the `??` chain to an empty endpoint; it should fall through
// to the existing profile's api_url.
writeProfile(
await writeProfile(
'default',
{ apiKey: 'sk-old', apiUrl: 'https://api.example.com:8443' },
{ path: credentialsPath },
Expand Down Expand Up @@ -817,7 +817,7 @@ describe('runWhoami', () => {
}

it('calls GET /me using the configured profile and prints text output', async () => {
writeProfile(
await writeProfile(
'default',
{ apiKey: 'sk-stored', apiUrl: 'https://api.example.com' },
{ path: credentialsPath },
Expand All @@ -840,7 +840,7 @@ describe('runWhoami', () => {
});

it('emits JSON when --output json', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runWhoami(
{ profile: 'default', output: 'json', debug: false },
Expand All @@ -865,7 +865,7 @@ describe('runWhoami', () => {
});

it('L1788: text output includes the resolved endpoint URL', async () => {
writeProfile(
await writeProfile(
'default',
{ apiKey: 'sk-stored', apiUrl: 'https://api.example.com' },
{ path: credentialsPath },
Expand Down Expand Up @@ -893,7 +893,7 @@ describe('runWhoami', () => {
});

it('L1788: JSON output does NOT add endpoint (raw /me envelope is passed through)', async () => {
writeProfile(
await writeProfile(
'default',
{ apiKey: 'sk-stored', apiUrl: 'https://api.example.com' },
{ path: credentialsPath },
Expand Down Expand Up @@ -922,7 +922,7 @@ describe('runWhoami', () => {
});

it('L1866: renders email + name in text mode when the backend supplies them', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const meWithEmail = new Response(
JSON.stringify({ ...sampleMe, email: 'alice@example.com', displayName: 'Alice' }),
Expand All @@ -939,7 +939,7 @@ describe('runWhoami', () => {
});

it('L1866: omits email/name lines when the backend does not return them', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runWhoami(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -952,7 +952,7 @@ describe('runWhoami', () => {
});

it('L1866: passes email through verbatim in JSON mode when present', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const meWithEmail = new Response(JSON.stringify({ ...sampleMe, email: 'alice@example.com' }), {
status: 200,
Expand Down Expand Up @@ -990,7 +990,7 @@ describe('runWhoami', () => {
});

it('emits debug events to stderr when debug is enabled', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runWhoami(
{ profile: 'default', output: 'json', debug: true },
Expand All @@ -1003,7 +1003,7 @@ describe('runWhoami', () => {
});

it('forwards server AUTH_INVALID with exit code 3', async () => {
writeProfile('default', { apiKey: 'sk-bad' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-bad' }, { path: credentialsPath });
const { deps } = makeCapture();
const errorBody = {
error: {
Expand Down Expand Up @@ -1033,7 +1033,7 @@ describe('runWhoami', () => {
...sampleMe,
scopes: ['read:projects', 'read:tests'],
};
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const fetchImpl = makeFetch(
new Response(JSON.stringify(readOnlyMe), {
Expand All @@ -1056,7 +1056,7 @@ describe('runWhoami', () => {
...sampleMe,
scopes: ['read:projects', 'read:tests', 'write:tests', 'run:tests'],
};
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const fetchImpl = makeFetch(
new Response(JSON.stringify(fullMe), {
Expand All @@ -1077,7 +1077,7 @@ describe('runWhoami', () => {
...sampleMe,
scopes: ['read:projects', 'read:tests'],
};
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const fetchImpl = makeFetch(
new Response(JSON.stringify(readOnlyMe), {
Expand All @@ -1099,8 +1099,8 @@ describe('runWhoami', () => {

describe('runLogout', () => {
it('removes the profile and reports success', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
writeProfile('dev', { apiKey: 'sk-dev' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('dev', { apiKey: 'sk-dev' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runLogout(
{ profile: 'default', output: 'text', debug: false },
Expand Down Expand Up @@ -1148,7 +1148,7 @@ describe('createAuthCommand wiring', () => {
});

it('remove deletes the active profile and exits 0', async () => {
writeProfile('default', { apiKey: 'sk-remove' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-remove' }, { path: credentialsPath });
const { deps } = makeCapture();
const auth = createAuthCommand({ ...deps, credentialsPath });
auth.exitOverride();
Expand All @@ -1158,7 +1158,7 @@ describe('createAuthCommand wiring', () => {
});

it('deprecated `whoami` alias emits a deprecation notice pointing at `auth status`', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const auth = createAuthCommand({
...deps,
Expand All @@ -1174,7 +1174,7 @@ describe('createAuthCommand wiring', () => {
});

it('whoami uses injected fetch and exits 0', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { deps } = makeCapture();
const fetchImpl = vi.fn(
async () =>
Expand All @@ -1191,7 +1191,7 @@ describe('createAuthCommand wiring', () => {
});

it('L1802: `status` alias resolves to the whoami action', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { deps } = makeCapture();
const fetchImpl = vi.fn(
async () =>
Expand All @@ -1208,7 +1208,7 @@ describe('createAuthCommand wiring', () => {
});

it('logout removes the profile', async () => {
writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk' }, { path: credentialsPath });
const { deps } = makeCapture();
const auth = createAuthCommand({ ...deps, credentialsPath });
auth.exitOverride();
Expand Down
4 changes: 2 additions & 2 deletions src/commands/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export async function runConfigure(opts: ConfigureOptions, deps: AuthDeps = {}):
);
}

writeProfile(opts.profile, { apiKey, apiUrl }, { path: credentialsPath });
await writeProfile(opts.profile, { apiKey, apiUrl }, { path: credentialsPath });

out.print({ profile: opts.profile, apiUrl, status: 'configured' }, data => {
const d = data as { profile: string; apiUrl: string };
Expand Down Expand Up @@ -276,7 +276,7 @@ export async function runLogout(opts: CommonOptions, deps: AuthDeps = {}): Promi
return;
}

const removed = deleteProfile(opts.profile, { path: credentialsPath });
const removed = await deleteProfile(opts.profile, { path: credentialsPath });
out.print({ profile: opts.profile, status: removed ? 'logged_out' : 'no_credentials' }, data => {
const d = data as { profile: string; status: string };
return d.status === 'logged_out'
Expand Down
16 changes: 8 additions & 8 deletions src/commands/doctor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ beforeEach(() => {

describe('runDoctor — healthy environment', () => {
it('returns an all-passing report and does not throw', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const report = await runDoctor(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -79,7 +79,7 @@ describe('runDoctor — healthy environment', () => {
});

it('never prints the API key anywhere in the report', async () => {
writeProfile('default', { apiKey: 'sk-super-secret-value' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-super-secret-value' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runDoctor(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -90,7 +90,7 @@ describe('runDoctor — healthy environment', () => {
});

it('emits a machine-readable report under --output json without leaking the API key', async () => {
writeProfile('default', { apiKey: 'sk-json-secret-value' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-json-secret-value' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runDoctor(
{ profile: 'default', output: 'json', debug: false },
Expand Down Expand Up @@ -124,7 +124,7 @@ describe('runDoctor — failing checks exit non-zero', () => {
});

it('invalid endpoint URL fails the API endpoint check', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const rejection = await runDoctor(
{ profile: 'default', output: 'text', debug: false, endpointUrl: 'not-a-url' },
Expand All @@ -137,7 +137,7 @@ describe('runDoctor — failing checks exit non-zero', () => {
});

it('rejected API key surfaces as a Connectivity failure', async () => {
writeProfile('default', { apiKey: 'sk-bad' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-bad' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const authError = {
error: { code: 'AUTH_INVALID', message: 'Bad key.', requestId: 'req_x', details: {} },
Expand All @@ -153,7 +153,7 @@ describe('runDoctor — failing checks exit non-zero', () => {
});

it('a non-auth /me error is reported as a Connectivity failure with its code', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const notFound = {
error: { code: 'NOT_FOUND', message: 'nope', requestId: 'req_y', details: {} },
Expand All @@ -167,7 +167,7 @@ describe('runDoctor — failing checks exit non-zero', () => {
});

it('an outdated Node runtime fails the Node.js check', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const rejection = await runDoctor(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -182,7 +182,7 @@ describe('runDoctor — failing checks exit non-zero', () => {

describe('runDoctor — warnings do not fail', () => {
it('missing verify skill is a warning, not a failure', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const report = await runDoctor(
{ profile: 'default', output: 'text', debug: false },
Expand Down
20 changes: 10 additions & 10 deletions src/commands/usage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ describe('runUsage — dry-run', () => {

describe('runUsage — real path without credits (current backend)', () => {
it('returns the /me response and emits a note about missing balance', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const result = await runUsage(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -116,7 +116,7 @@ describe('runUsage — real path without credits (current backend)', () => {
});

it('text output includes identity fields even without credits', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runUsage(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -132,7 +132,7 @@ describe('runUsage — real path without credits (current backend)', () => {
});

it('JSON output passes the raw /me response through (no credits key present)', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runUsage(
{ profile: 'default', output: 'json', debug: false },
Expand All @@ -150,7 +150,7 @@ describe('runUsage — real path without credits (current backend)', () => {

describe('runUsage — real path with credits (future backend)', () => {
it('renders balance block when credits + subPlan are present', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runUsage(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -173,7 +173,7 @@ describe('runUsage — real path with credits (future backend)', () => {
});

it('does NOT emit the missing-balance note when credits are present', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runUsage(
{ profile: 'default', output: 'text', debug: false },
Expand All @@ -189,7 +189,7 @@ describe('runUsage — real path with credits (future backend)', () => {
});

it('emits low-balance warning when credits < creditsPerRun', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const lowBalance: UsageResponse = { ...meWithCredits, credits: 1, creditsPerRun: 2 };
await runUsage(
Expand All @@ -206,7 +206,7 @@ describe('runUsage — real path with credits (future backend)', () => {
});

it('emits free-plan upgrade hint when subPlan is Free', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
const freePlan: UsageResponse = { ...meWithCredits, subPlan: 'Free', credits: 10 };
await runUsage(
Expand All @@ -223,7 +223,7 @@ describe('runUsage — real path with credits (future backend)', () => {
});

it('JSON output passes credits and subPlan through verbatim', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { capture, deps } = makeCapture();
await runUsage(
{ profile: 'default', output: 'json', debug: false },
Expand All @@ -249,7 +249,7 @@ describe('runUsage — error handling', () => {
});

it('forwards server AUTH_INVALID with exit code 3', async () => {
writeProfile('default', { apiKey: 'sk-bad' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-bad' }, { path: credentialsPath });
const { deps } = makeCapture();
const errorBody = {
error: {
Expand All @@ -273,7 +273,7 @@ describe('runUsage — error handling', () => {
});

it('re-maps INSUFFICIENT_CREDITS (rate_limited with credits sub-case) to exit 12', async () => {
writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
await writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath });
const { deps } = makeCapture();
const creditError = {
error: {
Expand Down
Loading
Loading