diff --git a/src/api/endpoints.js b/src/api/endpoints.js index 29cdfbf..43dd94a 100644 --- a/src/api/endpoints.js +++ b/src/api/endpoints.js @@ -229,7 +229,7 @@ export async function getComparison(client, comparisonId) { * Search for comparisons by name * @param {Object} client - API client * @param {string} name - Screenshot name to search for - * @param {Object} filters - Optional filters (branch, limit, offset) + * @param {Object} filters - Optional filters (branch, project, organization, limit, offset) * @returns {Promise} Search results with comparisons and pagination */ export async function searchComparisons(client, name, filters = {}) { @@ -237,10 +237,11 @@ export async function searchComparisons(client, name, filters = {}) { throw new VizzlyError('name is required and must be a non-empty string'); } - let { branch, project, limit = 50, offset = 0 } = filters; + let { branch, project, organization, limit = 50, offset = 0 } = filters; let params = { name, limit: String(limit), offset: String(offset) }; if (branch) params.branch = branch; if (project) params.project = project; + if (organization) params.organization = organization; let endpoint = buildEndpointWithParams('/api/sdk/comparisons/search', params); return client.request(endpoint); diff --git a/src/cli.js b/src/cli.js index c8c26eb..58f5031 100644 --- a/src/cli.js +++ b/src/cli.js @@ -626,6 +626,7 @@ program ) .option('--environment ', 'Filter by environment') .option('-p, --project ', 'Filter by project slug') + .option('--org ', 'Filter by organization slug') .option( '--limit ', 'Maximum results to return (1-250)', @@ -640,7 +641,8 @@ program Examples: $ vizzly builds # List recent builds $ vizzly builds --branch main # Filter by branch - $ vizzly builds --project abc123 # Filter by project + $ vizzly builds --project storybook # Filter by project + $ vizzly builds --project storybook --org my-org # Disambiguate by org $ vizzly builds --status completed # Filter by status $ vizzly builds -b abc123-def456 # Get specific build by ID $ vizzly builds -b abc123 --comparisons # Include comparisons @@ -679,6 +681,7 @@ program ) .option('--offset ', 'Skip first N results', val => parseInt(val, 10), 0) .option('-p, --project ', 'Filter by project slug') + .option('--org ', 'Filter by organization slug') .addHelpText( 'after', ` @@ -687,6 +690,7 @@ Examples: $ vizzly comparisons --id def456 # Get specific comparison by ID $ vizzly comparisons --name "Button" # Search by screenshot name $ vizzly comparisons --name "Login*" # Wildcard search + $ vizzly comparisons --name "Button" --org my-org # Filter by org $ vizzly comparisons --status changed # Only changed comparisons $ vizzly comparisons --json # Output as JSON for scripting ` diff --git a/src/commands/builds.js b/src/commands/builds.js index aa61062..ce3ae3b 100644 --- a/src/commands/builds.js +++ b/src/commands/builds.js @@ -86,6 +86,7 @@ export async function buildsCommand( if (options.status) filters.status = options.status; if (options.environment) filters.environment = options.environment; if (options.project) filters.project = options.project; + if (options.org) filters.organization = options.org; let response = await getBuilds(client, filters); output.stopSpinner(); diff --git a/src/commands/comparisons.js b/src/commands/comparisons.js index 6bef1ea..e145752 100644 --- a/src/commands/comparisons.js +++ b/src/commands/comparisons.js @@ -128,6 +128,7 @@ export async function comparisonsCommand( let filters = { branch: options.branch, project: options.project, + organization: options.org, limit: options.limit || 50, offset: options.offset || 0, }; diff --git a/tests/commands/builds.test.js b/tests/commands/builds.test.js index 680ea73..5b19ac0 100644 --- a/tests/commands/builds.test.js +++ b/tests/commands/builds.test.js @@ -307,5 +307,28 @@ describe('commands/builds', () => { assert.strictEqual(capturedFilters.project, 'proj-123'); }); + + it('passes organization filter to API', async () => { + let output = createMockOutput(); + let capturedFilters = null; + + await buildsCommand( + { project: 'storybook', org: 'my-org' }, + { json: true }, + { + loadConfig: async () => ({ apiKey: 'test-token' }), + createApiClient: () => ({}), + getBuilds: async (_client, filters) => { + capturedFilters = filters; + return { builds: [], pagination: { total: 0, hasMore: false } }; + }, + output, + exit: () => {}, + } + ); + + assert.strictEqual(capturedFilters.project, 'storybook'); + assert.strictEqual(capturedFilters.organization, 'my-org'); + }); }); }); diff --git a/tests/commands/comparisons.test.js b/tests/commands/comparisons.test.js index d3b8926..8c7ccd4 100644 --- a/tests/commands/comparisons.test.js +++ b/tests/commands/comparisons.test.js @@ -254,6 +254,32 @@ describe('commands/comparisons', () => { assert.strictEqual(capturedFilters.project, 'my-project'); }); + it('passes organization filter to search', async () => { + let output = createMockOutput(); + let capturedFilters = null; + + await comparisonsCommand( + { name: 'button-*', project: 'storybook', org: 'my-org' }, + { json: true }, + { + loadConfig: async () => ({ apiKey: 'test-token' }), + createApiClient: () => ({}), + searchComparisons: async (_client, _name, filters) => { + capturedFilters = filters; + return { + comparisons: [], + pagination: { total: 0, hasMore: false }, + }; + }, + output, + exit: () => {}, + } + ); + + assert.strictEqual(capturedFilters.project, 'storybook'); + assert.strictEqual(capturedFilters.organization, 'my-org'); + }); + it('fetches single comparison by ID', async () => { let output = createMockOutput(); let mockComparison = {