Showing
16 changed files
with
218 additions
and
50 deletions
1 | +0.3.1: | ||
2 | +- ajout fichier de test MovieGender.spec.ts. | ||
3 | +- ajout fichier de test ScoreAndVote.spec.ts. | ||
4 | + | ||
1 | 0.3.0: | 5 | 0.3.0: |
2 | - Installation vuelidate et vuelidate/validator. | 6 | - Installation vuelidate et vuelidate/validator. |
3 | - Ajout composant SkeletonMovieDetailLoader. | 7 | - Ajout composant SkeletonMovieDetailLoader. |
@@ -105,7 +105,7 @@ function handleMessageEvent(event: string) { | @@ -105,7 +105,7 @@ function handleMessageEvent(event: string) { | ||
105 | @blur="v$.rating.$touch" | 105 | @blur="v$.rating.$touch" |
106 | @input="v$.rating.$touch" | 106 | @input="v$.rating.$touch" |
107 | /> | 107 | /> |
108 | -<!-- <pre>{{ errormessages }}</pre>--> | 108 | + <!-- <pre>{{ errormessages }}</pre>--> |
109 | <ui-components-tiny-mce-field-editor | 109 | <ui-components-tiny-mce-field-editor |
110 | :error-message="v$?.message?.$errors[0]?.$message ? (v$.message.$errors[0].$message as string) : ''" | 110 | :error-message="v$?.message?.$errors[0]?.$message ? (v$.message.$errors[0].$message as string) : ''" |
111 | :model-value="formData.message" | 111 | :model-value="formData.message" |
1 | -import { describe, it, expect } from 'vitest' | 1 | +import { describe, expect, it } from "vitest"; |
2 | -import { mount } from '@vue/test-utils' | 2 | +import { mount } from "@vue/test-utils"; |
3 | 3 | ||
4 | -import HelloWorld from './HelloWorld.vue' | 4 | +import HelloWorld from "./HelloWorld.vue"; |
5 | 5 | ||
6 | -describe('HelloWorld', () => { | 6 | +describe("HelloWorld", () => { |
7 | - it('component renders Hello world properly', () => { | 7 | + it("component renders Hello world properly", () => { |
8 | - const wrapper = mount(HelloWorld) | 8 | + const wrapper = mount(HelloWorld); |
9 | - expect(wrapper.text()).toContain('Hello world') | 9 | + expect(wrapper.text()).toContain("Hello world"); |
10 | - }) | 10 | + }); |
11 | -}) | 11 | +}); |
@@ -20,12 +20,7 @@ defineProps({ | @@ -20,12 +20,7 @@ defineProps({ | ||
20 | <template> | 20 | <template> |
21 | <section class="w-full md:w-1/3 lg:w-1/4"> | 21 | <section class="w-full md:w-1/3 lg:w-1/4"> |
22 | <div class="rounded-lg overflow-hidden shadow-lg bg-gray-800"> | 22 | <div class="rounded-lg overflow-hidden shadow-lg bg-gray-800"> |
23 | - <v-img | 23 | + <v-img v-if="src" :alt="title" :src="`https://image.tmdb.org/t/p/w500${src}`" class="w-full h-auto" /> |
24 | - v-if="src" | ||
25 | - :alt="title" | ||
26 | - :src="`https://image.tmdb.org/t/p/w500${src}`" | ||
27 | - class="w-full h-auto" | ||
28 | - /> | ||
29 | <div v-else class="aspect-[2/3] bg-gray-700 flex items-center justify-center"> | 24 | <div v-else class="aspect-[2/3] bg-gray-700 flex items-center justify-center"> |
30 | <FilmIcon :size="64" class="text-gray-500" /> | 25 | <FilmIcon :size="64" class="text-gray-500" /> |
31 | </div> | 26 | </div> |
@@ -33,6 +28,4 @@ defineProps({ | @@ -33,6 +28,4 @@ defineProps({ | ||
33 | </section> | 28 | </section> |
34 | </template> | 29 | </template> |
35 | 30 | ||
36 | -<style scoped> | 31 | +<style scoped></style> |
37 | - | ||
38 | -</style> |
@@ -6,7 +6,7 @@ import { useDebounceFn } from "@vueuse/core"; | @@ -6,7 +6,7 @@ import { useDebounceFn } from "@vueuse/core"; | ||
6 | //#endregion | 6 | //#endregion |
7 | 7 | ||
8 | //#region --Emits--. | 8 | //#region --Emits--. |
9 | -const emit = defineEmits(['event:search', 'event:clear_search']); | 9 | +const emit = defineEmits(["event:search", "event:clear_search"]); |
10 | //#endregion | 10 | //#endregion |
11 | 11 | ||
12 | //#region --Props--. | 12 | //#region --Props--. |
@@ -29,12 +29,12 @@ const searchQuery = ref(""); | @@ -29,12 +29,12 @@ const searchQuery = ref(""); | ||
29 | * Debounced function | 29 | * Debounced function |
30 | */ | 30 | */ |
31 | const handleSearchEvent = useDebounceFn(() => { | 31 | const handleSearchEvent = useDebounceFn(() => { |
32 | - emit('event:search', searchQuery.value); | 32 | + emit("event:search", searchQuery.value); |
33 | }, 500); | 33 | }, 500); |
34 | 34 | ||
35 | function handleClearSearchEvent() { | 35 | function handleClearSearchEvent() { |
36 | - searchQuery.value = ''; | 36 | + searchQuery.value = ""; |
37 | - emit('event:clear_search') | 37 | + emit("event:clear_search"); |
38 | } | 38 | } |
39 | //#endregion | 39 | //#endregion |
40 | </script> | 40 | </script> |
1 | -<script setup lang="ts"> | 1 | +<script setup lang="ts"></script> |
2 | - | ||
3 | -</script> | ||
4 | 2 | ||
5 | <template> | 3 | <template> |
6 | <v-container class="bg-gray-900"> | 4 | <v-container class="bg-gray-900"> |
7 | - <v-row class="bg-gray-900" > | 5 | + <v-row class="bg-gray-900"> |
8 | <v-col cols="12" sm="4"> | 6 | <v-col cols="12" sm="4"> |
9 | <v-skeleton-loader | 7 | <v-skeleton-loader |
10 | class="mx-auto border bg-gray-800" | 8 | class="mx-auto border bg-gray-800" |
@@ -27,6 +25,4 @@ | @@ -27,6 +25,4 @@ | ||
27 | </v-container> | 25 | </v-container> |
28 | </template> | 26 | </template> |
29 | 27 | ||
30 | -<style scoped> | 28 | +<style scoped></style> |
31 | - | ||
32 | -</style> |
1 | { | 1 | { |
2 | "name": "nuxt-app", | 2 | "name": "nuxt-app", |
3 | - "version": "0.3.0", | 3 | + "version": "0.3.1", |
4 | "lockfileVersion": 3, | 4 | "lockfileVersion": 3, |
5 | "requires": true, | 5 | "requires": true, |
6 | "packages": { | 6 | "packages": { |
7 | "": { | 7 | "": { |
8 | "name": "nuxt-app", | 8 | "name": "nuxt-app", |
9 | - "version": "0.3.0", | 9 | + "version": "0.3.1", |
10 | "hasInstallScript": true, | 10 | "hasInstallScript": true, |
11 | "dependencies": { | 11 | "dependencies": { |
12 | "@nuxt/eslint": "^1.3.0", | 12 | "@nuxt/eslint": "^1.3.0", |
test/components/MovieGender.spec.ts
0 → 100644
1 | +//#region --Import--. | ||
2 | +import { describe, expect, it } from "vitest"; | ||
3 | +import { mount } from "@vue/test-utils"; | ||
4 | +import MovieGender from "../../components/details/MovieGender.vue"; | ||
5 | +import type { Genre } from "~/interfaces/movie"; | ||
6 | +//#endregion | ||
7 | + | ||
8 | +describe("MovieGender", () => { | ||
9 | + it("affiche correctement les genres", () => { | ||
10 | + // Données de test. | ||
11 | + const genres: Genre[] = [ | ||
12 | + { id: 1, name: "Action" }, | ||
13 | + { id: 2, name: "Comédie" }, | ||
14 | + { id: 3, name: "Drame" }, | ||
15 | + ]; | ||
16 | + // Monter le composant avec sa props. | ||
17 | + const wrapper = mount(MovieGender, { | ||
18 | + props: { | ||
19 | + genres, | ||
20 | + }, | ||
21 | + }); | ||
22 | + // Vérifier que tous les genres sont affichés. | ||
23 | + const spanElements = wrapper.findAll("span"); | ||
24 | + // spanElements.length doit être égal aux données de test (genres.length). | ||
25 | + expect(spanElements.length).toBe(genres.length); | ||
26 | + | ||
27 | + // Vérifier le contenu affiché de chaque élément. | ||
28 | + spanElements.forEach((spanElement, index) => { | ||
29 | + // Sur chaque itération d'élément (span), vérification que le nom du genre correspondant soit bien affiché. | ||
30 | + expect(spanElement.text()).toContain(genres[index].name); | ||
31 | + expect(spanElement.text()).toBe(genres[index].name); | ||
32 | + }); | ||
33 | + }); | ||
34 | + | ||
35 | + it("affiche correctement un seul genre", () => { | ||
36 | + // Données de test. | ||
37 | + const genres: Genre[] = [{ id: 1, name: "Horreur" }]; | ||
38 | + // Monter le composant avec sa props. | ||
39 | + const wrapper = mount(MovieGender, { | ||
40 | + props: { | ||
41 | + genres, | ||
42 | + }, | ||
43 | + }); | ||
44 | + // Vérifier que le genre soit affiché. | ||
45 | + const spanElements = wrapper.findAll("span"); | ||
46 | + // spanElements.length doit être égal aux données de test (ici 1). | ||
47 | + expect(spanElements.length).toBe(genres.length); | ||
48 | + | ||
49 | + // Vérifier le contenu affiché de l'élément. | ||
50 | + expect(spanElements[0].text()).toContain(genres[0].name); | ||
51 | + expect(spanElements[0].text()).toBe(genres[0].name); | ||
52 | + }); | ||
53 | + | ||
54 | + it("ne rend aucun élément span quand la liste est vide", () => { | ||
55 | + // Données de test volontairement vide. | ||
56 | + const genres: Genre[] = []; | ||
57 | + // Monter le composant avec sa props. | ||
58 | + const wrapper = mount(MovieGender, { | ||
59 | + props: { | ||
60 | + genres, | ||
61 | + }, | ||
62 | + }); | ||
63 | + // spanElements.length doit être égal à 0. | ||
64 | + const spanElements = wrapper.findAll("span"); | ||
65 | + expect(spanElements.length).toBe(0); | ||
66 | + }); | ||
67 | +}); |
test/components/ScoreAndVote.spec.ts
0 → 100644
1 | +//#region --Import--. | ||
2 | +import { describe, expect, it } from "vitest"; | ||
3 | +import { mount } from "@vue/test-utils"; | ||
4 | +import ScoreAndVote from "../../components/details/ScoreAndVote.vue"; | ||
5 | +//#endregion | ||
6 | + | ||
7 | +describe("ScoreAndVote", () => { | ||
8 | + it("affiche correctement le score", () => { | ||
9 | + // Monter le composant avec ses props. | ||
10 | + const wrapper = mount(ScoreAndVote, { | ||
11 | + props: { | ||
12 | + score: 7, | ||
13 | + nbVote: 100, | ||
14 | + }, | ||
15 | + }); | ||
16 | + // Trouver l'élément qui contient le score. | ||
17 | + const scoreElement = wrapper.find(".bg-primary"); | ||
18 | + // Vérifier que le score est affiché correctement. | ||
19 | + expect(scoreElement.text()).contain("7"); | ||
20 | + }); | ||
21 | + | ||
22 | + it("affiche exactement le score avec une décimale", () => { | ||
23 | + // Monter le composant avec ses props. | ||
24 | + const wrapper = mount(ScoreAndVote, { | ||
25 | + props: { | ||
26 | + score: 8.5, | ||
27 | + nbVote: 100, | ||
28 | + }, | ||
29 | + }); | ||
30 | + // Trouver l'élément qui contient le score. | ||
31 | + const scoreElement = wrapper.find(".bg-primary"); | ||
32 | + // Vérifier que le score est affiché correctement. | ||
33 | + expect(scoreElement.text()).toBe("8.5"); | ||
34 | + }); | ||
35 | + | ||
36 | + it("arrondit correctement le score à une décimale", () => { | ||
37 | + // Tester avec un score qui a plus d'une décimale. | ||
38 | + const wrapper = mount(ScoreAndVote, { | ||
39 | + props: { | ||
40 | + score: 7.654, | ||
41 | + nbVote: 100, | ||
42 | + }, | ||
43 | + }); | ||
44 | + // Trouver l'élément qui contient le score. | ||
45 | + const scoreElement = wrapper.find(".bg-primary"); | ||
46 | + // Arrondi à une décimale. | ||
47 | + expect(scoreElement.text()).toBe("7.7"); | ||
48 | + }); | ||
49 | + | ||
50 | + it("affiche correctement le paragraphe", () => { | ||
51 | + // Monter le composant avec ses props. | ||
52 | + const wrapper = mount(ScoreAndVote, { | ||
53 | + props: { | ||
54 | + score: 7.654, | ||
55 | + nbVote: 100, | ||
56 | + }, | ||
57 | + }); | ||
58 | + // Trouver l'élément qui contient le paragraphe. | ||
59 | + const paragrapheElement = wrapper.find("p"); | ||
60 | + expect(paragrapheElement.text()).toBe("Note TMDB"); | ||
61 | + }); | ||
62 | + | ||
63 | + it("affiche correctement le nombre de vote sans formatage si inférieur à 1000", () => { | ||
64 | + // Monter le composant avec ses props. | ||
65 | + const wrapper = mount(ScoreAndVote, { | ||
66 | + props: { | ||
67 | + score: 7.654, | ||
68 | + nbVote: 855, | ||
69 | + }, | ||
70 | + }); | ||
71 | + // Trouver l'élément qui contient le nombre de votes. | ||
72 | + const voteElement = wrapper.find("div"); | ||
73 | + // Vérifier si la div contient le nombre. | ||
74 | + expect(voteElement.text()).toContain("855"); | ||
75 | + // Vérifier si le texte de la div correspond exactement. | ||
76 | + expect(voteElement.text()).toBe("855 votes"); | ||
77 | + }); | ||
78 | + | ||
79 | + it("affiche correctement le nombre de vote formaté en 'k' si supérieur ou égal à 1000", () => { | ||
80 | + // Monter le composant avec ses props. | ||
81 | + const wrapper = mount(ScoreAndVote, { | ||
82 | + props: { | ||
83 | + score: 9, | ||
84 | + nbVote: 1477, | ||
85 | + }, | ||
86 | + }); | ||
87 | + // Trouver l'élément qui contient le nombre de votes. | ||
88 | + const voteElement = wrapper.find("div"); | ||
89 | + // Vérifier si la div contient le nombre. | ||
90 | + expect(voteElement.text()).toContain("1.5"); | ||
91 | + // Vérifier si le texte de la div correspond exactement. | ||
92 | + expect(voteElement.text()).toBe("1.5k votes"); | ||
93 | + }); | ||
94 | +}); |
@@ -5,7 +5,7 @@ export default { | @@ -5,7 +5,7 @@ export default { | ||
5 | plugins: [vue()], | 5 | plugins: [vue()], |
6 | test: { | 6 | test: { |
7 | globals: true, | 7 | globals: true, |
8 | - environment: "jsdom", | 8 | + environment: "happy-dom", |
9 | // Additional test configurations can be added here | 9 | // Additional test configurations can be added here |
10 | }, | 10 | }, |
11 | } | 11 | } |
1 | import { defineVitestConfig } from '@nuxt/test-utils/config' | 1 | import { defineVitestConfig } from '@nuxt/test-utils/config' |
2 | +import vue from '@vitejs/plugin-vue' | ||
3 | +import { fileURLToPath } from 'node:url' | ||
2 | 4 | ||
3 | export default defineVitestConfig({ | 5 | export default defineVitestConfig({ |
4 | /** | 6 | /** |
@@ -7,15 +9,30 @@ export default defineVitestConfig({ | @@ -7,15 +9,30 @@ export default defineVitestConfig({ | ||
7 | */ | 9 | */ |
8 | test: { | 10 | test: { |
9 | environment: 'nuxt', | 11 | environment: 'nuxt', |
12 | + globals: true, | ||
10 | // you can optionally set Nuxt-specific environment options | 13 | // you can optionally set Nuxt-specific environment options |
11 | - // environmentOptions: { | 14 | + environmentOptions: { |
12 | - // nuxt: { | 15 | + nuxt: { |
13 | - // rootDir: fileURLToPath(new URL('./playground', import.meta.url)), | 16 | + rootDir: fileURLToPath(new URL('./', import.meta.url)), |
14 | - // domEnvironment: 'happy-dom', // 'happy-dom' (default) or 'jsdom' | 17 | + domEnvironment: 'happy-dom', // 'happy-dom' (default) or 'jsdom' |
15 | - // overrides: { | 18 | + overrides: { |
16 | - // // other Nuxt config you want to pass | 19 | + // other Nuxt config you want to pass |
17 | - // } | 20 | + }, |
18 | - // } | 21 | + mock: { |
19 | - // } | 22 | + intersectionObserver: true, |
23 | + indexedDb: true, | ||
24 | + } | ||
25 | + }, | ||
26 | + }, | ||
27 | + coverage: { | ||
28 | + provider: 'v8', | ||
29 | + reporter: ['text', 'json', 'html'], | ||
30 | + } | ||
31 | + }, | ||
32 | + resolve: { | ||
33 | + alias: { | ||
34 | + '~': fileURLToPath(new URL('./', import.meta.url)), | ||
35 | + '@': fileURLToPath(new URL('./', import.meta.url)), | ||
36 | + } | ||
20 | } | 37 | } |
21 | }) | 38 | }) |
-
Please register or login to post a comment