@vitest/expect 4.0.0-beta.1 → 4.0.0-beta.11

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021-Present Vitest Team
3
+ Copyright (c) 2021-Present VoidZero Inc. and Vitest contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/index.d.ts CHANGED
@@ -1,18 +1,19 @@
1
1
  import { MockInstance } from '@vitest/spy';
2
- import { stringify, Constructable } from '@vitest/utils';
2
+ import { Constructable } from '@vitest/utils';
3
3
  import { Formatter } from 'tinyrainbow';
4
4
  import { diff, printDiffOrStringify } from '@vitest/utils/diff';
5
5
  export { DiffOptions } from '@vitest/utils/diff';
6
+ import { stringify } from '@vitest/utils/display';
7
+ import * as chai from 'chai';
8
+ export { chai };
6
9
 
7
10
  declare const MATCHERS_OBJECT: unique symbol;
8
11
  declare const JEST_MATCHERS_OBJECT: unique symbol;
9
12
  declare const GLOBAL_EXPECT: unique symbol;
10
13
  declare const ASYMMETRIC_MATCHERS_OBJECT: unique symbol;
11
14
 
12
- /* eslint-disable unicorn/no-instanceof-builtins -- we check both */
13
-
14
15
  interface AsymmetricMatcherInterface {
15
- asymmetricMatch: (other: unknown) => boolean;
16
+ asymmetricMatch: (other: unknown, customTesters?: Array<Tester>) => boolean;
16
17
  toString: () => string;
17
18
  getExpectedType?: () => string;
18
19
  toAsymmetricMatcher?: () => string;
@@ -23,11 +24,10 @@ declare abstract class AsymmetricMatcher<
23
24
  > implements AsymmetricMatcherInterface {
24
25
  protected sample: T;
25
26
  protected inverse: boolean;
26
- // should have "jest" to be compatible with its ecosystem
27
27
  $$typeof: symbol;
28
28
  constructor(sample: T, inverse?: boolean);
29
29
  protected getMatcherContext(expect?: Chai.ExpectStatic): State;
30
- abstract asymmetricMatch(other: unknown): boolean;
30
+ abstract asymmetricMatch(other: unknown, customTesters?: Array<Tester>): boolean;
31
31
  abstract toString(): string;
32
32
  getExpectedType?(): string;
33
33
  toAsymmetricMatcher?(): string;
@@ -43,17 +43,18 @@ declare class Anything extends AsymmetricMatcher<void> {
43
43
  toString(): string;
44
44
  toAsymmetricMatcher(): string;
45
45
  }
46
- declare class ObjectContaining extends AsymmetricMatcher<Record<string, unknown>> {
46
+ declare class ObjectContaining extends AsymmetricMatcher<Record<string | symbol | number, unknown>> {
47
47
  constructor(sample: Record<string, unknown>, inverse?: boolean);
48
48
  getPrototype(obj: object): any;
49
- hasProperty(obj: object | null, property: string): boolean;
50
- asymmetricMatch(other: any): boolean;
49
+ hasProperty(obj: object | null, property: string | symbol): boolean;
50
+ getProperties(obj: object): (string | symbol)[];
51
+ asymmetricMatch(other: any, customTesters?: Array<Tester>): boolean;
51
52
  toString(): string;
52
53
  getExpectedType(): string;
53
54
  }
54
55
  declare class ArrayContaining<T = unknown> extends AsymmetricMatcher<Array<T>> {
55
56
  constructor(sample: Array<T>, inverse?: boolean);
56
- asymmetricMatch(other: Array<T>): boolean;
57
+ asymmetricMatch(other: Array<T>, customTesters?: Array<Tester>): boolean;
57
58
  toString(): string;
58
59
  getExpectedType(): string;
59
60
  }
@@ -77,17 +78,17 @@ declare function matcherHint(matcherName: string, received?: string, expected?:
77
78
  declare function printReceived(object: unknown): string;
78
79
  declare function printExpected(value: unknown): string;
79
80
  declare function getMatcherUtils(): {
80
- EXPECTED_COLOR: Formatter
81
- RECEIVED_COLOR: Formatter
82
- INVERTED_COLOR: Formatter
83
- BOLD_WEIGHT: Formatter
84
- DIM_COLOR: Formatter
85
- diff: typeof diff
86
- matcherHint: typeof matcherHint
87
- printReceived: typeof printReceived
88
- printExpected: typeof printExpected
89
- printDiffOrStringify: typeof printDiffOrStringify
90
- printWithType: typeof printWithType
81
+ EXPECTED_COLOR: Formatter;
82
+ RECEIVED_COLOR: Formatter;
83
+ INVERTED_COLOR: Formatter;
84
+ BOLD_WEIGHT: Formatter;
85
+ DIM_COLOR: Formatter;
86
+ diff: typeof diff;
87
+ matcherHint: typeof matcherHint;
88
+ printReceived: typeof printReceived;
89
+ printExpected: typeof printExpected;
90
+ printDiffOrStringify: typeof printDiffOrStringify;
91
+ printWithType: typeof printWithType;
91
92
  };
92
93
  declare function printWithType<T>(name: string, value: T, print: (value: T) => string): string;
93
94
  declare function addCustomEqualityTesters(newTesters: Array<Tester>): void;
@@ -129,16 +130,14 @@ interface MatcherState {
129
130
  isExpectingAssertions?: boolean;
130
131
  isExpectingAssertionsError?: Error | null;
131
132
  isNot: boolean;
132
- // environment: VitestEnvironment
133
133
  promise: string;
134
- // snapshotState: SnapshotState
135
134
  suppressedErrors: Array<Error>;
136
135
  testPath?: string;
137
136
  utils: ReturnType<typeof getMatcherUtils> & {
138
- diff: typeof diff
139
- stringify: typeof stringify
140
- iterableEquality: Tester
141
- subsetEquality: Tester
137
+ diff: typeof diff;
138
+ stringify: typeof stringify;
139
+ iterableEquality: Tester;
140
+ subsetEquality: Tester;
142
141
  };
143
142
  soft?: boolean;
144
143
  poll?: boolean;
@@ -157,9 +156,6 @@ interface RawMatcherFn<
157
156
  > {
158
157
  (this: T, received: any, ...expected: E): ExpectationResult;
159
158
  }
160
- // Allow unused `T` to preserve its name for extensions.
161
- // Type parameter names must be identical when extending those types.
162
- // eslint-disable-next-line
163
159
  interface Matchers<T = any> {}
164
160
  type MatchersObject<T extends MatcherState = MatcherState> = Record<string, RawMatcherFn<T>> & ThisType<T> & { [K in keyof Matchers<T>]? : RawMatcherFn<T, Parameters<Matchers<T>[K]>> };
165
161
  interface ExpectStatic extends Chai.ExpectStatic, Matchers, AsymmetricMatchersContaining {
@@ -366,6 +362,13 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
366
362
  */
367
363
  toBeNull: () => void;
368
364
  /**
365
+ * Used to check that a variable is nullable (null or undefined).
366
+ *
367
+ * @example
368
+ * expect(value).toBeNullable();
369
+ */
370
+ toBeNullable: () => void;
371
+ /**
369
372
  * Ensure that a variable is not undefined.
370
373
  *
371
374
  * @example
@@ -736,52 +739,22 @@ interface Assertion<T = any> extends VitestAssertion<Chai.Assertion, T>, JestAss
736
739
  rejects: PromisifyAssertion<T>;
737
740
  }
738
741
  declare global {
739
- // support augmenting jest.Matchers by other libraries
740
- // eslint-disable-next-line ts/no-namespace
741
742
  namespace jest {
742
- // eslint-disable-next-line unused-imports/no-unused-vars, ts/no-empty-object-type
743
- interface Matchers<
743
+ interface Matchers<
744
744
  R,
745
745
  T = {}
746
746
  > {}
747
747
  }
748
748
  }
749
749
 
750
- // selectively ported from https://github.com/jest-community/jest-extended
751
750
  declare const customMatchers: MatchersObject;
752
751
 
753
- // Jest Expect Compact
754
752
  declare const JestChaiExpect: ChaiPlugin;
755
753
 
756
754
  declare const JestExtend: ChaiPlugin;
757
755
 
758
- /*
759
- Copyright (c) 2008-2016 Pivotal Labs
760
-
761
- Permission is hereby granted, free of charge, to any person obtaining
762
- a copy of this software and associated documentation files (the
763
- "Software"), to deal in the Software without restriction, including
764
- without limitation the rights to use, copy, modify, merge, publish,
765
- distribute, sublicense, and/or sell copies of the Software, and to
766
- permit persons to whom the Software is furnished to do so, subject to
767
- the following conditions:
768
-
769
- The above copyright notice and this permission notice shall be
770
- included in all copies or substantial portions of the Software.
771
-
772
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
773
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
774
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
775
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
776
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
777
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
778
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
779
-
780
- */
781
-
782
- // Extracted out of jasmine 2.5.2
783
756
  declare function equals(a: unknown, b: unknown, customTesters?: Array<Tester>, strictCheck?: boolean): boolean;
784
- declare function isAsymmetric(obj: any): boolean;
757
+ declare function isAsymmetric(obj: any): obj is AsymmetricMatcher<any>;
785
758
  declare function hasAsymmetric(obj: any, seen?: Set<any>): boolean;
786
759
  declare function isA(typeName: string, value: unknown): boolean;
787
760
  declare function fnNameFor(func: Function): string;
@@ -797,8 +770,8 @@ declare function generateToBeMessage(deepEqualityName: string, expected?: string
797
770
  declare function pluralize(word: string, count: number): string;
798
771
  declare function getObjectKeys(object: object): Array<string | symbol>;
799
772
  declare function getObjectSubset(object: any, subset: any, customTesters: Array<Tester>): {
800
- subset: any
801
- stripped: number
773
+ subset: any;
774
+ stripped: number;
802
775
  };
803
776
 
804
777
  declare function getState<State extends MatcherState = MatcherState>(expect: ExpectStatic): State;
package/dist/index.js CHANGED
@@ -1,9 +1,12 @@
1
- import { getType, stringify, isObject, noop, assertTypes } from '@vitest/utils';
2
1
  import { printDiffOrStringify, diff } from '@vitest/utils/diff';
2
+ import { stringify } from '@vitest/utils/display';
3
+ import { getType, isObject, noop, assertTypes } from '@vitest/utils/helpers';
3
4
  import c from 'tinyrainbow';
4
5
  import { isMockFunction } from '@vitest/spy';
5
6
  import { processError } from '@vitest/utils/error';
6
7
  import { use, util } from 'chai';
8
+ import * as chai from 'chai';
9
+ export { chai };
7
10
 
8
11
  const MATCHERS_OBJECT = Symbol.for("matchers-object");
9
12
  const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object");
@@ -178,24 +181,24 @@ function hasAsymmetric(obj, seen = new Set()) {
178
181
  }
179
182
  return false;
180
183
  }
181
- function asymmetricMatch(a, b) {
184
+ function asymmetricMatch(a, b, customTesters) {
182
185
  const asymmetricA = isAsymmetric(a);
183
186
  const asymmetricB = isAsymmetric(b);
184
187
  if (asymmetricA && asymmetricB) {
185
188
  return undefined;
186
189
  }
187
190
  if (asymmetricA) {
188
- return a.asymmetricMatch(b);
191
+ return a.asymmetricMatch(b, customTesters);
189
192
  }
190
193
  if (asymmetricB) {
191
- return b.asymmetricMatch(a);
194
+ return b.asymmetricMatch(a, customTesters);
192
195
  }
193
196
  }
194
197
  // Equality function lovingly adapted from isEqual in
195
198
  // [Underscore](http://underscorejs.org)
196
199
  function eq(a, b, aStack, bStack, customTesters, hasKey) {
197
200
  let result = true;
198
- const asymmetricResult = asymmetricMatch(a, b);
201
+ const asymmetricResult = asymmetricMatch(a, b, customTesters);
199
202
  if (asymmetricResult !== undefined) {
200
203
  return asymmetricResult;
201
204
  }
@@ -339,7 +342,7 @@ function hasDefinedKey(obj, key) {
339
342
  return hasKey(obj, key) && obj[key] !== undefined;
340
343
  }
341
344
  function hasKey(obj, key) {
342
- return Object.prototype.hasOwnProperty.call(obj, key);
345
+ return Object.hasOwn(obj, key);
343
346
  }
344
347
  function isA(typeName, value) {
345
348
  return Object.prototype.toString.apply(value) === `[object ${typeName}]`;
@@ -367,7 +370,7 @@ function hasProperty(obj, property) {
367
370
  if (!obj) {
368
371
  return false;
369
372
  }
370
- if (Object.prototype.hasOwnProperty.call(obj, property)) {
373
+ if (Object.hasOwn(obj, property)) {
371
374
  return true;
372
375
  }
373
376
  return hasProperty(getPrototype(obj), property);
@@ -514,7 +517,7 @@ function hasPropertyInObject(object, key) {
514
517
  if (shouldTerminate) {
515
518
  return false;
516
519
  }
517
- return Object.prototype.hasOwnProperty.call(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
520
+ return Object.hasOwn(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
518
521
  }
519
522
  function isObjectWithKeys(a) {
520
523
  return isObject(a) && !(a instanceof Error) && !Array.isArray(a) && !(a instanceof Date);
@@ -658,7 +661,7 @@ function getObjectSubset(object, subset, customTesters) {
658
661
  };
659
662
  }
660
663
 
661
- if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) {
664
+ if (!Object.hasOwn(globalThis, MATCHERS_OBJECT)) {
662
665
  const globalState = new WeakMap();
663
666
  const matchers = Object.create(null);
664
667
  const customEqualityTesters = [];
@@ -769,19 +772,32 @@ class ObjectContaining extends AsymmetricMatcher {
769
772
  if (!obj) {
770
773
  return false;
771
774
  }
772
- if (Object.prototype.hasOwnProperty.call(obj, property)) {
775
+ if (Object.hasOwn(obj, property)) {
773
776
  return true;
774
777
  }
775
778
  return this.hasProperty(this.getPrototype(obj), property);
776
779
  }
777
- asymmetricMatch(other) {
780
+ getProperties(obj) {
781
+ return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj).filter((s) => {
782
+ var _Object$getOwnPropert;
783
+ return (_Object$getOwnPropert = Object.getOwnPropertyDescriptor(obj, s)) === null || _Object$getOwnPropert === void 0 ? void 0 : _Object$getOwnPropert.enumerable;
784
+ })];
785
+ }
786
+ asymmetricMatch(other, customTesters) {
778
787
  if (typeof this.sample !== "object") {
779
788
  throw new TypeError(`You must provide an object to ${this.toString()}, not '${typeof this.sample}'.`);
780
789
  }
781
790
  let result = true;
782
- const matcherContext = this.getMatcherContext();
783
- for (const property in this.sample) {
784
- if (!this.hasProperty(other, property) || !equals(this.sample[property], other[property], matcherContext.customTesters)) {
791
+ const properties = this.getProperties(this.sample);
792
+ for (const property of properties) {
793
+ var _Object$getOwnPropert2, _Object$getOwnPropert3;
794
+ if (!this.hasProperty(other, property)) {
795
+ result = false;
796
+ break;
797
+ }
798
+ const value = ((_Object$getOwnPropert2 = Object.getOwnPropertyDescriptor(this.sample, property)) === null || _Object$getOwnPropert2 === void 0 ? void 0 : _Object$getOwnPropert2.value) ?? this.sample[property];
799
+ const otherValue = ((_Object$getOwnPropert3 = Object.getOwnPropertyDescriptor(other, property)) === null || _Object$getOwnPropert3 === void 0 ? void 0 : _Object$getOwnPropert3.value) ?? other[property];
800
+ if (!equals(value, otherValue, customTesters)) {
785
801
  result = false;
786
802
  break;
787
803
  }
@@ -799,12 +815,11 @@ class ArrayContaining extends AsymmetricMatcher {
799
815
  constructor(sample, inverse = false) {
800
816
  super(sample, inverse);
801
817
  }
802
- asymmetricMatch(other) {
818
+ asymmetricMatch(other, customTesters) {
803
819
  if (!Array.isArray(this.sample)) {
804
820
  throw new TypeError(`You must provide an array to ${this.toString()}, not '${typeof this.sample}'.`);
805
821
  }
806
- const matcherContext = this.getMatcherContext();
807
- const result = this.sample.length === 0 || Array.isArray(other) && this.sample.every((item) => other.some((another) => equals(item, another, matcherContext.customTesters)));
822
+ const result = this.sample.length === 0 || Array.isArray(other) && this.sample.every((item) => other.some((another) => equals(item, another, customTesters)));
808
823
  return this.inverse ? !result : result;
809
824
  }
810
825
  toString() {
@@ -1241,6 +1256,10 @@ const JestChaiExpect = (chai, utils) => {
1241
1256
  const obj = utils.flag(this, "object");
1242
1257
  this.assert(obj === null, "expected #{this} to be null", "expected #{this} not to be null", null, obj);
1243
1258
  });
1259
+ def("toBeNullable", function() {
1260
+ const obj = utils.flag(this, "object");
1261
+ this.assert(obj == null, "expected #{this} to be nullish", "expected #{this} not to be nullish", null, obj);
1262
+ });
1244
1263
  def("toBeDefined", function() {
1245
1264
  const obj = utils.flag(this, "object");
1246
1265
  this.assert(typeof obj !== "undefined", "expected #{this} to be defined", "expected #{this} to be undefined", obj);
@@ -1264,7 +1283,7 @@ const JestChaiExpect = (chai, utils) => {
1264
1283
  const actual = this._obj;
1265
1284
  const [propertyName, expected] = args;
1266
1285
  const getValue = () => {
1267
- const hasOwn = Object.prototype.hasOwnProperty.call(actual, propertyName);
1286
+ const hasOwn = Object.hasOwn(actual, propertyName);
1268
1287
  if (hasOwn) {
1269
1288
  return {
1270
1289
  value: actual[propertyName],
@@ -1383,7 +1402,7 @@ const JestChaiExpect = (chai, utils) => {
1383
1402
  def(["toHaveBeenLastCalledWith", "lastCalledWith"], function(...args) {
1384
1403
  const spy = getSpy(this);
1385
1404
  const spyName = spy.getMockName();
1386
- const lastCall = spy.mock.calls[spy.mock.calls.length - 1];
1405
+ const lastCall = spy.mock.calls.at(-1);
1387
1406
  this.assert(lastCall && equalsArgumentArray(lastCall, args), `expected last "${spyName}" call to have been called with #{exp}`, `expected last "${spyName}" call to not have been called with #{exp}`, args, lastCall);
1388
1407
  });
1389
1408
  /**
@@ -1522,22 +1541,22 @@ const JestChaiExpect = (chai, utils) => {
1522
1541
  [{
1523
1542
  name: "toHaveLastResolvedWith",
1524
1543
  condition: (spy, value) => {
1525
- const result = spy.mock.settledResults[spy.mock.settledResults.length - 1];
1526
- return result && result.type === "fulfilled" && equals(result.value, value);
1544
+ const result = spy.mock.settledResults.at(-1);
1545
+ return Boolean(result && result.type === "fulfilled" && equals(result.value, value));
1527
1546
  },
1528
1547
  action: "resolve"
1529
1548
  }, {
1530
1549
  name: ["toHaveLastReturnedWith", "lastReturnedWith"],
1531
1550
  condition: (spy, value) => {
1532
- const result = spy.mock.results[spy.mock.results.length - 1];
1533
- return result && result.type === "return" && equals(result.value, value);
1551
+ const result = spy.mock.results.at(-1);
1552
+ return Boolean(result && result.type === "return" && equals(result.value, value));
1534
1553
  },
1535
1554
  action: "return"
1536
1555
  }].forEach(({ name, condition, action }) => {
1537
1556
  def(name, function(value) {
1538
1557
  const spy = getSpy(this);
1539
1558
  const results = action === "return" ? spy.mock.results : spy.mock.settledResults;
1540
- const result = results[results.length - 1];
1559
+ const result = results.at(-1);
1541
1560
  const spyName = spy.getMockName();
1542
1561
  this.assert(condition(spy, value), `expected last "${spyName}" call to ${action} #{exp}`, `expected last "${spyName}" call to not ${action} #{exp}`, value, result === null || result === void 0 ? void 0 : result.value);
1543
1562
  });
@@ -1695,6 +1714,7 @@ function getMatcherState(assertion, expect) {
1695
1714
  const obj = assertion._obj;
1696
1715
  const isNot = util.flag(assertion, "negate");
1697
1716
  const promise = util.flag(assertion, "promise") || "";
1717
+ const customMessage = util.flag(assertion, "message");
1698
1718
  const jestUtils = {
1699
1719
  ...getMatcherUtils(),
1700
1720
  diff,
@@ -1716,7 +1736,8 @@ function getMatcherState(assertion, expect) {
1716
1736
  return {
1717
1737
  state: matcherState,
1718
1738
  isNot,
1719
- obj
1739
+ obj,
1740
+ customMessage
1720
1741
  };
1721
1742
  }
1722
1743
  class JestExtendError extends Error {
@@ -1730,19 +1751,21 @@ function JestExtendPlugin(c, expect, matchers) {
1730
1751
  return (_, utils) => {
1731
1752
  Object.entries(matchers).forEach(([expectAssertionName, expectAssertion]) => {
1732
1753
  function expectWrapper(...args) {
1733
- const { state, isNot, obj } = getMatcherState(this, expect);
1754
+ const { state, isNot, obj, customMessage } = getMatcherState(this, expect);
1734
1755
  const result = expectAssertion.call(state, obj, ...args);
1735
1756
  if (result && typeof result === "object" && typeof result.then === "function") {
1736
1757
  const thenable = result;
1737
1758
  return thenable.then(({ pass, message, actual, expected }) => {
1738
1759
  if (pass && isNot || !pass && !isNot) {
1739
- throw new JestExtendError(message(), actual, expected);
1760
+ const errorMessage = customMessage != null ? customMessage : message();
1761
+ throw new JestExtendError(errorMessage, actual, expected);
1740
1762
  }
1741
1763
  });
1742
1764
  }
1743
1765
  const { pass, message, actual, expected } = result;
1744
1766
  if (pass && isNot || !pass && !isNot) {
1745
- throw new JestExtendError(message(), actual, expected);
1767
+ const errorMessage = customMessage != null ? customMessage : message();
1768
+ throw new JestExtendError(errorMessage, actual, expected);
1746
1769
  }
1747
1770
  }
1748
1771
  const softWrapper = wrapAssertion(utils, expectAssertionName, expectWrapper);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/expect",
3
3
  "type": "module",
4
- "version": "4.0.0-beta.1",
4
+ "version": "4.0.0-beta.11",
5
5
  "description": "Jest's expect matchers as a Chai plugin",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -30,14 +30,13 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@types/chai": "^5.2.2",
33
- "chai": "^5.2.0",
34
- "tinyrainbow": "^2.0.0",
35
- "@vitest/spy": "4.0.0-beta.1",
36
- "@vitest/utils": "4.0.0-beta.1"
33
+ "chai": "^6.0.1",
34
+ "tinyrainbow": "^3.0.3",
35
+ "@vitest/spy": "4.0.0-beta.11",
36
+ "@vitest/utils": "4.0.0-beta.11"
37
37
  },
38
38
  "devDependencies": {
39
- "rollup-plugin-copy": "^3.5.0",
40
- "@vitest/runner": "4.0.0-beta.1"
39
+ "@vitest/runner": "4.0.0-beta.11"
41
40
  },
42
41
  "scripts": {
43
42
  "build": "rimraf dist && rollup -c",