├── data ├── auth.db3 ├── db-config.js ├── seeds │ ├── 01-users.js │ └── 00-cleanup.js └── migrations │ └── 20191217174228_bootstrap-db.js ├── index.js ├── .eslintrc.json ├── api ├── users │ ├── users-router.js │ └── users-model.js ├── auth │ ├── auth-middleware.js │ └── auth-router.js └── server.js ├── knexfile.js ├── package.json ├── .github └── lockdown.yml ├── .gitignore ├── README.md ├── codegrade_mvp.test.js └── jest.config.js /data/auth.db3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bloominstituteoftechnology/node-auth1-project/HEAD/data/auth.db3 -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const server = require('./api/server.js'); 2 | 3 | const PORT = process.env.PORT || 9000; 4 | 5 | server.listen(PORT, () => { 6 | console.log(`Listening on port ${PORT}...`); 7 | }); 8 | -------------------------------------------------------------------------------- /data/db-config.js: -------------------------------------------------------------------------------- 1 | // DO NOT CHANGE THIS FILE 2 | const knex = require('knex') 3 | const configs = require('../knexfile.js') 4 | const environment = process.env.NODE_ENV || 'development' 5 | 6 | module.exports = knex(configs[environment]) 7 | -------------------------------------------------------------------------------- /data/seeds/01-users.js: -------------------------------------------------------------------------------- 1 | // DO NOT CHANGE THIS FILE 2 | exports.seed = function (knex) { 3 | return knex('users').insert({ 4 | username: 'bob', 5 | password: '$2a$10$dFwWjD8hi8K2I9/Y65MWi.WU0qn9eAVaiBoRSShTvuJVGw8XpsCiq', // password "1234" 6 | }) 7 | }; 8 | -------------------------------------------------------------------------------- /data/seeds/00-cleanup.js: -------------------------------------------------------------------------------- 1 | // DO NOT CHANGE THIS FILE 2 | const cleaner = require('knex-cleaner'); 3 | 4 | exports.seed = function (knex) { 5 | return cleaner.clean(knex, { 6 | ignoreTables: ['knex_migrations', 'knex_migrations_lock'], // don't empty migration tables 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es2021": true, 5 | "node": true, 6 | "jest": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "parserOptions": { 10 | "ecmaVersion": "latest" 11 | }, 12 | "rules": { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /data/migrations/20191217174228_bootstrap-db.js: -------------------------------------------------------------------------------- 1 | exports.up = function (knex) { 2 | return knex.schema.createTable("users", users => { 3 | users.increments("user_id"); 4 | 5 | users 6 | .string("username", 128) 7 | .notNullable() 8 | .unique(); 9 | 10 | users.string("password", 128).notNullable(); 11 | }); 12 | }; 13 | 14 | exports.down = function (knex) { 15 | return knex.schema.dropTableIfExists("users"); 16 | }; 17 | -------------------------------------------------------------------------------- /api/users/users-router.js: -------------------------------------------------------------------------------- 1 | // Require the `restricted` middleware from `auth-middleware.js`. You will need it here! 2 | 3 | 4 | /** 5 | [GET] /api/users 6 | 7 | This endpoint is RESTRICTED: only authenticated clients 8 | should have access. 9 | 10 | response: 11 | status 200 12 | [ 13 | { 14 | "user_id": 1, 15 | "username": "bob" 16 | }, 17 | // etc 18 | ] 19 | 20 | response on non-authenticated: 21 | status 401 22 | { 23 | "message": "You shall not pass!" 24 | } 25 | */ 26 | 27 | 28 | // Don't forget to add the router to the `exports` object so it can be required in other modules 29 | -------------------------------------------------------------------------------- /api/users/users-model.js: -------------------------------------------------------------------------------- 1 | /** 2 | resolves to an ARRAY with all users, each user having { user_id, username } 3 | */ 4 | function find() { 5 | 6 | } 7 | 8 | /** 9 | resolves to an ARRAY with all users that match the filter condition 10 | */ 11 | function findBy(filter) { 12 | 13 | } 14 | 15 | /** 16 | resolves to the user { user_id, username } with the given user_id 17 | */ 18 | function findById(user_id) { 19 | 20 | } 21 | 22 | /** 23 | resolves to the newly inserted user { user_id, username } 24 | */ 25 | function add(user) { 26 | 27 | } 28 | 29 | // Don't forget to add these to the `exports` object so they can be required in other modules 30 | -------------------------------------------------------------------------------- /knexfile.js: -------------------------------------------------------------------------------- 1 | // DO NOT CHANGE THIS FILE 2 | const sharedConfig = { 3 | client: 'sqlite3', 4 | useNullAsDefault: true, 5 | migrations: { 6 | directory: './data/migrations', 7 | }, 8 | seeds: { 9 | directory: './data/seeds', 10 | }, 11 | // this enables foreign keys in SQLite 12 | pool: { 13 | afterCreate: (conn, done) => { 14 | conn.run('PRAGMA foreign_keys = ON', done) 15 | }, 16 | }, 17 | } 18 | 19 | module.exports = { 20 | development: { 21 | ...sharedConfig, 22 | connection: { filename: './data/auth.db3' }, 23 | }, 24 | testing: { 25 | ...sharedConfig, 26 | connection: { filename: './data/testing.db3' }, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /api/auth/auth-middleware.js: -------------------------------------------------------------------------------- 1 | /* 2 | If the user does not have a session saved in the server 3 | 4 | status 401 5 | { 6 | "message": "You shall not pass!" 7 | } 8 | */ 9 | function restricted() { 10 | 11 | } 12 | 13 | /* 14 | If the username in req.body already exists in the database 15 | 16 | status 422 17 | { 18 | "message": "Username taken" 19 | } 20 | */ 21 | function checkUsernameFree() { 22 | 23 | } 24 | 25 | /* 26 | If the username in req.body does NOT exist in the database 27 | 28 | status 401 29 | { 30 | "message": "Invalid credentials" 31 | } 32 | */ 33 | function checkUsernameExists() { 34 | 35 | } 36 | 37 | /* 38 | If password is missing from req.body, or if it's 3 chars or shorter 39 | 40 | status 422 41 | { 42 | "message": "Password must be longer than 3 chars" 43 | } 44 | */ 45 | function checkPasswordLength() { 46 | 47 | } 48 | 49 | // Don't forget to add these to the `exports` object so they can be required in other modules 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-auth1-project", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "server": "nodemon index.js", 7 | "test": "cross-env NODE_ENV=testing jest --verbose --runInBand", 8 | "migrate": "knex migrate:latest", 9 | "rollback": "knex migrate:rollback", 10 | "seed": "knex seed:run" 11 | }, 12 | "devDependencies": { 13 | "@types/jest": "^27.5.0", 14 | "cross-env": "^7.0.3", 15 | "eslint": "^8.15.0", 16 | "jest": "^28.1.0", 17 | "knex-cleaner": "^1.3.1", 18 | "nodemon": "^2.0.16", 19 | "set-cookie-parser": "^2.4.8", 20 | "supertest": "^6.2.3" 21 | }, 22 | "dependencies": { 23 | "bcryptjs": "^2.4.3", 24 | "cors": "^2.8.5", 25 | "express": "^4.18.1", 26 | "helmet": "^5.0.2", 27 | "knex": "^2.0.0", 28 | "sqlite3": "^5.0.8" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "git+https://github.com/bloominstituteoftechnology/node-auth1-project.git" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/lockdown.yml: -------------------------------------------------------------------------------- 1 | # PLEASE DO NOT REMOVE THIS FILE 2 | 3 | # Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown 4 | 5 | # Skip issues and pull requests created before a given timestamp. Timestamp must 6 | # follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable 7 | skipCreatedBefore: false 8 | 9 | # Issues and pull requests with these labels will be ignored. Set to `[]` to disable 10 | exemptLabels: [] 11 | 12 | # Comment to post before closing or locking. Set to `false` to disable 13 | comment: false 14 | 15 | # Label to add before closing or locking. Set to `false` to disable 16 | label: false 17 | 18 | # Close issues and pull requests 19 | close: true 20 | 21 | # Lock issues and pull requests 22 | lock: true 23 | 24 | # Limit to only `issues` or `pulls` 25 | only: pulls 26 | # Optionally, specify configuration settings just for `issues` or `pulls` 27 | # issues: 28 | # label: wontfix 29 | 30 | # pulls: 31 | # comment: > 32 | # This repository does not accept pull requests, see the README for details. 33 | # lock: false 34 | 35 | # Repository to extend settings from 36 | # _extends: repo 37 | -------------------------------------------------------------------------------- /api/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const helmet = require("helmet"); 3 | const cors = require("cors"); 4 | 5 | /** 6 | Do what needs to be done to support sessions with the `express-session` package! 7 | To respect users' privacy, do NOT send them a cookie unless they log in. 8 | This is achieved by setting 'saveUninitialized' to false, and by not 9 | changing the `req.session` object unless the user authenticates. 10 | 11 | Users that do authenticate should have a session persisted on the server, 12 | and a cookie set on the client. The name of the cookie should be "chocolatechip". 13 | 14 | The session can be persisted in memory (would not be adecuate for production) 15 | or you can use a session store like `connect-session-knex`. 16 | */ 17 | 18 | const server = express(); 19 | 20 | server.use(helmet()); 21 | server.use(express.json()); 22 | server.use(cors()); 23 | 24 | server.get("/", (req, res) => { 25 | res.json({ api: "up" }); 26 | }); 27 | 28 | server.use((err, req, res, next) => { // eslint-disable-line 29 | res.status(err.status || 500).json({ 30 | message: err.message, 31 | stack: err.stack, 32 | }); 33 | }); 34 | 35 | module.exports = server; 36 | -------------------------------------------------------------------------------- /api/auth/auth-router.js: -------------------------------------------------------------------------------- 1 | // Require `checkUsernameFree`, `checkUsernameExists` and `checkPasswordLength` 2 | // middleware functions from `auth-middleware.js`. You will need them here! 3 | 4 | 5 | /** 6 | 1 [POST] /api/auth/register { "username": "sue", "password": "1234" } 7 | 8 | response: 9 | status 200 10 | { 11 | "user_id": 2, 12 | "username": "sue" 13 | } 14 | 15 | response on username taken: 16 | status 422 17 | { 18 | "message": "Username taken" 19 | } 20 | 21 | response on password three chars or less: 22 | status 422 23 | { 24 | "message": "Password must be longer than 3 chars" 25 | } 26 | */ 27 | 28 | 29 | /** 30 | 2 [POST] /api/auth/login { "username": "sue", "password": "1234" } 31 | 32 | response: 33 | status 200 34 | { 35 | "message": "Welcome sue!" 36 | } 37 | 38 | response on invalid credentials: 39 | status 401 40 | { 41 | "message": "Invalid credentials" 42 | } 43 | */ 44 | 45 | 46 | /** 47 | 3 [GET] /api/auth/logout 48 | 49 | response for logged-in users: 50 | status 200 51 | { 52 | "message": "logged out" 53 | } 54 | 55 | response for not-logged-in users: 56 | status 200 57 | { 58 | "message": "no session" 59 | } 60 | */ 61 | 62 | 63 | // Don't forget to add the router to the `exports` object so it can be required in other modules 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | 118 | # Mac files 119 | .DS_Store 120 | 121 | # VSCode settings 122 | .vscode/ 123 | 124 | # testing db 125 | testing.db3 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction to Authentication Module Project 2 | 3 | ## Introduction 4 | 5 | Use `Node.js`, `Express` and `Knex` to build an API that provides register, login and logout functionality. 6 | 7 | ## Instructions 8 | 9 | ### Task 1: Project Setup and Submission 10 | 11 | Your assignment page on Canvas should contain instructions for submitting this project. If you are still unsure, reach out to School Staff. 12 | 13 | ### Task 2: Minimum Viable Product 14 | 15 | #### 2A - Database Access Functions 16 | 17 | Write the following user access functions inside `api/users/users-model.js`: 18 | 19 | - [ ] `find` 20 | - [ ] `findBy` 21 | - [ ] `findById` 22 | - [ ] `add` 23 | 24 | #### 2B - Middleware Functions 25 | 26 | Write the following auth middlewares inside `api/auth/auth-middleware.js`: 27 | 28 | - [ ] `restricted` 29 | - [ ] `checkUsernameFree` 30 | - [ ] `checkPasswordLength` 31 | - [ ] `checkUsernameExists` 32 | 33 | #### 2C - Endpoints 34 | 35 | Authentication will be tracked using sessions and cookies. See `api/server.js` for more instructions. 36 | 37 | Write the following endpoints. The first one belongs inside `api/users/users-router.js` and the rest inside `api/auth/auth-router.js`: 38 | 39 | - [ ] `[GET] /api/users` 40 | - [ ] `[POST] /api/auth/register` 41 | - [ ] `[POST] /api/auth/login` 42 | - [ ] `[GET] /api/auth/logout` 43 | 44 | #### Users Schema 45 | 46 | The database `auth.db3` includes a single `users` table: 47 | 48 | | field | data type | metadata | 49 | | :------- | :--------------- | :-------------------------------------------- | 50 | | user_id | unsigned integer | primary key, auto-increments, generated by db | 51 | | username | string | required, unique | 52 | | password | string | required | 53 | 54 | #### Notes 55 | 56 | - Run tests locally executing `npm test`. 57 | - The project comes with `migrate`, `rollback` and `seed` scripts in case you need to reset the database. 58 | - You are welcome to create additional files but **do not move or rename existing files** or folders. 59 | - Do not alter your `package.json` file except to install extra libraries or add extra scripts. Do not update existing libraries. 60 | - In your solution, it is essential that you follow best practices and produce clean and professional results. 61 | - Schedule time to review, refine, and assess your work. 62 | - Perform basic professional polishing including spell-checking and grammar-checking on your work. 63 | 64 | ### Task 3: Stretch Goals 65 | 66 | - Build a React application that implements components to register, login and view a list of users. Gotta keep sharpening your React skills. 67 | -------------------------------------------------------------------------------- /codegrade_mvp.test.js: -------------------------------------------------------------------------------- 1 | const request = require('supertest') 2 | const server = require('./api/server') 3 | const db = require('./data/db-config') 4 | const setCookie = require('set-cookie-parser') 5 | const bcrypt = require('bcryptjs') 6 | 7 | beforeAll(async () => { 8 | await db.migrate.rollback() 9 | await db.migrate.latest() 10 | }) 11 | beforeEach(async () => { 12 | await db.seed.run() 13 | }) 14 | afterAll(async () => { 15 | await db.destroy() 16 | }) 17 | 18 | it('[0] sanity check', () => { 19 | expect(true).not.toBe(false) 20 | }) 21 | 22 | describe('server.js', () => { 23 | describe('[POST] /api/auth/login', () => { 24 | it('[1] responds with the correct message on valid credentials', async () => { 25 | const res = await request(server).post('/api/auth/login').send({ username: 'bob', password: '1234' }) 26 | expect(res.body.message).toMatch(/welcome bob/i) 27 | }, 750) 28 | it('[2] a "chocolatechip" cookie gets set on the client on valid credentials', async () => { 29 | const res = await request(server).post('/api/auth/login').send({ username: 'bob', password: '1234' }) 30 | const cookies = setCookie.parse(res, { map: true }) 31 | expect(cookies.chocolatechip).toMatchObject({ name: 'chocolatechip' }) 32 | }, 750) 33 | it('[3] no cookie gets set on invalid credentials (saveUninitialized=false)', async () => { 34 | const res = await request(server).post('/api/auth/login').send({ username: 'bobsy', password: 'lady gaga' }) 35 | const cookies = setCookie.parse(res, { map: true }) 36 | expect(cookies).toEqual({}) // no SET-COOKIE 37 | }, 750) 38 | it('[4] responds with the correct message on invalid credentials', async () => { 39 | let res = await request(server).post('/api/auth/login').send({ username: 'bobsy', password: '1234' }) 40 | expect(res.body.message).toMatch(/invalid credentials/i) 41 | res = await request(server).post('/api/auth/login').send({ username: 'bob', password: '12345' }) 42 | expect(res.body.message).toMatch(/invalid credentials/i) 43 | }, 750) 44 | }) 45 | describe('[POST] /api/auth/register', () => { 46 | it('[5] creates a new user in the database', async () => { 47 | await request(server).post('/api/auth/register').send({ username: 'sue', password: '1234' }) 48 | const sue = await db('users').where('username', 'sue').first() 49 | expect(sue).toMatchObject({ username: 'sue' }) 50 | }, 750) 51 | it('[6] new user passwords are saved correctly bcrypted', async () => { 52 | await request(server).post('/api/auth/register').send({ username: 'sue', password: '1234' }) 53 | const sue = await db('users').where('username', 'sue').first() 54 | expect(bcrypt.compareSync('1234', sue.password)).toBeTruthy() 55 | }, 750) 56 | it('[7] no cookie gets set by registering (saveUninitialized=false)', async () => { 57 | const res = await request(server).post('/api/auth/register').send({ username: 'sue', password: '1234' }) 58 | const cookies = setCookie.parse(res, { map: true }) 59 | expect(cookies).toEqual({}) // no SET-COOKIE 60 | }, 750) 61 | it('[8] responds with the user (user_id and username)', async () => { 62 | const res = await request(server).post('/api/auth/register').send({ username: 'sue', password: '1234' }) 63 | expect(res.body).toMatchObject({ user_id: 2, username: 'sue' }) 64 | }, 750) 65 | it('[9] responds with the proper status code and message on "username taken"', async () => { 66 | const res = await request(server).post('/api/auth/register').send({ username: 'bob', password: '1234' }) 67 | expect(res.status).toBe(422) 68 | expect(res.body.message).toMatch(/username taken/i) 69 | }, 750) 70 | it('[10] responds with the proper status code and message on too short a password', async () => { 71 | let res = await request(server).post('/api/auth/register').send({ username: 'sue' }) 72 | expect(res.status).toBe(422) 73 | expect(res.body.message).toMatch(/ must be longer than 3/i) 74 | res = await request(server).post('/api/auth/register').send({ username: 'sue', password: '1' }) 75 | expect(res.status).toBe(422) 76 | expect(res.body.message).toMatch(/ must be longer than 3/i) 77 | }, 750) 78 | }) 79 | describe('[GET] /api/auth/logout', () => { 80 | it('[11] if there is a session it is destroyed so "chocolatechip" cookie not effective anymore', async () => { 81 | let res = await request(server).post('/api/auth/login').send({ username: 'bob', password: '1234' }) 82 | const { chocolatechip } = setCookie.parse(res, { map: true }) 83 | res = await request(server).get('/api/auth/logout') 84 | .set('Cookie', `${chocolatechip.name}=${chocolatechip.value}`) 85 | expect(res.body.message).toMatch(/logged out/i) 86 | res = await request(server).get('/api/users') 87 | .set('Cookie', `${chocolatechip.name}=${chocolatechip.value}`) 88 | expect(res.body.message).toMatch(/you shall not pass/i) 89 | }, 750) 90 | it('[12] responds with the proper message if the user was not actually logged in', async () => { 91 | let res = await request(server).get('/api/auth/logout') 92 | expect(res.body.message).toMatch(/no session/i) 93 | }, 750) 94 | }) 95 | describe('[GET] /api/users', () => { 96 | it('[13] responds with the proper status code and message on not-logged-in user', async () => { 97 | const res = await request(server).get('/api/users') 98 | expect(res.status).toBe(401) 99 | expect(res.body.message).toMatch(/you shall not pass/i) 100 | }, 750) 101 | it('[14] responds with the users if there is a session matching the "chocolatechip" cookie', async () => { 102 | let res = await request(server).post('/api/auth/login').send({ username: 'bob', password: '1234' }) 103 | const { chocolatechip } = setCookie.parse(res, { map: true }) 104 | res = await request(server).get('/api/users') 105 | .set('Cookie', `${chocolatechip.name}=${chocolatechip.value}`) 106 | expect(res.body).toMatchObject([{ user_id: 1, username: 'bob' }]) 107 | }, 750) 108 | }) 109 | }) 110 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | 6 | module.exports = { 7 | // All imported modules in your tests should be mocked automatically 8 | // automock: false, 9 | 10 | // Stop running tests after `n` failures 11 | // bail: 0, 12 | 13 | // The directory where Jest should store its cached dependency information 14 | // cacheDirectory: "/private/var/folders/mq/wc13nlwj4gdgcyshdy5j1hgr0000gn/T/jest_dx", 15 | 16 | // Automatically clear mock calls, instances, contexts and results before every test 17 | // clearMocks: false, 18 | 19 | // Indicates whether the coverage information should be collected while executing the test 20 | // collectCoverage: false, 21 | 22 | // An array of glob patterns indicating a set of files for which coverage information should be collected 23 | // collectCoverageFrom: undefined, 24 | 25 | // The directory where Jest should output its coverage files 26 | // coverageDirectory: undefined, 27 | 28 | // An array of regexp pattern strings used to skip coverage collection 29 | // coveragePathIgnorePatterns: [ 30 | // "/node_modules/" 31 | // ], 32 | 33 | // Indicates which provider should be used to instrument code for coverage 34 | coverageProvider: "v8", 35 | 36 | // A list of reporter names that Jest uses when writing coverage reports 37 | // coverageReporters: [ 38 | // "json", 39 | // "text", 40 | // "lcov", 41 | // "clover" 42 | // ], 43 | 44 | // An object that configures minimum threshold enforcement for coverage results 45 | // coverageThreshold: undefined, 46 | 47 | // A path to a custom dependency extractor 48 | // dependencyExtractor: undefined, 49 | 50 | // Make calling deprecated APIs throw helpful error messages 51 | // errorOnDeprecated: false, 52 | 53 | // The default configuration for fake timers 54 | // fakeTimers: { 55 | // "enableGlobally": false 56 | // }, 57 | 58 | // Force coverage collection from ignored files using an array of glob patterns 59 | // forceCoverageMatch: [], 60 | 61 | // A path to a module which exports an async function that is triggered once before all test suites 62 | // globalSetup: undefined, 63 | 64 | // A path to a module which exports an async function that is triggered once after all test suites 65 | // globalTeardown: undefined, 66 | 67 | // A set of global variables that need to be available in all test environments 68 | // globals: {}, 69 | 70 | // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. 71 | // maxWorkers: "50%", 72 | 73 | // An array of directory names to be searched recursively up from the requiring module's location 74 | // moduleDirectories: [ 75 | // "node_modules" 76 | // ], 77 | 78 | // An array of file extensions your modules use 79 | // moduleFileExtensions: [ 80 | // "js", 81 | // "mjs", 82 | // "cjs", 83 | // "jsx", 84 | // "ts", 85 | // "tsx", 86 | // "json", 87 | // "node" 88 | // ], 89 | 90 | // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module 91 | // moduleNameMapper: {}, 92 | 93 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 94 | // modulePathIgnorePatterns: [], 95 | 96 | // Activates notifications for test results 97 | // notify: false, 98 | 99 | // An enum that specifies notification mode. Requires { notify: true } 100 | // notifyMode: "failure-change", 101 | 102 | // A preset that is used as a base for Jest's configuration 103 | // preset: undefined, 104 | 105 | // Run tests from one or more projects 106 | // projects: undefined, 107 | 108 | // Use this configuration option to add custom reporters to Jest 109 | // reporters: undefined, 110 | 111 | // Automatically reset mock state before every test 112 | // resetMocks: false, 113 | 114 | // Reset the module registry before running each individual test 115 | // resetModules: false, 116 | 117 | // A path to a custom resolver 118 | // resolver: undefined, 119 | 120 | // Automatically restore mock state and implementation before every test 121 | // restoreMocks: false, 122 | 123 | // The root directory that Jest should scan for tests and modules within 124 | // rootDir: undefined, 125 | 126 | // A list of paths to directories that Jest should use to search for files in 127 | // roots: [ 128 | // "" 129 | // ], 130 | 131 | // Allows you to use a custom runner instead of Jest's default test runner 132 | // runner: "jest-runner", 133 | 134 | // The paths to modules that run some code to configure or set up the testing environment before each test 135 | // setupFiles: [], 136 | 137 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 138 | // setupFilesAfterEnv: [], 139 | 140 | // The number of seconds after which a test is considered as slow and reported as such in the results. 141 | // slowTestThreshold: 5, 142 | 143 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 144 | // snapshotSerializers: [], 145 | 146 | // The test environment that will be used for testing 147 | // testEnvironment: "jest-environment-node", 148 | 149 | // Options that will be passed to the testEnvironment 150 | // testEnvironmentOptions: {}, 151 | 152 | // Adds a location field to test results 153 | // testLocationInResults: false, 154 | 155 | // The glob patterns Jest uses to detect test files 156 | // testMatch: [ 157 | // "**/__tests__/**/*.[jt]s?(x)", 158 | // "**/?(*.)+(spec|test).[tj]s?(x)" 159 | // ], 160 | 161 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 162 | // testPathIgnorePatterns: [ 163 | // "/node_modules/" 164 | // ], 165 | 166 | // The regexp pattern or array of patterns that Jest uses to detect test files 167 | // testRegex: [], 168 | 169 | // This option allows the use of a custom results processor 170 | // testResultsProcessor: undefined, 171 | 172 | // This option allows use of a custom test runner 173 | // testRunner: "jest-circus/runner", 174 | 175 | // A map from regular expressions to paths to transformers 176 | // transform: undefined, 177 | 178 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 179 | // transformIgnorePatterns: [ 180 | // "/node_modules/", 181 | // "\\.pnp\\.[^\\/]+$" 182 | // ], 183 | 184 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 185 | // unmockedModulePathPatterns: undefined, 186 | 187 | // Indicates whether each individual test should be reported during the run 188 | // verbose: undefined, 189 | 190 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 191 | // watchPathIgnorePatterns: [], 192 | 193 | // Whether to use watchman for file crawling 194 | // watchman: true, 195 | }; 196 | --------------------------------------------------------------------------------