diff --git a/README.md b/README.md index aa8b027..b72e106 100644 --- a/README.md +++ b/README.md @@ -850,19 +850,20 @@ To test your **update** function you can use some helper functions in `react-elm | --- | --- | | `getOfMsgParams` | Extracts the messages out of a command | | `execCmd` | Executes the provided command and returns an array of all messages. | -| `getUpdateFn` | returns an `update` function for your update map object. | +| `getUpdateFn` | Returns an `update` function for your update map object. | +| `createUpdateArgsFactory` | Creates a factory function to create a message, a model, and props in a test. | ### Testing the model and simple message commands ```ts import * as Testing from "react-elmish/dist/Testing"; +const createUpdateArgs = Testing.createUpdateArgsFactory(() => ({ /* initial model */ }), () => ({ /* initial props */ })); + ... it("returns the correct model and cmd", () => { // arrange - const model = // create model for test - const props = // create props for test - const msg = Shared.Msg.test(); + const [msg, model, props] = createUpdateArgs(Shared.Msg.test(), { /* optionally override model here */ }, { /* optionally override props here */ }); const expectedValue = // what you expect in the model const expectedCmds = [ @@ -892,9 +893,7 @@ import * as Testing from "react-elmish/dist/Testing"; ... it("returns the correct cmd", () => { // arrange - const model = { /* create model */ }; - const props = { /* create props */ }; - const msg = Shared.Msg.asyncTest(); + const [msg, model, props] = createUpdateArgs(Shared.Msg.asyncTest()); // mock function which is called when the "AsyncTest" message is handled const functionMock = jest.fn(); diff --git a/src/Testing/index.ts b/src/Testing/index.ts index ec8ce59..7266f37 100644 --- a/src/Testing/index.ts +++ b/src/Testing/index.ts @@ -46,14 +46,53 @@ async function execCmd (cmd?: Cmd): Promise []> { return results; } +/** + * Creates an update function out of an UpdateMap. + * @param {UpdateMap} updateMap The UpdateMap. + * @returns {(msg: TMessage, model: TModel, props: TProps) => UpdateReturnType} The created update function which can be used in tests. + */ function getUpdateFn (updateMap: UpdateMap): (msg: TMessage, model: TModel, props: TProps) => UpdateReturnType { return function (msg: TMessage, model: TModel, props: TProps): UpdateReturnType { return callUpdateMap(updateMap, msg, model, props); }; } +type UpdateArgsFactory = (msg: TMessage, modelTemplate?: Partial, propsTemplate?: Partial) => [TMessage, TModel, TProps]; + +/** + * Creates a factory function to create a message, a model, and props which can be passed to an update function in tests. + * @param {() => TModel} initModel A function to create an initial model. + * @param {() => TProps} initProps A function to create initial props. + * @returns {UpdateArgsFactory} A function to create a message, a model, and props. + * @example + * // one time + * const createUpdateArgs = createUpdateArgsFactory(() => ({ ... }), () => ({ ... })); + * // in tests + * const [msg, model, props] = createUpdateArgs(Msg.myMessage(), { ... }, , { ... }); + */ +function createUpdateArgsFactory (initModel: () => TModel, initProps: () => TProps): UpdateArgsFactory { + return function (msg: TMessage, modelTemplate?: Partial, propsTemplate?: Partial): [TMessage, TModel, TProps] { + return [ + msg, + { + ...initModel(), + ...modelTemplate, + }, + { + ...initProps(), + ...propsTemplate, + }, + ]; + }; +} + +export type { + UpdateArgsFactory, +}; + export { getOfMsgParams, execCmd, getUpdateFn, + createUpdateArgsFactory, }; \ No newline at end of file