Skip to content

Commit

Permalink
test: fix test setup + add WordSuggestHint
Browse files Browse the repository at this point in the history
  • Loading branch information
felix-berlin committed Jul 12, 2024
1 parent 8d35c0e commit 96e6d32
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 11 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"lint:style": "stylelint \"**/*.{scss,sass}\" --ignore-path .gitignore",
"lint": "pnpm run lint:js && pnpm run lint:style",
"test:unit": "vitest --coverage",
"test:unit:ui": "vitest --coverage --ui",
"vitest:update": "vitest --update",
"format": "npx prettier --write .",
"gql:generate": "gql-gen --config codegen.ts",
Expand Down Expand Up @@ -77,6 +78,7 @@
"@vite-pwa/astro": "^0.4.0",
"@vitejs/plugin-vue": "^5.0.5",
"@vitest/coverage-v8": "^2.0.2",
"@vitest/web-worker": "^2.0.2",
"@vue/compiler-sfc": "^3.4.31",
"@vue/devtools-api": "^6.6.3",
"@vue/test-utils": "^2.4.6",
Expand Down
50 changes: 45 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/components/WordSuggestHint.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import Plus from "virtual:icons/lucide/plus";
import { $wordSearch } from "@stores/index.ts";
import { useStore } from "@nanostores/vue";
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const Modal = defineAsyncComponent(() => import("@components/Modal.vue"));
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const SuggestWordForm = defineAsyncComponent(() => import("@components/SuggestWordForm.vue"));
const wordSearch = useStore($wordSearch);
Expand Down
2 changes: 1 addition & 1 deletion src/tests/unit/components/RandomWordButton.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ describe("RandomWordButton.vue", () => {

// Check that the rendered href contains one of the word slugs
const href = wrapper.find("a").attributes("href");
expect(words.some((word) => href.includes(word.slug))).toBe(true);
expect(words.some((word) => href?.includes(word.slug))).toBe(true);
});
});
64 changes: 64 additions & 0 deletions src/tests/unit/components/WordSuggestHint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { describe, it, expect, vi } from "vitest";
import { mount } from "@vue/test-utils";
import WordSuggestHint from "/home/felix/workspace/berliner-schnauze/src/components/WordSuggestHint.vue";

vi.mock("@nanostores/vue", () => ({
useStore: () => ({
wordSearch: {
letterGroups: [],
activeLetterFilter: "",
wordTypes: [],
activeWordTypeFilter: "",
wordList: [],
search: "",
alphabeticalOrder: "asc",
dateOrder: "asc",
modifiedDateOrder: "asc",
activeOrderCategory: "alphabetical",
berolinismus: false,
},
}),
}));

vi.mock("@stores/index.ts", () => ({
$wordSearch: vi.fn(),
}));

vi.mock("@components/Modal.vue", async (importOriginal) => {
const originalModule = await importOriginal<typeof import("@components/Modal.vue")>();
return {
__esModule: true, // This line is important for Vitest to understand it's an ES module mock
__isTeleport: true, // Add the missing export
default: {
name: "Modal",
template: "<div></div>",
// You can spread other properties from the original module if needed
...originalModule,
},
};
});

vi.mock("@components/SuggestWordForm.vue", () => ({
name: "SuggestWordForm",
template: "<div></div>",
}));

describe("WordSuggestHint.vue", {}, () => {
it("renders without errors", () => {
const wrapper = mount(WordSuggestHint);
expect(wrapper.exists()).toBe(true);
});

it("initially does not show the modal", () => {
const wrapper = mount(WordSuggestHint);
expect(wrapper.vm.showModal).toBe(false);
});

it("attempts to load and show the modal when button is clicked", async () => {
const wrapper = mount(WordSuggestHint);
await wrapper.find("button").trigger("click");
// Since modal loading is asynchronous and involves retries, you might need to mock or wait
expect(wrapper.vm.loadModal).toBe(true);
// Further assertions can be made depending on the mock implementation of the modal loading logic
});
});
4 changes: 2 additions & 2 deletions src/tests/unit/components/filter/LetterFilter.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { mount } from "@vue/test-utils";
import { mount, VueWrapper } from "@vue/test-utils";
import LetterFilter from "@components/filter/LetterFilter.vue";
import { nextTick } from "vue";
import { $wordSearch, setLetterFilter } from "@stores/index.ts";
Expand All @@ -18,7 +18,7 @@ vi.mock("@stores/index.ts", () => ({
}));

describe("LetterFilter.vue", () => {
let wrapper;
let wrapper: VueWrapper<any, any>;

beforeEach(() => {
wrapper = mount(LetterFilter);
Expand Down
119 changes: 119 additions & 0 deletions src/tests/unit/services/filterWorker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { describe, it, expect } from "vitest";
import "@vitest/web-worker";
import filterWorker from "../../../services/filterWorker.ts?worker";

let worker = new filterWorker();
worker = new Worker(new URL("../../../services/filterWorker.ts?worker", import.meta.url));

describe("filterWorker", () => {
it("should filter words by activeLetterFilter", () => {
worker.postMessage({
letterGroups: [
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"Z",
"Ä",
"Ö",
"ü",
],
wordList: [
{
id: "cG9zdDo0MjUz",
slug: "aas",
wordGroup: "A",
dateGmt: "2022-01-22T17:28:48",
modifiedGmt: "2024-01-25T17:31:51",
berlinerWordId: 4253,
wordProperties: {
article: null,
berlinerisch: "Aas",
berlinerischAudio: null,
learnMore: null,
berolinismus: false,
examples: [
{ example: "Dir Aas kenn ick!", exampleExplanation: null, exampleAudio: null },
{ example: "Keen Aas hier!", exampleExplanation: "keiner da", exampleAudio: null },
],
translations: [
{ translation: "unbeliebter" },
{ translation: "hinterhältiger Mensch" },
],
alternativeWords: null,
relatedWords: {
nodes: [
{ id: "cG9zdDo0MjUz", wordProperties: { berlinerisch: "Aas" }, slug: "aas" },
{
id: "cG9zdDo0MjU0",
wordProperties: { berlinerisch: "Abeetadenkmal" },
slug: "abeetadenkmal",
},
{
id: "cG9zdDo0Njkx",
wordProperties: { berlinerisch: "abfahren " },
slug: "abfahren",
},
],
},
wikimediaFiles: null,
images: null,
},
berlinerischWordTypes: { nodes: [{ name: "Substantiv" }] },
},
{
id: "cG9zdDo0MjU0",
slug: "abeetadenkmal",
wordGroup: "A",
dateGmt: "2022-01-22T17:39:21",
modifiedGmt: "2022-06-03T11:20:04",
berlinerWordId: 4254,
wordProperties: {
article: null,
berlinerisch: "Abeetadenkmal",
berlinerischAudio: null,
learnMore: null,
berolinismus: false,
examples: [
{
example: "Der steht da mit seine Schaufel wie ‘n Abeetadenkmal.",
exampleExplanation: null,
exampleAudio: null,
},
],
translations: [{ translation: "Arbeiterdenkmal" }, { translation: "fauler Arbeiter" }],
alternativeWords: null,
relatedWords: null,
wikimediaFiles: null,
images: null,
},
berlinerischWordTypes: { nodes: [{ name: "Substantiv" }] },
},
],
activeLetterFilter: "A",
});

worker.onmessage = (e) => {
expect(e.data).toEqual([{ wordGroup: "a" }]);
};
});
});
11 changes: 8 additions & 3 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// <reference types="vitest" />
import { defineConfig } from "vite";
import { defineConfig, coverageConfigDefaults } from "vitest/config";
import Vue from "@vitejs/plugin-vue";
import Icons from "unplugin-icons/vite";
import allAlias from "./alias.ts";
Expand All @@ -26,10 +26,15 @@ export default defineConfig({
exclude: ["src/tests/unit/__needsFix/*"],
globals: true,
environment: "jsdom",
setupFiles: ["src/tests/setup.ts"],
setupFiles: ["src/tests/setup.ts", "@vitest/web-worker"],
coverage: {
include: ["src/**"],
exclude: ["src/types/**", "src/env.d.ts", "src/pages/_app.ts"],
exclude: [
"src/types/**",
"src/env.d.ts",
"src/pages/_app.ts",
...coverageConfigDefaults.exclude,
],
reportsDirectory: "./tests/unit/coverage",
},
},
Expand Down

0 comments on commit 96e6d32

Please sign in to comment.