Repository navigation
Releases
v0.10.2
Patch Changes
-
#103
2e6c3bf- Clarify declared states, conditional skips and expected failures in CLI help, API comments, recipes and CI reports.
Correct config inheritance and failure-scope descriptions. Add first-use guidance, concepts and troubleshooting,
preserve existing documentation URLs, and publish the diff schema alongside the inventory schema. -
#104
cf08b52- Add a checked complete library example, a CLI/library/MCP walkthrough, compact agent guidance and feature-level
compatibility notes. Prioritize essential Markdown references and distinguish illustrative excerpts from runnable
code by their copy controls. -
#105
9325281- Add focused documentation guides for each supported test framework and separate shared scanner limits from runner-specific exceptions. -
#107
ef35e6e- Add checked examples for Cypress component and E2E selection, WebdriverIO with Jasmine, Playwright projects and Bun case expansion to the framework guides. -
#106
30dc03f- Keep skipped-test queries consistent with the first scan, add focused Vitest, Jest and Mocha examples, and link framework guides to relevant next steps. -
#108
7891cc0- Read context modifiers and subtests in named node:test callbacks, retain valid parent test IDs when callbacks appear before their callers, recognize Windows patterns naming linked node:test folders, and reject TOML inline tables with missing commas.Stop claiming that Jest runs tests when a required local preset is missing. Config-based discovery returns no files, while explicit globs retain the declarations with a file-not-run diagnostic.
Validate node:test concurrency values, report unknown values, and inherit concurrency through parent tests without resetting it for null or undefined options.
v0.10.1
Patch Changes
-
#99
df8968d- Keep Playwright declaring modifiers when functions are stored in variables or selected inline. Read logical choices with the same rules as the other runners, and classify each nested branch once to avoid exponential traversal.Match Vite's alias merge precedence and preserve object aliases when mixed with lists. Mark imports as unfollowed when an unreadable alias entry or find could match them.
Ignore annotation and step line numbers in inventory diffs, so moving unchanged tests to another line does not report metadata changes.
-
#100
fa10d39- Read locally declared describe callbacks passed by name, preserving suite placement, inherited state, lexical values and expanded table arguments. Keep suite hashes, dependencies and nested parent links complete, including when a child is written before its calling parent. Apply the existing helper traversal limits and runner callback checks to these callbacks.
v0.10.0
Minor Changes
- #96
86e1765- Compare two complete saved scans withtest-inventory diff old.json new.jsonordiffInventories(before, after).
Reports additions, removals, renamed and moved tests, changed code and dependencies, state, tags and other metadata.
Matches ids first, then body hashes with file, suite or dependency context, leaving ambiguous matches unmatched.
Includes exact body clone groups, JSON Schema, and escaped Markdown output through--format markdownor
formatDiffMarkdown. Hash comparisons and rename matching require identical tool versions; incomplete scans warn.
Patch Changes
-
#96
86e1765- Keep unreadable config aliases as dependency gaps rather than silently treating their imports as installed packages.
Read string concatenation and templates in config paths. Follow config aliases in setup paths, Jasmine helper globs,
Cypress's default and configured support files, Bun preload files, and Node script preloads in dependencies and
dependencyHash, so --related keeps tests affected by changes to those files. -
#96
86e1765- Apply Mocha's focus filtering, including Cypress and WebdriverIO on Mocha, so an outer describe.only does not focus
tests that a more specific focus excludes. A root focused test in standalone Mocha excludes child suites across
files. Contain refused calls inside node:test and Bun describe callbacks: Node keeps earlier tests and tests outside
the describe; Bun loses that describe only. Vitest reads allowOnly per project, does not fail unconditionally skipped
focused tests, and refuses modifiers after a called each or for table.
v0.9.1
Patch Changes
-
#92
0001eea- Bun: a test whose function is passed by name, followed by a timeout or options, as in
test('reprices a basket', repricesBasket, 5_000), is read as a test. The scan took the timeout for the function and
reported atest-without-bodyerror, listing every test in the file as not loaded, though Bun runs them. -
#92
0001eea- A__proto__key in abunfig.tomlor.mocharc.ymlis read as a plain key, as Bun and Mocha read it. A
bunfig.tomlwith a[__proto__]table changedObject.prototypefor the whole process, so every later scan in it,
such as those of a long-running MCP server, read settings the project never set. A.mocharc.ymlone gave its map the
settings inside it. TOML keys namedconstructorortoStringare read too, where they were refused. -
#92
0001eea- Cypress:specPatternandexcludeSpecPatternare read as globby, which Cypress uses, reads them. AspecPatternthat
starts with!leaves files out, where the scan took it to match every other file and listed nearly the whole project;
anexcludeSpecPatterndrops its!, where the scan left out everything else; and a folder in either stands for every
file below it, where it matched nothing. -
#92
0001eea- Jasmine: a describe callback with a TypeScriptthisparameter, a parameter with a default value or a rest parameter,
asfunction (this: object), is no longer reported as taking arguments. Jasmine checks the function'slength, which
counts none of these, and runs the specs; the scan listed them as not loaded. -
#92
0001eea- Jasmine: anxdescribeinside anfdescribestays skipped, as in Jasmine, where the scan listed its specs as active;
a focus inside thexdescribestill runs. WebdriverIO on Jasmine now follows Jasmine's focus rules: afitinside an
xdescriberuns, and in anfdescribewith afitbelow it only thefithasisOnly, where the scan applied
Mocha's rules. -
#92
0001eea- A<rootDir>entry in Jest'smoduleDirectories, as['node_modules', '<rootDir>/src'], is followed as a folder to
look in, as Jest does. The scan looked for a folder named<rootDir>/srcand left the files out ofdependencies
without a warning. -
#92
0001eea- Jest'smoduleNameMapperreplaces the whole import name, as Jest does, also when its pattern matches only part of it,
as'\\.css$'does. The scan replaced only the matched part, so a mapped style or file mock was missing from
dependenciesand its import got adependency-not-followedwarning. Vite's aliases still replace only the part they
match. -
#92
0001eea- Test files reached through a symbolic link are read the way each runner reads them. Jasmine and Bun follow such links
and run the file once, as Vitest and Mocha do, so the file is no longer left out; Bun names it by its own path, as its
reports do. node:test runs a linked file, twice when its own path matches too, but a wildcard in its pattern doesn't
enter a linked folder. Thesymlink-ignoredwarning now names the runner in use, where it named Playwright for every
runner but Jest. -
#92
0001eea- Mocha: an absolute glob inspec, as a.mocharc.jsbuilds it withpath.join(__dirname, 'test', '**', '*.spec.js'),
runs the files it matches. The scan matched it against paths relative to the config's folder, found nothing, and
reportedno-files-matched. -
#92
0001eea- Mocha, Cypress and WebdriverIO on Mocha:this.skip()in anafterEachhook no longer marks the tests as skipped.
The test has passed by the time the hook runs, and Mocha reports it as a pass. -
#92
0001eea- Mocha: a.onlyin a project whose config setsforbid-only(orforbidOnly) gets aforbidden-onlyerror, as Mocha
stops the run before any test runs, or a warning when the setting depends on a condition, as Playwright'sforbidOnly
does. -
#92
0001eea- A.mocharc.ymlis read as js-yaml, Mocha's reader, reads it. Files that Mocha reads and the scan refused, which lost
every setting and so the files to test, are now read: a byte order mark, a comment or a%YAMLline before---, a
...at the end, quoted list items with commas, as['test/**/*.{ts,js}'], YAML's escapes in double quotes, as
\x41, and a tab or an escaped quote followed by#in quotes. A quote inside a value, as ingrep: buy 'limit # note,
no longer hides the comment after it,-a.json its own line is a value, not a list item, and what Mocha refuses is
reported rather than read: a key set twice, a tab in the indent,a: bin a value, a list inside a list, and values
that start with@,`or%.-.5is a string, as js-yaml reads it. A long line is read in linear time; one of
160 KB took 5 seconds. -
#92
0001eea- node:test and Bun: a skipped describe skips every test inside it, over the test's own todo, as node:test creates none of
them, and in Bun the outermost skipped or todo describe decides, over the describes inside it and the test's own state.
The scan took the state nearest the test, sotest.todo()indescribe.skip()was todo, and in Buntest.skip()in
describe.todo()was skipped. -
#92
0001eea- node:test: a test whose function is passed by name, astest('fills a market order', fillsMarketOrder)or
test(fillsMarketOrder), gets that function'sbodyHash, and without a title the function's name, as Node.js names it.
The scan took the function for the test's options, with anunresolved-optionwarning and no hash, or for a title it
couldn't work out. -
#92
0001eea- node:test: the scan reads thenode --testcommands of every script thetestscript runs throughnpm run,pnpm,
yarn,bun run,npm-run-all,run-sorrun-p, as in"test": "npm run test:unit && npm run test:integration".
It read only the first script that runsnode --test, and left out the files of the others without a warning. -
#92
0001eea- From Playwright 1.65,test.skip('reason'),test.fixme('reason')andtest.fail('reason')with only a string give
that string as the record'sreason, in a test body and at file or describe level, and no longer askip-without-body
warning, as Playwright 1.65 takes the string as the description. An empty string still applies nothing. Older versions
keep the old reading. -
#92
0001eea- Adependency-not-followedwarning for an import a config maps to a file that doesn't exist gives that file's path
relative to the root, as every path in the output is. It gave the absolute path, aspath.resolve()or<rootDir>
built it, so the output differed from machine to machine. -
#92
0001eea- A test or describe function chosen in place, as in(process.env.CI ? it.skip : it)('books a fill', ...)or
(process.env.CI && it.skip || it)(...), is read as one kept in a variable: only what both choices share applies. The
scan dropped these tests without a warning, for every runner but Playwright, whose case is still open. Jasmine
variables that holdxit,fit,xdescribeorfdescribe, asconst later = xit, keep thexorf, as the docs
said; their tests were dropped too. -
#92 [
0001eea](https://github.com/Huldoser/test-inventory...
v0.9.0
Minor Changes
-
#88
2d370c9- Bun 1.2.23 and newer:--framework bun, also found from a package.json script that runsbun testor a
bunfig.toml. Its version comes from.bun-version,packageManagerorengines.bun, else@types/bunor
bun-types. The scan reads Bun's globals and imports ofbun:test,@jest/globalsandvitest, which Bun rewrites;
chains of.skip,.todo,.failing,.only,.concurrent,.serialand.eachin any order, refusing the
combinations Bun refuses; the conditions.if,.skipIf,.todoIf,.failingIf,.concurrentIfand.serialIf;
options second or third, a number as the timeout or{ timeout, retry, repeats }; and.eachtitles as Bun formats
them. The files are Bun's*.test.*,*_test.*,*.spec.*and*_spec.*underbunfig.toml's[test] root, less
pathIgnorePatterns, with itsretryandconcurrentTestGlobapplied. A small TOML reader readsbunfig.toml.The oldest version a framework supports may now name a patch, as Bun's 1.2.23 does.
-
#87
ae2bd90-dependencyHashfollows imports through the config a file runs with: Vite'sresolve.aliasand Vitest's
test.alias, as an object or a list of{ find, replacement }with a name or a regex, and Jest'smoduleNameMapper,
modulePathsandmoduleDirectories, with<rootDir>. They were read from tsconfigpathsonly, so tests that
imported through such aliases hadhasUnfollowedDependenciesand a hash that missed those files. A mapping to no file
is adependency-not-followedwarning that names it. -
#83
9ef9c59- Cypress 13 and newer:--framework cypress, also found from acypresspackage or acypress.config.*file. Tests are
read as Mocha's, with Cypress's test config before the function:retries, of whichcypress runtakesrunMode,
browseras a skip condition,@cypress/grep'stags, and from Cypress 16 an error forenv, which Cypress refuses
there.this.timeout()is not read, as Cypress has only command timeouts;this.retries()in a describe and
.retries()afterit()ordescribe()are errors, as Cypress throws on them while it loads the spec. The config's
testing types are the projects,e2eandcomponent, each with itsspecPattern,excludeSpecPatternandretries.A project whose package.json lists
cypressnext to another runner, as Jest or Vitest for unit tests, now needs
--framework, as the scan asks for one whenever it finds several runners. -
#82
04e7328- Jasmine 4 and newer:--framework jasmine, also found from ajasmineorkarma-jasminepackage or a
spec/support/jasmine.*config. The scan readsdescribe,itand theirxandfforms with Jasmine's focus, a
spec without a function as pending,pending(reason)in a spec or itsbeforeEachorafterEach, from Jasmine 7
notApplicable(reason), the hooks, and a spec's timeout. The config'sspec_dirandspec_files, with!
exclusions, decide the files; without a config, as in Karma and Angular projects, the files given by glob run. A call
Jasmine refuses stops the whole run at the top level of a file, and is an error that leaves the file's tests as they
are inside a describe, which Jasmine catches. -
#81
85fb8a9- Mocha 10 and newer:--framework mocha, also found from amochapackage, a.mocharc.*file or amochakey in
package.json. The scan readsdescribe,context,it,specify, theirxforms,.onlyand.skip, a test
without a function as pending,ui: tdd'ssuiteandtest, the hooks,this.timeout(),this.retries()and
this.skip()wherethisis Mocha's, and.timeout()and.retries()afterit()anddescribe(). The config's
spec,extension,recursive,ignoreandfiledecide the files, and itstimeoutandretriesapply to every
test; a YAML config is read too. A describe without a function,it()ordescribe()without a title, and an
unknown chain such asit.concurrentare errors, as Mocha then runs no test.A project whose package.json lists
mochanext to another runner now needs--framework, as the scan asks for one
whenever it finds several runners. -
#86
1085fb7- node:test on Node.js 22 and newer:--framework node, also found from a package.json script that runsnode --test
or anode.config.json. Its version is the Node.js version the project pins in.node-version,.nvmrc, Volta's
nodeorengines.node. The scan readstest,it,describeandsuitefromnode:test, imported or required,
with.skip,.todo,.onlyand from 24.14.expectFailure, and the optionsskip,todo,only,timeout,
concurrency,expectFailureand from 24.19 and 26.2tags;t.skip()andt.todo()in a test's body; and the
hooks. The files are those the script givesnode --test, or Node.js's default patterns, with TypeScript files from
22.18.A test declared in a test's body, with
t.test()ortest(), is a subtest that node:test runs while it runs the test:
it is listed with the test's title insuitePathand the test's id in the new keyparentTestId, which isnullfor
every other test. -
#80
cae53c1- A newinvalid-fixture-argumenterror: a rest property among a Playwright function's fixture arguments, as
async ({ page, ...fixtures }) => {}in a test, hook,test.skip()condition ortest.extend()fixture written in
the test file. Playwright refuses it and runs no tests at all, so the file's tests are nownotLoadedinstead of
active. A nested rest, as({ page: { mouse, ...pointer } }), and atest.step()callback are allowed, as
Playwright allows them. -
#85
90df9aa-scan()takes asignal, anAbortSignal: the scan checks it before it starts and between files, and rejects with
the signal'sreasononce it aborts, so a server can stop a scan its client no longer waits for. -
#85
90df9aa- A Vitest.onlythatallowOnlymakes fail is aforbidden-onlydiagnostic, as for Playwright'sforbidOnly: an
error when the config setstest.allowOnlytofalse, and a warning when it is unset, as Vitest then turns it off in
CI, or depends on a condition. Vitest marks such a test failed instead of running it. -
#84
c68bac7- WebdriverIO 9 and newer:--framework webdriverio, also found from a@wdio/clipackage or awdio.conf.*file. The
config'sconfigexport, ES or CommonJS, decides the files:specs, with the nested lists that group files into one
worker, lessexclude, matched as WebdriverIO matches them. Itsframeworkdecides how the tests are read, Mocha by
default or Jasmine, withmochaOpts.timeout,retriesandui, orjasmineOpts.defaultTimeoutInterval, on every
test; Cucumber is reported, as its feature files aren't read. A number after a test's function is WebdriverIO's retry
count, and with Jasmine a second one, after the timeout. Mocha's and Jasmine's version gates follow the versions
WebdriverIO depends on. With Mocha, a call the runner refuses stops the file loading there, and the tests declared
above it still run. The config'srootDirand each capability's ownspecsandexcludeare read too.A project whose package.json lists
@wdio/clinext to another runner now needs--framework, as the scan asks for
one whenever it finds several runners.
Patch Changes
-
#85
90df9aa-expectCountcounts Playwright'sexpect.configure(...), called in place asexpect.configure({ timeout: 5_000 })(locator)
or kept in a variable asconst slowExpect = expect.configure(...); it missed both. -
#83
9ef9c59- The error for an unknownframeworkoption or--frameworkvalue names every runner the scan reads; it still named
only Playwright, Vitest and Jest. -
#89
fd4b13a---helpnames all nine runners--frameworktakes, and says which files node:test and Bun run without globs. -
#80 [
cae53c1](https://github.com/Huld...
v0.8.0
Minor Changes
-
#75
f6690bb---framework(library:framework) is now optional. Without it, the scan takes the runner the project uses: the one
whose package apackage.jsonin the root or below it lists, or whose config file is there, else one apackage.json
above the root lists. A project with several runners, or none, gets a usage error (aTypeErrorin the library) that
names what it found. -
#75
f6690bb- Jest 29 and 30:--framework jest(library:framework: 'jest') lists the tests of Jest files with the same keys as
Playwright and Vitest tests. It reads Jest's globals,fit,xit,xtest,fdescribeandxdescribeamong them,
imports andrequire()of@jest/globals, the chains Jest has, such astest.concurrent.only.each,.failingas
expectedToFail, the timeout passed third,jest.retryTimes()asretriesfor every test of the file (from 30.5,
withentireDescribe, of its describe) andwaitBeforeRetryasretryDelay, and@grouppragmas as tags, as
jest-runner-groups reads them.--expand-casestitles each case as jest-each 29 and 30 do. Calls Jest refuses, such
astest.only.concurrent,test('title')without a function or an async describe, mark the file's testsnotLoaded.Without globs, the test files come from the Jest config, read as Jest reads it:
jest.config.*, elsepackage.json,
withroots,testMatch,testRegex, the ignore patterns,moduleFileExtensions,projectsnamed by
displayName,testTimeoutandinjectGlobals, also through Jest 30.3'sdefineConfig()andmergeConfig();
without any config, Jest's defaults apply.frameworkin the output
can now bejest, an open set, soschemaVersionstays 1.The
cases-not-expandedmessage no longer names Vitest, as Jest tables can get it too.
Patch Changes
-
#75
f6690bb-require()of a local file is followed as an import is: tables, titles and other values it exports, with
module.exportsorexports.name, are read, and helper functions it exports that declare tests are followed. A
helper function a shared file imports and exports again, as anindex.jsof helpers does, is followed to where it is
written, instead of getting anunresolved-test-importerror. A helpers file may export a test function it takes from
the runner's globals, asexport const pendingTest = xit, or from the framework's module, with its modifiers. -
#75
f6690bb- A call the runner refuses, such astest.only.skip(...), that is only reached under a condition no longer marks every
test of its filenotLoaded, as the file loads unless the condition holds; the call is still reported. A test function
chosen with&&,||or??, as inconst onCi = process.env.CI && test.skip || test, is read like one chosen with
?:. In a config, a list with a spread the scan can't work out keeps the items it can. -
#75
f6690bb- A config thatrequire()s a local file, as a CommonJS config does with a shared base, now reads what that file
exports, as animportof it already did, and a JSON file, required or imported, is read as its value. -
#75
f6690bb- A table or loop gets itscaseCountwhen its length is known even if one of its values isn't, as in
[NaN, Infinity].forEach(...)or a table with a call in a row. A test or describe titled by a function or class
written in place, asdescribe(function OrderBook() {}, ...), takes its name, as the runners do. Code the parser
fails to hand over, such as a JSX name written as a Unicode escape, gets aparse-errorinstead of an
internal-error. -
#75
f6690bb-dependencyHashis faster on large projects: the files a test file and its describes reach are put together once for
all their tests, and a workspace's packages are found once, not once per folder that imports one. A scan of the Nx
repository with 17,571 tests went from 19.4 to 11.9 seconds. Hashes are unchanged.
v0.7.0
Minor Changes
-
#72
cf784f0---expand-cases(library:expandCases: true) lists each case of a.eachor.fortable and each pass of a loop
whose values the scan can work out as its own record, with the title the runner gives it. Vitest's titles follow the
rules of the project's Vitest version, 3.0 to 5:%s,%d,%i,%f,%j,%o,%O,%c,%#,%$and$name,
with values quoted and cut as that version does; they match the names Vitest 3.0, 3.1, 3.2, 4.0, 4.1 and 5.0 list.
Each case's values are bound in its callback, so titles, tags and conditions built from them are worked out per case,
and anif,?:,&&,||or??that reads nothing but them registers only the branch it takes. Loops in test
and hook bodies and loops over avarare not expanded, and a file starts expansions up to 1,000 loop passes and
describe cases.
Suites and tests have a new key,caseIndex: the case's index from 0, as%#counts, ornullwithout the option. A
table that can't be expanded stays one record with a newcases-not-expandedwarning. Without the option the output
is as before, apart fromcaseIndex: nullon every suite and test. -
#72
cf784f0- Values imported from other files of the project are now worked out: a title, tag, annotation, reason, run setting or
.eachtable built from a constant, enum or default export of another module, through re-exports,export *,
import * asand JSON files, found the same way as helper functions (relative paths, tsconfigpaths,#imports,
workspace packages). Values from installed packages are still not read, and keep their diagnostic.A test in a
for...of,for...in,forEachormaploop over values the scan can work out now hascaseCount, the
number of tests the runner registers, and notest-in-loopwarning; the warning now marks a loop the scan can't
count. Values also work out arithmetic on numbers, as in30 * 1000,?:,&&,||,??, comparisons,
Object.keys(),Object.values(),Object.entries(),JSON.stringify(),String(), and a string'stoUpperCase(),
toLowerCase()andtrim()and an array'sjoin(). A skip condition that works out to a constant, such as
side === 'short'in a helper called with'buy', now sets the state it gives instead of being kept as a condition.Code after an
ifwhose branch always returns or throws, as inif (!strategy.enabled) return;in a helper, is now
under the opposite condition, so its tests haveisInConditionand a loop around them no count. A tagged-template
table is counted as Vitest splits it: outer pipes are columns, an incomplete last row is left out, and a template
without values is one case.A test whose title was its source text and is now worked out gets a new
id, once.
Patch Changes
-
#71
bf8383f- A name destructured from a test object, as inconst { describe, beforeEach } = test, is now read as that member:
beforeEach(...)is a hook,describe(...)a describe andskip(...)a skipped test, for Playwright and Vitest,
also nested, as inconst { describe: { serial } } = test. Every such name was read astestitself, so a hook got
test-without-bodyand every test of the filenotLoaded, and the tests inside a describe were left out with
nested-testwarnings. -
#71
bf8383f- When the root and the folders above it don't have the framework, its version is now read from the shallowest
package.jsonbelow the root that declares it and holds scanned files, ascode/package.jsonin a monorepo, with
that package's lockfile or installed copy first. The version wasnullthere, so the newest rules applied: Vitest
5's, which refuse a file that callsvi.mockinside a block, made every test of such a filenotLoadedin a project
on Vitest 3.
v0.6.1
Patch Changes
-
#69
41ce74d- An import that matches a tsconfigpathspattern but none of its files, as an installed package does with
"paths": { "*": ["./src/types/*"] }, now goes on to the usual lookup, as TypeScript does. Such imports were reported
as unreadable, so every test that used a package or a built-in module such asnode:fsgot
hasUnfollowedDependencies. An@/or~/alias whose files are missing is still reported. -
#69
41ce74d- A file that only passes names on, as a barrelindex.tswithexport * from './fees'or
export { OrderTicket } from './order-ticket'does, is now in thedependenciesof the tests that import through it,
so--relatedkeeps them when the file changes. Which module a re-export points at is now part ofdependencyHash, as
an import's already was, so the hash of a test that imports through a re-export changes once. -
#69
41ce74d- An imported file that isn't text, such asimport logo from './logo.png', is now taken by its bytes in
dependencyHash. It was read as text, where every byte that isn't UTF-8 reads the same, so two different images could
give the same hash. -
#69
41ce74d- A<script>block in a Vue or Svelte component whosetypeisn't JavaScript, such as
<script type="application/ld+json">in<svelte:head>, is no longer read as the component's code. It made the
component unreadable, so the modules its real script imports were missing fromdependencies. -
#68
fa9b97a-dependencyHashnow follows what a Vue or Svelte single-file component imports, also the components and helpers only
its template uses, so a change to a child component changes the hash of the tests that mount its parent. A component
whose script doesn't parse is still taken by its text, and its tests gethasUnfollowedDependencies. -
#69
41ce74d- A file with brackets nested more than 500 deep, such as a generated fixture, now gets aparse-errorinstead of
crashing the scan. oxc-parser overflows the native stack on such a file, about 5,000 deep, and the process dies with a
segmentation fault that no error handling can catch, so no inventory was written. -
#69
41ce74d-expectCountnow countsexpect.element(), the assertion of Vitest browser mode, so a browser test that checks the
page only withawait expect.element(locator).toBeVisible()no longer looks like a test without assertions. -
#69
41ce74d- An import written with a.jsxextension now finds the.tsxfile it refers to, as.jsalready found.ts, so
import { OrderHeader } from './OrderHeader.jsx'is followed instead of marking the test with
hasUnfollowedDependencies. -
#69
41ce74d- From Playwright 1.57, the config'stagis now read: every test gets it first in itstags, and a project'sgrepor
grepInvertmatches it, so a project withgrepInvert: /@nightly/in a config withtag: '@nightly'no longer runs
the tests. When the scan can't work out thetag, as forprocess.env.CI_ENVIRONMENT_NAME, it gets a
config-value-unknownwarning, and the tests of a project with agrepgetprojects: null. -
#69
41ce74d- From Playwright 1.64, a project withdefault: falseis no longer listed in a test'sprojects, as Playwright runs it
only with--project, unless a project that runs lists it independenciesorteardown. Adefaultthe scan can't
work out gets aconfig-value-unknownwarning, and the tests it may run getprojects: null. -
#69
41ce74d- Playwright'sdefineConfig(base, config)is now merged as Playwright merges it: a project ofconfigmerges into the
project ofbasewith the same name instead of replacing all ofbase's projects, andexpect,useandbuild
merge key by key. A setup project from a base config is no longer lost, and anexpect.toHaveScreenshot.pathTemplate
from the base still marks the tests that compare screenshots withhasUnfollowedDependencies. -
#69
41ce74d- A Vitestretryobject in a test's or describe's options before Vitest 4.1 now gets anunresolved-optionwarning
andretries: null. Vitest 4.0 and 3.2 never run such a test; the scan used to ignore the object and give the
config's retry count instead. -
#69
41ce74d- A Vitest test's ownskip,only,todoorfailsoption now replaces the one its tags set, as Vitest does, so
test('title', { tags: ['flaky'], skip: false }, fn)is active instead of skipped, and a conditionalskipreplaces
the tag's unconditional one. -
#69
41ce74d- An import that starts with@/or~/, as a Viteresolve.aliasallows, now gives the test
hasUnfollowedDependenciesand adependency-not-followedwarning when no tsconfigpathsdefine it. It was taken for
an installed package, so the aliased file was missing fromdependencieswithout a sign, and--relatedleft the test
out when that file changed. -
#69
41ce74d- Vitest 5 tests follow the option rules of Vitest 5.0.5: the last of.skip,skipIf()andrunIf()on a test
decides its skip, sotest.skip.skipIf(false)is active, and askipIf()orrunIf()replaces the skip of a tag or of
the options a describe passes down. An option set toundefined, as intest.skip('title', { skip: undefined }, fn),
no longer undoes the chain or a tag. -
#69
41ce74d- In Vitest 5, the projects of a config that another config lists inprojectsare named inside that config's name, as
Vitest names them: theunitproject ofapps/web/vitest.config.ts, namedweb, isweb (unit). -
#69
41ce74d- A Vitest project without atest.namenow has the name Vitest gives it, inprojectsand inconfigs: thenamein
the package.json of its folder, else the folder's name, soprojects: ['packages/*']names its projects
@trading/pricingorledgerinstead of"". An inline project without a name is named after its place among the
inline projects, as0, and in Vitest 5 no longer takes the name of the config it extends.
v0.6.0
Minor Changes
-
#61
926352f- Each test now has adependencyHashof everything it runs in the project, beside the unchangedbodyHash: its own call
with its options, the hooks,test.use()and options of its file and of every describe around it, the fixtures it,
those hooks, conditions andtest.use()values ask for, with the fixtures those ask for,autoones and overrides of
Playwright's own, through everyextend()andmergeTests(), the file's other top-level code, the config and the
configs it builds on, setup files, global setup and teardown, the Playwright setup projects the test runs after, and the
snapshot files and screenshots it compares against, and the functions, classes, constants and modules all of these use,
followed by scope and through imports, re-exports, barrels,require(),import()and Vitest'svi.mock()with a
fixed path, with the code each module runs when it loads. A helper that declares the test is in it with the arguments of
the call that declares it, so two calls give two hashes. Formatting and comments don't change it, nor does moving the
test. Installed packages are left out, and types too, except for type tests.dependencieslists the files that went into the hash. When the test reaches something the scan can't follow, a local
file that is missing or doesn't parse, an import with a path worked out at run time or a pattern, a value only a
declaration file describes, or a setup file the config names in a way the scan can't work out,
hasUnfollowedDependenciesistrueand the newdependency-not-followedwarning says where, once per place. -
#65
31a9bee---related <file>and therelatedfilter offilterInventory()keep the tests a change to a file can affect: those
whosedependenciesinclude it, and those that reach code the scan can't follow, which a change may affect unseen.
--related -reads the files from standard input, one per line, sogit diff --name-only origin/main... | npx test-inventory --framework playwright --related -lists the tests a pull request can affect. Paths are taken from the
current folder, as git writes them, also when--rootis a folder in the repository.
v0.5.0
Minor Changes
-
#51
acec7e7- Each file record has a newconfigkey: the config the file uses, as the runner started at the root would pick it.
That is the outermost config at or above the file that runs it, and for Vitestprojectsthe project that does,
read from Playwright'stestDir,testMatch,testIgnoreand.gitignorefiles, and from Vitest'sinclude,
exclude,includeSource,typecheck.includeandbenchmark.includewith each version's defaults. Before, the
nearest config was taken, which is wrong for a root config whoseincludecovers packages that have their own
vite.config.ts. A file with tests that no config runs gets the newfile-not-runwarning.The globals check follows the same choice, so a test in a folder project without a config of its own gets Vitest's
defaults, and a test the root config runs takes the root'stest.globals. Files named bybenchmark.includeare
markedisBenchmark, in place of the default*.bench.*and*.benchmark.*names. The config reader now reads
regular expressions and paths built from__dirname,__filenameorimport.metawithpath.join(),
path.resolve(),path.dirname(),fileURLToPath()andnew URL(). -
#50
3e55445- The output lists the configs the scanned files use in a new top-levelconfigskey, and asconfiglines in JSON
Lines. A file uses the nearestplaywright.config.*,vitest.config.*orvite.config.*in its folder or a folder
above, up to the root, as the runner started in that folder would. A config is read as code, never run, andextends
lists the files it takes settings from through imports, such as a shared base config.Vitest's globals now come from
test.globalsin the config a file uses, read throughdefineConfig(),
mergeConfig(), spreads, constants and imported base configs. Before, anyglobals: truein a Vitest or Vite config
in the file's folder or a folder above counted, also one Vitest doesn't read for the file, as in avite.config.ts
next to avitest.config.ts. Soglobals-not-enabledcan now appear where it didn't, and go away where a base config
turns globals on. Atest.globalsthe scan can't work out without running the config, and a config it can't read,
get the newconfig-value-unknownwarning. -
#55
a714612- Run settings now come also from the config a file uses: Playwright'stimeout,retriesandrepeatEach, and
Vitest'stestTimeout,retryandrepeats, where the file sets none. NewtimeoutSource,retriesSourceandrepeatsSource
keys say where each value comes from:test,suite,fileorconfig, ornullwhen nothing sets it. A test
takes the settings of the projects that run it, after theirgrep. When those projects disagree, the config sets the
value under a condition, as inprocess.env.CI ? 2 : 0, or the scan can't work out the projects, the value isnull
with its sourceconfig. For a value under a condition,timeoutConfigText,retriesConfigTextand
repeatsConfigTexthold the config's text for it, soretries: process.env.CI ? 2 : 0reads as written. Playwright'sfullyParalleland Vitest'ssequence.concurrentmake tests
isParallelwhere the file sets no mode, when every project that runs the test sets it.A
.onlyin a Playwright file whose config setsforbidOnlygets the newforbidden-onlyerror, since the run then
fails before any test runs. WhenforbidOnlydepends on a condition, as in!!process.env.CI, it is a warning that
quotes the condition. -
#59
aeb3eb1- Vitest tags the config defines intest.tagsnow apply to the tests that carry them, as Vitest applies them. Their
skip,todo,failsandonlyare merged with the test's own and those a describe passes down, and Vitest's order,
onlyoverskipovertodo, gives the state, with the newstateSourcevalueconfigwhen a tag sets it. Their
concurrent,timeout,retry,repeatsandmetaset those keys where the test sets none: from Vitest 5 over a
describe's options, and in Vitest 4.1 under them. The lowestprioritywins between tags, and a Vitest 5 project's
owntagsreplace those of the config it extends.A tag the config doesn't define fails the file in Vitest unless
strictTagsis off, also when there is no config, so
it now gets the newundefined-tagerror, and the file's tests arenotLoaded; in a function or under a condition it
is a warning, as that code may not run. Theconfig-may-change-statewarning now shows only when
the scan can't work out the config's tags. -
#54
c610789- Each test record has a newprojectskey: the names of the projects that run the test, of the config its file uses.
For Playwright, those whosetestDir,testMatchandtestIgnoreinclude the file, less those whosegrepor
grepInvertleaves the test's title and tags out; for Vitest, those whose files include it, with each browser
instance as a project, named as Vitest names it, such asunit (chromium). It is[]when no project runs the test,
andnullwithout a config or when the scan can't tell. Config records list their projects inprojects, each with
itsname,testDirand Playwright'sdependencies. -
#53
b9471ec- Glob patterns are optional, inscan()and on the command line: without them, the test files are those the
Playwright or Vitest configs in the root and the folders below it run, each with the config it uses. A config whose
files the scan can't work out gets aconfig-value-unknownwarning that says to give patterns, and a scan without
patterns and without a config says so inno-files-matched. An empty list of patterns is still an error.