@@ -489,8 +489,8 @@ added: REPLACEME
489489
490490Tags annotate tests and suites with arbitrary string labels. The
491491[ ` --experimental-test-tag-filter ` ] [ ] CLI flag (or the ` testTagFilters `
492- option on [ ` run() ` ] [ ] ) selects tests whose tag set contains every
493- provided filter value .
492+ option on [ ` run() ` ] [ ] ) selects tests by a boolean expression over those
493+ labels .
494494
495495Tags are an alternative to encoding metadata into test names. They are
496496useful for cross-cutting axes such as subsystem, speed bucket, flakiness,
@@ -523,37 +523,89 @@ describe('database', { tags: ['db'] }, () => {
523523});
524524```
525525
526- Tag values must be non-empty strings. Tags are matched case-insensitively;
527- the canonical form is lowercase. Duplicates within a single ` tags ` array
528- are collapsed on the lowercased form, preserving the first-seen
529- declaration order.
526+ Tag values must be non-empty strings that contain no whitespace, no
527+ operator characters (` & | ! ( ) * ` ), and are not the reserved words
528+ ` 'and' ` , ` 'or' ` , or ` 'not' ` in any casing. Tags are matched
529+ case-insensitively; the canonical form is lowercase. Duplicates within a
530+ single ` tags ` array are collapsed on the lowercased form, preserving the
531+ first-seen declaration order.
530532
531533Hooks (` before ` , ` after ` , ` beforeEach ` , ` afterEach ` ) do not declare their
532534own tags. They run as part of their owning suite, which carries the
533535suite's tags.
534536
535- ### Filtering by tag
537+ ### Filtering syntax
536538
537- Each [ ` --experimental-test-tag-filter ` ] [ ] value is a literal tag name. A
538- test runs only when its tag set contains that name. The flag may be
539- specified more than once; tests must match ** every** filter to run. The
540- same applies to the ` testTagFilters ` array on [ ` run() ` ] [ ] . Filters are
541- case-insensitive and AND'd with [ ` --test-name-pattern ` ] [ ] ,
542- [ ` --test-skip-pattern ` ] [ ] , and ` .only ` filtering.
539+ The filter expression supports:
543540
544- Untagged tests are excluded under any non-empty filter, since the filter
545- requires the tag to be present.
541+ * Identifiers—any non-whitespace, non-operator characters. A literal
542+ identifier matches a tag of the same value (case-insensitive).
543+ * ` * ` wildcards inside an identifier match any sequence of characters.
544+ A bare ` * ` matches any tagged test.
545+ * Boolean operators with two equivalent forms:
546+ * ` and ` / ` && `
547+ * ` or ` / ` || `
548+ * ` not ` / ` ! `
549+ * Parentheses for grouping.
546550
547- ### Reading tags from inside a test
551+ The word forms (` and ` , ` or ` , ` not ` ) require whitespace separation; the
552+ punctuation forms do not.
553+
554+ #### Operator precedence
555+
556+ The expression is evaluated with the standard precedence
557+ ` not > and > or ` . Binary operators are left-associative.
558+
559+ | Expression | Equivalent grouping |
560+ | -------------- | ------------------- |
561+ | ` a or b and c ` | ` a or (b and c) ` |
562+ | ` not a and b ` | ` (not a) and b ` |
563+
564+ Use parentheses to override:
565+
566+ | Expression | Selects |
567+ | ------------------------------ | ------------------------------------------ |
568+ | ` (unit or smoke) and not slow ` | unit-or-smoke tests that are not also slow |
569+ | ` db && !flaky ` | db tests that are not flaky |
570+ | ` * ` | every tagged test |
571+
572+ #### Untagged tests
573+
574+ Untagged tests behave as if they have an empty tag set. As a result:
575+
576+ | Filter expression | Untagged test | Why |
577+ | ------------------------ | ------------- | ------------------------------------------------ |
578+ | ` db ` | excluded | Positive match against an empty tag set is false |
579+ | ` * ` | excluded | The bare wildcard requires at least one tag |
580+ | ` db or unit ` | excluded | Both branches are false against an empty tag set |
581+ | ` not flaky ` | included | Negation against an empty tag set is true |
582+ | ` not flaky and not slow ` | included | Both negations are true against an empty tag set |
583+ | ` db or not flaky ` | included | The negated branch is true |
584+
585+ For example, ` --experimental-test-tag-filter='not flaky' ` runs every test
586+ that is not tagged ` flaky ` , including all untagged tests.
587+
588+ #### Composing multiple filters
589+
590+ [ ` --experimental-test-tag-filter ` ] [ ] may be specified more than once on the
591+ command line. Multiple expressions compose by AND—a test must satisfy
592+ every expression to run. The same applies to passing an array to
593+ ` testTagFilters ` on [ ` run() ` ] [ ] . The tag filter is also AND'd with
594+ [ ` --test-name-pattern ` ] [ ] , [ ` --test-skip-pattern ` ] [ ] , and ` .only `
595+ filtering.
596+
597+ #### Reading tags from inside a test
548598
549599The [ ` TestContext ` ] [ ] object exposes the test's tags as a frozen array
550600through [ ` context.tags ` ] [ ] , so tests can branch on their own metadata.
551601
552- ### Errors
602+ #### Errors
553603
554604A tag value that violates the validation rules above throws
555605` ERR_INVALID_ARG_VALUE ` at the registration site, before any test runs.
556- A non-array ` tags ` value throws ` ERR_INVALID_ARG_TYPE ` .
606+ A non-array ` tags ` value throws ` ERR_INVALID_ARG_TYPE ` . A malformed
607+ filter expression on the CLI causes the test runner to exit with a
608+ non-zero status before running any test files.
557609
558610## Extraneous asynchronous activity
559611
@@ -826,7 +878,7 @@ test runner functionality:
826878
827879* ` --test ` - Prevented to avoid recursive test execution
828880* ` --experimental-test-coverage ` - Managed by the test runner
829- * ` --experimental-test-tag-filter ` - Filter values are validated by the parent
881+ * ` --experimental-test-tag-filter ` - Filter expressions are validated by the parent
830882 process and re-emitted to child processes
831883* ` --watch ` - Watch mode is handled at the parent level
832884* ` --experimental-default-config-file ` - Config file loading is handled by the parent
@@ -1737,10 +1789,11 @@ changes:
17371789 For each test that is executed, any corresponding test hooks, such as
17381790 ` beforeEach() ` , are also run.
17391791 ** Default:** ` undefined ` .
1740- * ` testTagFilters ` {string|string\[ ] } A tag name, or an array of tag names,
1741- used to filter tests by their declared tags. Tests must contain every
1742- listed tag to run. Equivalent to passing [ ` --experimental-test-tag-filter ` ] [ ]
1743- on the command line. See [ Test tags] [ ] . ** Default:** ` undefined ` .
1792+ * ` testTagFilters ` {string|string\[ ] } A boolean expression, or an array of
1793+ boolean expressions, used to filter tests by their declared tags.
1794+ Multiple expressions compose by AND. Equivalent to passing
1795+ [ ` --experimental-test-tag-filter ` ] [ ] on the command line. See
1796+ [ Test tags] [ ] . ** Default:** ` undefined ` .
17441797 * ` timeout ` {number} A number of milliseconds the test execution will
17451798 fail after.
17461799 If unspecified, subtests inherit this value from their parent.
0 commit comments