0.0.14 • Published 8 months ago

@gmjs/test-util v0.0.14

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

Test Utilities

This project contains utilities for writing file comparison tests.

Installation

npm install --save-dev @gmjs/test-util

API

File Test Functions

High-level functions to do the heavy lifting in file comparison tests.

createFsTestCases

Creates test cases for file system tests.

These are essentially tests for code that generates a file hierarchy. We can use it to specify expected file hierarchy that should result from the code under test, and compare it to the actual file hierarchy generated by the code under test.

So how do we do that?

First of all, this function expects to find a directory with test cases as described in Test Case File Structure Setup.

Parameters

The first parameter to the function, testCasesRoot specifies the path to the above mentioned directory (<test-cases-root>).

The second parameter, actualFunction is the actual code under test. You define this function yourself, and pass it to createFsTestCases(). Actual function will receive the full path to the test case directory, and it should return a promise that resolves to a FilesContainer object.

Return Value

The result of createFsTestCases() is an array of TestCaseRun objects:

interface TestCaseRun {
  readonly name: string;
  readonly run: () => Promise<TestComparisonStrings>;
}

interface TestComparisonStrings {
  readonly expected: string;
  readonly actual: string;
}

name is simply the name of the test case directory. For example, if the test case directory is <test-cases-root>/cases/test-case-01, then name will be test-case-01.

Running Tests

The actual test is executed by calling the run() function returned from createFsTestCases(). This function returns a promise, which resolves to a TestComparisonStrings object, which can be used for a simple string comparison test.

expected and actual strings are generated internally from the expected and actual FilesContainer objects. The string will contain a list of files, each with its path and content. The list of files is sorted by path, so that the order of files is deterministic. For binary files, only the hash is printed, not the actual content.

Example
describe('test', () => {
  const testCaseRuns = createFsTestCases('path/to/test-cases-root', getActualFiles);

  for (const testCaseRun of testCaseRuns) {
    it(testCaseRun.name, async () => {
      const { expected, actual } = await testCaseRun.run();
      expect(actual).toBe(expected);
    });
  }
});

async function getActualFiles(testCaseDirectory: string): Promise<FilesContainer> {
  // code under test, returns a FilesContainer object
}

Test Case File Structure Setup

This is the test case file structure used by createFsTestCases function.

This function expects to find a directory with test case files which will produce actual and expected results for a final test comparison.

Below is an example with a single test case, and a single shared directory.

<test-cases-root>
  cases
    test-case-01
      expected
        files
          subdir
            expected-11.png.bin
          expected-1.js.txt
          expected-2.json.txt
        path-mapping.json
      input
        input.json
  shared
    shared-dir
      shared-1.js.txt
      shared-2.ts.txt

Test Case

Test cases can have arbitrary names, not just test-case-*.

There can be any number of test cases in <test-cases-root>/cases directory.

<test-case>/expected/files directory contains files that will be used to create the expected result, this is the input for the mapping defined in path-mapping.json.

Each file under <test-case>/expected/files must have a .txt or .bin extension, which determines whether the file is read as text or binary.

<test-case>/expected/path-mapping.json file contains a list of fr-to entries, which are used to map files from <test-case>/expected/files to the final expected file system structure.

Besides <test-case>/expected directory, you can put any other directories and files inside <test-case> directory. You can for example use these as inputs for creating the actual result in case you need any inputs. Then you can read those inputs inside actualFunction. However, since you provide actualFunction yourself, you have full control of this process and you can generate the actual result in any way you want, using any inputs you want.

Shared Directories

<test-cases-root>/shared directory contains a list of shared directories, each with shared files that can be referenced from any test case. These are essentially shared expected files, ones which would otherwise be inside <test-case>/expected/files, but are moved to a shared directory to avoid duplication. Like files under <test-case>/expected/files, files under <test-cases-root>/shared must also have a .txt or .bin extension.

Directories under <test-cases-root>/shared can have arbitrary names. Let's say we have the following directory structure:

<test-cases-root>
  cases
    ...
  shared
    a-shared-dir
      shared-1.js.txt
      shared-2.ts.txt
    another-shared-dir
      shared-3.json.txt
      shared-4.svg.txt

Then, in path-mapping.json files, you can reference files under <test-cases-root>/shared like this (<a-shared-dir> etc. are literal, verbatim values in the mapping json file, not documentation placeholders like <test-cases-root>):

[
  {
    "group": "some-group",
    "files": [
      {
        "fr": "<a-shared-dir>/shared-1.js.txt",
        "to": "target-dir/some-file.js"
      },
      {
        "fr": "<another-shared-dir>/shared-3.json.txt",
        "to": "target-dir/some-other-file.json"
      }
    ]
  }
]

Note that for example <a-shared-dir> refers to <test-cases-root>/shared/a-shared-dir.

<test-cases-root>/shared is optional, and you don't have to create it if you don't use it in path-mapping.json files.

Test Case Path Mapping

<test-case>/expected/path-mapping.json file contains a list of fr-to entries, which are used to map files from <test-case>/expected/files to the final expected file system structure.

More precisely, path-mapping.json will contain groups of fr-to entries, but these groups are arbitrary, used just for visual organization of the file, and the lists of fr-to entries are simply flattened into a single list.

Using the first directory structure example, we can have the following file mapping:

[
  {
    "group": "assets",
    "files": [
      {
        "fr": "subdir/expected-11.png.bin",
        "to": "target-dir/assets/asset-11.png"
      }
    ]
  },
  {
    "group": "src",
    "files": [
      {
        "fr": "expected-1.js.txt",
        "to": "target-dir/src/file-1.js"
      },
      {
        "fr": "expected-2.json.txt",
        "to": "target-dir/src/file-2.json"
      },
      {
        "fr": "<shared-dir>/shared-1.js.txt",
        "to": "target-dir/src/shared-file-1.js"
      },
      {
        "fr": "<shared-dir>/shared-2.ts.txt",
        "to": "target-dir/src/shared-file-2.ts"
      }
    ]
  }
]

You can think of the above as a flat list of 5 file mappings, which will produce the following file structure in the expected result:

target-dir
  assets
    asset-11.png
  src
    file-1.js
    file-2.json
    shared-file-1.js
    shared-file-2.ts

Types

FilesContainer

Container with file path-content pairs.

Has the following structure:

interface FilesContainer {
  readonly textFiles: readonly FilePathTextContent[];
  readonly binaryFiles: readonly FilePathBinaryContent[];
}

Items in the above array have essentially the following structure:

interface FilePathTextContent {
  readonly path: string;
  readonly content: string;
}

interface FilePathBinaryContent {
  readonly path: string;
  readonly content: Buffer;
}
0.0.10

9 months ago

0.0.11

9 months ago

0.0.12

8 months ago

0.0.13

8 months ago

0.0.14

8 months ago

0.0.1

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.9

1 year ago

0.0.8

1 year ago

0.0.4

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.175

1 year ago

0.0.174

1 year ago

0.0.173

1 year ago

0.0.172

1 year ago

0.0.179

1 year ago

0.0.178

1 year ago

0.0.177

1 year ago

0.0.176

1 year ago

0.0.171

1 year ago

0.0.170

1 year ago

0.0.184

1 year ago

0.0.183

1 year ago

0.0.182

1 year ago

0.0.181

1 year ago

0.0.180

1 year ago

0.0.169

1 year ago

0.0.168

1 year ago

0.0.167

1 year ago

0.0.166

1 year ago

0.0.165

1 year ago

0.0.164

1 year ago

0.0.163

1 year ago

0.0.162

1 year ago

0.0.161

1 year ago

0.0.159

2 years ago

0.0.158

2 years ago

0.0.153

2 years ago

0.0.152

2 years ago

0.0.157

2 years ago

0.0.156

2 years ago

0.0.155

2 years ago

0.0.154

2 years ago

0.0.160

2 years ago

0.0.151

2 years ago

0.0.150

2 years ago

0.0.149

2 years ago

0.0.148

2 years ago

0.0.147

2 years ago

0.0.146

2 years ago

0.0.145

2 years ago

0.0.144

2 years ago

0.0.128

2 years ago

0.0.127

2 years ago

0.0.126

2 years ago

0.0.125

2 years ago

0.0.129

2 years ago

0.0.139

2 years ago

0.0.138

2 years ago

0.0.137

2 years ago

0.0.136

2 years ago

0.0.131

2 years ago

0.0.130

2 years ago

0.0.135

2 years ago

0.0.134

2 years ago

0.0.133

2 years ago

0.0.132

2 years ago

0.0.142

2 years ago

0.0.141

2 years ago

0.0.140

2 years ago

0.0.143

2 years ago

0.0.124

2 years ago

0.0.120

2 years ago

0.0.123

2 years ago

0.0.122

2 years ago

0.0.121

2 years ago

0.0.84

2 years ago

0.0.85

2 years ago

0.0.86

2 years ago

0.0.87

2 years ago

0.0.88

2 years ago

0.0.89

2 years ago

0.0.80

2 years ago

0.0.81

2 years ago

0.0.82

2 years ago

0.0.83

2 years ago

0.0.73

2 years ago

0.0.74

2 years ago

0.0.75

2 years ago

0.0.76

2 years ago

0.0.77

2 years ago

0.0.78

2 years ago

0.0.79

2 years ago

0.0.70

2 years ago

0.0.71

2 years ago

0.0.72

2 years ago

0.0.64

2 years ago

0.0.65

2 years ago

0.0.66

2 years ago

0.0.67

2 years ago

0.0.68

2 years ago

0.0.69

2 years ago

0.0.60

2 years ago

0.0.61

2 years ago

0.0.59

2 years ago

0.0.106

2 years ago

0.0.51

2 years ago

0.0.105

2 years ago

0.0.52

2 years ago

0.0.104

2 years ago

0.0.53

2 years ago

0.0.103

2 years ago

0.0.54

2 years ago

0.0.55

2 years ago

0.0.109

2 years ago

0.0.56

2 years ago

0.0.108

2 years ago

0.0.57

2 years ago

0.0.107

2 years ago

0.0.58

2 years ago

0.0.102

2 years ago

0.0.101

2 years ago

0.0.100

2 years ago

0.0.50

2 years ago

0.0.48

2 years ago

0.0.49

2 years ago

0.0.117

2 years ago

0.0.40

2 years ago

0.0.116

2 years ago

0.0.41

2 years ago

0.0.115

2 years ago

0.0.42

2 years ago

0.0.114

2 years ago

0.0.43

2 years ago

0.0.44

2 years ago

0.0.45

2 years ago

0.0.119

2 years ago

0.0.46

2 years ago

0.0.118

2 years ago

0.0.47

2 years ago

0.0.113

2 years ago

0.0.112

2 years ago

0.0.111

2 years ago

0.0.110

2 years ago

0.0.37

2 years ago

0.0.38

2 years ago

0.0.39

2 years ago

0.0.31

2 years ago

0.0.32

2 years ago

0.0.33

2 years ago

0.0.34

2 years ago

0.0.35

2 years ago

0.0.36

2 years ago

0.0.95

2 years ago

0.0.96

2 years ago

0.0.97

2 years ago

0.0.98

2 years ago

0.0.99

2 years ago

0.0.90

2 years ago

0.0.91

2 years ago

0.0.92

2 years ago

0.0.93

2 years ago

0.0.94

2 years ago

0.0.30

2 years ago

0.0.29

2 years ago

0.0.28

2 years ago

0.0.27

2 years ago

0.0.26

2 years ago

0.0.25

2 years ago

0.0.24

2 years ago

0.0.23

2 years ago