Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: reaction service #331

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,111 @@
import ReactionService from "src/feedback/reaction/services/reactionService/reaction.service";
import { ReactionType } from "src/feedback/reaction/reaction.types";
import { setupAPIServiceSpy } from "src/_test_utilities/fetchSpy";
import { StatusCodes } from "http-status-codes";

describe("ReactionService", () => {
describe("sendReaction", () => {
test("should send reaction successfully", async () => {
// GIVEN a successful response from the API
// GIVEN a reaction on a message with a given messageId in a session with a given SessionId
const givenReaction = { kind: ReactionType.LIKE };
const givenSessionId = 123;
const givenMessageId = "456";

// AND the API will return a successful response
const fetchSpy = setupAPIServiceSpy(StatusCodes.OK, {}, "application/json;charset=UTF-8");

// WHEN sending a reaction
const reactionService = new ReactionService();
await reactionService.sendReaction(givenSessionId, givenMessageId, givenReaction);

// THEN expect the API to be called correctly
expect(fetchSpy).toHaveBeenCalledWith(
`${reactionService.reactionEndpointUrl}/${givenSessionId}/messages/${givenMessageId}/reaction`,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ reaction: givenReaction }),
expectedStatusCode: StatusCodes.OK,
serviceName: "ReactionService",
serviceFunction: "sendReaction",
failureMessage: `Failed to send reaction for message 456`,
expectedContentType: "application/json",
}
);
});

test("should throw the same error thrown by the customFetch method", async () => {
// GIVEN a reaction on a message with a given messageId in a session with a given SessionId
const givenReaction = { kind: ReactionType.LIKE };
const givenSessionId = 123;
const givenMessageId = "456";

// AND the API will return an error response
const givenFetchError = new Error("some error");
jest.spyOn(require("src/utils/customFetch/customFetch"), "customFetch").mockImplementationOnce(() => {
return new Promise(() => {
throw givenFetchError;
});
});

// WHEN sending a reaction
const reactionService = new ReactionService();

// THEN expect the correct error to be thrown
await expect(reactionService.sendReaction(givenSessionId, givenMessageId, givenReaction)).rejects.toThrow(
givenFetchError
);
});
});

describe("deleteReaction", () => {
test("should delete reaction successfully", async () => {
// GIVEN a message with a given messageId
const givenSessionId = 123;
// AND a session with a given SessionId
const givenMessageId = "456";

// AND the API will return a successful response
const fetchSpy = setupAPIServiceSpy(StatusCodes.NO_CONTENT, undefined, "");

// WHEN deleting the given reaction
const reactionService = new ReactionService();
await reactionService.deleteReaction(givenSessionId, givenMessageId);

// THEN expect the correct API call to be made
expect(fetchSpy).toHaveBeenCalled();
// AND expect the response to match the expected response
expect(fetchSpy).toHaveBeenCalledWith(
`${reactionService.reactionEndpointUrl}/${givenSessionId}/messages/${givenMessageId}/reaction`,
{
method: "DELETE",
expectedStatusCode: StatusCodes.NO_CONTENT,
serviceName: "ReactionService",
serviceFunction: "deleteReaction",
failureMessage: `Failed to delete reaction for message 456`,
}
);
});

test("should throw the same error thrown by the customFetch method", async () => {
// GIVEN an error response
// WHEN sending a reaction
// GIVEN a message with a given messageId
const givenSessionId = 123;
// AND a session with a given SessionId
const givenMessageId = "456";

// AND the API will return an error response
const givenFetchError = new Error("some error");
jest.spyOn(require("src/utils/customFetch/customFetch"), "customFetch").mockImplementationOnce(() => {
return new Promise(() => {
throw givenFetchError;
});
});

// WHEN deleting the given reaction
const reactionService = new ReactionService();

// THEN expect the correct error to be thrown
await expect(reactionService.deleteReaction(givenSessionId, givenMessageId)).rejects.toThrow(givenFetchError);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
import { customFetch } from "src/utils/customFetch/customFetch";
import { StatusCodes } from "http-status-codes";
import { Reaction } from "src/feedback/reaction/reaction.types";
import { getBackendUrl } from "src/envService";

export class ReactionService {
async sendReaction(sessionId:string, messageId: string, reaction: Reaction): Promise<void> {
readonly reactionEndpointUrl: string;
readonly apiServerUrl: string;

constructor() {
this.apiServerUrl = getBackendUrl();
this.reactionEndpointUrl = `${this.apiServerUrl}/conversation`;
}

async sendReaction(sessionId: number, messageId: string, reaction: Reaction): Promise<void> {
const serviceName = "ReactionService";
const serviceFunction = "sendReaction";
const method = "PUT";

const reactionURL = `/conversation/${sessionId}/messages/${messageId}/reaction`;
await customFetch(
reactionURL,
{
method: method,
headers: { "Content-Type": "application/json" },
body: undefined, // implement body along with the API
expectedStatusCode: StatusCodes.OK,
serviceName: serviceName,
serviceFunction: serviceFunction,
failureMessage: `Failed to send reaction for message ${messageId}`,
expectedContentType: "application/json",
}
);
const reactionURL = `${this.reactionEndpointUrl}/${sessionId}/messages/${messageId}/reaction`;
const body = JSON.stringify({ reaction });

await customFetch(reactionURL, {
method: method,
headers: { "Content-Type": "application/json" },
body: body,
expectedStatusCode: StatusCodes.OK,
serviceName: serviceName,
serviceFunction: serviceFunction,
failureMessage: `Failed to send reaction for message ${messageId}`,
expectedContentType: "application/json",
});
}
async deleteReaction(sessionId:string, messageId: string): Promise<void> {

async deleteReaction(sessionId: number, messageId: string): Promise<void> {
const serviceName = "ReactionService";
const serviceFunction = "deleteReaction";
const method = "DELETE";

const reactionURL = `/conversation/${sessionId}/messages/${messageId}/reaction`;
await customFetch(
reactionURL,
{
method: method,
headers: { "Content-Type": "application/json" },
body: undefined, // implement body along with the API
expectedStatusCode: StatusCodes.NO_CONTENT,
serviceName: serviceName,
serviceFunction: serviceFunction,
failureMessage: `Failed to delete reaction for message ${messageId}`,
expectedContentType: "application/json",
}
);
const reactionURL = `${this.reactionEndpointUrl}/${sessionId}/messages/${messageId}/reaction`;
await customFetch(reactionURL, {
method: method,
expectedStatusCode: StatusCodes.NO_CONTENT,
serviceName: serviceName,
serviceFunction: serviceFunction,
failureMessage: `Failed to delete reaction for message ${messageId}`,
});
}
}

export default ReactionService;
export default ReactionService;
2 changes: 1 addition & 1 deletion frontend-new/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12901,7 +12901,7 @@ playwright-core@>=1.2.0:
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.44.1.tgz#53ec975503b763af6fc1a7aa995f34bc09ff447c"
integrity sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==

playwright@^1.14.0, playwright@^1.49.0:
playwright@^1.14.0, playwright@^1.49.1:
version "1.49.1"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.49.1.tgz#830266dbca3008022afa7b4783565db9944ded7c"
integrity sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==
Expand Down
Loading