From bde087e5a3668ab14b348236a920328ef70f6d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanislas=20Ormi=C3=A8res?= Date: Wed, 6 Dec 2023 14:58:52 +0100 Subject: [PATCH 01/13] feat: :sparkles: configure vitest et cypress pour nuxt3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - met à jour toutes les dépendances - configure vitest - configure cypress pour les tests E2E --- template-nuxt3-ts/README.md | 26 + template-nuxt3-ts/cypress.config.ts | 57 ++ template-nuxt3-ts/cypress/e2e/home.cy.ts | 5 + .../cypress/fixtures/example.json | 5 + template-nuxt3-ts/cypress/support/commands.ts | 37 + template-nuxt3-ts/cypress/support/e2e.ts | 20 + template-nuxt3-ts/nuxt.config.ts | 7 +- template-nuxt3-ts/package.json | 51 +- template-nuxt3-ts/vitest-setup.ts | 6 + template-nuxt3-ts/vitest.config.ts | 13 + template-vue3-ts/.eslintrc-auto-import.json | 6 +- template-vue3-ts/.eslintrc.cjs | 1 + template-vue3-ts/.vscode/extensions.json | 10 +- .../.vscode/vue-dsfr.code-snippets | 821 ------------------ template-vue3-ts/auto-imports.d.ts | 4 +- template-vue3-ts/cypress/.eslintrc.cjs | 12 - template-vue3-ts/cypress/e2e/tsconfig.json | 7 +- template-vue3-ts/cypress/tsconfig.json | 8 - template-vue3-ts/package.json | 64 +- .../public/android-chrome-192x192.png | Bin 0 -> 27293 bytes .../public/android-chrome-512x512.png | Bin 0 -> 135603 bytes template-vue3-ts/public/apple-touch-icon.png | Bin 0 -> 24423 bytes template-vue3-ts/public/favicon-16x16.png | Bin 0 -> 608 bytes template-vue3-ts/public/favicon-32x32.png | Bin 0 -> 1510 bytes template-vue3-ts/vite.config.ts | 24 +- template-vue3-ts/vitest-setup.ts | 2 +- template-vue3/.eslintrc-auto-import.json | 6 +- ...ailhog-commands.ts => mailhog-commands.js} | 0 template-vue3/package.json | 60 +- template-vue3/vitest-setup.js | 2 +- 30 files changed, 308 insertions(+), 946 deletions(-) create mode 100644 template-nuxt3-ts/cypress.config.ts create mode 100644 template-nuxt3-ts/cypress/e2e/home.cy.ts create mode 100644 template-nuxt3-ts/cypress/fixtures/example.json create mode 100644 template-nuxt3-ts/cypress/support/commands.ts create mode 100644 template-nuxt3-ts/cypress/support/e2e.ts create mode 100644 template-nuxt3-ts/vitest-setup.ts create mode 100644 template-nuxt3-ts/vitest.config.ts delete mode 100644 template-vue3-ts/.vscode/vue-dsfr.code-snippets delete mode 100644 template-vue3-ts/cypress/.eslintrc.cjs delete mode 100644 template-vue3-ts/cypress/tsconfig.json create mode 100644 template-vue3-ts/public/android-chrome-192x192.png create mode 100644 template-vue3-ts/public/android-chrome-512x512.png create mode 100644 template-vue3-ts/public/apple-touch-icon.png create mode 100644 template-vue3-ts/public/favicon-16x16.png create mode 100644 template-vue3-ts/public/favicon-32x32.png rename template-vue3/cypress/support/{mailhog-commands.ts => mailhog-commands.js} (100%) diff --git a/template-nuxt3-ts/README.md b/template-nuxt3-ts/README.md index e9b395c..d0edac5 100644 --- a/template-nuxt3-ts/README.md +++ b/template-nuxt3-ts/README.md @@ -31,4 +31,30 @@ Prévisualisation du code de prod (nécessite un build préalable) : npm run preview ``` +## Lancer les tests avec vitest + +Vitest est déjà configuré pour vos tests. + +Pour les lancer : + +```bash +npm run test:unit +``` + +## Lancer les tests de bout-en-bout avec Cypress + +Cypress est déjà configuré pour vos tests de bout-en-bout (end-to-end). + +Pour les lancer avec l’interface : + +```bash +npm run test:e2e +``` + +Pour les lancer sans l’interface (dans la CI) : + +```bash +npm run test:e2e:ci +``` + Regarder ensuite la [documentation de Nuxt concernant le déploiement](https://nuxt.com/docs/getting-started/deployment). diff --git a/template-nuxt3-ts/cypress.config.ts b/template-nuxt3-ts/cypress.config.ts new file mode 100644 index 0000000..0db56f8 --- /dev/null +++ b/template-nuxt3-ts/cypress.config.ts @@ -0,0 +1,57 @@ +// cypress.config.ts +import { defineConfig } from 'cypress' +import { loadNuxt, buildNuxt } from '@nuxt/kit' +import type { InlineConfig } from 'vite' + +async function getNuxtViteConfig () { + const nuxt = await loadNuxt({ + cwd: process.cwd(), + dev: false, + overrides: { + ssr: false, + }, + }) + return new Promise((resolve, reject) => { + nuxt.hook('vite:extendConfig', (config) => { + resolve(config) + throw new Error('_stop_') + }) + buildNuxt(nuxt).catch((err) => { + if (!err.toString().includes('_stop_')) { + reject(err) + } + }) + }).finally(() => nuxt.close()) +} + +export default defineConfig({ + // ... + component: { + devServer: { + framework: 'vue', + bundler: 'vite', + async viteConfig () { + const config = await getNuxtViteConfig() + + config.plugins = config?.plugins?.filter( + // @ts-ignore + item => !['replace', 'vite-plugin-eslint'].includes(item.name), + ) + + if (config.server) { + config.server.middlewareMode = false + } + + return config + }, + }, + }, + + e2e: { + supportFolder: 'cypress/support', + fixturesFolder: 'cypress/fixtures', + setupNodeEvents (on, config) { + // implement node event listeners here + }, + }, +}) diff --git a/template-nuxt3-ts/cypress/e2e/home.cy.ts b/template-nuxt3-ts/cypress/e2e/home.cy.ts new file mode 100644 index 0000000..b9b1c93 --- /dev/null +++ b/template-nuxt3-ts/cypress/e2e/home.cy.ts @@ -0,0 +1,5 @@ +describe('Homepage', () => { + it('shows homepage', () => { + cy.visit('http://localhost:3000/') + }) +}) diff --git a/template-nuxt3-ts/cypress/fixtures/example.json b/template-nuxt3-ts/cypress/fixtures/example.json new file mode 100644 index 0000000..02e4254 --- /dev/null +++ b/template-nuxt3-ts/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/template-nuxt3-ts/cypress/support/commands.ts b/template-nuxt3-ts/cypress/support/commands.ts new file mode 100644 index 0000000..698b01a --- /dev/null +++ b/template-nuxt3-ts/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/template-nuxt3-ts/cypress/support/e2e.ts b/template-nuxt3-ts/cypress/support/e2e.ts new file mode 100644 index 0000000..f80f74f --- /dev/null +++ b/template-nuxt3-ts/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/template-nuxt3-ts/nuxt.config.ts b/template-nuxt3-ts/nuxt.config.ts index a76fb4a..fe09391 100644 --- a/template-nuxt3-ts/nuxt.config.ts +++ b/template-nuxt3-ts/nuxt.config.ts @@ -1,8 +1,9 @@ -import { defineNuxtConfig } from 'nuxt/config' - // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - buildModules: ['@nuxt/typescript-build'], + devtools: { enabled: true }, + modules: [ + 'nuxt-vitest', + ], css: [ '@gouvfr/dsfr/dist/dsfr.min.css', '@gouvfr/dsfr/dist/utility/icons/icons.min.css', diff --git a/template-nuxt3-ts/package.json b/template-nuxt3-ts/package.json index 08f3b67..aa6f5a8 100644 --- a/template-nuxt3-ts/package.json +++ b/template-nuxt3-ts/package.json @@ -1,6 +1,7 @@ { "name": "vue-dsfr-nuxt-ts-starter", "version": "0.0.0", + "type": "module", "scripts": { "build": "nuxt build", "dev": "nuxt dev", @@ -8,41 +9,43 @@ "generate": "nuxt generate", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore", "preview": "nuxt preview", + "test:unit": "vitest run", + "test:e2e": "cypress open --e2e", + "test:e2e:ci": "cypress run --e2e", "postinstall": "nuxt prepare" }, "dependencies": { "@gouvfr/dsfr": "1.10.1", - "@gouvminint/vue-dsfr": "^4.6.0", - "focus-trap": "^7.5.2", - "focus-trap-vue": "^4.0.2" + "@gouvminint/vue-dsfr": "^5.3.1", + "focus-trap": "^7.5.4", + "focus-trap-vue": "^4.0.3" }, "devDependencies": { "@nuxt/devtools": "latest", - "@nuxt/test-utils": "^3.7.3", - "@nuxt/types": "^2.17.1", - "@nuxt/typescript-build": "^3.0.1", "@nuxtjs/eslint-config-typescript": "^12.1.0", - "@rushstack/eslint-patch": "^1.3.3", - "@testing-library/jest-dom": "^6.1.3", - "@testing-library/user-event": "^14.4.3", - "@testing-library/vue": "^7.0.0", - "@types/jsdom": "^21.1.2", - "@types/node": "^18.17.15", - "@typescript-eslint/eslint-plugin": "^6.7.0", - "@typescript-eslint/parser": "^6.7.0", + "@rushstack/eslint-patch": "^1.6.0", + "@testing-library/jest-dom": "^6.1.5", + "@testing-library/user-event": "^14.5.1", + "@testing-library/vue": "^8.0.1", + "@types/jsdom": "^21.1.6", + "@types/node": "^18.19.2", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", "@vue/eslint-config-typescript": "^12.0.0", - "@vue/tsconfig": "^0.4.0", - "eslint": "^8.49.0", - "eslint-config-standard-with-typescript": "^39.0.0", - "eslint-plugin-cypress": "^2.14.0", - "eslint-plugin-import": "^2.28.1", + "cypress": "^13.6.1", + "eslint": "^8.55.0", + "eslint-config-standard-with-typescript": "^39.1.1", + "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-n": "^16.3.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-vue": "^9.17.0", - "jsdom": "^22.1.0", + "eslint-plugin-vue": "^9.19.2", + "happy-dom": "^12.10.3", "npm-run-all": "^4.1.5", - "nuxt": "^3.7.3", - "start-server-and-test": "^2.0.0", - "typescript": "~5.2.2" + "nuxt": "^3.8.2", + "nuxt-vitest": "^0.11.5", + "typescript": "^5.3.2", + "vitest": "^1.0.1" } } \ No newline at end of file diff --git a/template-nuxt3-ts/vitest-setup.ts b/template-nuxt3-ts/vitest-setup.ts new file mode 100644 index 0000000..08bf47b --- /dev/null +++ b/template-nuxt3-ts/vitest-setup.ts @@ -0,0 +1,6 @@ +// setupTests.ts +import '@testing-library/jest-dom/vitest' + +window.matchMedia = function () { + return { matches: false } +} diff --git a/template-nuxt3-ts/vitest.config.ts b/template-nuxt3-ts/vitest.config.ts new file mode 100644 index 0000000..9d70622 --- /dev/null +++ b/template-nuxt3-ts/vitest.config.ts @@ -0,0 +1,13 @@ +import { fileURLToPath } from 'node:url' +import { defineVitestConfig } from 'nuxt-vitest/config' + +export default defineVitestConfig({ + test: { + environment: 'happy-dom', + globals: true, + setupFiles: [ + fileURLToPath(new URL('./vitest-setup.ts', import.meta.url)), + ], + }, + // any custom vitest config you require +}) diff --git a/template-vue3-ts/.eslintrc-auto-import.json b/template-vue3-ts/.eslintrc-auto-import.json index 1e2170f..ee60c88 100644 --- a/template-vue3-ts/.eslintrc-auto-import.json +++ b/template-vue3-ts/.eslintrc-auto-import.json @@ -159,6 +159,10 @@ "watch": true, "watchEffect": true, "watchPostEffect": true, - "watchSyncEffect": true + "watchSyncEffect": true, + "ExtractDefaultPropTypes": true, + "ExtractPropTypes": true, + "ExtractPublicPropTypes": true, + "WritableComputedRef": true } } diff --git a/template-vue3-ts/.eslintrc.cjs b/template-vue3-ts/.eslintrc.cjs index 838a16a..3db7172 100644 --- a/template-vue3-ts/.eslintrc.cjs +++ b/template-vue3-ts/.eslintrc.cjs @@ -24,6 +24,7 @@ module.exports = { { files: [ 'cypress/e2e/*.{spec,e2e}.{js,ts,jsx,tsx}', + 'cypress/support/*.{js,ts,jsx,tsx}', 'src/**/*.{ct,cy}.{js,ts,jsx,tsx}', ], extends: [ diff --git a/template-vue3-ts/.vscode/extensions.json b/template-vue3-ts/.vscode/extensions.json index f2bcb8a..37286b7 100644 --- a/template-vue3-ts/.vscode/extensions.json +++ b/template-vue3-ts/.vscode/extensions.json @@ -7,19 +7,15 @@ "mhutchie.git-graph", "eamodio.gitlens", - // Node / npm - "christian-kohler.npm-intellisense", - // JavaScript "dbaeumer.vscode-eslint", // Vue.js "Vue.volar", "Vue.vscode-typescript-vue-plugin", - - // Vitejs - "antfu.vite", - "antfu.browse-lite", + + // VueDsfr + "stormier.vue-dsfr-snippets", // CSS "csstools.postcss", diff --git a/template-vue3-ts/.vscode/vue-dsfr.code-snippets b/template-vue3-ts/.vscode/vue-dsfr.code-snippets deleted file mode 100644 index 8801ac1..0000000 --- a/template-vue3-ts/.vscode/vue-dsfr.code-snippets +++ /dev/null @@ -1,821 +0,0 @@ -{ - "template": { - "scope": "vue", - "prefix": "template", - "body": [ - "" - ], - "description": "Create