Skip to content

Commit 661cf8e

Browse files
Merge pull request #63 from contentstack/develop
v1.4.0--beta.1
2 parents fde8046 + 15d2353 commit 661cf8e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2365
-1271
lines changed

.eslintrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
"plugin:@typescript-eslint/eslint-recommended",
1313
"plugin:@typescript-eslint/recommended"
1414
],
15+
"env": {
16+
"browser": true,
17+
"node": true
18+
},
19+
1520
"rules": {
1621
"@typescript-eslint/no-explicit-any": 0,
1722
"@typescript-eslint/prefer-const": 0,

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ npm install @contentstack/app-sdk
1313
Alternatively, you can use the following command within the script tag to install the App SDK:
1414

1515
```html
16-
<script src="https://unpkg.com/@contentstack/app-sdk@^1.3.0/dist/index.js"></script>
16+
<script src="https://unpkg.com/@contentstack/app-sdk@^1.4.0/dist/index.js"></script>
1717
```
1818

1919
### Initializing the App SDK

__test__/appConfig.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import EventEmitter from "wolfy87-eventemitter";
2+
import { AppConfig } from "../src/appConfig";
3+
import { ERROR_MESSAGES } from "../src/utils/errorMessages";
4+
5+
describe("app config", () => {
6+
const mockConnection = {
7+
sendToParent: jest.fn().mockReturnValue(Promise.resolve({})),
8+
};
9+
const mockEmitter: EventEmitter = new EventEmitter();
10+
const mockData = {
11+
stack: {},
12+
};
13+
const appConfig: AppConfig = new AppConfig(
14+
mockData,
15+
mockConnection,
16+
mockEmitter,
17+
{ currentBranch: "master" }
18+
);
19+
20+
afterEach(() => {
21+
jest.clearAllMocks();
22+
});
23+
24+
it("stack method should return stack object", () => {
25+
expect(appConfig.stack()).toBeDefined();
26+
});
27+
28+
it("setInstallationData method should send data to parent", () => {
29+
const data = {
30+
configuration: {},
31+
serverConfiguration: {},
32+
};
33+
appConfig.setInstallationData(data);
34+
35+
expect(mockConnection.sendToParent).toHaveBeenLastCalledWith(
36+
"setInstallationData",
37+
data
38+
);
39+
});
40+
it("getInstallationData method should send request to parent for data", () => {
41+
appConfig.getInstallationData();
42+
43+
expect(mockConnection.sendToParent).toHaveBeenLastCalledWith(
44+
"getInstallationData"
45+
);
46+
});
47+
48+
describe("setValidity", () => {
49+
it("should throw error if isValid is not a boolean", async () => {
50+
await expect(appConfig.setValidity("true" as any)).rejects.toThrow(
51+
ERROR_MESSAGES.configPage.setValidity.isValidTypeBoolean
52+
);
53+
});
54+
55+
it("should throw error if message is not a string", async () => {
56+
await expect(
57+
appConfig.setValidity(true, { message: 123 as any })
58+
).rejects.toThrow(
59+
ERROR_MESSAGES.configPage.setValidity.messageTypeString
60+
);
61+
});
62+
63+
it("should work when options parameter is not provided", async () => {
64+
await appConfig.setValidity(true);
65+
66+
expect(mockConnection.sendToParent).toHaveBeenLastCalledWith(
67+
"setValidity",
68+
{ isValid: true }
69+
);
70+
});
71+
72+
it("should send data to parent", async () => {
73+
await appConfig.setValidity(true);
74+
75+
expect(mockConnection.sendToParent).toHaveBeenLastCalledWith(
76+
"setValidity",
77+
{ isValid: true }
78+
);
79+
80+
await appConfig.setValidity(false, { message: "message" });
81+
82+
expect(mockConnection.sendToParent).toHaveBeenLastCalledWith(
83+
"setValidity",
84+
{ isValid: false, options: { message: "message" } }
85+
);
86+
});
87+
});
88+
});

__test__/extension.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import Extension from "../src/extension";
2+
import { IAppConfigInitData } from "../src/types";
3+
4+
jest.mock("post-robot", () => ({
5+
sendToParent: jest.fn(),
6+
on: jest.fn(),
7+
}));
8+
9+
const initData: IAppConfigInitData = {
10+
data: {
11+
type: "APP_CONFIG_WIDGET",
12+
app_id: "app_id",
13+
installation_uid: "installation_uid",
14+
extension_uid: "extension_uid",
15+
stack: {
16+
created_at: "created_at",
17+
updated_at: "updated_at",
18+
uid: "uid",
19+
org_uid: "org_uid",
20+
api_key: "api_key",
21+
master_locale: "master_locale",
22+
is_asset_download_public: true,
23+
owner_uid: "owner_uid",
24+
user_uids: ["user_uids"],
25+
settings: {},
26+
name: "name",
27+
},
28+
user: {},
29+
currentBranch: "currentBranch",
30+
},
31+
};
32+
33+
describe("Main extension", () => {
34+
35+
afterEach(() => {
36+
window["postRobot"] = undefined;
37+
window["iframeRef"] = undefined;
38+
})
39+
40+
it("should have modal property", () => {
41+
const extension = new Extension(initData);
42+
expect(extension.modal).toBeDefined();
43+
})
44+
45+
describe("Properties in the window object", () => {
46+
it("should have postRobot property", () => {
47+
expect(window["postRobot"]).toBeUndefined();
48+
new Extension(initData);
49+
expect(window["postRobot"]).toBeDefined();
50+
51+
Object.prototype.hasOwnProperty.call(
52+
window["postRobot"],
53+
"sendToParent"
54+
);
55+
});
56+
});
57+
});

__test__/extenstion.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import postRobot from "post-robot";
2+
import Extension from "../src/extension";
3+
4+
jest.mock("post-robot", () => ({
5+
__esModule: true,
6+
default: {
7+
on: jest.fn(),
8+
sendToParent: jest.fn(),
9+
},
10+
}));
11+
12+
describe("Extension", () => {
13+
let extensionObj: Extension;
14+
const initializationData = { data: { type: "DASHBOARD" } };
15+
16+
beforeEach(function () {
17+
extensionObj = new Extension(initializationData as any);
18+
});
19+
20+
it("pulse should invoke post robot method with type analytics", () => {
21+
const eventName = "Sample Event";
22+
const metadata = { foo: "bar" };
23+
extensionObj.pulse(eventName, metadata);
24+
expect((postRobot as any).sendToParent).toHaveBeenCalledWith("analytics", {
25+
eventName,
26+
metadata,
27+
});
28+
});
29+
});

__test__/entryFieldLocation/entry.test.ts renamed to __test__/fieldModifierLocation/entry.test.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import EntryFieldLocationEntry from "../../src/entryFieldLocation/entry";
1+
import FieldModifierLocationEntry from "../../src/fieldModifierLocation/entry";
22
import testData from "../data/testData.json";
3-
import { IEntryFieldLocationInitData } from "../../src/types";
4-
import { errorMessage } from "../../src/utils/errorMessages";
3+
import { IFieldModifierLocationInitData } from "../../src/types";
4+
import generateErrorMessages, { ERROR_MESSAGES } from "../../src/utils/errorMessages";
55

6-
describe("EntryFieldLocationEntry", () => {
7-
let entryInstance: EntryFieldLocationEntry;
6+
describe("FieldModifierLocationEntry", () => {
7+
let entryInstance: FieldModifierLocationEntry;
88
let sendToParent: any;
99
let connection: { sendToParent: (...props: any[]) => any };
1010

1111
let emitter: any;
12-
function getEntryInitialData(): IEntryFieldLocationInitData {
12+
function getEntryInitialData(): IFieldModifierLocationInitData {
1313
return {
1414
data: {
15-
type: "ENTRY_FIELD_LOCATION",
15+
type: "FIELD_MODIFIER_LOCATION",
1616
config: {},
1717
content_type: {},
1818
entry: {
@@ -54,7 +54,8 @@ describe("EntryFieldLocationEntry", () => {
5454
},
5555
};
5656
}
57-
const entryIntialData: IEntryFieldLocationInitData = getEntryInitialData();
57+
const entryIntialData: IFieldModifierLocationInitData =
58+
getEntryInitialData();
5859

5960
beforeEach(() => {
6061
sendToParent = () => {};
@@ -73,7 +74,7 @@ describe("EntryFieldLocationEntry", () => {
7374
};
7475

7576
jest.spyOn(emitter, "on");
76-
entryInstance = new EntryFieldLocationEntry(
77+
entryInstance = new FieldModifierLocationEntry(
7778
entryIntialData,
7879
connection,
7980
emitter
@@ -131,19 +132,19 @@ describe("EntryFieldLocationEntry", () => {
131132
it("should throw an error when tags are not defined", async () => {
132133
// @ts-ignore
133134
await expect(entryInstance.setTags()).rejects.toThrow(
134-
errorMessage.entryField.entry.tagsShouldNotBeBlank
135+
generateErrorMessages(ERROR_MESSAGES.entryField.entry.tagsShouldNotBeBlank)
135136
);
136137
});
137138

138139
it("should throw an error if tags is not an array of strings", async () => {
139140
// @ts-ignore
140141
await expect(entryInstance.setTags(["tag3", 4])).rejects.toThrow(
141-
errorMessage.entryField.entry.tagsShouldBeArrayOfStrings
142+
generateErrorMessages(ERROR_MESSAGES.entryField.entry.tagsShouldBeArrayOfStrings)
142143
);
143144

144145
// @ts-ignore
145146
await expect(entryInstance.setTags("tag3")).rejects.toThrow(
146-
errorMessage.entryField.entry.tagsShouldBeArrayOfStrings
147+
generateErrorMessages(ERROR_MESSAGES.entryField.entry.tagsShouldBeArrayOfStrings)
147148
);
148149
});
149150

__test__/entryFieldLocation/field.test.ts renamed to __test__/fieldModifierLocation/field.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Field from "../../src/entryFieldLocation/field";
1+
import Field from "../../src/fieldModifierLocation/field";
22
import testData from "../data/testData.json";
33
import fileFieldData from "../data/fileField.json";
44
import helpers from "../helpers";

__test__/entryFieldLocation/frame.test.ts renamed to __test__/fieldModifierLocation/frame.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import EntryFieldLocationFrame from "../../src/entryFieldLocation/frame";
2-
import { errorMessage } from "../../src/utils/errorMessages";
1+
import FieldModifierLocationFrame from "../../src/fieldModifierLocation/frame";
2+
import { ERROR_MESSAGES } from "../../src/utils/errorMessages";
33
import testData from "../data/testData.json";
44

5-
describe("EntryFieldLocationFrame", () => {
6-
let frameInstance: EntryFieldLocationFrame;
5+
describe("FieldModifierLocationFrame", () => {
6+
let frameInstance: FieldModifierLocationFrame;
77
let sendToParent: any;
88
let connection: { sendToParent: (...props: any[]) => any };
99

@@ -26,7 +26,7 @@ describe("EntryFieldLocationFrame", () => {
2626
};
2727

2828
jest.spyOn(emitter, "on");
29-
frameInstance = new EntryFieldLocationFrame(connection, emitter);
29+
frameInstance = new FieldModifierLocationFrame(connection, emitter);
3030
});
3131

3232
afterEach(() => {
@@ -76,7 +76,7 @@ describe("EntryFieldLocationFrame", () => {
7676
// @ts-ignore
7777
frameInstance.updateDimension({ height: "100" })
7878
).rejects.toThrowError(
79-
errorMessage.entryField.frame.dimensionHeightShouldBeNumber
79+
ERROR_MESSAGES.entryField.frame.dimensionHeightShouldBeNumber
8080
);
8181
});
8282

@@ -85,7 +85,7 @@ describe("EntryFieldLocationFrame", () => {
8585
// @ts-ignore
8686
frameInstance.updateDimension({ width: "100" })
8787
).rejects.toThrowError(
88-
errorMessage.entryField.frame.dimensionWidthShouldBeNumber
88+
ERROR_MESSAGES.entryField.frame.dimensionWidthShouldBeNumber
8989
);
9090
});
9191
});
@@ -108,7 +108,7 @@ describe("EntryFieldLocationFrame", () => {
108108
//@ts-ignore
109109
global.MutationObserver = mutationObserverMock;
110110

111-
frameInstance = new EntryFieldLocationFrame(connection, emitter);
111+
frameInstance = new FieldModifierLocationFrame(connection, emitter);
112112

113113
const [observerInstance] = <void[] | [{ trigger: () => {} }]>(
114114
mutationObserverMock.mock.instances
@@ -150,7 +150,7 @@ describe("EntryFieldLocationFrame", () => {
150150
//@ts-ignore
151151
global.MutationObserver = mutationObserverMock;
152152

153-
frameInstance = new EntryFieldLocationFrame(connection, emitter);
153+
frameInstance = new FieldModifierLocationFrame(connection, emitter);
154154

155155
frameInstance.disableAutoResizing();
156156

__test__/modal.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import Modal from "../src/modal";
2+
3+
describe("Modal module", () => {
4+
const bodyChildInnerText = "body-child";
5+
const divElementInnerText = "separate-div";
6+
7+
const bodyChild = document.createElement("div");
8+
bodyChild.innerText = bodyChildInnerText;
9+
document.body.appendChild(bodyChild);
10+
11+
const divElement = document.createElement("div");
12+
divElement.innerText = divElementInnerText;
13+
document.body.appendChild(divElement);
14+
15+
afterEach(() => {
16+
window["iframeRef"] = undefined;
17+
});
18+
19+
it("should add first child of the body to iframeRef if the user has not provided one", () => {
20+
expect(window["iframeRef"]).toBeUndefined();
21+
22+
new Modal();
23+
expect(window["iframeRef"]).toBeDefined();
24+
expect(window["iframeRef"].tagName).toBe(bodyChild.tagName);
25+
expect(window["iframeRef"].innerText).toBe(bodyChildInnerText);
26+
});
27+
28+
it("should not add anything to iframeRef if it already exists", () => {
29+
window["iframeRef"] = divElement;
30+
31+
new Modal();
32+
const iframeRef = window["iframeRef"];
33+
34+
expect(iframeRef).toBeDefined();
35+
expect(iframeRef.tagName).toBe(divElement.tagName);
36+
expect(iframeRef.innerText).toBe(divElementInnerText);
37+
});
38+
39+
it("should set iframeRef to the element provided by the user", () => {
40+
const modal = new Modal();
41+
modal.setBackgroundElement(divElement);
42+
const iframeRef = window["iframeRef"];
43+
44+
expect(iframeRef).toBeDefined();
45+
expect(iframeRef.tagName).toBe(divElement.tagName);
46+
expect(iframeRef.innerText).toBe(divElementInnerText);
47+
});
48+
});

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)