vitest 0.0.90 → 0.0.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/vitest.mjs CHANGED
@@ -2,12 +2,16 @@
2
2
 
3
3
  import { fileURLToPath } from 'url'
4
4
  import { resolve } from 'path'
5
- import { checkPeerDependency } from '../dist/utils.js'
5
+ import { ensurePackageInstalled } from '../dist/utils.js'
6
6
 
7
7
  const argv = process.argv.slice(2)
8
8
 
9
+ if (!await ensurePackageInstalled('vite'))
10
+ process.exit(1)
11
+
9
12
  if (argv.includes('--coverage')) {
10
- checkPeerDependency('c8/bin/c8.js')
13
+ if (!await ensurePackageInstalled('c8'))
14
+ process.exit(1)
11
15
  const filename = fileURLToPath(import.meta.url)
12
16
  const entry = resolve(filename, '../../dist/cli.js')
13
17
  process.argv.splice(2, 0, process.argv[0], entry)
package/dist/cli.js CHANGED
@@ -1,23 +1,24 @@
1
- import readline from 'readline';
1
+ import require$$0 from 'readline';
2
2
  import { EventEmitter } from 'events';
3
- import { c } from './utils-385e2d09.js';
4
- import { c as createVitest } from './index-733e7378.js';
5
- import 'module';
3
+ import { c, e as ensurePackageInstalled } from './utils-576876dc.js';
4
+ import { c as createVitest } from './index-de606d4a.js';
6
5
  import 'tty';
6
+ import 'local-pkg';
7
7
  import 'path';
8
8
  import 'vite';
9
9
  import 'process';
10
10
  import 'fs';
11
- import './constants-adef7ffb.js';
11
+ import 'fast-glob';
12
+ import 'util';
13
+ import './constants-9cfa4d7b.js';
12
14
  import 'url';
13
15
  import 'perf_hooks';
14
- import './error-309196c9.js';
16
+ import './error-81292c96.js';
15
17
  import 'source-map';
18
+ import './index-5cc247ff.js';
16
19
  import 'assert';
17
20
  import 'worker_threads';
18
21
  import 'piscina';
19
- import 'fast-glob';
20
- import 'micromatch';
21
22
 
22
23
  function toArr(any) {
23
24
  return any == null ? [] : Array.isArray(any) ? any : [any];
@@ -632,7 +633,7 @@ class CAC extends EventEmitter {
632
633
 
633
634
  const cac = (name = "") => new CAC(name);
634
635
 
635
- var version = "0.0.90";
636
+ var version = "0.0.94";
636
637
 
637
638
  const cli = cac("vitest");
638
639
  cli.version(version).option("-r, --root <path>", "root path").option("-c, --config <path>", "path to config file").option("-u, --update", "update snapshot").option("-w, --watch", "watch mode").option("-o, --open", "open Vitest UI").option("--api", "listen to port and serve API").option("--threads", "enabled threads", { default: true }).option("--silent", "silent").option("--global", "inject apis globally").option("--dom", "mock browser api with happy-dom").option("--environment <env>", "runner environment", {
@@ -653,12 +654,18 @@ async function run(cliFilters, options) {
653
654
  process.env.NODE_ENV = "test";
654
655
  if (!options.silent) {
655
656
  console.log(c.magenta(c.bold("\nVitest is in closed beta exclusively for Sponsors")));
656
- console.log(c.yellow("Learn more at https://vitest.dev\n"));
657
+ console.log(c.yellow("Learn more at https://vitest.dev"));
657
658
  }
658
659
  const ctx = await createVitest(options);
659
- process.__vitest__ = ctx;
660
660
  process.chdir(ctx.config.root);
661
661
  registerConsoleShortcuts(ctx);
662
+ if (ctx.config.environment && ctx.config.environment !== "node") {
663
+ if (!await ensurePackageInstalled(ctx.config.environment))
664
+ process.exit(1);
665
+ }
666
+ ctx.onServerRestarted(() => {
667
+ ctx.start(cliFilters);
668
+ });
662
669
  try {
663
670
  await ctx.start(cliFilters);
664
671
  } catch (e) {
@@ -671,7 +678,7 @@ async function run(cliFilters, options) {
671
678
  }
672
679
  function registerConsoleShortcuts(ctx) {
673
680
  if (process.stdin.isTTY) {
674
- readline.emitKeypressEvents(process.stdin);
681
+ require$$0.emitKeypressEvents(process.stdin);
675
682
  process.stdin.setRawMode(true);
676
683
  process.stdin.on("keypress", (str) => {
677
684
  if (str === "" || str === "")
@@ -22,9 +22,8 @@ const globalApis = [
22
22
  "chai",
23
23
  "expect",
24
24
  "assert",
25
- "spy",
26
- "spyOn",
27
25
  "vitest",
26
+ "vi",
28
27
  "beforeAll",
29
28
  "afterAll",
30
29
  "beforeEach",
package/dist/entry.js CHANGED
@@ -1,3 +1,4 @@
1
+ import fs, { promises } from 'fs';
1
2
  import { Console } from 'console';
2
3
  import { Writable } from 'stream';
3
4
  import { importModule } from 'local-pkg';
@@ -5,13 +6,12 @@ import chai, { expect, util } from 'chai';
5
6
  import Subset from 'chai-subset';
6
7
  import path, { basename } from 'path';
7
8
  import { r as rpc, s as send } from './rpc-7de86f29.js';
8
- import { g as getNames, c as c$1, t as toArray, i as interpretOnlyMode, p as partitionSuiteChildren, d as hasTests, h as hasFailed } from './utils-385e2d09.js';
9
- import fs from 'fs';
10
- import { u as unifiedDiff } from './error-309196c9.js';
9
+ import { g as getNames, c as c$1, t as toArray, i as interpretOnlyMode, p as partitionSuiteChildren, f as hasTests, h as hasFailed } from './utils-576876dc.js';
10
+ import { u as unifiedDiff } from './error-81292c96.js';
11
11
  import { performance } from 'perf_hooks';
12
12
  import { b as setHooks, c as createSuiteHooks, e as clearContext, f as defaultSuite, h as context, j as getHooks, k as getFn } from './suite-b8c6cb53.js';
13
13
  import { n as nanoid } from './index-9e71c815.js';
14
- import 'module';
14
+ import { format as format$1 } from 'util';
15
15
  import 'tty';
16
16
  import 'source-map';
17
17
 
@@ -3414,7 +3414,7 @@ const JestChaiExpect = (chai, utils) => {
3414
3414
  const expected = args[0];
3415
3415
  const actual = utils.flag(this, "object");
3416
3416
  if (hasAsymmetric(expected)) {
3417
- this.assert(equals(actual, expected, void 0, true), "not match with #{this}", "should not match with #{this}", true);
3417
+ this.assert(equals(actual, expected, void 0, true), "not match with #{act}", "should not match with #{act}", actual, expected);
3418
3418
  } else {
3419
3419
  _super.apply(this, args);
3420
3420
  }
@@ -3425,7 +3425,7 @@ const JestChaiExpect = (chai, utils) => {
3425
3425
  const expected = args[0];
3426
3426
  const actual = utils.flag(this, "object");
3427
3427
  if (hasAsymmetric(expected)) {
3428
- this.assert(equals(actual, expected), "not match with #{this}", "should not match with #{this}", true);
3428
+ this.assert(equals(actual, expected), "not match with #{exp}", "should not match with #{exp}", actual, expected);
3429
3429
  } else {
3430
3430
  _super.apply(this, args);
3431
3431
  }
@@ -3438,7 +3438,7 @@ const JestChaiExpect = (chai, utils) => {
3438
3438
  return this.chaiEqual(expected);
3439
3439
  });
3440
3440
  def("toBe", function(expected) {
3441
- return this.chaiEqual(expected);
3441
+ return this.equal(expected);
3442
3442
  });
3443
3443
  def("toMatchObject", function(expected) {
3444
3444
  return this.containSubset(expected);
@@ -3535,7 +3535,7 @@ const JestChaiExpect = (chai, utils) => {
3535
3535
  def(["toHaveBeenCalledWith", "toBeCalledWith"], function(...args) {
3536
3536
  const spy = getSpy(this);
3537
3537
  const pass = spy.calls.some((callArg) => equals(callArg, args));
3538
- return this.assert(pass, "expected spy to be called with arguments: #{exp}", "expected spy to not be called with arguments: #{exp}", args);
3538
+ return this.assert(pass, "expected spy to be called with arguments: #{exp}", "expected spy to not be called with arguments: #{exp}", args, spy.calls);
3539
3539
  });
3540
3540
  const ordinalOf = (i) => {
3541
3541
  const j = i % 10;
@@ -3628,8 +3628,138 @@ class StringContaining extends AsymmetricMatcher {
3628
3628
  return "string";
3629
3629
  }
3630
3630
  }
3631
+ class Anything extends AsymmetricMatcher {
3632
+ asymmetricMatch(other) {
3633
+ return other != null;
3634
+ }
3635
+ toString() {
3636
+ return "Anything";
3637
+ }
3638
+ toAsymmetricMatcher() {
3639
+ return "Anything";
3640
+ }
3641
+ }
3642
+ class ObjectContaining extends AsymmetricMatcher {
3643
+ constructor(sample, inverse = false) {
3644
+ super(sample, inverse);
3645
+ }
3646
+ getPrototype(obj) {
3647
+ if (Object.getPrototypeOf)
3648
+ return Object.getPrototypeOf(obj);
3649
+ if (obj.constructor.prototype === obj)
3650
+ return null;
3651
+ return obj.constructor.prototype;
3652
+ }
3653
+ hasProperty(obj, property) {
3654
+ if (!obj)
3655
+ return false;
3656
+ if (Object.prototype.hasOwnProperty.call(obj, property))
3657
+ return true;
3658
+ return this.hasProperty(this.getPrototype(obj), property);
3659
+ }
3660
+ asymmetricMatch(other) {
3661
+ if (typeof this.sample !== "object") {
3662
+ throw new TypeError(`You must provide an object to ${this.toString()}, not '${typeof this.sample}'.`);
3663
+ }
3664
+ let result = true;
3665
+ for (const property in this.sample) {
3666
+ if (!this.hasProperty(other, property) || !equals(this.sample[property], other[property])) {
3667
+ result = false;
3668
+ break;
3669
+ }
3670
+ }
3671
+ return this.inverse ? !result : result;
3672
+ }
3673
+ toString() {
3674
+ return `Object${this.inverse ? "Not" : ""}Containing`;
3675
+ }
3676
+ getExpectedType() {
3677
+ return "object";
3678
+ }
3679
+ }
3680
+ class ArrayContaining extends AsymmetricMatcher {
3681
+ constructor(sample, inverse = false) {
3682
+ super(sample, inverse);
3683
+ }
3684
+ asymmetricMatch(other) {
3685
+ if (!Array.isArray(this.sample)) {
3686
+ throw new TypeError(`You must provide an array to ${this.toString()}, not '${typeof this.sample}'.`);
3687
+ }
3688
+ const result = this.sample.length === 0 || Array.isArray(other) && this.sample.every((item) => other.some((another) => equals(item, another)));
3689
+ return this.inverse ? !result : result;
3690
+ }
3691
+ toString() {
3692
+ return `Array${this.inverse ? "Not" : ""}Containing`;
3693
+ }
3694
+ getExpectedType() {
3695
+ return "array";
3696
+ }
3697
+ }
3698
+ class Any extends AsymmetricMatcher {
3699
+ constructor(sample) {
3700
+ if (typeof sample === "undefined") {
3701
+ throw new TypeError("any() expects to be passed a constructor function. Please pass one or use anything() to match any object.");
3702
+ }
3703
+ super(sample);
3704
+ }
3705
+ fnNameFor(func) {
3706
+ if (func.name)
3707
+ return func.name;
3708
+ const functionToString = Function.prototype.toString;
3709
+ const matches = functionToString.call(func).match(/^(?:async)?\s*function\s*\*?\s*([\w$]+)\s*\(/);
3710
+ return matches ? matches[1] : "<anonymous>";
3711
+ }
3712
+ asymmetricMatch(other) {
3713
+ if (this.sample === String)
3714
+ return typeof other == "string" || other instanceof String;
3715
+ if (this.sample === Number)
3716
+ return typeof other == "number" || other instanceof Number;
3717
+ if (this.sample === Function)
3718
+ return typeof other == "function" || other instanceof Function;
3719
+ if (this.sample === Boolean)
3720
+ return typeof other == "boolean" || other instanceof Boolean;
3721
+ if (this.sample === BigInt)
3722
+ return typeof other == "bigint" || other instanceof BigInt;
3723
+ if (this.sample === Symbol)
3724
+ return typeof other == "symbol" || other instanceof Symbol;
3725
+ if (this.sample === Object)
3726
+ return typeof other == "object";
3727
+ return other instanceof this.sample;
3728
+ }
3729
+ toString() {
3730
+ return "Any";
3731
+ }
3732
+ getExpectedType() {
3733
+ if (this.sample === String)
3734
+ return "string";
3735
+ if (this.sample === Number)
3736
+ return "number";
3737
+ if (this.sample === Function)
3738
+ return "function";
3739
+ if (this.sample === Object)
3740
+ return "object";
3741
+ if (this.sample === Boolean)
3742
+ return "boolean";
3743
+ return this.fnNameFor(this.sample);
3744
+ }
3745
+ toAsymmetricMatcher() {
3746
+ return `Any<${this.fnNameFor(this.sample)}>`;
3747
+ }
3748
+ }
3631
3749
  const JestAsymmetricMatchers = (chai, utils) => {
3632
3750
  utils.addMethod(chai.expect, "stringContaining", (expected) => new StringContaining(expected));
3751
+ utils.addMethod(chai.expect, "anything", () => {
3752
+ return new Anything();
3753
+ });
3754
+ utils.addMethod(chai.expect, "objectContaining", (expected) => {
3755
+ return new ObjectContaining(expected);
3756
+ });
3757
+ utils.addMethod(chai.expect, "any", (expected) => {
3758
+ return new Any(expected);
3759
+ });
3760
+ utils.addMethod(chai.expect, "arrayContaining", (expected) => {
3761
+ return new ArrayContaining(expected);
3762
+ });
3633
3763
  };
3634
3764
 
3635
3765
  let installed = false;
@@ -3652,7 +3782,7 @@ async function setupGlobalEnv(config) {
3652
3782
  setupConsoleLogSpy();
3653
3783
  await setupChai();
3654
3784
  if (config.global)
3655
- (await import('./global-f3eab75a.js')).registerApiGlobally();
3785
+ (await import('./global-473089f7.js')).registerApiGlobally();
3656
3786
  }
3657
3787
  function setupConsoleLogSpy() {
3658
3788
  const stdout = new Writable({
@@ -3712,6 +3842,8 @@ function serializeError(val) {
3712
3842
  return "Promise";
3713
3843
  if (typeof Element !== "undefined" && val instanceof Element)
3714
3844
  return val.tagName;
3845
+ if (typeof val.asymmetricMatch === "function")
3846
+ return `${val.toString()} ${format$1(val.sample)}`;
3715
3847
  Object.keys(val).forEach((key) => {
3716
3848
  val[key] = serializeError(val[key]);
3717
3849
  });
@@ -3768,14 +3900,6 @@ async function collectTests(paths, config) {
3768
3900
  }
3769
3901
  const tasks = files.reduce((tasks2, file) => tasks2.concat(file.tasks), []);
3770
3902
  interpretOnlyMode(tasks);
3771
- tasks.forEach((i) => {
3772
- if (i.type === "suite") {
3773
- if (i.mode === "skip")
3774
- i.tasks.forEach((c) => c.mode === "run" && (c.mode = "skip"));
3775
- else
3776
- interpretOnlyMode(i.tasks);
3777
- }
3778
- });
3779
3903
  return files;
3780
3904
  }
3781
3905
 
@@ -3878,10 +4002,17 @@ async function startTests(paths, config) {
3878
4002
  }
3879
4003
 
3880
4004
  async function run(files, config) {
4005
+ var _a;
3881
4006
  await setupGlobalEnv(config);
3882
- await withEnv(config.environment, async () => {
3883
- await startTests(files, config);
3884
- });
4007
+ for (const file of files) {
4008
+ const code = await promises.readFile(file, "utf-8");
4009
+ const env = ((_a = code.match(/@(?:vitest|jest)-environment\s+?([\w-]+)\b/)) == null ? void 0 : _a[1]) || config.environment || "node";
4010
+ if (!["node", "jsdom", "happy-dom"].includes(env))
4011
+ throw new Error(`Unsupported environment: ${env}`);
4012
+ await withEnv(env, async () => {
4013
+ await startTests([file], config);
4014
+ });
4015
+ }
3885
4016
  }
3886
4017
 
3887
4018
  export { run };
@@ -1,6 +1,7 @@
1
1
  import { existsSync, promises } from 'fs';
2
2
  import { relative } from 'path';
3
- import { n as notNullish, c } from './utils-385e2d09.js';
3
+ import { format } from 'util';
4
+ import { d as notNullish, c } from './utils-576876dc.js';
4
5
  import { SourceMapConsumer } from 'source-map';
5
6
 
6
7
  function Diff() {}
@@ -1338,7 +1339,7 @@ function generateCodeFrame(source, indent = 0, start = 0, end, range = 2) {
1338
1339
  return res.join("\n");
1339
1340
  }
1340
1341
  function stringify(obj) {
1341
- return String(obj);
1342
+ return format(obj);
1342
1343
  }
1343
1344
  const stackFnCallRE = /at (.*) \((.+):(\d+):(\d+)\)$/;
1344
1345
  const stackBarePathRE = /at ?(.*) (.+):(\d+):(\d+)$/;
@@ -1373,35 +1374,34 @@ function unifiedDiff(actual, expected) {
1373
1374
  if (expectedLinesCount >= diffLimit)
1374
1375
  return;
1375
1376
  expectedLinesCount++;
1377
+ line = line[0] + " " + line.slice(1);
1376
1378
  const isLastLine = expectedLinesCount === diffLimit;
1377
- return indent + c.green(`${formatLine(line)} ${isLastLine ? renderTruncateMessage(indent) : ""}`);
1379
+ return indent + c.red(`${formatLine(line)} ${isLastLine ? renderTruncateMessage(indent) : ""}`);
1378
1380
  }
1379
1381
  if (line[0] === "-") {
1380
1382
  if (actualLinesCount >= diffLimit)
1381
1383
  return;
1382
1384
  actualLinesCount++;
1385
+ line = line[0] + " " + line.slice(1);
1383
1386
  const isLastLine = actualLinesCount === diffLimit;
1384
- return indent + c.red(`${formatLine(line)} ${isLastLine ? renderTruncateMessage(indent) : ""}`);
1387
+ return indent + c.green(`${formatLine(line)} ${isLastLine ? renderTruncateMessage(indent) : ""}`);
1385
1388
  }
1386
1389
  if (line.match(/@@/))
1387
1390
  return "--";
1388
1391
  if (line.match(/\\ No newline/))
1389
1392
  return null;
1390
- return indent + line;
1393
+ return indent + " " + line;
1391
1394
  }
1392
1395
  const msg = createPatch("string", actual, expected);
1393
1396
  const lines = msg.split("\n").splice(5);
1394
1397
  return `
1395
- ${indent}${c.red("- actual")}
1396
- ${indent}${c.green("+ expected")}
1398
+ ${indent}${c.green("- expected")}
1399
+ ${indent}${c.red("+ actual")}
1397
1400
 
1398
1401
  ${lines.map(cleanUp).filter(notBlank).join("\n")}`;
1399
1402
  }
1400
1403
  function formatLine(line) {
1401
- const lineLimitLength = 50;
1402
- if (line.length > lineLimitLength)
1403
- return `${line.slice(0, lineLimitLength)} ${c.dim("[...truncated]")}`;
1404
- return line;
1404
+ return cliTruncate(line, (process.stdout.columns || 40) - 1);
1405
1405
  }
1406
1406
  function renderTruncateMessage(indent) {
1407
1407
  return `
@@ -1,5 +1,5 @@
1
- import { g as globalApis } from './constants-adef7ffb.js';
2
- import { i as index } from './index-722fb5a5.js';
1
+ import { g as globalApis } from './constants-9cfa4d7b.js';
2
+ import { i as index } from './index-368448f4.js';
3
3
  import 'path';
4
4
  import 'url';
5
5
  import './suite-b8c6cb53.js';