handler.test.ts configuration
Introduction to the handler.test.ts file
This file will contain the unit tests that ensure the operation is working as expected.
This page shows how to create and run tests.
You can directly jump to the examples of positive and negative testing if you are familiar with typescript.
Creating Tests
Tests are configured using configureHandlerTest
function of the OperationHandlerTestSetup
inteface.
configureHandlerTest
takes two arguements:
Parameter | Notes |
---|---|
handler |
Reference to handler function |
handlerTest callback |
Function for configuring and validating the result |
handlerTest
callback uses given-when-then style of testing.
The inputs are configured in the when
block and expect
is used to validate the operation result in the then
block.
Here is a test for an operation that converts HTML to Markdown:
import { OperationHandlerTestSetup } from "@trayio/cdk-dsl/connector/operation/OperationHandlerTest";
import { htmlToMarkdownHandler } from "./handler";
import {
OperationHandlerError,
OperationHandlerResult,
} from "@trayio/cdk-dsl/connector/operation/OperationHandler";
import "@trayio/cdk-runtime/connector/operation/OperationHandlerTestRunner";
OperationHandlerTestSetup.configureHandlerTest(
htmlToMarkdownHandler,
(handlerTest) =>
handlerTest
.usingHandlerContext("test")
.nothingBeforeAll()
.testCase("should do something", (testCase) =>
testCase
.givenNothing()
// input object { htmlString: `<h3>Hello world!</h3>` } passed through when block
.when(() => ({ htmlString: `<h3>Hello world!</h3>` }))
.then(({ output }) => {
// use getSuccessfulValueOrFail to get the operation result
const outputValue =
OperationHandlerResult.getSuccessfulValueOrFail(output);
// using expect to validate the result
expect(outputValue.markdownString).toEqual("### Hello world!");
})
.finallyDoNothing()
)
.nothingAfterAll()
);
Running Tests
info
You can also use npm test
script to run all tests at once.
You can run:
tray-cdk connector test
to test all the operations
OR
tray-cdk connector test [OPERATION_NAME]
to test an individual operation.
Examples
Positive test
You must use getSuccessfulValueOrFail
method of OperationHandlerResult
object to process the success response from the operation.
Once you have the response you can use jest's expect function to validate the result.
Here is a positive test case for an operation that converts Markdown to HTML:
.testCase("should return HTML", (testCase) =>
testCase
.givenNothing()
.when(() => ({ markdownString: `### Hello world!` }))
.then(({ output }) => {
const outputValue =
OperationHandlerResult.getSuccessfulValueOrFail(output);
expect(outputValue.htmlString).toEqual("<h3>Hello world!</h3>\n");
})
.finallyDoNothing()
)
Negative test
For a negative test, the operation (defined in handler.ts
) should return a failure. Check error handling section on how to return failures.
Here is an example of a composite operation that converts Contentful's Richtext document to HTML and resolves with an API error upon failure.
import { documentToHtmlString } from "@contentful/rich-text-html-renderer";
export const richtextToHtmlHandler = OperationHandlerSetup.configureHandler<
DataFormatHelperAuth,
RichtextToHtmlInput,
RichtextToHtmlOutput
>((handler) =>
handler.usingComposite(async (ctx, { richTextDocument }, invoke) => {
const htmlString = documentToHtmlString(richTextDocument);
if (htmlString === "")
return OperationHandlerResult.failure(
OperationHandlerError.userInputError("Invalid Richtext document")
);
return OperationHandlerResult.success({ htmlString });
})
);
.testCase("should fail", (testCase) =>
testCase
.givenNothing()
.when(() => ({ richTextDocument: badRichTextDocument }))
.then(({ output }) => {
expect(output.isFailure).toBe(true);
if (output.isFailure) {
expect(output.error._tag).toEqual("UserInputError");
expect(output.error.message).toEqual("Invalid Richtext document");
}
})
.finallyDoNothing()
)
Multiple tests
To ensure your connectors don't return unexpected results, you should write tests for each scenario.
To achieve this, You can chain testCase
functions as shown below:
.testCase("should return H3", (testCase) =>
testCase
.givenNothing()
.when(() => ({ markdownString: `### Hello world!` }))
.then(({ output }) => {
const outputValue =
OperationHandlerResult.getSuccessfulValueOrFail(output);
expect(outputValue.htmlString).toEqual("<h3>Hello world!</h3>\n");
})
.finallyDoNothing()
).testCase("should return H4", (testCase) =>
testCase
.givenNothing()
.when(() => ({ markdownString: `#### Hello world!` }))
.then(({ output }) => {
const outputValue =
OperationHandlerResult.getSuccessfulValueOrFail(output);
expect(outputValue.htmlString).toEqual("<h4>Hello world!</h4>\n");
})
.finallyDoNothing()
)