Skip to content

Commit

Permalink
test: add component tests for paper details card
Browse files Browse the repository at this point in the history
  • Loading branch information
Slartibartfass2 committed Jan 21, 2025
1 parent c52959f commit 5ffeec4
Show file tree
Hide file tree
Showing 7 changed files with 379 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/lib/components/composites/input/ToggleableInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ Usage:
rows="1"
{value}
readonly={!isEditable}
data-testid="toggleable-input"
></textarea>
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Usage:
<PaperDetail id={key} {key} {value} {loadingPaper} {areDetailsInEditMode} />
```
-->
<div class="flex flex-row gap-2">
<div class="flex flex-row gap-2" data-testid="paper-detail">
<!-- Match top padding of input -->
<span class="w-24 pt-[0.3125rem]">{key}</span>
{#await loadingPaper}
Expand All @@ -35,6 +35,6 @@ Usage:
{:then}
<ToggleableInput isEditable={areDetailsInEditMode} {value} />
{:catch error}
<span class="pt-2 text-error">Coudn't load {key}{error ? `: ${error}` : ""}</span>
<span class="pt-2 text-error">Couldn't load {key}{error ? `: ${error}` : ""}</span>
{/await}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
import UnderlineTabsList from "$lib/components/composites/tabs/UnderlineTabsList.svelte";
import * as Card from "$lib/components/primitives/card/index.js";
import * as Tabs from "$lib/components/primitives/tabs/index.js";
import { cn } from "$lib/utils/shadcn-helper";
import type { WithElementRef } from "bits-ui";
import type { Snippet } from "svelte";
import type { HTMLAttributes } from "svelte/elements";
interface Props {
type Props = WithElementRef<HTMLAttributes<HTMLDivElement>> & {
tabs: Tab[];
children: Snippet;
}
const { tabs, children }: Props = $props();
};
const { tabs, children, class: className, ...restProps }: Props = $props();
</script>

<!-- Use PaperCardContent elements as children with values according to the tabs props -->
Expand All @@ -32,7 +36,10 @@ Usage:
</PaperCard>
```
-->
<Card.Root class="shadow-lg border-container-border-grey flex w-full h-full max-w-[50%]">
<Card.Root
class={cn(className, "shadow-lg border-container-border-grey flex w-full h-full max-w-[50%]")}
{...restProps}
>
<section class="flex flex-col h-full w-full">
<Tabs.Root value={tabs.length == 0 ? "" : tabs[0].value} class="flex flex-col h-full">
<UnderlineTabsList {tabs} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Usage:
<PaperDetailsCard {paper} allowEditModeToggle startInEditMode />
```
-->
<PaperCard {tabs}>
<PaperCard {tabs} data-testid="paper-details-card">
<PaperCardContent value="1">
<section class="flex flex-col gap-2 px-1">
<div class="flex flex-row justify-between items-center">
Expand All @@ -116,7 +116,12 @@ Usage:
{/if}
</div>
<div class="flex justify-center pt-2">
<Button class="w-fit" variant="outline" onclick={toggleAdditionalInfos}>
<Button
class="w-fit"
variant="outline"
onclick={toggleAdditionalInfos}
data-testid="toggle-additional-infos-btn"
>
{#if showAdditionalInfos}
<ChevronUp />
Show less information
Expand Down Expand Up @@ -153,7 +158,7 @@ Usage:
value={paper.abstrakt}
/>
{:catch error}
<span class="text-error">Coudn't load abstract{error ? `: ${error}` : ""}</span>
<span class="text-error">Couldn't load abstract{error ? `: ${error}` : ""}</span>
{/await}
</section>
</PaperCardContent>
Expand Down
50 changes: 50 additions & 0 deletions tests/integration/input/toggleable-input.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import ToggleableInput from "$lib/components/composites/input/ToggleableInput.svelte";
import { render, screen } from "@testing-library/svelte";
import { keyboard } from "@testing-library/user-event/dist/cjs/setup/directApi.js";
import { describe, expect, test } from "vitest";

describe("ToggleableInput", () => {
test("When isEditable is set to true, then input border is shown and content can be edited", async () => {
render(ToggleableInput, {
target: document.body,
props: {
isEditable: true,
value: "",
},
});

const input = screen.getByRole("textbox");
expect(input).toBeInTheDocument();

expect(input.classList.contains("border")).toBe(true);
expect(input.classList.contains("border-input")).toBe(true);
expect(input.classList.contains("rounded-md")).toBe(true);
expect(input.classList.contains("border-transparent")).toBe(false);

expect(input).not.toHaveAttribute("readonly");

await keyboard("Test");

expect(input).not.toHaveValue("Test");
expect(input).toHaveValue("");
});

test("When isEditable is set to false, then input border is not shown and content cannot be edited", () => {
render(ToggleableInput, {
target: document.body,
props: {
isEditable: false,
},
});

const input = screen.getByRole("textbox");
expect(input).toBeInTheDocument();

expect(input.classList.contains("border")).toBe(true);
expect(input.classList.contains("border-input")).toBe(false);
expect(input.classList.contains("rounded-md")).toBe(false);
expect(input.classList.contains("border-transparent")).toBe(true);

expect(input).toHaveAttribute("readonly");
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import PaperDetailsCard from "$lib/components/composites/paper-components/paper-view/cards/PaperDetailsCard.svelte";
import { render, screen, waitFor } from "@testing-library/svelte";
import { describe, expect, test } from "vitest";
import { createPaper } from "../../../../model-builder";
import { waitForComponentLoading } from "../../../test-helper";
import userEvent from "@testing-library/user-event";
import type { Paper } from "$lib/model/backend";

describe("PaperDetailsCard", () => {
test("When props are provided, then component is shown", async () => {
render(PaperDetailsCard, {
target: document.body,
props: {
loadingPaper: Promise.resolve(createPaper()),
allowEditModeToggle: true,
startInEditMode: false,
showButtonBar: true,
},
});

await waitForComponentLoading();

const card = screen.getByTestId("paper-details-card");
expect(card).toBeInTheDocument();

// edit mode can be toggled
const editButtons = document.getElementsByTagName("svg");
let editButtonCount = 0;
for (const editButton of editButtons) {
if (!editButton.classList.contains("lucide-pencil")) {
continue;
}

expect(editButton).toBeInTheDocument();
editButtonCount++;
}
expect(editButtonCount).toBe(2);

// paper details are in read-only mode
const toggleableInputs = screen.queryAllByTestId("toggleable-input");
expect(toggleableInputs).toHaveLength(5);
for (const input of toggleableInputs) {
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute("readonly");
}

// additional details are not shown by default
const showMoreButton = screen.queryByTestId("toggle-additional-infos-btn");
expect(showMoreButton).toBeInTheDocument();
});

test("When show more information button is pressed, then additional details are shown", async () => {
const user = userEvent.setup();
render(PaperDetailsCard, {
target: document.body,
props: {
loadingPaper: Promise.resolve(createPaper()),
allowEditModeToggle: true,
startInEditMode: false,
showButtonBar: true,
},
});

await waitForComponentLoading();

const showMoreButton = screen.queryByTestId("toggle-additional-infos-btn");
expect(showMoreButton).not.toBeNull();
expect(showMoreButton).toBeInTheDocument();

await user.click(showMoreButton!);

await waitFor(() => {
const paperDetails = screen.queryAllByTestId("paper-detail");
expect(paperDetails).toHaveLength(7);
});

expect(showMoreButton).toHaveTextContent("Show less information");

await user.click(showMoreButton!);

await waitFor(() => {
const paperDetails = screen.queryAllByTestId("paper-detail");
expect(paperDetails).toHaveLength(4);
});

expect(showMoreButton).toHaveTextContent("Show more information");
});

test("When edit mode is toggled, then paper details are in edit mode", async () => {
const user = userEvent.setup();
render(PaperDetailsCard, {
target: document.body,
props: {
loadingPaper: Promise.resolve(createPaper()),
allowEditModeToggle: true,
startInEditMode: false,
showButtonBar: true,
},
});

await waitForComponentLoading();

const svgs = document.getElementsByTagName("svg");
const editButtons: SVGSVGElement[] = [];
for (const svg of svgs) {
if (svg.classList.contains("lucide-pencil")) {
editButtons.push(svg);
}
}
expect(editButtons.length).toBe(2);

const generalInfoBtn = editButtons[0];
const abstractBtn = editButtons[1];

await user.click(generalInfoBtn);

await waitFor(() => {
const toggleableInputs = screen.queryAllByTestId("toggleable-input");
expect(toggleableInputs).toHaveLength(5);
for (const input of toggleableInputs.slice(0, 4)) {
expect(input).toBeInTheDocument();
expect(input).not.toHaveAttribute("readonly");
}
expect(toggleableInputs[4]).toBeInTheDocument();
expect(toggleableInputs[4]).toHaveAttribute("readonly");
});

await user.click(abstractBtn);

await waitFor(() => {
const toggleableInputs = screen.queryAllByTestId("toggleable-input");
expect(toggleableInputs).toHaveLength(5);
for (const input of toggleableInputs) {
expect(input).toBeInTheDocument();
expect(input).not.toHaveAttribute("readonly");
}
});

await user.click(generalInfoBtn);

await waitFor(() => {
const toggleableInputs = screen.queryAllByTestId("toggleable-input");
expect(toggleableInputs).toHaveLength(5);
for (const input of toggleableInputs.slice(0, 4)) {
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute("readonly");
}
expect(toggleableInputs[4]).toBeInTheDocument();
expect(toggleableInputs[4]).not.toHaveAttribute("readonly");
});

await user.click(abstractBtn);

await waitFor(() => {
const toggleableInputs = screen.queryAllByTestId("toggleable-input");
expect(toggleableInputs).toHaveLength(5);
for (const input of toggleableInputs) {
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute("readonly");
}
});
});

test("When editMode is not allowed, then edit buttons are not shown", async () => {
render(PaperDetailsCard, {
target: document.body,
props: {
loadingPaper: Promise.resolve(createPaper()),
allowEditModeToggle: false,
startInEditMode: false,
showButtonBar: true,
},
});

await waitForComponentLoading();

const editButtons = document.getElementsByTagName("svg");
let editButtonCount = 0;
for (const editButton of editButtons) {
if (!editButton.classList.contains("lucide-pencil")) {
continue;
}

expect(editButton).toBeInTheDocument();
editButtonCount++;
}
expect(editButtonCount).toBe(0);
});

test("When paper is loading, then skeletons are shown", async () => {
render(PaperDetailsCard, {
target: document.body,
props: {
loadingPaper: new Promise<Paper>((resolve) => {
setTimeout(() => {
resolve(createPaper());
}, 1000);
}),
allowEditModeToggle: true,
startInEditMode: false,
showButtonBar: true,
},
});

const skeletons = screen.queryAllByTestId("skeleton");
expect(skeletons).toHaveLength(11);
});
});
Loading

0 comments on commit 5ffeec4

Please sign in to comment.