Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(integration-karma): add a new FORCED_MIXED_SHADOW_MODE #2496

Merged
merged 3 commits into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/@lwc/engine-core/src/framework/vm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import features from '@lwc/features';
import {
ArrayPush,
ArraySlice,
Expand Down Expand Up @@ -316,6 +317,9 @@ export function createVM<HostNode, HostElement>(
vm.toString = (): string => {
return `[object:vm ${def.name} (${vm.idx})]`;
};
if (features.ENABLE_FORCE_NATIVE_SHADOW_MODE_FOR_TEST) {
vm.shadowMode = ShadowMode.Native;
}
ekashida marked this conversation as resolved.
Show resolved Hide resolved
}

// Create component instance associated to the vm and the element.
Expand Down
1 change: 1 addition & 0 deletions packages/@lwc/features/src/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const features: FeatureFlagMap = {
ENABLE_HMR: null,
ENABLE_INNER_OUTER_TEXT_PATCH: null,
ENABLE_ELEMENT_PATCH: null,
ENABLE_FORCE_NATIVE_SHADOW_MODE_FOR_TEST: null,
ENABLE_NODE_LIST_PATCH: null,
ENABLE_HTML_COLLECTIONS_PATCH: null,
ENABLE_NODE_PATCH: null,
Expand Down
5 changes: 5 additions & 0 deletions packages/@lwc/features/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export interface FeatureFlagMap {
*/
ENABLE_ELEMENT_PATCH: FeatureFlagValue;

/**
* LWC engine flag to force native shadow mode for mixed shadow mode testing.
*/
ENABLE_FORCE_NATIVE_SHADOW_MODE_FOR_TEST: FeatureFlagValue;

/**
* Synthetic shadow DOM flag to enable `Node.prototype` global patching. The following APIs are
* affected by this flag:
Expand Down
3 changes: 3 additions & 0 deletions packages/integration-karma/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This set of environment variables applies to the `start` and `test` commands:

- **`COMPAT=1`:** Compile and deliver tests in COMPAT mode.
- **`DISABLE_SYNTHETIC=1`:** Run without any synthetic shadow polyfill patches.
- **`FORCE_NATIVE_SHADOW_MODE_FOR_TEST=1`:** Force tests to run in native shadow mode with synthetic shadow polyfill patches.
- **`COVERAGE=1`:** Gather engine code coverage, and store it in the `coverage` folder.
- **`GREP="pattern"`:** Filter the spec to run based on the pattern.

Expand All @@ -46,4 +47,6 @@ COVERAGE=1 yarn test # Compute coverage after a single test run
variable is set.
- `process.env.DISABLE_SYNTHETIC`: is set to `false` by default and `true` if the
`DISABLE_SYNTHETIC` environment variable is set.
- `FORCE_NATIVE_SHADOW_MODE_FOR_TEST`: is set to `false` by default and `true` if the
`FORCE_NATIVE_SHADOW_MODE_FOR_TEST` environment variable is set.
- The test setup file (`test-setup.js`) will automatically clean up the DOM before and after each test. So you don't have to do anything to clean up. However, you should use `beforeEach()` rather than `beforeAll()` to add DOM elements for your test, so that the cleanup code can properly clean up the DOM.
4 changes: 2 additions & 2 deletions packages/integration-karma/scripts/karma-configs/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const { getModulePath } = require('lwc');

const karmaPluginLwc = require('../karma-plugins/lwc');
const karmaPluginEnv = require('../karma-plugins/env');
const { COMPAT, DISABLE_SYNTHETIC, TAGS, GREP, COVERAGE } = require('../shared/options');
const { COMPAT, SYNTHETIC_SHADOW_ENABLED, TAGS, GREP, COVERAGE } = require('../shared/options');

const BASE_DIR = path.resolve(__dirname, '../../test');
const COVERAGE_DIR = path.resolve(__dirname, '../../coverage');
Expand Down Expand Up @@ -45,7 +45,7 @@ function getFiles() {
frameworkFiles.push(createPattern(LWC_ENGINE_COMPAT));
frameworkFiles.push(createPattern(WIRE_SERVICE_COMPAT));
} else {
if (!DISABLE_SYNTHETIC) {
if (SYNTHETIC_SHADOW_ENABLED) {
frameworkFiles.push(createPattern(SYNTHETIC_SHADOW));
}
frameworkFiles.push(createPattern(LWC_ENGINE));
Expand Down
30 changes: 18 additions & 12 deletions packages/integration-karma/scripts/karma-plugins/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
const fs = require('fs');
const path = require('path');

const { COMPAT, DISABLE_SYNTHETIC } = require('../shared/options');
const {
COMPAT,
FORCE_NATIVE_SHADOW_MODE_FOR_TEST,
SYNTHETIC_SHADOW_ENABLED,
} = require('../shared/options');

const DIST_DIR = path.resolve(__dirname, '../../dist');
const ENV_FILENAME = path.resolve(DIST_DIR, 'env.js');
Expand All @@ -25,17 +29,19 @@ function createEnvFile() {
fs.mkdirSync(DIST_DIR);
}

const content = [
`window.process = {`,
` env: {`,
` NODE_ENV: "development",`,
` COMPAT: ${COMPAT},`,
` DISABLE_SYNTHETIC: ${DISABLE_SYNTHETIC},`,
` NATIVE_SHADOW_ROOT_DEFINED: typeof ShadowRoot !== "undefined"`,
` }`,
`};`,
];
fs.writeFileSync(ENV_FILENAME, content.join('\n'));
fs.writeFileSync(
ENV_FILENAME,
`
window.process = {
env: {
NODE_ENV: 'development',
COMPAT: ${COMPAT},
NATIVE_SHADOW: ${!SYNTHETIC_SHADOW_ENABLED || FORCE_NATIVE_SHADOW_MODE_FOR_TEST},
NATIVE_SHADOW_ROOT_DEFINED: typeof ShadowRoot !== 'undefined'
}
};
`
);
}

function initEnv(files) {
Expand Down
6 changes: 4 additions & 2 deletions packages/integration-karma/scripts/shared/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ if (process.env.NATIVE_SHADOW) {

const COMPAT = Boolean(process.env.COMPAT);
const DISABLE_SYNTHETIC = Boolean(process.env.DISABLE_SYNTHETIC);
const FORCE_NATIVE_SHADOW_MODE_FOR_TEST = Boolean(process.env.FORCE_NATIVE_SHADOW_MODE_FOR_TEST);
const TAGS = [`${DISABLE_SYNTHETIC ? 'native' : 'synthetic'}-shadow`, COMPAT && 'compat'].filter(
(v) => Boolean(v)
Boolean
);

module.exports = {
// Test configuration
COMPAT,
DISABLE_SYNTHETIC,
FORCE_NATIVE_SHADOW_MODE_FOR_TEST,
SYNTHETIC_SHADOW_ENABLED: !DISABLE_SYNTHETIC,
TAGS,
GREP: process.env.GREP,
COVERAGE: Boolean(process.env.COVERAGE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ beforeEach(() => {
});

// TODO [#985]: Firefox does not implement delegatesFocus
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
describe('host.focus() when { delegatesFocus: true }', () => {
it('should focus the host element', () => {
const elm = createElement('x-focus', { is: DelegatesFocusTrue });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ it('returns an HTMLElement', () => {
expect(elm instanceof HTMLElement).toBe(true);
});

if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
it('should create an element with a synthetic shadow root by default', () => {
const elm = createElement('x-component', { is: Test });
expect(elm.shadowRoot.constructor.name).toBe('SyntheticShadowRoot');
Expand All @@ -64,7 +64,7 @@ it('supports component constructors in circular dependency', () => {
expect(elm instanceof HTMLElement).toBe(true);
});

if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
it('should create an element with a native shadow root if fallback is false', () => {
const elm = createElement('x-component', {
is: Test,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ it('should return true on elements manually inserted in the DOM inside an elemen
// TODO [#1253]: optimization to synchronously adopt new child nodes added
// to this elm, we can do that by patching the most common operations
// on the node itself
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
expect(isNodeFromTemplate(div)).toBe(false); // it is false sync because MO hasn't pick up the element yet
}
return new Promise((resolve) => {
Expand All @@ -63,7 +63,7 @@ it('should return true on elements manually inserted in the DOM inside an elemen

// TODO [#1252]: old behavior that is still used by some pieces of the platform
// if isNodeFromTemplate() returns true, locker will prevent traversing to such elements from document
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
it('should return false on elements manually inserted in the DOM inside an element NOT marked with lwc:dom="manual"', () => {
const elm = createElement('x-test', { is: Test });
document.body.appendChild(elm);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ orderings. For any given component, the invariants are:

It's ok to update the orderings below after a refactor, as long as these invariants hold!
*/
if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
it(`should invoke connectedCallback and renderedCallback in the expected order (native shadow)`, () => {
const elm = createElement('order-container', { is: Container });
document.body.appendChild(elm);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('host element', () => {
it('should accept children being appended to it', () => {
const element = createElement('x-container', { is: Shadow });
document.body.appendChild(element);
if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
// synthetic shadow returns null here even though it successfully inserts the div
expect(element.firstChild.tagName).toEqual('DIV');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('Light DOM IDs and fragment links', () => {
expect(light.querySelector('.go-to-bar').href).toMatch(/#bar$/);
expect(light.querySelector('.go-to-quux').href).toMatch(/#quux$/);

if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
expect(shadow.shadowRoot.querySelector('.foo').id).toEqual('foo');
expect(shadow.shadowRoot.querySelector('.quux').id).toEqual('quux');
expect(shadow.shadowRoot.querySelector('.go-to-foo').href).toMatch(/#foo$/);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('Slotting', () => {
it('shadow container, light consumer', () => {
const nodes = createTestElement('x-light-consumer', LightConsumer);

const expected = process.env.DISABLE_SYNTHETIC // native shadow doesn't output slots in innerHTML
const expected = process.env.NATIVE_SHADOW // native shadow doesn't output slots in innerHTML
? '<x-shadow-container><p data-id="light-consumer-text">Hello from Light DOM</p></x-shadow-container>'
: '<x-shadow-container><slot><p data-id="light-consumer-text">Hello from Light DOM</p></slot></x-shadow-container>';
expect(nodes['x-light-consumer'].innerHTML).toEqual(expected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('Light DOM styling at the global level', () => {
expect(getColor(elm.querySelector('x-one .globally-styled'))).toEqual('rgb(0, 0, 255)');
expect(getColor(elm.querySelector('x-two .globally-styled'))).toEqual('rgb(0, 0, 255)');
// synthetic shadow can't do this kind of style encapsulation
if (process.env.DISABLE_SYNTHETIC === true) {
if (process.env.NATIVE_SHADOW) {
expect(
getColor(elm.querySelector('x-shadow').shadowRoot.querySelector('.globally-styled'))
).toEqual('rgb(0, 0, 0)');
Expand All @@ -31,7 +31,7 @@ describe('Light DOM styling at the global level', () => {

expect(getColor(two.querySelector('.globally-styled'))).toEqual('rgb(0, 0, 255)');
// synthetic shadow can't do this kind of style encapsulation
if (process.env.DISABLE_SYNTHETIC === true) {
if (process.env.NATIVE_SHADOW) {
expect(getColor(shadow.shadowRoot.querySelector('.globally-styled'))).toEqual(
'rgb(0, 0, 0)'
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createElement } from 'lwc';
import Container from 'x/container';

// synthetic shadow can't do this kind of style encapsulation
if (process.env.DISABLE_SYNTHETIC === true) {
if (process.env.NATIVE_SHADOW) {
describe('Light DOM styling with :host', () => {
it(':host can style a containing shadow component', () => {
const elm = createElement('x-container', { is: Container });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('Light DOM styling', () => {
'rgb(255, 0, 0)'
);
// synthetic shadow can't do this kind of style encapsulation
if (process.env.DISABLE_SYNTHETIC === true) {
if (process.env.NATIVE_SHADOW) {
expect(
getColor(
elm.shadowRoot
Expand All @@ -31,7 +31,7 @@ describe('Light DOM styling', () => {
}

// synthetic shadow can't do this kind of style encapsulation
if (process.env.DISABLE_SYNTHETIC === true) {
if (process.env.NATIVE_SHADOW) {
// sibling elements should be unaffected
const two = createElement('x-two', { is: Two });
const shadow = createElement('x-shadow', { is: Shadow });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createElement } from 'lwc';
import Container from 'x/container';

// This test only matters for synthetic shadow
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
describe('Light DOM and synthetic shadow', () => {
it('shadow scoping tokens are not set for light DOM components', () => {
// shadow grandparent, light child, shadow grandchild
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ function assertNativeShadowRootWhenPossible(elm) {
}
}

const SYNTHETIC_SHADOW_DEFINED = !process.env.DISABLE_SYNTHETIC;

if (SYNTHETIC_SHADOW_DEFINED) {
if (!process.env.NATIVE_SHADOW) {
describe('when root component shadowSupportMode="any"', () => {
let elm;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ if (process.env.COMPAT !== true) {
document.body.appendChild(synthetic);

let expected;
if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
expected = [
div.shadowRoot,
div,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('dynamic nodes', () => {
expect(document.querySelector('span.manual-span')).toBe(null);
});
});
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
// TODO [#1252]: old behavior that is still used by some pieces of the platform
// that is only useful in synthetic mode where elements inserted manually without lwc:dom="manual"
// are still considered global elements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ describe('custom elements', () => {
expect(xSimple.assignedSlot).not.toBeNull();
expect(elm.shadowRoot.querySelector('.mark')).not.toBeNull();

if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
expect(xSimple).not.toBe(firstRenderCustomElement);
}
});
});
});

describe('elements', () => {
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
it('should not be reused when slotted', function () {
const elm = createElement('x-container', { is: Container });
elm.isElement = true;
Expand Down Expand Up @@ -94,7 +94,7 @@ describe('elements', () => {
});
});

if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
it('should render same styles for custom element instances', function () {
const elm = createElement('x-container', { is: Container });
elm.isStyleCheck = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('Event.target', () => {
div.dispatchEvent(new CustomEvent('test', { bubbles: true, composed: true }));
});

if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
describe('legacy behavior', () => {
beforeAll(() => {
// Suppress error logging
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ describe('MutationObserver is synthetic shadow dom aware.', () => {
});
});
});
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
describe('References to mutation observers are not leaked', () => {
let container;
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ describe('Node.childNodes', () => {
// While with synthetic shadow, the fallback slot content is only rendered only when the slot has no assigned
// nodes.
expect(container.shadowRoot.querySelector('slot').childNodes.length).toBe(
process.env.DISABLE_SYNTHETIC ? 1 : 0
process.env.NATIVE_SHADOW ? 1 : 0
);
});

// TODO [#1761]: Difference in behavior of slot.childNodes in native and synthetic-shadow
// enable this test in synthetic-shadow mode once the bug is fixed
if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
it('should always return an default content for slots not rendering default content', () => {
const elm = createElement('x-slotted-parent', { is: SlottedParent });
document.body.appendChild(elm);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ describe('Node.getRootNode', () => {
expect(processingInstruction.getRootNode(composedTrueConfig)).toBe(fragment);
});

if (process.env.DISABLE_SYNTHETIC) {
if (process.env.NATIVE_SHADOW) {
it('native shadow dom', () => {
const shadowHost = document.createElement('div');
document.body.appendChild(shadowHost);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('Node.hasChildNodes', () => {

expect(container.shadowRoot.querySelector('.container').hasChildNodes()).toBe(true);
expect(container.shadowRoot.querySelector('slot').hasChildNodes()).toBe(
process.env.DISABLE_SYNTHETIC
process.env.NATIVE_SHADOW
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ describe('Node.textContent - getter', () => {

const container = elm.shadowRoot.querySelector('x-container');
expect(container.shadowRoot.textContent).toBe(
process.env.DISABLE_SYNTHETIC ? 'Before[default-slotted]After' : 'Before[]After'
process.env.NATIVE_SHADOW ? 'Before[default-slotted]After' : 'Before[]After'
);
expect(container.shadowRoot.querySelector('slot').textContent).toBe(
process.env.DISABLE_SYNTHETIC ? 'default-slotted' : ''
process.env.NATIVE_SHADOW ? 'default-slotted' : ''
);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createElement } from 'lwc';

describe('ShadowRoot.delegatesFocus', () => {
// TODO [#985]: delegatedFocus is only implemented the native ShadowRoot by Blink
if (!process.env.DISABLE_SYNTHETIC) {
if (!process.env.NATIVE_SHADOW) {
it('ShadowRoot.delegatesFocus should be false by default', () => {
class NoDelegatesFocus extends LightningElement {}

Expand Down
Loading