Skip to content

Commit f4e723e

Browse files
Vp 444 stag sync 2 (#562)
* feat: added enableLivePreviewOutsideIframe key to on or off the outside iframe feature by default * test: added enableLivePreviewOutsideIframe key to on or off the outside iframe feature by default * Vp 444 by default bug fix (#558) * fix: live preview fixed new tab default setup * chore: updated readme file * fix: updated stackSDK usage in init new data flag --------- Co-authored-by: Mridul Sharma <mridul.sharma@contentstack.com> Co-authored-by: Mridul Sharma <109782971+contentstackMridul@users.noreply.github.com>
1 parent 8545559 commit f4e723e

10 files changed

Lines changed: 158 additions & 11 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Alternatively, if you want to include the package directly in your website HTML
1616

1717
```html
1818
<script type='module' crossorigin="anonymous">
19-
import ContentstackLivePreview from 'https://esm.sh/@contentstack/live-preview-utils@4.2.1';
19+
import ContentstackLivePreview from 'https://esm.sh/@contentstack/live-preview-utils@4.3.0';
2020
2121
ContentstackLivePreview.init({
2222
stackDetails: {

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/live-preview-utils",
3-
"version": "4.2.1",
3+
"version": "4.3.0",
44
"description": "Contentstack provides the Live Preview SDK to establish a communication channel between the various Contentstack SDKs and your website, transmitting live changes to the preview pane.",
55
"type": "module",
66
"types": "dist/legacy/index.d.ts",

src/configManager/__test__/configManager.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Config, { updateConfigFromUrl } from "../configManager";
2-
import { getDefaultConfig } from "../config.default";
2+
import { getDefaultConfig, getUserInitData } from "../config.default";
33
import { DeepSignal } from "deepsignal";
44
import { IConfig } from "../../types/types";
55

@@ -90,6 +90,18 @@ describe("Config", () => {
9090
});
9191
});
9292

93+
describe("config default flags", () => {
94+
test("enableLivePreviewOutsideIframe defaults to undefined in getDefaultConfig", () => {
95+
const defaultConfig = getDefaultConfig();
96+
expect(defaultConfig.enableLivePreviewOutsideIframe).toBeUndefined();
97+
});
98+
99+
test("enableLivePreviewOutsideIframe defaults to undefined in getUserInitData", () => {
100+
const initData = getUserInitData();
101+
expect(initData.enableLivePreviewOutsideIframe).toBeUndefined();
102+
});
103+
});
104+
93105
describe("update config from url", () => {
94106
let config: DeepSignal<IConfig>;
95107

src/configManager/__test__/handleUserConfig.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,41 @@ describe("handleInitData()", () => {
411411
});
412412
});
413413

414+
describe("handleInitData() - enableLivePreviewOutsideIframe", () => {
415+
let config: DeepSignal<IConfig>;
416+
417+
beforeEach(() => {
418+
Config.reset();
419+
config = Config.get();
420+
});
421+
422+
afterAll(() => {
423+
Config.reset();
424+
});
425+
426+
test("should default to undefined when not provided", () => {
427+
const initData: Partial<IInitData> = {};
428+
handleInitData(initData);
429+
expect(config.enableLivePreviewOutsideIframe).toBeUndefined();
430+
});
431+
432+
test("should set to true when provided as true", () => {
433+
const initData: Partial<IInitData> = {
434+
enableLivePreviewOutsideIframe: true,
435+
};
436+
handleInitData(initData);
437+
expect(config.enableLivePreviewOutsideIframe).toBe(true);
438+
});
439+
440+
test("should remain false when provided as false", () => {
441+
const initData: Partial<IInitData> = {
442+
enableLivePreviewOutsideIframe: false,
443+
};
444+
handleInitData(initData);
445+
expect(config.enableLivePreviewOutsideIframe).toBe(false);
446+
});
447+
});
448+
414449
describe("handleClientUrlParams()", () => {
415450
let config: DeepSignal<IConfig>;
416451

src/configManager/config.default.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export function getUserInitData(): IInitData {
3939
environment: "",
4040
},
4141
runScriptsOnUpdate: false,
42+
enableLivePreviewOutsideIframe: undefined,
4243
};
4344
}
4445

@@ -110,5 +111,6 @@ export function getDefaultConfig(): IConfig {
110111
},
111112
payload: [],
112113
},
114+
enableLivePreviewOutsideIframe: undefined,
113115
};
114116
}

src/configManager/handleUserConfig.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ export const handleInitData = (initData: Partial<IInitData>): void => {
121121
"bottom-right",
122122
})
123123

124+
Config.set(
125+
"enableLivePreviewOutsideIframe",
126+
initData.enableLivePreviewOutsideIframe ??
127+
config.enableLivePreviewOutsideIframe
128+
);
129+
124130
// client URL params
125131
handleClientUrlParams(
126132
initData.clientUrlParams ??

src/livePreview/eventManager/__test__/postMessageEvent.hooks.test.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import {
1515
import {
1616
useOnEntryUpdatePostMessageEvent,
1717
useHistoryPostMessageEvent,
18+
sendInitializeLivePreviewPostMessageEvent,
1819
} from "../postMessageEvent.hooks";
1920
import { isOpeningInNewTab } from "../../../common/inIframe";
2021

2122
// Mock dependencies
2223
vi.mock("../../../configManager/configManager", () => ({
2324
default: {
2425
get: vi.fn(),
26+
set: vi.fn(),
2527
},
2628
setConfigFromParams: vi.fn(),
2729
}));
@@ -35,13 +37,19 @@ vi.mock("../../../logger/logger", () => ({
3537
vi.mock("../livePreviewEventManager", () => ({
3638
default: {
3739
on: vi.fn(),
40+
send: vi.fn(),
3841
},
3942
}));
4043

4144
vi.mock("../../../common/inIframe", () => ({
4245
isOpeningInNewTab: vi.fn(),
4346
}));
4447

48+
vi.mock("../../../utils", () => ({
49+
addParamsToUrl: vi.fn(),
50+
isOpeningInTimeline: vi.fn(() => false),
51+
}));
52+
4553
describe("postMessageEvent.hooks", () => {
4654
let mockWindow: any;
4755
let mockConfig: any;
@@ -415,4 +423,73 @@ describe("postMessageEvent.hooks", () => {
415423
}).toThrow("Unhandled event: unknown");
416424
});
417425
});
426+
427+
describe("sendInitializeLivePreviewPostMessageEvent", () => {
428+
beforeEach(() => {
429+
// default send resolves with preview windowType, no contentType/entry to avoid side-effects
430+
(livePreviewPostMessage as any).send.mockResolvedValue({
431+
windowType: "preview",
432+
});
433+
});
434+
435+
it("should omit enableLivePreviewOutsideIframe in INIT payload when config is unset", async () => {
436+
mockConfig = {
437+
ssr: true,
438+
mode: 1,
439+
enableLivePreviewOutsideIframe: undefined,
440+
};
441+
(Config.get as any).mockReturnValue(mockConfig);
442+
443+
await sendInitializeLivePreviewPostMessageEvent();
444+
await Promise.resolve();
445+
446+
const initPayload = (livePreviewPostMessage?.send as any).mock.calls.at(-1)?.[1];
447+
expect(initPayload.config).not.toHaveProperty(
448+
"enableLivePreviewOutsideIframe"
449+
);
450+
});
451+
452+
it("should include enableLivePreviewOutsideIframe=false in INIT payload", async () => {
453+
mockConfig = {
454+
ssr: true, // avoid timers
455+
mode: 1,
456+
enableLivePreviewOutsideIframe: false,
457+
};
458+
(Config.get as any).mockReturnValue(mockConfig);
459+
460+
await sendInitializeLivePreviewPostMessageEvent();
461+
// allow microtasks to flush
462+
await Promise.resolve();
463+
464+
expect(livePreviewPostMessage?.send).toHaveBeenCalledWith(
465+
LIVE_PREVIEW_POST_MESSAGE_EVENTS.INIT,
466+
expect.objectContaining({
467+
config: expect.objectContaining({
468+
enableLivePreviewOutsideIframe: false,
469+
}),
470+
})
471+
);
472+
});
473+
474+
it("should include enableLivePreviewOutsideIframe=true in INIT payload", async () => {
475+
mockConfig = {
476+
ssr: true, // avoid timers
477+
mode: 1,
478+
enableLivePreviewOutsideIframe: true,
479+
};
480+
(Config.get as any).mockReturnValue(mockConfig);
481+
482+
await sendInitializeLivePreviewPostMessageEvent();
483+
await Promise.resolve();
484+
485+
expect(livePreviewPostMessage?.send).toHaveBeenCalledWith(
486+
LIVE_PREVIEW_POST_MESSAGE_EVENTS.INIT,
487+
expect.objectContaining({
488+
config: expect.objectContaining({
489+
enableLivePreviewOutsideIframe: true,
490+
}),
491+
})
492+
);
493+
});
494+
});
418495
});

src/livePreview/eventManager/postMessageEvent.hooks.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,29 @@ export function useOnEntryUpdatePostMessageEvent(): void {
119119
}
120120

121121
export function sendInitializeLivePreviewPostMessageEvent(): void {
122+
const config = Config.get();
123+
const initConfig: {
124+
shouldReload: boolean;
125+
href: string;
126+
sdkVersion: string | undefined;
127+
mode: number;
128+
enableLivePreviewOutsideIframe?: boolean;
129+
} = {
130+
shouldReload: config.ssr,
131+
href: window.location.href,
132+
sdkVersion: process?.env?.PACKAGE_VERSION,
133+
mode: config.mode,
134+
};
135+
136+
if (config.enableLivePreviewOutsideIframe !== undefined) {
137+
initConfig.enableLivePreviewOutsideIframe = config.enableLivePreviewOutsideIframe;
138+
}
139+
122140
livePreviewPostMessage
123141
?.send<LivePreviewInitEventResponse>(
124142
LIVE_PREVIEW_POST_MESSAGE_EVENTS.INIT,
125143
{
126-
config: {
127-
shouldReload: Config.get().ssr,
128-
href: window.location.href,
129-
sdkVersion: process?.env?.PACKAGE_VERSION,
130-
mode: Config.get().mode,
131-
},
144+
config: initConfig,
132145
}
133146
)
134147
.then((data) => {

src/types/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export declare interface IConfig {
8787
highlightedElement: HTMLElement | null;
8888
};
8989
collab: ICollabConfig["collab"];
90+
enableLivePreviewOutsideIframe: boolean | undefined;
9091
}
9192

9293

@@ -132,6 +133,7 @@ export declare interface IInitData {
132133
editButton: IConfigEditButton;
133134
editInVisualBuilderButton: IConfigEditInVisualBuilderButton;
134135
mode: ILivePreviewMode;
136+
enableLivePreviewOutsideIframe: boolean | undefined; // default: undefined
135137
}
136138

137139
// type PickPartial<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>;

0 commit comments

Comments
 (0)