Skip to content
Draft
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
123 changes: 123 additions & 0 deletions packages/cli/src/constructs/__tests__/api-check.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { describe, it, expect, beforeEach, afterAll } from 'vitest'

import { ApiCheck, CheckGroup, Request } from '../index'
import { Project, Session } from '../project'
import { Diagnostics } from '../diagnostics'

const runtimes = {
'2022.10': { name: '2022.10', default: false, stage: 'CURRENT', description: 'Main updates are Playwright 1.28.0, Node.js 16.x and Typescript support. We are also dropping support for Puppeteer', dependencies: { '@playwright/test': '1.28.0', '@opentelemetry/api': '1.0.4', '@opentelemetry/sdk-trace-base': '1.0.1', '@faker-js/faker': '5.5.3', aws4: '1.11.0', axios: '0.27.2', btoa: '1.2.1', chai: '4.3.7', 'chai-string': '1.5.0', 'crypto-js': '4.1.1', expect: '29.3.1', 'form-data': '4.0.0', jsonwebtoken: '8.5.1', lodash: '4.17.21', mocha: '10.1.0', moment: '2.29.2', node: '16.x', otpauth: '9.0.2', playwright: '1.28.0', typescript: '4.8.4', uuid: '9.0.0' } },
Expand Down Expand Up @@ -211,4 +212,126 @@ describe('ApiCheck', () => {
expect(payload.retryStrategy?.onlyOn).toEqual('NETWORK_ERROR')
})
})

describe('validation', () => {
beforeEach(() => {
Session.project = new Project('validation-test-project', {
name: 'Validation Test Project',
repoUrl: 'https://github.com/checkly/checkly-cli',
})
})

it('should validate URL length', async () => {
const longUrl = 'https://example.com/' + 'a'.repeat(2030)
const apiCheck = new ApiCheck('test-api', {
name: 'Test API',
request: {
url: longUrl,
method: 'GET'
}
})

const diagnostics = new Diagnostics()
await apiCheck.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('URL length must not exceed 2048 characters')
})
])
)
})

it('should validate HTTP method', async () => {
const apiCheck = new ApiCheck('test-api', {
name: 'Test API',
request: {
url: 'https://example.com',
method: 'INVALID' as any
}
})

const diagnostics = new Diagnostics()
await apiCheck.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('Invalid HTTP method')
})
])
)
})

it('should validate response times', async () => {
const apiCheck = new ApiCheck('test-api', {
name: 'Test API',
request: {
url: 'https://example.com',
method: 'GET'
},
degradedResponseTime: -100,
maxResponseTime: 40000
})

const diagnostics = new Diagnostics()
await apiCheck.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('must be 0 or greater')
}),
expect.objectContaining({
message: expect.stringContaining('must be 30000 or lower')
})
])
)
})

it('should validate IP family', async () => {
const apiCheck = new ApiCheck('test-api', {
name: 'Test API',
request: {
url: 'https://example.com',
method: 'GET',
ipFamily: 'IPv5' as any
}
})

const diagnostics = new Diagnostics()
await apiCheck.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('Invalid IP family')
})
])
)
})

it('should validate body type', async () => {
const apiCheck = new ApiCheck('test-api', {
name: 'Test API',
request: {
url: 'https://example.com',
method: 'POST',
bodyType: 'INVALID' as any
}
})

const diagnostics = new Diagnostics()
await apiCheck.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('Invalid body type')
})
])
)
})
})
})
70 changes: 70 additions & 0 deletions packages/cli/src/constructs/__tests__/browser-check.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { describe, it, expect, beforeEach, afterAll } from 'vitest'

import { BrowserCheck, CheckGroup } from '../index'
import { Project, Session } from '../project'
import { Diagnostics } from '../diagnostics'

const runtimes = {
'2022.10': { name: '2022.10', default: false, stage: 'CURRENT', description: 'Main updates are Playwright 1.28.0, Node.js 16.x and Typescript support. We are also dropping support for Puppeteer', dependencies: { '@playwright/test': '1.28.0', '@opentelemetry/api': '1.0.4', '@opentelemetry/sdk-trace-base': '1.0.1', '@faker-js/faker': '5.5.3', aws4: '1.11.0', axios: '0.27.2', btoa: '1.2.1', chai: '4.3.7', 'chai-string': '1.5.0', 'crypto-js': '4.1.1', expect: '29.3.1', 'form-data': '4.0.0', jsonwebtoken: '8.5.1', lodash: '4.17.21', mocha: '10.1.0', moment: '2.29.2', node: '16.x', otpauth: '9.0.2', playwright: '1.28.0', typescript: '4.8.4', uuid: '9.0.0' } },
Expand Down Expand Up @@ -288,4 +289,73 @@ describe('BrowserCheck', () => {
expect(browserCheck).toMatchObject(custom)
})
})

describe('validation', () => {
beforeEach(() => {
Session.project = new Project('validation-test-project', {
name: 'Validation Test Project',
repoUrl: 'https://github.com/checkly/checkly-cli',
})
})

it('should validate SSL check domain format', async () => {
const browserCheck = new BrowserCheck('test-browser', {
name: 'Test Browser',
code: { content: 'test' },
sslCheckDomain: 'invalid domain'
})

const diagnostics = new Diagnostics()
await browserCheck.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('Invalid FQDN')
})
])
)
})

it('should accept valid SSL check domain', async () => {
const browserCheck = new BrowserCheck('test-browser', {
name: 'Test Browser',
code: { content: 'test' },
sslCheckDomain: 'app.checklyhq.com'
})

const diagnostics = new Diagnostics()
await browserCheck.validate(diagnostics)

expect(diagnostics.isFatal()).toBe(false)
})

it('should validate various invalid SSL check domains', async () => {
const invalidDomains = [
'domain with spaces.com', // Contains spaces
'', // Empty string
'example..com', // Double dots
'-sub.example.com' // Starts with hyphen
]

for (const [i, domain] of invalidDomains.entries()) {
const browserCheck = new BrowserCheck(`test-browser-invalid-${i}`, {
name: 'Test Browser',
code: { content: 'test' },
sslCheckDomain: domain
})

const diagnostics = new Diagnostics()
await browserCheck.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('Invalid FQDN')
})
])
)
}
})
})
})
78 changes: 78 additions & 0 deletions packages/cli/src/constructs/__tests__/email-alert-channel.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { describe, it, expect, beforeEach } from 'vitest'

import { EmailAlertChannel } from '../index'
import { Project, Session } from '../project'
import { Diagnostics } from '../diagnostics'

describe('EmailAlertChannel', () => {
describe('validation', () => {
beforeEach(() => {
Session.project = new Project('validation-test-project', {
name: 'Validation Test Project',
repoUrl: 'https://github.com/checkly/checkly-cli',
})
})

it('should validate email address format', async () => {
const emailChannel = new EmailAlertChannel('test-email', {
address: 'invalid-email'
})

const diagnostics = new Diagnostics()
await emailChannel.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('Must contain @ symbol')
})
])
)
})

it('should validate various invalid email formats', async () => {
const invalidEmails = [
'plainaddress',
'',
'no-at-symbol.com'
]

for (const [i, email] of invalidEmails.entries()) {
const emailChannel = new EmailAlertChannel(`test-email-invalid-${i}`, {
address: email
})

const diagnostics = new Diagnostics()
await emailChannel.validate(diagnostics)

expect(diagnostics.observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
message: expect.stringContaining('Must contain @ symbol')
})
])
)
}
})

it('should accept valid email addresses', async () => {
const validEmails = [
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]'
]

for (const email of validEmails) {
const emailChannel = new EmailAlertChannel(`test-email-${email.replace(/[^a-zA-Z0-9]/g, '-')}`, {
address: email
})

const diagnostics = new Diagnostics()
await emailChannel.validate(diagnostics)

expect(diagnostics.isFatal()).toBe(false)
}
})
})
})
Loading
Loading