Skip to content

Commit 3ed517a

Browse files
committed
feat: add command compliance-check list
1 parent e51cd4d commit 3ed517a

File tree

3 files changed

+146
-5
lines changed

3 files changed

+146
-5
lines changed

src/__tests__/cli-commands.test.ts

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* eslint-env jest */
22

3-
import { getVersion, runDoctor, addProjectWithGithubOrgs, printChecklists } from '../cli-commands.js'
3+
import { getVersion, runDoctor, addProjectWithGithubOrgs, printChecklists, printChecks } from '../cli-commands.js'
44
import { getPackageJson } from '../utils.js'
5-
import { APIHealthResponse, APIProjectDetails, APIGithubOrgDetails, APIErrorResponse, APIChecklistItem } from '../types.js'
6-
import { mockApiHealthResponse, mockAPIProjectResponse, mockAPIGithubOrgResponse, mockAPIChecklistResponse } from './fixtures.js'
5+
import { APIHealthResponse, APIProjectDetails, APIGithubOrgDetails, APIErrorResponse, APIChecklistItem, APICheckItem } from '../types.js'
6+
import { mockApiHealthResponse, mockAPIProjectResponse, mockAPIGithubOrgResponse, mockAPIChecklistResponse, mockAPICheckResponse } from './fixtures.js'
77
import nock from 'nock'
88

99
const pkg = getPackageJson()
@@ -278,4 +278,106 @@ describe('CLI Commands', () => {
278278
expect(result.messages[0]).toBe('No compliance checklists found')
279279
})
280280
})
281+
282+
describe('printChecks', () => {
283+
let mockChecks: APICheckItem[]
284+
285+
beforeEach(() => {
286+
nock.cleanAll()
287+
mockChecks = [...mockAPICheckResponse]
288+
})
289+
290+
it('should retrieve and format check items successfully', async () => {
291+
// Mock API call
292+
nock('http://localhost:3000')
293+
.get('/api/v1/compliance-check')
294+
.reply(200, mockChecks)
295+
296+
// Execute the function
297+
const result = await printChecks()
298+
299+
// Verify the result
300+
expect(result.success).toBe(true)
301+
expect(result.messages[0]).toBe('Compliance checks available:')
302+
expect(result.messages[1]).toContain(mockChecks[0].code_name)
303+
expect(result.messages[1]).toContain(mockChecks[0].description)
304+
expect(result.messages[1]).toContain(mockChecks[0].details_url)
305+
expect(result.messages).toHaveLength(2) // Header + 1 check item
306+
expect(nock.isDone()).toBe(true) // Verify all mocked endpoints were called
307+
})
308+
309+
it('should handle multiple check items', async () => {
310+
// Add a second check item
311+
const secondCheck = {
312+
...mockChecks[0],
313+
id: 456,
314+
title: 'Second Check',
315+
code_name: 'secondCheck',
316+
description: 'Another check description',
317+
details_url: 'https://openpathfinder.com/docs/checks/secondCheck'
318+
}
319+
mockChecks.push(secondCheck)
320+
321+
// Mock API call
322+
nock('http://localhost:3000')
323+
.get('/api/v1/compliance-check')
324+
.reply(200, mockChecks)
325+
326+
// Execute the function
327+
const result = await printChecks()
328+
329+
// Verify the result
330+
expect(result.success).toBe(true)
331+
expect(result.messages[0]).toBe('Compliance checks available:')
332+
expect(result.messages[1]).toContain(mockChecks[0].code_name)
333+
expect(result.messages[2]).toContain(mockChecks[1].code_name)
334+
expect(result.messages).toHaveLength(3) // Header + 2 check items
335+
})
336+
337+
it('should handle API errors gracefully', async () => {
338+
// Mock API error
339+
nock('http://localhost:3000')
340+
.get('/api/v1/compliance-check')
341+
.reply(500, { errors: [{ message: 'Internal server error' }] } as APIErrorResponse)
342+
343+
// Execute the function
344+
const result = await printChecks()
345+
346+
// Verify the result
347+
expect(result.success).toBe(false)
348+
expect(result.messages[0]).toContain('❌ Failed to retrieve compliance check items')
349+
expect(result.messages).toHaveLength(1)
350+
})
351+
352+
it('should handle network errors gracefully', async () => {
353+
// Mock network error
354+
nock('http://localhost:3000')
355+
.get('/api/v1/compliance-check')
356+
.replyWithError('Network error')
357+
358+
// Execute the function
359+
const result = await printChecks()
360+
361+
// Verify the result
362+
expect(result.success).toBe(false)
363+
expect(result.messages[0]).toContain('❌ Failed to retrieve compliance check items')
364+
expect(result.messages[0]).toContain('Network error')
365+
expect(result.messages).toHaveLength(1)
366+
})
367+
368+
it('should handle empty check response', async () => {
369+
// Mock empty response
370+
nock('http://localhost:3000')
371+
.get('/api/v1/compliance-check')
372+
.reply(200, [])
373+
374+
// Execute the function
375+
const result = await printChecks()
376+
377+
// Verify the result
378+
expect(result.success).toBe(true)
379+
expect(result.messages).toHaveLength(1) // Only the header message
380+
expect(result.messages[0]).toBe('No compliance checks found')
381+
})
382+
})
281383
})

src/cli-commands.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CommandResult } from './types.js'
22
import { isApiAvailable, isApiCompatible, getPackageJson } from './utils.js'
3-
import { getAPIDetails, createProject, addGithubOrgToProject, getAllChecklistItems } from './api-client.js'
3+
import { getAPIDetails, createProject, addGithubOrgToProject, getAllChecklistItems, getAllChecks } from './api-client.js'
44

55
const pkg = getPackageJson()
66

@@ -83,3 +83,30 @@ export const printChecklists = async (): Promise<CommandResult> => {
8383
success
8484
}
8585
}
86+
87+
export const printChecks = async (): Promise<CommandResult> => {
88+
const messages: string[] = []
89+
let success = true
90+
try {
91+
const checks = await getAllChecks()
92+
if (checks.length === 0) {
93+
messages.push('No compliance checks found')
94+
return {
95+
messages,
96+
success
97+
}
98+
}
99+
messages.push('Compliance checks available:')
100+
checks.forEach((check) => {
101+
messages.push(`- ${check.code_name}: ${check.description}. ${check.details_url}`)
102+
})
103+
} catch (error) {
104+
messages.push(`❌ Failed to retrieve compliance check items: ${error instanceof Error ? error.message : 'Unknown error'}`)
105+
success = false
106+
}
107+
108+
return {
109+
messages,
110+
success
111+
}
112+
}

src/index.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Command } from 'commander'
44
// @ts-ignore
55
import { stringToArray } from '@ulisesgascon/string-to-array'
66
import { handleCommandResult } from './utils.js'
7-
import { getVersion, runDoctor, addProjectWithGithubOrgs, printChecklists } from './cli-commands.js'
7+
import { getVersion, runDoctor, addProjectWithGithubOrgs, printChecklists, printChecks } from './cli-commands.js'
88

99
const program = new Command()
1010

@@ -35,6 +35,18 @@ checklist
3535
handleCommandResult(result)
3636
})
3737

38+
const check = program
39+
.command('compliance-check')
40+
.description('Compliance check management')
41+
42+
check
43+
.command('list')
44+
.description('Print all available compliance checks')
45+
.action(async () => {
46+
const result = await printChecks()
47+
handleCommandResult(result)
48+
})
49+
3850
const project = program
3951
.command('project')
4052
.description('Project management')

0 commit comments

Comments
 (0)