├── __tests__
├── lib
│ ├── mocks
│ │ ├── .hoge
│ │ ├── search
│ │ │ ├── empty.ts
│ │ │ └── _userName@string.ts
│ │ ├── collections
│ │ │ ├── .sample
│ │ │ └── entries.json.ts
│ │ ├── @utils
│ │ │ └── index.ts
│ │ ├── @types.ts
│ │ ├── index.ts
│ │ ├── users
│ │ │ ├── self.ts
│ │ │ ├── _userId.ts
│ │ │ └── index.ts
│ │ ├── $mock.js
│ │ └── $mock.ts
│ └── index.spec.ts
├── units.spec.ts
└── index.spec.ts
├── .vscode
├── extensions.json
└── settings.json
├── bin
└── index.js
├── tsconfig.build.json
├── examples
├── node
│ ├── nodemon.json
│ ├── src
│ │ └── index.js
│ ├── mocks
│ │ └── users
│ │ │ └── _userId.js
│ ├── README.md
│ └── package.json
├── with-nuxtjs
│ ├── plugins
│ │ └── mock.js
│ ├── nuxt.config.js
│ ├── mocks
│ │ └── users
│ │ │ └── _userId.js
│ ├── pages
│ │ └── index.vue
│ ├── jsconfig.json
│ ├── README.md
│ └── package.json
├── with-typescript
│ ├── nodemon.json
│ ├── tsconfig.json
│ ├── src
│ │ └── index.ts
│ ├── mocks
│ │ └── users
│ │ │ └── _userId.ts
│ ├── README.md
│ └── package.json
└── browser
│ ├── public
│ └── index.html
│ ├── mocks
│ └── users
│ │ └── _userId.js
│ ├── webpack.config.js
│ ├── src
│ └── index.js
│ ├── README.md
│ └── package.json
├── devConfigs
├── .js.rc
└── .ts.rc
├── src
├── settle.d.ts
├── lib
│ ├── getInputs.ts
│ ├── watchInputDir.ts
│ ├── writeRouteFile.ts
│ ├── listFiles.ts
│ ├── getConfig.ts
│ ├── cli.ts
│ ├── buildRouteFile.ts
│ └── createRouteString.ts
├── asyncResponse.ts
├── findHandler.ts
├── createRelativePath.ts
├── untransformData.ts
├── compositeParams.ts
├── createValues.ts
├── createLogString.ts
├── index.ts
├── makeResponse.ts
├── types.ts
├── findAndCallHandler.ts
└── MockServer.ts
├── .editorconfig
├── jest.config.js
├── .versionrc.json
├── .github
├── pull_request_template.md
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── dependabot.yml
└── workflows
│ └── nodejs.yml
├── tsconfig.json
├── LICENSE
├── .gitignore
├── package.json
├── CHANGELOG.md
├── docs
└── ja
│ └── README.md
└── README.md
/__tests__/lib/mocks/.hoge:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/search/empty.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/collections/.sample:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/@utils/index.ts:
--------------------------------------------------------------------------------
1 | export const testFn = () => 'Hello!'
2 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/@types.ts:
--------------------------------------------------------------------------------
1 | export interface Sample {
2 | id: number
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["dbaeumer.vscode-eslint"]
3 | }
4 |
--------------------------------------------------------------------------------
/bin/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | require('../dist/lib/cli').run(process.argv.slice(2))
3 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src/**/*"]
4 | }
5 |
--------------------------------------------------------------------------------
/examples/node/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "exec": "node src/index.js",
3 | "watch": ["src", "mocks"]
4 | }
5 |
--------------------------------------------------------------------------------
/devConfigs/.js.rc:
--------------------------------------------------------------------------------
1 | {
2 | "input": "__tests__/lib/mocks",
3 | "target": "cjs",
4 | "outputExt": "js"
5 | }
6 |
--------------------------------------------------------------------------------
/devConfigs/.ts.rc:
--------------------------------------------------------------------------------
1 | {
2 | "input": "__tests__/lib/mocks",
3 | "target": "es6",
4 | "outputExt": "ts"
5 | }
6 |
--------------------------------------------------------------------------------
/examples/with-nuxtjs/plugins/mock.js:
--------------------------------------------------------------------------------
1 | import mock from '~/mocks/$mock.js'
2 |
3 | export default ({ $axios }) => {
4 | mock($axios)
5 | }
6 |
--------------------------------------------------------------------------------
/examples/with-typescript/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "exec": "tsc && node dist/src/index.js",
3 | "ext": "ts",
4 | "watch": ["src", "mocks"]
5 | }
6 |
--------------------------------------------------------------------------------
/examples/with-nuxtjs/nuxt.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | mode: 'spa',
3 | modules: ['@nuxtjs/axios'],
4 | plugins: ['~/plugins/mock.js']
5 | }
6 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/index.ts:
--------------------------------------------------------------------------------
1 | import { MockMethods } from '~/src/types'
2 |
3 | export default {
4 | get: () => [200, 'Hello world!']
5 | } as MockMethods
6 |
--------------------------------------------------------------------------------
/examples/browser/public/index.html:
--------------------------------------------------------------------------------
1 |
Examples - axios-mock-server
2 | browser
3 | request
4 |
5 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/users/self.ts:
--------------------------------------------------------------------------------
1 | import { MockMethods } from '~/src/types'
2 | import { users } from './index'
3 |
4 | export default { get: () => [200, users[0]] } as MockMethods
5 |
--------------------------------------------------------------------------------
/src/settle.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'axios/lib/core/settle' {
2 | const settle: (resolve: (res: any) => void, reject: (reason: any) => void, res: any) => void
3 | export = settle
4 | }
5 |
--------------------------------------------------------------------------------
/examples/with-typescript/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "outDir": "dist",
5 | "strict": true,
6 | "target": "esnext"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/getInputs.ts:
--------------------------------------------------------------------------------
1 | import { defaultConfig } from './getConfig'
2 |
3 | export default (input?: string | string[]) =>
4 | Array.isArray(input) ? input : [input || defaultConfig.input]
5 |
--------------------------------------------------------------------------------
/examples/node/src/index.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios')
2 | require('../mocks/$mock')()
3 |
4 | axios.get('https://example.com/users/0').then(({ data }) => {
5 | console.log(data)
6 | })
7 |
--------------------------------------------------------------------------------
/examples/node/mocks/users/_userId.js:
--------------------------------------------------------------------------------
1 | const users = [{ id: 0, name: 'foo' }]
2 |
3 | module.exports = {
4 | get({ values }) {
5 | return [200, users.find(user => user.id === values.userId)]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/browser/mocks/users/_userId.js:
--------------------------------------------------------------------------------
1 | const users = [{ id: 0, name: 'foo' }]
2 |
3 | export default {
4 | get({ values }) {
5 | return [200, users.find(user => user.id === values.userId)]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/with-nuxtjs/mocks/users/_userId.js:
--------------------------------------------------------------------------------
1 | const users = [{ id: 0, name: 'foo' }]
2 |
3 | export default {
4 | get({ values }) {
5 | return [200, users.find(user => user.id === values.userId)]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/with-nuxtjs/pages/index.vue:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.run": "onSave",
3 | "editor.codeActionsOnSave": {
4 | "source.fixAll.eslint": true
5 | },
6 | "files.associations": {
7 | ".mockserverrc": "json"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/asyncResponse.ts:
--------------------------------------------------------------------------------
1 | import { MockResponse } from './types'
2 |
3 | export default async (
4 | status: number,
5 | query: Promise,
6 | headers?: any
7 | ): Promise => [status, await query, headers]
8 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/users/_userId.ts:
--------------------------------------------------------------------------------
1 | import { MockMethods } from '~/src/types'
2 | import { users } from './index'
3 |
4 | export default {
5 | get: ({ values }) => [200, users.filter(user => user.id === values.userId)[0]]
6 | } as MockMethods
7 |
--------------------------------------------------------------------------------
/examples/browser/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | devServer: {
5 | contentBase: path.resolve(__dirname, 'public'),
6 | hot: true,
7 | port: 3000,
8 | watchContentBase: true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/search/_userName@string.ts:
--------------------------------------------------------------------------------
1 | import { MockMethods } from '~/src/types'
2 | import { users } from '../users/index'
3 |
4 | export default {
5 | get: ({ values }) => [200, users.filter(user => user.name === values.userName)[0]]
6 | } as MockMethods
7 |
--------------------------------------------------------------------------------
/examples/with-typescript/src/index.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | // @ts-ignore: Cannot find module
4 | import mock from '../mocks/$mock'
5 |
6 | mock()
7 |
8 | axios.get('https://example.com/users/0').then(({ data }) => {
9 | console.log(data)
10 | })
11 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/collections/entries.json.ts:
--------------------------------------------------------------------------------
1 | import { MockMethods } from '~/src/types'
2 |
3 | export const entries = [
4 | { id: 0, title: 'aaa' },
5 | { id: 1, title: 'bbb' }
6 | ]
7 |
8 | export default {
9 | get: () => [200, entries]
10 | } as MockMethods
11 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/src/lib/watchInputDir.ts:
--------------------------------------------------------------------------------
1 | import chokidar from 'chokidar'
2 | import { mockFileRegExp } from './getConfig'
3 |
4 | export default (input: string, callback: (...args: any) => void) => {
5 | chokidar.watch(input, { ignoreInitial: true, ignored: mockFileRegExp }).on('all', callback)
6 | }
7 |
--------------------------------------------------------------------------------
/examples/with-nuxtjs/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "~/*": ["./*"],
6 | "@/*": ["./*"],
7 | "~~/*": ["./*"],
8 | "@@/*": ["./*"]
9 | }
10 | },
11 | "exclude": ["node_modules", ".nuxt", "dist"]
12 | }
13 |
--------------------------------------------------------------------------------
/src/findHandler.ts:
--------------------------------------------------------------------------------
1 | import { HandlersSet, HttpMethod } from './types'
2 |
3 | export default (method = '', relativePath: string, handlersSet: HandlersSet) => {
4 | const handlers = handlersSet[method.toLowerCase() as HttpMethod]
5 |
6 | if (handlers) return handlers.find(([regPath]) => regPath.test(relativePath))
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/writeRouteFile.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 |
3 | export default ({ filePath, text }: { filePath: string; text: string }) => {
4 | if (fs.existsSync(filePath) && fs.readFileSync(filePath, 'utf8') === text) return
5 |
6 | fs.writeFileSync(filePath, text, 'utf8')
7 | console.log(`${filePath} was built successfully.`)
8 | }
9 |
--------------------------------------------------------------------------------
/examples/with-typescript/mocks/users/_userId.ts:
--------------------------------------------------------------------------------
1 | import { MockMethods } from 'axios-mock-server'
2 |
3 | const users = [{ id: 0, name: 'foo' }]
4 |
5 | const mockMethods: MockMethods = {
6 | get({ values }) {
7 | return [200, users.find(user => user.id === values.userId)]
8 | }
9 | }
10 |
11 | export default mockMethods
12 |
--------------------------------------------------------------------------------
/examples/browser/src/index.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import mock from '../mocks/$mock'
3 |
4 | mock()
5 |
6 | const button = document.querySelector('button')
7 |
8 | button.addEventListener('click', async () => {
9 | const { data } = await axios.get('https://example.com/users/0')
10 | alert(JSON.stringify(data))
11 | })
12 |
--------------------------------------------------------------------------------
/src/lib/listFiles.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import path from 'path'
3 |
4 | export const listFiles = (targetDir: string): string[] =>
5 | fs.readdirSync(targetDir, { withFileTypes: true }).flatMap(dirent => {
6 | const target = path.posix.join(targetDir, dirent.name)
7 | return dirent.isFile() ? [target] : listFiles(target)
8 | })
9 |
--------------------------------------------------------------------------------
/src/createRelativePath.ts:
--------------------------------------------------------------------------------
1 | const regOriginURL = /^(https?:)?\/\/[^/]+/
2 |
3 | export default (url = '', baseURL?: string) =>
4 | `/${url
5 | .replace(
6 | baseURL && url.startsWith(baseURL) ? baseURL : regOriginURL.test(url) ? regOriginURL : '',
7 | ''
8 | )
9 | .replace(/^\//, '')
10 | .replace(/\/$/, '')}`
11 |
--------------------------------------------------------------------------------
/examples/node/README.md:
--------------------------------------------------------------------------------
1 | # Node.js
2 |
3 | ## How to use
4 |
5 | Download the example:
6 |
7 | ```sh
8 | $ curl https://codeload.github.com/solufa/axios-mock-server/tar.gz/develop | tar -xzo --no-same-permissions --strip=2 axios-mock-server-develop/examples/node
9 | $ cd node
10 | ```
11 |
12 | Install it and start development:
13 |
14 | ```sh
15 | $ npm install
16 | $ npm run dev
17 | ```
18 |
--------------------------------------------------------------------------------
/examples/browser/README.md:
--------------------------------------------------------------------------------
1 | # Browser
2 |
3 | ## How to use
4 |
5 | Download the example:
6 |
7 | ```sh
8 | $ curl https://codeload.github.com/solufa/axios-mock-server/tar.gz/develop | tar -xzo --no-same-permissions --strip=2 axios-mock-server-develop/examples/browser
9 | $ cd browser
10 | ```
11 |
12 | Install it and start development:
13 |
14 | ```sh
15 | $ npm install
16 | $ npm run dev
17 | ```
18 |
--------------------------------------------------------------------------------
/src/untransformData.ts:
--------------------------------------------------------------------------------
1 | export default (data: any, headers: any) => {
2 | const contentType: string | undefined = headers['Content-Type'] || headers['content-type']
3 |
4 | if (contentType) {
5 | if (/^application\/json/.test(contentType)) return JSON.parse(data)
6 | if (/^application\/x-www-form-urlencoded/.test(contentType)) return new URLSearchParams(data)
7 | }
8 |
9 | return data
10 | }
11 |
--------------------------------------------------------------------------------
/examples/with-nuxtjs/README.md:
--------------------------------------------------------------------------------
1 | # With Nuxt.js
2 |
3 | ## How to use
4 |
5 | Download the example:
6 |
7 | ```sh
8 | $ curl https://codeload.github.com/solufa/axios-mock-server/tar.gz/develop | tar -xzo --no-same-permissions --strip=2 axios-mock-server-develop/examples/with-nuxtjs
9 | $ cd with-nuxtjs
10 | ```
11 |
12 | Install it and start development:
13 |
14 | ```sh
15 | $ npm install
16 | $ npm run dev
17 | ```
18 |
--------------------------------------------------------------------------------
/examples/with-typescript/README.md:
--------------------------------------------------------------------------------
1 | # With TypeScript
2 |
3 | ## How to use
4 |
5 | Download the example:
6 |
7 | ```sh
8 | $ curl https://codeload.github.com/solufa/axios-mock-server/tar.gz/develop | tar -xzo --no-same-permissions --strip=2 axios-mock-server-develop/examples/with-typescript
9 | $ cd with-typescript
10 | ```
11 |
12 | Install it and start development:
13 |
14 | ```sh
15 | $ npm install
16 | $ npm run dev
17 | ```
18 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/users/index.ts:
--------------------------------------------------------------------------------
1 | import { MockMethods } from '~/src/types'
2 |
3 | export const users = [
4 | { id: 0, name: 'aaa' },
5 | { id: 1, name: '123' }
6 | ]
7 |
8 | export default {
9 | get: () => [200, users],
10 | post: ({ data }) => {
11 | const user = {
12 | id: users.length,
13 | name: data.name
14 | }
15 |
16 | users.push(user)
17 |
18 | return [201, user]
19 | }
20 | } as MockMethods
21 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | const { pathsToModuleNameMapper } = require('ts-jest/utils')
2 | const { compilerOptions } = require('./tsconfig')
3 |
4 | module.exports = {
5 | preset: 'ts-jest',
6 | testEnvironment: 'node',
7 | watchPathIgnorePatterns: ['/examples/'],
8 | testPathIgnorePatterns: ['/__tests__/lib/mocks/'],
9 | moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
10 | prefix: '/'
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/src/compositeParams.ts:
--------------------------------------------------------------------------------
1 | export default (
2 | query: string | undefined,
3 | configParams: { [key: string]: any }
4 | ): { [key: string]: any } => {
5 | const searchParams = new URLSearchParams(query)
6 | const searchObject = [...searchParams].reduce(
7 | (prev, current) => ({
8 | ...prev,
9 | [current[0]]: isNaN(+current[1]) ? current[1] : +current[1]
10 | }),
11 | {}
12 | )
13 |
14 | return {
15 | ...searchObject,
16 | ...configParams
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node",
3 | "private": true,
4 | "scripts": {
5 | "dev": "npm-run-all mock:build --parallel watch mock:watch",
6 | "watch": "nodemon",
7 | "mock:build": "axios-mock-server --build",
8 | "mock:watch": "axios-mock-server --watch"
9 | },
10 | "dependencies": {
11 | "axios": "^0.19.0"
12 | },
13 | "devDependencies": {
14 | "axios-mock-server": "latest",
15 | "nodemon": "^1.19.2",
16 | "npm-run-all": "^4.1.5"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/with-nuxtjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-nuxtjs",
3 | "private": true,
4 | "scripts": {
5 | "dev": "npm-run-all mock:build --parallel nuxt mock:watch",
6 | "nuxt": "nuxt",
7 | "mock:build": "axios-mock-server --build",
8 | "mock:watch": "axios-mock-server --watch"
9 | },
10 | "dependencies": {
11 | "nuxt": "^2.9.2",
12 | "@nuxtjs/axios": "^5.6.0"
13 | },
14 | "devDependencies": {
15 | "axios-mock-server": "latest",
16 | "npm-run-all": "^4.1.5"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/createValues.ts:
--------------------------------------------------------------------------------
1 | export default (path: string, relativePath: string) => {
2 | const values: { [key: string]: string | number } = {}
3 | const dirList = path.split('/')
4 | const parsedRequestUrl = relativePath.split('/')
5 |
6 | parsedRequestUrl.forEach((dir, i) => {
7 | if (dirList[i].startsWith('_')) {
8 | const [valueName, type = 'number'] = dirList[i].slice(1).split('@')
9 | values[valueName] = isNaN(+dir) || type !== 'number' ? dir : +dir
10 | }
11 | })
12 |
13 | return values
14 | }
15 |
--------------------------------------------------------------------------------
/.versionrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "types": [
3 | { "type": "build", "hidden": true },
4 | { "type": "chore", "hidden": true },
5 | { "type": "ci", "hidden": true },
6 | { "type": "docs", "section": "Documentation" },
7 | { "type": "feat", "section": "Features" },
8 | { "type": "fix", "section": "Bug Fixes" },
9 | { "type": "perf", "section": "Performance Improvements" },
10 | { "type": "refactor", "section": "Refactors" },
11 | { "type": "style", "hidden": true },
12 | { "type": "test", "section": "Tests" }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Types of changes
2 |
3 | What kind of change does this PR introduce? (check at least one)
4 |
5 |
6 |
7 | - [ ] Breaking change
8 | - [ ] Bugfix
9 | - [ ] Feature
10 | - [ ] Code style update
11 | - [ ] Refactoring
12 | - [ ] Build related changes
13 | - [ ] CI related changes
14 | - [ ] Documentation content changes
15 | - [ ] Other... Please describe:
16 |
17 | ## Description
18 |
19 |
20 |
21 | Issue Number: N/A
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/lib/getConfig.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 |
3 | export type Config = {
4 | input?: string | string[]
5 | target?: 'es6' | 'cjs'
6 | outputExt?: 'js' | 'ts'
7 | outputFilename?: string
8 | }
9 |
10 | export const mockFileRegExp = /\/(\$|@)/
11 |
12 | export const defaultConfig = {
13 | input: fs.existsSync('mocks') || !fs.existsSync('apis') ? 'mocks' : 'apis',
14 | target: 'es6' as const,
15 | outputExt: 'js' as const
16 | }
17 |
18 | export default (rcFilePath = '.mockserverrc'): Config =>
19 | fs.existsSync(rcFilePath) ? JSON.parse(fs.readFileSync(rcFilePath, 'utf8')) : {}
20 |
--------------------------------------------------------------------------------
/examples/browser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "browser",
3 | "private": true,
4 | "scripts": {
5 | "dev": "npm-run-all mock:build --parallel dev:server mock:watch",
6 | "dev:server": "webpack-dev-server",
7 | "mock:build": "axios-mock-server --build",
8 | "mock:watch": "axios-mock-server --watch"
9 | },
10 | "dependencies": {
11 | "axios": "^0.19.0"
12 | },
13 | "devDependencies": {
14 | "axios-mock-server": "latest",
15 | "npm-run-all": "^4.1.5",
16 | "webpack": "^4.39.3",
17 | "webpack-cli": "^3.3.8",
18 | "webpack-dev-server": "^3.8.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest a feature for axios-mock-server
4 | ---
5 |
6 | ## Description
7 |
8 |
9 |
10 | ## Describe the solution you'd like
11 |
12 |
13 |
14 | ## Describe alternatives you've considered
15 |
16 |
17 |
18 | ## Additional context
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "declaration": true,
5 | "declarationMap": true,
6 | "downlevelIteration": true,
7 | "esModuleInterop": true,
8 | "lib": ["dom", "dom.iterable", "esnext"],
9 | "module": "commonjs",
10 | "moduleResolution": "node",
11 | "outDir": "dist",
12 | "paths": {
13 | "~/*": ["./*"],
14 | "axios-mock-server": ["src"]
15 | },
16 | "resolveJsonModule": true,
17 | "sourceMap": true,
18 | "strict": true,
19 | "target": "es5"
20 | },
21 | "exclude": ["node_modules", "dist", "examples"]
22 | }
23 |
--------------------------------------------------------------------------------
/examples/with-typescript/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-typescript",
3 | "private": true,
4 | "scripts": {
5 | "dev": "npm-run-all mock:build --parallel watch mock:watch",
6 | "build": "axios-mock-server --build && tsc",
7 | "watch": "nodemon",
8 | "type-check": "tsc --noEmit",
9 | "mock:build": "axios-mock-server --build",
10 | "mock:watch": "axios-mock-server --watch"
11 | },
12 | "dependencies": {
13 | "axios": "^0.19.0"
14 | },
15 | "devDependencies": {
16 | "axios-mock-server": "latest",
17 | "nodemon": "^1.19.2",
18 | "npm-run-all": "^4.1.5",
19 | "typescript": "^3.6.3"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/createLogString.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig } from 'axios'
2 | import createRelativePath from './createRelativePath'
3 |
4 | export default (config: AxiosRequestConfig, status: number) => {
5 | const [dirPath, query] = (config.url || '').split('?')
6 | const relativePath = createRelativePath(dirPath, config.baseURL)
7 | const params = new URLSearchParams(query)
8 | Object.keys(config.params || {}).forEach(key => params.append(key, config.params[key]))
9 | const searchString = params.toString()
10 |
11 | return `[mock] ${config.method}: ${relativePath}${
12 | searchString === '' ? '' : `?${searchString}`
13 | } => ${status}`
14 | }
15 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import 'url-search-params-polyfill'
2 |
3 | import { AxiosInstance } from 'axios'
4 | import { MockRoute, HttpMethod, MockResponse, MockMethods } from './types'
5 | import MockServer from './MockServer'
6 | import asyncResponse from './asyncResponse'
7 |
8 | export { asyncResponse, MockServer, MockRoute, HttpMethod, MockResponse, MockMethods }
9 |
10 | export default (route?: MockRoute, client?: AxiosInstance, baseURL = '') =>
11 | new MockServer(route, client, baseURL)
12 |
13 | /* eslint-disable dot-notation */
14 | module.exports = exports['default']
15 | module.exports.default = exports['default']
16 | module.exports.asyncResponse = asyncResponse
17 |
--------------------------------------------------------------------------------
/src/makeResponse.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig, AxiosResponse } from 'axios'
2 | import { MockResponse } from './types'
3 |
4 | const copyData = (data?: any) =>
5 | data && typeof data !== 'string' ? JSON.parse(JSON.stringify(data)) : data
6 | const arrayToObj = (mockRes: MockResponse) =>
7 | Array.isArray(mockRes) ? { status: mockRes[0], data: mockRes[1], headers: mockRes[2] } : mockRes
8 |
9 | export default (mockRes: MockResponse, config: AxiosRequestConfig): AxiosResponse => {
10 | const { status, data, headers } = arrayToObj(mockRes)
11 |
12 | return {
13 | status,
14 | statusText: `${status}`,
15 | data: copyData(data),
16 | headers,
17 | config
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Report a bug in axios-mock-server
4 | ---
5 |
6 | ## Description
7 |
8 |
9 |
10 | ## Environment
11 |
12 | - **axios-mock-server version:**
13 |
14 | `vX.X.X`
15 | - **OS:**
16 |
17 | - [ ] Linux
18 | - [ ] Windows
19 | - [ ] macOS
20 | - **Node.js version:**
21 |
22 | ``
23 | - **npm version:**
24 |
25 | ``
26 |
27 | ## Additional context
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 | target-branch: "develop"
13 | versioning-strategy: "increase"
14 | commit-message:
15 | prefix: "fix"
16 | prefix-development: "chore"
17 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/$mock.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | module.exports = (client) => require('axios-mock-server')([
3 | {
4 | path: '/users/self',
5 | methods: require('./users/self')
6 | },
7 | {
8 | path: '/users',
9 | methods: require('./users/index')
10 | },
11 | {
12 | path: '/users/_userId',
13 | methods: require('./users/_userId')
14 | },
15 | {
16 | path: '/search/_userName@string',
17 | methods: require('./search/_userName@string')
18 | },
19 | {
20 | path: '/',
21 | methods: require('./index')
22 | },
23 | {
24 | path: '/collections/entries.json',
25 | methods: require('./collections/entries.json')
26 | }
27 | ], client, 'https://example.com/api')
28 |
--------------------------------------------------------------------------------
/__tests__/lib/mocks/$mock.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import { AxiosInstance } from 'axios'
3 | import mockServer from 'axios-mock-server'
4 | import mock0 from './users/self'
5 | import mock1 from './users/index'
6 | import mock2 from './users/_userId'
7 | import mock3 from './search/_userName@string'
8 | import mock4 from './index'
9 | import mock5 from './collections/entries.json'
10 |
11 | export default (client?: AxiosInstance) => mockServer([
12 | {
13 | path: '/users/self',
14 | methods: mock0
15 | },
16 | {
17 | path: '/users',
18 | methods: mock1
19 | },
20 | {
21 | path: '/users/_userId',
22 | methods: mock2
23 | },
24 | {
25 | path: '/search/_userName@string',
26 | methods: mock3
27 | },
28 | {
29 | path: '/',
30 | methods: mock4
31 | },
32 | {
33 | path: '/collections/entries.json',
34 | methods: mock5
35 | }
36 | ], client, 'https://example.com/api')
37 |
--------------------------------------------------------------------------------
/src/lib/cli.ts:
--------------------------------------------------------------------------------
1 | import minimist from 'minimist'
2 | import getConfig from './getConfig'
3 | import getInputs from './getInputs'
4 | import build from './buildRouteFile'
5 | import write from './writeRouteFile'
6 | import watch from './watchInputDir'
7 |
8 | export const run = (args: string[]) => {
9 | const argv = minimist(args, {
10 | string: ['version', 'config', 'watch', 'baseurl'],
11 | alias: { v: 'version', c: 'config', w: 'watch', u: 'baseurl' }
12 | })
13 | const config = getConfig(argv.config)
14 |
15 | // eslint-disable-next-line no-unused-expressions
16 | argv.version !== undefined
17 | ? console.log(`v${require('../../package.json').version}`)
18 | : argv.watch !== undefined
19 | ? getInputs(config.input).forEach(input => {
20 | write(build(input, config, argv.baseurl))
21 | watch(input, () => write(build(input, config, argv.baseurl)))
22 | })
23 | : getInputs(config.input)
24 | .map(input => build(input, config, argv.baseurl))
25 | .forEach(write)
26 | }
27 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig } from 'axios'
2 | import createValues from './createValues'
3 | import compositeParams from './compositeParams'
4 |
5 | export const httpMethods = ['get', 'post', 'put', 'delete', 'head', 'patch'] as const
6 |
7 | export type HttpMethod = typeof httpMethods[number]
8 |
9 | export type MockResponse =
10 | | [number, any?, { [key: string]: any }?]
11 | | { status: number; data?: any; headers?: { [key: string]: any } }
12 |
13 | export type MockMethods = {
14 | [T in HttpMethod]?: ({
15 | config,
16 | values,
17 | params,
18 | data
19 | }: {
20 | config: AxiosRequestConfig
21 | values: ReturnType
22 | params: ReturnType
23 | data: any
24 | }) => MockResponse | Promise
25 | }
26 |
27 | type Handler = [RegExp, string, MockMethods[HttpMethod]]
28 | export type HandlersSet = { [key in HttpMethod]?: Handler[] }
29 |
30 | export type MockRoute = {
31 | path: string
32 | methods: MockMethods
33 | }[]
34 |
--------------------------------------------------------------------------------
/src/findAndCallHandler.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig } from 'axios'
2 | import { HandlersSet } from './types'
3 | import findHandler from './findHandler'
4 | import createValues from './createValues'
5 | import untransformData from './untransformData'
6 | import compositeParams from './compositeParams'
7 | import createRelativePath from './createRelativePath'
8 |
9 | export default (config: AxiosRequestConfig, handlersSet: HandlersSet) => {
10 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
11 | const [dirPath, query] = config.url!.split('?')
12 | const relativePath = createRelativePath(dirPath, config.baseURL)
13 | const handler = findHandler(config.method, relativePath, handlersSet)
14 |
15 | return (
16 | handler &&
17 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
18 | handler[2]!({
19 | config,
20 | values: createValues(handler[1], relativePath),
21 | params: compositeParams(query, config.params),
22 | data: untransformData(config.data, config.headers)
23 | })
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Solufa
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/lib/buildRouteFile.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import path from 'path'
3 | import { Config, defaultConfig, mockFileRegExp } from './getConfig'
4 | import { listFiles } from './listFiles'
5 | import createRouteString from './createRouteString'
6 |
7 | const getTarget = (filePath?: string) =>
8 | !filePath
9 | ? defaultConfig.target
10 | : /(\n|^)export default/.test(fs.readFileSync(filePath, 'utf8'))
11 | ? 'es6'
12 | : 'cjs'
13 |
14 | const findExportingFile = (filePaths: string[]) =>
15 | filePaths.find(filePath => /export/.test(fs.readFileSync(filePath, 'utf8')))
16 |
17 | const getMockFilePaths = (input: string, filename = '') =>
18 | listFiles(input)
19 | .filter(
20 | filePath =>
21 | filePath !== filename &&
22 | !mockFileRegExp.test(filePath) &&
23 | /^\.(js|ts)$/.test(path.extname(filePath)) &&
24 | /(\n|^)(export default|module.exports)/.test(fs.readFileSync(filePath, 'utf8'))
25 | )
26 | .sort()
27 | .reverse()
28 |
29 | export default (input: string, config: Config, baseURL = '') => {
30 | const mockFilePaths = getMockFilePaths(input, config.outputFilename)
31 | const ext =
32 | config.outputExt ||
33 | (config.outputFilename ?? '').split('.').pop() ||
34 | (mockFilePaths[0] ? path.extname(mockFilePaths[0]).slice(1) : defaultConfig.outputExt)
35 | const text = createRouteString(
36 | input,
37 | config.target || getTarget(findExportingFile(mockFilePaths)),
38 | ext === 'ts',
39 | mockFilePaths,
40 | baseURL
41 | )
42 |
43 | return { text, filePath: path.posix.join(input, config.outputFilename ?? `$mock.${ext}`) }
44 | }
45 |
--------------------------------------------------------------------------------
/src/lib/createRouteString.ts:
--------------------------------------------------------------------------------
1 | const moduleName = "'axios-mock-server'"
2 | const eslintComment = '/* eslint-disable */'
3 | const createImportPath = (filePath: string, inputDir: string) =>
4 | filePath
5 | .replace(new RegExp(`^(.\\/)?${inputDir.replace(/^.\//, '').replace(/\/$/, '')}`), '')
6 | .replace(/\.(ts|js)$/, '')
7 |
8 | const createCondition = (filePath: string, inputDir: string, methods: string) => `
9 | {
10 | path: '${createImportPath(filePath, inputDir).replace(/(\/index)$/, '') || '/'}',
11 | methods: ${methods}
12 | }`
13 |
14 | export default (
15 | inputDir: string,
16 | target: 'es6' | 'cjs',
17 | isTS: boolean,
18 | pathList: string[],
19 | baseURL = ''
20 | ) =>
21 | target === 'es6'
22 | ? `${eslintComment}
23 | ${
24 | isTS
25 | ? `import { AxiosInstance } from 'axios'
26 | `
27 | : ''
28 | }import mockServer from ${moduleName}
29 | ${pathList
30 | .map(
31 | (filePath, i) => `import mock${i} from '.${createImportPath(filePath, inputDir)}'
32 | `
33 | )
34 | .join('')}
35 | export default (client${
36 | isTS ? '?: AxiosInstance' : ''
37 | }) => mockServer([${pathList
38 | .map((filePath, i) => createCondition(filePath, inputDir, `mock${i}`))
39 | .join(',')}
40 | ], client, '${baseURL}')
41 | `
42 | : `${eslintComment}
43 | ${
44 | isTS
45 | ? `import { AxiosInstance } = require('axios')
46 | `
47 | : ''
48 | }module.exports = (client${
49 | isTS ? '?: AxiosInstance' : ''
50 | }) => require(${moduleName})([${pathList
51 | .map(filePath =>
52 | createCondition(filePath, inputDir, `require('.${createImportPath(filePath, inputDir)}')`)
53 | )
54 | .join(',')}
55 | ], client, '${baseURL}')
56 | `
57 |
--------------------------------------------------------------------------------
/__tests__/lib/index.spec.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import { version } from '~/package.json'
3 | import { run } from '~/src/lib/cli'
4 | import build from '~/src/lib/buildRouteFile'
5 |
6 | describe('cli', () => {
7 | test('version command', () => {
8 | const spyLog = jest.spyOn(console, 'log')
9 | const args = ['--version']
10 |
11 | run(args)
12 | expect(console.log).toHaveBeenCalledWith(`v${version}`)
13 |
14 | spyLog.mockRestore()
15 | })
16 |
17 | test('snapshot', () => {
18 | const configs = [
19 | {
20 | input: '__tests__/lib/mocks',
21 | resultDirPath: '__tests__/lib/mocks',
22 | target: 'es6' as const,
23 | outputExt: 'ts' as const
24 | },
25 | {
26 | input: '__tests__/lib/mocks',
27 | resultDirPath: '__tests__/lib/mocks',
28 | target: 'cjs' as const,
29 | outputExt: 'js' as const
30 | },
31 | {
32 | input: './__tests__/lib/mocks',
33 | resultDirPath: '__tests__/lib/mocks',
34 | target: 'es6' as const,
35 | outputExt: 'ts' as const
36 | },
37 | {
38 | input: './__tests__/lib/mocks',
39 | resultDirPath: '__tests__/lib/mocks',
40 | target: 'cjs' as const,
41 | outputExt: 'js' as const
42 | },
43 | {
44 | input: '__tests__/lib/mocks/',
45 | resultDirPath: '__tests__/lib/mocks',
46 | target: 'es6' as const,
47 | outputExt: 'ts' as const
48 | },
49 | {
50 | input: '__tests__/lib/mocks/',
51 | resultDirPath: '__tests__/lib/mocks',
52 | target: 'cjs' as const,
53 | outputExt: 'js' as const
54 | }
55 | ]
56 |
57 | configs.forEach(config => {
58 | const resultFilePath = `${config.resultDirPath}/$mock.${config.outputExt}`
59 | const result = fs.readFileSync(resultFilePath, 'utf8')
60 | const { text, filePath } = build(config.input, config, 'https://example.com/api')
61 |
62 | expect(text).toBe(result.replace(/\r/g, ''))
63 | expect(filePath).toBe(resultFilePath)
64 | })
65 | })
66 | })
67 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Node.js
2 |
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 | lerna-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
13 |
14 | # Runtime data
15 | pids
16 | *.pid
17 | *.seed
18 | *.pid.lock
19 |
20 | # Directory for instrumented libs generated by jscoverage/JSCover
21 | lib-cov
22 |
23 | # Coverage directory used by tools like istanbul
24 | coverage
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # TypeScript v1 declaration files
46 | typings/
47 |
48 | # Optional npm cache directory
49 | .npm
50 |
51 | # Optional eslint cache
52 | .eslintcache
53 |
54 | # Optional stylelint cache
55 | .stylelintcache
56 |
57 | # Optional REPL history
58 | .node_repl_history
59 |
60 | # Output of 'npm pack'
61 | *.tgz
62 |
63 | # Yarn Integrity file
64 | .yarn-integrity
65 |
66 | # dotenv environment variables file
67 | .env
68 | .env.test
69 |
70 | # parcel-bundler cache (https://parceljs.org/)
71 | .cache
72 |
73 | # next.js build output
74 | .next
75 |
76 | # nuxt.js build output
77 | .nuxt
78 |
79 | # Nuxt generate
80 | dist
81 |
82 | # vuepress build output
83 | .vuepress/dist
84 |
85 | # Serverless directories
86 | .serverless/
87 |
88 | # FuseBox cache
89 | .fusebox/
90 |
91 | # DynamoDB Local files
92 | .dynamodb/
93 |
94 |
95 | # IDE
96 | .idea
97 |
98 | # Service worker
99 | sw.*
100 |
101 |
102 | ### Visual Studio Code
103 |
104 | .vscode/*
105 | !.vscode/settings.json
106 | !.vscode/tasks.json
107 | !.vscode/launch.json
108 | !.vscode/extensions.json
109 |
110 |
111 | ### Miscellaneous
112 |
113 | # examples directory
114 | examples/**/$mock.*
115 | examples/**/package-lock.json
116 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 |
3 | on: push
4 |
5 | jobs:
6 | test:
7 | name: "Test on Node:${{ matrix.node-version }} OS:${{ matrix.os }}"
8 | runs-on: ${{ matrix.os }}
9 | strategy:
10 | matrix:
11 | node-version: [12, 14]
12 | os: [windows-latest, ubuntu-latest]
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: setup Node.js ${{ matrix.node-version }}
16 | uses: actions/setup-node@v1
17 | with:
18 | node-version: ${{ matrix.node-version }}
19 | - name: Get yarn cache directory path
20 | id: yarn-cache-dir-path
21 | run: echo "::set-output name=dir::$(yarn cache dir)"
22 | - uses: actions/cache@v2
23 | id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
24 | with:
25 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
26 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
27 | restore-keys: |
28 | ${{ runner.os }}-yarn-
29 | - run: yarn --frozen-lockfile
30 | - run: yarn lint
31 | if: matrix.os != 'windows-latest'
32 | - run: yarn typecheck
33 | - run: yarn test --coverage
34 | - run: npx codecov
35 | if: github.ref == 'refs/heads/master' && matrix.os == 'ubuntu-latest' && matrix.node-version == 14
36 | env:
37 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
38 |
39 | release:
40 | runs-on: ubuntu-latest
41 | needs: test
42 | if: contains(github.ref, 'tags/v')
43 | steps:
44 | - uses: actions/checkout@v2
45 | - name: Use Node.js
46 | uses: actions/setup-node@v1
47 | with:
48 | node-version: "12.x"
49 | registry-url: "https://registry.npmjs.org"
50 | - name: Get yarn cache directory path
51 | id: yarn-cache-dir-path
52 | run: echo "::set-output name=dir::$(yarn cache dir)"
53 | - uses: actions/cache@v2
54 | id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
55 | with:
56 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
57 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
58 | restore-keys: |
59 | ${{ runner.os }}-yarn-
60 | - run: yarn --frozen-lockfile
61 | - run: yarn build
62 | - run: npm publish
63 | env:
64 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
65 |
--------------------------------------------------------------------------------
/src/MockServer.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosInstance, AxiosAdapter } from 'axios'
2 | import settle from 'axios/lib/core/settle'
3 | import { HandlersSet, MockRoute, httpMethods } from './types'
4 | import createLogString from './createLogString'
5 | import makeResponse from './makeResponse'
6 | import findAndCallHandler from './findAndCallHandler'
7 |
8 | export const createPathRegExp = (path: string) =>
9 | new RegExp(`^${path.replace(/\/_[^/]+/g, '/[^/]+')}$`)
10 |
11 | export default class {
12 | private handlersSet: HandlersSet = {}
13 | private delayTime = 0
14 | private needsLog = false
15 | private client?: AxiosInstance
16 | private originalAdapter?: AxiosAdapter
17 | private baseURL = ''
18 |
19 | constructor(route?: MockRoute, client?: AxiosInstance, baseURL = '') {
20 | if (route)
21 | this.setBaseURL(baseURL)
22 | .setClient(client || axios)
23 | .setRoute(route)
24 | }
25 |
26 | public setClient(client: AxiosInstance) {
27 | this.client = client
28 | this.originalAdapter = client.defaults.adapter
29 |
30 | client.defaults.adapter = config =>
31 | // eslint-disable-next-line no-async-promise-executor
32 | new Promise(async (resolve, reject) => {
33 | const customConfig = {
34 | ...config,
35 | baseURL: config.baseURL || this.baseURL
36 | }
37 |
38 | try {
39 | const result = findAndCallHandler(customConfig, this.handlersSet)
40 |
41 | if (!result && this.originalAdapter) {
42 | this.originalAdapter(customConfig).then(resolve, reject)
43 | return
44 | }
45 |
46 | const res = result
47 | ? makeResponse(result instanceof Promise ? await result : result, customConfig)
48 | : { status: 404, config: customConfig }
49 |
50 | if (this.needsLog) console.log(createLogString(customConfig, res.status))
51 |
52 | setTimeout(() => settle(resolve, reject, res), this.delayTime)
53 | } catch (e) {
54 | reject(e)
55 | }
56 | })
57 |
58 | return this
59 | }
60 |
61 | public setRoute(route: MockRoute) {
62 | route.forEach(r => {
63 | const pathRegExp = createPathRegExp(r.path)
64 |
65 | httpMethods.forEach(method => {
66 | if (r.methods[method]) {
67 | this.handlersSet[method] = [
68 | ...(this.handlersSet[method] || []),
69 | [pathRegExp, r.path, r.methods[method]]
70 | ]
71 | }
72 | })
73 | })
74 |
75 | return this
76 | }
77 |
78 | public setDelayTime(delayTime: number) {
79 | this.delayTime = delayTime
80 | return this
81 | }
82 |
83 | public setBaseURL(baseURL: string) {
84 | this.baseURL = baseURL
85 | return this
86 | }
87 |
88 | public reset() {
89 | this.setDelayTime(0).disableLog()
90 | this.handlersSet = {}
91 | return this
92 | }
93 |
94 | public restore() {
95 | if (!this.client) return
96 |
97 | this.reset()
98 | delete this.client.defaults.adapter
99 |
100 | if (this.originalAdapter) {
101 | this.client.defaults.adapter = this.originalAdapter
102 | delete this.originalAdapter
103 | }
104 |
105 | delete this.client
106 | return this
107 | }
108 |
109 | public enableLog() {
110 | this.needsLog = true
111 | return this
112 | }
113 |
114 | public disableLog() {
115 | this.needsLog = false
116 | return this
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "axios-mock-server",
3 | "version": "0.19.1",
4 | "description": "RESTful mock server using axios",
5 | "author": "Solufa ",
6 | "license": "MIT",
7 | "main": "dist/index.js",
8 | "bin": "bin/index.js",
9 | "scripts": {
10 | "dev": "npm run build && node bin/index.js -c devConfigs/.js.rc -b -u https://example.com/api && node bin/index.js -c devConfigs/.ts.rc -b -u https://example.com/api",
11 | "build": "node -e \"require('fs').rmdirSync('dist', { recursive: true })\" && tsc -p tsconfig.build.json",
12 | "release": "standard-version --skip.tag",
13 | "release:major": "npm run release -- --release-as major",
14 | "release:minor": "npm run release -- --release-as minor",
15 | "release:patch": "npm run release -- --release-as patch",
16 | "lint": "eslint --ext .js,.ts --ignore-path .gitignore .",
17 | "lint:fix": "npm run lint -- --fix",
18 | "typecheck": "tsc --noEmit",
19 | "test": "jest"
20 | },
21 | "homepage": "https://github.com/solufa/axios-mock-server#readme",
22 | "repository": {
23 | "type": "git",
24 | "url": "git+https://github.com/solufa/axios-mock-server.git"
25 | },
26 | "bugs": {
27 | "url": "https://github.com/solufa/axios-mock-server/issues"
28 | },
29 | "files": [
30 | "dist"
31 | ],
32 | "keywords": [
33 | "axios",
34 | "test",
35 | "mock"
36 | ],
37 | "eslintConfig": {
38 | "env": {
39 | "es6": true,
40 | "node": true,
41 | "browser": true
42 | },
43 | "extends": [
44 | "standard",
45 | "plugin:@typescript-eslint/recommended",
46 | "plugin:jest/recommended",
47 | "plugin:prettier/recommended",
48 | "prettier/@typescript-eslint",
49 | "prettier/standard"
50 | ],
51 | "parserOptions": {
52 | "ecmaVersion": 2018,
53 | "sourceType": "module"
54 | },
55 | "root": true,
56 | "rules": {
57 | "@typescript-eslint/explicit-function-return-type": "off",
58 | "@typescript-eslint/ban-ts-comment": "off",
59 | "@typescript-eslint/explicit-module-boundary-types": "off",
60 | "@typescript-eslint/no-var-requires": "off",
61 | "@typescript-eslint/ban-types": "off",
62 | "@typescript-eslint/camelcase": "off",
63 | "@typescript-eslint/no-explicit-any": "off"
64 | }
65 | },
66 | "prettier": {
67 | "printWidth": 100,
68 | "semi": false,
69 | "arrowParens": "avoid",
70 | "singleQuote": true,
71 | "trailingComma": "none",
72 | "overrides": [
73 | {
74 | "files": [
75 | "*.md",
76 | "*.yml"
77 | ],
78 | "options": {
79 | "singleQuote": false
80 | }
81 | }
82 | ]
83 | },
84 | "devDependencies": {
85 | "@types/jest": "^26.0.20",
86 | "@types/minimist": "^1.2.1",
87 | "@typescript-eslint/eslint-plugin": "^4.15.0",
88 | "@typescript-eslint/parser": "^4.15.0",
89 | "axios": "^0.21.1",
90 | "eslint": "^7.20.0",
91 | "eslint-config-prettier": "^7.2.0",
92 | "eslint-config-standard": "^16.0.2",
93 | "eslint-plugin-import": "^2.22.1",
94 | "eslint-plugin-jest": "^24.1.3",
95 | "eslint-plugin-node": "^11.1.0",
96 | "eslint-plugin-prettier": "^3.3.1",
97 | "eslint-plugin-promise": "^4.3.1",
98 | "eslint-plugin-standard": "^5.0.0",
99 | "jest": "^26.6.3",
100 | "prettier": "^2.2.1",
101 | "standard-version": "^9.1.0",
102 | "ts-jest": "^26.5.1",
103 | "typescript": "^4.1.5"
104 | },
105 | "dependencies": {
106 | "chokidar": "^3.5.1",
107 | "minimist": "^1.2.5",
108 | "url-search-params-polyfill": "^8.1.0"
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/__tests__/units.spec.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig } from 'axios'
2 | import { HandlersSet, HttpMethod } from '~/src/types'
3 | import { asyncResponse } from '~/src'
4 | import createValues from '~/src/createValues'
5 | import findHandler from '~/src/findHandler'
6 | import { createPathRegExp } from '~/src/MockServer'
7 | import createRelativePath from '~/src/createRelativePath'
8 | import createLogString from '~/src/createLogString'
9 | import untransformData from '~/src/untransformData'
10 |
11 | describe('unit tests', () => {
12 | test('createValues', () => {
13 | const list: {
14 | conditions: [string, string]
15 | values: { [key: string]: string | number }
16 | }[] = [
17 | {
18 | conditions: ['/aa/_bb/cc/_dd', '/aa/hoge/cc/123'],
19 | values: { bb: 'hoge', dd: 123 }
20 | },
21 | {
22 | conditions: ['/aa/_bb/cc/_dd@number', '/aa/hoge/cc/123'],
23 | values: { bb: 'hoge', dd: 123 }
24 | },
25 | {
26 | conditions: ['/aa/_bb/cc/_dd@string', '/aa/hoge/cc/123'],
27 | values: { bb: 'hoge', dd: '123' }
28 | }
29 | ]
30 |
31 | list.forEach(({ conditions, values }) => expect(createValues(...conditions)).toEqual(values))
32 | })
33 |
34 | test('findHandler', () => {
35 | const list = [
36 | {
37 | method: 'get',
38 | path: '/aa/hoge/cc/123',
39 | handlersSet: { get: [[createPathRegExp('/aa/_bb/cc/_dd'), '/aa/_bb/cc/_dd', () => [200]]] },
40 | resultIndex: 0
41 | },
42 | {
43 | method: 'get',
44 | path: '/zz/aa/hoge/cc/123',
45 | handlersSet: { get: [[createPathRegExp('/aa/_bb/cc/_dd'), '/aa/_bb/cc/_dd', () => [200]]] },
46 | resultIndex: undefined
47 | },
48 | {
49 | method: 'post',
50 | path: '/aa/hoge/cc/123',
51 | handlersSet: { get: [[createPathRegExp('/aa/_bb/cc/_dd'), '/aa/_bb/cc/_dd', () => [200]]] },
52 | resultIndex: undefined
53 | },
54 | {
55 | method: 'get',
56 | path: '/aa/hoge/cc',
57 | handlersSet: { get: [[createPathRegExp('/aa/_bb/cc/_dd'), '/aa/_bb/cc/_dd', () => [200]]] },
58 | resultIndex: undefined
59 | },
60 | {
61 | method: 'post',
62 | path: '/aa/hoge/cc',
63 | handlersSet: {
64 | post: [
65 | [createPathRegExp('/aa/_bb/cc/_dd'), '/aa/_bb/cc/_dd', () => [200]],
66 | [createPathRegExp('/aa/_bb/cc'), '/aa/_bb/cc', () => [200]]
67 | ]
68 | },
69 | resultIndex: 1
70 | },
71 | {
72 | method: undefined,
73 | path: '/aa',
74 | handlersSet: { get: [[createPathRegExp('/aa'), '/aa', () => [200]]] },
75 | resultIndex: undefined
76 | }
77 | ]
78 |
79 | list.forEach(({ method, path, handlersSet, resultIndex }) =>
80 | expect(findHandler(method, path, handlersSet as HandlersSet)).toBe(
81 | resultIndex === undefined
82 | ? undefined
83 | : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
84 | (handlersSet as HandlersSet)[method as HttpMethod]![resultIndex]
85 | )
86 | )
87 | })
88 |
89 | test('asyncResponse', async () => {
90 | const result = [200, { test: 'aaa' }, { 'cache-control': 'max-age=0' }] as const
91 | const res = await asyncResponse(result[0], (async () => result[1])(), result[2])
92 | expect(res).toEqual(result)
93 | })
94 |
95 | test('createRelativePath', () => {
96 | const paths = [
97 | { url: '//apple.com/aa/bb', baseURL: 'https://google.com/', result: '/aa/bb' },
98 | { url: '/aa/bb', baseURL: undefined, result: '/aa/bb' },
99 | { url: '/cc/dd/', baseURL: '/aa/bb', result: '/cc/dd' },
100 | { url: undefined, baseURL: 'https://google.com/abc/', result: '/' },
101 | { url: undefined, baseURL: undefined, result: '/' }
102 | ]
103 |
104 | paths.forEach(path => expect(createRelativePath(path.url, path.baseURL)).toBe(path.result))
105 | })
106 |
107 | test('createLogString', () => {
108 | const configs = [
109 | {
110 | config: {
111 | method: 'get',
112 | url: '/bb/?cc=123',
113 | baseURL: '//google.com/aa'
114 | },
115 | status: 200,
116 | result: '[mock] get: /bb?cc=123 => 200'
117 | },
118 | {
119 | config: {
120 | method: 'post',
121 | url: '/bb/?cc=123',
122 | params: { dd: 'abc' }
123 | },
124 | status: 201,
125 | result: '[mock] post: /bb?cc=123&dd=abc => 201'
126 | },
127 | {
128 | config: {
129 | method: 'put',
130 | baseURL: '//google.com/aa',
131 | params: { dd: 'abc' }
132 | },
133 | status: 204,
134 | result: '[mock] put: /?dd=abc => 204'
135 | },
136 | {
137 | config: {
138 | method: 'delete',
139 | url: '?aa=123',
140 | params: { bb: 'abc' }
141 | },
142 | status: 204,
143 | result: '[mock] delete: /?aa=123&bb=abc => 204'
144 | }
145 | ]
146 |
147 | configs.forEach(c =>
148 | expect(createLogString(c.config as AxiosRequestConfig, c.status)).toBe(c.result)
149 | )
150 | })
151 |
152 | test('untransformData', () => {
153 | expect(untransformData('{"aa": 1}', { 'Content-Type': 'application/json' })).toEqual({ aa: 1 })
154 | expect(untransformData(undefined, {})).toBe(undefined)
155 |
156 | const fakeImage = {}
157 | expect(untransformData(fakeImage, { 'Content-Type': 'image/jpeg' })).toBe(fakeImage)
158 |
159 | const params: URLSearchParams = untransformData('foo=1&bar=2', {
160 | 'Content-Type': 'application/x-www-form-urlencoded'
161 | })
162 | expect(params.get('foo')).toBe('1')
163 | expect(params.get('bar')).toBe('2')
164 | })
165 | })
166 |
--------------------------------------------------------------------------------
/__tests__/index.spec.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosInstance } from 'axios'
2 | import mockServer, { MockRoute, asyncResponse, MockResponse } from '~/src'
3 |
4 | describe('initialize', () => {
5 | const mock = mockServer()
6 | let client: AxiosInstance
7 |
8 | beforeEach(() => {
9 | client = axios.create({ baseURL: 'https://google.com/aa' })
10 | mock.setClient(client)
11 | })
12 |
13 | afterEach(() => mock.reset())
14 |
15 | test('enabled mock', async () => {
16 | const route: MockRoute = []
17 |
18 | mock.setRoute(route)
19 | await expect(client.get('/')).rejects.toHaveProperty('response.status', 404)
20 | })
21 |
22 | test('default axios', async () => {
23 | const testPath = '/test'
24 | const defaultValue = { name: 'test' }
25 | const route: MockRoute = [
26 | {
27 | path: testPath,
28 | methods: { get: () => [200, defaultValue] }
29 | }
30 | ]
31 |
32 | const mock = mockServer(route)
33 |
34 | const { data } = await axios.get(testPath)
35 |
36 | expect(data).toEqual(defaultValue)
37 | expect(data).not.toBe(defaultValue)
38 |
39 | mock.restore()
40 | })
41 |
42 | test('get object', async () => {
43 | const testPath = '/test'
44 | const defaultValue = [{ name: 'test1' }, { name: 'test2' }]
45 | const route: MockRoute = [
46 | {
47 | path: testPath,
48 | methods: { get: () => [200, defaultValue] }
49 | }
50 | ]
51 |
52 | mock.setRoute(route)
53 | const { data } = await client.get(testPath)
54 |
55 | expect(data).toEqual(defaultValue)
56 | expect(data).not.toBe(defaultValue)
57 | })
58 |
59 | test('get without baseURL', async () => {
60 | const axiosInstance = axios.create()
61 | const testPath = '/test'
62 | const defaultValue = { name: 'test' }
63 | const route: MockRoute = [
64 | {
65 | path: testPath,
66 | methods: { get: () => [200, defaultValue] }
67 | }
68 | ]
69 |
70 | mockServer(route, axiosInstance)
71 | const { data } = await axiosInstance.get(testPath)
72 |
73 | expect(data).toEqual(defaultValue)
74 | })
75 |
76 | test('get path through', async () => {
77 | const axiosInstance = axios.create({ baseURL: 'https://google.com/' })
78 | const testPath = '/test'
79 | const defaultValue = [{ name: 'test1' }, { name: 'test2' }]
80 | const route: MockRoute = [
81 | {
82 | path: testPath,
83 | methods: { get: () => [200, defaultValue] }
84 | }
85 | ]
86 |
87 | mockServer(route, axiosInstance)
88 |
89 | const { status } = await axiosInstance.get('/')
90 | expect(status).toBe(200)
91 |
92 | const { data } = await axiosInstance.get(testPath)
93 | expect(data).toEqual(defaultValue)
94 | })
95 |
96 | test('get with query and params', async () => {
97 | const response = { name: 'mario', height: 155, color: 'red' }
98 | const testPath = '/test'
99 | const route: MockRoute = [
100 | {
101 | path: testPath,
102 | methods: { get: ({ params }) => [200, params] }
103 | }
104 | ]
105 |
106 | mock.setRoute(route)
107 | const { data } = await client.get(
108 | `${testPath}/?height=${response.height}&color=${response.color}`,
109 | {
110 | params: { name: response.name }
111 | }
112 | )
113 |
114 | expect(data).toEqual(response)
115 | })
116 |
117 | test('404 request', async () => {
118 | const testPath = '/test'
119 | const route: MockRoute = [{ path: testPath, methods: {} }]
120 |
121 | mock.setRoute(route)
122 | await expect(client.get(testPath)).rejects.toHaveProperty('response.status', 404)
123 | })
124 |
125 | test('get with params', async () => {
126 | const testPath = '/test'
127 | const name = 'mario'
128 | const route: MockRoute = [
129 | {
130 | path: testPath,
131 | methods: { get: ({ params }) => [200, params.name] }
132 | }
133 | ]
134 |
135 | mock.setRoute(route)
136 | const { data } = await client.get(testPath, { params: { name } })
137 |
138 | expect(data).toEqual(name)
139 | })
140 |
141 | test('get with values', async () => {
142 | const testRegPath = '/test/_name/hoge.json'
143 | const name = 'mario'
144 | const testPath = `/test/${name}/hoge.json`
145 | const route: MockRoute = [
146 | {
147 | path: testRegPath,
148 | methods: { get: ({ values }) => [200, { name: values.name }] }
149 | }
150 | ]
151 |
152 | mock.setRoute(route)
153 | const { data } = await client.get(testPath)
154 |
155 | expect(data.name).toEqual(name)
156 | })
157 |
158 | test('get with typed values', async () => {
159 | const testRegPath = '/test/_name@string/hoge.json'
160 | const name = '12345'
161 | const testPath = `/test/${name}/hoge.json`
162 | const route: MockRoute = [
163 | {
164 | path: testRegPath,
165 | methods: { get: ({ values }) => [200, { name: values.name }] }
166 | }
167 | ]
168 |
169 | mock.setRoute(route)
170 | const { data } = await client.get(testPath)
171 |
172 | expect(data.name).toEqual(name)
173 | })
174 |
175 | test('post with data', async () => {
176 | const testPath = '/test'
177 | const name = 'mario'
178 | const route: MockRoute = [
179 | {
180 | path: testPath,
181 | methods: { post: ({ data: { name } }) => [201, name] }
182 | }
183 | ]
184 |
185 | mock.setRoute(route)
186 | const { data } = await client.post(testPath, { name })
187 |
188 | expect(data).toEqual(name)
189 | })
190 |
191 | test('post with data by x-www-form-urlencoded', async () => {
192 | const testPath = '/test'
193 | const name = 'mario'
194 | const params = new URLSearchParams()
195 | params.append('name', name)
196 |
197 | const route: MockRoute = [
198 | {
199 | path: testPath,
200 | methods: { post: ({ data }) => [201, data.get('name')] }
201 | }
202 | ]
203 |
204 | mock.setRoute(route)
205 | const { data } = await client.post(testPath, params)
206 |
207 | expect(data).toEqual(name)
208 | })
209 |
210 | test('put with data', async () => {
211 | const testPath = '/test'
212 | const name = 'mario'
213 | const route: MockRoute = [
214 | {
215 | path: testPath,
216 | methods: { put: ({ data: { name } }) => [200, name] }
217 | }
218 | ]
219 |
220 | mock.setRoute(route)
221 | const { data } = await client.put(testPath, { name })
222 |
223 | expect(data).toEqual(name)
224 | })
225 |
226 | test('delete with data', async () => {
227 | const testPath = '/test'
228 | const name = 'mario'
229 | const route: MockRoute = [
230 | {
231 | path: testPath,
232 | methods: { delete: ({ data: { name } }) => [200, name] }
233 | }
234 | ]
235 |
236 | mock.setRoute(route)
237 | const { data } = await client.delete(testPath, { data: { name } })
238 |
239 | expect(data).toEqual(name)
240 | })
241 |
242 | test('response 401 error', async () => {
243 | const testPath = '/test'
244 | const status = 401
245 | const route: MockRoute = [{ path: testPath, methods: { get: () => [status] } }]
246 |
247 | mock.setRoute(route)
248 | await expect(client.get(testPath)).rejects.toHaveProperty('response.status', status)
249 | })
250 |
251 | test('response 500 error', async () => {
252 | const testPath = '/test'
253 | const status = 500
254 | const route: MockRoute = [{ path: testPath, methods: { get: () => [status] } }]
255 |
256 | mock.setRoute(route)
257 | await expect(client.get(testPath)).rejects.toHaveProperty('response.status', status)
258 | })
259 |
260 | test('set delayTime', async () => {
261 | const delayTime = 500
262 | const testPath = '/test'
263 | const route: MockRoute = [{ path: testPath, methods: { get: () => [204] } }]
264 |
265 | mock.setRoute(route).setDelayTime(delayTime)
266 | const startTime = Date.now()
267 |
268 | await client.get(testPath)
269 |
270 | const elapsedTime = Date.now() - startTime
271 | expect(elapsedTime).toBeGreaterThanOrEqual(delayTime - 1)
272 | expect(elapsedTime).toBeLessThan(delayTime + 20)
273 | })
274 |
275 | test('async methods', async () => {
276 | const testPath = '/test'
277 | const name = 'mario'
278 | const errorStatus = 500
279 | const errorMessage = 'error test'
280 | const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
281 | const route: MockRoute = [
282 | {
283 | path: testPath,
284 | methods: {
285 | async get({ params }) {
286 | await sleep(100)
287 | return {
288 | status: 200,
289 | data: params.name,
290 | headers: { 'cache-control': 'max-age=0' }
291 | }
292 | },
293 | async post() {
294 | await sleep(100)
295 | return { status: errorStatus }
296 | },
297 | async put() {
298 | await sleep(100)
299 | throw new Error(errorMessage)
300 | },
301 | delete() {
302 | throw new Error(errorMessage)
303 | }
304 | }
305 | },
306 | {
307 | path: 'type-error-test',
308 | methods: {
309 | get: () =>
310 | asyncResponse(
311 | 200,
312 | new Promise(resolve => resolve())
313 | ),
314 | async post() {
315 | await sleep(100)
316 | return [errorStatus] as MockResponse
317 | }
318 | }
319 | }
320 | ]
321 |
322 | mock.setRoute(route)
323 | const { data } = await client.get(testPath, { params: { name } })
324 |
325 | expect(data).toEqual(name)
326 |
327 | await expect(client.post(testPath)).rejects.toHaveProperty('response.status', errorStatus)
328 | await expect(client.put(testPath)).rejects.toHaveProperty('message', errorMessage)
329 | await expect(client.delete(testPath)).rejects.toHaveProperty('message', errorMessage)
330 | })
331 |
332 | test('enable log', async () => {
333 | const spyLog = jest.spyOn(console, 'log')
334 | const testPath = '/test'
335 | const route: MockRoute = [{ path: testPath, methods: { get: () => [204] } }]
336 |
337 | mock.setRoute(route).enableLog()
338 | await client.get(testPath)
339 |
340 | expect(console.log).toHaveBeenCalled()
341 |
342 | spyLog.mockReset()
343 | mock.disableLog()
344 | await client.get(testPath)
345 | expect(console.log).not.toHaveBeenCalled()
346 |
347 | spyLog.mockReset()
348 | spyLog.mockRestore()
349 | })
350 | })
351 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ### [0.19.1](https://github.com/solufa/axios-mock-server/compare/v0.19.0...v0.19.1) (2021-02-13)
6 |
7 |
8 | ### Bug Fixes
9 |
10 | * lint and typecheck error ([612b1bc](https://github.com/solufa/axios-mock-server/commit/612b1bc6c7c07240f293b6d185eef642d01ffc70))
11 | * **deps:** [security] bump ini from 1.3.5 to 1.3.7 ([e2874d2](https://github.com/solufa/axios-mock-server/commit/e2874d2fb51cd2807860745bd6894a6844110ba7))
12 | * **deps:** bump chokidar from 3.4.2 to 3.4.3 ([acfe4c4](https://github.com/solufa/axios-mock-server/commit/acfe4c406140ef2992f2ad20aa2e841623017fec))
13 |
14 |
15 | ### Documentation
16 |
17 | * update README ([1e56cce](https://github.com/solufa/axios-mock-server/commit/1e56cceb414b71b1caf0e9b7a20f37f7948319a1))
18 |
19 | ## [0.19.0](https://github.com/solufa/axios-mock-server/compare/v0.18.1...v0.19.0) (2020-08-25)
20 |
21 |
22 | ### Features
23 |
24 | * add outputFilename option ([763be9f](https://github.com/solufa/axios-mock-server/commit/763be9fd8e9359c634c919bee7b9a5c5c14e5adf))
25 |
26 |
27 | ### Bug Fixes
28 |
29 | * **deps:** bump chokidar from 3.4.1 to 3.4.2 ([b85074a](https://github.com/solufa/axios-mock-server/commit/b85074acd8e11a1f55278fe82dbf63aedfe8e8d5))
30 |
31 | ### [0.18.1](https://github.com/solufa/axios-mock-server/compare/v0.18.0...v0.18.1) (2020-07-28)
32 |
33 |
34 | ### Bug Fixes
35 |
36 | * version command for building depth ([fc7a7d1](https://github.com/solufa/axios-mock-server/commit/fc7a7d1f561525354deba11498c6289b4a763fb8))
37 |
38 | ## [0.18.0](https://github.com/solufa/axios-mock-server/compare/v0.17.2...v0.18.0) (2020-07-28)
39 |
40 |
41 | ### Features
42 |
43 | * optimize build command ([0d93bde](https://github.com/solufa/axios-mock-server/commit/0d93bded96c992ef774d3bf619aa668fb5883b23))
44 |
45 | ### [0.17.2](https://github.com/solufa/axios-mock-server/compare/v0.17.1...v0.17.2) (2020-07-26)
46 |
47 |
48 | ### Bug Fixes
49 |
50 | * version option of cli ([844ee33](https://github.com/solufa/axios-mock-server/commit/844ee337a42b12b2a613854d195498593034baed))
51 |
52 | ### [0.17.1](https://github.com/solufa/axios-mock-server/compare/v0.17.0...v0.17.1) (2020-07-21)
53 |
54 |
55 | ### Bug Fixes
56 |
57 | * type of makeResponse ([9ed59a9](https://github.com/solufa/axios-mock-server/commit/9ed59a9069fe65b72ae7e2cc1f1e0e97badba072))
58 |
59 | ## [0.17.0](https://github.com/solufa/axios-mock-server/compare/v0.16.3...v0.17.0) (2020-07-21)
60 |
61 |
62 | ### Bug Fixes
63 |
64 | * **deps:** [security] bump acorn from 6.4.0 to 6.4.1 ([2c96445](https://github.com/solufa/axios-mock-server/commit/2c96445028e42d623125794ed40b2075ac740458))
65 | * **deps:** bump chokidar from 3.3.0 to 3.3.1 ([1e8a5c4](https://github.com/solufa/axios-mock-server/commit/1e8a5c42704b37ef055d587a282612ef9b223969))
66 | * **deps:** bump chokidar from 3.3.1 to 3.4.1 ([6803a34](https://github.com/solufa/axios-mock-server/commit/6803a347589c4a42bc2a4b3b7c068b9948ff4281))
67 | * **deps:** bump minimist from 1.2.0 to 1.2.1 ([166598b](https://github.com/solufa/axios-mock-server/commit/166598bedf1cefa737624b2c0226575cc09c1d90))
68 | * **deps:** bump minimist from 1.2.1 to 1.2.2 ([858137a](https://github.com/solufa/axios-mock-server/commit/858137a3cfd15aa1af8a0f7942fbb0393a017f23))
69 | * **deps:** bump minimist from 1.2.2 to 1.2.3 ([62424c0](https://github.com/solufa/axios-mock-server/commit/62424c0d6a4fd38ab49e7529ce7a822d757c0df7))
70 | * **deps:** bump minimist from 1.2.3 to 1.2.4 ([2e37d82](https://github.com/solufa/axios-mock-server/commit/2e37d82681b3c558dfb81c97cada2359cc987290))
71 | * **deps:** bump minimist from 1.2.4 to 1.2.5 ([cf16377](https://github.com/solufa/axios-mock-server/commit/cf1637752240ca45ac525bb91c2bf4eb146c806c))
72 | * **deps:** bump url-search-params-polyfill from 7.0.0 to 7.0.1 ([02a074a](https://github.com/solufa/axios-mock-server/commit/02a074ae47996ede7c80a6bdeb7f67cbf4510210))
73 | * **deps:** bump url-search-params-polyfill from 7.0.1 to 8.0.0 ([cc23d81](https://github.com/solufa/axios-mock-server/commit/cc23d8158f43b1af2fd55ba09481b3e49c073aa9))
74 | * **deps:** bump url-search-params-polyfill from 8.0.0 to 8.1.0 ([42e6e71](https://github.com/solufa/axios-mock-server/commit/42e6e71cd98549d038eabf6e8fce99cdc8f3ab15))
75 |
76 |
77 | ### Refactors
78 |
79 | * clarify dev command ([efcd257](https://github.com/solufa/axios-mock-server/commit/efcd257ef82f65c9b5bbb1bc2b286b6c3855930f))
80 | * clarify listFiles ([d715a7f](https://github.com/solufa/axios-mock-server/commit/d715a7f3de7e6ba1ebc1324037be17573f4f28c6))
81 |
82 | ### [0.16.3](https://github.com/solufa/axios-mock-server/compare/v0.16.2...v0.16.3) (2019-11-06)
83 |
84 |
85 | ### Bug Fixes
86 |
87 | * ignore empty file ([c1ea53e](https://github.com/solufa/axios-mock-server/commit/c1ea53e14aacfd05386cf6ad55486e7303003570))
88 | * **deps:** bump chokidar from 3.2.2 to 3.2.3 ([0fec72f](https://github.com/solufa/axios-mock-server/commit/0fec72f1bee310bdaf30238dc0b16a41aa92e7c9))
89 | * **deps:** bump chokidar from 3.2.3 to 3.3.0 ([68000b2](https://github.com/solufa/axios-mock-server/commit/68000b23b0ce1f2d3bd846322236bbd1b2985aee))
90 |
91 | ### [0.16.2](https://github.com/solufa/axios-mock-server/compare/v0.16.1...v0.16.2) (2019-10-24)
92 |
93 |
94 | ### Bug Fixes
95 |
96 | * **cli:** ignore files other than js and ts ([fe31b37](https://github.com/solufa/axios-mock-server/commit/fe31b376cc5168ce6e749aa686f5be3fa7ab48de))
97 |
98 | ### [0.16.1](https://github.com/solufa/axios-mock-server/compare/v0.16.0...v0.16.1) (2019-10-21)
99 |
100 |
101 | ### Bug Fixes
102 |
103 | * **factory:** add baseURL ([71fa401](https://github.com/solufa/axios-mock-server/commit/71fa401afd7ac13930bbc680e3d53f686748aa56))
104 |
105 | ## [0.16.0](https://github.com/solufa/axios-mock-server/compare/v0.15.0...v0.16.0) (2019-10-21)
106 |
107 |
108 | ### Features
109 |
110 | * **cli:** add baseURL ([4c4dbaa](https://github.com/solufa/axios-mock-server/commit/4c4dbaa8481987fa3269f8ef7b13e9db0a533af4))
111 |
112 | ## [0.15.0](https://github.com/solufa/axios-mock-server/compare/v0.14.1...v0.15.0) (2019-10-20)
113 |
114 |
115 | ### Features
116 |
117 | * **cli:** change file ignore pattern ([d23604d](https://github.com/solufa/axios-mock-server/commit/d23604d36bacc9aab9ce42ebfe56201086c4f587))
118 | * **cli:** implement typed path values ([757a530](https://github.com/solufa/axios-mock-server/commit/757a530aefbecd56005cc4dac468d103491f8dbb))
119 |
120 |
121 | ### Bug Fixes
122 |
123 | * **deps:** bump chokidar from 3.2.1 to 3.2.2 ([530ae8e](https://github.com/solufa/axios-mock-server/commit/530ae8e48f449cc63c5a9fd33d67473e9da41464))
124 |
125 | ### [0.14.1](https://github.com/solufa/axios-mock-server/compare/v0.14.0...v0.14.1) (2019-10-14)
126 |
127 | ## [0.14.0](https://github.com/solufa/axios-mock-server/compare/v0.13.2...v0.14.0) (2019-10-12)
128 |
129 |
130 | ### Documentation
131 |
132 | * fix Dependabot badge ([f190e07](https://github.com/solufa/axios-mock-server/commit/f190e07))
133 |
134 |
135 | ### Features
136 |
137 | * **cli:** add default input config ([c49f8a0](https://github.com/solufa/axios-mock-server/commit/c49f8a0))
138 | * **main:** add auto path through ([da17d79](https://github.com/solufa/axios-mock-server/commit/da17d79))
139 |
140 | ### [0.13.2](https://github.com/solufa/axios-mock-server/compare/v0.13.1...v0.13.2) (2019-10-10)
141 |
142 |
143 | ### Refactors
144 |
145 | * **axios:** move to devDependencies ([edb860e](https://github.com/solufa/axios-mock-server/commit/edb860e))
146 | * **cli:** delete replacePathSepIfWindows ([0547552](https://github.com/solufa/axios-mock-server/commit/0547552))
147 |
148 | ### [0.13.1](https://github.com/solufa/axios-mock-server/compare/v0.13.0...v0.13.1) (2019-10-07)
149 |
150 |
151 | ### Bug Fixes
152 |
153 | * **main:** correspond es5 for ie11 ([7ba004c](https://github.com/solufa/axios-mock-server/commit/7ba004c))
154 | * **package.json:** conflict ([8f9deac](https://github.com/solufa/axios-mock-server/commit/8f9deac))
155 |
156 | ## [0.13.0](https://github.com/solufa/axios-mock-server/compare/v0.12.1...v0.13.0) (2019-10-06)
157 |
158 |
159 | ### Bug Fixes
160 |
161 | * **cli:** add eslint-disable comment ([8465697](https://github.com/solufa/axios-mock-server/commit/8465697))
162 |
163 |
164 | ### Documentation
165 |
166 | * update README.md ([9bd4e9a](https://github.com/solufa/axios-mock-server/commit/9bd4e9a))
167 |
168 |
169 | ### Features
170 |
171 | * **cli:** change $route -> $mock ([4a8f19d](https://github.com/solufa/axios-mock-server/commit/4a8f19d))
172 |
173 | ### [0.12.1](https://github.com/solufa/axios-mock-server/compare/v0.12.0...v0.12.1) (2019-10-02)
174 |
175 |
176 | ### Bug Fixes
177 |
178 | * **cli:** change route file write rules ([75cf691](https://github.com/solufa/axios-mock-server/commit/75cf691))
179 | * **deps:** bump chokidar from 3.2.0 to 3.2.1 ([79f0af0](https://github.com/solufa/axios-mock-server/commit/79f0af0))
180 | * **main:** copy response ([0dc3ba3](https://github.com/solufa/axios-mock-server/commit/0dc3ba3))
181 |
182 | ## [0.12.0](https://github.com/solufa/axios-mock-server/compare/v0.11.0...v0.12.0) (2019-10-01)
183 |
184 |
185 | ### Bug Fixes
186 |
187 | * **deps:** bump chokidar from 3.1.1 to 3.2.0 ([bc22406](https://github.com/solufa/axios-mock-server/commit/bc22406))
188 |
189 |
190 | ### Features
191 |
192 | * **main:** ignore directory path of baseURL ([acd6cc1](https://github.com/solufa/axios-mock-server/commit/acd6cc1))
193 | * **mock server:** add restore method ([0883db8](https://github.com/solufa/axios-mock-server/commit/0883db8))
194 |
195 |
196 | ### Refactors
197 |
198 | * **test:** add untransformData ([b626f9c](https://github.com/solufa/axios-mock-server/commit/b626f9c))
199 |
200 | ## [0.11.0](https://github.com/solufa/axios-mock-server/compare/v0.10.0...v0.11.0) (2019-09-29)
201 |
202 |
203 | ### Bug Fixes
204 |
205 | * **deps:** bump chokidar from 3.0.2 to 3.1.1 ([55dd8cd](https://github.com/solufa/axios-mock-server/commit/55dd8cd))
206 | * **jest:** ignore examples ([d2a9c75](https://github.com/solufa/axios-mock-server/commit/d2a9c75))
207 |
208 |
209 | ### Documentation
210 |
211 | * add README.md for Japanese ([5839148](https://github.com/solufa/axios-mock-server/commit/5839148))
212 | * fix examples ([93c90ae](https://github.com/solufa/axios-mock-server/commit/93c90ae))
213 | * translate README.md ([8c97c12](https://github.com/solufa/axios-mock-server/commit/8c97c12))
214 | * update .mockserverrc ([7a963c0](https://github.com/solufa/axios-mock-server/commit/7a963c0))
215 | * update README.md ([f72bea6](https://github.com/solufa/axios-mock-server/commit/f72bea6))
216 | * update README.md ([ffef998](https://github.com/solufa/axios-mock-server/commit/ffef998))
217 |
218 |
219 | ### Features
220 |
221 | * **cli:** infer extension and import type ([2a545d4](https://github.com/solufa/axios-mock-server/commit/2a545d4))
222 | * **log:** add status ([e1e849d](https://github.com/solufa/axios-mock-server/commit/e1e849d))
223 |
224 |
225 | ### Refactors
226 |
227 | * **cli:** clarify codes ([e88a43e](https://github.com/solufa/axios-mock-server/commit/e88a43e))
228 | * **mockserver:** set-client method ([5f4d9c3](https://github.com/solufa/axios-mock-server/commit/5f4d9c3))
229 |
230 | ## [0.10.0](https://github.com/solufa/axios-mock-server/compare/v0.9.0...v0.10.0) (2019-09-11)
231 |
232 |
233 | ### Features
234 |
235 | * **arguments:** add params ([c228a5a](https://github.com/solufa/axios-mock-server/commit/c228a5a))
236 | * **log:** change output format ([72fb5d4](https://github.com/solufa/axios-mock-server/commit/72fb5d4))
237 | * **main:** add log methods ([b49b121](https://github.com/solufa/axios-mock-server/commit/b49b121))
238 | * **response:** add Object style for type error ([4f3d8dc](https://github.com/solufa/axios-mock-server/commit/4f3d8dc))
239 |
240 |
241 | ### Refactors
242 |
243 | * use require function without default in CommonJS ([7fe1c9e](https://github.com/solufa/axios-mock-server/commit/7fe1c9e))
244 |
245 |
246 | ### Tests
247 |
248 | * add case of method is undefined ([9221979](https://github.com/solufa/axios-mock-server/commit/9221979))
249 |
250 | ## [0.9.0](https://github.com/solufa/axios-mock-server/compare/v0.8.1...v0.9.0) (2019-09-08)
251 |
252 |
253 | ### Features
254 |
255 | * **mockserver:** remove 'restore' method ([bb186f9](https://github.com/solufa/axios-mock-server/commit/bb186f9))
256 |
257 | ### [0.8.1](https://github.com/solufa/axios-mock-server/compare/v0.8.0...v0.8.1) (2019-09-07)
258 |
259 |
260 | ### Bug Fixes
261 |
262 | * **CLI:** change path '/aaa/index.js' to '/aaa' ([3667fda](https://github.com/solufa/axios-mock-server/commit/3667fda))
263 |
264 | ## [0.8.0](https://github.com/solufa/axios-mock-server/compare/v0.7.0...v0.8.0) (2019-09-07)
265 |
266 |
267 | ### Bug Fixes
268 |
269 | * **chokidar:** change watcher config ([0552255](https://github.com/solufa/axios-mock-server/commit/0552255))
270 | * **test:** add path pattern ([094d526](https://github.com/solufa/axios-mock-server/commit/094d526))
271 |
272 |
273 | ### Features
274 |
275 | * **toDataURI:** delete from repository ([8aa7223](https://github.com/solufa/axios-mock-server/commit/8aa7223))
276 |
277 | ## [0.7.0](https://github.com/solufa/axios-mock-server/compare/v0.6.0...v0.7.0) (2019-09-04)
278 |
279 |
280 | ### Bug Fixes
281 |
282 | * **adapter:** delete utils.ts ([afdcd82](https://github.com/solufa/axios-mock-server/commit/afdcd82))
283 | * **main:** add values and params ([adb9384](https://github.com/solufa/axios-mock-server/commit/adb9384))
284 |
285 |
286 | ### Features
287 |
288 | * **CLI:** extend multiple input ([bd1cdad](https://github.com/solufa/axios-mock-server/commit/bd1cdad))
289 | * **main:** add factory ([3942401](https://github.com/solufa/axios-mock-server/commit/3942401))
290 | * **main:** delete axios-mock-adapter ([d53aa6c](https://github.com/solufa/axios-mock-server/commit/d53aa6c))
291 |
292 | ## [0.6.0](https://github.com/solufa/axios-mock-server/compare/v0.5.0...v0.6.0) (2019-09-01)
293 |
294 |
295 | ### Features
296 |
297 | * **NeDB:** delete from dependencies ([65db40d](https://github.com/solufa/axios-mock-server/commit/65db40d))
298 |
299 | ## [0.5.0](https://github.com/solufa/axios-mock-server/compare/v0.4.0...v0.5.0) (2019-09-01)
300 |
301 |
302 | ### Bug Fixes
303 |
304 | * **main:** transform request data ([1057694](https://github.com/solufa/axios-mock-server/commit/1057694))
305 |
306 |
307 | ### Features
308 |
309 | * **Nedb:** add async methods ([488e9f6](https://github.com/solufa/axios-mock-server/commit/488e9f6))
310 |
311 | ## [0.4.0](https://github.com/solufa/axios-mock-server/compare/v0.3.0...v0.4.0) (2019-08-31)
312 |
313 |
314 | ### Features
315 |
316 | * **CLI:** add outputExt to config ([965f292](https://github.com/solufa/axios-mock-server/commit/965f292))
317 |
318 | ## [0.3.0](https://github.com/solufa/axios-mock-server/compare/v0.2.0...v0.3.0) (2019-08-30)
319 |
320 |
321 | ### Features
322 |
323 | * **CLI:** add 'watch' and 'build' ([45b41b6](https://github.com/solufa/axios-mock-server/commit/45b41b6))
324 |
325 | ## [0.2.0](https://github.com/solufa/axios-mock-server/compare/v0.1.0...v0.2.0) (2019-08-28)
326 |
327 |
328 | ### Bug Fixes
329 |
330 | * **deps:** [security] bump eslint-utils from 1.4.0 to 1.4.2 ([7f797b5](https://github.com/solufa/axios-mock-server/commit/7f797b5))
331 |
332 |
333 | ### Documentation
334 |
335 | * fix CHANGELOG.md ([8c91ed1](https://github.com/solufa/axios-mock-server/commit/8c91ed1))
336 |
337 |
338 | ### Features
339 |
340 | * **cli:** add command line arguments parser ([9e6e24e](https://github.com/solufa/axios-mock-server/commit/9e6e24e))
341 | * **main:** change function to class ([248cb18](https://github.com/solufa/axios-mock-server/commit/248cb18))
342 |
343 | ## [0.1.0](https://github.com/solufa/axios-mock-server/compare/v0.0.1...v0.1.0) (2019-08-21)
344 |
345 |
346 | ### Documentation
347 |
348 | * add badges ([c7d613b](https://github.com/solufa/axios-mock-server/commit/c7d613b))
349 | * add GitHub templates ([97a257d](https://github.com/solufa/axios-mock-server/commit/97a257d))
350 |
351 |
352 | ### Features
353 |
354 | * **change:** response of HTTP methods ([254c1a9](https://github.com/solufa/axios-mock-server/commit/254c1a9))
355 | * **changing:** separated datastore ([b5bf246](https://github.com/solufa/axios-mock-server/commit/b5bf246))
356 | * **http post:** multipart/form-data ([daaebfa](https://github.com/solufa/axios-mock-server/commit/daaebfa))
357 |
358 | ### 0.0.1 (2019-08-18)
359 |
360 |
361 | ### Bug Fixes
362 |
363 | * test ([7c31ad6](https://github.com/solufa/axios-mock-server/commit/7c31ad6))
364 | * url params ([a5c4631](https://github.com/solufa/axios-mock-server/commit/a5c4631))
365 |
366 |
367 | ### Documentation
368 |
369 | * add README.md ([7e6ed38](https://github.com/solufa/axios-mock-server/commit/7e6ed38))
370 |
371 |
372 | ### Refactors
373 |
374 | * fix implicit 'any' type ([1a9863d](https://github.com/solufa/axios-mock-server/commit/1a9863d))
375 |
--------------------------------------------------------------------------------
/docs/ja/README.md:
--------------------------------------------------------------------------------
1 |
2 | 🇺🇸English |
3 | 🇯🇵日本語
4 |
5 |
6 | axios-mock-server
7 |
8 | [![npm version][badge-npm]][badge-npm-url]
9 | [![npm bundle size][badge-bundlephobia]][badge-bundlephobia-url]
10 | [![CircleCI][badge-ci]][badge-ci-url]
11 | [![Codecov][badge-coverage]][badge-coverage-url]
12 | [![Language grade: JavaScript][badge-lgtm]][badge-lgtm-url]
13 | [![Dependabot Status][badge-dependabot]][dependabot]
14 | [![License][badge-license]][axios-mock-server-license]
15 |
16 | [axios][axios] を使った RESTful API のモックサーバー。
17 |
18 |
19 | 目次
20 |
21 |
26 |
27 | - [特徴](#特徴)
28 | - [入門](#入門)
29 | - [インストール](#インストール)
30 | - [チュートリアル](#チュートリアル)
31 | - [API の作成](#api-の作成)
32 | - [API のビルド](#api-のビルド)
33 | - [axios のモック化](#axios-のモック化)
34 | - [使用例](#使用例)
35 | - [使い方](#使い方)
36 | - [API エンドポイントの作成](#api-エンドポイントの作成)
37 | - [axios との接続](#axios-との接続)
38 | - [デフォルト](#デフォルト)
39 | - [特定のインスタンスのみモックにする](#特定のインスタンスのみモックにする)
40 | - [関数](#関数)
41 | - [`setDelayTime(millisecond: number): void`](#setdelaytimemillisecond-number-void)
42 | - [`enableLog(): void` と `disableLog(): void`](#enablelog-void-と-disablelog-void)
43 | - [TypeScript](#typescript)
44 | - [注意事項](#注意事項)
45 | - [`.gitignore`](#gitignore)
46 | - [`@ts-ignore`, `eslint-disable`](#ts-ignore-eslint-disable)
47 | - [トラブルシューティング](#トラブルシューティング)
48 | - [TypeScript で `The expected type comes from property 'get' which is declared here on type 'MockMethods'` のエラー](#typescript-で-the-expected-type-comes-from-property-get-which-is-declared-here-on-type-mockmethods-のエラー)
49 | - [Command Line Interface のオプション](#command-line-interface-のオプション)
50 | - [設定](#設定)
51 | - [ライセンス](#ライセンス)
52 |
53 |
54 |
55 | ## 特徴
56 |
57 | - `GET`/`POST`/`PUT`/`DELETE` の API エンドポイントを数行で作成できます。
58 | - 専用のサーバーは不要です。
59 | - 静的な [JavaScript][javascript] ファイルとして SPA でも動作します。
60 | - [Node.js][nodejs] の環境でも [axios][axios] をモックにすることができます。
61 | - [Nuxt.js][nuxtjs] 同様のオートルーティング機能があり、パスの記述は必要ありません。
62 | - [TypeScript][typescript] に対応しています。
63 |
64 | ## 入門
65 |
66 | ### インストール
67 |
68 | - [npm][npm] を使ってインストール:
69 |
70 | ```sh
71 | $ npm install axios
72 | $ npm install axios-mock-server --save-dev
73 | ```
74 |
75 | - [Yarn][yarn] を使ってインストール:
76 |
77 | ```sh
78 | $ yarn add axios
79 | $ yarn add axios-mock-server --dev
80 | ```
81 |
82 | ### チュートリアル
83 |
84 | axios-mock-server の最もシンプルな使い方を紹介します。
85 |
86 |
87 | チュートリアルを始める
88 |
89 | #### API の作成
90 |
91 | まずはモックにするファイルを保存する `mocks` ディレクトリを作成します。
92 |
93 | ```sh
94 | $ mkdir mocks
95 | ```
96 |
97 | 次に `mocks` ディレクトリの中に API のエンドポイントとなるファイルを作成します。
98 | `GET` リクエストでユーザーの基本情報を取得する API をモックとして定義してみましょう。
99 |
100 | `mocks/users` ディレクトリを作り `_userId.js` ファイルを作成します。
101 |
102 | ```sh
103 | $ mkdir mocks/users
104 | $ touch mocks/users/_userId.js
105 |
106 | # Windows の場合(コマンド プロンプト)
107 | > mkdir mocks\users
108 | > echo. > mocks\users\_userId.js
109 | ```
110 |
111 | `mocks/users/_userId.js` のファイルには以下の記述を追加します。
112 |
113 |
114 | ```js
115 | // ファイル: 'mocks/users/_userId.js'
116 | const users = [{ id: 0, name: 'foo' }, { id: 1, name: 'bar' }]
117 |
118 | module.exports = {
119 | get({ values }) {
120 | return [200, users.find(user => user.id === values.userId)]
121 | }
122 | }
123 | ```
124 |
125 | axios-mock-server のルーティングは [Nuxt.js][nuxtjs] のルーティングと同じように、`mocks` ディレクトリ内の **[JavaScript][javascript]、[TypeScript][typescript] ファイルのツリー構造に合わせて自動的に生成します。**
126 |
127 | 参考: [Routing - Nuxt.js][nuxtjs-routing]
128 |
129 | つまり `mocks/users/_userId.js` のファイルは `/users/:userId` のパスとして、**動的なルーティングを利用したエンドポイントを定義することができます。**
130 |
131 | #### API のビルド
132 |
133 | axios-mock-server は実行前にルーティングに必要なファイルをビルドして生成する必要があります。
134 |
135 | ```sh
136 | $ node_modules/.bin/axios-mock-server
137 |
138 | # Windows の場合(コマンド プロンプト)
139 | > node_modules\.bin\axios-mock-server
140 | ```
141 |
142 | ビルドが成功すると `$mock.js` ファイルが `mocks` ディレクトリの中に生成されています。
143 |
144 | ```sh
145 | $ cat mocks/\$mock.js
146 | /* eslint-disable */
147 | module.exports = (client) => require('axios-mock-server')([
148 | {
149 | path: '/users/_userId',
150 | methods: require('./users/_userId')
151 | }
152 | ], client)
153 |
154 | # Windows の場合(コマンド プロンプト)
155 | > type mocks\$mock.js
156 | ```
157 |
158 | #### axios のモック化
159 |
160 | 最後に `index.js` ファイルなどで生成した `mocks/$mock.js` ファイルをインポートし、axios-mock-server の引数に渡せば完成です。
161 | axios-mock-server はデフォルトで [axios][axios] のすべての通信をモック化します。
162 |
163 |
164 | ```js
165 | // ファイル: 'index.js'
166 | const axios = require('axios')
167 | const mock = require('./mocks/$mock.js')
168 |
169 | mock()
170 |
171 | axios.get('https://example.com/users/1').then(({ data }) => {
172 | console.log(data)
173 | })
174 | ```
175 |
176 | `index.js` ファイルを実行すると `{ id: 1, name: 'bar' }` が返ってくることがわかります。
177 |
178 | ```sh
179 | $ node index.js
180 | { id: 1, name: 'bar' }
181 | ```
182 |
183 |
184 |
185 | ### 使用例
186 |
187 | axios-mock-server は **ブラウザーでの利用** から **データの永続化**、**`multipart/form-data` 形式の通信** までモックにすることができます。
188 | また、**[Nuxt.js][nuxtjs]([@nuxtjs/axios][nuxtjs-axios]) との連携** も簡単です。
189 |
190 | ソースコードは [examples][axios-mock-server-examples] を参照してください。
191 |
192 |
193 | 使用例の一覧を見る
194 |
195 | - **[browser](https://github.com/solufa/axios-mock-server/tree/develop/examples/browser)**:
196 | ブラウザーでの使用例
197 | - **[node](https://github.com/solufa/axios-mock-server/tree/develop/examples/node)**:
198 | [Node.js][nodejs](CommonJS)での使用例
199 | - **[with-nuxtjs](https://github.com/solufa/axios-mock-server/tree/develop/examples/with-nuxtjs)**:
200 | [Nuxt.js][nuxtjs] での使用例
201 | - **[with-typescript](https://github.com/solufa/axios-mock-server/tree/develop/examples/with-typescript)**:
202 | [TypeScript][typescript] での使用例
203 |
204 | **WIP**
205 |
206 | - with-in-memory-database
207 |
208 |
209 |
210 | ## 使い方
211 |
212 | ### API エンドポイントの作成
213 |
214 |
215 | ```js
216 | const users = [{ id: 0, name: 'foo' }, { id: 1, name: 'bar' }]
217 |
218 | /**
219 | * リクエストで引数として渡される変数の型定義
220 | * @typedef { Object } MockMethodParams
221 | * @property { import('axios').AxiosRequestConfig } config axios のリクエストの設定
222 | * @property {{ [key: string]: string | number }} values リクエストされた URL の動的な値(パスのアンダースコア部分)
223 | * @property {{ [key: string]: any }} params リクエストされた URL のクエリパラメータの値
224 | * @property { any } data POST などで送信されたリクエストデータ
225 | */
226 |
227 | /**
228 | * レスポンスをオブジェクトとして返す場合の型定義
229 | * @typedef { Object } MockResponseObject
230 | * @property { number } status HTTP レスポンスステータスコード
231 | * @property { any? } data レスポンスデータ
232 | * @property {{ [key: string]: any }?} headers レスポンスヘッダー
233 | */
234 |
235 | /**
236 | * レスポンスの型定義
237 | * @typedef { [number, any?, { [key: string]: any }?] | MockResponseObject } MockResponse
238 | */
239 |
240 | export default {
241 | /**
242 | * GET、POST などすべてのメソッドの型は共通です
243 | * @param { MockMethodParams }
244 | * @returns { MockResponse }
245 | */
246 | get({ values }) {
247 | return [200, users.find(user => user.id === values.userId)]
248 | },
249 |
250 | /**
251 | * 非同期にレスポンスを返すこともできます
252 | * @param { MockMethodParams }
253 | * @returns { Promise }
254 | */
255 | async post({ data }) {
256 | await new Promise(resolve => setTimeout(resolve, 1000))
257 |
258 | users.push({
259 | id: users.length,
260 | name: data.name
261 | })
262 |
263 | return { status: 201 }
264 | }
265 | }
266 | ```
267 |
268 | ### axios との接続
269 |
270 | #### デフォルト
271 |
272 | axios-mock-server はデフォルトで [axios][axios] のすべての通信をモック化します。
273 |
274 |
275 | ```js
276 | import axios from 'axios'
277 | import mock from './mocks/$mock.js'
278 |
279 | mock()
280 |
281 | axios.get('https://example.com/api/foo').then(response => {
282 | /* ... */
283 | })
284 | ```
285 |
286 | #### 特定のインスタンスのみモックにする
287 |
288 | [axios のインスタンス][axios-instance] ごとにモック化することもできます。
289 |
290 |
291 | ```js
292 | import axios from 'axios'
293 | import mock from './mocks/$mock.js'
294 |
295 | const client = axios.create({ baseURL: 'https://example.com/api' })
296 |
297 | mock(client)
298 |
299 | client.get('/foo').then(response => {
300 | /* ... */
301 | })
302 |
303 | // axios はモックされません
304 | axios.get('https://example.com/api/foo').catch(error => {
305 | console.log(error.response.status) // 404
306 | })
307 | ```
308 |
309 | ### 関数
310 |
311 | axios-mock-server ではいくつかの組み込み関数を利用することができます。
312 |
313 | #### `setDelayTime(millisecond: number): void`
314 |
315 | レスポンスの遅延をシミュレートします。
316 |
317 |
318 | ```js
319 | import axios from 'axios'
320 | import mock from './mocks/$mock.js'
321 |
322 | mock().setDelayTime(500)
323 |
324 | console.time()
325 | axios.get('https://example.com/api/foo').then(() => {
326 | console.timeEnd() // default: 506.590ms
327 | })
328 | ```
329 |
330 | #### `enableLog(): void` と `disableLog(): void`
331 |
332 | リクエストログの出力を切り替えます。
333 |
334 |
335 | ```js
336 | import axios from 'axios'
337 | import mock from './mocks/$mock.js'
338 |
339 | const mockServer = mock()
340 |
341 | ;(async () => {
342 | // 有効にする
343 | mockServer.enableLog()
344 | await axios.get('/foo', { baseURL: 'https://example.com/api', params: { bar: 'baz' } }) // 標準出力 -> [mock] get: /foo?bar=baz => 200
345 |
346 | // 無効にする
347 | mockServer.disableLog()
348 | await axios.get('/foo', { baseURL: 'https://example.com/api', params: { bar: 'baz' } }) // 標準出力 ->
349 | })()
350 | ```
351 |
352 | ### TypeScript
353 |
354 | axios-mock-server には [TypeScript][typescript] の定義が含まれています。
355 |
356 | ### 注意事項
357 |
358 | #### `.gitignore`
359 |
360 | axios-mock-server がビルドで生成する `$mock.js`、または `$mock.ts` を [Git][git] の監視から除外してください。
361 |
362 | ```sh
363 | $ echo "\$mock.*" >> .gitignore
364 | ```
365 |
366 | #### `@ts-ignore`, `eslint-disable`
367 |
368 | [TypeScript][typescript] のプロジェクトの場合は、`$ mock.ts` をインポートする上の行に `// @ ts-ignore` コメントを追加します。
369 | [typescript-eslint][typescript-eslint] で [`@typescript-eslint/ban-ts-ignore`][typescript-eslint-ban-ts-ignore] ルールが有効になっている場合、[ESLint][eslint] から `// ts-ignore` コメントを除外してください。
370 |
371 |
372 | ```ts
373 | // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
374 | // @ts-ignore: Cannot find module
375 | import mock from './mocks/$mock'
376 | ```
377 |
378 | ## トラブルシューティング
379 |
380 | ### TypeScript で `The expected type comes from property 'get' which is declared here on type 'MockMethods'` のエラー
381 |
382 | [TypeScript][typescript] で非同期にレスポンスを返す場合、レスポンスを配列にしようとすると型が一致しないためにエラーになります。
383 | `MockResponse` をアサーションするか、オブジェクトで返すようにしてください。
384 |
385 | エラーになる例(**axios-mock-server のビルドは通ることに注意してください!**)
386 |
387 |
388 | ```ts
389 | import { MockMethods } from 'axios-mock-server'
390 |
391 | const methods: MockMethods = {
392 | async get() {
393 | await new Promise(resolve => setTimeout(resolve, 100))
394 | return [200, { foo: 'bar' }] // Error
395 | }
396 | }
397 |
398 | export default methods
399 | ```
400 |
401 | `MockResponse` をアサーションして解決します。
402 |
403 |
404 | ```ts
405 | import { MockMethods, MockResponse } from 'axios-mock-server'
406 |
407 | const methods: MockMethods = {
408 | async get() {
409 | await new Promise(resolve => setTimeout(resolve, 100))
410 | return [200, { foo: 'bar' }] as MockResponse // Type safe
411 | }
412 | }
413 |
414 | export default methods
415 | ```
416 |
417 | レスポンスをオブジェクトにすることができればアサーションも不要です。
418 |
419 |
420 | ```ts
421 | import { MockMethods } from 'axios-mock-server'
422 |
423 | const methods: MockMethods = {
424 | async get() {
425 | await new Promise(resolve => setTimeout(resolve, 100))
426 | return { status: 200, data: { foo: 'bar' } } // Type safe
427 | }
428 | }
429 |
430 | export default methods
431 | ```
432 |
433 | ## Command Line Interface のオプション
434 |
435 | Command Line Interface では以下のオプションを指定することができます。
436 |
437 |
438 |
439 |
440 | Option
441 | Type
442 | Default
443 | Description
444 |
445 |
446 |
447 |
448 | --config-c
449 | string
450 | ".mockserverrc"
451 | 設定ファイルまでのパスを指定します。
452 |
453 |
454 | --watch-w
455 |
456 |
457 |
458 | 監視モードを有効にします。
459 | API のエンドポイントとなるファイルの増減に合わせて
460 | $mock.js、または $mock.ts を再生成します。
461 |
462 |
463 |
464 | --version-v
465 |
466 |
467 | axios-mock-server のバージョンを表示します。
468 |
469 |
470 |
471 |
472 | ## 設定
473 |
474 | 設定は `.mockserverrc` ファイルに JSON の構文で記述します。
475 |
476 |
477 |
478 |
479 | Option
480 | Type
481 | Default
482 | Description
483 |
484 |
485 |
486 |
487 | input
488 | string | string[]
489 | "mocks" or "apis"
490 |
491 | API のエンドポイントとなるファイルが保存されているディレクトリを指定します。
492 | 複数のディレクトリを指定した場合は、それぞれのディレクトリに
493 | $mock.js、または $mock.ts を生成します。
494 |
495 |
496 |
497 | outputExt
498 | "js" | "ts"
499 |
500 |
501 | 生成するファイルの拡張子を指定します。
502 | デフォルトは API エンドポイントのファイルの内容から自動で設定します。
503 |
504 |
505 |
506 | outputFilename
507 | string
508 | "$mock.js" or "$mock.ts"
509 | 生成するファイル名を指定します。
510 |
511 |
512 | target
513 | "es6" | "cjs"
514 |
515 |
516 | 生成するモジュールのコードを指定します。
517 | デフォルトは API エンドポイントのファイルの拡張子から自動で設定します。
518 |
519 |
520 |
521 |
522 |
523 | ## ライセンス
524 |
525 | axios-mock-server は [MIT License][axios-mock-server-license] のもとで利用を許諾します。
526 |
527 |
528 |
529 | [axios-mock-server-examples]: https://github.com/solufa/axios-mock-server/tree/develop/examples
530 | [axios-mock-server-license]: https://github.com/solufa/axios-mock-server/blob/develop/LICENSE
531 |
532 |
533 |
534 | [badge-bundlephobia-url]: https://bundlephobia.com/result?p=axios-mock-server@latest
535 | [badge-bundlephobia]: https://img.shields.io/bundlephobia/min/axios-mock-server
536 | [badge-ci-url]: https://circleci.com/gh/solufa/axios-mock-server
537 | [badge-ci]: https://img.shields.io/circleci/build/github/solufa/axios-mock-server.svg?label=test
538 | [badge-coverage-url]: https://codecov.io/gh/solufa/axios-mock-server
539 | [badge-coverage]: https://img.shields.io/codecov/c/github/solufa/axios-mock-server.svg
540 | [badge-dependabot]: https://api.dependabot.com/badges/status?host=github&repo=solufa/axios-mock-server
541 | [badge-lgtm-url]: https://lgtm.com/projects/g/solufa/axios-mock-server/context:javascript
542 | [badge-lgtm]: https://img.shields.io/lgtm/grade/javascript/g/solufa/axios-mock-server.svg
543 | [badge-license]: https://img.shields.io/npm/l/axios-mock-server
544 | [badge-npm-url]: https://www.npmjs.com/package/axios-mock-server
545 | [badge-npm]: https://img.shields.io/npm/v/axios-mock-server
546 |
547 |
548 |
549 | [axios-instance]: https://github.com/axios/axios#creating-an-instance
550 | [axios]: https://github.com/axios/axios
551 | [dependabot]: https://dependabot.com
552 | [eslint]: https://eslint.org
553 | [git]: https://git-scm.com/
554 | [javascript]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
555 | [nodejs]: https://nodejs.org/
556 | [npm]: https://www.npmjs.com/
557 | [nuxtjs-axios]: https://github.com/nuxt-community/axios-module
558 | [nuxtjs-routing]: https://nuxtjs.org/guide/routing
559 | [nuxtjs]: https://nuxtjs.org/
560 | [typescript-eslint-ban-ts-ignore]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-ignore.md
561 | [typescript-eslint]: https://github.com/typescript-eslint/typescript-eslint
562 | [typescript]: https://www.typescriptlang.org/
563 | [yarn]: https://yarnpkg.com/
564 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 🇺🇸English |
3 | 🇯🇵日本語
4 |
5 |
6 | axios-mock-server
7 |
8 | [![npm version][badge-npm]][badge-npm-url]
9 | [![npm bundle size][badge-bundlephobia]][badge-bundlephobia-url]
10 | [![CircleCI][badge-ci]][badge-ci-url]
11 | [![Codecov][badge-coverage]][badge-coverage-url]
12 | [![Language grade: JavaScript][badge-lgtm]][badge-lgtm-url]
13 | [![Dependabot Status][badge-dependabot]][dependabot]
14 | [![License][badge-license]][axios-mock-server-license]
15 |
16 | RESTful mock server using axios.
17 |
18 |
19 | Table of contents
20 |
21 |
26 |
27 | - [Features](#features)
28 | - [Getting Started](#getting-started)
29 | - [Installation](#installation)
30 | - [Tutorial](#tutorial)
31 | - [Create API](#create-api)
32 | - [Build API](#build-api)
33 | - [Mocking Axios](#mocking-axios)
34 | - [Examples](#examples)
35 | - [Usage](#usage)
36 | - [Create an API endpoint](#create-an-api-endpoint)
37 | - [Connect to axios](#connect-to-axios)
38 | - [Default](#default)
39 | - [Each instance](#each-instance)
40 | - [Functions](#functions)
41 | - [`setDelayTime(millisecond: number): void`](#setdelaytimemillisecond-number-void)
42 | - [`enableLog(): void` and `disableLog(): void`](#enablelog-void-and-disablelog-void)
43 | - [TypeScript](#typescript)
44 | - [Cautions](#cautions)
45 | - [`.gitignore`](#gitignore)
46 | - [`@ts-ignore`, `eslint-disable`](#ts-ignore-eslint-disable)
47 | - [Troubleshooting](#troubleshooting)
48 | - [`The expected type comes from property 'get' which is declared here on type 'MockMethods'` error in TypeScript](#the-expected-type-comes-from-property-get-which-is-declared-here-on-type-mockmethods-error-in-typescript)
49 | - [Command Line Interface Options](#command-line-interface-options)
50 | - [Configuration](#configuration)
51 | - [License](#license)
52 |
53 |
54 |
55 | ## Features
56 |
57 | - You can create a `GET`/`POST`/`PUT`/`DELETE` API endpoint in a few lines.
58 | - A dedicated server is not required.
59 | - It works with SPA as a static [JavaScript][javascript] file.
60 | - You can use [axios][axios] as mock-up even in [Node.js][nodejs] environment.
61 | - There is an auto-routing function similar to [Nuxt.js][nuxtjs], and no path description is required.
62 | - Supports [TypeScript][typescript].
63 |
64 | ## Getting Started
65 |
66 | ### Installation
67 |
68 | - Using [npm][npm]:
69 |
70 | ```sh
71 | $ npm install axios
72 | $ npm install axios-mock-server --save-dev
73 | ```
74 |
75 | - Using [Yarn][yarn]:
76 |
77 | ```sh
78 | $ yarn add axios
79 | $ yarn add axios-mock-server --dev
80 | ```
81 |
82 | ### Tutorial
83 |
84 | Introducing the simplest use of axios-mock-server.
85 |
86 |
87 | Start the tutorial
88 |
89 | #### Create API
90 |
91 | First, create a `mocks` directory to store the files you want to mock up.
92 |
93 | ```sh
94 | $ mkdir mocks
95 | ```
96 |
97 | Next, create an API endpoint file in the `mocks` directory.
98 | Let's define a mock API that retrieves basic user information with a `GET` request.
99 |
100 | Create a `mocks/users` directory and create a `_userId.js` file.
101 |
102 | ```sh
103 | $ mkdir mocks/users
104 | $ touch mocks/users/_userId.js
105 |
106 | # If Windows (Command Prompt)
107 | > mkdir mocks\users
108 | > echo. > mocks\users\_userId.js
109 | ```
110 |
111 | Add the following to the `mocks/users/_userId.js` file.
112 |
113 |
114 | ```js
115 | // file: 'mocks/users/_userId.js'
116 | const users = [{ id: 0, name: 'foo' }, { id: 1, name: 'bar' }]
117 |
118 | module.exports = {
119 | get({ values }) {
120 | return [200, users.find(user => user.id === values.userId)]
121 | }
122 | }
123 | ```
124 |
125 | The routing of axios-mock-server is **automatically generated according to the tree structure of [JavaScript][javascript] and [TypeScript][typescript] files** in the `mocks` directory in the same way as the routing of [Nuxt.js][nuxtjs].
126 |
127 | Reference: [Routing - Nuxt.js][nuxtjs-routing]
128 |
129 | In other words, the `mocks/users/_userId.js` file **can define an endpoint using dynamic routing** as the path of `/users/:userId`.
130 |
131 | #### Build API
132 |
133 | axios-mock-server needs to build and generate the necessary files for routing before running.
134 |
135 | ```sh
136 | $ node_modules/.bin/axios-mock-server
137 |
138 | # If Windows (Command Prompt)
139 | > node_modules\.bin\axios-mock-server
140 | ```
141 |
142 | If the build is successful, the `$mock.js` file is generated in the`mocks` directory.
143 |
144 | ```sh
145 | $ cat mocks/\$mock.js
146 | /* eslint-disable */
147 | module.exports = (client) => require('axios-mock-server')([
148 | {
149 | path: '/users/_userId',
150 | methods: require('./users/_userId')
151 | }
152 | ], client)
153 |
154 | # If Windows (Command Prompt)
155 | > type mocks\$mock.js
156 | ```
157 |
158 | #### Mocking Axios
159 |
160 | Finally, import the `mocks/$mock.js` file generated by `index.js` file etc. and pass it to the argument of axios-mock-server.
161 | axios-mock-server will mock up all [axios][axios] communications by default.
162 |
163 |
164 | ```js
165 | // file: 'index.js'
166 | const axios = require('axios')
167 | const mock = require('./mocks/$mock.js')
168 |
169 | mock()
170 |
171 | axios.get('https://example.com/users/1').then(({ data }) => {
172 | console.log(data)
173 | })
174 | ```
175 |
176 | If you run the `index.js` file, you will see that `{ id: 1, name: 'bar' }` is returned.
177 |
178 | ```sh
179 | $ node index.js
180 | { id: 1, name: 'bar' }
181 | ```
182 |
183 |
184 |
185 | ### Examples
186 |
187 | axios-mock-server can be used to mock up **browser usage**, **data persistence** and **`multipart/form-data` format communication**.
188 | It is also easy to link with [Nuxt.js][nuxtjs] ([@nuxtjs/axios][nuxtjs-axios]).
189 |
190 | See [examples][axios-mock-server-examples] for source code.
191 |
192 |
193 | See a list of use cases
194 |
195 | - **[browser](https://github.com/solufa/axios-mock-server/tree/develop/examples/browser)**:
196 | Use in browser
197 | - **[node](https://github.com/solufa/axios-mock-server/tree/develop/examples/node)**:
198 | Use in [Node.js][nodejs] (CommonJS)
199 | - **[with-nuxtjs](https://github.com/solufa/axios-mock-server/tree/develop/examples/with-nuxtjs)**:
200 | Using with a [Nuxt.js][nuxtjs]
201 | - **[with-typescript](https://github.com/solufa/axios-mock-server/tree/develop/examples/with-typescript)**:
202 | Using with a [TypeScript][typescript]
203 |
204 | **WIP**
205 |
206 | - with-in-memory-database
207 |
208 |
209 |
210 | ## Usage
211 |
212 | ### Create an API endpoint
213 |
214 |
215 | ```js
216 | const users = [{ id: 0, name: 'foo' }, { id: 1, name: 'bar' }]
217 |
218 | /**
219 | * Type definitions for variables passed as arguments in requests
220 | * @typedef { Object } MockMethodParams
221 | * @property { import('axios').AxiosRequestConfig } config axios request settings
222 | * @property {{ [key: string]: string | number }} values Dynamic value of the requested URL (underscore part of the path)
223 | * @property {{ [key: string]: any }} params The value of the query parameter for the requested URL
224 | * @property { any } data Request data sent by POST etc.
225 | */
226 |
227 | /**
228 | * Type definition when response is returned as an object
229 | * @typedef { Object } MockResponseObject
230 | * @property { number } status HTTP response status code
231 | * @property { any? } data Response data
232 | * @property {{ [key: string]: any }?} headers Response header
233 | */
234 |
235 | /**
236 | * Response type definition
237 | * @typedef { [number, any?, { [key: string]: any }?] | MockResponseObject } MockResponse
238 | */
239 |
240 | export default {
241 | /**
242 | * All methods such as GET and POST have the same type
243 | * @param { MockMethodParams }
244 | * @returns { MockResponse }
245 | */
246 | get({ values }) {
247 | return [200, users.find(user => user.id === values.userId)]
248 | },
249 |
250 | /**
251 | * You can also return a response asynchronously
252 | * @param { MockMethodParams }
253 | * @returns { Promise }
254 | */
255 | async post({ data }) {
256 | await new Promise(resolve => setTimeout(resolve, 1000))
257 |
258 | users.push({
259 | id: users.length,
260 | name: data.name
261 | })
262 |
263 | return { status: 201 }
264 | }
265 | }
266 | ```
267 |
268 | ### Connect to axios
269 |
270 | #### Default
271 |
272 | axios-mock-server will mock up all [axios][axios] communications by default.
273 |
274 |
275 | ```js
276 | import axios from 'axios'
277 | import mock from './mocks/$mock.js'
278 |
279 | mock()
280 |
281 | axios.get('https://example.com/api/foo').then(response => {
282 | /* ... */
283 | })
284 | ```
285 |
286 | #### Each instance
287 |
288 | You can also mock up each [axios instance][axios-instance].
289 |
290 |
291 | ```js
292 | import axios from 'axios'
293 | import mock from './mocks/$mock.js'
294 |
295 | const client = axios.create({ baseURL: 'https://example.com/api' })
296 |
297 | mock(client)
298 |
299 | client.get('/foo').then(response => {
300 | /* ... */
301 | })
302 |
303 | // axios will not be mocked up
304 | axios.get('https://example.com/api/foo').catch(error => {
305 | console.log(error.response.status) // 404
306 | })
307 | ```
308 |
309 | ### Functions
310 |
311 | axios-mock-server has several built-in functions available.
312 |
313 | #### `setDelayTime(millisecond: number): void`
314 |
315 | Simulate response delay.
316 |
317 |
318 | ```js
319 | import axios from 'axios'
320 | import mock from './mocks/$mock.js'
321 |
322 | mock().setDelayTime(500)
323 |
324 | console.time()
325 | axios.get('https://example.com/api/foo').then(() => {
326 | console.timeEnd() // default: 506.590ms
327 | })
328 | ```
329 |
330 | #### `enableLog(): void` and `disableLog(): void`
331 |
332 | Switch request log output.
333 |
334 |
335 | ```js
336 | import axios from 'axios'
337 | import mock from './mocks/$mock.js'
338 |
339 | const mockServer = mock()
340 |
341 | ;(async () => {
342 | // To enable
343 | mockServer.enableLog()
344 | await axios.get('/foo', { baseURL: 'https://example.com/api', params: { bar: 'baz' } }) // stdout -> [mock] get: /foo?bar=baz => 200
345 |
346 | // To disable
347 | mockServer.disableLog()
348 | await axios.get('/foo', { baseURL: 'https://example.com/api', params: { bar: 'baz' } }) // stdout ->
349 | })()
350 | ```
351 |
352 | ### TypeScript
353 |
354 | axios-mock-server includes [TypeScript][typescript] definitions.
355 |
356 | ### Cautions
357 |
358 | #### `.gitignore`
359 |
360 | Exclude `$mock.js` or `$mock.ts` generated by axios-mock-server in the build from [Git][git] monitoring.
361 |
362 | ```sh
363 | $ echo "\$mock.*" >> .gitignore
364 |
365 | # If Windows (Command Prompt)
366 | > echo $mock.* >> .gitignore
367 | ```
368 |
369 | #### `@ts-ignore`, `eslint-disable`
370 |
371 | For [TypeScript][typescript] projects, add a `// @ ts-ignore` comment to the above line that imports`$ mock.ts`.
372 | If [`@typescript-eslint/ban-ts-ignore`][typescript-eslint-ban-ts-ignore] rule is enabled in [typescript-eslint][typescript-eslint], please exclude the `// @ ts-ignore` comment from [ESLint][eslint].
373 |
374 |
375 | ```ts
376 | // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
377 | // @ts-ignore: Cannot find module
378 | import mock from './mocks/$mock'
379 | ```
380 |
381 | ## Troubleshooting
382 |
383 | ### `The expected type comes from property 'get' which is declared here on type 'MockMethods'` error in TypeScript
384 |
385 | When returning a response asynchronously with [TypeScript][typescript], an error occurs because the type does not match if you try to make the response an array.
386 | Assert `MockResponse` or return it as an object.
387 |
388 | Example of error (**Note that the axios-mock-server build will pass!**)
389 |
390 |
391 | ```ts
392 | import { MockMethods } from 'axios-mock-server'
393 |
394 | const methods: MockMethods = {
395 | async get() {
396 | await new Promise(resolve => setTimeout(resolve, 100))
397 | return [200, { foo: 'bar' }] // Error
398 | }
399 | }
400 |
401 | export default methods
402 | ```
403 |
404 | Resolve by asserting `MockResponse`.
405 |
406 |
407 | ```ts
408 | import { MockMethods, MockResponse } from 'axios-mock-server'
409 |
410 | const methods: MockMethods = {
411 | async get() {
412 | await new Promise(resolve => setTimeout(resolve, 100))
413 | return [200, { foo: 'bar' }] as MockResponse // Type safe
414 | }
415 | }
416 |
417 | export default methods
418 | ```
419 |
420 | If the response can be an object, no assertion is required.
421 |
422 |
423 | ```ts
424 | import { MockMethods } from 'axios-mock-server'
425 |
426 | const methods: MockMethods = {
427 | async get() {
428 | await new Promise(resolve => setTimeout(resolve, 100))
429 | return { status: 200, data: { foo: 'bar' } } // Type safe
430 | }
431 | }
432 |
433 | export default methods
434 | ```
435 |
436 | ## Command Line Interface Options
437 |
438 | The following options can be specified in the Command Line Interface.
439 |
440 |
441 |
442 |
443 | Option
444 | Type
445 | Default
446 | Description
447 |
448 |
449 |
450 |
451 | --config-c
452 | string
453 | ".mockserverrc"
454 | Specify the path to the configuration file.
455 |
456 |
457 | --watch-w
458 |
459 |
460 |
461 | Enable watch mode.
462 | Regenerate $mock.js or $mock.ts according to
463 | the increase / decrease of the API endpoint file.
464 |
465 |
466 |
467 | --version-v
468 |
469 |
470 | Print axios-mock-server version.
471 |
472 |
473 |
474 |
475 | ## Configuration
476 |
477 | Settings are written in `.mockserverrc` file with JSON syntax.
478 |
479 |
480 |
481 |
482 | Option
483 | Type
484 | Default
485 | Description
486 |
487 |
488 |
489 |
490 | input
491 | string | string[]
492 | "mocks" or "apis"
493 |
494 | Specify the directory where the API endpoint file is stored.
495 | If multiple directories are specified, $mock.js or
496 | $mock.ts is generated in each directory.
497 |
498 |
499 |
500 | outputExt
501 | "js" | "ts"
502 |
503 |
504 | Specify the extension of the file to be generated.
505 | The default is set automatically from scripts of the API endpoint file.
506 |
507 |
508 |
509 | outputFilename
510 | string
511 | "$mock.js" or "$mock.ts"
512 | Specify the filename to be generated.
513 |
514 |
515 | target
516 | "es6" | "cjs"
517 |
518 |
519 | Specify the code of the module to be generated.
520 | The default is set automatically from extension of the API endpoint
521 | file.
522 |
523 |
524 |
525 |
526 |
527 | ## License
528 |
529 | axios-mock-server is licensed under a [MIT License][axios-mock-server-license].
530 |
531 |
532 |
533 | [axios-mock-server-examples]: https://github.com/solufa/axios-mock-server/tree/develop/examples
534 | [axios-mock-server-license]: https://github.com/solufa/axios-mock-server/blob/develop/LICENSE
535 |
536 |
537 |
538 | [badge-bundlephobia-url]: https://bundlephobia.com/result?p=axios-mock-server@latest
539 | [badge-bundlephobia]: https://img.shields.io/bundlephobia/min/axios-mock-server
540 | [badge-ci-url]: https://circleci.com/gh/solufa/axios-mock-server
541 | [badge-ci]: https://img.shields.io/circleci/build/github/solufa/axios-mock-server.svg?label=test
542 | [badge-coverage-url]: https://codecov.io/gh/solufa/axios-mock-server
543 | [badge-coverage]: https://img.shields.io/codecov/c/github/solufa/axios-mock-server.svg
544 | [badge-dependabot]: https://api.dependabot.com/badges/status?host=github&repo=solufa/axios-mock-server
545 | [badge-lgtm-url]: https://lgtm.com/projects/g/solufa/axios-mock-server/context:javascript
546 | [badge-lgtm]: https://img.shields.io/lgtm/grade/javascript/g/solufa/axios-mock-server.svg
547 | [badge-license]: https://img.shields.io/npm/l/axios-mock-server
548 | [badge-npm-url]: https://www.npmjs.com/package/axios-mock-server
549 | [badge-npm]: https://img.shields.io/npm/v/axios-mock-server
550 |
551 |
552 |
553 | [axios-instance]: https://github.com/axios/axios#creating-an-instance
554 | [axios]: https://github.com/axios/axios
555 | [dependabot]: https://dependabot.com
556 | [eslint]: https://eslint.org
557 | [git]: https://git-scm.com/
558 | [javascript]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
559 | [nodejs]: https://nodejs.org/
560 | [npm]: https://www.npmjs.com/
561 | [nuxtjs-axios]: https://github.com/nuxt-community/axios-module
562 | [nuxtjs-routing]: https://nuxtjs.org/guide/routing
563 | [nuxtjs]: https://nuxtjs.org/
564 | [typescript-eslint-ban-ts-ignore]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-ignore.md
565 | [typescript-eslint]: https://github.com/typescript-eslint/typescript-eslint
566 | [typescript]: https://www.typescriptlang.org/
567 | [yarn]: https://yarnpkg.com/
568 |
--------------------------------------------------------------------------------