diff --git a/packages/@lwc/integration-not-karma/configs/plugins/serve-integration.js b/packages/@lwc/integration-not-karma/configs/plugins/serve-integration.js
index 3864925f65..0f0a0cd1c7 100644
--- a/packages/@lwc/integration-not-karma/configs/plugins/serve-integration.js
+++ b/packages/@lwc/integration-not-karma/configs/plugins/serve-integration.js
@@ -32,12 +32,8 @@ const createRollupPlugin = (input, options) => {
enableStaticContentOptimization: !DISABLE_STATIC_CONTENT_OPTIMIZATION,
disableSyntheticShadowSupport: DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER,
apiVersion: API_VERSION,
- modules: [
- {
- // Assume `ctx.path` is a component file, e.g. modules/x/foo/foo.js
- dir: path.resolve(input, '../../..'),
- },
- ],
+ // Assume `ctx.path` is a component file, e.g. modules/x/foo/foo.js
+ modules: [{ dir: path.resolve(input, '../../..') }],
...options,
});
};
@@ -85,6 +81,7 @@ const transform = async (ctx) => {
plugins: [customLwcRollupPlugin],
external: [
+ '@vitest/spy',
'lwc',
'wire-service',
// Some helper files export functions that mutate a global state. The setup file calls
diff --git a/packages/@lwc/integration-not-karma/configs/plugins/test-hydration.js b/packages/@lwc/integration-not-karma/configs/plugins/test-hydration.js
index 96d0371034..01e8a6fa6d 100644
--- a/packages/@lwc/integration-not-karma/configs/plugins/test-hydration.js
+++ b/packages/@lwc/integration-not-karma/configs/plugins/test-hydration.js
@@ -1,5 +1,5 @@
+import { spyOn } from '@vitest/spy';
import * as LWC from 'lwc';
-import { spyConsole } from '../../helpers/console';
import { setHooks } from '../../helpers/hooks';
setHooks({ sanitizeHtmlContent: (content) => content });
@@ -8,6 +8,28 @@ function parseStringToDom(html) {
return Document.parseHTMLUnsafe(html).body.firstChild;
}
+/**
+ * A much simplified version of the spies originally used for Karma.
+ * Should probably be eventually replaced with individual spies.
+ */
+export function spyConsole() {
+ const log = spyOn(console, 'log');
+ const warn = spyOn(console, 'warn');
+ const error = spyOn(console, 'error');
+ return {
+ calls: {
+ log: log.mock.calls,
+ warn: warn.mock.calls,
+ error: error.mock.calls,
+ },
+ reset() {
+ log.mockRestore();
+ warn.mockRestore();
+ error.mockRestore();
+ },
+ };
+}
+
function appendTestTarget(ssrText) {
const div = document.createElement('div');
const testTarget = parseStringToDom(ssrText);
diff --git a/packages/@lwc/integration-not-karma/helpers/console.js b/packages/@lwc/integration-not-karma/helpers/console.js
deleted file mode 100644
index 9a52018dcb..0000000000
--- a/packages/@lwc/integration-not-karma/helpers/console.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import { spyOn } from '@vitest/spy';
-
-/**
- * A much simplified version of the spies originally used for Karma.
- * Should probably be eventually replaced with individual spies.
- */
-export function spyConsole() {
- const log = spyOn(console, 'log');
- const warn = spyOn(console, 'warn');
- const error = spyOn(console, 'error');
- return {
- calls: {
- log: log.mock.calls,
- warn: warn.mock.calls,
- error: error.mock.calls,
- },
- reset() {
- log.mockRestore();
- warn.mockRestore();
- error.mockRestore();
- },
- };
-}
diff --git a/packages/@lwc/integration-not-karma/test/api/CustomElementConstructor-getter/index.spec.js b/packages/@lwc/integration-not-karma/test/api/CustomElementConstructor-getter/index.spec.js
index 5d224c512c..6850011af9 100644
--- a/packages/@lwc/integration-not-karma/test/api/CustomElementConstructor-getter/index.spec.js
+++ b/packages/@lwc/integration-not-karma/test/api/CustomElementConstructor-getter/index.spec.js
@@ -9,7 +9,7 @@ import AttrChanged from 'x/attrChanged';
import ReflectCamel from 'x/reflectCamel';
import WithChildElmsHasSlot from 'x/withChildElmsHasSlot';
import WithChildElmsHasSlotLight from 'x/withChildElmsHasSlotLight';
-import { spyConsole } from '../../../helpers/console.js';
+import { spyOn } from '@vitest/spy';
import { USE_COMMENTS_FOR_FRAGMENT_BOOKENDS } from '../../../helpers/constants.js';
const vFragBookend = USE_COMMENTS_FOR_FRAGMENT_BOOKENDS ? '' : '';
@@ -69,19 +69,9 @@ it('should create custom element if it exists before customElements.define', ()
describe('non-empty custom element', () => {
let consoleSpy;
beforeEach(() => {
- consoleSpy = spyConsole();
+ consoleSpy = spyOn(console, 'warn').mockImplementation(() => {});
});
- afterEach(() => {
- consoleSpy.reset();
- });
-
- function expectWarnings(expectedWarnings) {
- const observedWarnings = consoleSpy.calls.warn
- .flat()
- .map((err) => (err instanceof Error ? err.message : err));
-
- expect(observedWarnings).toEqual(expectedWarnings);
- }
+ afterEach(() => consoleSpy.mockRestore());
it('should log error if non-native-shadow custom element has children', () => {
const elm = document.createElement('test-custom-element-preexisting2');
@@ -93,11 +83,11 @@ describe('non-empty custom element', () => {
class extends WithChildElms.CustomElementConstructor {}
);
if (process.env.NODE_ENV !== 'production' && !process.env.NATIVE_SHADOW) {
- expectWarnings([
- 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.',
- ]);
+ expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
+ 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.'
+ );
} else {
- expectWarnings([]);
+ expect(consoleSpy).not.toHaveBeenCalled();
}
expect(elm.shadowRoot.childNodes.length).toBe(1);
@@ -123,11 +113,11 @@ describe('non-empty custom element', () => {
);
if (process.env.NODE_ENV !== 'production') {
- expectWarnings([
- 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.',
- ]);
+ expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
+ 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.'
+ );
} else {
- expectWarnings([]);
+ expect(consoleSpy).not.toHaveBeenCalled();
}
expect(elm.innerHTML).toBe(`${vFragBookend}${vFragBookend}`);
@@ -143,11 +133,11 @@ describe('non-empty custom element', () => {
class extends WithChildElmsHasSlot.CustomElementConstructor {}
);
if (process.env.NODE_ENV !== 'production' && !process.env.NATIVE_SHADOW) {
- expectWarnings([
- 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.',
- ]);
+ expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
+ 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.'
+ );
} else {
- expectWarnings([]);
+ expect(consoleSpy).not.toHaveBeenCalled();
}
expect(elm.shadowRoot.childNodes.length).toBe(1);
@@ -174,11 +164,11 @@ describe('non-empty custom element', () => {
);
if (process.env.NODE_ENV === 'production') {
- expectWarnings([]);
+ expect(consoleSpy).not.toHaveBeenCalled();
} else {
- expectWarnings([
- 'Found an existing shadow root for the custom element "Child". Call `hydrateComponent` instead.',
- ]);
+ expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
+ 'Found an existing shadow root for the custom element "Child". Call `hydrateComponent` instead.'
+ );
}
expect(elm.shadowRoot.innerHTML).toBe('
');
});
@@ -194,11 +184,11 @@ describe('non-empty custom element', () => {
document.body.appendChild(elm);
if (process.env.NODE_ENV !== 'production' && !process.env.NATIVE_SHADOW) {
- expectWarnings([
- 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.',
- ]);
+ expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
+ 'Light DOM and synthetic shadow custom elements cannot have child nodes. Ensure the element is empty, including whitespace.'
+ );
} else {
- expectWarnings([]);
+ expect(consoleSpy).not.toHaveBeenCalled();
}
expect(elm.childNodes.length).toBe(1);
diff --git a/packages/@lwc/integration-not-karma/test/component/LightningElement.addEventListener/index.spec.js b/packages/@lwc/integration-not-karma/test/component/LightningElement.addEventListener/index.spec.js
index 2b10f0152f..2f5c7c9cdf 100644
--- a/packages/@lwc/integration-not-karma/test/component/LightningElement.addEventListener/index.spec.js
+++ b/packages/@lwc/integration-not-karma/test/component/LightningElement.addEventListener/index.spec.js
@@ -3,7 +3,7 @@ import { createElement } from 'lwc';
import EventHandler from 'x/eventHandler';
import EventHandlerOptions from 'x/eventHandlerOptions';
import AdditionWhileDispatch from 'x/additionWhileDispatch';
-import { spyConsole } from '../../../helpers/console.js';
+import { spyOn } from '@vitest/spy';
it('should be able to attach an event listener on the host element', () => {
let thisValue;
@@ -39,12 +39,11 @@ it('should warn when passing a 3rd parameter to the event handler', () => {
describe('event handler is not a function', () => {
let consoleSpy;
- beforeEach(() => {
- consoleSpy = spyConsole();
- });
- afterEach(() => {
- consoleSpy.reset();
+ beforeAll(() => {
+ consoleSpy = spyOn(console, 'error');
});
+ afterEach(() => consoleSpy.mockReset());
+ afterAll(() => consoleSpy.mockRestore());
it('should log an error if event handler is not a function', () => {
const elm = createElement('x-event-handler', { is: EventHandler });
@@ -54,11 +53,10 @@ describe('event handler is not a function', () => {
}).toThrowCallbackReactionError(/Expected an EventListener but received undefined/);
if (process.env.NODE_ENV === 'production') {
- expect(consoleSpy.calls.error.length).toEqual(0);
+ expect(consoleSpy).not.toHaveBeenCalled();
} else {
- expect(consoleSpy.calls.error.length).toEqual(1);
- expect(consoleSpy.calls.error[0][0].message).toContain(
- 'Invalid second argument for this.addEventListener()'
+ expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
+ expect.stringContaining('Invalid second argument for this.addEventListener()')
);
}
});
diff --git a/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js b/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js
index 640bd51eea..23d79a92b8 100644
--- a/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js
+++ b/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js
@@ -10,7 +10,7 @@ import LwcDynamicSlotted from 'x/lwcDynamicSlotted';
import ContainerFoo from 'x/containerFoo';
import ContainerBar from 'x/containerBar';
-import { spyConsole } from '../../../helpers/console.js';
+import { spyOn } from '@vitest/spy';
import { registerForLoad, clearRegister } from '../../../helpers/dynamic-loader.js';
beforeEach(() => {
@@ -116,12 +116,10 @@ it('should not cache DOM elements using lwc:dynamic', async () => {
describe('slotted content using lwc:dynamic', () => {
let consoleSpy;
- beforeEach(() => {
- consoleSpy = spyConsole();
- });
- afterEach(() => {
- consoleSpy.reset();
+ beforeAll(() => {
+ consoleSpy = spyOn(console, 'error');
});
+ afterAll(() => consoleSpy.mockRestore());
it('reallocate slotted content after changing constructor', async () => {
const elm = createElement('x-dynamic-slotted', { is: LwcDynamicSlotted });
@@ -136,7 +134,7 @@ describe('slotted content using lwc:dynamic', () => {
// `slot-bar` is not rendered in synthetic shadow
expect(elm.shadowRoot.querySelector('[data-id="slot-bar"]').assignedSlot).toBe(null);
}
- expect(consoleSpy.calls.error.length).toEqual(0);
+ expect(consoleSpy).not.toHaveBeenCalled();
// Swap construstor and check if nodes have been reallocated.
elm.ctor = ContainerBar;
@@ -150,7 +148,7 @@ describe('slotted content using lwc:dynamic', () => {
// `slot-foo` is not rendered in synthetic shadow
expect(elm.shadowRoot.querySelector('[data-id="slot-foo"]').assignedSlot).toBe(null);
}
- expect(consoleSpy.calls.error.length).toEqual(0);
+ expect(consoleSpy).not.toHaveBeenCalled();
});
});
@@ -242,12 +240,10 @@ it('should not cache DOM elements', async () => {
describe('slotted content', () => {
let consoleSpy;
- beforeEach(() => {
- consoleSpy = spyConsole();
- });
- afterEach(() => {
- consoleSpy.reset();
+ beforeAll(() => {
+ consoleSpy = spyOn(console, 'error');
});
+ afterAll(() => consoleSpy.mockRestore());
it('reallocate slotted content after changing constructor', async () => {
const elm = createElement('x-dynamic-slotted', { is: DynamicSlotted });
@@ -262,7 +258,7 @@ describe('slotted content', () => {
// `slot-bar` is not rendered in synthetic shadow
expect(elm.shadowRoot.querySelector('[data-id="slot-bar"]').assignedSlot).toBe(null);
}
- expect(consoleSpy.calls.error.length).toEqual(0);
+ expect(consoleSpy).not.toHaveBeenCalled();
// Swap constructor and check if nodes have been reallocated.
elm.ctor = ContainerBar;
@@ -276,6 +272,6 @@ describe('slotted content', () => {
// `slot-foo` is not rendered in synthetic shadow
expect(elm.shadowRoot.querySelector('[data-id="slot-foo"]').assignedSlot).toBe(null);
}
- expect(consoleSpy.calls.error.length).toEqual(0);
+ expect(consoleSpy).not.toHaveBeenCalled();
});
});
diff --git a/packages/@lwc/integration-not-karma/test/lwc-on/index.spec.js b/packages/@lwc/integration-not-karma/test/lwc-on/index.spec.js
index d62d43e081..32a1562a25 100644
--- a/packages/@lwc/integration-not-karma/test/lwc-on/index.spec.js
+++ b/packages/@lwc/integration-not-karma/test/lwc-on/index.spec.js
@@ -11,8 +11,8 @@ import RerenderLoop from 'x/rerenderLoop';
import PublicProp from 'x/publicProp';
import ComputedKey from 'x/computedKey';
import ValueEvaluationThrows from 'x/valueEvaluationThrows';
+import { spyOn } from '@vitest/spy';
import { jasmine } from '../../helpers/jasmine.js';
-import { spyConsole } from '../../helpers/console.js';
import { catchUnhandledRejectionsAndErrors } from '../../helpers/utils.js';
describe('lwc:on', () => {
@@ -257,10 +257,10 @@ describe('lwc:on', () => {
describe('with same object modified', () => {
let consoleSpy;
beforeEach(() => {
- consoleSpy = spyConsole();
+ consoleSpy = spyOn(console, 'error').mockImplementation(() => {});
});
afterEach(() => {
- consoleSpy.reset();
+ consoleSpy.mockRestore();
});
it('throws when a new property is added to object passed to lwc:on', async () => {
@@ -268,12 +268,16 @@ describe('lwc:on', () => {
await element.triggerReRender();
if (process.env.NODE_ENV !== 'production') {
- expect(consoleSpy.calls.error.length).toEqual(1);
- expect(consoleSpy.calls.error[0][0].message).toContain(
- "Detected mutation of property 'mouseover' in the object passed to lwc:on for