├── .eslintrc.cjs ├── .gitignore ├── .prettierrc.json ├── .vscode └── extensions.json ├── README.md ├── index.html ├── package.json ├── public └── favicon.ico ├── src ├── App.test.js ├── App.vue ├── assets │ ├── base.css │ ├── logo.svg │ └── main.css ├── components │ ├── NotificationToast.vue │ ├── PostCard.vue │ └── __tests__ │ │ ├── NotificationToast.test.js │ │ ├── PostCard.test.js │ │ └── __snapshots__ │ │ ├── NotificationToast.test.js.snap │ │ └── PostCard.test.js.snap └── main.js ├── vite.config.js ├── vitest.config.js └── yarn.lock /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-prettier/skip-formatting' 10 | ], 11 | parserOptions: { 12 | ecmaVersion: 'latest' 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Quicktests with Vitest 2 | 3 | Look at the [Vitest documentation](https://vitest.dev/) to learn more 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # yarn 11 | yarn install 12 | 13 | # npm 14 | npm install 15 | ``` 16 | 17 | ### Run Unit Tests with [Vitest](https://vitest.dev/) 18 | 19 | ```sh 20 | yarn test:unit 21 | ``` -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quicktests with Vitest 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quicktest-with-vitest", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "test": "vitest", 10 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore", 11 | "format": "prettier --write src/" 12 | }, 13 | "dependencies": { 14 | "axios": "^1.4.0", 15 | "vue": "^3.2.47" 16 | }, 17 | "devDependencies": { 18 | "@rushstack/eslint-patch": "^1.2.0", 19 | "@vitejs/plugin-vue": "^4.0.0", 20 | "@vitest/coverage-v8": "^0.34.1", 21 | "@vitest/ui": "^0.34.1", 22 | "@vue/eslint-config-prettier": "^8.0.0", 23 | "@vue/test-utils": "^2.3.0", 24 | "eslint": "^8.34.0", 25 | "eslint-plugin-vue": "^9.9.0", 26 | "jsdom": "^22.1.0", 27 | "prettier": "^3.0.0", 28 | "vite": "^4.1.4", 29 | "vitest": "^0.34.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Code-Pop/quicktests-with-vitest/fe7095a8506467e533a15afe317ab6d94b6afbeb/public/favicon.ico -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import { mount, flushPromises } from '@vue/test-utils' 3 | import axios from 'axios' 4 | 5 | import App from './App.vue' 6 | 7 | const mockPost = { 8 | userId: 1, //this is necessary for the API call 9 | id: 1, 10 | title: 'Test Post', 11 | body: 'test body...' 12 | } 13 | 14 | describe('Posts App', () => { 15 | test('user can create a new post', async () => { 16 | vi.spyOn(axios, 'post').mockResolvedValueOnce({ data: mockPost }) 17 | 18 | const wrapper = mount(App) 19 | 20 | //fill in the input fields 21 | await wrapper.find('[data-testid="title-input"]').setValue(mockPost.title) 22 | await wrapper.find('[data-testid="body-input"]').setValue(mockPost.body) 23 | 24 | //submit the form 25 | await wrapper.find('[data-testid="post-form"]').trigger('submit') 26 | 27 | expect(wrapper.find('[type="submit"]').html()).toContain('Creating...') 28 | 29 | await flushPromises() 30 | 31 | // assert that the created post is displayed on screen 32 | expect(wrapper.html()).toContain(mockPost.title) 33 | expect(wrapper.html()).toContain(mockPost.body) 34 | }) 35 | 36 | // second group of tests 37 | describe('user gets notified', () => { 38 | test('when attempting to create a post with incomplete fields', async () => { 39 | const wrapper = mount(App) 40 | 41 | //try to submit the form with empty fields 42 | await wrapper.find('[data-testid="post-form"]').trigger('submit') 43 | 44 | expect(wrapper.html()).toContain('Please input post title') 45 | 46 | //click the close button 47 | await wrapper.find('[data-testid="close-notification"]').trigger('click') 48 | 49 | // assert that the error message is no longer on screen 50 | expect(wrapper.html()).not.toContain('Please input post title') 51 | 52 | await wrapper.find('[data-testid="title-input"]').setValue(mockPost.title) 53 | 54 | await wrapper.find('[data-testid="post-form"]').trigger('submit') 55 | 56 | //assert that a new error prompting user for post body is diplayed 57 | expect(wrapper.html()).toContain('Please input post body') 58 | }) 59 | 60 | test('when creating a new post fails', async () => { 61 | vi.spyOn(axios, 'post').mockRejectedValueOnce(new Error('Error occurred')) 62 | 63 | const wrapper = mount(App) 64 | 65 | await wrapper.find('[data-testid="title-input"]').setValue(mockPost.title) 66 | await wrapper.find('[data-testid="body-input"]').setValue(mockPost.body) 67 | 68 | await wrapper.find('[data-testid="post-form"]').trigger('submit') 69 | 70 | expect(wrapper.find('[type="submit"]').html()).toContain('Creating...') 71 | 72 | await flushPromises() 73 | 74 | expect(wrapper.html()).toContain('Error occurred') 75 | }) 76 | }) 77 | }) 78 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 |