diff --git a/packages/@lwc/integration-karma/test/component/LightningElement.disconnectedCallback/index.spec.js b/packages/@lwc/integration-karma/test/component/LightningElement.disconnectedCallback/index.spec.js index 765c954e46..bc5ef3c281 100644 --- a/packages/@lwc/integration-karma/test/component/LightningElement.disconnectedCallback/index.spec.js +++ b/packages/@lwc/integration-karma/test/component/LightningElement.disconnectedCallback/index.spec.js @@ -92,14 +92,6 @@ describe('disconnectedCallback for host with slots', () => { let slotAcceptingChildSpy; let parent; - beforeAll(() => { - // Ignore the engine logging about passing slot content to a component that does not accept slot - // These should become unnecessary when #869 is fixed - spyOn(console, 'group'); - spyOn(console, 'log'); - spyOn(console, 'groupEnd'); - }); - beforeEach(() => { parentDisconnectSpy = jasmine.createSpy(); slotIgnoringChildSpy = jasmine.createSpy(); diff --git a/packages/@lwc/integration-karma/test/shadow-dom/ignoring-slotted/issue-1090.spec.js b/packages/@lwc/integration-karma/test/shadow-dom/ignoring-slotted/issue-1090.spec.js index ba0ac90104..ca82ae97cd 100644 --- a/packages/@lwc/integration-karma/test/shadow-dom/ignoring-slotted/issue-1090.spec.js +++ b/packages/@lwc/integration-karma/test/shadow-dom/ignoring-slotted/issue-1090.spec.js @@ -3,14 +3,6 @@ import { createElement } from 'lwc'; import Parent from 'x/parent'; describe('Issue #1090', () => { - beforeAll(() => { - // Ignore the engine logging about passing slot content to a component that does not accept slot - // These should become unnecessary when #869 is fixed - spyOn(console, 'group'); - spyOn(console, 'log'); - spyOn(console, 'groupEnd'); - }); - it('should disconnect slotted content even if it is not allocated into a slot', () => { const elm = createElement('x-parent', { is: Parent }); document.body.appendChild(elm); diff --git a/packages/@lwc/integration-karma/test/template/directive-lwc-dom-manual/index.spec.js b/packages/@lwc/integration-karma/test/template/directive-lwc-dom-manual/index.spec.js index 78351e391a..5f12e9b3cd 100644 --- a/packages/@lwc/integration-karma/test/template/directive-lwc-dom-manual/index.spec.js +++ b/packages/@lwc/integration-karma/test/template/directive-lwc-dom-manual/index.spec.js @@ -14,17 +14,16 @@ describe('dom mutation without the lwc:dom="manual" directive', () => { const root = createElement('x-without-lwc-dom-manual', { is: withoutLwcDomManual }); document.body.appendChild(root); const elm = root.shadowRoot.querySelector('div'); + const mutate = () => fn(elm); - // eslint-disable-next-line vitest/valid-expect - let expected = expect(() => fn(elm)); + const warning = new RegExp( + `\\[LWC warn\\]: The \`${method}\` method is available only on elements that use the \`lwc:dom="manual"\` directive.` + ); if (process.env.NATIVE_SHADOW) { - expected = expected.not; // no error + expect(mutate).not.toLogWarningDev(warning); + } else { + expect(mutate).toLogWarningDev(warning); } - expected.toLogWarningDev( - new RegExp( - `\\[LWC warn\\]: The \`${method}\` method is available only on elements that use the \`lwc:dom="manual"\` directive.` - ) - ); }); } diff --git a/packages/@lwc/integration-not-karma/helpers/console.mjs b/packages/@lwc/integration-not-karma/helpers/console.mjs new file mode 100644 index 0000000000..9a52018dcb --- /dev/null +++ b/packages/@lwc/integration-not-karma/helpers/console.mjs @@ -0,0 +1,23 @@ +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/helpers/matchers.mjs b/packages/@lwc/integration-not-karma/helpers/matchers.mjs deleted file mode 100644 index d1781cd5ba..0000000000 --- a/packages/@lwc/integration-not-karma/helpers/matchers.mjs +++ /dev/null @@ -1,31 +0,0 @@ -// FIXME: copy implementations from karma tests - -const customMatchers = [ - // LWC custom - 'toLogError', - 'toLogErrorDev', - 'toThrowErrorDev', - 'toLogWarningDev', - 'toThrowCallbackReactionError', - 'toThrowCallbackReactionErrorDev', - 'toThrowCallbackReactionErrorEvenInSyntheticLifecycleMode', - // jasmine compat - 'toHaveSize', - 'toBeFalse', - 'toBeTrue', -]; -export const registerCustomMatchers = (chai, utils) => { - for (const matcher of customMatchers) { - utils.addMethod(chai.Assertion.prototype, matcher, function () { - // FIXME: implement for realsies - const fn = utils.flag(this, 'object'); - if (typeof fn === 'function') { - try { - fn(); - } catch (_) { - // - } - } - }); - } -}; diff --git a/packages/@lwc/integration-not-karma/helpers/matchers/console.mjs b/packages/@lwc/integration-not-karma/helpers/matchers/console.mjs new file mode 100644 index 0000000000..a0f356db40 --- /dev/null +++ b/packages/@lwc/integration-not-karma/helpers/matchers/console.mjs @@ -0,0 +1,117 @@ +import { spyOn } from '@vitest/spy'; + +function formatConsoleCall(args) { + // Just calling .join suppresses null/undefined, so we stringify separately + return args.map(String).join(' '); +} + +function formatAllCalls(argsList) { + return argsList.map((args) => `"${formatConsoleCall(args)}"`).join(', '); +} + +function callAndGetLogs(fn, methodName) { + const spy = spyOn(console, methodName).mockImplementation(() => {}); + try { + fn(); + return spy.mock.calls; + } finally { + spy.mockRestore(); + } +} + +function consoleMatcherFactory(chai, utils, methodName, expectInProd) { + return function consoleMatcher(expectedMessages) { + const actual = utils.flag(this, 'object'); + + if (utils.flag(this, 'negate')) { + // If there's a .not in the assertion chain + const callsArgs = callAndGetLogs(actual, methodName); + if (callsArgs.length === 0) { + return; + } + throw new chai.AssertionError( + `Expect no message but received:\n${formatAllCalls(callsArgs)}` + ); + } + + if (!Array.isArray(expectedMessages)) { + expectedMessages = [expectedMessages]; + } + + if (typeof actual !== 'function') { + throw new Error('Expected function to throw error.'); + } else if (expectedMessages.some((m) => typeof m !== 'string' && !(m instanceof RegExp))) { + throw new Error( + 'Expected a string or a RegExp to compare the thrown error against, or an array of such.' + ); + } + + const callsArgs = callAndGetLogs(actual, methodName); + + if (!expectInProd && process.env.NODE_ENV === 'production') { + if (callsArgs.length !== 0) { + throw new chai.AssertionError( + `Expected console.${ + methodName + } to never be called in production mode, but it was called ${ + callsArgs.length + } time(s) with ${formatAllCalls(callsArgs)}.` + ); + } + } else { + if (callsArgs.length === 0) { + // Result: "string", /regex/ + const formattedExpected = expectedMessages + .map((msg) => (typeof msg === 'string' ? JSON.stringify(msg) : msg.toString())) + .join(', '); + throw new chai.AssertionError( + `Expected console.${methodName} to be called with [${ + formattedExpected + }], but was never called.` + ); + } else { + if (callsArgs.length !== expectedMessages.length) { + throw new chai.AssertionError( + `Expected console.${methodName} to be called ${ + expectedMessages.length + } time(s), but was called ${callsArgs.length} time(s).` + ); + } + for (let i = 0; i < callsArgs.length; i++) { + const callsArg = callsArgs[i]; + const expectedMessage = expectedMessages[i]; + const actualMessage = formatConsoleCall(callsArg); + + const matches = + typeof expectedMessage === 'string' + ? actualMessage === expectedMessage + : expectedMessage.test(actualMessage); + if (!matches) { + throw new chai.AssertionError( + `Expected console.${methodName} to be called with "${ + expectedMessage + }", but was called with "${actualMessage}".` + ); + } + } + } + } + }; +} + +/** + * Custom console assertions + * @type {Chai.ChaiPlugin} + */ +export const registerConsoleMatchers = (chai, utils) => { + const customMatchers = { + // FIXME: Add descriptions explaining the what/why of these custom matchers + toLogErrorDev: consoleMatcherFactory(chai, utils, 'error'), + toLogError: consoleMatcherFactory(chai, utils, 'error', true), + toLogWarningDev: consoleMatcherFactory(chai, utils, 'warn'), + }; + + for (const [name, impl] of Object.entries(customMatchers)) { + utils.addMethod(chai.Assertion.prototype, name, impl); + } +}; diff --git a/packages/@lwc/integration-not-karma/helpers/matchers/errors.mjs b/packages/@lwc/integration-not-karma/helpers/matchers/errors.mjs new file mode 100644 index 0000000000..668ef31047 --- /dev/null +++ b/packages/@lwc/integration-not-karma/helpers/matchers/errors.mjs @@ -0,0 +1,144 @@ +// Listen for errors thrown directly by the callback +function directErrorListener(callback) { + try { + callback(); + } catch (error) { + return error; + } +} + +// Listen for errors using window.addEventListener('error') +function windowErrorListener(callback) { + let error; + function onError(event) { + event.preventDefault(); // don't log the error + error = event.error; + } + + // Prevent jasmine from handling the global error. There doesn't seem to be another + // way to disable this behavior: https://github.com/jasmine/jasmine/pull/1860 + const originalOnError = window.onerror; + window.onerror = null; + window.addEventListener('error', onError); + + try { + callback(); + } finally { + window.onerror = originalOnError; + window.removeEventListener('error', onError); + } + return error; +} + +// For errors we expect to be thrown in the connectedCallback() phase +// of a custom element, there are two possibilities: +// 1) We're using non-native lifecycle callbacks, so the error is thrown synchronously +// 2) We're using native lifecycle callbacks, so the error is thrown asynchronously and can +// only be caught with window.addEventListener('error') +// - Note native lifecycle callbacks are all thrown asynchronously. +function customElementCallbackReactionErrorListener(callback) { + return lwcRuntimeFlags.DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE + ? directErrorListener(callback) + : windowErrorListener(callback); +} + +function matchError(error, expectedErrorCtor, expectedMessage) { + if ((!error) instanceof expectedErrorCtor) { + return false; + } else if (typeof expectedMessage === 'undefined') { + return true; + } else if (typeof expectedMessage === 'string') { + return error.message === expectedMessage; + } else { + return expectedMessage.test(error.message); + } +} + +function throwDescription(thrown) { + return `${thrown.name} with message "${thrown.message}"`; +} + +function errorMatcherFactory(chai, utils, errorListener, expectInProd) { + return function toThrowError(expectedErrorCtor, expectedMessage) { + if (typeof expectedMessage === 'undefined') { + if (typeof expectedErrorCtor === 'undefined') { + // 0 arguments provided + expectedMessage = undefined; + expectedErrorCtor = Error; + } else { + // 1 argument provided + expectedMessage = expectedErrorCtor; + expectedErrorCtor = Error; + } + } + + const actual = utils.flag(this, 'object'); + if (typeof actual !== 'function') { + throw new Error('Expected function to throw error.'); + } else if (expectedErrorCtor !== Error && !(expectedErrorCtor.prototype instanceof Error)) { + throw new Error('Expected an error constructor.'); + } else if ( + typeof expectedMessage !== 'undefined' && + typeof expectedMessage !== 'string' && + !(expectedMessage instanceof RegExp) + ) { + throw new Error('Expected a string or a RegExp to compare the thrown error against.'); + } + + const thrown = errorListener(actual); + + if (!expectInProd && process.env.NODE_ENV === 'production') { + if (thrown !== undefined) { + throw new chai.AssertionError( + `Expected function not to throw an error in production mode, but it threw ${throwDescription( + thrown + )}.` + ); + } + } else if (thrown === undefined) { + throw new chai.AssertionError( + `Expected function to throw an ${ + expectedErrorCtor.name + } error in development mode "${ + expectedMessage ? 'with message ' + expectedMessage : '' + }".` + ); + } else if (!matchError(thrown, expectedErrorCtor, expectedMessage)) { + throw new chai.AssertionError( + `Expected function to throw an ${ + expectedErrorCtor.name + } error in development mode "${ + expectedMessage ? 'with message ' + expectedMessage : '' + }", but it threw ${throwDescription(thrown)}.` + ); + } + }; +} + +/** @type {Chai.ChaiPlugin} */ +export const registerErrorMatchers = (chai, utils) => { + const matchers = { + toThrowErrorDev: errorMatcherFactory(chai, utils, directErrorListener), + toThrowCallbackReactionErrorDev: errorMatcherFactory( + chai, + utils, + customElementCallbackReactionErrorListener + ), + toThrowCallbackReactionError: errorMatcherFactory( + chai, + utils, + customElementCallbackReactionErrorListener, + true + ), + toThrowCallbackReactionErrorEvenInSyntheticLifecycleMode: errorMatcherFactory( + chai, + utils, + windowErrorListener, + true + ), + }; + + for (const [name, impl] of Object.entries(matchers)) { + utils.addMethod(chai.Assertion.prototype, name, impl); + } +}; diff --git a/packages/@lwc/integration-not-karma/helpers/matchers/index.mjs b/packages/@lwc/integration-not-karma/helpers/matchers/index.mjs new file mode 100644 index 0000000000..95397e4e1d --- /dev/null +++ b/packages/@lwc/integration-not-karma/helpers/matchers/index.mjs @@ -0,0 +1,9 @@ +import { registerConsoleMatchers } from './console.mjs'; +import { registerErrorMatchers } from './errors.mjs'; +import { registerJasmineMatchers } from './jasmine.mjs'; + +export const registerCustomMatchers = (chai, utils) => { + registerConsoleMatchers(chai, utils); + registerErrorMatchers(chai, utils); + registerJasmineMatchers(chai, utils); +}; diff --git a/packages/@lwc/integration-not-karma/helpers/matchers/jasmine.mjs b/packages/@lwc/integration-not-karma/helpers/matchers/jasmine.mjs new file mode 100644 index 0000000000..31ff4dee47 --- /dev/null +++ b/packages/@lwc/integration-not-karma/helpers/matchers/jasmine.mjs @@ -0,0 +1,27 @@ +/** + * Custom matchers implemented as part of the migration from Karma to Web Test + * Runner. Should be removed and usage replaced with chai assertions. + * @type {Chai.ChaiPlugin} + */ +export const registerJasmineMatchers = (chai, utils) => { + const matchers = { + toHaveSize(size) { + const value = utils.flag(this, 'object'); + chai.expect(value).to.have.length(size); + }, + toBeFalse() { + const value = utils.flag(this, 'object'); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + chai.expect(value).to.be.false; + }, + toBeTrue() { + const value = utils.flag(this, 'object'); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + chai.expect(value).to.be.true; + }, + }; + + for (const [name, impl] of Object.entries(matchers)) { + utils.addMethod(chai.Assertion.prototype, name, impl); + } +}; diff --git a/packages/@lwc/integration-not-karma/helpers/setup.mjs b/packages/@lwc/integration-not-karma/helpers/setup.mjs index 3fdbd96975..6bd47784ea 100644 --- a/packages/@lwc/integration-not-karma/helpers/setup.mjs +++ b/packages/@lwc/integration-not-karma/helpers/setup.mjs @@ -3,7 +3,7 @@ import { JestAsymmetricMatchers, JestChaiExpect, JestExtend } from '@vitest/expe import * as chai from 'chai'; import * as LWC from 'lwc'; import { spyOn, fn } from '@vitest/spy'; -import { registerCustomMatchers } from './matchers.mjs'; +import { registerCustomMatchers } from './matchers/index.mjs'; // allows using expect.extend instead of chai.use to extend plugins chai.use(JestExtend); diff --git a/packages/@lwc/integration-not-karma/helpers/signals.mjs b/packages/@lwc/integration-not-karma/helpers/signals.mjs new file mode 100644 index 0000000000..40a45eada1 --- /dev/null +++ b/packages/@lwc/integration-not-karma/helpers/signals.mjs @@ -0,0 +1,8 @@ +import { setTrustedSignalSet } from 'lwc'; + +const signalValidator = new WeakSet(); +setTrustedSignalSet(signalValidator); + +export function addTrustedSignal(signal) { + signalValidator.add(signal); +} diff --git a/packages/@lwc/integration-not-karma/helpers/wtr-utils.mjs b/packages/@lwc/integration-not-karma/helpers/wtr-utils.mjs index df7facf5cf..70875552aa 100644 --- a/packages/@lwc/integration-not-karma/helpers/wtr-utils.mjs +++ b/packages/@lwc/integration-not-karma/helpers/wtr-utils.mjs @@ -7,6 +7,7 @@ import { nonStandardAriaProperties, } from './aria.mjs'; import { setHooks, getHooks } from './hooks.mjs'; +import { spyConsole } from './console.mjs'; import { DISABLE_OBJECT_REST_SPREAD_TRANSFORMATION, ENABLE_ELEMENT_INTERNALS_AND_FACE, @@ -19,44 +20,7 @@ import { USE_FRAGMENTS_FOR_LIGHT_DOM_SLOTS, USE_LIGHT_DOM_SLOT_FORWARDING, } from './constants.mjs'; - -// TODO [#869]: Replace this custom spy with standard spyOn jasmine spy when logWarning doesn't use console.group -// anymore. On IE11 console.group has a different behavior when the F12 inspector is attached to the page. -function spyConsole() { - const originalConsole = window.console; - const calls = { - log: [], - warn: [], - error: [], - group: [], - groupEnd: [], - }; - - window.console = { - log: function () { - calls.log.push(Array.prototype.slice.call(arguments)); - }, - warn: function () { - calls.warn.push(Array.prototype.slice.call(arguments)); - }, - error: function () { - calls.error.push(Array.prototype.slice.call(arguments)); - }, - group: function () { - calls.group.push(Array.prototype.slice.call(arguments)); - }, - groupEnd: function () { - calls.groupEnd.push(Array.prototype.slice.call(arguments)); - }, - }; - - return { - calls: calls, - reset: function () { - window.console = originalConsole; - }, - }; -} +import { addTrustedSignal } from './signals.mjs'; // Listen for errors thrown directly by the callback function directErrorListener(callback) { @@ -348,13 +312,6 @@ function expectEquivalentDOM(element, html) { expectEquivalent(element, fragment.body.firstChild); } -const signalValidator = new WeakSet(); -LWC.setTrustedSignalSet(signalValidator); - -function addTrustedSignal(signal) { - signalValidator.add(signal); -} - export { clearRegister, extractDataIds, diff --git a/packages/@lwc/integration-not-karma/web-test-runner.config.mjs b/packages/@lwc/integration-not-karma/web-test-runner.config.mjs index 518e23e3c9..bce0d9f208 100644 --- a/packages/@lwc/integration-not-karma/web-test-runner.config.mjs +++ b/packages/@lwc/integration-not-karma/web-test-runner.config.mjs @@ -3,6 +3,7 @@ import customRollup from './helpers/lwc.mjs'; import * as options from './helpers/options.mjs'; const pluck = (obj, keys) => Object.fromEntries(keys.map((k) => [k, Boolean(obj[k])])); +const maybeImport = (file, condition) => (condition ? `await import('${file}');` : ''); /** `process.env` to inject into test environment. */ const env = { @@ -31,26 +32,25 @@ export default { '!test/api/freezeTemplate/index.spec.js', '!test/api/getComponentDef/index.spec.js', '!test/api/isNodeFromTemplate/index.spec.js', - '!test/api/readonly/index.spec.js', '!test/api/registerTemplate/index.spec.js', '!test/api/sanitizeAttribute/index.spec.js', '!test/api/sanitizeHtmlContent/index.spec.js', - '!test/component/face-callbacks/index.spec.js', - '!test/component/lifecycle-callbacks/index.spec.js', '!test/component/LightningElement.addEventListener/index.spec.js', '!test/component/LightningElement.attachInternals/api/index.spec.js', '!test/component/LightningElement.attachInternals/elementInternals/formAssociated/index.spec.js', + '!test/component/LightningElement.connectedCallback/index.spec.js', + '!test/component/LightningElement.disconnectedCallback/index.spec.js', '!test/component/LightningElement.errorCallback/index.spec.js', '!test/component/LightningElement.hostElement/index.spec.js', '!test/component/LightningElement.render/index.spec.js', '!test/component/LightningElement.style/index.spec.js', '!test/component/LightningElement/index.spec.js', + '!test/component/face-callbacks/index.spec.js', '!test/component/native-vs-synthetic-lifecycle/index.spec.js', '!test/custom-elements-registry/index.spec.js', '!test/events/focus-event-related-target/index.spec.js', '!test/integrations/locker/index.spec.js', '!test/light-dom/host-pseudo/index.spec.js', - '!test/light-dom/ids/index.spec.js', '!test/light-dom/lifecycle/index.spec.js', '!test/light-dom/multiple-templates/index.spec.js', '!test/light-dom/scoped-slot/if-block/index.spec.js', @@ -63,66 +63,51 @@ export default { '!test/light-dom/slotting/index.spec.js', '!test/light-dom/style-global/index.spec.js', '!test/light-dom/synthetic-shadow-styles/index.spec.js', + '!test/lwc-on/index.spec.js', '!test/misc/clean-dom/index.spec.js', '!test/misc/object-rest-spread/index.spec.js', '!test/mixed-shadow-mode/composed-path/index.spec.js', - '!test/mixed-shadow-mode/reporting/index.spec.js', - '!test/mixed-shadow-mode/synthetic-behavior/index.spec.js', - '!test/native-shadow/Event-methods/Event.composedPath.spec.js', '!test/polyfills/document-body-properties/index.spec.js', '!test/polyfills/document-properties/index.spec.js', '!test/profiler/mutation-logging/index.spec.js', - '!test/profiler/sanity/profiler.spec.js', '!test/regression/invalid-key/index.spec.js', '!test/rendering/callback-invocation-order/index.spec.js', - '!test/rendering/elements-are-not-recycled/index.spec.js', '!test/rendering/fragment-cache/index.spec.js', '!test/rendering/iframe/index.spec.js', '!test/rendering/inner-outer-html/index.spec.js', '!test/rendering/legacy-scope-tokens/index.spec.js', - '!test/rendering/native-only-css/index.spec.js', + '!test/rendering/legacy-stylesheet-api/index.spec.js', '!test/rendering/programmatic-stylesheets/index.spec.js', '!test/rendering/sanitize-stylesheet-token/index.spec.js', '!test/rendering/scoped-styles-with-existing-class/index.spec.js', + '!test/rendering/side-effects/index.spec.js', '!test/rendering/slot-not-at-top-level/element/light/index.spec.js', - '!test/rendering/slot-not-at-top-level/element/shadow/index.spec.js', '!test/rendering/slot-not-at-top-level/external/light/index.spec.js', - '!test/rendering/slot-not-at-top-level/external/shadow/index.spec.js', - '!test/rendering/slot-not-at-top-level/ifTrue/shadow/index.spec.js', + '!test/rendering/slot-not-at-top-level/ifTrue/light/index.spec.js', '!test/rendering/slot-not-at-top-level/lwcIf/light/index.spec.js', - '!test/rendering/slot-not-at-top-level/lwcIf/shadow/index.spec.js', '!test/rendering/slotting/index.spec.js', '!test/rendering/stylesheet-caching/index.spec.js', '!test/rendering/version-mismatch/index.spec.js', - '!test/shadow-dom/event-in-shadow-tree/propagation.spec.js', + '!test/shadow-dom/Element-properties/index.spec.js', '!test/shadow-dom/Event-properties/Event.target.spec.js', - '!test/shadow-dom/multiple-templates/index.spec.js', - '!test/shadow-dom/MutationObserver/MutationObserver.spec.js', - '!test/shadow-dom/Node-properties/Node.childNodes.spec.js', - '!test/shadow-dom/Node-properties/Node.hasChildNodes.spec.js', - '!test/shadow-dom/Node-properties/Node.textContent.spec.js', - '!test/shadow-dom/ShadowRoot-properties/ShadowRoot.spec.js', + '!test/shadow-dom/Node-properties/Node.getRootNode.spec.js', '!test/shadow-dom/ShadowRoot.elementsFromPoint/index.spec.js', - '!test/rendering/slot-not-at-top-level/ifTrue/light/index.spec.js', + '!test/shadow-dom/multiple-templates/index.spec.js', '!test/signal/protocol/index.spec.js', '!test/spread/index.spec.js', '!test/static-content/index.spec.js', '!test/swapping/styles/index.spec.js', - '!test/synthetic-shadow/active-element/index.spec.js', '!test/synthetic-shadow/dom-manual-sharing-nodes/index.spec.js', '!test/synthetic-shadow/element-api/element-api.spec.js', - '!test/synthetic-shadow/global-styles/index.spec.js', '!test/synthetic-shadow/host-pseudo/index.spec.js', - '!test/synthetic-shadow/inner-outer-text/inner-outer-text.spec.js', - '!test/synthetic-shadow/scoped-id/multiple-idrefs.spec.js', '!test/synthetic-shadow/style-svg/index.spec.js', '!test/template/attribute-class/object-values.spec.js', '!test/template/directive-for-each/index.spec.js', - '!test/template/directive-if/index.spec.js', '!test/template/directive-lwc-render-mode/index.spec.js', '!test/wire/legacy-adapters/index.spec.js', '!test/wire/reactive-params.spec.js', '!test/wire/wirecontextevent-legacy/index.spec.js', + '!test/wire/wiring/index.spec.js', ], nodeResolve: true, rootDir: import.meta.dirname, @@ -157,6 +142,9 @@ export default { globalThis.lwcRuntimeFlags = ${JSON.stringify( pluck(options, ['DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE']) )}; + + ${maybeImport('@lwc/synthetic-shadow', !options.DISABLE_SYNTHETIC)} + ${maybeImport('@lwc/aria-reflection', options.ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL)}