Added additional documentation to the software templating section including unit tests.

Signed-off-by: Steven Billington <sbillington@aurorasolar.com>
This commit is contained in:
Steven Billington
2024-04-24 15:43:57 -04:00
parent 2384a49962
commit 6a563f9e53
2 changed files with 69 additions and 10 deletions
@@ -734,7 +734,7 @@ an entity reference, such as the `kind`, `namespace`, and `name`.
### pick
This `pick` filter allows you to select specific properties from an object.
This `pick` filter allows you to select specific properties (`kind`, `namespace`, `name`) from an object.
**Usage Example**
@@ -4,15 +4,13 @@ title: Writing Tests For Actions
description: How to write tests for actions
---
Once you created a new action, your own custom one, or you would like to contribute new actions, you have to cover it with
Unit tests to be sure that your actions do what they suppose to do.
# Unit Testing Custom Actions
Make sure that you cover the most of scenario's, which could happen with the action.
One of indispensable part of the test is to supply the context to a handler of action for the execution.
We encourage you to use a utility method for that, so your tests are immune to structural changes of context.
What is inevitably going to happen during the time.
Unit tests help prevent regressions in custom action functionality. The `createTemplateAction` function that is the core of a custom action can be difficult to mock. There are helper methods that can assist.
Example how to use it:
## Mocking the Context
The `handler` property of the `createTemplateAction` input object expects a context. You can create a mock context using the code below:
```typescript
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
@@ -29,10 +27,11 @@ expect(mockContext.output).toHaveBeenCalledWith(
);
```
### Mocking a Workspace within the Context object
One thing to be aware about: if you would like to call `createMockActionContext` inside `it`,
you have to provide a `workspacePath`. By default, `createMockActionContext` uses
`import { createMockDirectory } from '@backstage/backend-test-utils';` to create it for you.
This implementation contains a hook inside which creates this limitation. So in this case you can do then:
`import { createMockDirectory } from '@backstage/backend-test-utils';` to create it for you. You can use the code below to customize the `workspacePath` without using the default workspace of the `createMockActionContext` function.
```typescript
describe('github:autolinks:create', async () => {
@@ -55,3 +54,63 @@ describe('github:autolinks:create', async () => {
});
});
```
## Mocking a Config Core Service
If your custom Action requires the Config Core Service within execution of the `handler(ctx)` such as the custom action below, mocking the context object can be done by building a `mockContext` with the `ConfigReader` function within the `@backstage/config` package.
```typescript
// custom-action.ts
import { Config } from '@backstage/config';
export const customActionRequiringConfigCoreService = (config: Config) => {
const fieldRequiringValueFromConfig = config.getString('app.service.url');
return createTemplateAction({
...
async handler(ctx) {
// Some code requiring the config const
ctx.logger.info(fieldRequiringValueFromConfig);
}
})
}
```
```typescript
// custom-action.test.ts
import { ConfigReader } from '@backstage/config';
import { customActionRequiringConfigCoreService } from './custom-action.ts';
...
const mockConfig = new ConfigReader({
app: {
service: {
url: 'https://api.service.io/graphql',
apiKeyId: '123',
apiKeySecret: '123abc',
},
},
});
...
const action = customActionRequiringConfigCoreService(mockConfig);
await action.handler({
...mockContext
})
```
## Mocking a Cache Core Service
Similar to the `Mocking a Config Core Service` section above, if your custom action expects a Cache Core Service Object as part of the function input, you can mock it out with the following:
```typescript
import { CacheService } from '@backstage/backend-plugin-api';
const mockCacheServiceMethods = {
get: jest.fn(),
set: jest.fn(),
delete: jest.fn(),
};
const mockCacheService = mockCacheServiceMethods as unknown as CacheService;
const action = customActionRequiringCacheCoreService(mockCacheService);
...
```