jest-simple-template

simple jest template based on iteration

Usage no npm install needed!

<script type="module">
  import jestSimpleTemplate from 'https://cdn.skypack.dev/jest-simple-template';
</script>

README

jest-simple-template

concepts

The concept of this template is to make closely test code to test document. So In this template, We use the describe.each method to define test code. The describe each is one of the jest feature.

https://jestjs.io/docs/en/api#describeeachtablename-fn-timeout

There are 2 principals

[Principal1] Meaning of table indexes

The describe.each accepts test cases as table. This template gives meanings to each index below.

index[0] - Object: Description of the test
index[1] - Object: Input of the test
index[2] - Function: Validate expectation of the test

[Principal2] Mocking Convention

This template automatically call mocks in a mock file. Test method calls the mock definition which is matched the name of the test description(=index[0])

Usage

To use this template, there are 2 steps for preparation.

1. Generate template

First, generate template by the generate_test_case command

generate_test_case <<category>> <<name of the test>>

This command generates mocks and test template in the tests folder.

+- <<root of the project>>  
  +- __tests__  
    +- <<category>>  
      +- <<name>>.test.ts  
      +- mocks.ts  

Important: currently, generator creates files only the tests folder of project root.

2. Import target method

Import target method in the test file

in the test file,


import handler from '../src/target' <---- importing function you want to test

/**
 * Test Case Definition
 *
 * [0]: test description
 * [1]: request(input)
 * [2]: expect(output)
 */
const testCase = [
    [
        // [0]: description
        {
            name: 'OK',
            description: 'should return succeeded response'
        },
        // [1]: request
        request,
        // [2]: expected
        (result: {}) => {
            expect(result).toBe(1)
        }
    ],
    [
        // [0]: description
        {
            name: 'Duplicated',
            description: 'should return duplicate something error'
        },
        // [1]: request
        request,
        // [2]: expected
        (result: {}) => {
            expect(result).toBe('error')
        }
    ]
]

describe.each(testCase)('Publish state', (d, r, e) => {
    beforeEach(() => {
        jest.resetAllMocks()
    })
    const testMeta = d as TestCaseMetaData
    it(`${testMeta.name}:${testMeta.description}`, async () => {
        if (mocks.hasOwnProperty(testMeta.name)) {
            mocks[testMeta.name]()
        }

        // @ts-ignore
        const result = await handler(r)
        const expected = e as (result: any) => void
        expected(result)
    })
})

Define mocks

You can define mock functions. Key has matched the name of test.

const mocks: Mocks = {
    OK: () => {
      // write the code of mocking some objects
    },
    Duplicated: () => {
      // write the code of mocking some objects
    }
}

export default mocks

Mock "OK" function will be called when the "OK" test case run.

/**
 * Test Case Definition
 *
 * [0]: test description
 * [1]: request(input)
 * [2]: expect(output)
 */
const testCase = [
    [
        // [0]: description
        {
            name: 'OK',
            description: 'should return succeeded response'
        },
        // [1]: request
        request,
        // [2]: expected
        (result: {}) => {
            expect(result).toBe(1)
        }
    ],
    [
        // [0]: description
        {
            name: 'Duplicated',
            description: 'should return duplicate something error'
        },
        // [1]: request
        request,
        // [2]: expected
        (result: {}) => {
            expect(result).toBe('error')
        }
    ]
]

describe.each(testCase)('Publish state', (d, r, e) => {
    beforeEach(() => {
        jest.resetAllMocks()
    })
    const testMeta = d as TestCaseMetaData
    it(`${testMeta.name}:${testMeta.description}`, async () => {
        if (mocks.hasOwnProperty(testMeta.name)) {
            mocks[testMeta.name]()
        }

        // @ts-ignore
        const result = await handler(r)
        const expected = e as (result: any) => void
        expected(result)
    })
})

Exported types and utilities

/// <reference types="jest" />
/**
 * list of mocks
 *
 */
export interface Mocks {
    [name: string]: () => {
        [name: string]: jest.SpyInstance;
    };
}
/**
 * mocked object list
 */
export interface MockReturn {
    [name: string]: jest.SpyInstance;
}
/**
 * Test Case Description
 */
export interface TestCaseMetaData {
    name: string;
    description: string;
}
/**
 * Test Case Expected function
 * @param result: result from test target
 * @param spies: mocked objects at ./mocks.ts
 */
export declare type TestCaseExpectedFunction = (result: {}, spies: MockReturn) => void;
/**
 * alter test input
 * only input is object
 * It's not supported nested key
 */
export interface AlterationParams {
    [name: string]: any;
}
/**
 * input alteration
 * @param base based object
 * @param alteration alter parameter
 */
export declare const alter: (base: {}, alteration: AlterationParams) => {};
/**
 *
 * @param testCase list of the test
 * @param name name of test case(should be matched name of test)
 */
export declare const sameAs: (testCase: any, name: string) => {};