Showing
16 changed files
with
221 additions
and
53 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" |
| @@ -14,7 +12,7 @@ | @@ -14,7 +12,7 @@ | ||
| 14 | type="paragraph, image" | 12 | type="paragraph, image" |
| 15 | /> | 13 | /> |
| 16 | </v-col> | 14 | </v-col> |
| 17 | - <v-col cols="12" sm="8"> | 15 | + <v-col cols="12" sm="8"> |
| 18 | <v-skeleton-loader | 16 | <v-skeleton-loader |
| 19 | class="mx-auto mt-10" | 17 | class="mx-auto mt-10" |
| 20 | color="#1f2937" | 18 | color="#1f2937" |
| @@ -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