@etsoo/appscript
Version:
Applications shared TypeScript framework
288 lines (242 loc) • 8.09 kB
text/typescript
import { ApiDataError, ApiMethod } from "@etsoo/restclient";
import { DataTypes, ExtendUtils, IActionResult } from "@etsoo/shared";
import {
EntityStatus,
ExternalEndpoint,
ExternalSettings,
UserRole
} from "../../src";
import { TestApp } from "./TestApp";
// Arrange
// Mixins example
function EnhanceApp<TBase extends DataTypes.MConstructor<TestApp>>(
Base: TBase
) {
return class extends Base {};
}
const appClass = EnhanceApp(TestApp);
const app = new appClass();
// First make sure the default culture (here is 'en') is loaded
await ExtendUtils.sleep(50);
// Then change the culture to the first one (here is 'zh-CN')
await app.changeCulture(app.settings.cultures[0]);
await ExtendUtils.sleep(50);
test("Test for domain substitution", () => {
expect(app.settings.endpoint).toBe("http://admin.etsoo.com:9000/api/");
expect(app.settings.endpoints?.core.endpoint).toBe(
"https://core.etsoo.com:9001/api/"
);
});
test("Test for formatApp", () => {
expect(
ExternalSettings.formatApp(
"admin.app.local",
"core",
"https://{hostname}/api/"
)
).toBe("https://core.app.local/api/");
expect(
ExternalSettings.formatApp("localhost", "admin", "https://{hostname}/api/")
).toBe("https://localhost/api/");
// Custom sub domain match
ExternalSettings.subDomainMatch = /app(?=\.)/i;
expect(
ExternalSettings.formatApp(
"admin.app.local",
"core",
"https://{hostname}/api/"
)
).toBe("https://admin.core.local/api/");
});
test("Test for formatHost with endpoints", () => {
// Reset sub domain match
ExternalSettings.subDomainMatch = /(?<=\/\/)[0-9a-z]+(?=\.)/i;
const endpoints: Record<string, ExternalEndpoint> = {
core: {
endpoint: "https://{hostname}/api/",
webUrl: "https://{hostname}/"
}
};
const result = ExternalSettings.formatHost(endpoints, "admin.app.local");
expect(result).toStrictEqual({
core: {
endpoint: "https://core.app.local/api/",
webUrl: "https://core.app.local/"
}
});
});
test("Test for properties", () => {
expect(app.settings.currentRegion.label).toBe("中国大陆");
});
test("Test for formatAction", () => {
Object.assign(app.settings.currentCulture.resources, {
appName: "司友®云ERP"
});
expect(app.formatAction("修改", "客户A")).toBe("[司友®云ERP] 修改 - 客户A");
expect(app.formatAction("修改", "客户A", "企业")).toBe(
"[司友®云ERP] 修改 - 客户A, 企业"
);
});
test("Tests for addRootUrl", () => {
expect(app.addRootUrl("/home")).toBe("/cms/home");
expect(app.addRootUrl("./home")).toBe("/cms/./home");
expect(app.addRootUrl("home")).toBe("/cms/home");
});
test("Tests for encrypt / decrypt", async () => {
// Arrange
const input = "Hello, world!";
const passphrase = "My password";
await new Promise((resolve) => setTimeout(resolve, 100));
// Act
const encrypted = app.encrypt(input, passphrase);
const plain = app.decrypt(encrypted, passphrase);
expect(plain).toEqual(input);
});
test("Tests for encryptEnhanced / decryptEnhanced", async () => {
// Arrange
const input = "Hello, world!";
const passphrase = "My password";
await new Promise((resolve) => setTimeout(resolve, 100));
// Act
const encrypted = app.encryptEnhanced(input, passphrase);
const plain = app.decryptEnhanced(encrypted, passphrase);
expect(plain).toEqual(input);
});
test("Tests for initCallUpdateLocal", () => {
// Act
const passphrase = app.initCallUpdateLocal(
{
deviceId:
"ZmNjZlov+10067A1520126643352C2022735B85DC8F380088468402C98A5631A8CFBE14E134zXfxmw77lFopTTlbqOfsK2KUqPSsTAQb35Ejrm1BAvUaQH3SuZcwGYu3+PQ/Rd56",
passphrase:
"01397BF28A93FC031BC8B9B808F880F12C398AB792DF2ADE7A8768CADD2259EB50HJuKhqGuLQO+SmvCVzuEGUN4TdkUuPMWR0E6lliszbNiXboCziXx5SdfX3lMpoBX"
},
1639282438620
);
expect(passphrase).not.toBeNull();
});
test("Tests for formatFullName", () => {
expect(app.formatFullName("亿速", null)).toBe("亿速");
expect(app.formatFullName(null, null)).toBe("");
expect(app.formatFullName("亿速", "思维")).toBe("亿速思维");
expect(app.formatFullName("Xiao", "Garry")).toBe("Garry Xiao");
});
test("Tests for getRoleLabel", () => {
const labels = app.getRoleLabel(
UserRole.User | UserRole.Manager | UserRole.Admin,
"-"
);
expect(labels).toBe("User-Manager-Admin");
});
test("Tests for getRoles", () => {
const roles = app.getRoles(UserRole.User | UserRole.Manager | UserRole.Admin);
expect(roles.length).toBe(3);
expect(roles.map((r) => r.id)).toEqual([16, 64, 8192]);
});
test("Tests for getStatusList", () => {
const statuses = app.getStatusList([
EntityStatus.Normal,
EntityStatus.Approved,
EntityStatus.Doing,
EntityStatus.Completed,
EntityStatus.Deleted
]);
expect(statuses.length).toBe(5);
expect(statuses.map((s) => s.id)).toStrictEqual([0, 100, 110, 250, 255]);
expect(app.getStatusList().length).toBe(9);
});
test("Tests for formatResult", () => {
const result: IActionResult = {
ok: false,
type: "https://tools.ietf.org/html/rfc9110#section-15.5.1",
title: "One or more validation errors occurred.",
status: 400,
errors: {
$: [
"JSON deserialization for type \u0027com.etsoo.CMS.RQ.User.UserCreateRQ\u0027 was missing required properties, including the following: password"
],
rq: ["The rq field is required."]
},
traceId: "00-ed96a4f0c83f066594ecc69b77da9803-df770e3cd714fedd-00"
};
const formatted = app.formatResult(result);
expect(formatted).toBe(
"One or more validation errors occurred. (400, https://tools.ietf.org/html/rfc9110#section-15.5.1)"
);
});
test("Tests for formatResult with type", () => {
const result: IActionResult = {
ok: false,
type: "TokenExpired",
title: "您的令牌已过期",
data: {}
};
const formatted = app.formatResult(result);
expect(formatted).toBe("您的令牌已过期 (TokenExpired)");
});
test("Tests for formatResult with custom label", () => {
const result: IActionResult = {
ok: false,
type: "ItemRequired",
title: "{0} is required.",
field: "url"
};
const formatted = app.formatResult(result, () => "Url");
expect(formatted).toBe("Url is required. (ItemRequired, url)");
});
test("Tests for formatResult with custom label", () => {
const result: IActionResult = {
ok: false,
type: "ItemExists",
field: "url"
};
const fieldLabel = "文章地址";
const formatted = app.formatResult(result, () => fieldLabel);
expect(formatted).toBe(`'${fieldLabel}'已经存在 (ItemExists, url)`);
});
test("Tests for formatError", () => {
const error: ApiDataError = {
name: "ApiDataError",
message: "Api data error",
response: {
type: "https://tools.ietf.org/html/rfc9110#section-15.5.1",
title: "One or more validation errors occurred.",
status: 400,
errors: {
$: [
"JSON deserialization for type \u0027com.etsoo.CMS.RQ.User.UserCreateRQ\u0027 was missing required properties, including the following: password"
],
rq: ["The rq field is required."]
},
traceId: "00-ed96a4f0c83f066594ecc69b77da9803-df770e3cd714fedd-00"
},
data: {
data: undefined,
headers: [],
method: ApiMethod.POST,
params: {},
url: ""
}
};
expect(app.formatError(error)).toBe("Api data error (ApiDataError)");
});
test("Tests for isValidPassword", () => {
expect(app.isValidPassword("12345678")).toBeFalsy();
expect(app.isValidPassword("abcd3")).toBeFalsy();
expect(app.isValidPassword("1234abcd")).toBeTruthy();
});
test("Tests for checkSesession", async () => {
await app.checkSession((isSame) => {
expect(isSame).toBeFalsy();
return Promise.resolve();
});
await app.checkSession((isSame) => {
expect(isSame).toBeTruthy();
return Promise.resolve();
});
app.clearSession();
await app.checkSession((isSame) => {
expect(isSame).toBeFalsy();
return Promise.resolve();
});
});