Skip to content

Commit

Permalink
chore: use JSON for test snapshots for easier comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
eoinsha committed Dec 1, 2023
1 parent d0c2f59 commit 962bf72
Show file tree
Hide file tree
Showing 15 changed files with 19,102 additions and 12,552 deletions.
11 changes: 6 additions & 5 deletions CONTRIBUTING.md
Expand Up @@ -30,20 +30,21 @@ The following is a checklist of steps that must be followed to add support for a
a. Once you have added the new resource to `serverless-test-project`, compile the project to generate the CloudFormation JSON by running `serverless package`
b. Copy `serverless-test-project/.serverless/cloudformation-template-update-stack.json` to [serverless-plugin/tests/resources/cloudformation-template-stack.json](serverless-plugin/tests/resources/cloudformation-template-stack.json`).
c. Manually edit `serverless-plugin/tests/resources/cloudformation-template-stack.json` to remove any `AWS::CloudWatch::Dashboard` and `AWS::CloudWatch::Alarm` resources. This is important since we need the unit tests to generate these resources, so they cannot exist in the source template
4. Add alarms:
4. Snapshot tests are used to detect breaking or problematic changes in generated templates. They are automatically run with `npm test` but can be run in isolation with `npm run test:snapshots`. Snapshots can be regenerated (if you really are sure that they should be updated!) with `npm run test:snapshots:generate`
5. Add alarms:
a. Create a new `alarms-<service>.js` module in [serverless-plugin](./serverless-plugin/). One of the existing `alarms-<service>.js` modules may be used as a template.
b. Update [serverless-plugin/alarms.js](./serverless-plugin/alarms.js) to wire in the new `alarms-<service>` module.
c. Create a unit test for the new alarm module and update [alarms.test.js](./serverless-plugin/tests/alarms.test.js) to add coverage for the new resource. This will use the CloudFormation template you updated above.
5. Add dashboard widgets:
6. Add dashboard widgets:
a. Add support for the new dashboard widgets in [serverless-plugin/dashboard.js](./serverless-plugin/dashboard.js)
b. Update [dashboard.test.js](./serverless-plugin/tests/dashboard.test.js) to add coverage for the new resource
6. Update SLIC Watch configuration support:
7. Update SLIC Watch configuration support:
a. Add default values for your resource's alarm and dashboard configuration in [default-config.js](./serverless-plugin/default-config.js).
b. Update the JSON schema for SLIC Watch configuration ([config-schema.js](./serverless-plugin/config-schema.js)). Here, you can define the supported alarm metrics and widgets.
7. Manually (or using automation) integration test the new feature
8. Manually (or using automation) integration test the new feature
a. The method will vary based on the resource type, but the idea is to trigger alarms and generate metrics to validate that both alarms and dashboards are working as expected. You can use the resource you added to `serverless-test-project` for this.
b. For example integration tests, see the Python-based notebooks in [testing](./testing).
8. Update the README.md:
9. Update the README.md:
a. Include the updated default configuration
b. Add the new resource type to the list of features
c. Update the dashboard screenshots to include your new widget with metrics shown (using Dark Mode in the CloudWatch Console!)
Expand Down
Expand Up @@ -2,6 +2,8 @@ import { test } from 'tap'
import type { Template } from 'cloudform'
import { handler } from 'cf-macro-slic-watch/index'

import { setUpSnapshotDefaults } from 'test-utils/snapshot-utils'

import generalEuStack from './fixtures/CdkGeneralStackTest-Europe.template.json'
import generalUsStack from './fixtures/CdkGeneralStackTest-US.template.json'
import ecsStack from './fixtures/CdkECSStackTest-Europe.template.json'
Expand All @@ -13,8 +15,8 @@ const stacks = {
ecsStack,
stepFunctionStack
}

test('cdk-test-project snapshot', async (t) => {
setUpSnapshotDefaults(t)
for (const [name, stack] of Object.entries(stacks)) {
const response = await handler({ fragment: stack as Template, requestId: 'snapshot-test' })
t.notOk(response.errorMessage)
Expand Down
7 changes: 4 additions & 3 deletions cf-macro/index.ts
Expand Up @@ -6,7 +6,8 @@ import { setLogger } from 'slic-watch-core/logging'
import { type SlicWatchConfig, resolveSlicWatchConfig } from 'slic-watch-core/inputs/general-config'
import { type Template } from 'cloudform-types'

const logger = pino({ name: 'macroHandler' })
const logger = pino({ name: 'macroHandler', level: process.env.DEBUG_LEVEL ?? 'DEBUG' })

setLogger(logger)

interface Event {
Expand All @@ -29,7 +30,7 @@ export async function handler (event: Event): Promise<MacroResponse> {
let status = 'success'
let errorMessage: string | undefined

logger.info({ event })
logger.debug({ event })
const transformedTemplate = event.fragment
let outputFragment: Template | undefined
try {
Expand Down Expand Up @@ -58,7 +59,7 @@ export async function handler (event: Event): Promise<MacroResponse> {
status = 'fail'
}

logger.info({ outputFragment: transformedTemplate })
logger.debug({ outputFragment: transformedTemplate })

return {
status,
Expand Down
5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -24,8 +24,9 @@
"build": "npm run build -w core && npm run build -w cf-macro && npm run build -w serverless-plugin",
"lint": "eslint .",
"lintfix": "eslint --cache --fix .",
"test:packages": "tap --include='**/tests/**/*.ts' --coverage-report=lcovonly --allow-incomplete-coverage",
"test:snapshots": "tap --include='**/tests/**/*snapshot.test.ts' --coverage-report=lcovonly --allow-incomplete-coverage",
"test:packages": "DEBUG_LEVEL=info tap --include='**/tests/**/*.ts' --coverage-report=lcovonly --allow-incomplete-coverage",
"test:snapshots": "DEBUG_LEVEL=info tap --include='**/tests/**/*snapshot.test.ts' --coverage-report=lcovonly --allow-incomplete-coverage",
"test:snapshots:generate": "TAP_SNAPSHOT=1 npm run test:snapshots",
"test:report": "tap report html",
"test": "npm run lint && npm run test:packages",
"prepare": "test ! -d '.git' || is-ci || husky install",
Expand Down
8 changes: 3 additions & 5 deletions sam-test-project/template.yaml
Expand Up @@ -4,16 +4,14 @@ Description: >-
Transform:
- AWS::Serverless-2016-10-31
- SlicWatch-v3

Metadata:
slicWatch:
enabled: true
alarmActionsConfig: {
alarmActions: [!Ref MonitoringTopic],
okActions: [!Ref MonitoringTopic],
alarmActionsConfig:
alarmActions: [!Ref MonitoringTopic]
okActions: [!Ref MonitoringTopic]
actionsEnabled: true
}
alarms:
Lambda:
Invocations:
Expand Down
Expand Up @@ -3,8 +3,10 @@ import type { Template } from 'cloudform'
import { handler } from 'cf-macro-slic-watch/index'

import inputTemplate from './fixtures/sam-test-project-transformed-template.json'
import { setUpSnapshotDefaults } from 'test-utils/snapshot-utils'

test('sam-test-project snapshot', async (t) => {
setUpSnapshotDefaults(t)
const response = await handler({ fragment: inputTemplate as Template, requestId: 'snapshot-test' })
t.notOk(response.errorMessage)
t.equal(response.status, 'success')
Expand Down
@@ -1,16 +1,19 @@
import { test } from 'tap'
import { type Template } from 'cloudform-types'

import ServerlessPlugin from 'serverless-slic-watch-plugin/serverless-plugin'

import inputTemplate from './fixtures/cloudformation-template-update-stack.json'
import { createMockServerless } from 'test-utils/sls-test-utils'
import type { ResourceType } from 'slic-watch-core'
import { setUpSnapshotDefaults } from 'test-utils/snapshot-utils'

const logger = {}

const pluginUtils = { log: logger }

test('serverless-test-project-alb snapshot', (t) => {
const mockServerless = createMockServerless(inputTemplate.Resources as ResourceType)
setUpSnapshotDefaults(t)
const mockServerless = createMockServerless(inputTemplate as Template)
const plugin = new ServerlessPlugin(mockServerless, null, pluginUtils)
plugin.createSlicWatchResources()
const generatedTemplate = mockServerless.service.provider.compiledCloudFormationTemplate
Expand Down
@@ -1,16 +1,19 @@
import { test } from 'tap'
import { type Template } from 'cloudform-types'

import ServerlessPlugin from 'serverless-slic-watch-plugin/serverless-plugin'

import inputTemplate from './fixtures/cloudformation-template-update-stack.json'
import { createMockServerless } from 'test-utils/sls-test-utils'
import type { ResourceType } from 'slic-watch-core'
import { setUpSnapshotDefaults } from 'test-utils/snapshot-utils'

const logger = {}

const pluginUtils = { log: logger }

test('serverless-test-project-appsync snapshot', (t) => {
const mockServerless = createMockServerless(inputTemplate.Resources as ResourceType)
setUpSnapshotDefaults(t)
const mockServerless = createMockServerless(inputTemplate as unknown as Template)
const plugin = new ServerlessPlugin(mockServerless, null, pluginUtils)
plugin.createSlicWatchResources()
const generatedTemplate = mockServerless.service.provider.compiledCloudFormationTemplate
Expand Down
@@ -1,16 +1,19 @@
import { test } from 'tap'
import { type Template } from 'cloudform-types'

import ServerlessPlugin from 'serverless-slic-watch-plugin/serverless-plugin'

import inputTemplate from './fixtures/cloudformation-template-update-stack.json'
import { createMockServerless } from 'test-utils/sls-test-utils'
import type { ResourceType } from 'slic-watch-core'
import { setUpSnapshotDefaults } from 'test-utils/snapshot-utils'

const logger = {}

const pluginUtils = { log: logger }

test('serverless-test-project snapshot', (t) => {
const mockServerless = createMockServerless(inputTemplate.Resources as ResourceType)
setUpSnapshotDefaults(t)
const mockServerless = createMockServerless(inputTemplate as Template)
const plugin = new ServerlessPlugin(mockServerless, null, pluginUtils)
plugin.createSlicWatchResources()
const generatedTemplate = mockServerless.service.provider.compiledCloudFormationTemplate
Expand Down

0 comments on commit 962bf72

Please sign in to comment.