Skip to content

Commit ed9c66a

Browse files
fix: test coverage for signal/context validation behavior
1 parent 0804c69 commit ed9c66a

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (c) 2025, salesforce.com, inc.
3+
* All rights reserved.
4+
* SPDX-License-Identifier: MIT
5+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6+
*/
7+
import { describe, it, expect, vi, beforeAll, afterEach } from 'vitest';
8+
import { setFeatureFlagForTest } from '@lwc/features';
9+
import { setTrustedContextSet, setContextKeys } from '@lwc/shared';
10+
import { logWarnOnce } from '../../shared/logger';
11+
import { connectContext, disconnectContext } from '../modules/context';
12+
13+
// Mock the logger to avoid console output during tests
14+
vi.mock('../../shared/logger', () => ({
15+
logWarnOnce: vi.fn(),
16+
}));
17+
18+
// Create mock component with a regular, non-contextful property
19+
const mockComponent = {};
20+
Object.setPrototypeOf(mockComponent, {
21+
regularProp: 'not contextful',
22+
});
23+
24+
// Create mock renderer
25+
const mockRenderer = {
26+
registerContextProvider: vi.fn(),
27+
};
28+
29+
// Create mock VM
30+
const mockVM = {
31+
component: mockComponent,
32+
elm: null,
33+
renderer: mockRenderer,
34+
} as any;
35+
36+
/**
37+
* These tests test that properties are correctly validated within the connectContext and disconnectContext
38+
* functions regardless of whether trusted context has been defined or not.
39+
* Integration tests have been used for extensive coverage of the LWC context feature, but this particular
40+
* scenario is best isolated and unit tested as it involves manipulation of the trusted context API.
41+
*/
42+
describe('context functions', () => {
43+
beforeAll(() => {
44+
const connectContext = Symbol('connectContext');
45+
const disconnectContext = Symbol('disconnectContext');
46+
setContextKeys({ connectContext, disconnectContext });
47+
});
48+
49+
afterEach(() => {
50+
vi.clearAllMocks();
51+
});
52+
53+
describe('without setting trusted context', () => {
54+
it('should log a warning when trustedContext is not defined and connectContext is called with legacy signal context validation', () => {
55+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', true);
56+
connectContext(mockVM);
57+
expect(logWarnOnce).toHaveBeenCalledWith(
58+
'Attempted to connect to trusted context but received the following error: component[contextfulKeys[i]][connectContext2] is not a function'
59+
);
60+
});
61+
62+
it('should not log a warning when trustedContext is not defined and connectContext is called with non-legacy context validation', () => {
63+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', false);
64+
connectContext(mockVM);
65+
expect(logWarnOnce).not.toHaveBeenCalled();
66+
});
67+
68+
it('should log a warning when trustedContext is not defined and disconnectContext is called with legacy signal context validation', () => {
69+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', true);
70+
disconnectContext(mockVM);
71+
expect(logWarnOnce).toHaveBeenCalledWith(
72+
'Attempted to disconnect from trusted context but received the following error: component[contextfulKeys[i]][disconnectContext2] is not a function'
73+
);
74+
});
75+
76+
it('should not log a warning when trustedContext is not defined and disconnectContext is called with non-legacy context validation', () => {
77+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', false);
78+
disconnectContext(mockVM);
79+
expect(logWarnOnce).not.toHaveBeenCalled();
80+
});
81+
});
82+
83+
describe('with trusted context set', () => {
84+
it('should not log warnings when trustedContext is defined', () => {
85+
setTrustedContextSet(new WeakSet());
86+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', true);
87+
connectContext(mockVM);
88+
disconnectContext(mockVM);
89+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', false);
90+
expect(logWarnOnce).not.toHaveBeenCalled();
91+
});
92+
});
93+
});
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2019, salesforce.com, inc.
3+
* All rights reserved.
4+
* SPDX-License-Identifier: MIT
5+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6+
*/
7+
import { describe, it, expect, vi, afterEach, beforeEach, afterAll, beforeAll } from 'vitest';
8+
import { setTrustedSignalSet } from '@lwc/shared';
9+
import { setFeatureFlagForTest } from '@lwc/features';
10+
import { componentValueObserved } from '../../framework/mutation-tracker';
11+
12+
// Create a mock VM object with required properties
13+
const mockVM = {
14+
component: {},
15+
tro: {
16+
isObserving: () => true,
17+
},
18+
} as any;
19+
20+
/**
21+
* These tests check that properties are correctly validated within the mutation-tracker
22+
* regardless of whether trusted context has been defined by a state manager or not.
23+
* Integration tests have been used for extensive coverage of the LWC signals feature, but this particular
24+
* scenario is best isolated and unit tested as it involves manipulation of the trusted context API.
25+
*/
26+
describe('mutation-tracker', () => {
27+
it('should not throw when componentValueObserved is called using the new signals validation and no signal set is defined', () => {
28+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', false);
29+
expect(() => {
30+
componentValueObserved(mockVM, 'testKey', {});
31+
}).not.toThrow();
32+
});
33+
34+
it('should throw when componentValueObserved is called using legacy signals validation and no signal set has been defined', () => {
35+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', true);
36+
expect(() => {
37+
componentValueObserved(mockVM, 'testKey', {});
38+
}).toThrow();
39+
});
40+
41+
it('should not throw when a trusted signal set is defined abd componentValueObserved is called', () => {
42+
setTrustedSignalSet(new WeakSet());
43+
44+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', false);
45+
expect(() => {
46+
componentValueObserved(mockVM, 'testKey', {});
47+
}).not.toThrow();
48+
49+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', true);
50+
expect(() => {
51+
componentValueObserved(mockVM, 'testKey', {});
52+
}).not.toThrow();
53+
});
54+
55+
beforeAll(() => {
56+
setFeatureFlagForTest('ENABLE_EXPERIMENTAL_SIGNALS', true);
57+
});
58+
59+
afterAll(() => {
60+
setFeatureFlagForTest('ENABLE_EXPERIMENTAL_SIGNALS', false);
61+
setFeatureFlagForTest('ENABLE_LEGACY_SIGNAL_CONTEXT_VALIDATION', false);
62+
});
63+
64+
beforeEach(() => {
65+
vi.stubEnv('IS_BROWSER', 'true'); // Signals is a browser-only feature
66+
});
67+
68+
afterEach(() => {
69+
vi.unstubAllEnvs(); // Reset environment variables after each test
70+
});
71+
});

0 commit comments

Comments
 (0)