Skip to content

Commit

Permalink
test(integration-karma): add a new FORCED_MIXED_SHADOW_MODE (#2496)
Browse files Browse the repository at this point in the history
  • Loading branch information
rui-rayqiu authored Oct 4, 2021
1 parent c5db1bc commit c7db20f
Show file tree
Hide file tree
Showing 37 changed files with 84 additions and 65 deletions.
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;
}
}

// 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
2 changes: 1 addition & 1 deletion packages/integration-karma/test/host-element/index.spec.js
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
4 changes: 2 additions & 2 deletions packages/integration-karma/test/light-dom/style/index.spec.js
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

0 comments on commit c7db20f

Please sign in to comment.