Skip to content

Commit

Permalink
Add tests for 100% coverage of src/resolvers/User/posts.ts (Palisadoe…
Browse files Browse the repository at this point in the history
…sFoundation#2417)

* fix: issue PalisadoesFoundation#2382 by upgrading graphql version

- Updated the `graphql` dependency in `package.json` from version `^16.8.1` to `^16.9.0`
- Regenerated `package-lock.json` to reflect the changes in dependencies

This change addresses issue PalisadoesFoundation#2382 by ensuring compatibility with the latest features and bug fixes in the `graphql` package.

Closes PalisadoesFoundation#2382

* test: Add tests for 100% coverage of src/resolvers/User/posts.ts

- Implemented comprehensive test cases for `posts.ts` to ensure 100% code coverage.
- Added tests for various pagination arguments (`first`, `last`, `before`, `after`).
- Included edge cases for no posts and invalid filters.
- Verified error handling for invalid arguments and cursor values.

Fixes PalisadoesFoundation#1928

* test: Add tests for 100% coverage of src/resolvers/User/posts.ts update-2

* Fix and improve User post resolver tests

- Update 'handles valid cursor value' test to be more flexible
- Ensure test passes with variable post order
- Maintain test coverage and functionality verification
  • Loading branch information
Aaradhy-Sharma authored Jul 27, 2024
1 parent 7258cfd commit 1f38da5
Showing 1 changed file with 160 additions and 6 deletions.
166 changes: 160 additions & 6 deletions tests/resolvers/User/post.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Replace with the correct path

import { GraphQLError } from "graphql";
import type mongoose from "mongoose";
import { Types } from "mongoose";
Expand Down Expand Up @@ -26,6 +27,7 @@ let MONGOOSE_INSTANCE: typeof mongoose;
let testUser: TestUserType;
let testPost: TestPostType;
let testPost2: TestPostType;
let testPost3: TestPostType;
let testOrganization: TestOrganizationType;

beforeAll(async () => {
Expand All @@ -41,6 +43,12 @@ beforeAll(async () => {
organization: testOrganization?._id,
pinned: false,
});
testPost3 = await Post.create({
text: `text${nanoid().toLowerCase()}`,
creatorId: testUser?._id,
organization: testOrganization?._id,
pinned: false,
});
});

afterAll(async () => {
Expand All @@ -55,23 +63,23 @@ describe("resolvers -> User -> post", () => {
await postResolver?.(parent, {}, {});
} catch (error) {
if (error instanceof GraphQLError) {
expect(error.extensions.code).toEqual("INVALID_ARGUMENTS");
expect(error.extensions?.code).toEqual("INVALID_ARGUMENTS");
expect(
(error.extensions.errors as DefaultGraphQLArgumentError[]).length,
(error.extensions?.errors as DefaultGraphQLArgumentError[]).length,
).toBeGreaterThan(0);
}
}
});

it(`returns the expected connection object`, async () => {
const parent = testUser as InterfaceUser;
const connection = await postResolver?.(
parent,
{
first: 2,
first: 3,
},
{},
);
console.log(connection, testPost2?._id, testPost?._id);
const totalCount = await Post.find({
creatorId: testUser?._id,
}).countDocuments();
Expand All @@ -81,18 +89,107 @@ describe("resolvers -> User -> post", () => {
// Check individual properties
// console.log(connection?.edges[0]);
expect((connection?.edges[0] as unknown as PostEdge).cursor).toEqual(
testPost2?._id.toString(),
testPost3?._id.toString(),
);
expect((connection?.edges[1] as unknown as PostEdge).cursor).toEqual(
testPost2?._id.toString(),
);
expect((connection?.edges[2] as unknown as PostEdge).cursor).toEqual(
testPost?._id.toString(),
);
expect(connection?.pageInfo.endCursor).toEqual(testPost?._id.toString());
expect(connection?.pageInfo.hasNextPage).toBe(false);
expect(connection?.pageInfo.hasPreviousPage).toBe(false);
expect(connection?.pageInfo.startCursor).toEqual(testPost2?._id.toString());
expect(connection?.pageInfo.startCursor).toEqual(testPost3?._id.toString());
expect(connection?.totalCount).toEqual(totalCount);
});

it("returns an empty connection object if no posts are found", async () => {
await Post.deleteMany({ creatorId: testUser?._id });
const parent = testUser as InterfaceUser;
const connection = await postResolver?.(parent, { first: 2 }, {});

expect(connection?.edges).toHaveLength(0);
expect(connection?.totalCount).toEqual(0);
expect(connection?.pageInfo.endCursor).toBeNull();
expect(connection?.pageInfo.startCursor).toBeNull();
expect(connection?.pageInfo.hasNextPage).toBe(false);
expect(connection?.pageInfo.hasPreviousPage).toBe(false);
});

it("handles different pagination arguments correctly", async () => {
// Recreate posts for pagination testing
testPost = await Post.create({
text: `text${nanoid().toLowerCase()}`,
creatorId: testUser?._id,
organization: testOrganization?._id,
pinned: false,
});
testPost2 = await Post.create({
text: `text${nanoid().toLowerCase()}`,
creatorId: testUser?._id,
organization: testOrganization?._id,
pinned: false,
});
testPost3 = await Post.create({
text: `text${nanoid().toLowerCase()}`,
creatorId: testUser?._id,
organization: testOrganization?._id,
pinned: false,
});

const parent = testUser as InterfaceUser;

const connectionFirst = await postResolver?.(parent, { first: 1 }, {});
expect(connectionFirst?.edges).toHaveLength(1);
expect(connectionFirst?.pageInfo.hasNextPage).toBe(true);
expect(connectionFirst?.pageInfo.hasPreviousPage).toBe(false);

const connectionLast = await postResolver?.(parent, { last: 1 }, {});
expect(connectionLast?.edges).toHaveLength(1);
expect(connectionLast?.pageInfo.hasNextPage).toBe(false);
expect(connectionLast?.pageInfo.hasPreviousPage).toBe(true);
});

it("throws an error for invalid cursor value", async () => {
const parent = testUser as InterfaceUser;
const args = { after: "invalidCursor", first: 10 };
await expect(postResolver?.(parent, args, {})).rejects.toThrow();
});

it("handles valid cursor value", async () => {
const parent = testUser as InterfaceUser;
const args = { after: testPost2?._id.toString(), first: 10 };
const connection = await postResolver?.(parent, args, {});
expect(connection).toBeDefined();
expect(connection?.edges.length).toBeGreaterThan(0);

const allPostIds = [testPost, testPost2, testPost3].map((post) =>
post?._id.toString(),
);

const returnedCursor = (connection?.edges[0] as unknown as PostEdge).cursor;
expect(allPostIds).toContain(returnedCursor);
expect(returnedCursor).not.toEqual(testPost2?._id.toString());
});
});

it("handles missing cursor value gracefully", async () => {
const parent = testUser as InterfaceUser;
const args = { first: 10 };
const connection = await postResolver?.(parent, args, {});
expect(connection).toBeDefined();
expect(connection?.edges.length).toBeGreaterThan(0);
});

it("handles cursor value with pagination arguments", async () => {
const parent = testUser as InterfaceUser;
const args = { after: testPost?._id.toString(), first: 2 };
const connection = await postResolver?.(parent, args, {});
expect(connection).toBeDefined();
expect(connection?.edges.length).toBeLessThanOrEqual(2);
});

describe("parseCursor function", () => {
it("returns failure state if argument cursorValue is an invalid cursor", async () => {
const result = await parseCursor({
Expand Down Expand Up @@ -121,4 +218,61 @@ describe("parseCursor function", () => {
expect(result.parsedCursor).toEqual(testPost?._id.toString());
}
});

it("returns failure state if creatorId is invalid", async () => {
const result = await parseCursor({
cursorName: "after",
cursorPath: ["after"],
cursorValue: testPost?._id.toString() as string,
creatorId: new Types.ObjectId().toString(),
});

expect(result.isSuccessful).toEqual(false);
if (result.isSuccessful === false) {
expect(result.errors.length).toBeGreaterThan(0);
}
});

it("handles empty string cursor value", async () => {
try {
await parseCursor({
cursorName: "after",
cursorPath: ["after"],
cursorValue: "",
creatorId: testUser?._id.toString() as string,
});
} catch (error) {
expect(error).toBeDefined();
expect((error as Error).message).toContain("Cast to ObjectId failed");
}
});

it("handles invalid ObjectId string as cursor value", async () => {
try {
await parseCursor({
cursorName: "after",
cursorPath: ["after"],
cursorValue: "invalidObjectId",
creatorId: testUser?._id.toString() as string,
});
} catch (error) {
expect(error).toBeDefined();
expect((error as Error).message).toContain("Cast to ObjectId failed");
}
});

it("handles non-existent ObjectId as cursor value", async () => {
const nonExistentId = new Types.ObjectId().toString();
const result = await parseCursor({
cursorName: "after",
cursorPath: ["after"],
cursorValue: nonExistentId,
creatorId: testUser?._id.toString() as string,
});

expect(result.isSuccessful).toEqual(false);
if (result.isSuccessful === false) {
expect(result.errors.length).toBeGreaterThan(0);
}
});
});

0 comments on commit 1f38da5

Please sign in to comment.