494 lines
13 KiB
TypeScript
494 lines
13 KiB
TypeScript
import {
|
|
describe,
|
|
it,
|
|
expect,
|
|
vi,
|
|
beforeAll,
|
|
beforeEach,
|
|
afterEach,
|
|
} from "vitest";
|
|
import { ObjectId } from "mongodb";
|
|
|
|
import * as ConnectionsDal from "../../../src/dal/connections";
|
|
import { createConnection } from "../../__testData__/connections";
|
|
import { createUser } from "../../__testData__/users";
|
|
|
|
describe("ConnectionsDal", () => {
|
|
beforeAll(async () => {
|
|
await ConnectionsDal.createIndicies();
|
|
});
|
|
|
|
describe("getRequests", () => {
|
|
it("get by uid", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const initOne = await createConnection({ initiatorUid: uid });
|
|
const initTwo = await createConnection({ initiatorUid: uid });
|
|
const friendOne = await createConnection({ receiverUid: uid });
|
|
const _decoy = await createConnection({});
|
|
|
|
//WHEN / THEM
|
|
|
|
expect(
|
|
await ConnectionsDal.getConnections({
|
|
initiatorUid: uid,
|
|
receiverUid: uid,
|
|
}),
|
|
).toStrictEqual([initOne, initTwo, friendOne]);
|
|
});
|
|
|
|
it("get by uid and status", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const initAccepted = await createConnection({
|
|
initiatorUid: uid,
|
|
status: "accepted",
|
|
});
|
|
const _initPending = await createConnection({
|
|
initiatorUid: uid,
|
|
status: "pending",
|
|
});
|
|
const initBlocked = await createConnection({
|
|
initiatorUid: uid,
|
|
status: "blocked",
|
|
});
|
|
|
|
const friendAccepted = await createConnection({
|
|
receiverUid: uid,
|
|
status: "accepted",
|
|
});
|
|
const _friendPending = await createConnection({
|
|
receiverUid: uid,
|
|
status: "pending",
|
|
});
|
|
|
|
const _decoy = await createConnection({ status: "accepted" });
|
|
|
|
//WHEN / THEN
|
|
|
|
expect(
|
|
await ConnectionsDal.getConnections({
|
|
initiatorUid: uid,
|
|
receiverUid: uid,
|
|
status: ["accepted", "blocked"],
|
|
}),
|
|
).toStrictEqual([initAccepted, initBlocked, friendAccepted]);
|
|
});
|
|
});
|
|
|
|
describe("create", () => {
|
|
const now = 1715082588;
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(now);
|
|
});
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("should fail creating duplicates", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const first = await createConnection({
|
|
initiatorUid: uid,
|
|
});
|
|
|
|
//WHEN/THEN
|
|
await expect(
|
|
createConnection({
|
|
initiatorUid: first.receiverUid,
|
|
receiverUid: uid,
|
|
}),
|
|
).rejects.toThrow("Connection request already sent");
|
|
});
|
|
|
|
it("should create", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const receiverUid = new ObjectId().toHexString();
|
|
|
|
//WHEN
|
|
const created = await ConnectionsDal.create(
|
|
{ uid, name: "Bob" },
|
|
{ uid: receiverUid, name: "Kevin" },
|
|
2,
|
|
);
|
|
|
|
//THEN
|
|
expect(created).toEqual({
|
|
_id: created._id,
|
|
initiatorUid: uid,
|
|
initiatorName: "Bob",
|
|
receiverUid: receiverUid,
|
|
receiverName: "Kevin",
|
|
lastModified: now,
|
|
status: "pending",
|
|
key: `${uid}/${receiverUid}`,
|
|
});
|
|
});
|
|
|
|
it("should fail if maximum connections are reached", async () => {
|
|
//GIVEN
|
|
const initiatorUid = new ObjectId().toHexString();
|
|
await createConnection({ initiatorUid });
|
|
await createConnection({ initiatorUid });
|
|
|
|
//WHEN / THEM
|
|
await expect(createConnection({ initiatorUid }, 2)).rejects.toThrow(
|
|
"Maximum number of connections reached\nStack: create connection request",
|
|
);
|
|
});
|
|
|
|
it("should fail creating if blocked", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const first = await createConnection({
|
|
initiatorUid: uid,
|
|
status: "blocked",
|
|
});
|
|
|
|
//WHEN/THEN
|
|
await expect(
|
|
createConnection({
|
|
initiatorUid: first.receiverUid,
|
|
receiverUid: uid,
|
|
}),
|
|
).rejects.toThrow("Connection blocked");
|
|
});
|
|
});
|
|
describe("updateStatus", () => {
|
|
const now = 1715082588;
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(now);
|
|
});
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
it("should update the status", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const first = await createConnection({
|
|
receiverUid: uid,
|
|
lastModified: 100,
|
|
});
|
|
const second = await createConnection({
|
|
receiverUid: uid,
|
|
lastModified: 200,
|
|
});
|
|
|
|
//WHEN
|
|
await ConnectionsDal.updateStatus(
|
|
uid,
|
|
first._id.toHexString(),
|
|
"accepted",
|
|
);
|
|
|
|
//THEN
|
|
expect(await ConnectionsDal.getConnections({ receiverUid: uid })).toEqual(
|
|
[{ ...first, status: "accepted", lastModified: now }, second],
|
|
);
|
|
|
|
//can update twice to the same status
|
|
await ConnectionsDal.updateStatus(
|
|
uid,
|
|
first._id.toHexString(),
|
|
"accepted",
|
|
);
|
|
});
|
|
it("should fail if uid does not match the reeceiverUid", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const first = await createConnection({
|
|
initiatorUid: uid,
|
|
});
|
|
|
|
//WHEN / THEN
|
|
await expect(
|
|
ConnectionsDal.updateStatus(uid, first._id.toHexString(), "accepted"),
|
|
).rejects.toThrow("No permission or connection not found");
|
|
});
|
|
});
|
|
|
|
describe("deleteById", () => {
|
|
it("should delete by initiator", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const first = await createConnection({
|
|
initiatorUid: uid,
|
|
});
|
|
const second = await createConnection({
|
|
initiatorUid: uid,
|
|
});
|
|
|
|
//WHEN
|
|
await ConnectionsDal.deleteById(uid, first._id.toHexString());
|
|
|
|
//THEN
|
|
expect(
|
|
await ConnectionsDal.getConnections({ initiatorUid: uid }),
|
|
).toStrictEqual([second]);
|
|
});
|
|
|
|
it("should delete by receiver", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const first = await createConnection({
|
|
receiverUid: uid,
|
|
});
|
|
const second = await createConnection({
|
|
receiverUid: uid,
|
|
status: "accepted",
|
|
});
|
|
|
|
//WHEN
|
|
await ConnectionsDal.deleteById(uid, first._id.toHexString());
|
|
|
|
//THEN
|
|
expect(
|
|
await ConnectionsDal.getConnections({
|
|
initiatorUid: second.initiatorUid,
|
|
}),
|
|
).toStrictEqual([second]);
|
|
});
|
|
|
|
it("should fail if uid does not match", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const first = await createConnection({
|
|
initiatorUid: uid,
|
|
});
|
|
|
|
//WHEN / THEN
|
|
await expect(
|
|
ConnectionsDal.deleteById("Bob", first._id.toHexString()),
|
|
).rejects.toThrow("No permission or connection not found");
|
|
});
|
|
|
|
it("should fail if initiator deletes blocked by receiver", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const myRequestWasBlocked = await createConnection({
|
|
initiatorName: uid,
|
|
status: "blocked",
|
|
});
|
|
|
|
//WHEN / THEN
|
|
await expect(
|
|
ConnectionsDal.deleteById(uid, myRequestWasBlocked._id.toHexString()),
|
|
).rejects.toThrow("No permission or connection not found");
|
|
});
|
|
it("allow receiver to delete blocked", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const myBlockedUser = await createConnection({
|
|
receiverUid: uid,
|
|
status: "blocked",
|
|
});
|
|
|
|
//WHEN
|
|
await ConnectionsDal.deleteById(uid, myBlockedUser._id.toHexString());
|
|
|
|
//THEN
|
|
expect(await ConnectionsDal.getConnections({ receiverUid: uid })).toEqual(
|
|
[],
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("deleteByUid", () => {
|
|
it("should delete by uid", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const _initOne = await createConnection({ initiatorUid: uid });
|
|
const _initTwo = await createConnection({ initiatorUid: uid });
|
|
const _friendOne = await createConnection({ receiverUid: uid });
|
|
const decoy = await createConnection({});
|
|
|
|
//WHEN
|
|
await ConnectionsDal.deleteByUid(uid);
|
|
|
|
//THEN
|
|
expect(
|
|
await ConnectionsDal.getConnections({
|
|
initiatorUid: uid,
|
|
receiverUid: uid,
|
|
}),
|
|
).toEqual([]);
|
|
|
|
expect(
|
|
await ConnectionsDal.getConnections({
|
|
initiatorUid: decoy.initiatorUid,
|
|
}),
|
|
).toEqual([decoy]);
|
|
});
|
|
});
|
|
describe("updateName", () => {
|
|
it("should update the name", async () => {
|
|
//GIVEN
|
|
const uid = new ObjectId().toHexString();
|
|
const initOne = await createConnection({
|
|
initiatorUid: uid,
|
|
initiatorName: "Bob",
|
|
});
|
|
const initTwo = await createConnection({
|
|
initiatorUid: uid,
|
|
initiatorName: "Bob",
|
|
});
|
|
const friendOne = await createConnection({
|
|
receiverUid: uid,
|
|
receiverName: "Bob",
|
|
});
|
|
const decoy = await createConnection({});
|
|
|
|
//WHEN
|
|
await ConnectionsDal.updateName(uid, "King Bob");
|
|
|
|
//THEN
|
|
expect(
|
|
await ConnectionsDal.getConnections({
|
|
initiatorUid: uid,
|
|
receiverUid: uid,
|
|
}),
|
|
).toEqual([
|
|
{ ...initOne, initiatorName: "King Bob" },
|
|
{ ...initTwo, initiatorName: "King Bob" },
|
|
{ ...friendOne, receiverName: "King Bob" },
|
|
]);
|
|
|
|
expect(
|
|
await ConnectionsDal.getConnections({
|
|
initiatorUid: decoy.initiatorUid,
|
|
}),
|
|
).toEqual([decoy]);
|
|
});
|
|
});
|
|
|
|
describe("getFriendsUids", () => {
|
|
it("should return friend uids", async () => {
|
|
//GIVE
|
|
const uid = new ObjectId().toHexString();
|
|
const friendOne = await createConnection({
|
|
initiatorUid: uid,
|
|
status: "accepted",
|
|
});
|
|
const friendTwo = await createConnection({
|
|
receiverUid: uid,
|
|
status: "accepted",
|
|
});
|
|
const friendThree = await createConnection({
|
|
receiverUid: uid,
|
|
status: "accepted",
|
|
});
|
|
const _pending = await createConnection({
|
|
initiatorUid: uid,
|
|
status: "pending",
|
|
});
|
|
const _blocked = await createConnection({
|
|
initiatorUid: uid,
|
|
status: "blocked",
|
|
});
|
|
const _decoy = await createConnection({});
|
|
|
|
//WHEN
|
|
const friendUids = await ConnectionsDal.getFriendsUids(uid);
|
|
|
|
//THEN
|
|
expect(friendUids).toEqual([
|
|
uid,
|
|
friendOne.receiverUid,
|
|
friendTwo.initiatorUid,
|
|
friendThree.initiatorUid,
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("aggregateWithAcceptedConnections", () => {
|
|
it("should return friend uids", async () => {
|
|
//GIVE
|
|
const uid = (await createUser()).uid;
|
|
const friendOne = await createConnection({
|
|
initiatorUid: uid,
|
|
receiverUid: (await createUser()).uid,
|
|
status: "accepted",
|
|
});
|
|
const friendTwo = await createConnection({
|
|
initiatorUid: (await createUser()).uid,
|
|
receiverUid: uid,
|
|
status: "accepted",
|
|
});
|
|
const friendThree = await createConnection({
|
|
initiatorUid: (await createUser()).uid,
|
|
receiverUid: uid,
|
|
status: "accepted",
|
|
});
|
|
const _pending = await createConnection({
|
|
initiatorUid: uid,
|
|
receiverUid: (await createUser()).uid,
|
|
status: "pending",
|
|
});
|
|
const _blocked = await createConnection({
|
|
initiatorUid: uid,
|
|
receiverUid: (await createUser()).uid,
|
|
status: "blocked",
|
|
});
|
|
const _decoy = await createConnection({
|
|
receiverUid: (await createUser()).uid,
|
|
status: "accepted",
|
|
});
|
|
|
|
//WHEN
|
|
const friendUids = await ConnectionsDal.aggregateWithAcceptedConnections<{
|
|
uid: string;
|
|
}>({ collectionName: "users", uid }, [{ $project: { uid: true } }]);
|
|
|
|
//THEN
|
|
expect(friendUids.flatMap((it) => it.uid).toSorted()).toEqual([
|
|
uid,
|
|
friendOne.receiverUid,
|
|
friendTwo.initiatorUid,
|
|
friendThree.initiatorUid,
|
|
]);
|
|
});
|
|
it("should return friend uids and metaData", async () => {
|
|
//GIVE
|
|
const me = await createUser();
|
|
const friend = await createUser();
|
|
|
|
const connection = await createConnection({
|
|
initiatorUid: me.uid,
|
|
receiverUid: friend.uid,
|
|
status: "accepted",
|
|
});
|
|
|
|
//WHEN
|
|
const friendUids = await ConnectionsDal.aggregateWithAcceptedConnections(
|
|
{ collectionName: "users", uid: me.uid, includeMetaData: true },
|
|
[
|
|
{
|
|
$project: {
|
|
uid: true,
|
|
lastModified: "$connectionMeta.lastModified",
|
|
connectionId: "$connectionMeta._id",
|
|
},
|
|
},
|
|
],
|
|
);
|
|
|
|
//THEN
|
|
expect(friendUids).toEqual([
|
|
{
|
|
_id: friend._id,
|
|
connectionId: connection._id,
|
|
lastModified: connection.lastModified,
|
|
uid: friend.uid,
|
|
},
|
|
{
|
|
_id: me._id,
|
|
uid: me.uid,
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
});
|