Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
41d75ca
feat(cli): add checks list/get commands with typed formatters
MichaelHogers Feb 23, 2026
6e79a23
refactor(cli): reduce formatter code duplication
MichaelHogers Feb 23, 2026
482d32e
refactor(cli): move test fixtures to __fixtures__ directory
MichaelHogers Feb 23, 2026
63174a4
fix(cli): add checks topic to help e2e test expectations
MichaelHogers Feb 23, 2026
7718b6f
fix(cli): fix duplicate error output and status filter including inac…
MichaelHogers Feb 23, 2026
93dbf06
fix(cli): avoid leading whitespace in summary bar when no statuses
MichaelHogers Feb 23, 2026
5f03031
fix(cli): handle empty account gracefully in checks list
MichaelHogers Feb 23, 2026
95db6bb
test(cli): add e2e tests for empty account edge cases
MichaelHogers Feb 23, 2026
00b0459
fix(cli): support --output md for error group detail and align e2e co…
MichaelHogers Feb 23, 2026
f7c6b16
feat(cli): add type breakdown line to checks list summary bar
MichaelHogers Feb 23, 2026
372cbe2
feat(cli): use server-side checkType and search filters in checks list
MichaelHogers Feb 24, 2026
771423e
fix(cli): update e2e test expectation for checks output format
MichaelHogers Feb 25, 2026
bd84adc
test(cli): enhance e2e tests for checks list output and limit functio…
MichaelHogers Feb 25, 2026
2aadd76
refactor(cli): centralize output flag for checks commands
MichaelHogers Feb 25, 2026
81fb682
fix(cli): move shared flags out of commands directory
MichaelHogers Feb 25, 2026
3c66ad8
Merge branch 'main' into michael/tim-9-10-11-checks-cli
MichaelHogers Feb 25, 2026
60856d2
fix(cli): use oclif globPatterns to exclude flags from command discovery
MichaelHogers Feb 25, 2026
e25c652
fix(cli): narrow oclif glob exclusion to checks/flags only
MichaelHogers Feb 25, 2026
ed903bf
refactor(cli): prefix shared flags file with underscore convention
MichaelHogers Feb 25, 2026
20d75e3
fix(cli): remove TS extensions from oclif globPatterns
MichaelHogers Feb 25, 2026
763fae8
refactor(cli): move shared flags to helpers directory
MichaelHogers Feb 25, 2026
80ecd78
test(cli): remove --status flag e2e test
MichaelHogers Feb 25, 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
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ jobs:
CHECKLY_ACCOUNT_NAME: ${{ secrets.E2E_CHECKLY_ACCOUNT_NAME }}
CHECKLY_ACCOUNT_ID: ${{ secrets.E2E_CHECKLY_ACCOUNT_ID }}
CHECKLY_API_KEY: ${{ secrets.E2E_CHECKLY_API_KEY }}
CHECKLY_EMPTY_ACCOUNT_ID: ${{ secrets.E2E_EMPTY_CHECKLY_ACCOUNT_ID }}
CHECKLY_EMPTY_API_KEY: ${{ secrets.E2E_EMPTY_CHECKLY_API_KEY }}
- name: Save LLM rules as an artifact
uses: actions/upload-artifact@v4
with:
Expand Down
6 changes: 6 additions & 0 deletions packages/cli/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ Since the E2E tests rely on test accounts in Checkly, some configuration is need

To run the E2E tests locally, create a file `local.js` in [./config](./config). This configuration file should override all of the options from [./config/default.js](./config/default.js).

### Empty account tests (optional)

Some tests verify edge-case behavior against an account with no checks. These are skipped automatically when credentials aren't configured.

To run them locally, add `emptyApiKey` and `emptyAccountId` to your `config/local.js`, or set `CHECKLY_EMPTY_API_KEY` and `CHECKLY_EMPTY_ACCOUNT_ID` in your environment. In CI, these are provided via GitHub secrets.

61 changes: 61 additions & 0 deletions packages/cli/e2e/__tests__/checks-empty-account.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import config from 'config'
import { describe, it, expect } from 'vitest'

import { runChecklyCli } from '../run-checkly'

const apiKey: string | undefined = config.get('emptyApiKey')
const accountId: string | undefined = config.get('emptyAccountId')

describe.skipIf(!apiKey || !accountId)('checks commands on empty account', () => {
it('should show "No checks found." for checks list', async () => {
const result = await runChecklyCli({
args: ['checks', 'list'],
apiKey,
accountId,
})
expect(result.status).toBe(0)
expect(result.stdout).toContain('No checks found.')
})

it('should return empty JSON array for checks list --output json', async () => {
const result = await runChecklyCli({
args: ['checks', 'list', '--output', 'json'],
apiKey,
accountId,
})
expect(result.status).toBe(0)
const parsed = JSON.parse(result.stdout)
expect(parsed.data).toEqual([])
expect(parsed.pagination.total).toBe(0)
})

it('should show "No checks found." for checks list --output md', async () => {
const result = await runChecklyCli({
args: ['checks', 'list', '--output', 'md'],
apiKey,
accountId,
})
expect(result.status).toBe(0)
expect(result.stdout).toContain('No checks found.')
})

it('should handle --search filter gracefully on empty account', async () => {
const result = await runChecklyCli({
args: ['checks', 'list', '--search', 'anything'],
apiKey,
accountId,
})
expect(result.status).toBe(0)
expect(result.stdout).toContain('No checks matching')
})

it('should fail gracefully for checks get on empty account', async () => {
const result = await runChecklyCli({
args: ['checks', 'get', '00000000-0000-0000-0000-000000000000'],
apiKey,
accountId,
})
expect(result.status).toBe(1)
expect(result.stdout).toContain('Failed to get check details')
})
})
60 changes: 60 additions & 0 deletions packages/cli/e2e/__tests__/checks-get.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import config from 'config'
import { describe, it, expect, beforeAll } from 'vitest'

import { runChecklyCli } from '../run-checkly'

describe('checkly checks get', () => {
let checkId: string

beforeAll(async () => {
const result = await runChecklyCli({
args: ['checks', 'list', '--output', 'json', '--limit', '1'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).toBe(0)
const parsed = JSON.parse(result.stdout)
expect(parsed.data.length).toBeGreaterThan(0)
checkId = parsed.data[0].id
})

it('should get check detail with default output', async () => {
const result = await runChecklyCli({
args: ['checks', 'get', checkId],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).toBe(0)
expect(result.stdout).toBeTruthy()
})

it('should output valid JSON with --output json', async () => {
const result = await runChecklyCli({
args: ['checks', 'get', checkId, '--output', 'json'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).toBe(0)
const parsed = JSON.parse(result.stdout)
expect(parsed.check.id).toBe(checkId)
})

it('should output markdown with --output md', async () => {
const result = await runChecklyCli({
args: ['checks', 'get', checkId, '--output', 'md'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).toBe(0)
expect(result.stdout).toContain('| Field | Value |')
})

it('should fail for nonexistent check ID', async () => {
const result = await runChecklyCli({
args: ['checks', 'get', 'nonexistent-check-id-00000'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).not.toBe(0)
})
})
58 changes: 58 additions & 0 deletions packages/cli/e2e/__tests__/checks-list.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import config from 'config'
import { describe, it, expect } from 'vitest'

import { runChecklyCli } from '../run-checkly'

describe('checkly checks list', () => {
it('should list checks with default output', async () => {
const result = await runChecklyCli({
args: ['checks', 'list'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).toBe(0)
expect(result.stdout).toBeTruthy()
})

it('should output valid JSON with --output json', async () => {
const result = await runChecklyCli({
args: ['checks', 'list', '--output', 'json'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).toBe(0)
const parsed = JSON.parse(result.stdout)
expect(parsed).toHaveProperty('data')
expect(Array.isArray(parsed.data)).toBe(true)
})

it('should output markdown with --output md', async () => {
const result = await runChecklyCli({
args: ['checks', 'list', '--output', 'md'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(result.status).toBe(0)
expect(result.stdout).toContain('| Name | Type | Status |')
})

it('should respect --limit flag', async () => {
const allResult = await runChecklyCli({
args: ['checks', 'list', '--output', 'json'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(allResult.status).toBe(0)
const allParsed = JSON.parse(allResult.stdout)
expect(allParsed.data.length).toBeGreaterThan(1)

const limitedResult = await runChecklyCli({
args: ['checks', 'list', '--output', 'json', '--limit', '1'],
apiKey: config.get('apiKey'),
accountId: config.get('accountId'),
})
expect(limitedResult.status).toBe(0)
const limitedParsed = JSON.parse(limitedResult.stdout)
expect(limitedParsed.data).toHaveLength(1)
})
})
1 change: 1 addition & 0 deletions packages/cli/e2e/__tests__/help.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe('help', () => {
trigger Trigger your existing checks on Checkly.`)

expect(stdout).toContain(`ADDITIONAL COMMANDS
checks List and inspect checks in your Checkly account.
destroy Destroy your project with all its related resources.
env Manage Checkly environment variables.
help Display help for checkly.
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/e2e/config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ config.apiKey = process.env.CHECKLY_API_KEY
config.accountId = process.env.CHECKLY_ACCOUNT_ID
config.baseURL = process.env.CHECKLY_BASE_URL || 'https://api.checklyhq.com'

// Optional: empty account for edge-case testing (no checks, no groups, etc.)
config.emptyApiKey = process.env.CHECKLY_EMPTY_API_KEY
config.emptyAccountId = process.env.CHECKLY_EMPTY_ACCOUNT_ID

module.exports = config
3 changes: 3 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
"message": "<%= config.name %> update available from <%= chalk.greenBright(config.version) %> to <%= chalk.greenBright(latest) %>. To update, run `npm install -D checkly@latest`"
},
"topics": {
"checks": {
"description": "List and inspect checks in your Checkly account."
},
"env": {
"description": "Manage Checkly environment variables."
},
Expand Down
Loading
Loading