File: cli.md

package info (click to toggle)
node-uvu 0.5.6%2B~cs4.10.4-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,352 kB
  • sloc: javascript: 6,951; makefile: 10
file content (118 lines) | stat: -rw-r--r-- 5,443 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# CLI

> The `uvu` CLI is available whenever you install the `uvu` package.

The _role_ of the `uvu` CLI is to collect and execute your tests suites. In order to do that, you must tell it how/where to find your tests. Otherwise, it has a default set of file patterns to search for – but that probably won't align with your project's structure.

> **Note:** Using the `uvu` CLI is actually _optional_! See [Isolation](#isolation) for more info.

Let's take a look at the CLI's help text:

```sh
$ uvu --help
#
#   Usage
#     $ uvu [dir] [pattern] [options]
#
#   Options
#     -b, --bail       Exit on first failure
#     -i, --ignore     Any file patterns to ignore
#     -r, --require    Additional module(s) to preload
#     -C, --cwd        The current directory to resolve from  (default .)
#     -c, --color      Print colorized output  (default true)
#     -v, --version    Displays current version
#     -h, --help       Displays this message
#
```

As you can see, there are few arguments and option flags! <br>They're categorized by responsibility:

* where/how to locate test files (`dir`, `pattern`, `--ignore`, and `--cwd`)
* environment preparation (`--require` and `--color`)
* whether or not to exit on suite failures (`--bail`)

## Matching

***Aside: Glob Patterns***

Unlike other test runners, `uvu` intentionally _does not_ rely on glob patterns. <br>Parsing and matching globs both require a non-trivial amount of work. (Even the smallest glob-parsers are as large – or larger – than the entire `uvu` source!) This price has to be paid upfront – at startup – and then becomes completely irrelevant. And then on the consumer side, glob patterns fall into one of two categories:

* extremely simple patterns (eg, `test/**`, `tests/**/*.test.(ts|js)`, etc)
* extremely complicated patterns that require squinting and fine-tuning

Simple patterns don't _require_ a glob pattern 99% of the time. <br>
Complicated glob patterns can (often) be better expressed or understood as separate segments.

And then there's the reoccurring issue of some shells and/or operating systems (eg, Windows) that will pre-evaluate a glob pattern, ruining a CLI's expected input... And how different systems require quotation marks, and/or certain characters to be escaped... There are issues with this approach. It certainly _can_ work, but `uvu` sidesteps this can of worms in favor of a different, but simpler approach.

***Logic***

The CLI will _always_ resolve lookups from the `--cwd` location, which is the `process.cwd()` when unspecified.

By default (aka, when no arguments are given), `uvu` looks for files matching this behemoth of a pattern:

```js
/((\/|^)(tests?|__tests?__)\/.*|\.(tests?|spec)|^\/?tests?)\.([mc]js|[jt]sx?)$/i;
```

This will:

* search within `test`, `tests` or `__test__` or `__tests__` directories if they exist; otherwise any directory
* search for files matching `*.test.{ext}` or `*.tests.{ext}` or `*.spec.{ext}`
* search for files with these extensions: `mjs`, `cjs`, `js`, `jsx`, `tsx`, or `ts`

Of course, you can help `uvu` out and narrow down its search party by providing a `dir` argument. Instead of searching from your project's root, `dir` tells `uvu` where to _start_ its traversal from. And by specifying a `dir`, the default `pattern` changes such that any file with a `mjs`, `cjs`, `js`, `jsx`, `tsx`, or `ts` extension will match.

Finally, you may specify your own `pattern` too &mdash; assuming `dir` has been set. <br>The `pattern` value is passed through `new RegExp(<pattern>, 'i')`. If you are nostalgic for complex glob patterns, this is your chance to relive its glory days – with substitutions, of course.

For example, if we assume a [monorepo environment](/examples/monorepo/package.json), your `uvu` usage may look like this:

```sh
$ uvu packages tests -i fixtures
```

This will traverse the `packages` directory, looking at files and subdirectories that match `/tests/i`, but ignore anything that matches the `/fixtures/i` pattern.


***Ignoring***

Any file or directory names matching `node_modules` or `^.git` are _always_ ignored.

You can use the `-i/--ignore` flags to provide additional patterns to ignore. Much like `[pattern]`, these values are cast to a `RegExp`, allowing you to be as vague or specific as you need to be.

The `-i/--ignore` flags can be passed multiple times:

```sh
# Traverse "packages" diectory
# ~> ignore items matching /foobar/i
# ~> ignore items matching /fixtures/i
# ~> ignore items matching /\d+.js$/i
$ uvu packages -i foobar -i fixtures -i \\d+.js$
```


## Isolation

When running `uvu`, it looks for all test files and will enqueue all suites for execution. You can always disable individual suites (by commenting out its `.run()` call), but sometimes you just want to execute a single file.

To do this, you can simply call `node` with the path to your file! 🎉<br>This works _because_ `uvu` test files are self-contained – its `import`/`require` statements aren't tucked away, nor are the suites' `run()` invocation.

```sh
# Before (runs everything in packages/**/**test**)
$ uvu packages test

# After (specific file)
$ node packages/utils/test/random.js
```

Since `uvu` and `node` share the `--require` hook, you can bring your `uvu -r` arguments to `node` too~!

```sh
# Before
$ uvu -r esm tests
$ uvu -r ts-node/register tests

# After
$ node -r esm tests/math.js
$ node -r ts-node/register tests/math.ts
```