Files
kandev/apps/web/components/task/review-selection.test.ts
T

118 lines
4.1 KiB
TypeScript

import { act, renderHook } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import type { ReviewItemSummary } from "@/lib/plugins/types";
import { reviewItemId, selectReviewItem, useReviewItemSelection } from "./review-selection";
const githubReview: ReviewItemSummary = {
providerId: "github",
reviewKey: "owner/repository/12",
title: "GitHub pull request",
url: "https://github.test/owner/repository/pull/12",
connectionScope: "https://github.test",
repositoryId: "owner/repository",
changeRequestNumber: 12,
state: "OPEN",
};
const bitbucketReview: ReviewItemSummary = {
providerId: "bitbucket",
reviewKey: "workspace/repository/42",
title: "Bitbucket pull request",
url: "https://bitbucket.test/workspace/repository/pull-requests/42",
connectionScope: "https://bitbucket.test",
repositoryId: "workspace/repository",
changeRequestNumber: 42,
state: "OPEN",
};
const secondGithubReview: ReviewItemSummary = {
...githubReview,
reviewKey: "owner/repository/13",
changeRequestNumber: 13,
title: "Second GitHub pull request",
url: "https://github.test/owner/repository/pull/13",
};
describe("selectReviewItem", () => {
it("requires an explicit choice when built-in and plugin reviews coexist", () => {
expect(selectReviewItem([githubReview, bitbucketReview], null)).toBeNull();
});
it("selects the requested plugin review instead of the first built-in result", () => {
expect(selectReviewItem([githubReview, bitbucketReview], reviewItemId(bitbucketReview))).toBe(
bitbucketReview,
);
});
it("keeps delimiter-bearing provider and review identities distinct", () => {
const first = { ...bitbucketReview, providerId: "a:b", reviewKey: "c" };
const second = { ...bitbucketReview, providerId: "a", reviewKey: "b:c" };
expect(reviewItemId(first)).not.toBe(reviewItemId(second));
expect(selectReviewItem([first, second], reviewItemId(second))).toBe(second);
});
it("uses immutable repository identity when a repository path is recreated", () => {
const oldRepository = {
...bitbucketReview,
repositoryId: "repository-uuid-old",
reviewKey: "workspace/repository#42",
};
const recreatedRepository = {
...oldRepository,
repositoryId: "repository-uuid-new",
};
expect(reviewItemId(oldRepository)).not.toBe(reviewItemId(recreatedRepository));
expect(
selectReviewItem([oldRepository, recreatedRepository], reviewItemId(recreatedRepository)),
).toBe(recreatedRepository);
});
it("opens a lone review without an unnecessary chooser", () => {
expect(selectReviewItem([bitbucketReview], null)).toBe(bitbucketReview);
});
it("preserves the provider's primary review when every choice has the same owner", () => {
expect(selectReviewItem([githubReview, secondGithubReview], null)).toBe(githubReview);
});
});
describe("useReviewItemSelection", () => {
it("honors an externally requested review from a same-provider list", () => {
const { result } = renderHook(() =>
useReviewItemSelection(
"task-1",
[githubReview, secondGithubReview],
reviewItemId(secondGithubReview),
),
);
expect(result.current.selectedReview).toBe(secondGithubReview);
});
it("keeps an explicit local choice while the external request is unchanged", () => {
const preferredReviewId = reviewItemId(githubReview);
const { result, rerender } = renderHook(() =>
useReviewItemSelection("task-1", [githubReview, bitbucketReview], preferredReviewId),
);
act(() => result.current.selectReview(bitbucketReview));
rerender();
expect(result.current.selectedReview).toBe(bitbucketReview);
});
it("follows a changed external review request", () => {
const { result, rerender } = renderHook(
({ preferredReviewId }) =>
useReviewItemSelection("task-1", [githubReview, secondGithubReview], preferredReviewId),
{ initialProps: { preferredReviewId: reviewItemId(githubReview) } },
);
rerender({ preferredReviewId: reviewItemId(secondGithubReview) });
expect(result.current.selectedReview).toBe(secondGithubReview);
});
});