@tsed/formio
Version:
Formio package for Ts.ED framework
397 lines (342 loc) • 12.5 kB
text/typescript
import {catchAsyncError} from "@tsed/core";
import {BadRequest} from "@tsed/exceptions";
import {PlatformTest} from "@tsed/platform-http/testing";
import {FormioAuthService} from "./FormioAuthService.js";
import {FormioHooksService} from "./FormioHooksService.js";
import {FormioService} from "./FormioService.js";
function createSubmissionModelFixture(): any {
return class {
static findOne = vi.fn().mockReturnThis();
static updateOne = vi.fn().mockResolvedValue({});
static lean = vi.fn().mockReturnThis();
static exec = vi.fn().mockReturnThis();
save = vi.fn().mockReturnThis();
constructor(public ctrOptions: any) {}
get form(): string {
return this.ctrOptions.form;
}
set form(form: string) {
this.ctrOptions.form = form;
}
toObject() {
return this.ctrOptions;
}
};
}
function createFormModelFixture(): any {
return class {
static findOne = vi.fn().mockReturnThis();
static lean = vi.fn().mockReturnThis();
static exec = vi.fn();
};
}
function createRoleModelFixture(): any {
return class {
static find = vi.fn().mockReturnThis();
static sort = vi.fn().mockReturnThis();
static lean = vi.fn().mockReturnThis();
static exec = vi.fn().mockResolvedValue({});
};
}
async function createServiceFixture() {
const formioService = {
audit: vi.fn(),
auth: {
tempToken: vi.fn(),
logout: vi.fn(),
currentUser: vi.fn().mockImplementation((req, res, next) => next()),
getToken: vi.fn().mockReturnValue("auth_token")
},
mongoose: {
models: {
submission: createSubmissionModelFixture(),
form: createFormModelFixture(),
role: createRoleModelFixture()
}
},
util: {
idToBson: vi.fn().mockImplementation((f) => f),
errorCodes: {
role: {EROLESLOAD: "EROLESLOAD"}
}
}
};
const formioHooksService = {
alter: vi.fn().mockImplementation((event: string, value: any) => value),
alterAsync: vi.fn().mockImplementation((event: string, value: any) => Promise.resolve(value))
};
const service = await PlatformTest.invoke<FormioAuthService>(FormioAuthService, [
{
token: FormioService,
use: formioService
},
{
token: FormioHooksService,
use: formioHooksService
}
]);
return {service, formioService, formioHooksService};
}
describe("FormioAuthService", () => {
beforeEach(() => PlatformTest.create());
afterEach(PlatformTest.reset);
describe("createUser()", () => {
it("should create a user submission", async () => {
const {service} = await createServiceFixture();
const submission = await service.createUser({
form: "formId",
data: {
fullname: "fullname"
}
});
expect(submission.form).toEqual("formId");
expect(submission.data).toEqual({
fullname: "fullname"
});
});
});
describe("updateUser()", () => {
it("should update a user submission", async () => {
const {service, formioService} = await createServiceFixture();
const result = await service.updateUser({
_id: "id",
form: "formId",
data: {
fullname: "fullname"
}
});
expect(result).toEqual({
_id: "id",
form: "formId",
data: {
fullname: "fullname"
}
});
expect(formioService.mongoose.models.submission.updateOne).toHaveBeenCalledWith(
{_id: "id"},
{$set: {_id: "id", data: {fullname: "fullname"}, form: "formId"}}
);
});
});
describe("getRoles()", () => {
it("should return all formio roles", async () => {
const {service, formioService} = await createServiceFixture();
formioService.mongoose.models.role.exec.mockResolvedValue([{name: "administrator"}]);
const roles = await service.getRoles({} as any);
expect(roles).toEqual([{name: "administrator"}]);
expect(formioService.mongoose.models.role.find).toHaveBeenCalledWith({deleted: {$eq: null}});
expect(formioService.mongoose.models.role.sort).toHaveBeenCalledWith({title: 1});
expect(formioService.mongoose.models.role.lean).toHaveBeenCalledWith();
});
it("should throw an error", async () => {
const {service, formioService} = await createServiceFixture();
vi.mocked(formioService.mongoose.models.role.exec).mockRejectedValue(new Error("test"));
const error = await catchAsyncError(() => service.getRoles({} as any));
expect(error).toBeInstanceOf(BadRequest);
expect(error?.message).toEqual("EROLESLOAD");
});
});
describe("updateUserRole()", () => {
it("should update the role associated to the submission", async () => {
const {service, formioService, formioHooksService} = await createServiceFixture();
const submission = {
_id: "submissionId",
save: vi.fn()
};
formioService.mongoose.models.submission.exec = vi.fn().mockResolvedValue(submission);
const user = await service.updateUserRole("submissionId", "roleId", {} as any);
expect(formioHooksService.alter).toHaveBeenCalledWith("submissionQuery", {_id: "submissionId", deleted: {$eq: null}}, {});
expect(formioService.mongoose.models.submission.findOne).toHaveBeenCalledWith({_id: "submissionId", deleted: {$eq: null}});
expect(user.save).toHaveBeenCalledWith();
expect(user.roles).toEqual(["roleId"]);
});
it("should update the role associated to the submission without save", async () => {
const {service, formioService, formioHooksService} = await createServiceFixture();
const submission = {
_id: "submissionId"
};
formioService.mongoose.models.submission.exec = vi.fn().mockResolvedValue(submission);
const user = await service.updateUserRole("submissionId", "roleId", {} as any);
expect(formioHooksService.alter).toHaveBeenCalledWith("submissionQuery", {_id: "submissionId", deleted: {$eq: null}}, {});
expect(formioService.mongoose.models.submission.findOne).toHaveBeenCalledWith({_id: "submissionId", deleted: {$eq: null}});
expect(user.roles).toEqual(["roleId"]);
});
it("should throw an error when submission doesn't exists", async () => {
const {service, formioService} = await createServiceFixture();
formioService.mongoose.models.submission.exec = vi.fn().mockResolvedValue(null);
const error = await catchAsyncError(() => service.updateUserRole("submissionId", "roleId", {} as any));
expect(error).toBeInstanceOf(BadRequest);
});
});
describe("setCurrentUser()", () => {
it("should set current user", async () => {
const {service} = await createServiceFixture();
const ctx = PlatformTest.createRequestContext();
ctx.getRequest().submission = {};
const user = {
_id: "id",
data: {}
};
const token = {
decoded: {
form: {
_id: "id"
},
user: {
_id: "id"
}
},
token: "token"
};
service.setCurrentUser(user as any, token, ctx);
expect(ctx.getRequest().submission).toEqual({data: {}});
expect(ctx.getRequest().user).toEqual({_id: "id", data: {}});
expect(ctx.getRequest().token).toEqual({
form: {
_id: "id"
},
user: {
_id: "id"
}
});
expect(ctx.getResponse().token).toEqual("token");
expect(ctx.getRequest()["x-jwt-token"]).toEqual("token");
});
});
describe("generatePayloadToken()", () => {
it("should return the payload token", async () => {
const {service, formioService, formioHooksService} = await createServiceFixture();
const ctx = PlatformTest.createRequestContext();
const user = {
_id: "id",
form: "605f0d40fe971372e448bcad",
data: {}
};
const form = {
_id: "605f0d40fe971372e448bcad"
};
const payload = {
user: {
_id: user._id
},
form: {
_id: form._id
}
};
formioService.mongoose.models.form.exec.mockResolvedValue(form);
const result = await service.generatePayloadToken(user as any, ctx);
expect(result).toEqual({
token: {
decoded: payload,
token: "auth_token"
},
user: {
_id: "id",
data: {},
form: "605f0d40fe971372e448bcad"
}
});
expect(formioHooksService.alter).toHaveBeenCalledWith("token", payload, form, ctx.getRequest());
expect(formioHooksService.alter).toHaveBeenCalledWith("tokenDecode", payload, ctx.getRequest());
expect(formioHooksService.alterAsync).toHaveBeenCalledWith("user", user);
expect(formioHooksService.alterAsync).toHaveBeenCalledWith("login", user, ctx.getRequest());
});
it("should throw error when the getForm throw error", async () => {
const {service, formioService} = await createServiceFixture();
const ctx = PlatformTest.createRequestContext();
const user = {
_id: "id",
form: "605f0d40fe971372e448bcad",
data: {}
};
formioService.mongoose.models.form.exec.mockRejectedValue(new Error("message"));
const error = await catchAsyncError(() => service.generatePayloadToken(user as any, ctx));
expect(error?.name).toEqual("Error");
expect(formioService.audit).toHaveBeenCalledWith(
"EAUTH_USERFORM",
{...ctx.request.raw, userId: user._id},
"605f0d40fe971372e448bcad",
error
);
});
it("should throw error when the form isn't found", async () => {
const {service, formioService} = await createServiceFixture();
const ctx = PlatformTest.createRequestContext();
const user = {
_id: "id",
form: "605f0d40fe971372e448bcad",
data: {}
};
formioService.mongoose.models.form.exec.mockResolvedValue(null);
const error = await catchAsyncError(() => service.generatePayloadToken(user as any, ctx));
expect(error?.name).toEqual("NOT_FOUND");
expect(formioService.audit).toHaveBeenCalledWith(
"EAUTH_USERFORM",
{...ctx.request.raw, userId: user._id},
"605f0d40fe971372e448bcad",
{
message: "User form not found"
}
);
});
});
describe("generateSession()", () => {
it("should generate session", async () => {
const {service, formioService} = await createServiceFixture();
const ctx = PlatformTest.createRequestContext();
const user = {
_id: "id",
form: "605f0d40fe971372e448bcad",
data: {}
};
vi.spyOn(service, "setCurrentUser").mockReturnValue(undefined as any);
vi.spyOn(service, "generatePayloadToken").mockResolvedValue({
user,
token: {
token: "token"
}
} as any);
await service.generateSession(user as any, ctx);
expect(service.setCurrentUser).toHaveBeenCalledWith(
user,
{
token: "token"
},
ctx
);
expect(service.setCurrentUser).toHaveBeenCalledWith(
user,
{
token: "token"
},
ctx
);
expect(formioService.auth.currentUser).toHaveBeenCalledWith(ctx.getRequest(), ctx.getResponse(), expect.any(Function));
});
it("should throw an error when an action isn't permitted", async () => {
const {service} = await createServiceFixture();
const ctx = PlatformTest.createRequestContext();
const user = {
_id: "id",
form: "605f0d40fe971372e448bcad",
data: {}
};
vi.spyOn(service, "setCurrentUser").mockReturnValue(undefined as any);
vi.spyOn(service, "generatePayloadToken").mockRejectedValue(new Error("Not found"));
const error = await catchAsyncError(() => service.generateSession(user as any, ctx));
expect(error?.message).toEqual("Not found");
});
});
describe("tempToken()", () => {
it("should return tempToken", async () => {
const {service, formioService} = await createServiceFixture();
expect(service.tempToken).toEqual(formioService.auth.tempToken);
});
});
describe("logout()", () => {
it("should return logout", async () => {
const {service, formioService} = await createServiceFixture();
expect(service.logout).toEqual(formioService.auth.logout);
});
});
});