Ver Fonte

configure vitest and first unit tests

Olivier Massot há 3 anos atrás
pai
commit
4873f61595

+ 6 - 3
package.json

@@ -16,10 +16,10 @@
     "start": "nuxt start --hostname '127.0.0.1' --port 3003",
     "lint": "eslint --ext \".ts,.js,.vue\" --ignore-path .gitignore .",
     "lint-fix": "eslint --fix --ext \".ts,.js,.vue\" --ignore-path .gitignore .",
-    "deploy": "git pull && yarn install && yarn build && pm2 start app",
-    "infos": "npx nuxi info"
+    "test": "vitest run --coverage"
   },
   "devDependencies": {
+    "@nuxt/test-utils": "^3.0.0",
     "@nuxt/test-utils-edge": "^3.0.1-rc.0-27810184.d991a55",
     "@nuxtjs/eslint-config": "^11.0.0",
     "@nuxtjs/eslint-config-typescript": "^11.0.0",
@@ -31,13 +31,16 @@
     "@types/uuid": "^8.3.4",
     "@typescript-eslint/eslint-plugin": "^5.43.0",
     "@typescript-eslint/parser": "^5.43.0",
+    "@vitejs/plugin-vue": "^4.0.0",
+    "@vitest/coverage-c8": "^0.27.2",
     "@vue/eslint-config-standard": "^8.0.1",
+    "@vue/test-utils": "^2.2.7",
     "eslint": "^8.27.0",
     "eslint-config-prettier": "^8.5.0",
     "eslint-plugin-nuxt": "^4.0.0",
     "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-vue": "^9.7.0",
-    "jest": "^29.3.1",
+    "jsdom": "^21.0.0",
     "nuxt": "^3.0.0",
     "prettier": "^2.7.1",
     "ts-jest": "^29.0.3",

+ 0 - 0
tests/.gitkeep


+ 19 - 0
tests/alias.ts

@@ -0,0 +1,19 @@
+import { resolve } from 'path'
+
+/**
+ * Nécessaire pour permettre à vitest de résoudre les imports relatifs
+ * @see https://github.com/vitest-dev/vitest/discussions/1285
+ */
+
+const r = (p: string) => resolve(__dirname, '..', p)
+
+export const alias: Record<string, string> = {
+    '~': r('.'),
+    '~~': r('.'),
+    '~~/': r('./'),
+    '@@': r('.'),
+    '@@/': r('./'),
+    assets: r('./assets'),
+    public: r('./public'),
+    'public/': r('./public/'),
+}

+ 57 - 0
tests/readme.md

@@ -0,0 +1,57 @@
+# Tests unitaires
+
+Ce répertoire contient les tests unitaires du front Vue.js
+
+> Plus d'infos:
+> 
+> * https://vuejs.org/guide/scaling-up/testing.html#unit-testing
+> * https://test-utils.vuejs.org/
+> * https://plugins.jetbrains.com/plugin/19220-vitest-runner
+
+## Exécuter les tests
+
+Pour exécuter les tests, lancer :
+
+    yarn test
+
+## Mocking
+
+#### Différentes façons pour Mocker
+
+    import axios from 'axios'
+    import { NuxtAxiosInstance } from '@nuxtjs/axios'
+    jest.mock('axios')
+    const mockNuxtAxios = axios as jest.Mocked<NuxtAxiosInstance>
+    mockNuxtAxios.$get = jest.fn().mockReturnValue({})
+
+Ou
+
+    import DataProvider from "~/services/dataProvider/dataProvider";
+    jest.mock('~/services/dataProvider/dataProvider');
+    const DataProviderMock = DataProvider as jest.MockedClass<typeof DataProvider>;
+    DataProviderMock.prototype.invoke.mockImplementation(async () => true)
+
+Ou
+
+    import VueI18n from "vue-i18n";
+    const VueI18nMock = VueI18n as jest.MockedClass<typeof VueI18n>;
+    VueI18nMock.prototype.t = jest.fn().mockReturnValue('siret_error')
+
+Ou, si on définit le fichier ~/services/dataProvider/__mocks__/dataProvider.ts avec l'implémenation de invoke :
+
+    const mock = jest.fn().mockImplementation(() => {
+        return {invoke: () => {
+            return true
+        }};
+    });
+    export default mock;
+
+Alors on appelle useHandleSiret comme cela : 
+
+    const siretResponse = UseChecker.useHandleSiret(new DataProviderMock())
+
+
+ATTENTION : dans ce cas cette déclaration sera prioritaire sur les autres façons de mocker l'implémentation et on ne peut pas avoir 2 types de mock différents pour
+cette classe dans l'application.
+
+Pour pouvoir gérer l'implémentation à la volée, il ne faut pas qu'il y ait le fichier dans le dossier __mocks__

+ 122 - 0
tests/units/services/data/serializer/denormalizer/hydraDenormalizer.spec.ts

@@ -0,0 +1,122 @@
+import { describe, test, it, expect } from 'vitest'
+import {AnyJson} from "~/types/data";
+import HydraDenormalizer from "~/services/data/serializer/denormalizer/hydraDenormalizer";
+
+describe('denormalize', () => {
+    test('should parse a API Item response and return a JSON Object', () => {
+        const serverResponse: AnyJson = {
+            '@context': '/api/contexts/Access',
+            '@id': '/api/accesses/7351',
+            '@type': 'Access',
+            organization: '/api/organizations/37306',
+            id: 7351,
+            person: {
+                '@type': 'Person',
+                id: 11344,
+                name: 'BRUEL',
+                givenName: 'Patrick'
+            },
+            'hydra:totalItems': 20,
+            'hydra:previous': '/api/organizations?page=1',
+            'hydra:next': '/api/organizations?page=2',
+            'hydra:itemPosition': 1
+        }
+
+        expect(HydraDenormalizer.denormalize(serverResponse)).toStrictEqual<AnyJson>({
+            "data": {
+                "@context": "/api/contexts/Access",
+                "@id": "/api/accesses/7351",
+                "@type": "Access",
+                "hydra:itemPosition": 1,
+                "hydra:next": "/api/organizations?page=2",
+                "hydra:previous": "/api/organizations?page=1",
+                "hydra:totalItems": 20,
+                "id": 7351,
+                "organization": "/api/organizations/37306",
+                "person": {
+                    "@type": "Person",
+                    "givenName": "Patrick",
+                    "id": 11344,
+                    "name": "BRUEL"
+                }
+            },
+            "metadata": {
+                "type": 0
+            }
+        })
+    })
+
+    it('should parse a API Collection response and return a JSON Object', () => {
+        const serverResponse: AnyJson = {
+            '@context': '/api/contexts/Access',
+            '@id': '/api/accesses',
+            '@type': 'hydra:Collection',
+            'hydra:member': [{
+                '@id': '/api/accesses/7351',
+                organization: '/api/organizations/37306',
+                id: 7351,
+                person: {
+                    '@type': 'Person',
+                    id: 11344,
+                    name: 'BRUEL',
+                    givenName: 'Patrick'
+                }
+            }, {
+                '@id': '/api/accesses/7352',
+                organization: '/api/organizations/37306',
+                id: 7352,
+                person: {
+                    '@type': 'Person',
+                    id: 11345,
+                    name: 'BRASSENS',
+                    givenName: 'George'
+                }
+            }
+            ],
+            'hydra:search': {
+                'hydra:mapping': [
+                    {
+                        property: 'id',
+                        required: false,
+                        variable: 'filter[order][id]'
+                    },
+                    {
+                        property: 'id',
+                        required: false,
+                        variable: 'filter[where][id]'
+                    }
+                ]
+            }
+        }
+
+        const response = HydraDenormalizer.denormalize(serverResponse)
+        expect(JSON.stringify(response)).toEqual(JSON.stringify({"data":[
+                {
+                    '@id': '/api/accesses/7351',
+                    organization: '/api/organizations/37306',
+                    id: 7351,
+                    person:
+                        {
+                            '@type': 'Person',
+                            id: 11344,
+                            name: 'BRUEL',
+                            givenName: 'Patrick'
+                        }
+                },
+                {
+                    '@id': '/api/accesses/7352',
+                    organization: '/api/organizations/37306',
+                    id: 7352,
+                    person:
+                        {
+                            '@type': 'Person',
+                            id: 11345,
+                            name: 'BRASSENS',
+                            givenName: 'George'
+                        }
+                }
+            ], 'metadata':{'type':1}}
+        ))
+    })
+})
+

+ 15 - 0
vitest.config.ts

@@ -0,0 +1,15 @@
+import { defineConfig } from 'vitest/config'
+import {alias} from "./tests/alias";
+
+/**
+ * @see https://vitest.dev/config/
+ */
+export default defineConfig({
+    test: {
+        globals: true,
+        environment: 'jsdom',
+    },
+    resolve: {
+        alias,
+    },
+})