Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0a98264
feat(cli): add manifest module for reading, writing, validating insta…
sarahdayan May 21, 2026
6add482
chore: trigger ci
sarahdayan May 21, 2026
8eea187
test(cli): drop envelope apiVersion assertions from manifest tests
sarahdayan May 26, 2026
6efa32b
refactor(cli): make manifest framework field optional
sarahdayan May 26, 2026
07409e8
refactor(cli): drop manifest apiVersion field
sarahdayan May 28, 2026
b33a7e2
fix(cli): turn writeManifest IO errors into a structured envelope; re…
sarahdayan May 28, 2026
4438ad7
feat(cli): add init command for scaffolding manifest, client, and pro…
sarahdayan May 28, 2026
f186f72
fix(cli): address review findings on init scaffolding and run wiring
sarahdayan May 28, 2026
e94b33a
fix(cli): drop indexName from generated provider
sarahdayan May 28, 2026
e8b8a37
fix(cli): address second round of init review findings
sarahdayan May 28, 2026
a4db9e8
Merge branch 'master' into feat/init-command
sarahdayan Jun 1, 2026
63acb94
fix(cli): roll back partial init state on scaffold failure
sarahdayan Jun 1, 2026
92e73e6
fix(cli): validate libPath, fix Windows spawn, treat empty prompt as …
sarahdayan Jun 1, 2026
4049db5
fix(cli): drop shell:true from spawn, append .cmd on Windows for shim…
sarahdayan Jun 1, 2026
7141222
fix(cli): validate componentsPath, pin prompts version
sarahdayan Jun 1, 2026
d22bb02
refactor(cli): move HandledFailure into its own module to break circu…
sarahdayan Jun 1, 2026
7ac6a56
feat(cli): add introspect command for retrieving index facets and sea…
sarahdayan May 22, 2026
e66b591
fix(cli): propagate introspect's exit code via HandledFailure
sarahdayan May 26, 2026
dd591a2
test(cli): drop apiVersion assertions from introspect tests
sarahdayan May 26, 2026
4a9a89f
chore(cli): drop MANIFEST_API_VERSION from introspect tests
sarahdayan May 28, 2026
aff3e3d
feat(cli): distinguish credentials_invalid from other Algolia errors …
sarahdayan May 28, 2026
8a516c9
chore(cli): exclude instantsearch-cli from legacy algoliasearch v4 CI
sarahdayan Jun 1, 2026
708510b
fix(cli): require both credential flags when either is passed in intr…
sarahdayan Jun 1, 2026
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
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const config = {
'<rootDir>/packages/react-instantsearch-nextjs/__tests__',
'/__utils__/',
algoliaSearchMajor !== '5' && '<rootDir>/packages/algolia-experiences',
algoliaSearchMajor !== '5' && '<rootDir>/packages/instantsearch-cli',
].filter((x) => x !== false),
watchPathIgnorePatterns: [
'<rootDir>/packages/*/cjs',
Expand Down
23 changes: 23 additions & 0 deletions packages/instantsearch-cli/__tests__/__utils__/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,26 @@ export async function runCapturing(

return { exitCode, stdout: stdout.join(''), stderr: stderr.join('') };
}

type CapturedIO = {
stdout: string[];
stderr: string[];
io: { stdout: (chunk: string) => void; stderr: (chunk: string) => void };
};

export function captureIO(): CapturedIO {
const stdout: string[] = [];
const stderr: string[] = [];
return {
stdout,
stderr,
io: {
stdout: (chunk: string) => stdout.push(chunk),
stderr: (chunk: string) => stderr.push(chunk),
},
};
}

export function readEnvelope(stdout: string[]): Record<string, unknown> {
return JSON.parse(stdout.join(''));
}
6 changes: 3 additions & 3 deletions packages/instantsearch-cli/__tests__/global-options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('global options', () => {
describe('--json implies --yes', () => {
it('sets yes=true when --json is passed', async () => {
const program = createProgram(silentIO);
await program.parseAsync(['init', '--json'], { from: 'user' });
await program.parseAsync(['add', '--json'], { from: 'user' });

expect(program.opts()).toMatchObject({ json: true, yes: true });
});
Expand All @@ -18,14 +18,14 @@ describe('global options', () => {
describe('--yes', () => {
it('is a standalone global flag (yes=true, json=false)', async () => {
const program = createProgram(silentIO);
await program.parseAsync(['init', '--yes'], { from: 'user' });
await program.parseAsync(['add', '--yes'], { from: 'user' });

expect(program.opts()).toMatchObject({ json: false, yes: true });
});

it('defaults to false when neither --yes nor --json is passed', async () => {
const program = createProgram(silentIO);
await program.parseAsync(['init'], { from: 'user' });
await program.parseAsync(['add'], { from: 'user' });

expect(program.opts()).toMatchObject({ json: false, yes: false });
});
Expand Down
21 changes: 9 additions & 12 deletions packages/instantsearch-cli/__tests__/human-output.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { runCapturing } from './__utils__/helpers';

describe.each(['init', 'add', 'introspect'])(
'%s (no --json)',
(command) => {
it('emits human-readable output, not a JSON envelope', async () => {
const { exitCode, stdout, stderr } = await runCapturing([command]);
describe('add (no --json)', () => {
it('emits human-readable output, not a JSON envelope', async () => {
const { exitCode, stdout, stderr } = await runCapturing(['add']);

expect(exitCode).toBe(0);
expect(stderr).toBe('');
expect(stdout).toContain(command);
expect(stdout.trimStart().startsWith('{')).toBe(false);
});
}
);
expect(exitCode).toBe(0);
expect(stderr).toBe('');
expect(stdout).toContain('add');
expect(stdout.trimStart().startsWith('{')).toBe(false);
});
});
47 changes: 47 additions & 0 deletions packages/instantsearch-cli/__tests__/init-exit-code.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import path from 'path';

import { runCapturing } from './__utils__/helpers';

const FIXTURES_ROOT = path.join(__dirname, 'fixtures', 'detector');

describe('init exit code', () => {
it('returns a non-zero process exit code when runInit fails', async () => {
const originalCwd = process.cwd();
process.chdir(path.join(FIXTURES_ROOT, 'vanilla'));
try {
const { exitCode } = await runCapturing([
'init',
'--json',
'--app-id',
'X',
'--search-api-key',
'Y',
]);

expect(exitCode).not.toBe(0);
} finally {
process.chdir(originalCwd);
}
});

it('surfaces the human-mode failure message on stderr', async () => {
const originalCwd = process.cwd();
process.chdir(path.join(FIXTURES_ROOT, 'vanilla'));
try {
const { exitCode, stdout, stderr } = await runCapturing([
'init',
'--yes',
'--app-id',
'X',
'--search-api-key',
'Y',
]);

expect(exitCode).not.toBe(0);
expect(stdout).toBe('');
expect(stderr).toMatch(/react/i);
} finally {
process.chdir(originalCwd);
}
});
});
Loading
Loading