Skip to content

Commit 7087835

Browse files
author
Kaushik Shetty
committed
test: add unit tests for init and asset sidebar modules
1 parent 0a03e77 commit 7087835

File tree

2 files changed

+313
-0
lines changed

2 files changed

+313
-0
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
import EventEmitter from "wolfy87-eventemitter";
2+
3+
import AssetSidebarWidget from "../src/AssetSidebarWidget";
4+
import { IAssetSidebarInitData } from "../src/types";
5+
import Asset from "../src/stack/api/asset";
6+
7+
jest.mock("post-robot", () => ({
8+
__esModule: true,
9+
default: {
10+
sendToParent: jest.fn(),
11+
},
12+
}));
13+
14+
jest.mock("../src/stack/api/asset");
15+
16+
describe("AssetSidebarWidget", () => {
17+
let assetSidebarWidget: AssetSidebarWidget;
18+
let mockInitData: IAssetSidebarInitData = {
19+
data: {
20+
type: "ASSET_SIDEBAR_WIDGET",
21+
currentAsset: {},
22+
config: {},
23+
app_id: "mock_app_uid",
24+
installation_uid: "mock_installation_uid",
25+
extension_uid: "mock_extension_uid",
26+
stack: {} as any,
27+
user: {},
28+
currentBranch: "mock_branch",
29+
region: "region",
30+
},
31+
};
32+
33+
let connection: { sendToParent: (...props: any[]) => any };
34+
let sendToParent;
35+
let emitter: EventEmitter;
36+
37+
beforeEach(function () {
38+
sendToParent = function () {
39+
return Promise.resolve({ data: {} });
40+
};
41+
42+
emitter = {
43+
on: (_event, cbf) => {
44+
setTimeout(() => {
45+
cbf({ state: "full_width" });
46+
}, 50);
47+
},
48+
} as EventEmitter;
49+
50+
jest.spyOn(emitter, "on");
51+
52+
connection = { sendToParent };
53+
jest.spyOn(connection, "sendToParent");
54+
assetSidebarWidget = new AssetSidebarWidget(
55+
mockInitData as IAssetSidebarInitData,
56+
connection,
57+
emitter
58+
);
59+
});
60+
61+
afterEach(() => {
62+
jest.resetAllMocks();
63+
});
64+
65+
it("should set instance properties in constructor", () => {
66+
expect(assetSidebarWidget.currentAsset).toBe(
67+
mockInitData.data.currentAsset
68+
);
69+
expect(assetSidebarWidget._emitter).toBe(emitter);
70+
expect(assetSidebarWidget._connection).toBe(connection);
71+
});
72+
73+
describe("getData", () => {
74+
it("should return the current asset", () => {
75+
const currentAsset = assetSidebarWidget.getData();
76+
expect(currentAsset).toBe(mockInitData.data.currentAsset);
77+
});
78+
});
79+
80+
describe("setData", () => {
81+
it("should set the current asset with the one provided", async () => {
82+
const asset = {};
83+
const result = await assetSidebarWidget.setData(asset);
84+
expect(connection.sendToParent).toHaveBeenCalledWith(
85+
"setData",
86+
asset
87+
);
88+
expect(result).toEqual({ data: {} });
89+
});
90+
});
91+
92+
describe("syncAsset", () => {
93+
it("should sync the upstream asset with the current", async () => {
94+
const result = await assetSidebarWidget.syncAsset();
95+
expect(connection.sendToParent).toHaveBeenCalledWith("syncAsset");
96+
expect(result).toEqual({ data: {} });
97+
});
98+
});
99+
100+
describe("updateWidth", () => {
101+
it("should throw an error if width is invalid", () => {
102+
const error = new Error("Width must be a number");
103+
expect(
104+
assetSidebarWidget.updateWidth("500" as any)
105+
).rejects.toThrowError(error);
106+
});
107+
108+
it("should update the width with the one provided", async () => {
109+
const mockWidth = 500;
110+
const result = await assetSidebarWidget.updateWidth(mockWidth);
111+
expect(connection.sendToParent).toHaveBeenCalledWith(
112+
"updateAssetSidebarWidth",
113+
mockWidth
114+
);
115+
expect(result).toEqual({ data: {} });
116+
});
117+
});
118+
119+
describe("replaceAsset", () => {
120+
it("should sync the upstream asset with the current", async () => {
121+
const mockHandleUpload = jest.fn();
122+
(Asset as jest.Mock).mockReturnValue({
123+
handleUpload: mockHandleUpload,
124+
});
125+
const file = {} as any;
126+
const result = await assetSidebarWidget.replaceAsset(file);
127+
expect(Asset).toHaveBeenLastCalledWith(emitter);
128+
expect(mockHandleUpload).toHaveBeenCalledWith([file], "replace");
129+
});
130+
});
131+
132+
describe("onSave", () => {
133+
it("should only accept functions as a callback", () => {
134+
const mockCallback: any = {};
135+
const error = new Error("Callback must be a function");
136+
expect(() => assetSidebarWidget.onSave(mockCallback)).toThrow(
137+
error
138+
);
139+
});
140+
141+
it("should setup a listener for assetSave event", () => {
142+
const mockCallback = jest.fn();
143+
const result = assetSidebarWidget.onSave(mockCallback);
144+
expect(emitter.on).toHaveBeenLastCalledWith(
145+
"assetSave",
146+
expect.any(Function)
147+
);
148+
expect(result).toBeUndefined();
149+
});
150+
151+
it("should invoke the callback provided ", () => {
152+
const mockCallback = jest.fn();
153+
jest.useFakeTimers();
154+
assetSidebarWidget.onSave(mockCallback);
155+
expect(emitter.on).toHaveBeenLastCalledWith(
156+
"assetSave",
157+
expect.any(Function)
158+
);
159+
jest.runAllTimers();
160+
expect(mockCallback).toHaveBeenCalled();
161+
});
162+
});
163+
164+
describe("onChange", () => {
165+
it("should only accept functions as a callback", () => {
166+
const mockCallback: any = {};
167+
const error = new Error("Callback must be a function");
168+
expect(() => assetSidebarWidget.onChange(mockCallback)).toThrow(
169+
error
170+
);
171+
});
172+
173+
it("should setup a listener for assetSave event", () => {
174+
const mockCallback = jest.fn();
175+
const result = assetSidebarWidget.onChange(mockCallback);
176+
expect(emitter.on).toHaveBeenLastCalledWith(
177+
"assetChange",
178+
expect.any(Function)
179+
);
180+
expect(result).toBeUndefined();
181+
});
182+
183+
it("should invoke the callback provided ", () => {
184+
const mockCallback = jest.fn();
185+
jest.useFakeTimers();
186+
assetSidebarWidget.onChange(mockCallback);
187+
expect(emitter.on).toHaveBeenLastCalledWith(
188+
"assetChange",
189+
expect.any(Function)
190+
);
191+
jest.runAllTimers();
192+
expect(mockCallback).toHaveBeenCalled();
193+
});
194+
});
195+
196+
describe("onPublish", () => {
197+
it("should only accept functions as a callback", () => {
198+
const mockCallback: any = {};
199+
const error = new Error("Callback must be a function");
200+
expect(() => assetSidebarWidget.onPublish(mockCallback)).toThrow(
201+
error
202+
);
203+
});
204+
205+
it("should setup a listener for assetSave event", () => {
206+
const mockCallback = jest.fn();
207+
const result = assetSidebarWidget.onPublish(mockCallback);
208+
expect(emitter.on).toHaveBeenLastCalledWith(
209+
"assetPublish",
210+
expect.any(Function)
211+
);
212+
expect(result).toBeUndefined();
213+
});
214+
215+
it("should invoke the callback provided ", () => {
216+
const mockCallback = jest.fn();
217+
jest.useFakeTimers();
218+
assetSidebarWidget.onPublish(mockCallback);
219+
expect(emitter.on).toHaveBeenLastCalledWith(
220+
"assetPublish",
221+
expect.any(Function)
222+
);
223+
jest.runAllTimers();
224+
expect(mockCallback).toHaveBeenCalled();
225+
});
226+
});
227+
228+
describe("onUnPublish", () => {
229+
it("should only accept functions as a callback", () => {
230+
const mockCallback: any = {};
231+
const error = new Error("Callback must be a function");
232+
expect(() => assetSidebarWidget.onUnPublish(mockCallback)).toThrow(
233+
error
234+
);
235+
});
236+
237+
it("should setup a listener for assetSave event", () => {
238+
const mockCallback = jest.fn();
239+
const result = assetSidebarWidget.onUnPublish(mockCallback);
240+
expect(emitter.on).toHaveBeenLastCalledWith(
241+
"assetUnPublish",
242+
expect.any(Function)
243+
);
244+
expect(result).toBeUndefined();
245+
});
246+
247+
it("should invoke the callback provided ", () => {
248+
const mockCallback = jest.fn();
249+
jest.useFakeTimers();
250+
assetSidebarWidget.onUnPublish(mockCallback);
251+
expect(emitter.on).toHaveBeenLastCalledWith(
252+
"assetUnPublish",
253+
expect.any(Function)
254+
);
255+
jest.runAllTimers();
256+
expect(mockCallback).toHaveBeenCalled();
257+
});
258+
});
259+
});

__test__/init.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import ContentstackAppSDK from "../src/index";
2+
import Extension from "../src/extension";
3+
import { version } from "../package.json";
4+
5+
jest.mock("../src/extension");
6+
7+
describe("ContentstackAppSDK", () => {
8+
describe("init", () => {
9+
const mockInitData = {
10+
worked: true,
11+
};
12+
beforeEach(() => {
13+
const mockInitialize = jest.fn().mockResolvedValue(mockInitData);
14+
Extension.initialize = mockInitialize;
15+
});
16+
17+
afterEach(() => {
18+
// Reset the static variable after every test
19+
(ContentstackAppSDK._extension as any) = undefined;
20+
jest.resetAllMocks();
21+
});
22+
23+
it("should initialize the extension and return an instance of Extension", async () => {
24+
const extension = await ContentstackAppSDK.init();
25+
26+
expect(Extension.initialize).toHaveBeenCalledTimes(1);
27+
expect(Extension.initialize).toBeCalledWith(version);
28+
expect(Extension).toHaveBeenCalledWith(mockInitData);
29+
expect(extension).toBeInstanceOf(Extension);
30+
});
31+
32+
it("should return the same instance of Extension if it has already been initialized", async () => {
33+
(Extension.initialize as jest.Mock).mockResolvedValue(mockInitData);
34+
const extension = await ContentstackAppSDK.init();
35+
const extension2 = await ContentstackAppSDK.init();
36+
37+
expect(Extension.initialize).toHaveBeenCalledTimes(1);
38+
expect(extension).toBe(extension2);
39+
});
40+
41+
it("should reject the promise if initialization fails", async () => {
42+
const error = new Error("Initialization failed");
43+
(Extension.initialize as jest.Mock).mockRejectedValue(error);
44+
45+
await expect(ContentstackAppSDK.init()).rejects.toThrow(error);
46+
});
47+
});
48+
49+
describe("SDK_VERSION", () => {
50+
it("should return the version of the SDK", () => {
51+
expect(ContentstackAppSDK.SDK_VERSION).toBe(version);
52+
});
53+
});
54+
});

0 commit comments

Comments
 (0)