From a7f41f5bb574826ae411e28ba495776442e57614 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 30 Mar 2026 20:15:15 +0200 Subject: [PATCH] chore: remove all old and un-needed files (#10584) * chore: remove all old and un-needed files * chore: fix missing file * chore: fix ref error * chore: add back missing file * chore: incorrect folder location * chore: ignore ts issues --- .github/workflows/update-sponsor-block.yml | 8 +- bin/GithubAPI.js | 157 - bin/RepoBot.js | 134 - bin/actions/notify_published.js | 26 - bin/api.js | 3 - bin/check-build-version.js | 27 - bin/contributors.js | 247 -- bin/helpers/colorize.js | 16 - bin/helpers/parser.js | 13 - bin/injectContributorsList.js | 74 - bin/pr.js | 139 - bin/repo.js | 40 - bin/resolveNPMTag.js | 20 - bin/run-karma-tests.js | 37 - bin/ssl_hotfix.js | 24 - gulpfile.js | 2 +- .../axios-build-instance.js | 4 +- .../{sponsors => }/update-readme-sponsors.mjs | 2 +- templates/contributors.hbs | 13 - templates/pr.hbs | 21 - templates/pr_published.hbs | 1 - templates/prs.hbs | 13 - test/helpers/retry.js | 20 - test/helpers/server.js | 239 -- test/manual/basic.html | 24 - test/manual/cors.html | 23 - test/manual/fixture.json | 3 - test/manual/progress.html | 40 - test/manual/promise.js | 9 - test/module/cjs/index.js | 11 - test/module/cjs/package.json | 15 - test/module/esm/index.js | 16 - test/module/esm/package.json | 16 - test/module/test.js | 184 - test/module/ts-require-default/index.js | 23 - test/module/ts-require-default/package.json | 20 - test/module/ts-require-default/tsconfig.json | 103 - test/module/ts-require/index.js | 23 - test/module/ts-require/package.json | 20 - test/module/ts-require/tsconfig.json | 103 - test/module/ts/index.js | 59 - test/module/ts/package.json | 20 - test/module/ts/tsconfig.json | 103 - test/module/typings/cjs/package.json | 20 - test/module/typings/cjs/tsconfig.json | 6 - test/module/typings/esm/package.json | 21 - test/module/typings/esm/tsconfig.json | 6 - test/specs/__helpers.js | 45 - test/specs/adapter.spec.js | 98 - test/specs/api.spec.js | 81 - test/specs/basicAuth.spec.js | 87 - test/specs/cancel.spec.js | 130 - test/specs/cancel/CancelToken.spec.js | 88 - test/specs/cancel/CanceledError.spec.js | 22 - test/specs/cancel/isCancel.spec.js | 13 - test/specs/core/AxiosError.spec.js | 110 - test/specs/core/buildFullPath.spec.js | 34 - test/specs/core/mergeConfig.spec.js | 348 -- test/specs/core/settle.spec.js | 85 - test/specs/core/transformData.spec.js | 66 - test/specs/defaults.spec.js | 209 -- test/specs/formdata.spec.js | 20 - test/specs/headers.spec.js | 169 - test/specs/helpers/bind.spec.js | 13 - test/specs/helpers/buildURL.spec.js | 126 - test/specs/helpers/combineURLs.spec.js | 24 - test/specs/helpers/cookies.spec.js | 40 - test/specs/helpers/formDataToJSON.spec.js | 72 - test/specs/helpers/isAbsoluteURL.spec.js | 24 - test/specs/helpers/isAxiosError.spec.js | 21 - test/specs/helpers/isURLSameOrigin.spec.js | 12 - test/specs/helpers/parseHeaders.spec.js | 43 - test/specs/helpers/spread.spec.js | 21 - test/specs/helpers/toFormData.spec.js | 126 - test/specs/helpers/validator.spec.js | 56 - test/specs/instance.spec.js | 165 - test/specs/interceptors.spec.js | 697 ---- test/specs/options.spec.js | 151 - test/specs/progress.spec.js | 113 - test/specs/promise.spec.js | 75 - test/specs/requests.spec.js | 547 --- test/specs/transform.spec.js | 238 -- test/specs/utils/endsWith.js | 13 - test/specs/utils/extend.spec.js | 40 - test/specs/utils/forEach.spec.js | 69 - test/specs/utils/isX.spec.js | 80 - test/specs/utils/kindOf.js | 13 - test/specs/utils/kindOfTest.js | 11 - test/specs/utils/merge.spec.js | 97 - test/specs/utils/toArray.js | 13 - test/specs/utils/toFlatObject.js | 13 - test/specs/utils/trim.spec.js | 12 - test/specs/xsrf.spec.js | 148 - test/unit/adapters/adapters.js | 48 - test/unit/adapters/axios.png | Bin 1716 -> 0 bytes test/unit/adapters/cert.pem | 17 - test/unit/adapters/error-details.spec.js | 90 - test/unit/adapters/fetch.js | 541 --- test/unit/adapters/http.js | 3196 ----------------- test/unit/adapters/key.pem | 27 - test/unit/core/Axios.js | 54 - test/unit/core/AxiosHeaders.js | 527 --- test/unit/core/prototypePollution.js | 213 -- test/unit/defaults/transformResponse.js | 67 - test/unit/helpers/composeSignals.js | 44 - .../estimateDataURLDecodedBytes.spec.js | 31 - test/unit/helpers/fromDataURI.js | 13 - test/unit/helpers/parseProtocol.js | 28 - test/unit/helpers/toFormData.js | 133 - test/unit/platform/index.js | 23 - test/unit/regression/SNYK-JS-AXIOS-1038255.js | 75 - test/unit/regression/SNYK-JS-AXIOS-7361793.js | 88 - test/unit/regression/bugs.js | 101 - test/unit/utils/utils.js | 177 - .../module/cjs/tests/helpers/cjs-typing.ts | 1 + .../cjs/tests/helpers/ts-require-default.ts | 1 + .../module/cjs/tests/helpers/ts-require.ts | 1 + .../tests/ts-require-default.module.test.cjs | 2 +- .../cjs/tests/ts-require.module.test.cjs | 2 +- .../module/cjs/tests/typings.module.test.cjs | 2 +- .../module/esm/tests/helpers/esm-functions.ts | 1 + .../module/esm/tests/helpers/esm-index.ts | 1 + tests/module/esm/tests/ts.module.test.js | 2 +- tests/module/esm/tests/typings.module.test.js | 2 +- 124 files changed, 18 insertions(+), 12316 deletions(-) delete mode 100644 bin/GithubAPI.js delete mode 100644 bin/RepoBot.js delete mode 100644 bin/actions/notify_published.js delete mode 100644 bin/api.js delete mode 100644 bin/check-build-version.js delete mode 100644 bin/contributors.js delete mode 100644 bin/helpers/colorize.js delete mode 100644 bin/helpers/parser.js delete mode 100644 bin/injectContributorsList.js delete mode 100644 bin/pr.js delete mode 100644 bin/repo.js delete mode 100644 bin/resolveNPMTag.js delete mode 100644 bin/run-karma-tests.js delete mode 100644 bin/ssl_hotfix.js rename bin/githubAxios.js => scripts/axios-build-instance.js (77%) rename scripts/{sponsors => }/update-readme-sponsors.mjs (98%) delete mode 100644 templates/contributors.hbs delete mode 100644 templates/pr.hbs delete mode 100644 templates/pr_published.hbs delete mode 100644 templates/prs.hbs delete mode 100644 test/helpers/retry.js delete mode 100644 test/helpers/server.js delete mode 100644 test/manual/basic.html delete mode 100644 test/manual/cors.html delete mode 100644 test/manual/fixture.json delete mode 100644 test/manual/progress.html delete mode 100644 test/manual/promise.js delete mode 100644 test/module/cjs/index.js delete mode 100644 test/module/cjs/package.json delete mode 100644 test/module/esm/index.js delete mode 100644 test/module/esm/package.json delete mode 100644 test/module/test.js delete mode 100644 test/module/ts-require-default/index.js delete mode 100644 test/module/ts-require-default/package.json delete mode 100644 test/module/ts-require-default/tsconfig.json delete mode 100644 test/module/ts-require/index.js delete mode 100644 test/module/ts-require/package.json delete mode 100644 test/module/ts-require/tsconfig.json delete mode 100644 test/module/ts/index.js delete mode 100644 test/module/ts/package.json delete mode 100644 test/module/ts/tsconfig.json delete mode 100644 test/module/typings/cjs/package.json delete mode 100644 test/module/typings/cjs/tsconfig.json delete mode 100644 test/module/typings/esm/package.json delete mode 100644 test/module/typings/esm/tsconfig.json delete mode 100644 test/specs/__helpers.js delete mode 100644 test/specs/adapter.spec.js delete mode 100644 test/specs/api.spec.js delete mode 100644 test/specs/basicAuth.spec.js delete mode 100644 test/specs/cancel.spec.js delete mode 100644 test/specs/cancel/CancelToken.spec.js delete mode 100644 test/specs/cancel/CanceledError.spec.js delete mode 100644 test/specs/cancel/isCancel.spec.js delete mode 100644 test/specs/core/AxiosError.spec.js delete mode 100644 test/specs/core/buildFullPath.spec.js delete mode 100644 test/specs/core/mergeConfig.spec.js delete mode 100644 test/specs/core/settle.spec.js delete mode 100644 test/specs/core/transformData.spec.js delete mode 100644 test/specs/defaults.spec.js delete mode 100644 test/specs/formdata.spec.js delete mode 100644 test/specs/headers.spec.js delete mode 100644 test/specs/helpers/bind.spec.js delete mode 100644 test/specs/helpers/buildURL.spec.js delete mode 100644 test/specs/helpers/combineURLs.spec.js delete mode 100644 test/specs/helpers/cookies.spec.js delete mode 100644 test/specs/helpers/formDataToJSON.spec.js delete mode 100644 test/specs/helpers/isAbsoluteURL.spec.js delete mode 100644 test/specs/helpers/isAxiosError.spec.js delete mode 100644 test/specs/helpers/isURLSameOrigin.spec.js delete mode 100644 test/specs/helpers/parseHeaders.spec.js delete mode 100644 test/specs/helpers/spread.spec.js delete mode 100644 test/specs/helpers/toFormData.spec.js delete mode 100644 test/specs/helpers/validator.spec.js delete mode 100644 test/specs/instance.spec.js delete mode 100644 test/specs/interceptors.spec.js delete mode 100644 test/specs/options.spec.js delete mode 100644 test/specs/progress.spec.js delete mode 100644 test/specs/promise.spec.js delete mode 100644 test/specs/requests.spec.js delete mode 100644 test/specs/transform.spec.js delete mode 100644 test/specs/utils/endsWith.js delete mode 100644 test/specs/utils/extend.spec.js delete mode 100644 test/specs/utils/forEach.spec.js delete mode 100644 test/specs/utils/isX.spec.js delete mode 100644 test/specs/utils/kindOf.js delete mode 100644 test/specs/utils/kindOfTest.js delete mode 100644 test/specs/utils/merge.spec.js delete mode 100644 test/specs/utils/toArray.js delete mode 100644 test/specs/utils/toFlatObject.js delete mode 100644 test/specs/utils/trim.spec.js delete mode 100644 test/specs/xsrf.spec.js delete mode 100644 test/unit/adapters/adapters.js delete mode 100644 test/unit/adapters/axios.png delete mode 100644 test/unit/adapters/cert.pem delete mode 100644 test/unit/adapters/error-details.spec.js delete mode 100644 test/unit/adapters/fetch.js delete mode 100644 test/unit/adapters/http.js delete mode 100644 test/unit/adapters/key.pem delete mode 100644 test/unit/core/Axios.js delete mode 100644 test/unit/core/AxiosHeaders.js delete mode 100644 test/unit/core/prototypePollution.js delete mode 100644 test/unit/defaults/transformResponse.js delete mode 100644 test/unit/helpers/composeSignals.js delete mode 100644 test/unit/helpers/estimateDataURLDecodedBytes.spec.js delete mode 100644 test/unit/helpers/fromDataURI.js delete mode 100644 test/unit/helpers/parseProtocol.js delete mode 100644 test/unit/helpers/toFormData.js delete mode 100644 test/unit/platform/index.js delete mode 100644 test/unit/regression/SNYK-JS-AXIOS-1038255.js delete mode 100644 test/unit/regression/SNYK-JS-AXIOS-7361793.js delete mode 100644 test/unit/regression/bugs.js delete mode 100644 test/unit/utils/utils.js rename test/module/typings/cjs/index.ts => tests/module/cjs/tests/helpers/cjs-typing.ts (99%) rename test/module/ts-require-default/index.ts => tests/module/cjs/tests/helpers/ts-require-default.ts (98%) rename test/module/ts-require/index.ts => tests/module/cjs/tests/helpers/ts-require.ts (98%) rename test/module/ts/index.ts => tests/module/esm/tests/helpers/esm-functions.ts (98%) rename test/module/typings/esm/index.ts => tests/module/esm/tests/helpers/esm-index.ts (99%) diff --git a/.github/workflows/update-sponsor-block.yml b/.github/workflows/update-sponsor-block.yml index ac7b549f..09b2d052 100644 --- a/.github/workflows/update-sponsor-block.yml +++ b/.github/workflows/update-sponsor-block.yml @@ -6,7 +6,7 @@ on: types: - webhook schedule: - - cron: "0 1 * * *" + - cron: '0 1 * * *' permissions: contents: write @@ -33,7 +33,7 @@ jobs: run: npm ci - name: Check if sponsors require updates id: sponsors-requires-update - run: node ./scripts/sponsors/update-readme-sponsors.mjs + run: node ./scripts/update-readme-sponsors.mjs - name: Check tracked README sponsor diff id: readme-tracked-change run: | @@ -58,8 +58,8 @@ jobs: with: branch: sponsors delete-branch: true - commit-message: "chore(sponsor): update sponsor block" - title: "chore(docs): update sponsor block" + commit-message: 'chore(sponsor): update sponsor block' + title: 'chore(docs): update sponsor block' body: | **New sponsor block update:** ${{ env.CONTENT }} diff --git a/bin/GithubAPI.js b/bin/GithubAPI.js deleted file mode 100644 index deb02533..00000000 --- a/bin/GithubAPI.js +++ /dev/null @@ -1,157 +0,0 @@ -import util from 'util'; -import cp from 'child_process'; -import { parseVersion } from './helpers/parser.js'; -import githubAxios from './githubAxios.js'; -import memoize from 'memoizee'; - -const exec = util.promisify(cp.exec); - -export default class GithubAPI { - constructor(owner, repo) { - if (!owner) { - throw new Error('repo owner must be specified'); - } - - if (!repo) { - throw new Error('repo must be specified'); - } - - this.repo = repo; - this.owner = owner; - this.axios = githubAxios.create({ - baseURL: `https://api.github.com/repos/${this.owner}/${this.repo}/`, - }); - } - - async createComment(issue, body) { - return (await this.axios.post(`/issues/${issue}/comments`, { body })).data; - } - - async getComments(issue, { desc = false, per_page = 100, page = 1 } = {}) { - return ( - await this.axios.get(`/issues/${issue}/comments`, { - params: { direction: desc ? 'desc' : 'asc', per_page, page }, - }) - ).data; - } - - async getComment(id) { - return (await this.axios.get(`/issues/comments/${id}`)).data; - } - - async updateComment(id, body) { - return (await this.axios.patch(`/issues/comments/${id}`, { body })).data; - } - - async appendLabels(issue, labels) { - return (await this.axios.post(`/issues/${issue}/labels`, { labels })).data; - } - - async getUser(user) { - return (await githubAxios.get(`/users/${user}`)).data; - } - - async isCollaborator(user) { - try { - return (await this.axios.get(`/collaborators/${user}`)).status === 204; - } catch (e) { - // Do nothing - } - } - - async deleteLabel(issue, label) { - return (await this.axios.delete(`/issues/${issue}/labels/${label}`)).data; - } - - async getIssue(issue) { - return (await this.axios.get(`/issues/${issue}`)).data; - } - - async getPR(issue) { - return (await this.axios.get(`/pulls/${issue}`)).data; - } - - async getIssues({ - state = 'open', - labels, - sort = 'created', - desc = false, - per_page = 100, - page = 1, - }) { - return ( - await this.axios.get(`/issues`, { - params: { state, labels, sort, direction: desc ? 'desc' : 'asc', per_page, page }, - }) - ).data; - } - - async updateIssue(issue, data) { - return (await this.axios.patch(`/issues/${issue}`, data)).data; - } - - async closeIssue(issue) { - return this.updateIssue(issue, { - state: 'closed', - }); - } - - async getReleases({ per_page = 30, page = 1 } = {}) { - return (await this.axios.get(`/releases`, { params: { per_page, page } })).data; - } - - async getRelease(release = 'latest') { - return ( - await this.axios.get( - parseVersion(release) ? `/releases/tags/${release}` : `/releases/${release}` - ) - ).data; - } - - async getTags({ per_page = 30, page = 1 } = {}) { - return (await this.axios.get(`/tags`, { params: { per_page, page } })).data; - } - - async reopenIssue(issue) { - return this.updateIssue(issue, { - state: 'open', - }); - } - - static async getTagRef(tag) { - try { - return (await exec(`git show-ref --tags "refs/tags/${tag}"`)).stdout.split(' ')[0]; - } catch (e) { - // Do nothing - } - } - - static async getLatestTag() { - try { - const { stdout } = await exec( - `git for-each-ref refs/tags --sort=-taggerdate --format='%(refname)' --count=1` - ); - - return stdout.split('/').pop(); - } catch (e) { - // Do nothing - } - } - - static normalizeTag(tag) { - return tag ? 'v' + tag.replace(/^v/, '') : ''; - } -} - -const { prototype } = GithubAPI; - -['getUser', 'isCollaborator'].forEach((methodName) => { - prototype[methodName] = memoize(prototype[methodName], { promise: true }); -}); - -['get', 'post', 'put', 'delete', 'isAxiosError'].forEach( - (method) => - (prototype[method] = function (...args) { - return this.axios[method](...args); - }) -); diff --git a/bin/RepoBot.js b/bin/RepoBot.js deleted file mode 100644 index 7edb946b..00000000 --- a/bin/RepoBot.js +++ /dev/null @@ -1,134 +0,0 @@ -import GithubAPI from './GithubAPI.js'; -import api from './api.js'; -import Handlebars from 'handlebars'; -import fs from 'fs/promises'; -import { colorize } from './helpers/colorize.js'; -import { getReleaseInfo } from './contributors.js'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -const NOTIFY_PR_TEMPLATE = path.resolve(__dirname, '../templates/pr_published.hbs'); - -const normalizeTag = (tag) => (tag ? 'v' + tag.replace(/^v/, '') : ''); - -const GITHUB_BOT_LOGIN = 'github-actions[bot]'; - -const skipCollaboratorPRs = true; - -class RepoBot { - constructor(options) { - const { owner, repo, templates } = options || {}; - - this.templates = { - published: NOTIFY_PR_TEMPLATE, - ...templates, - }; - - this.github = api || new GithubAPI(owner, repo); - - this.owner = this.github.owner; - this.repo = this.github.repo; - } - - async addComment(targetId, message) { - return this.github.createComment(targetId, message); - } - - async notifyPRPublished(id, tag) { - let pr; - - try { - pr = await this.github.getPR(id); - } catch (err) { - if (err.response?.status === 404) { - throw new Error(`PR #${id} not found (404)`); - } - - throw err; - } - - tag = normalizeTag(tag); - - const { - merged, - labels, - user: { login, type }, - } = pr; - - const isBot = type === 'Bot'; - - if (!merged) { - return false; - } - - await this.github.appendLabels(id, [tag]); - - if ( - isBot || - labels.find(({ name }) => name === 'automated pr') || - (skipCollaboratorPRs && (await this.github.isCollaborator(login))) - ) { - return false; - } - - const comments = await this.github.getComments(id, { desc: true }); - - const comment = comments.find( - ({ body, user }) => user.login === GITHUB_BOT_LOGIN && body.indexOf('published in') >= 0 - ); - - if (comment) { - console.log(colorize()`Release comment [${comment.html_url}] already exists in #${pr.id}`); - return false; - } - - const author = await this.github.getUser(login); - - author.isBot = isBot; - - const message = await this.constructor.renderTemplate(this.templates.published, { - id, - author, - release: { - tag, - url: `https://github.com/${this.owner}/${this.repo}/releases/tag/${tag}`, - }, - }); - - return await this.addComment(id, message); - } - - async notifyPublishedPRs(tag) { - tag = normalizeTag(tag); - - const release = await getReleaseInfo(tag); - - if (!release) { - throw Error(colorize()`Can't get release info for ${tag}`); - } - - const { merges } = release; - - console.log(colorize()`Found ${merges.length} PRs in ${tag}:`); - - let i = 0; - - for (const pr of merges) { - try { - console.log(colorize()`${i++}) Notify PR #${pr.id}`); - const result = await this.notifyPRPublished(pr.id, tag); - console.log('✔️', result ? 'Label, comment' : 'Label'); - } catch (err) { - console.warn(colorize('green', 'red')`❌ Failed notify PR ${pr.id}: ${err.message}`); - } - } - } - - static async renderTemplate(template, data) { - return Handlebars.compile(String(await fs.readFile(template)))(data); - } -} - -export default RepoBot; diff --git a/bin/actions/notify_published.js b/bin/actions/notify_published.js deleted file mode 100644 index 8e8ec8aa..00000000 --- a/bin/actions/notify_published.js +++ /dev/null @@ -1,26 +0,0 @@ -import minimist from 'minimist'; -import RepoBot from '../RepoBot.js'; -import fs from 'fs/promises'; - -const argv = minimist(process.argv.slice(2)); -console.log(argv); - -let { tag } = argv; - -(async () => { - if (!tag || tag === true) { - const { version } = JSON.parse((await fs.readFile('./package.json')).toString()); - - tag = 'v' + version; - } else if (typeof tag !== 'string') { - throw new Error('tag must be a string'); - } - - const bot = new RepoBot(); - - try { - await bot.notifyPublishedPRs(tag); - } catch (err) { - console.warn('Error:', err.message); - } -})(); diff --git a/bin/api.js b/bin/api.js deleted file mode 100644 index 708e5bfb..00000000 --- a/bin/api.js +++ /dev/null @@ -1,3 +0,0 @@ -import GithubAPI from './GithubAPI.js'; - -export default new GithubAPI('axios', 'axios'); diff --git a/bin/check-build-version.js b/bin/check-build-version.js deleted file mode 100644 index ce0111f0..00000000 --- a/bin/check-build-version.js +++ /dev/null @@ -1,27 +0,0 @@ -import fs from 'fs'; -import assert from 'assert'; -import axios from '../index.js'; -import axiosBuild from '../dist/node/axios.cjs'; - -const { version } = JSON.parse(fs.readFileSync('./package.json')); - -console.log('Checking versions...\n----------------------------'); - -console.log(`Package version: v${version}`); -console.log(`Axios version: v${axios.VERSION}`); -console.log(`Axios build version: v${axiosBuild.VERSION}`); -console.log(`----------------------------`); - -assert.strictEqual( - version, - axios.VERSION, - `Version mismatch between package and Axios ${version} != ${axios.VERSION}` -); - -assert.strictEqual( - version, - axiosBuild.VERSION, - `Version mismatch between package and build ${version} != ${axiosBuild.VERSION}` -); - -console.log('✔️ PASSED\n'); diff --git a/bin/contributors.js b/bin/contributors.js deleted file mode 100644 index 1e6685b9..00000000 --- a/bin/contributors.js +++ /dev/null @@ -1,247 +0,0 @@ -import axios from './githubAxios.js'; -import util from 'util'; -import cp from 'child_process'; -import Handlebars from 'handlebars'; -import fs from 'fs/promises'; -import { colorize } from './helpers/colorize.js'; - -const exec = util.promisify(cp.exec); - -const ONE_MB = 1024 * 1024; - -const removeExtraLineBreaks = (str) => str.replace(/(?:\r\n|\r|\n){3,}/gm, '\r\n\r\n'); - -const cleanTemplate = (template) => - template - .replace(/\n +/g, '\n') - .replace(/^ +/, '') - .replace(/\n\n\n+/g, '\n\n') - .replace(/\n\n$/, '\n'); - -const getUserFromCommit = ((commitCache) => async (sha) => { - try { - if (commitCache[sha] !== undefined) { - return commitCache[sha]; - } - - console.log(colorize()`fetch github commit info (${sha})`); - - const { data } = await axios.get(`https://api.github.com/repos/axios/axios/commits/${sha}`); - - return (commitCache[sha] = { - ...data.commit.author, - ...data.author, - avatar_url_sm: data.author.avatar_url ? data.author.avatar_url + '&s=18' : '', - }); - } catch (err) { - return (commitCache[sha] = null); - } -})({}); - -const getIssueById = ((cache) => async (id) => { - if (cache[id] !== undefined) { - return cache[id]; - } - - try { - const { data } = await axios.get(`https://api.github.com/repos/axios/axios/issues/${id}`); - - return (cache[id] = data); - } catch (err) { - return null; - } -})({}); - -const getUserInfo = ((userCache) => async (userEntry) => { - const { email, commits } = userEntry; - - if (userCache[email] !== undefined) { - return userCache[email]; - } - - console.log(colorize()`fetch github user info [${userEntry.name}]`); - - return (userCache[email] = { - ...userEntry, - ...(await getUserFromCommit(commits[0].hash)), - }); -})({}); - -const deduplicate = (authors) => { - const loginsMap = {}; - const combined = {}; - - const assign = (a, b) => { - const { insertions, _deletions, _points, ...rest } = b; - - Object.assign(a, rest); - - a.insertions += insertions; - a.deletions += insertions; - a.insertions += insertions; - }; - - for (const [email, user] of Object.entries(authors)) { - const { login } = user; - let entry; - - if (login && (entry = loginsMap[login])) { - assign(entry, user); - } else { - login && (loginsMap[login] = user); - combined[email] = user; - } - } - - return combined; -}; - -const getReleaseInfo = ((releaseCache) => async (tag) => { - if (releaseCache[tag] !== undefined) { - return releaseCache[tag]; - } - - const isUnreleasedTag = !tag; - - const version = 'v' + tag.replace(/^v/, ''); - - const command = isUnreleasedTag - ? `npx auto-changelog --unreleased-only --stdout --commit-limit false --template json` - : `npx auto-changelog ${ - version ? '--starting-version ' + version + ' --ending-version ' + version : '' - } --stdout --commit-limit false --template json`; - - console.log(command); - - const { stdout } = await exec(command, { maxBuffer: 10 * ONE_MB }); - - const release = JSON.parse(stdout)[0]; - - if (release) { - const authors = {}; - - const commits = [ - ...release.commits, - ...release.fixes.map((fix) => fix.commit), - ...release.merges.map((fix) => fix.commit), - ].filter(Boolean); - - const commitMergeMap = {}; - - for (const merge of release.merges) { - commitMergeMap[merge.commit.hash] = merge.id; - } - - for (const { hash, author, email, insertions, deletions } of commits) { - const entry = (authors[email] = authors[email] || { - name: author, - prs: [], - email, - commits: [], - insertions: 0, - deletions: 0, - }); - - entry.commits.push({ hash }); - - let pr; - - if ((pr = commitMergeMap[hash])) { - entry.prs.push(pr); - } - - console.log(colorize()`Found commit [${hash}]`); - - entry.displayName = entry.name || author || entry.login; - - entry.github = entry.login ? `https://github.com/${encodeURIComponent(entry.login)}` : ''; - - entry.insertions += insertions; - entry.deletions += deletions; - entry.points = entry.insertions + entry.deletions; - } - - for (const [email, author] of Object.entries(authors)) { - const entry = (authors[email] = await getUserInfo(author)); - - entry.isBot = entry.type === 'Bot'; - } - - release.authors = Object.values(deduplicate(authors)).sort((a, b) => b.points - a.points); - - release.allCommits = commits; - } - - releaseCache[tag] = release; - - return release; -})({}); - -const renderContributorsList = async (tag, template) => { - const release = await getReleaseInfo(tag); - - const compile = Handlebars.compile(String(await fs.readFile(template))); - - const content = compile(release); - - return removeExtraLineBreaks(cleanTemplate(content)); -}; - -const renderPRsList = async ( - tag, - template, - { comments_threshold = 5, awesome_threshold = 5, label = 'add_to_changelog' } = {} -) => { - const release = await getReleaseInfo(tag); - - const prs = {}; - - for (const merge of release.merges) { - const pr = await getIssueById(merge.id); - - if (pr && pr.labels.find(({ name }) => name === label)) { - const { reactions, body } = pr; - prs[pr.number] = pr; - pr.isHot = pr.comments > comments_threshold; - const points = - reactions['+1'] + - reactions['hooray'] + - reactions['rocket'] + - reactions['heart'] + - reactions['laugh'] - - reactions['-1']; - - pr.isAwesome = points > awesome_threshold; - - let match; - - pr.messages = []; - - if (body) { - const reg = /```+changelog\n*(.+?)?\n*```/gms; - - while ((match = reg.exec(body))) { - match[1] && pr.messages.push(match[1]); - } - } - } - } - - release.prs = Object.values(prs); - - const compile = Handlebars.compile(String(await fs.readFile(template))); - - const content = compile(release); - - return removeExtraLineBreaks(cleanTemplate(content)); -}; - -const getTagRef = async (tag) => { - try { - return (await exec(`git show-ref --tags "refs/tags/${tag}"`)).stdout.split(' ')[0]; - } catch (e) { - // Do nothing - } -}; - -export { renderContributorsList, getReleaseInfo, renderPRsList, getTagRef }; diff --git a/bin/helpers/colorize.js b/bin/helpers/colorize.js deleted file mode 100644 index a250b8e7..00000000 --- a/bin/helpers/colorize.js +++ /dev/null @@ -1,16 +0,0 @@ -import chalk from 'chalk'; - -export const colorize = (...colors) => { - if (!colors.length) { - colors = ['green', 'cyan', 'magenta', 'blue', 'yellow', 'red']; - } - - const colorsCount = colors.length; - - return (strings, ...values) => { - const { length } = values; - return strings - .map((str, i) => (i < length ? str + chalk[colors[i % colorsCount]].bold(values[i]) : str)) - .join(''); - }; -}; diff --git a/bin/helpers/parser.js b/bin/helpers/parser.js deleted file mode 100644 index 338e9dda..00000000 --- a/bin/helpers/parser.js +++ /dev/null @@ -1,13 +0,0 @@ -export const matchAll = (text, regexp, cb) => { - let match; - - while ((match = regexp.exec(text))) { - cb(match); - } -}; - -export const parseSection = (body, name, cb) => { - matchAll(body, new RegExp(`^(#+)\\s+${name}?(.*?)^\\1\\s+\\w+`, 'gims'), cb); -}; - -export const parseVersion = (rawVersion) => /^v?(\d+).(\d+).(\d+)/.exec(rawVersion); diff --git a/bin/injectContributorsList.js b/bin/injectContributorsList.js deleted file mode 100644 index d74e7bcf..00000000 --- a/bin/injectContributorsList.js +++ /dev/null @@ -1,74 +0,0 @@ -import fs from 'fs/promises'; -import path from 'path'; -import { renderContributorsList, getTagRef, renderPRsList } from './contributors.js'; -import asyncReplace from 'string-replace-async'; -import { fileURLToPath } from 'url'; -import { colorize } from './helpers/colorize.js'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -const CONTRIBUTORS_TEMPLATE = path.resolve(__dirname, '../templates/contributors.hbs'); -const PRS_TEMPLATE = path.resolve(__dirname, '../templates/prs.hbs'); - -const injectSection = async (name, contributorsRE, injector, infile = '../CHANGELOG.md') => { - console.log(colorize()`Checking ${name} sections in ${infile}`); - - infile = path.resolve(__dirname, infile); - - const content = String(await fs.readFile(infile)); - const headerRE = /^#+\s+\[([-_\d.\w]+)].+?$/gim; - - let tag; - let index = 0; - let isFirstTag = true; - - const newContent = await asyncReplace(content, headerRE, async (match, nextTag, offset) => { - const releaseContent = content.slice(index, offset); - - const hasSection = contributorsRE.test(releaseContent); - - const currentTag = tag; - - tag = nextTag; - index = offset + match.length; - - if (currentTag) { - if (hasSection) { - console.log(colorize()`[${currentTag}]: ✓ OK`); - } else { - const target = isFirstTag && !(await getTagRef(currentTag)) ? '' : currentTag; - - console.log(colorize()`[${currentTag}]: ❌ MISSED` + (!target ? ' (UNRELEASED)' : '')); - - isFirstTag = false; - - console.log(`Generating section...`); - - const section = await injector(target); - - if (!section) { - return match; - } - - console.log(colorize()`\nRENDERED SECTION [${name}] for [${currentTag}]:`); - console.log('-------------BEGIN--------------\n'); - console.log(section); - console.log('--------------END---------------\n'); - - return section + '\n' + match; - } - } - - return match; - }); - - await fs.writeFile(infile, newContent); -}; - -await injectSection('PRs', /^\s*### PRs/im, (tag) => - tag ? '' : renderPRsList(tag, PRS_TEMPLATE, { awesome_threshold: 5, comments_threshold: 7 }) -); - -await injectSection('contributors', /^\s*### Contributors/im, (tag) => - renderContributorsList(tag, CONTRIBUTORS_TEMPLATE) -); diff --git a/bin/pr.js b/bin/pr.js deleted file mode 100644 index 71d66b8b..00000000 --- a/bin/pr.js +++ /dev/null @@ -1,139 +0,0 @@ -import Handlebars from 'handlebars'; -import fs from 'fs/promises'; -import prettyBytes from 'pretty-bytes'; -import { getBlobHistory } from './repo.js'; -import pacote from 'pacote'; -import zlib from 'zlib'; -import tar from 'tar-stream'; -import { Readable } from 'stream'; - -const FILE_SIZE_DIFF_THRESHOLD = 512; // 0.5KB - -const readJSONFile = async (file) => JSON.parse(String(await fs.readFile(file))); - -const { version } = await readJSONFile('./package.json'); - -const parseVersion = (tag) => { - const [, major, minor, patch] = /^v?(\d+)\.(\d+)\.(\d+)/.exec(tag) || []; - return [major, minor, patch]; -}; - -const [MAJOR_NUMBER] = parseVersion(version); - -async function getFilesFromNPM(pkg) { - const tgzData = await pacote.tarball(pkg); // Buffer з npm - const files = {}; - - return new Promise((resolve, reject) => { - const extract = tar.extract(); - - extract.on('entry', (header, stream, next) => { - const buffers = []; - - stream.on('data', (buffer) => { - buffers.push(buffer); - }); - - stream.on('end', () => { - const content = Buffer.concat(buffers); - - const gzipped = zlib.gzipSync(content); - - files[header.name.replace(/^package\//, '')] = { - gzip: gzipped.length, - compressed: header.size ? gzipped.length / header.size : 1, - ...header, - }; - - next(); - }); - }); - - Readable.from(tgzData) - .pipe(zlib.createGunzip()) - .pipe(extract) - .on('error', reject) - .on('finish', () => resolve(files)); - }); -} - -const generateFileReport = async (files, historyCount = 3) => { - const allFilesStat = {}; - const commits = (await getBlobHistory('package.json', historyCount)).filter(({ tag }) => { - return MAJOR_NUMBER === parseVersion(tag)[0]; - }); - const warns = []; - - const npmHistory = {}; - - await Promise.all( - commits.map(async ({ tag }) => { - npmHistory[tag] = await getFilesFromNPM(`axios@${tag.replace(/^v/, '')}`); - }) - ); - - for (const [name, filename] of Object.entries(files)) { - const file = await fs.stat(filename).catch(console.warn); - const gzip = file ? zlib.gzipSync(await fs.readFile(filename)).length : 0; - - const stat = (allFilesStat[filename] = file - ? { - name, - size: file.size, - path: filename, - gzip, - compressed: file.size ? gzip / file.size : 1, - history: commits.map(({ tag }) => { - const files = npmHistory[tag]; - const file = (files && files[filename]) || null; - - return { - tag, - ...file, - }; - }), - } - : null); - - if (stat.history[0]) { - const diff = stat.gzip - stat.history[0].gzip; - - if (diff > FILE_SIZE_DIFF_THRESHOLD) { - warns.push({ - filename, - sizeReport: true, - diff, - percent: stat.gzip ? diff / stat.gzip : 0, - }); - } - } - } - - return { - version, - files: allFilesStat, - warns, - }; -}; - -const generateBody = async ({ files, template = './templates/pr.hbs' } = {}) => { - const data = await generateFileReport(files); - - Handlebars.registerHelper('filesize', (bytes) => - bytes != null ? prettyBytes(bytes) : '' - ); - Handlebars.registerHelper('percent', (value) => - Number.isFinite(value) ? `${(value * 100).toFixed(1)}%` : `---` - ); - - return Handlebars.compile(String(await fs.readFile(template)))(data); -}; - -console.log( - await generateBody({ - files: { - 'Browser build (UMD)': 'dist/axios.min.js', - 'Browser build (ESM)': 'dist/esm/axios.min.js', - }, - }) -); diff --git a/bin/repo.js b/bin/repo.js deleted file mode 100644 index ce191054..00000000 --- a/bin/repo.js +++ /dev/null @@ -1,40 +0,0 @@ -import util from 'util'; -import cp from 'child_process'; - -export const exec = util.promisify(cp.exec); - -export const getBlobSize = async (filepath, sha = 'HEAD') => { - const size = (await exec(`git cat-file -s ${sha}:${filepath}`)).stdout; - - return size ? +size : 0; -}; - -export const getBlobHistory = async (filepath, maxCount = 5) => { - const log = ( - await exec( - `git log --max-count=${maxCount} --no-walk --tags=v* --oneline --format=%H%d -- ${filepath}` - ) - ).stdout; - - const commits = []; - - let match; - - const regexp = /^(\w+) \(tag: (v?[.\d]+)\)$/gm; - - while ((match = regexp.exec(log))) { - commits.push({ - sha: match[1], - tag: match[2], - size: await getBlobSize(filepath, match[1]), - }); - } - - return commits; -}; - -export const getTags = async (pattern = 'v*', sort = '-v:refname') => { - const log = (await exec(`git tag -l ${pattern} --sort=${sort}`)).stdout; - - return log.split(/\r?\n/); -}; diff --git a/bin/resolveNPMTag.js b/bin/resolveNPMTag.js deleted file mode 100644 index fc78758c..00000000 --- a/bin/resolveNPMTag.js +++ /dev/null @@ -1,20 +0,0 @@ -import { exec, getTags } from './repo.js'; -import fs from 'fs'; -import { colorize } from './helpers/colorize.js'; - -const { version } = JSON.parse(fs.readFileSync('./package.json')); - -const [major] = version.split('.'); -const tags = await getTags(); -const latestTag = (tags[0] || '').replace(/^v/, ''); - -const isBeta = !/^v?(\d+).(\d)+.(\d)+$/.test(version); -const isLatest = latestTag === version; - -let tag = isBeta ? 'next' : isLatest ? 'latest' : `v${major}`; - -console.log( - colorize()`Version [${version}] [${isBeta ? 'prerelease' : 'release'}] latest [${latestTag}]=> NPM Tag [${tag}]` -); - -await exec(`echo "tag=${tag}" >> $GITHUB_OUTPUT`); diff --git a/bin/run-karma-tests.js b/bin/run-karma-tests.js deleted file mode 100644 index 178af1ad..00000000 --- a/bin/run-karma-tests.js +++ /dev/null @@ -1,37 +0,0 @@ -import { startTestServer, stopHTTPServer } from '../test/helpers/server.js'; -import { spawn } from 'child_process'; -import chalk from 'chalk'; - -let server; - -async function run() { - console.log(chalk.red.bold(`[ Starting HTTP server... ]`)); - - server = await startTestServer(3000); - - await new Promise((resolve, reject) => { - console.log('Starting karma runner...'); - - const karma = spawn('npx', ['karma', 'start', 'karma.conf.cjs', '--single-run'], { - stdio: 'inherit', - shell: true, - env: { ...process.env, LISTEN_ADDR: '0.0.0.0' }, - }); - - karma.on('exit', (code) => { - code ? reject(new Error(`Karma tests failed with exit code ${code}`)) : resolve(); - }); - }); -} - -(async () => { - try { - await run(); - } finally { - if (server) { - console.log(chalk.red.bold(`[ Terminating HTTP server... ]`)); - - await stopHTTPServer(server); - } - } -})(); diff --git a/bin/ssl_hotfix.js b/bin/ssl_hotfix.js deleted file mode 100644 index 4a671aec..00000000 --- a/bin/ssl_hotfix.js +++ /dev/null @@ -1,24 +0,0 @@ -import { spawn } from 'child_process'; - -const args = process.argv.slice(2); - -console.log(`Running ${args.join(' ')} on ${process.version}\n`); - -const match = /v(\d+)/.exec(process.version); - -const isHotfixNeeded = match && match[1] > 16; - -isHotfixNeeded && console.warn('Setting --openssl-legacy-provider as ssl hotfix'); - -const test = spawn( - 'cross-env', - isHotfixNeeded ? ['NODE_OPTIONS=--openssl-legacy-provider', ...args] : args, - { - shell: true, - stdio: 'inherit', - } -); - -test.on('exit', function (code) { - process.exit(code); -}); diff --git a/gulpfile.js b/gulpfile.js index 439b63e1..f3a5151b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,6 +1,6 @@ import gulp from 'gulp'; import fs from 'fs-extra'; -import axios from './bin/githubAxios.js'; +import axios from './scripts/axios-build-instance.js'; import minimist from 'minimist'; const argv = minimist(process.argv.slice(2)); diff --git a/bin/githubAxios.js b/scripts/axios-build-instance.js similarity index 77% rename from bin/githubAxios.js rename to scripts/axios-build-instance.js index 23a4b9e6..e7447917 100644 --- a/bin/githubAxios.js +++ b/scripts/axios-build-instance.js @@ -1,5 +1,4 @@ import axios from '../index.js'; -import { colorize } from './helpers/colorize.js'; const { GITHUB_TOKEN } = process.env; @@ -12,8 +11,9 @@ export default axios.create({ defaultTransform[0], function (data) { console.log( - colorize()`[${this.method.toUpperCase()}] Request [${new URL(axios.getUri(this)).pathname}]` + `[${this.method.toUpperCase()}] Request [${new URL(axios.getUri(this)).pathname}]` ); + return data; }, ], diff --git a/scripts/sponsors/update-readme-sponsors.mjs b/scripts/update-readme-sponsors.mjs similarity index 98% rename from scripts/sponsors/update-readme-sponsors.mjs rename to scripts/update-readme-sponsors.mjs index f39efb3e..ad50d312 100644 --- a/scripts/sponsors/update-readme-sponsors.mjs +++ b/scripts/update-readme-sponsors.mjs @@ -1,5 +1,5 @@ import fs from 'fs/promises'; -import _axios from '../../index.js'; +import _axios from '../index.js'; const axios = _axios.create({ headers: { diff --git a/templates/contributors.hbs b/templates/contributors.hbs deleted file mode 100644 index 53fb6a36..00000000 --- a/templates/contributors.hbs +++ /dev/null @@ -1,13 +0,0 @@ -{{#if authors}} - ### Contributors to this release - - {{#each authors}} - {{#unless isBot}} - {{#if login}} - - {{#if avatar_url}}avatar{{/if}} [{{displayName}}]({{html_url}} "+{{insertions}}/-{{deletions}} ({{#each prs}}#{{this}} {{/each}})") - {{else}} - - {{displayName}} - {{/if}} - {{/unless}} - {{/each}} -{{/if}} diff --git a/templates/pr.hbs b/templates/pr.hbs deleted file mode 100644 index 2ad96d30..00000000 --- a/templates/pr.hbs +++ /dev/null @@ -1,21 +0,0 @@ -{{#if files}} -### Build info (v{{version}}) - -Client bundles: -{{#each files}} - - {{ name}} ({{ path }}) - - **[ this ]** - {{ filesize size }} (**{{ filesize gzip }}** gzipped, {{percent compressed}}) - {{#each history}} - - **[{{ tag }}]** - {{filesize size}} (**{{ filesize gzip }}** gzipped, {{percent compressed}}) - {{/each}} -{{/each}} -{{/if}} - -{{#if warns}} -#### Warnings - {{#each warns}} - {{#if sizeReport}} - - ⚠️ File `{{filename}}` has increased in size by `{{filesize diff}}` (`+{{percent percent}}`) - {{/if}} - {{/each}} -{{/if}} diff --git a/templates/pr_published.hbs b/templates/pr_published.hbs deleted file mode 100644 index c1c5b504..00000000 --- a/templates/pr_published.hbs +++ /dev/null @@ -1 +0,0 @@ -Hi, @{{ author.login }}! This PR has been published in [{{ release.tag }}]({{ release.url }}) release. Thank you for your contribution ❤️! diff --git a/templates/prs.hbs b/templates/prs.hbs deleted file mode 100644 index 9713a9ce..00000000 --- a/templates/prs.hbs +++ /dev/null @@ -1,13 +0,0 @@ -{{#if prs}} -### PRs -{{#each prs}} - - {{title}} ( [#{{number}}]({{pull_request.url}}) ){{#if isHot}} 🔥{{/if}}{{#if isHot}} 🚀{{/if}} - {{#if messages}} - {{#each messages}} - ``` - {{this}} - ``` - {{/each}} - {{/if}} -{{/each}} -{{/if}} diff --git a/test/helpers/retry.js b/test/helpers/retry.js deleted file mode 100644 index b89c6001..00000000 --- a/test/helpers/retry.js +++ /dev/null @@ -1,20 +0,0 @@ -export const retryNetwork = async (fn, retries = 3, delay = 1000) => { - let attempt = 0, - sleep; - - do { - try { - return await fn(); - } catch (err) { - if (err.code === 'ERR_NETWORK' && attempt++ < retries) { - sleep = attempt * attempt * delay; - console.warn( - `[ERR_NETWORK]: Attempt ${attempt}/${retries}${err.config ? ' [' + err.config.url + ']' : ''} sleep [${sleep}ms]` - ); - await new Promise((resolve) => setTimeout(resolve, sleep)); - } else { - throw err; - } - } - } while (true); -}; diff --git a/test/helpers/server.js b/test/helpers/server.js deleted file mode 100644 index 197ee148..00000000 --- a/test/helpers/server.js +++ /dev/null @@ -1,239 +0,0 @@ -import http from 'http'; -import http2 from 'http2'; -import stream from 'stream'; -import getStream, { getStreamAsBuffer } from 'get-stream'; -import { Throttle } from 'stream-throttle'; -import formidable from 'formidable'; -import selfsigned from 'selfsigned'; - -export const LOCAL_SERVER_URL = 'http://localhost:4444'; - -export const SERVER_HANDLER_STREAM_ECHO = (req, res) => req.pipe(res); - -export const setTimeoutAsync = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - -const certificatePromise = selfsigned.generate(null, { keySize: 2048 }); - -export const startHTTPServer = async (handlerOrOptions, options) => { - const certificate = await certificatePromise; - - const { - handler, - useBuffering = false, - rate = undefined, - port = 4444, - keepAlive = 1000, - useHTTP2, - key = certificate.private, - cert = certificate.cert, - } = Object.assign( - typeof handlerOrOptions === 'function' - ? { - handler: handlerOrOptions, - } - : handlerOrOptions || {}, - options - ); - - return new Promise((resolve, reject) => { - const serverHandler = - handler || - async function (req, res) { - try { - req.headers['content-length'] && - res.setHeader('content-length', req.headers['content-length']); - - let dataStream = req; - - if (useBuffering) { - dataStream = stream.Readable.from(await getStream(req)); - } - - let streams = [dataStream]; - - if (rate) { - streams.push(new Throttle({ rate })); - } - - streams.push(res); - - stream.pipeline(streams, (err) => { - err && console.log('Server warning: ' + err.message); - }); - } catch (err) { - console.warn('HTTP server error:', err); - } - }; - - const server = useHTTP2 - ? http2.createSecureServer({ key, cert }, serverHandler) - : http.createServer(serverHandler); - - const sessions = new Set(); - - if (useHTTP2) { - server.on('session', (session) => { - sessions.add(session); - - session.once('close', () => { - sessions.delete(session); - }); - }); - - server.closeAllSessions = () => { - for (const session of sessions) { - session.destroy(); - } - }; - } else { - server.keepAliveTimeout = keepAlive; - } - - server.listen(port, function (err) { - err ? reject(err) : resolve(this); - }); - }); -}; - -export const stopHTTPServer = async (server, timeout = 10000) => { - if (server) { - if (typeof server.closeAllConnections === 'function') { - server.closeAllConnections(); - } - - if (typeof server.closeAllSessions === 'function') { - server.closeAllSessions(); - } - - await Promise.race([new Promise((resolve) => server.close(resolve)), setTimeoutAsync(timeout)]); - } -}; - -export const handleFormData = (req) => { - return new Promise((resolve, reject) => { - const form = new formidable.IncomingForm(); - - form.parse(req, (err, fields, files) => { - if (err) { - return reject(err); - } - - resolve({ fields, files }); - }); - }); -}; - -export const nodeVersion = process.versions.node.split('.').map((v) => parseInt(v, 10)); - -export const generateReadable = (length = 1024 * 1024, chunkSize = 10 * 1024, sleep = 50) => { - return stream.Readable.from( - (async function* () { - let dataLength = 0; - - while (dataLength < length) { - const leftBytes = length - dataLength; - - const chunk = Buffer.alloc(leftBytes > chunkSize ? chunkSize : leftBytes); - - dataLength += chunk.length; - - yield chunk; - - if (sleep) { - await setTimeoutAsync(sleep); - } - } - })() - ); -}; - -export const makeReadableStream = (chunk = 'chunk', n = 10, timeout = 100) => { - return new ReadableStream( - { - async pull(controller) { - await setTimeoutAsync(timeout); - n-- ? controller.enqueue(chunk) : controller.close(); - }, - }, - { - highWaterMark: 1, - } - ); -}; - -export const makeEchoStream = (echo) => - new WritableStream({ - write(chunk) { - echo && console.log(`Echo chunk`, chunk); - }, - }); - -export const startTestServer = async (port) => { - const handler = async (req) => { - const parsed = new URL(req.url, `http://localhost:${port}`); - - const params = Object.fromEntries(parsed.searchParams); - - let response = { - url: req.url, - pathname: parsed.pathname, - params, - method: req.method, - headers: req.headers, - }; - - const contentType = req.headers['content-type'] || ''; - - const { delay = 0 } = params; - - if (+delay) { - await setTimeoutAsync(+delay); - } - - switch (parsed.pathname.replace(/\/$/, '')) { - case '/echo/json': - default: - if (contentType.startsWith('multipart/')) { - let { fields, files } = await handleFormData(req); - response.form = fields; - response.files = files; - } else { - response.body = (await getStreamAsBuffer(req)).toString('hex'); - } - - return { - body: response, - }; - } - }; - - return await startHTTPServer( - (req, res) => { - // Set CORS headers - res.setHeader('Access-Control-Allow-Origin', `*`); // Allows all origins, or specify a domain like 'http://example.com' - res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); // Allowed HTTP methods - res.setHeader('Access-Control-Allow-Headers', '*'); // Allowed request headers - res.setHeader('Access-Control-Max-Age', '86400'); // Cache preflight requests for 24 hours - - // Handle preflight requests (OPTIONS method) - if (req.method === 'OPTIONS') { - res.writeHead(204); // No content - res.end(); - return; - } - - Promise.resolve(handler(req, res)).then((response) => { - const { status = 200, headers = {}, body } = response || {}; - - res.statusCode = status; - - Object.entries(headers).forEach((header, value) => { - res.setHeader(header, value); - }); - - res.end(JSON.stringify(body, null, 2)); - }); - }, - { port } - ); -}; diff --git a/test/manual/basic.html b/test/manual/basic.html deleted file mode 100644 index 7affac08..00000000 --- a/test/manual/basic.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - An alert should be shown with the {"name":"axios"} - - - - - - - - \ No newline at end of file diff --git a/test/manual/cors.html b/test/manual/cors.html deleted file mode 100644 index 4a85c37d..00000000 --- a/test/manual/cors.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - An alert should be shown with {"status":"ok"} - - - - - - - - \ No newline at end of file diff --git a/test/manual/fixture.json b/test/manual/fixture.json deleted file mode 100644 index 55807659..00000000 --- a/test/manual/fixture.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "axios" -} \ No newline at end of file diff --git a/test/manual/progress.html b/test/manual/progress.html deleted file mode 100644 index 84f3a96b..00000000 --- a/test/manual/progress.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - See your console - - - - - - \ No newline at end of file diff --git a/test/manual/promise.js b/test/manual/promise.js deleted file mode 100644 index 2d483515..00000000 --- a/test/manual/promise.js +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * @overview es6-promise - a tiny implementation of Promises/A+. - * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) - * @license Licensed under MIT license - * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE - * @version 3.0.2 - */ - -(function(){"use strict";function lib$es6$promise$utils$$objectOrFunction(x){return typeof x==="function"||typeof x==="object"&&x!==null}function lib$es6$promise$utils$$isFunction(x){return typeof x==="function"}function lib$es6$promise$utils$$isMaybeThenable(x){return typeof x==="object"&&x!==null}var lib$es6$promise$utils$$_isArray;if(!Array.isArray){lib$es6$promise$utils$$_isArray=function(x){return Object.prototype.toString.call(x)==="[object Array]"}}else{lib$es6$promise$utils$$_isArray=Array.isArray}var lib$es6$promise$utils$$isArray=lib$es6$promise$utils$$_isArray;var lib$es6$promise$asap$$len=0;var lib$es6$promise$asap$$toString={}.toString;var lib$es6$promise$asap$$vertxNext;var lib$es6$promise$asap$$customSchedulerFn;var lib$es6$promise$asap$$asap=function asap(callback,arg){lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len]=callback;lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len+1]=arg;lib$es6$promise$asap$$len+=2;if(lib$es6$promise$asap$$len===2){if(lib$es6$promise$asap$$customSchedulerFn){lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush)}else{lib$es6$promise$asap$$scheduleFlush()}}};function lib$es6$promise$asap$$setScheduler(scheduleFn){lib$es6$promise$asap$$customSchedulerFn=scheduleFn}function lib$es6$promise$asap$$setAsap(asapFn){lib$es6$promise$asap$$asap=asapFn}var lib$es6$promise$asap$$browserWindow=typeof window!=="undefined"?window:undefined;var lib$es6$promise$asap$$browserGlobal=lib$es6$promise$asap$$browserWindow||{};var lib$es6$promise$asap$$BrowserMutationObserver=lib$es6$promise$asap$$browserGlobal.MutationObserver||lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver;var lib$es6$promise$asap$$isNode=typeof process!=="undefined"&&{}.toString.call(process)==="[object process]";var lib$es6$promise$asap$$isWorker=typeof Uint8ClampedArray!=="undefined"&&typeof importScripts!=="undefined"&&typeof MessageChannel!=="undefined";function lib$es6$promise$asap$$useNextTick(){return function(){process.nextTick(lib$es6$promise$asap$$flush)}}function lib$es6$promise$asap$$useVertxTimer(){return function(){lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush)}}function lib$es6$promise$asap$$useMutationObserver(){var iterations=0;var observer=new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush);var node=document.createTextNode("");observer.observe(node,{characterData:true});return function(){node.data=iterations=++iterations%2}}function lib$es6$promise$asap$$useMessageChannel(){var channel=new MessageChannel;channel.port1.onmessage=lib$es6$promise$asap$$flush;return function(){channel.port2.postMessage(0)}}function lib$es6$promise$asap$$useSetTimeout(){return function(){setTimeout(lib$es6$promise$asap$$flush,1)}}var lib$es6$promise$asap$$queue=new Array(1e3);function lib$es6$promise$asap$$flush(){for(var i=0;i - new Promise((resolve, reject) => { - cp.spawn(command, args, { - shell: true, - stdio: 'inherit', - }) - .once('error', reject) - .on('close', (code) => (code ? reject(new Error(`Exit code ${code}`)) : resolve())); - }); - -const { Axios } = axiosFactory; - -const ignoreList = ['default']; - -const instance = axiosFactory.create({}); - -const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - -const remove = async (file) => { - console.log(`✓ Remove entry '${file}'...`); - try { - await sleep(1000); - await fs.remove(file); - } catch (err) { - console.warn(err.message); - } -}; - -describe('module', function () { - before(async () => { - console.log('✓ Creating build backup...'); - await fs.copy('./dist/', BACKUP_PATH); - console.log('✓ Exec build script...'); - await exec('npm run build'); - console.log('✓ Running tests...'); - }); - - after(async () => { - console.log('✓ Restore build from the backup...'); - await fs.copy(BACKUP_PATH, './dist/'); - await remove(BACKUP_PATH); - }); - - describe('export', function () { - it('should have consistent ESM export', function () { - const namedExport = {}; - const factoryExport = {}; - - Object.entries(axiosFactory).forEach(([key, value]) => { - if (!utils.hasOwnProp(Axios, key) && !(key in instance) && ignoreList.indexOf(key) === -1) { - factoryExport[key] = value; - } - }); - - Object.entries(axios).forEach(([key, value]) => { - key !== 'default' && ignoreList.indexOf(key) === -1 && (namedExport[key] = value); - }); - - assert.deepStrictEqual(namedExport, factoryExport); - }); - - describe('CommonJS', () => { - const pkgPath = path.join(__dirname, './cjs'); - - after(async () => { - await remove(path.join(pkgPath, './node_modules')); - }); - - it('should be able to be loaded with require', async function () { - this.timeout(30000); - - await exec(`npm test --prefix ${pkgPath}`); - }); - }); - - describe('ESM', () => { - const pkgPath = path.join(__dirname, './esm'); - - after(async () => { - await remove(path.join(pkgPath, './node_modules')); - }); - - it('should be able to be loaded with import', async function () { - this.timeout(30000); - - await exec(`npm test --prefix ${pkgPath}`); - }); - }); - - describe('TS', () => { - const pkgPath = path.join(__dirname, './ts'); - - after(async () => { - await remove(path.join(pkgPath, './node_modules')); - }); - - it('should be able to be loaded with import', async function () { - this.timeout(30000); - - await exec(`npm test --prefix ${pkgPath}`, {}); - }); - }); - - describe("TS require('axios')", () => { - const pkgPath = path.join(__dirname, './ts-require'); - - after(async () => { - await remove(path.join(pkgPath, './node_modules')); - }); - - it('should be able to be loaded with require', async function () { - this.timeout(30000); - - await exec(`npm test --prefix ${pkgPath}`, {}); - }); - }); - - describe("TS require('axios').default", () => { - const pkgPath = path.join(__dirname, './ts-require-default'); - - after(async () => { - await remove(path.join(pkgPath, './node_modules')); - }); - - it('should be able to be loaded with require', async function () { - this.timeout(30000); - - await exec(`npm test --prefix ${pkgPath}`, {}); - }); - }); - }); - - describe('typings', () => { - describe('ESM', () => { - const pkgPath = path.join(__dirname, './typings/esm'); - - after(async () => { - await remove(path.join(pkgPath, './node_modules')); - }); - - it('should pass types check', async function () { - this.timeout(30000); - - await spawn(`npm test --prefix ${pkgPath}`, [], { - shell: true, - stdio: 'pipe', - }); - }); - }); - - describe('CommonJS', () => { - const pkgPath = path.join(__dirname, './typings/cjs'); - - after(async () => { - await remove(path.join(pkgPath, './node_modules')); - }); - - it('should pass types check', async function () { - this.timeout(30000); - - await spawn(`npm test --prefix ${pkgPath}`, [], { - shell: true, - stdio: 'pipe', - }); - }); - }); - }); -}); diff --git a/test/module/ts-require-default/index.js b/test/module/ts-require-default/index.js deleted file mode 100644 index 196f1d32..00000000 --- a/test/module/ts-require-default/index.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; -const assert = require('assert'); -const axios = require('axios').default; -const { CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData, } = axios; -assert.strictEqual(typeof axios, 'function'); -assert.strictEqual(typeof CanceledError, 'function'); -assert.strictEqual(typeof AxiosError, 'function'); -assert.strictEqual(typeof AxiosHeaders, 'function'); -assert.strictEqual(typeof formToJSON, 'function'); -assert.strictEqual(typeof spread, 'function'); -assert.strictEqual(typeof isAxiosError, 'function'); -assert.strictEqual(typeof isCancel, 'function'); -assert.strictEqual(typeof all, 'function'); -assert.strictEqual(typeof toFormData, 'function'); -assert.strictEqual(typeof axios.CanceledError, 'function'); -assert.strictEqual(typeof axios.AxiosError, 'function'); -assert.strictEqual(typeof axios.AxiosHeaders, 'function'); -assert.strictEqual(typeof axios.formToJSON, 'function'); -assert.strictEqual(typeof axios.spread, 'function'); -assert.strictEqual(typeof axios.isAxiosError, 'function'); -assert.strictEqual(typeof axios.isCancel, 'function'); -assert.strictEqual(typeof axios.all, 'function'); -assert.strictEqual(typeof axios.toFormData, 'function'); diff --git a/test/module/ts-require-default/package.json b/test/module/ts-require-default/package.json deleted file mode 100644 index 9fecadd4..00000000 --- a/test/module/ts-require-default/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "ts-entrypoint-test", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "npm i --no-save --no-package-lock && npm run build && node index.js", - "build": "tsc" - }, - "keywords": [], - "author": "", - "license": "MIT", - "dependencies": { - "@types/node": "^18.11.3", - "axios": "file:../../.." - }, - "devDependencies": { - "typescript": "^5.9.3" - } -} \ No newline at end of file diff --git a/test/module/ts-require-default/tsconfig.json b/test/module/ts-require-default/tsconfig.json deleted file mode 100644 index 0e68f666..00000000 --- a/test/module/ts-require-default/tsconfig.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - - /* Type Checking */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/test/module/ts-require/index.js b/test/module/ts-require/index.js deleted file mode 100644 index 38b7c444..00000000 --- a/test/module/ts-require/index.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; -const assert = require('assert'); -const axios = require('axios'); -const { CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData, } = axios; -assert.strictEqual(typeof axios, 'function'); -assert.strictEqual(typeof CanceledError, 'function'); -assert.strictEqual(typeof AxiosError, 'function'); -assert.strictEqual(typeof AxiosHeaders, 'function'); -assert.strictEqual(typeof formToJSON, 'function'); -assert.strictEqual(typeof spread, 'function'); -assert.strictEqual(typeof isAxiosError, 'function'); -assert.strictEqual(typeof isCancel, 'function'); -assert.strictEqual(typeof all, 'function'); -assert.strictEqual(typeof toFormData, 'function'); -assert.strictEqual(typeof axios.CanceledError, 'function'); -assert.strictEqual(typeof axios.AxiosError, 'function'); -assert.strictEqual(typeof axios.AxiosHeaders, 'function'); -assert.strictEqual(typeof axios.formToJSON, 'function'); -assert.strictEqual(typeof axios.spread, 'function'); -assert.strictEqual(typeof axios.isAxiosError, 'function'); -assert.strictEqual(typeof axios.isCancel, 'function'); -assert.strictEqual(typeof axios.all, 'function'); -assert.strictEqual(typeof axios.toFormData, 'function'); diff --git a/test/module/ts-require/package.json b/test/module/ts-require/package.json deleted file mode 100644 index 9fecadd4..00000000 --- a/test/module/ts-require/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "ts-entrypoint-test", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "npm i --no-save --no-package-lock && npm run build && node index.js", - "build": "tsc" - }, - "keywords": [], - "author": "", - "license": "MIT", - "dependencies": { - "@types/node": "^18.11.3", - "axios": "file:../../.." - }, - "devDependencies": { - "typescript": "^5.9.3" - } -} \ No newline at end of file diff --git a/test/module/ts-require/tsconfig.json b/test/module/ts-require/tsconfig.json deleted file mode 100644 index 0e68f666..00000000 --- a/test/module/ts-require/tsconfig.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - - /* Type Checking */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/test/module/ts/index.js b/test/module/ts/index.js deleted file mode 100644 index f87cb0be..00000000 --- a/test/module/ts/index.js +++ /dev/null @@ -1,59 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const assert_1 = __importDefault(require("assert")); -const axios_1 = __importStar(require("axios")); -assert_1.default.strictEqual(typeof axios_1.default, 'function'); -assert_1.default.strictEqual(typeof axios_1.CanceledError, 'function'); -assert_1.default.strictEqual(typeof axios_1.AxiosError, 'function'); -assert_1.default.strictEqual(typeof axios_1.AxiosHeaders, 'function'); -assert_1.default.strictEqual(typeof axios_1.formToJSON, 'function'); -assert_1.default.strictEqual(typeof axios_1.spread, 'function'); -assert_1.default.strictEqual(typeof axios_1.isAxiosError, 'function'); -assert_1.default.strictEqual(typeof axios_1.isCancel, 'function'); -assert_1.default.strictEqual(typeof axios_1.all, 'function'); -assert_1.default.strictEqual(typeof axios_1.toFormData, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.CanceledError, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.AxiosError, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.AxiosHeaders, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.formToJSON, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.spread, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.isAxiosError, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.isCancel, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.all, 'function'); -assert_1.default.strictEqual(typeof axios_1.default.toFormData, 'function'); diff --git a/test/module/ts/package.json b/test/module/ts/package.json deleted file mode 100644 index 9fecadd4..00000000 --- a/test/module/ts/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "ts-entrypoint-test", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "npm i --no-save --no-package-lock && npm run build && node index.js", - "build": "tsc" - }, - "keywords": [], - "author": "", - "license": "MIT", - "dependencies": { - "@types/node": "^18.11.3", - "axios": "file:../../.." - }, - "devDependencies": { - "typescript": "^5.9.3" - } -} \ No newline at end of file diff --git a/test/module/ts/tsconfig.json b/test/module/ts/tsconfig.json deleted file mode 100644 index 0e68f666..00000000 --- a/test/module/ts/tsconfig.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - - /* Type Checking */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/test/module/typings/cjs/package.json b/test/module/typings/cjs/package.json deleted file mode 100644 index 0043dddf..00000000 --- a/test/module/typings/cjs/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "commonjs-typings-test", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "npm i --no-save --no-package-lock && tsc -v && npm run test:types", - "test:types": "tsc --noEmit" - }, - "keywords": [], - "author": "", - "license": "MIT", - "dependencies": { - "@types/node": "^18.11.3", - "axios": "file:../../../.." - }, - "devDependencies": { - "typescript": "^5.9.3" - } -} \ No newline at end of file diff --git a/test/module/typings/cjs/tsconfig.json b/test/module/typings/cjs/tsconfig.json deleted file mode 100644 index 9d66348d..00000000 --- a/test/module/typings/cjs/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "checkJs": true, - "module": "node16" - } -} diff --git a/test/module/typings/esm/package.json b/test/module/typings/esm/package.json deleted file mode 100644 index 4273f50c..00000000 --- a/test/module/typings/esm/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "esm-typings-test", - "version": "1.0.0", - "description": "", - "main": "index.js", - "type": "module", - "scripts": { - "test:types": "tsc --noEmit", - "test": "npm i --no-save --no-package-lock && tsc -v && npm run test:types" - }, - "keywords": [], - "author": "", - "license": "MIT", - "dependencies": { - "@types/node": "^18.11.3", - "axios": "file:../../../.." - }, - "devDependencies": { - "typescript": "^5.9.3" - } -} \ No newline at end of file diff --git a/test/module/typings/esm/tsconfig.json b/test/module/typings/esm/tsconfig.json deleted file mode 100644 index 9d66348d..00000000 --- a/test/module/typings/esm/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "checkJs": true, - "module": "node16" - } -} diff --git a/test/specs/__helpers.js b/test/specs/__helpers.js deleted file mode 100644 index a00eb2c4..00000000 --- a/test/specs/__helpers.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -import _axios from '../../index.js'; - -window.axios = _axios; - -// Jasmine config -jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; -jasmine.getEnv().defaultTimeoutInterval = 60000; - -window.TEST_SERVER_URL = 'http://localhost:3000'; - -// Get Ajax request using an increasing timeout to retry -window.getAjaxRequest = (function () { - let attempts = 0; - const MAX_ATTEMPTS = 5; - const ATTEMPT_DELAY_FACTOR = 5; - - function getAjaxRequest() { - return new Promise(function (resolve, reject) { - attempts = 0; - attemptGettingAjaxRequest(resolve, reject); - }); - } - - function attemptGettingAjaxRequest(resolve, reject) { - const delay = attempts * attempts * ATTEMPT_DELAY_FACTOR; - - if (attempts++ > MAX_ATTEMPTS) { - reject(new Error('No request was found')); - return; - } - - setTimeout(function () { - const request = jasmine.Ajax.requests.mostRecent(); - if (request) { - resolve(request); - } else { - attemptGettingAjaxRequest(resolve, reject); - } - }, delay); - } - - return getAjaxRequest; -})(); diff --git a/test/specs/adapter.spec.js b/test/specs/adapter.spec.js deleted file mode 100644 index 9e23f274..00000000 --- a/test/specs/adapter.spec.js +++ /dev/null @@ -1,98 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -describe('adapter', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should support custom adapter', function (done) { - axios('/foo', { - adapter: function barAdapter(config) { - return new Promise(function dispatchXhrRequest(resolve) { - const request = new XMLHttpRequest(); - request.open('GET', '/bar'); - - request.onreadystatechange = function () { - resolve({ - config: config, - request: request, - }); - }; - - request.send(null); - }); - }, - }).catch(done); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/bar'); - done(); - }); - }); - - it('should execute adapter code synchronously', function (done) { - let asyncFlag = false; - axios('/foo', { - adapter: function barAdapter(config) { - return new Promise(function dispatchXhrRequest(resolve) { - const request = new XMLHttpRequest(); - request.open('GET', '/bar'); - - request.onreadystatechange = function () { - resolve({ - config: config, - request: request, - }); - }; - - expect(asyncFlag).toBe(false); - request.send(null); - }); - }, - }).catch(done); - - asyncFlag = true; - - getAjaxRequest().then(function () { - done(); - }); - }); - - it('should execute adapter code asynchronously when interceptor is present', function (done) { - let asyncFlag = false; - - axios.interceptors.request.use(function (config) { - config.headers.async = 'async it!'; - return config; - }); - - axios('/foo', { - adapter: function barAdapter(config) { - return new Promise(function dispatchXhrRequest(resolve) { - const request = new XMLHttpRequest(); - request.open('GET', '/bar'); - - request.onreadystatechange = function () { - resolve({ - config: config, - request: request, - }); - }; - - expect(asyncFlag).toBe(true); - request.send(null); - }); - }, - }).catch(done); - - asyncFlag = true; - - getAjaxRequest().then(function () { - done(); - }); - }); -}); diff --git a/test/specs/api.spec.js b/test/specs/api.spec.js deleted file mode 100644 index 767474ed..00000000 --- a/test/specs/api.spec.js +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint-env mocha */ -describe('static api', function () { - it('should have request method helpers', function () { - expect(typeof axios.request).toEqual('function'); - expect(typeof axios.get).toEqual('function'); - expect(typeof axios.head).toEqual('function'); - expect(typeof axios.options).toEqual('function'); - expect(typeof axios.delete).toEqual('function'); - expect(typeof axios.post).toEqual('function'); - expect(typeof axios.put).toEqual('function'); - expect(typeof axios.patch).toEqual('function'); - }); - - it('should have promise method helpers', function () { - const promise = axios('/test'); - - expect(typeof promise.then).toEqual('function'); - expect(typeof promise.catch).toEqual('function'); - }); - - it('should have defaults', function () { - expect(typeof axios.defaults).toEqual('object'); - expect(typeof axios.defaults.headers).toEqual('object'); - }); - - it('should have interceptors', function () { - expect(typeof axios.interceptors.request).toEqual('object'); - expect(typeof axios.interceptors.response).toEqual('object'); - }); - - it('should have all/spread helpers', function () { - expect(typeof axios.all).toEqual('function'); - expect(typeof axios.spread).toEqual('function'); - }); - - it('should have factory method', function () { - expect(typeof axios.create).toEqual('function'); - }); - - it('should have CanceledError, CancelToken, and isCancel properties', function () { - expect(typeof axios.Cancel).toEqual('function'); - expect(typeof axios.CancelToken).toEqual('function'); - expect(typeof axios.isCancel).toEqual('function'); - }); - - it('should have getUri method', function () { - expect(typeof axios.getUri).toEqual('function'); - }); - - it('should have isAxiosError properties', function () { - expect(typeof axios.isAxiosError).toEqual('function'); - }); - - it('should have mergeConfig properties', function () { - expect(typeof axios.mergeConfig).toEqual('function'); - }); - - it('should have getAdapter properties', function () { - expect(typeof axios.getAdapter).toEqual('function'); - }); -}); - -describe('instance api', function () { - const instance = axios.create(); - - it('should have request methods', function () { - expect(typeof instance.request).toEqual('function'); - expect(typeof instance.get).toEqual('function'); - expect(typeof instance.options).toEqual('function'); - expect(typeof instance.head).toEqual('function'); - expect(typeof instance.delete).toEqual('function'); - expect(typeof instance.post).toEqual('function'); - expect(typeof instance.put).toEqual('function'); - expect(typeof instance.patch).toEqual('function'); - }); - - it('should have interceptors', function () { - expect(typeof instance.interceptors.request).toEqual('object'); - expect(typeof instance.interceptors.response).toEqual('object'); - }); -}); diff --git a/test/specs/basicAuth.spec.js b/test/specs/basicAuth.spec.js deleted file mode 100644 index 4c903421..00000000 --- a/test/specs/basicAuth.spec.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -import axios from '../../index'; - -function validateInvalidCharacterError(error) { - expect(/character/i.test(error.message)).toEqual(true); -} - -describe('basicAuth', function () { - // Validate an invalid character error - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should accept HTTP Basic auth with username/password', function (done) { - axios('/foo', { - auth: { - username: 'Aladdin', - password: 'open sesame', - }, - }); - - setTimeout(function () { - const request = jasmine.Ajax.requests.mostRecent(); - - expect(request.requestHeaders['Authorization']).toEqual('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='); - done(); - }, 100); - }); - - it('should accept HTTP Basic auth credentials without the password parameter', function (done) { - axios('/foo', { - auth: { - username: 'Aladdin', - }, - }); - - setTimeout(function () { - const request = jasmine.Ajax.requests.mostRecent(); - - expect(request.requestHeaders['Authorization']).toEqual('Basic QWxhZGRpbjo='); - done(); - }, 100); - }); - - it('should accept HTTP Basic auth credentials with non-Latin1 characters in password', function (done) { - axios('/foo', { - auth: { - username: 'Aladdin', - password: 'open ßç£☃sesame', - }, - }); - - setTimeout(function () { - const request = jasmine.Ajax.requests.mostRecent(); - - expect(request.requestHeaders['Authorization']).toEqual( - 'Basic QWxhZGRpbjpvcGVuIMOfw6fCo+KYg3Nlc2FtZQ==' - ); - done(); - }, 100); - }); - - it('should fail to encode HTTP Basic auth credentials with non-Latin1 characters in username', function (done) { - axios('/foo', { - auth: { - username: 'Aladßç£☃din', - password: 'open sesame', - }, - }) - .then(function (response) { - done( - new Error( - 'Should not succeed to make a HTTP Basic auth request with non-latin1 chars in credentials.' - ) - ); - }) - .catch(function (error) { - validateInvalidCharacterError(error); - done(); - }); - }); -}); diff --git a/test/specs/cancel.spec.js b/test/specs/cancel.spec.js deleted file mode 100644 index a0b3d248..00000000 --- a/test/specs/cancel.spec.js +++ /dev/null @@ -1,130 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -const Cancel = axios.Cancel; -const CancelToken = axios.CancelToken; -import { AbortController as _AbortController } from 'abortcontroller-polyfill/dist/cjs-ponyfill.js'; - -const envAbortController = - typeof AbortController === 'function' ? AbortController : _AbortController; - -describe('cancel', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - describe('when called before sending request', function () { - it('rejects Promise with a CanceledError object', function (done) { - const source = CancelToken.source(); - source.cancel('Operation has been canceled.'); - axios - .get('/foo', { - cancelToken: source.token, - }) - .catch(function (thrown) { - expect(thrown).toEqual(jasmine.any(Cancel)); - expect(thrown.message).toBe('Operation has been canceled.'); - done(); - }); - }); - }); - - describe('when called after request has been sent', function () { - it('rejects Promise with a CanceledError object', function (done) { - const source = CancelToken.source(); - axios - .get('/foo/bar', { - cancelToken: source.token, - }) - .catch(function (thrown) { - expect(thrown).toEqual(jasmine.any(Cancel)); - expect(thrown.message).toBe('Operation has been canceled.'); - done(); - }); - - getAjaxRequest().then(function (request) { - // call cancel() when the request has been sent, but a response has not been received - source.cancel('Operation has been canceled.'); - request.respondWith({ - status: 200, - responseText: 'OK', - }); - }); - }); - - it('calls abort on request object', function (done) { - const source = CancelToken.source(); - let request; - axios - .get('/foo/bar', { - cancelToken: source.token, - }) - .catch(function () { - // jasmine-ajax sets statusText to 'abort' when request.abort() is called - expect(request.statusText).toBe('abort'); - done(); - }); - - getAjaxRequest().then(function (req) { - // call cancel() when the request has been sent, but a response has not been received - source.cancel(); - request = req; - }); - }); - }); - - // describe('when called after response has been received', function() { - // // https://github.com/axios/axios/issues/482 - // it('does not cause unhandled rejection', function(done) { - // var source = CancelToken.source(); - // axios.get('/foo', { - // cancelToken: source.token - // }).then(function() { - // window.addEventListener('unhandledrejection', function() { - // done.fail('Unhandled rejection.'); - // }); - // source.cancel(); - // setTimeout(done, 100); - // }); - - // getAjaxRequest().then(function(request) { - // request.respondWith({ - // status: 200, - // responseText: 'OK' - // }); - // }); - // }); - // }); - - it('it should support cancellation using AbortController signal', function (done) { - const controller = new envAbortController(); - - axios - .get('/foo/bar', { - signal: controller.signal, - }) - .then( - function () { - done.fail('Has not been canceled'); - }, - function (thrown) { - expect(thrown).toEqual(jasmine.any(Cancel)); - done(); - } - ); - - getAjaxRequest().then(function (request) { - // call cancel() when the request has been sent, but a response has not been received - controller.abort(); - setTimeout(function () { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - }, 0); - }); - }); -}); diff --git a/test/specs/cancel/CancelToken.spec.js b/test/specs/cancel/CancelToken.spec.js deleted file mode 100644 index 66e125ae..00000000 --- a/test/specs/cancel/CancelToken.spec.js +++ /dev/null @@ -1,88 +0,0 @@ -/* eslint-env mocha */ -import CancelToken from '../../../lib/cancel/CancelToken'; -import CanceledError from '../../../lib/cancel/CanceledError'; - -describe('CancelToken', function () { - describe('constructor', function () { - it('throws when executor is not specified', function () { - expect(function () { - new CancelToken(); - }).toThrowError(TypeError, 'executor must be a function.'); - }); - - it('throws when executor is not a function', function () { - expect(function () { - new CancelToken(123); - }).toThrowError(TypeError, 'executor must be a function.'); - }); - }); - - describe('reason', function () { - it('returns a CanceledError if cancellation has been requested', function () { - let cancel; - const token = new CancelToken(function (c) { - cancel = c; - }); - cancel('Operation has been canceled.'); - expect(token.reason).toEqual(jasmine.any(CanceledError)); - expect(token.reason.message).toBe('Operation has been canceled.'); - }); - - it('returns undefined if cancellation has not been requested', function () { - const token = new CancelToken(function () {}); - expect(token.reason).toBeUndefined(); - }); - }); - - describe('promise', function () { - it('returns a Promise that resolves when cancellation is requested', function (done) { - let cancel; - const token = new CancelToken(function (c) { - cancel = c; - }); - token.promise.then(function onFulfilled(value) { - expect(value).toEqual(jasmine.any(CanceledError)); - expect(value.message).toBe('Operation has been canceled.'); - done(); - }); - cancel('Operation has been canceled.'); - }); - }); - - describe('throwIfRequested', function () { - it('throws if cancellation has been requested', function () { - // Note: we cannot use expect.toThrowError here as CanceledError does not inherit from Error - let cancel; - const token = new CancelToken(function (c) { - cancel = c; - }); - cancel('Operation has been canceled.'); - try { - token.throwIfRequested(); - fail('Expected throwIfRequested to throw.'); - } catch (thrown) { - if (!(thrown instanceof CanceledError)) { - fail('Expected throwIfRequested to throw a CanceledError, but it threw ' + thrown + '.'); - } - expect(thrown.message).toBe('Operation has been canceled.'); - } - }); - - it('does not throw if cancellation has not been requested', function () { - const token = new CancelToken(function () {}); - token.throwIfRequested(); - }); - }); - - describe('source', function () { - it('returns an object containing token and cancel function', function () { - const source = CancelToken.source(); - expect(source.token).toEqual(jasmine.any(CancelToken)); - expect(source.cancel).toEqual(jasmine.any(Function)); - expect(source.token.reason).toBeUndefined(); - source.cancel('Operation has been canceled.'); - expect(source.token.reason).toEqual(jasmine.any(CanceledError)); - expect(source.token.reason.message).toBe('Operation has been canceled.'); - }); - }); -}); diff --git a/test/specs/cancel/CanceledError.spec.js b/test/specs/cancel/CanceledError.spec.js deleted file mode 100644 index 7b9c39db..00000000 --- a/test/specs/cancel/CanceledError.spec.js +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-env mocha */ -import CanceledError from '../../../lib/cancel/CanceledError'; - -describe('Cancel', function () { - describe('toString', function () { - it('returns correct result when message is not specified', function () { - const cancel = new CanceledError(); - expect(cancel.toString()).toBe('CanceledError: canceled'); - }); - - it('returns correct result when message is specified', function () { - const cancel = new CanceledError('Operation has been canceled.'); - expect(cancel.toString()).toBe('CanceledError: Operation has been canceled.'); - }); - }); - it('should be a native error as checked by the NodeJS `isNativeError` function', function () { - if (typeof process !== 'undefined' && process.release.name === 'node') { - let { isNativeError } = require('node:util/types'); - expect(isNativeError(new CanceledError('My Canceled Error'))).toBeTruthy(); - } - }); -}); diff --git a/test/specs/cancel/isCancel.spec.js b/test/specs/cancel/isCancel.spec.js deleted file mode 100644 index 159738dc..00000000 --- a/test/specs/cancel/isCancel.spec.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -import isCancel from '../../../lib/cancel/isCancel'; -import CanceledError from '../../../lib/cancel/CanceledError'; - -describe('isCancel', function () { - it('returns true if value is a CanceledError', function () { - expect(isCancel(new CanceledError())).toBe(true); - }); - - it('returns false if value is not a CanceledError', function () { - expect(isCancel({ foo: 'bar' })).toBe(false); - }); -}); diff --git a/test/specs/core/AxiosError.spec.js b/test/specs/core/AxiosError.spec.js deleted file mode 100644 index 409f2017..00000000 --- a/test/specs/core/AxiosError.spec.js +++ /dev/null @@ -1,110 +0,0 @@ -/* eslint-env mocha */ -import AxiosError from '../../../lib/core/AxiosError'; - -describe('core::AxiosError', function () { - it('should create an Error with message, config, code, request, response, stack and isAxiosError', function () { - const request = { path: '/foo' }; - const response = { status: 200, data: { foo: 'bar' } }; - const error = new AxiosError('Boom!', 'ESOMETHING', { foo: 'bar' }, request, response); - expect(error instanceof Error).toBe(true); - expect(error.message).toBe('Boom!'); - expect(error.config).toEqual({ foo: 'bar' }); - expect(error.code).toBe('ESOMETHING'); - expect(error.request).toBe(request); - expect(error.response).toBe(response); - expect(error.isAxiosError).toBe(true); - expect(error.stack).toBeDefined(); - }); - it('should create an Error that can be serialized to JSON', function () { - // Attempting to serialize request and response results in - // TypeError: Converting circular structure to JSON - const request = { path: '/foo' }; - const response = { status: 200, data: { foo: 'bar' } }; - const error = new AxiosError('Boom!', 'ESOMETHING', { foo: 'bar' }, request, response); - const json = error.toJSON(); - expect(json.message).toBe('Boom!'); - expect(json.config).toEqual({ foo: 'bar' }); - expect(json.code).toBe('ESOMETHING'); - expect(json.status).toBe(200); - expect(json.request).toBe(undefined); - expect(json.response).toBe(undefined); - }); - - describe('core::createError.from', function () { - it('should add config, config, request and response to error', function () { - const error = new Error('Boom!'); - const request = { path: '/foo' }; - const response = { status: 200, data: { foo: 'bar' } }; - - const axiosError = AxiosError.from(error, 'ESOMETHING', { foo: 'bar' }, request, response); - expect(axiosError.config).toEqual({ foo: 'bar' }); - expect(axiosError.code).toBe('ESOMETHING'); - expect(axiosError.request).toBe(request); - expect(axiosError.response).toBe(response); - expect(axiosError.isAxiosError).toBe(true); - }); - - it('should return error', function () { - const error = new Error('Boom!'); - expect( - AxiosError.from(error, 'ESOMETHING', { foo: 'bar' }) instanceof AxiosError - ).toBeTruthy(); - }); - - it('should preserve status property from original error when response is not provided', function () { - const error = new Error('Network Error'); - error.status = 404; - - const axiosError = AxiosError.from(error, 'ERR_NETWORK', { foo: 'bar' }); - expect(axiosError.status).toBe(404); - }); - - it('should use response.status over error.status when response is provided', function () { - const error = new Error('Error'); - error.status = 500; - const response = { status: 404 }; - - const axiosError = AxiosError.from(error, 'ERR_BAD_REQUEST', {}, null, response); - expect(axiosError.status).toBe(404); - }); - }); - - it('should be a native error as checked by the NodeJS `isNativeError` function', function () { - if (typeof process !== 'undefined' && process.release.name === 'node') { - let { isNativeError } = require('node:util/types'); - expect(isNativeError(new AxiosError('My Axios Error'))).toBeTruthy(); - } - }); - - it('should create an error using one of the static class properties as an error code', function () { - const myError = new AxiosError('My Axios Error', AxiosError.ECONNABORTED); - expect(myError.code).toEqual(AxiosError.ECONNABORTED); - }); - - it('should have status property when response was passed to the constructor', () => { - const err = new AxiosError('test', 'foo', {}, {}, { status: 400 }); - expect(err.status).toBe(400); - }); - - it('should have message property as enumerable for backward compatibility', () => { - const err = new AxiosError('Test error message', 'ERR_TEST', { foo: 'bar' }); - - // Test Object.keys() includes message - const keys = Object.keys(err); - expect(keys).toContain('message'); - - // Test Object.entries() includes message - const entries = Object.entries(err); - const messageEntry = entries.find(([key]) => key === 'message'); - expect(messageEntry).toBeDefined(); - expect(messageEntry[1]).toBe('Test error message'); - - // Test spread operator includes message - const spread = { ...err }; - expect(spread.message).toBe('Test error message'); - - // Verify message descriptor is enumerable - const descriptor = Object.getOwnPropertyDescriptor(err, 'message'); - expect(descriptor.enumerable).toBe(true); - }); -}); diff --git a/test/specs/core/buildFullPath.spec.js b/test/specs/core/buildFullPath.spec.js deleted file mode 100644 index a6d8048d..00000000 --- a/test/specs/core/buildFullPath.spec.js +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-env mocha */ -import buildFullPath from '../../../lib/core/buildFullPath'; - -describe('helpers::buildFullPath', function () { - it('should combine URLs when the requestedURL is relative', function () { - expect(buildFullPath('https://api.github.com', '/users')).toBe('https://api.github.com/users'); - }); - - it('should not combine the URLs when the requestedURL is absolute', function () { - expect(buildFullPath('https://api.github.com', 'https://api.example.com/users')).toBe( - 'https://api.example.com/users' - ); - }); - - it('should combine the URLs when the requestedURL is absolute and allowAbsoluteUrls is false', function () { - expect(buildFullPath('https://api.github.com', 'https://api.example.com/users', false)).toBe( - 'https://api.github.com/https://api.example.com/users' - ); - }); - - it('should not combine the URLs when the requestedURL is absolute, allowAbsoluteUrls is false, and the baseURL is not configured', function () { - expect(buildFullPath(undefined, 'https://api.example.com/users', false)).toBe( - 'https://api.example.com/users' - ); - }); - - it('should not combine URLs when the baseURL is not configured', function () { - expect(buildFullPath(undefined, '/users')).toBe('/users'); - }); - - it('should combine URLs when the baseURL and requestedURL are relative', function () { - expect(buildFullPath('/api', '/users')).toBe('/api/users'); - }); -}); diff --git a/test/specs/core/mergeConfig.spec.js b/test/specs/core/mergeConfig.spec.js deleted file mode 100644 index 45110274..00000000 --- a/test/specs/core/mergeConfig.spec.js +++ /dev/null @@ -1,348 +0,0 @@ -/* eslint-env mocha */ -import defaults from '../../../lib/defaults'; -import mergeConfig from '../../../lib/core/mergeConfig'; -import { AxiosHeaders } from '../../../index.js'; - -describe('core::mergeConfig', function () { - it('should accept undefined for second argument', function () { - expect(mergeConfig(defaults, undefined)).toEqual(defaults); - }); - - it('should accept an object for second argument', function () { - expect(mergeConfig(defaults, {})).toEqual(defaults); - }); - - it('should not leave references', function () { - const merged = mergeConfig(defaults, {}); - expect(merged).not.toBe(defaults); - expect(merged.headers).not.toBe(defaults.headers); - }); - - it('should allow setting request options', function () { - const config = { - url: '__sample url__', - method: '__sample method__', - params: '__sample params__', - data: { foo: true }, - }; - const merged = mergeConfig(defaults, config); - expect(merged.url).toEqual(config.url); - expect(merged.method).toEqual(config.method); - expect(merged.params).toEqual(config.params); - expect(merged.data).toEqual(config.data); - }); - - it('should not inherit request options', function () { - const localDefaults = { - method: '__sample method__', - data: { foo: true }, - }; - const merged = mergeConfig(localDefaults, {}); - expect(merged.method).toEqual(undefined); - expect(merged.data).toEqual(undefined); - }); - - ['auth', 'headers', 'params', 'proxy'].forEach(function (key) { - it('should set new config for' + key + ' without default', function () { - const a = {}, - b = {}, - c = {}; - a[key] = undefined; - b[key] = { user: 'foo', pass: 'test' }; - c[key] = { user: 'foo', pass: 'test' }; - - expect(mergeConfig(a, b)).toEqual(c); - }); - - it('should merge ' + key + ' with defaults', function () { - const a = {}, - b = {}, - c = {}; - a[key] = { user: 'foo', pass: 'bar' }; - b[key] = { pass: 'test' }; - c[key] = { user: 'foo', pass: 'test' }; - - expect(mergeConfig(a, b)).toEqual(c); - }); - - it('should overwrite default ' + key + ' with a non-object value', function () { - [false, null, 123].forEach(function (value) { - const a = {}, - b = {}, - c = {}; - a[key] = { user: 'foo', pass: 'test' }; - b[key] = value; - c[key] = value; - - expect(mergeConfig(a, b)).toEqual(c); - }); - }); - }); - - it('should allow setting other options', function () { - const merged = mergeConfig(defaults, { timeout: 123 }); - expect(merged.timeout).toEqual(123); - }); - - it('should allow setting custom options', function () { - const merged = mergeConfig(defaults, { foo: 'bar' }); - expect(merged.foo).toEqual('bar'); - }); - - it('should allow setting custom default options', function () { - const merged = mergeConfig({ foo: 'bar' }, {}); - expect(merged.foo).toEqual('bar'); - }); - - it('should allow merging custom objects in the config', function () { - const merged = mergeConfig( - { - nestedConfig: { - propertyOnDefaultConfig: true, - }, - }, - { - nestedConfig: { - propertyOnRequestConfig: true, - }, - } - ); - expect(merged.nestedConfig.propertyOnDefaultConfig).toEqual(true); - expect(merged.nestedConfig.propertyOnRequestConfig).toEqual(true); - }); - - describe('headers', () => { - it('should allow merging with AxiosHeaders instances', () => { - const merged = mergeConfig( - { - headers: new AxiosHeaders({ - x: 1, - y: 2, - }), - }, - { - headers: new AxiosHeaders({ - X: 1, - Y: 2, - }), - } - ); - expect(merged.headers).toEqual({ - x: '1', - y: '2', - }); - }); - }); - - describe('valueFromConfig2Keys', function () { - const config1 = { url: '/foo', method: 'post', data: { a: 3 } }; - - it('should skip if config2 is undefined', function () { - expect(mergeConfig(config1, {})).toEqual({}); - }); - - it('should clone config2 if is plain object', function () { - const data = { a: 1, b: 2 }; - const merged = mergeConfig(config1, { data: data }); - expect(merged.data).toEqual(data); - expect(merged.data).not.toBe(data); - }); - - it('should clone config2 if is array', function () { - const data = [1, 2, 3]; - const merged = mergeConfig(config1, { data: data }); - expect(merged.data).toEqual(data); - expect(merged.data).not.toBe(data); - }); - - it('should set as config2 in other cases', function () { - const obj = Object.create({}); - expect(mergeConfig(config1, { data: 1 }).data).toBe(1); - expect(mergeConfig(config1, { data: 'str' }).data).toBe('str'); - expect(mergeConfig(config1, { data: obj }).data).toBe(obj); - expect(mergeConfig(config1, { data: null }).data).toBe(null); - }); - }); - - describe('mergeDeepPropertiesKeys', function () { - it('should skip if both config1 and config2 are undefined', function () { - expect(mergeConfig({ headers: undefined }, { headers: undefined })).toEqual({}); - }); - - it('should merge if both config1 and config2 are plain object', function () { - expect(mergeConfig({ headers: { a: 1, b: 1 } }, { headers: { b: 2, c: 2 } })).toEqual({ - headers: { a: 1, b: 2, c: 2 }, - }); - }); - - it('should clone config2 if is plain object', function () { - const config1 = { headers: [1, 2, 3] }; - const config2 = { headers: { a: 1, b: 2 } }; - const merged = mergeConfig(config1, config2); - expect(merged.headers).toEqual(config2.headers); - expect(merged.headers).not.toBe(config2.headers); - }); - - it('should clone config2 if is array', function () { - const config1 = { headers: { a: 1, b: 1 } }; - const config2 = { headers: [1, 2, 3] }; - const merged = mergeConfig(config1, config2); - expect(merged.headers).toEqual(config2.headers); - expect(merged.headers).not.toBe(config2.headers); - }); - - it('should set as config2 in other cases', function () { - const config1 = { headers: { a: 1, b: 1 } }; - const obj = Object.create({}); - expect(mergeConfig(config1, { headers: 1 }).headers).toBe(1); - expect(mergeConfig(config1, { headers: 'str' }).headers).toBe('str'); - expect(mergeConfig(config1, { headers: obj }).headers).toBe(obj); - expect(mergeConfig(config1, { headers: null }).headers).toBe(null); - }); - - it('should clone config1 if is plain object', function () { - const config1 = { headers: { a: 1, b: 2 } }; - const config2 = {}; - const merged = mergeConfig(config1, config2); - expect(merged.headers).toEqual(config1.headers); - expect(merged.headers).not.toBe(config1.headers); - }); - - it('should clone config1 if is array', function () { - const config1 = { headers: [1, 2, 3] }; - const config2 = {}; - const merged = mergeConfig(config1, config2); - expect(merged.headers).toEqual(config1.headers); - expect(merged.headers).not.toBe(config1.headers); - }); - - it('should set as config1 in other cases', function () { - const config2 = {}; - const obj = Object.create({}); - expect(mergeConfig({ headers: 1 }, config2).headers).toBe(1); - expect(mergeConfig({ headers: 'str' }, config2).headers).toBe('str'); - expect(mergeConfig({ headers: obj }, config2).headers).toBe(obj); - expect(mergeConfig({ headers: null }, config2).headers).toBe(null); - }); - }); - - describe('defaultToConfig2Keys', function () { - it('should skip if both config1 and config2 are undefined', function () { - expect(mergeConfig({ transformRequest: undefined }, { transformRequest: undefined })).toEqual( - {} - ); - }); - - it('should clone config2 if both config1 and config2 are plain object', function () { - const config1 = { transformRequest: { a: 1, b: 1 } }; - const config2 = { transformRequest: { b: 2, c: 2 } }; - const merged = mergeConfig(config1, config2); - expect(merged.transformRequest).toEqual(config2.transformRequest); - expect(merged.transformRequest).not.toBe(config2.transformRequest); - }); - - it('should clone config2 if is array', function () { - const config1 = { transformRequest: { a: 1, b: 1 } }; - const config2 = { transformRequest: [1, 2, 3] }; - const merged = mergeConfig(config1, config2); - expect(merged.transformRequest).toEqual(config2.transformRequest); - expect(merged.transformRequest).not.toBe(config2.transformRequest); - }); - - it('should set as config2 in other cases', function () { - const config1 = { transformRequest: { a: 1, b: 1 } }; - const obj = Object.create({}); - expect(mergeConfig(config1, { transformRequest: 1 }).transformRequest).toBe(1); - expect(mergeConfig(config1, { transformRequest: 'str' }).transformRequest).toBe('str'); - expect(mergeConfig(config1, { transformRequest: obj }).transformRequest).toBe(obj); - expect(mergeConfig(config1, { transformRequest: null }).transformRequest).toBe(null); - }); - - it('should clone config1 if is plain object', function () { - const config1 = { transformRequest: { a: 1, b: 2 } }; - const config2 = {}; - const merged = mergeConfig(config1, config2); - expect(merged.transformRequest).toEqual(config1.transformRequest); - expect(merged.transformRequest).not.toBe(config1.transformRequest); - }); - - it('should clone config1 if is array', function () { - const config1 = { transformRequest: [1, 2, 3] }; - const config2 = {}; - const merged = mergeConfig(config1, config2); - expect(merged.transformRequest).toEqual(config1.transformRequest); - expect(merged.transformRequest).not.toBe(config1.transformRequest); - }); - - it('should set as config1 in other cases', function () { - const config2 = {}; - const obj = Object.create({}); - expect(mergeConfig({ transformRequest: 1 }, config2).transformRequest).toBe(1); - expect(mergeConfig({ transformRequest: 'str' }, config2).transformRequest).toBe('str'); - expect(mergeConfig({ transformRequest: obj }, config2).transformRequest).toBe(obj); - expect(mergeConfig({ transformRequest: null }, config2).transformRequest).toBe(null); - }); - }); - - describe('directMergeKeys', function () { - it('should merge if config2 in keys', function () { - expect(mergeConfig({}, { validateStatus: undefined })).toEqual({ validateStatus: undefined }); - }); - - it('should merge if both config1 and config2 are plain object', function () { - expect( - mergeConfig({ validateStatus: { a: 1, b: 1 } }, { validateStatus: { b: 2, c: 2 } }) - ).toEqual({ validateStatus: { a: 1, b: 2, c: 2 } }); - }); - - it('should clone config2 if is plain object', function () { - const config1 = { validateStatus: [1, 2, 3] }; - const config2 = { validateStatus: { a: 1, b: 2 } }; - const merged = mergeConfig(config1, config2); - expect(merged.validateStatus).toEqual(config2.validateStatus); - expect(merged.validateStatus).not.toBe(config2.validateStatus); - }); - - it('should clone config2 if is array', function () { - const config1 = { validateStatus: { a: 1, b: 2 } }; - const config2 = { validateStatus: [1, 2, 3] }; - const merged = mergeConfig(config1, config2); - expect(merged.validateStatus).toEqual(config2.validateStatus); - expect(merged.validateStatus).not.toBe(config2.validateStatus); - }); - - it('should set as config2 in other cases', function () { - const config1 = { validateStatus: { a: 1, b: 2 } }; - const obj = Object.create({}); - expect(mergeConfig(config1, { validateStatus: 1 }).validateStatus).toBe(1); - expect(mergeConfig(config1, { validateStatus: 'str' }).validateStatus).toBe('str'); - expect(mergeConfig(config1, { validateStatus: obj }).validateStatus).toBe(obj); - expect(mergeConfig(config1, { validateStatus: null }).validateStatus).toBe(null); - }); - - it('should clone config1 if is plain object', function () { - const config1 = { validateStatus: { a: 1, b: 2 } }; - const config2 = {}; - const merged = mergeConfig(config1, config2); - expect(merged.validateStatus).toEqual(config1.validateStatus); - expect(merged.validateStatus).not.toBe(config1.validateStatus); - }); - - it('should clone config1 if is array', function () { - const config1 = { validateStatus: [1, 2, 3] }; - const config2 = {}; - const merged = mergeConfig(config1, config2); - expect(merged.validateStatus).toEqual(config1.validateStatus); - expect(merged.validateStatus).not.toBe(config1.validateStatus); - }); - - it('should set as config1 in other cases', function () { - const config2 = {}; - const obj = Object.create({}); - expect(mergeConfig({ validateStatus: 1 }, config2).validateStatus).toBe(1); - expect(mergeConfig({ validateStatus: 'str' }, config2).validateStatus).toBe('str'); - expect(mergeConfig({ validateStatus: obj }, config2).validateStatus).toBe(obj); - expect(mergeConfig({ validateStatus: null }, config2).validateStatus).toBe(null); - }); - }); -}); diff --git a/test/specs/core/settle.spec.js b/test/specs/core/settle.spec.js deleted file mode 100644 index cea58fb6..00000000 --- a/test/specs/core/settle.spec.js +++ /dev/null @@ -1,85 +0,0 @@ -/* eslint-env mocha */ -import settle from '../../../lib/core/settle'; - -describe('core::settle', function () { - let resolve; - let reject; - - beforeEach(function () { - resolve = jasmine.createSpy('resolve'); - reject = jasmine.createSpy('reject'); - }); - - it('should resolve promise if status is not set', function () { - const response = { - config: { - validateStatus: function () { - return true; - }, - }, - }; - settle(resolve, reject, response); - expect(resolve).toHaveBeenCalledWith(response); - expect(reject).not.toHaveBeenCalled(); - }); - - it('should resolve promise if validateStatus is not set', function () { - const response = { - status: 500, - config: {}, - }; - settle(resolve, reject, response); - expect(resolve).toHaveBeenCalledWith(response); - expect(reject).not.toHaveBeenCalled(); - }); - - it('should resolve promise if validateStatus returns true', function () { - const response = { - status: 500, - config: { - validateStatus: function () { - return true; - }, - }, - }; - settle(resolve, reject, response); - expect(resolve).toHaveBeenCalledWith(response); - expect(reject).not.toHaveBeenCalled(); - }); - - it('should reject promise if validateStatus returns false', function () { - const req = { - path: '/foo', - }; - const response = { - status: 500, - config: { - validateStatus: function () { - return false; - }, - }, - request: req, - }; - settle(resolve, reject, response); - expect(resolve).not.toHaveBeenCalled(); - expect(reject).toHaveBeenCalled(); - const reason = reject.calls.first().args[0]; - expect(reason instanceof Error).toBe(true); - expect(reason.message).toBe('Request failed with status code 500'); - expect(reason.config).toBe(response.config); - expect(reason.request).toBe(req); - expect(reason.response).toBe(response); - }); - - it('should pass status to validateStatus', function () { - const validateStatus = jasmine.createSpy('validateStatus'); - const response = { - status: 500, - config: { - validateStatus: validateStatus, - }, - }; - settle(resolve, reject, response); - expect(validateStatus).toHaveBeenCalledWith(500); - }); -}); diff --git a/test/specs/core/transformData.spec.js b/test/specs/core/transformData.spec.js deleted file mode 100644 index 190f8b51..00000000 --- a/test/specs/core/transformData.spec.js +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-env mocha */ -import transformData from '../../../lib/core/transformData'; - -describe('core::transformData', function () { - it('should support a single transformer', function () { - let data; - - data = transformData.call({}, function (data) { - data = 'foo'; - return data; - }); - - expect(data).toEqual('foo'); - }); - - it('should support an array of transformers', function () { - let data = ''; - data = transformData.call({ data }, [ - function (data) { - data += 'f'; - return data; - }, - function (data) { - data += 'o'; - return data; - }, - function (data) { - data += 'o'; - return data; - }, - ]); - - expect(data).toEqual('foo'); - }); - - it('should support reference headers in transformData', function () { - const headers = { - 'content-type': 'foo/bar', - }; - let data = ''; - data = transformData.call({ data, headers }, [ - function (data, headers) { - data += headers['content-type']; - return data; - }, - ]); - - expect(data).toEqual('foo/bar'); - }); - - it('should support reference status code in transformData', function () { - let data = ''; - data = transformData.call( - {}, - [ - function (data, headers, status) { - data += status; - return data; - }, - ], - { data, status: 200 } - ); - - expect(data).toEqual('200'); - }); -}); diff --git a/test/specs/defaults.spec.js b/test/specs/defaults.spec.js deleted file mode 100644 index 74a6e0bf..00000000 --- a/test/specs/defaults.spec.js +++ /dev/null @@ -1,209 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -import defaults from '../../lib/defaults'; -import AxiosHeaders from '../../lib/core/AxiosHeaders'; - -describe('defaults', function () { - const XSRF_COOKIE_NAME = 'CUSTOM-XSRF-TOKEN'; - - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - delete axios.defaults.baseURL; - delete axios.defaults.headers.get['X-CUSTOM-HEADER']; - delete axios.defaults.headers.post['X-CUSTOM-HEADER']; - document.cookie = - XSRF_COOKIE_NAME + '=;expires=' + new Date(Date.now() - 86400000).toGMTString(); - }); - - it('should transform request json', function () { - expect(defaults.transformRequest[0]({ foo: 'bar' }, new AxiosHeaders())).toEqual( - '{"foo":"bar"}' - ); - }); - - it("should also transform request json when 'Content-Type' is 'application/json'", function () { - const headers = new AxiosHeaders({ - 'Content-Type': 'application/json', - }); - expect(defaults.transformRequest[0](JSON.stringify({ foo: 'bar' }), headers)).toEqual( - '{"foo":"bar"}' - ); - expect(defaults.transformRequest[0]([42, 43], headers)).toEqual('[42,43]'); - expect(defaults.transformRequest[0]('foo', headers)).toEqual('"foo"'); - expect(defaults.transformRequest[0](42, headers)).toEqual('42'); - expect(defaults.transformRequest[0](true, headers)).toEqual('true'); - expect(defaults.transformRequest[0](false, headers)).toEqual('false'); - expect(defaults.transformRequest[0](null, headers)).toEqual('null'); - }); - - it("should transform the plain data object to a FormData instance 'Content-Type' if header is 'multipart/form-data'", function () { - const headers = new AxiosHeaders({ - 'Content-Type': 'multipart/form-data', - }); - - const payload = { x: 1 }; - - const transformed = defaults.transformRequest[0](payload, headers); - - expect(transformed).toEqual(jasmine.any(FormData)); - }); - - it('should do nothing to request string', function () { - expect(defaults.transformRequest[0]('foo=bar', new AxiosHeaders())).toEqual('foo=bar'); - }); - - it('should transform response json', function () { - const data = defaults.transformResponse[0].call(defaults, '{"foo":"bar"}'); - - expect(typeof data).toEqual('object'); - expect(data.foo).toEqual('bar'); - }); - - it('should do nothing to response string', function () { - expect(defaults.transformResponse[0]('foo=bar')).toEqual('foo=bar'); - }); - - it('should use global defaults config', function (done) { - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo'); - done(); - }); - }); - - it('should use modified defaults config', function (done) { - axios.defaults.baseURL = 'http://example.com/'; - - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('http://example.com/foo'); - done(); - }); - }); - - it('should use request config', function (done) { - axios('/foo', { - baseURL: 'http://www.example.com', - }); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('http://www.example.com/foo'); - done(); - }); - }); - - it('should use default config for custom instance', function (done) { - const instance = axios.create({ - xsrfCookieName: XSRF_COOKIE_NAME, - xsrfHeaderName: 'X-CUSTOM-XSRF-TOKEN', - }); - document.cookie = instance.defaults.xsrfCookieName + '=foobarbaz'; - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[instance.defaults.xsrfHeaderName]).toEqual('foobarbaz'); - done(); - }); - }); - - it('should use GET headers', function (done) { - axios.defaults.headers.get['X-CUSTOM-HEADER'] = 'foo'; - axios.get('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo'); - done(); - }); - }); - - it('should use POST headers', function (done) { - axios.defaults.headers.post['X-CUSTOM-HEADER'] = 'foo'; - axios.post('/foo', {}); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo'); - done(); - }); - }); - - it('should use header config', function (done) { - const instance = axios.create({ - headers: { - common: { - 'X-COMMON-HEADER': 'commonHeaderValue', - }, - get: { - 'X-GET-HEADER': 'getHeaderValue', - }, - post: { - 'X-POST-HEADER': 'postHeaderValue', - }, - }, - }); - - instance.get('/foo', { - headers: { - 'X-FOO-HEADER': 'fooHeaderValue', - 'X-BAR-HEADER': 'barHeaderValue', - }, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders).toEqual( - AxiosHeaders.concat(defaults.headers.common, defaults.headers.get, { - 'X-COMMON-HEADER': 'commonHeaderValue', - 'X-GET-HEADER': 'getHeaderValue', - 'X-FOO-HEADER': 'fooHeaderValue', - 'X-BAR-HEADER': 'barHeaderValue', - }).toJSON() - ); - done(); - }); - }); - - it('should be used by custom instance if set before instance created', function (done) { - axios.defaults.baseURL = 'http://example.org/'; - const instance = axios.create(); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('http://example.org/foo'); - done(); - }); - }); - - it('should not be used by custom instance if set after instance created', function (done) { - const instance = axios.create(); - axios.defaults.baseURL = 'http://example.org/'; - - instance.get('/foo/users'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo/users'); - done(); - }); - }); - - it('should resistant to ReDoS attack', function (done) { - const instance = axios.create(); - const start = performance.now(); - const slashes = '/'.repeat(100000); - instance.defaults.baseURL = '/' + slashes + 'bar/'; - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - const elapsedTimeMs = performance.now() - start; - expect(elapsedTimeMs).toBeLessThan(20); - expect(request.url).toBe('/' + slashes + 'bar/foo'); - done(); - }); - }); -}); diff --git a/test/specs/formdata.spec.js b/test/specs/formdata.spec.js deleted file mode 100644 index b7ef2d1f..00000000 --- a/test/specs/formdata.spec.js +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-env mocha */ -import { retryNetwork } from '../helpers/retry.js'; - -describe('FormData', function () { - it('should allow FormData posting', async () => { - await retryNetwork(() => { - return axios - .postForm(TEST_SERVER_URL, { - a: 'foo', - b: 'bar', - }) - .then(({ data }) => { - expect(data.form).toEqual({ - a: 'foo', - b: 'bar', - }); - }); - }); - }); -}); diff --git a/test/specs/headers.spec.js b/test/specs/headers.spec.js deleted file mode 100644 index 6a0c4ea5..00000000 --- a/test/specs/headers.spec.js +++ /dev/null @@ -1,169 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -const { AxiosHeaders } = axios; - -function testHeaderValue(headers, key, val) { - let found = false; - - for (const k in headers) { - if (k.toLowerCase() === key.toLowerCase()) { - found = true; - expect(headers[k]).toEqual(val); - break; - } - } - - if (!found) { - if (typeof val === 'undefined') { - expect(headers.hasOwnProperty(key)).toEqual(false); - } else { - throw new Error(key + ' was not found in headers'); - } - } -} - -describe('headers', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should default common headers', function (done) { - const headers = axios.defaults.headers.common; - - axios('/foo'); - - getAjaxRequest().then(function (request) { - for (const key in headers) { - if (headers.hasOwnProperty(key)) { - expect(request.requestHeaders[key]).toEqual(headers[key]); - } - } - done(); - }); - }); - - it('should respect common Content-Type header', function () { - const instance = axios.create(); - - instance.defaults.headers.common['Content-Type'] = 'application/custom'; - - instance.patch('/foo', ''); - - const expectedHeaders = { - 'Content-Type': 'application/custom', - }; - - return getAjaxRequest().then(function (request) { - for (const key in expectedHeaders) { - if (expectedHeaders.hasOwnProperty(key)) { - expect(request.requestHeaders[key]).toEqual(expectedHeaders[key]); - } - } - }); - }); - - it('should add extra headers for post', function () { - const headers = AxiosHeaders.from(axios.defaults.headers.common).toJSON(); - - axios.post('/foo', 'fizz=buzz'); - - return getAjaxRequest().then(function (request) { - for (const key in headers) { - expect(request.requestHeaders[key]).toEqual(headers[key]); - } - }); - }); - - it('should reset headers by null or explicit undefined', function (done) { - axios - .create({ - headers: { - common: { - 'x-header-a': 'a', - 'x-header-b': 'b', - 'x-header-c': 'c', - }, - }, - }) - .post( - '/foo', - { fizz: 'buzz' }, - { - headers: { - 'Content-Type': null, - 'x-header-a': null, - 'x-header-b': undefined, - }, - } - ) - .catch(function (err) { - done(err); - }); - - getAjaxRequest() - .then(function (request) { - testHeaderValue(request.requestHeaders, 'Content-Type', undefined); - testHeaderValue(request.requestHeaders, 'x-header-a', undefined); - testHeaderValue(request.requestHeaders, 'x-header-b', undefined); - testHeaderValue(request.requestHeaders, 'x-header-c', 'c'); - done(); - }) - .catch(done); - }); - - it('should use application/json when posting an object', function (done) { - axios.post('/foo/bar', { - firstName: 'foo', - lastName: 'bar', - }); - - getAjaxRequest().then(function (request) { - testHeaderValue(request.requestHeaders, 'Content-Type', 'application/json'); - done(); - }); - }); - - it('should remove content-type if data is empty', function (done) { - axios.post('/foo'); - - getAjaxRequest().then(function (request) { - testHeaderValue(request.requestHeaders, 'Content-Type', undefined); - done(); - }); - }); - - it('should preserve content-type if data is false', async function () { - axios.post('/foo', false); - - await getAjaxRequest().then(function (request) { - testHeaderValue(request.requestHeaders, 'Content-Type', 'application/x-www-form-urlencoded'); - }); - }); - - it('should allow an AxiosHeaders instance to be used as the value of the headers option', async () => { - const instance = axios.create({ - headers: new AxiosHeaders({ - xFoo: 'foo', - xBar: 'bar', - }), - }); - - instance.get('/foo', { - headers: { - XFOO: 'foo2', - xBaz: 'baz', - }, - }); - - await getAjaxRequest().then(function (request) { - expect(request.requestHeaders.xFoo).toEqual('foo2'); - expect(request.requestHeaders.xBar).toEqual('bar'); - expect(request.requestHeaders.xBaz).toEqual('baz'); - expect(request.requestHeaders.XFOO).toEqual(undefined); - }); - }); -}); diff --git a/test/specs/helpers/bind.spec.js b/test/specs/helpers/bind.spec.js deleted file mode 100644 index bb66a665..00000000 --- a/test/specs/helpers/bind.spec.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -import bind from '../../../lib/helpers/bind'; - -describe('bind', function () { - it('should bind an object to a function', function () { - const o = { val: 123 }; - const f = bind(function (num) { - return this.val * num; - }, o); - - expect(f(2)).toEqual(246); - }); -}); diff --git a/test/specs/helpers/buildURL.spec.js b/test/specs/helpers/buildURL.spec.js deleted file mode 100644 index 06bb86d2..00000000 --- a/test/specs/helpers/buildURL.spec.js +++ /dev/null @@ -1,126 +0,0 @@ -/* eslint-env mocha */ -import buildURL from '../../../lib/helpers/buildURL'; - -describe('helpers::buildURL', function () { - it('should support null params', function () { - expect(buildURL('/foo')).toEqual('/foo'); - }); - - it('should support params', function () { - expect( - buildURL('/foo', { - foo: 'bar', - isUndefined: undefined, - isNull: null, - }) - ).toEqual('/foo?foo=bar'); - }); - - it('should support sending raw params to custom serializer func', function () { - const serializer = sinon.stub(); - const params = { foo: 'bar' }; - serializer.returns('foo=bar'); - expect( - buildURL( - '/foo', - { - foo: 'bar', - }, - { - serialize: serializer, - } - ) - ).toEqual('/foo?foo=bar'); - expect(serializer.calledOnce).toBe(true); - expect(serializer.calledWith(params)).toBe(true); - }); - - it('should support object params', function () { - expect( - buildURL('/foo', { - foo: { - bar: 'baz', - }, - }) - ).toEqual('/foo?foo%5Bbar%5D=baz'); - }); - - it('should support date params', function () { - const date = new Date(); - - expect( - buildURL('/foo', { - date: date, - }) - ).toEqual('/foo?date=' + date.toISOString()); - }); - - it('should support array params with encode', function () { - expect( - buildURL('/foo', { - foo: ['bar', 'baz'], - }) - ).toEqual('/foo?foo%5B%5D=bar&foo%5B%5D=baz'); - }); - - it('should support special char params', function () { - expect( - buildURL('/foo', { - foo: ':$, ', - }) - ).toEqual('/foo?foo=:$,+'); - }); - - it('should support existing params', function () { - expect( - buildURL('/foo?foo=bar', { - bar: 'baz', - }) - ).toEqual('/foo?foo=bar&bar=baz'); - }); - - it('should support "length" parameter', function () { - expect( - buildURL('/foo', { - query: 'bar', - start: 0, - length: 5, - }) - ).toEqual('/foo?query=bar&start=0&length=5'); - }); - - it('should correct discard url hash mark', function () { - expect( - buildURL('/foo?foo=bar#hash', { - query: 'baz', - }) - ).toEqual('/foo?foo=bar&query=baz'); - }); - - it('should support URLSearchParams', function () { - expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz'); - }); - - it('should support custom serialize function', function () { - const params = { - x: 1, - }; - - const options = { - serialize: (thisParams, thisOptions) => { - expect(thisParams).toEqual(params); - expect(thisOptions).toEqual(options); - return 'rendered'; - }, - }; - - expect(buildURL('/foo', params, options)).toEqual('/foo?rendered'); - - const customSerializer = (thisParams) => { - expect(thisParams).toEqual(params); - return 'rendered'; - }; - - expect(buildURL('/foo', params, customSerializer)).toEqual('/foo?rendered'); - }); -}); diff --git a/test/specs/helpers/combineURLs.spec.js b/test/specs/helpers/combineURLs.spec.js deleted file mode 100644 index 81f4549f..00000000 --- a/test/specs/helpers/combineURLs.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-env mocha */ -import combineURLs from '../../../lib/helpers/combineURLs'; - -describe('helpers::combineURLs', function () { - it('should combine URLs', function () { - expect(combineURLs('https://api.github.com', '/users')).toBe('https://api.github.com/users'); - }); - - it('should remove duplicate slashes', function () { - expect(combineURLs('https://api.github.com/', '/users')).toBe('https://api.github.com/users'); - }); - - it('should insert missing slash', function () { - expect(combineURLs('https://api.github.com', 'users')).toBe('https://api.github.com/users'); - }); - - it('should not insert slash when relative url missing/empty', function () { - expect(combineURLs('https://api.github.com/users', '')).toBe('https://api.github.com/users'); - }); - - it('should allow a single slash for relative url', function () { - expect(combineURLs('https://api.github.com/users', '/')).toBe('https://api.github.com/users/'); - }); -}); diff --git a/test/specs/helpers/cookies.spec.js b/test/specs/helpers/cookies.spec.js deleted file mode 100644 index ee60fb33..00000000 --- a/test/specs/helpers/cookies.spec.js +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-env mocha */ -import cookies from '../../../lib/helpers/cookies'; - -describe('helpers::cookies', function () { - afterEach(function () { - // Remove all the cookies - const expires = Date.now() - 60 * 60 * 24 * 7; - document.cookie - .split(';') - .map(function (cookie) { - return cookie.split('=')[0]; - }) - .forEach(function (name) { - document.cookie = name + '=; expires=' + new Date(expires).toGMTString(); - }); - }); - - it('should write cookies', function () { - cookies.write('foo', 'baz'); - expect(document.cookie).toEqual('foo=baz'); - }); - - it('should read cookies', function () { - cookies.write('foo', 'abc'); - cookies.write('bar', 'def'); - expect(cookies.read('foo')).toEqual('abc'); - expect(cookies.read('bar')).toEqual('def'); - }); - - it('should remove cookies', function () { - cookies.write('foo', 'bar'); - cookies.remove('foo'); - expect(cookies.read('foo')).toEqual(null); - }); - - it('should uri encode values', function () { - cookies.write('foo', 'bar baz%'); - expect(document.cookie).toEqual('foo=bar%20baz%25'); - }); -}); diff --git a/test/specs/helpers/formDataToJSON.spec.js b/test/specs/helpers/formDataToJSON.spec.js deleted file mode 100644 index 4bc3ec4f..00000000 --- a/test/specs/helpers/formDataToJSON.spec.js +++ /dev/null @@ -1,72 +0,0 @@ -/* eslint-env mocha */ -import formDataToJSON from '../../../lib/helpers/formDataToJSON'; - -describe('formDataToJSON', function () { - it('should convert a FormData Object to JSON Object', function () { - const formData = new FormData(); - - formData.append('foo[bar][baz]', '123'); - - expect(formDataToJSON(formData)).toEqual({ - foo: { - bar: { - baz: '123', - }, - }, - }); - }); - - it('should convert repeatable values as an array', function () { - const formData = new FormData(); - - formData.append('foo', '1'); - formData.append('foo', '2'); - - expect(formDataToJSON(formData)).toEqual({ - foo: ['1', '2'], - }); - }); - - it('should convert props with empty brackets to arrays', function () { - const formData = new FormData(); - - formData.append('foo[]', '1'); - formData.append('foo[]', '2'); - - expect(formDataToJSON(formData)).toEqual({ - foo: ['1', '2'], - }); - }); - - it('should supported indexed arrays', function () { - const formData = new FormData(); - - formData.append('foo[0]', '1'); - formData.append('foo[1]', '2'); - - expect(formDataToJSON(formData)).toEqual({ - foo: ['1', '2'], - }); - }); - - it('should resist prototype pollution CVE', () => { - const formData = new FormData(); - - formData.append('foo[0]', '1'); - formData.append('foo[1]', '2'); - formData.append('__proto__.x', 'hack'); - formData.append('constructor.prototype.y', 'value'); - - expect(formDataToJSON(formData)).toEqual({ - foo: ['1', '2'], - constructor: { - prototype: { - y: 'value', - }, - }, - }); - - expect({}.x).toEqual(undefined); - expect({}.y).toEqual(undefined); - }); -}); diff --git a/test/specs/helpers/isAbsoluteURL.spec.js b/test/specs/helpers/isAbsoluteURL.spec.js deleted file mode 100644 index 0a6bfaac..00000000 --- a/test/specs/helpers/isAbsoluteURL.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-env mocha */ -import isAbsoluteURL from '../../../lib/helpers/isAbsoluteURL'; - -describe('helpers::isAbsoluteURL', function () { - it('should return true if URL begins with valid scheme name', function () { - expect(isAbsoluteURL('https://api.github.com/users')).toBe(true); - expect(isAbsoluteURL('custom-scheme-v1.0://example.com/')).toBe(true); - expect(isAbsoluteURL('HTTP://example.com/')).toBe(true); - }); - - it('should return false if URL begins with invalid scheme name', function () { - expect(isAbsoluteURL('123://example.com/')).toBe(false); - expect(isAbsoluteURL('!valid://example.com/')).toBe(false); - }); - - it('should return true if URL is protocol-relative', function () { - expect(isAbsoluteURL('//example.com/')).toBe(true); - }); - - it('should return false if URL is relative', function () { - expect(isAbsoluteURL('/foo')).toBe(false); - expect(isAbsoluteURL('foo')).toBe(false); - }); -}); diff --git a/test/specs/helpers/isAxiosError.spec.js b/test/specs/helpers/isAxiosError.spec.js deleted file mode 100644 index 37cbf1b5..00000000 --- a/test/specs/helpers/isAxiosError.spec.js +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-env mocha */ -import AxiosError from '../../../lib/core/AxiosError'; -import isAxiosError from '../../../lib/helpers/isAxiosError'; - -describe('helpers::isAxiosError', function () { - it('should return true if the error is created by core::createError', function () { - expect(isAxiosError(new AxiosError('Boom!', null, { foo: 'bar' }))).toBe(true); - }); - - it('should return true if the error is enhanced by core::enhanceError', function () { - expect(isAxiosError(AxiosError.from(new Error('Boom!'), null, { foo: 'bar' }))).toBe(true); - }); - - it('should return false if the error is a normal Error instance', function () { - expect(isAxiosError(new Error('Boom!'))).toBe(false); - }); - - it('should return false if the error is null', function () { - expect(isAxiosError(null)).toBe(false); - }); -}); diff --git a/test/specs/helpers/isURLSameOrigin.spec.js b/test/specs/helpers/isURLSameOrigin.spec.js deleted file mode 100644 index e0c41873..00000000 --- a/test/specs/helpers/isURLSameOrigin.spec.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-env mocha */ -import isURLSameOrigin from '../../../lib/helpers/isURLSameOrigin'; - -describe('helpers::isURLSameOrigin', function () { - it('should detect same origin', function () { - expect(isURLSameOrigin(window.location.href)).toEqual(true); - }); - - it('should detect different origin', function () { - expect(isURLSameOrigin('https://github.com/axios/axios')).toEqual(false); - }); -}); diff --git a/test/specs/helpers/parseHeaders.spec.js b/test/specs/helpers/parseHeaders.spec.js deleted file mode 100644 index 0d2e266d..00000000 --- a/test/specs/helpers/parseHeaders.spec.js +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-env mocha */ -import parseHeaders from '../../../lib/helpers/parseHeaders'; - -describe('helpers::parseHeaders', function () { - it('should parse headers', function () { - const date = new Date(); - const parsed = parseHeaders( - 'Date: ' + - date.toISOString() + - '\n' + - 'Content-Type: application/json\n' + - 'Connection: keep-alive\n' + - 'Transfer-Encoding: chunked' - ); - - expect(parsed['date']).toEqual(date.toISOString()); - expect(parsed['content-type']).toEqual('application/json'); - expect(parsed['connection']).toEqual('keep-alive'); - expect(parsed['transfer-encoding']).toEqual('chunked'); - }); - - it('should use array for set-cookie', function () { - const parsedZero = parseHeaders(''); - const parsedSingle = parseHeaders('Set-Cookie: key=val;'); - const parsedMulti = parseHeaders('Set-Cookie: key=val;\n' + 'Set-Cookie: key2=val2;\n'); - - expect(parsedZero['set-cookie']).toBeUndefined(); - expect(parsedSingle['set-cookie']).toEqual(['key=val;']); - expect(parsedMulti['set-cookie']).toEqual(['key=val;', 'key2=val2;']); - }); - - it('should handle duplicates', function () { - const parsed = parseHeaders( - 'Age: age-a\n' + // age is in ignore duplicates blocklist - 'Age: age-b\n' + - 'Foo: foo-a\n' + - 'Foo: foo-b\n' - ); - - expect(parsed['age']).toEqual('age-a'); - expect(parsed['foo']).toEqual('foo-a, foo-b'); - }); -}); diff --git a/test/specs/helpers/spread.spec.js b/test/specs/helpers/spread.spec.js deleted file mode 100644 index 7d49cacf..00000000 --- a/test/specs/helpers/spread.spec.js +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-env mocha */ -import spread from '../../../lib/helpers/spread'; - -describe('helpers::spread', function () { - it('should spread array to arguments', function () { - let value = 0; - spread(function (a, b) { - value = a * b; - })([5, 10]); - - expect(value).toEqual(50); - }); - - it('should return callback result', function () { - const value = spread(function (a, b) { - return a * b; - })([5, 10]); - - expect(value).toEqual(50); - }); -}); diff --git a/test/specs/helpers/toFormData.spec.js b/test/specs/helpers/toFormData.spec.js deleted file mode 100644 index a6ff198d..00000000 --- a/test/specs/helpers/toFormData.spec.js +++ /dev/null @@ -1,126 +0,0 @@ -/* eslint-env mocha */ -import toFormData from '../../../lib/helpers/toFormData'; - -describe('toFormData', function () { - it('should convert nested data object to FormData with dots option enabled', function () { - const o = { - val: 123, - nested: { - arr: ['hello', 'world'], - }, - }; - - const form = toFormData(o, null, { dots: true }); - expect(form instanceof FormData).toEqual(true); - expect(Array.from(form.keys()).length).toEqual(3); - expect(form.get('val')).toEqual('123'); - expect(form.get('nested.arr.0')).toEqual('hello'); - }); - - it('should respect metaTokens option', function () { - const data = { - 'obj{}': { x: 1, y: 2 }, - }; - - const str = JSON.stringify(data['obj{}']); - - const form = toFormData(data, null, { metaTokens: false }); - - expect(Array.from(form.keys()).length).toEqual(1); - expect(form.getAll('obj')).toEqual([str]); - }); - - describe('Flat arrays serialization', function () { - it('should include full indexes when the `indexes` option is set to true', function () { - const data = { - arr: [1, 2, 3], - arr2: [1, [2], 3], - }; - - const form = toFormData(data, null, { indexes: true }); - - expect(Array.from(form.keys()).length).toEqual(6); - - expect(form.get('arr[0]')).toEqual('1'); - expect(form.get('arr[1]')).toEqual('2'); - expect(form.get('arr[2]')).toEqual('3'); - - expect(form.get('arr2[0]')).toEqual('1'); - expect(form.get('arr2[1][0]')).toEqual('2'); - expect(form.get('arr2[2]')).toEqual('3'); - }); - - it('should include brackets only when the `indexes` option is set to false', function () { - const data = { - arr: [1, 2, 3], - arr2: [1, [2], 3], - }; - - const form = toFormData(data, null, { indexes: false }); - - expect(Array.from(form.keys()).length).toEqual(6); - - expect(form.getAll('arr[]')).toEqual(['1', '2', '3']); - - expect(form.get('arr2[0]')).toEqual('1'); - expect(form.get('arr2[1][0]')).toEqual('2'); - expect(form.get('arr2[2]')).toEqual('3'); - }); - - it('should omit brackets when the `indexes` option is set to null', function () { - const data = { - arr: [1, 2, 3], - arr2: [1, [2], 3], - }; - - const form = toFormData(data, null, { indexes: null }); - - expect(Array.from(form.keys()).length).toEqual(6); - - expect(form.getAll('arr')).toEqual(['1', '2', '3']); - - expect(form.get('arr2[0]')).toEqual('1'); - expect(form.get('arr2[1][0]')).toEqual('2'); - expect(form.get('arr2[2]')).toEqual('3'); - }); - }); - - it('should convert nested data object to FormData', function () { - const o = { - val: 123, - nested: { - arr: ['hello', 'world'], - }, - }; - - const form = toFormData(o); - expect(form instanceof FormData).toEqual(true); - expect(Array.from(form.keys()).length).toEqual(3); - expect(form.get('val')).toEqual('123'); - expect(form.get('nested[arr][0]')).toEqual('hello'); - }); - - it('should append value whose key ends with [] as separate values with the same key', function () { - const data = { - 'arr[]': [1, 2, 3], - }; - - const form = toFormData(data); - - expect(Array.from(form.keys()).length).toEqual(3); - expect(form.getAll('arr[]')).toEqual(['1', '2', '3']); - }); - - it('should append value whose key ends with {} as a JSON string', function () { - const data = { - 'obj{}': { x: 1, y: 2 }, - }; - - const str = JSON.stringify(data['obj{}']); - - const form = toFormData(data); - - expect(Array.from(form.keys()).length).toEqual(1); - expect(form.getAll('obj{}')).toEqual([str]); - }); -}); diff --git a/test/specs/helpers/validator.spec.js b/test/specs/helpers/validator.spec.js deleted file mode 100644 index 1bffd46d..00000000 --- a/test/specs/helpers/validator.spec.js +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-env mocha */ -'use strict'; - -import validator from '../../../lib/helpers/validator'; - -describe('validator::assertOptions', function () { - it('should throw only if unknown an option was passed', function () { - expect(function () { - validator.assertOptions( - { - x: true, - }, - { - y: validator.validators.boolean, - } - ); - }).toThrow(new Error('Unknown option x')); - - expect(function () { - validator.assertOptions( - { - x: true, - }, - { - x: validator.validators.boolean, - y: validator.validators.boolean, - } - ); - }).not.toThrow(new Error('Unknown option x')); - }); - - it("should throw TypeError only if option type doesn't match", function () { - expect(function () { - validator.assertOptions( - { - x: 123, - }, - { - x: validator.validators.boolean, - } - ); - }).toThrow(new TypeError('option x must be a boolean')); - - expect(function () { - validator.assertOptions( - { - x: true, - }, - { - x: validator.validators.boolean, - y: validator.validators.boolean, - } - ); - }).not.toThrow(); - }); -}); diff --git a/test/specs/instance.spec.js b/test/specs/instance.spec.js deleted file mode 100644 index 3c5fd9c8..00000000 --- a/test/specs/instance.spec.js +++ /dev/null @@ -1,165 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -describe('instance', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should have the same methods as default instance', function () { - const instance = axios.create(); - - for (const prop in axios) { - if ( - [ - 'Axios', - 'AxiosError', - 'create', - 'Cancel', - 'CanceledError', - 'CancelToken', - 'isCancel', - 'all', - 'spread', - 'getUri', - 'isAxiosError', - 'mergeConfig', - 'getAdapter', - 'VERSION', - 'default', - 'toFormData', - 'formToJSON', - 'AxiosHeaders', - 'HttpStatusCode', - ].indexOf(prop) > -1 - ) { - continue; - } - expect(typeof instance[prop]).toBe(typeof axios[prop]); - } - }); - - it('should make an http request without verb helper', function (done) { - const instance = axios.create(); - - instance('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo'); - done(); - }); - }); - - it('should make an http request with url instead of baseURL', function (done) { - const instance = axios.create({ - url: 'https://api.example.com', - }); - - instance('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo'); - done(); - }); - }); - - it('should make an http request', function (done) { - const instance = axios.create(); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo'); - done(); - }); - }); - - it('should use instance options', function (done) { - const instance = axios.create({ timeout: 1000 }); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.timeout).toBe(1000); - done(); - }); - }); - - it('should have defaults.headers', function () { - const instance = axios.create({ - baseURL: 'https://api.example.com', - }); - - expect(typeof instance.defaults.headers, 'object'); - expect(typeof instance.defaults.headers.common, 'object'); - }); - - it('should have interceptors on the instance', function (done) { - axios.interceptors.request.use(function (config) { - config.foo = true; - return config; - }); - - const instance = axios.create(); - instance.interceptors.request.use(function (config) { - config.bar = true; - return config; - }); - - let response; - instance.get('/foo').then(function (res) { - response = res; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - }); - - setTimeout(function () { - expect(response.config.foo).toEqual(undefined); - expect(response.config.bar).toEqual(true); - done(); - }, 100); - }); - }); - - it('should have getUri on the instance', function () { - const instance = axios.create({ - baseURL: 'https://api.example.com', - }); - const options = { - url: 'foo/bar', - params: { - name: 'axios', - }, - }; - expect(instance.getUri(options)).toBe('https://api.example.com/foo/bar?name=axios'); - }); - - it('should correctly build url without baseURL', function () { - const instance = axios.create(); - const options = { - url: 'foo/bar?foo=bar', - params: { - name: 'axios', - }, - }; - expect(instance.getUri(options)).toBe('foo/bar?foo=bar&name=axios'); - }); - - it('should correctly discard url hash mark', function () { - const instance = axios.create(); - const options = { - baseURL: 'https://api.example.com', - url: 'foo/bar?foo=bar#hash', - params: { - name: 'axios', - }, - }; - expect(instance.getUri(options)).toBe('https://api.example.com/foo/bar?foo=bar&name=axios'); - }); -}); diff --git a/test/specs/interceptors.spec.js b/test/specs/interceptors.spec.js deleted file mode 100644 index 95bf5b8f..00000000 --- a/test/specs/interceptors.spec.js +++ /dev/null @@ -1,697 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -describe('interceptors', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - axios.interceptors.request.handlers = []; - axios.interceptors.response.handlers = []; - }); - - it('should add a request interceptor (asynchronous by default)', function (done) { - let asyncFlag = false; - axios.interceptors.request.use(function (config) { - config.headers.test = 'added by interceptor'; - expect(asyncFlag).toBe(true); - return config; - }); - - axios('/foo'); - asyncFlag = true; - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.test).toBe('added by interceptor'); - done(); - }); - }); - - it('should add a request interceptor (explicitly flagged as asynchronous)', function (done) { - let asyncFlag = false; - axios.interceptors.request.use( - function (config) { - config.headers.test = 'added by interceptor'; - expect(asyncFlag).toBe(true); - return config; - }, - null, - { synchronous: false } - ); - - axios('/foo'); - asyncFlag = true; - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.test).toBe('added by interceptor'); - done(); - }); - }); - - it('should add a request interceptor that is executed synchronously when flag is provided', function (done) { - let asyncFlag = false; - axios.interceptors.request.use( - function (config) { - config.headers.test = 'added by synchronous interceptor'; - expect(asyncFlag).toBe(false); - return config; - }, - null, - { synchronous: true } - ); - - axios('/foo'); - asyncFlag = true; - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.test).toBe('added by synchronous interceptor'); - done(); - }); - }); - - it('should execute asynchronously when not all interceptors are explicitly flagged as synchronous', function (done) { - let asyncFlag = false; - axios.interceptors.request.use(function (config) { - config.headers.foo = 'uh oh, async'; - expect(asyncFlag).toBe(true); - return config; - }); - - axios.interceptors.request.use( - function (config) { - config.headers.test = 'added by synchronous interceptor'; - expect(asyncFlag).toBe(true); - return config; - }, - null, - { synchronous: true } - ); - - axios.interceptors.request.use(function (config) { - config.headers.test = 'added by the async interceptor'; - expect(asyncFlag).toBe(true); - return config; - }); - - axios('/foo'); - asyncFlag = true; - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.foo).toBe('uh oh, async'); - /* request interceptors have a reversed execution order */ - expect(request.requestHeaders.test).toBe('added by synchronous interceptor'); - done(); - }); - }); - - it('should execute request interceptor in legacy order', function (done) { - let sequence = ''; - axios.interceptors.request.use(function (config) { - sequence += '1'; - return config; - }); - - axios.interceptors.request.use(function (config) { - sequence += '2'; - return config; - }); - - axios.interceptors.request.use(function (config) { - sequence += '3'; - return config; - }); - - axios({ - url: '/foo', - }); - - getAjaxRequest().then(function (request) { - expect(sequence).toBe('321'); - done(); - }); - }); - - it('should execute request interceptor in order', function (done) { - let sequence = ''; - axios.interceptors.request.use(function (config) { - sequence += '1'; - return config; - }); - - axios.interceptors.request.use(function (config) { - sequence += '2'; - return config; - }); - - axios.interceptors.request.use(function (config) { - sequence += '3'; - return config; - }); - - axios({ - url: '/foo', - transitional: { - legacyInterceptorReqResOrdering: false, - }, - }); - - getAjaxRequest().then(function (request) { - expect(sequence).toBe('123'); - done(); - }); - }); - - it('runs the interceptor if runWhen function is provided and resolves to true', function (done) { - function onGetCall(config) { - return config.method === 'get'; - } - axios.interceptors.request.use( - function (config) { - config.headers.test = 'special get headers'; - return config; - }, - null, - { runWhen: onGetCall } - ); - - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.test).toBe('special get headers'); - done(); - }); - }); - - it('does not run the interceptor if runWhen function is provided and resolves to false', function (done) { - function onPostCall(config) { - return config.method === 'post'; - } - axios.interceptors.request.use( - function (config) { - config.headers.test = 'special get headers'; - return config; - }, - null, - { runWhen: onPostCall } - ); - - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.test).toBeUndefined(); - done(); - }); - }); - - it('does not run async interceptor if runWhen function is provided and resolves to false (and run synchronously)', function (done) { - let asyncFlag = false; - - function onPostCall(config) { - return config.method === 'post'; - } - axios.interceptors.request.use( - function (config) { - config.headers.test = 'special get headers'; - return config; - }, - null, - { synchronous: false, runWhen: onPostCall } - ); - - axios.interceptors.request.use( - function (config) { - config.headers.sync = 'hello world'; - expect(asyncFlag).toBe(false); - return config; - }, - null, - { synchronous: true } - ); - - axios('/foo'); - asyncFlag = true; - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.test).toBeUndefined(); - expect(request.requestHeaders.sync).toBe('hello world'); - done(); - }); - }); - - it('should add a request interceptor with an onRejected block that is called if interceptor code fails', function (done) { - const rejectedSpy = jasmine.createSpy('rejectedSpy'); - const error = new Error('deadly error'); - axios.interceptors.request.use( - function () { - throw error; - }, - rejectedSpy, - { synchronous: true } - ); - - axios('/foo').catch(done); - - getAjaxRequest().then(function () { - expect(rejectedSpy).toHaveBeenCalledWith(error); - done(); - }); - }); - - it('should add a request interceptor that returns a new config object', function (done) { - axios.interceptors.request.use(function () { - return { - url: '/bar', - method: 'post', - }; - }); - - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.method).toBe('POST'); - expect(request.url).toBe('/bar'); - done(); - }); - }); - - it('should add a request interceptor that returns a promise', function (done) { - axios.interceptors.request.use(function (config) { - return new Promise(function (resolve) { - // do something async - setTimeout(function () { - config.headers.async = 'promise'; - resolve(config); - }, 100); - }); - }); - - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.async).toBe('promise'); - done(); - }); - }); - - it('should add multiple request interceptors', function (done) { - axios.interceptors.request.use(function (config) { - config.headers.test1 = '1'; - return config; - }); - axios.interceptors.request.use(function (config) { - config.headers.test2 = '2'; - return config; - }); - axios.interceptors.request.use(function (config) { - config.headers.test3 = '3'; - return config; - }); - - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.test1).toBe('1'); - expect(request.requestHeaders.test2).toBe('2'); - expect(request.requestHeaders.test3).toBe('3'); - done(); - }); - }); - - it('should add a response interceptor', function (done) { - let response; - - axios.interceptors.response.use(function (data) { - data.data = data.data + ' - modified by interceptor'; - return data; - }); - - axios('/foo').then(function (data) { - response = data; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - - setTimeout(function () { - expect(response.data).toBe('OK - modified by interceptor'); - done(); - }, 100); - }); - }); - - it('should add a response interceptor when request interceptor is defined', function (done) { - let response; - - axios.interceptors.request.use(function (data) { - return data; - }); - - axios.interceptors.response.use(function (data) { - data.data = data.data + ' - modified by interceptor'; - return data; - }); - - axios('/foo').then(function (data) { - response = data; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - - setTimeout(function () { - expect(response.data).toBe('OK - modified by interceptor'); - done(); - }, 100); - }); - }); - - it('should add a response interceptor that returns a new data object', function (done) { - let response; - - axios.interceptors.response.use(function () { - return { - data: 'stuff', - }; - }); - - axios('/foo').then(function (data) { - response = data; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - - setTimeout(function () { - expect(response.data).toBe('stuff'); - done(); - }, 100); - }); - }); - - it('should add a response interceptor that returns a promise', function (done) { - let response; - - axios.interceptors.response.use(function (data) { - return new Promise(function (resolve) { - // do something async - setTimeout(function () { - data.data = 'you have been promised!'; - resolve(data); - }, 10); - }); - }); - - axios('/foo').then(function (data) { - response = data; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - - setTimeout(function () { - expect(response.data).toBe('you have been promised!'); - done(); - }, 100); - }); - }); - - describe('given you add multiple response interceptors', function () { - describe('and when the response was fulfilled', function () { - function fireRequestAndExpect(expectation) { - let response; - axios('/foo').then(function (data) { - response = data; - }); - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - - setTimeout(function () { - expectation(response); - }, 100); - }); - } - - it('then each interceptor is executed', function (done) { - const interceptor1 = jasmine.createSpy('interceptor1'); - const interceptor2 = jasmine.createSpy('interceptor2'); - axios.interceptors.response.use(interceptor1); - axios.interceptors.response.use(interceptor2); - - fireRequestAndExpect(function () { - expect(interceptor1).toHaveBeenCalled(); - expect(interceptor2).toHaveBeenCalled(); - done(); - }); - }); - - it('then they are executed in the order they were added', function (done) { - const interceptor1 = jasmine.createSpy('interceptor1'); - const interceptor2 = jasmine.createSpy('interceptor2'); - axios.interceptors.response.use(interceptor1); - axios.interceptors.response.use(interceptor2); - - fireRequestAndExpect(function () { - expect(interceptor1).toHaveBeenCalledBefore(interceptor2); - done(); - }); - }); - - it("then only the last interceptor's result is returned", function (done) { - axios.interceptors.response.use(function () { - return 'response 1'; - }); - axios.interceptors.response.use(function () { - return 'response 2'; - }); - - fireRequestAndExpect(function (response) { - expect(response).toBe('response 2'); - done(); - }); - }); - - it("then every interceptor receives the result of it's predecessor", function (done) { - axios.interceptors.response.use(function () { - return 'response 1'; - }); - axios.interceptors.response.use(function (response) { - return [response, 'response 2']; - }); - - fireRequestAndExpect(function (response) { - expect(response).toEqual(['response 1', 'response 2']); - done(); - }); - }); - - describe('and when the fulfillment-interceptor throws', function () { - function fireRequestCatchAndExpect(expectation) { - axios('/foo').catch(function (data) { - // dont handle result - }); - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - - setTimeout(function () { - expectation(); - }, 100); - }); - } - - it('then the following fulfillment-interceptor is not called', function (done) { - axios.interceptors.response.use(function () { - throw Error('throwing interceptor'); - }); - const interceptor2 = jasmine.createSpy('interceptor2'); - axios.interceptors.response.use(interceptor2); - - fireRequestCatchAndExpect(function () { - expect(interceptor2).not.toHaveBeenCalled(); - done(); - }); - }); - - it('then the following rejection-interceptor is called', function (done) { - axios.interceptors.response.use(function () { - throw Error('throwing interceptor'); - }); - const unusedFulfillInterceptor = function () {}; - const rejectIntercept = jasmine.createSpy('rejectIntercept'); - axios.interceptors.response.use(unusedFulfillInterceptor, rejectIntercept); - - fireRequestCatchAndExpect(function () { - expect(rejectIntercept).toHaveBeenCalled(); - done(); - }); - }); - - it('once caught, another following fulfill-interceptor is called again (just like in a promise chain)', function (done) { - axios.interceptors.response.use(function () { - throw Error('throwing interceptor'); - }); - - const unusedFulfillInterceptor = function () {}; - const catchingThrowingInterceptor = function () {}; - axios.interceptors.response.use(unusedFulfillInterceptor, catchingThrowingInterceptor); - - const interceptor3 = jasmine.createSpy('interceptor3'); - axios.interceptors.response.use(interceptor3); - - fireRequestCatchAndExpect(function () { - expect(interceptor3).toHaveBeenCalled(); - done(); - }); - }); - }); - }); - }); - - it('should allow removing interceptors', function (done) { - let response, intercept; - - axios.interceptors.response.use(function (data) { - data.data = data.data + '1'; - return data; - }); - intercept = axios.interceptors.response.use(function (data) { - data.data = data.data + '2'; - return data; - }); - axios.interceptors.response.use(function (data) { - data.data = data.data + '3'; - return data; - }); - - axios.interceptors.response.eject(intercept); - - axios('/foo').then(function (data) { - response = data; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK', - }); - - setTimeout(function () { - expect(response.data).toBe('OK13'); - done(); - }, 100); - }); - }); - - it('should remove async interceptor before making request and execute synchronously', function (done) { - let asyncFlag = false; - const asyncIntercept = axios.interceptors.request.use( - function (config) { - config.headers.async = 'async it!'; - return config; - }, - null, - { synchronous: false } - ); - - axios.interceptors.request.use( - function (config) { - config.headers.sync = 'hello world'; - expect(asyncFlag).toBe(false); - return config; - }, - null, - { synchronous: true } - ); - - axios.interceptors.request.eject(asyncIntercept); - - axios('/foo'); - asyncFlag = true; - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders.async).toBeUndefined(); - expect(request.requestHeaders.sync).toBe('hello world'); - done(); - }); - }); - - it('should execute interceptors before transformers', function (done) { - axios.interceptors.request.use(function (config) { - config.data.baz = 'qux'; - return config; - }); - - axios.post('/foo', { - foo: 'bar', - }); - - getAjaxRequest().then(function (request) { - expect(request.params).toEqual('{"foo":"bar","baz":"qux"}'); - done(); - }); - }); - - it('should modify base URL in request interceptor', function (done) { - const instance = axios.create({ - baseURL: 'http://test.com/', - }); - - instance.interceptors.request.use(function (config) { - config.baseURL = 'http://rebase.com/'; - return config; - }); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('http://rebase.com/foo'); - done(); - }); - }); - - it('should clear all request interceptors', function () { - const instance = axios.create({ - baseURL: 'http://test.com/', - }); - - instance.interceptors.request.use(function (config) { - return config; - }); - - instance.interceptors.request.clear(); - - expect(instance.interceptors.request.handlers.length).toBe(0); - }); - - it('should clear all response interceptors', function () { - const instance = axios.create({ - baseURL: 'http://test.com/', - }); - - instance.interceptors.response.use(function (config) { - return config; - }); - - instance.interceptors.response.clear(); - - expect(instance.interceptors.response.handlers.length).toBe(0); - }); -}); diff --git a/test/specs/options.spec.js b/test/specs/options.spec.js deleted file mode 100644 index 304cd9a5..00000000 --- a/test/specs/options.spec.js +++ /dev/null @@ -1,151 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ - -// import AxiosHeaders from "../../lib/core/AxiosHeaders.js"; -// import isAbsoluteURL from '../../lib/helpers/isAbsoluteURL.js'; - -describe('options', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should default method to get', function (done) { - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.method).toBe('GET'); - done(); - }); - }); - - it('should accept headers', function (done) { - axios('/foo', { - headers: { - 'X-Requested-With': 'XMLHttpRequest', - }, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['X-Requested-With']).toEqual('XMLHttpRequest'); - done(); - }); - }); - - it('should accept params', function (done) { - axios('/foo', { - params: { - foo: 123, - bar: 456, - }, - }); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo?foo=123&bar=456'); - done(); - }); - }); - - it('should allow overriding default headers', function (done) { - axios('/foo', { - headers: { - Accept: 'foo/bar', - }, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['Accept']).toEqual('foo/bar'); - done(); - }); - }); - - it('should accept base URL', function (done) { - const instance = axios.create({ - baseURL: 'http://test.com/', - }); - - instance.get('/foo'); - getAjaxRequest().then(function (request) { - expect(request.url).toBe('http://test.com/foo'); - done(); - }); - }); - - it('should warn about baseUrl', function (done) { - spyOn(window.console, 'warn'); - - const instance = axios.create({ - baseUrl: 'http://example.com/', - }); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - expect(window.console.warn).toHaveBeenCalledWith( - 'baseUrl is likely a misspelling of baseURL' - ); - expect(request.url).toBe('/foo'); - done(); - }); - }); - - it('should ignore base URL if request URL is absolute', function (done) { - const instance = axios.create({ - baseURL: 'http://someurl.com/', - }); - - instance.get('http://someotherurl.com/'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('http://someotherurl.com/'); - done(); - }); - }); - - it('should combine the URLs if base url and request url exist and allowAbsoluteUrls is false', function (done) { - const instance = axios.create({ - baseURL: 'http://someurl.com/', - allowAbsoluteUrls: false, - }); - - instance.get('http://someotherurl.com/'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('http://someurl.com/http://someotherurl.com/'); - done(); - }); - }); - - it('should change only the baseURL of the specified instance', function () { - const instance1 = axios.create(); - const instance2 = axios.create(); - - instance1.defaults.baseURL = 'http://instance1.example.com/'; - - expect(instance2.defaults.baseURL).not.toBe('http://instance1.example.com/'); - }); - - it('should change only the headers of the specified instance', function () { - const instance1 = axios.create(); - const instance2 = axios.create(); - - instance1.defaults.headers.common.Authorization = 'faketoken'; - instance2.defaults.headers.common.Authorization = 'differentfaketoken'; - - instance1.defaults.headers.common['Content-Type'] = 'application/xml'; - instance2.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded'; - - expect(axios.defaults.headers.common.Authorization).toBe(undefined); - expect(instance1.defaults.headers.common.Authorization).toBe('faketoken'); - expect(instance2.defaults.headers.common.Authorization).toBe('differentfaketoken'); - - expect(axios.defaults.headers.common['Content-Type']).toBe(undefined); - expect(instance1.defaults.headers.common['Content-Type']).toBe('application/xml'); - expect(instance2.defaults.headers.common['Content-Type']).toBe( - 'application/x-www-form-urlencoded' - ); - }); -}); diff --git a/test/specs/progress.spec.js b/test/specs/progress.spec.js deleted file mode 100644 index d5b5e865..00000000 --- a/test/specs/progress.spec.js +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -describe('progress events', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should add a download progress handler', function (done) { - const progressSpy = jasmine.createSpy('progress'); - - axios('/foo', { onDownloadProgress: progressSpy }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: '{"foo": "bar"}', - }); - expect(progressSpy).toHaveBeenCalled(); - done(); - }); - }); - - it('should add a upload progress handler', function (done) { - const progressSpy = jasmine.createSpy('progress'); - - axios('/foo', { onUploadProgress: progressSpy }); - - getAjaxRequest().then(function (request) { - // Jasmine AJAX doesn't trigger upload events. Waiting for upstream fix - // expect(progressSpy).toHaveBeenCalled(); - done(); - }); - }); - - it('should add both upload and download progress handlers', function (done) { - const downloadProgressSpy = jasmine.createSpy('downloadProgress'); - const uploadProgressSpy = jasmine.createSpy('uploadProgress'); - - axios('/foo', { onDownloadProgress: downloadProgressSpy, onUploadProgress: uploadProgressSpy }); - - getAjaxRequest().then(function (request) { - // expect(uploadProgressSpy).toHaveBeenCalled(); - expect(downloadProgressSpy).not.toHaveBeenCalled(); - request.respondWith({ - status: 200, - responseText: '{"foo": "bar"}', - }); - expect(downloadProgressSpy).toHaveBeenCalled(); - done(); - }); - }); - - it('should add a download progress handler from instance config', function (done) { - const progressSpy = jasmine.createSpy('progress'); - - const instance = axios.create({ - onDownloadProgress: progressSpy, - }); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: '{"foo": "bar"}', - }); - expect(progressSpy).toHaveBeenCalled(); - done(); - }); - }); - - it('should add a upload progress handler from instance config', function (done) { - const progressSpy = jasmine.createSpy('progress'); - - const instance = axios.create({ - onUploadProgress: progressSpy, - }); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - // expect(progressSpy).toHaveBeenCalled(); - done(); - }); - }); - - it('should add upload and download progress handlers from instance config', function (done) { - const downloadProgressSpy = jasmine.createSpy('downloadProgress'); - const uploadProgressSpy = jasmine.createSpy('uploadProgress'); - - const instance = axios.create({ - onDownloadProgress: downloadProgressSpy, - onUploadProgress: uploadProgressSpy, - }); - - instance.get('/foo'); - - getAjaxRequest().then(function (request) { - // expect(uploadProgressSpy).toHaveBeenCalled(); - expect(downloadProgressSpy).not.toHaveBeenCalled(); - request.respondWith({ - status: 200, - responseText: '{"foo": "bar"}', - }); - expect(downloadProgressSpy).toHaveBeenCalled(); - done(); - }); - }); -}); diff --git a/test/specs/promise.spec.js b/test/specs/promise.spec.js deleted file mode 100644 index 57179cde..00000000 --- a/test/specs/promise.spec.js +++ /dev/null @@ -1,75 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -describe('promise', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should provide succinct object to then', function (done) { - let response; - - axios('/foo').then(function (r) { - response = r; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: '{"hello":"world"}', - }); - - setTimeout(function () { - expect(typeof response).toEqual('object'); - expect(response.data.hello).toEqual('world'); - expect(response.status).toEqual(200); - expect(response.headers['content-type']).toEqual('application/json'); - expect(response.config.url).toEqual('/foo'); - done(); - }, 100); - }); - }); - - it('should support all', function (done) { - let fulfilled = false; - - axios.all([true, 123]).then(function () { - fulfilled = true; - }); - - setTimeout(function () { - expect(fulfilled).toEqual(true); - done(); - }, 100); - }); - - it('should support spread', function (done) { - let sum = 0; - let fulfilled = false; - let result; - - axios - .all([123, 456]) - .then( - axios.spread(function (a, b) { - sum = a + b; - fulfilled = true; - return 'hello world'; - }) - ) - .then(function (res) { - result = res; - }) - .catch(done); - - setTimeout(function () { - expect(fulfilled).toEqual(true); - expect(sum).toEqual(123 + 456); - expect(result).toEqual('hello world'); - done(); - }, 100); - }); -}); diff --git a/test/specs/requests.spec.js b/test/specs/requests.spec.js deleted file mode 100644 index 6480f60b..00000000 --- a/test/specs/requests.spec.js +++ /dev/null @@ -1,547 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -describe('requests', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should treat single string arg as url', function (done) { - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo'); - expect(request.method).toBe('GET'); - done(); - }); - }); - - it('should treat method value as lowercase string', function (done) { - axios({ - url: '/foo', - method: 'POST', - }).then(function (response) { - expect(response.config.method).toBe('post'); - done(); - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - }); - }); - }); - - it('should allow string arg as url, and config arg', function (done) { - axios.post('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo'); - expect(request.method).toBe('POST'); - done(); - }); - }); - - it('should allow data', function (done) { - axios.delete('/foo', { - data: { foo: 'bar' }, - }); - - getAjaxRequest().then(function (request) { - expect(request.params).toBe(JSON.stringify({ foo: 'bar' })); - done(); - }); - }); - - it('should make an http request', function (done) { - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.url).toBe('/foo'); - done(); - }); - }); - - describe('timeouts', function () { - beforeEach(function () { - jasmine.clock().install(); - }); - - afterEach(function () { - jasmine.clock().uninstall(); - }); - - it('should handle timeouts', function (done) { - axios({ - url: '/foo', - timeout: 100, - }).then( - function () { - fail(new Error('timeout error not caught')); - }, - function (err) { - expect(err instanceof Error).toBe(true); - expect(err.code).toEqual('ECONNABORTED'); - done(); - } - ); - - jasmine.Ajax.requests.mostRecent().responseTimeout(); - }); - - describe('transitional.clarifyTimeoutError', function () { - it('should activate throwing ETIMEDOUT instead of ECONNABORTED on request timeouts', function (done) { - axios({ - url: '/foo', - timeout: 100, - transitional: { - clarifyTimeoutError: true, - }, - }).then( - function () { - fail(new Error('timeout error not caught')); - }, - function (err) { - expect(err instanceof Error).toBe(true); - expect(err.code).toEqual('ETIMEDOUT'); - done(); - } - ); - - jasmine.Ajax.requests.mostRecent().responseTimeout(); - }); - }); - }); - - it('should reject on network errors', function (done) { - // disable jasmine.Ajax since we're hitting a non-existent server anyway - jasmine.Ajax.uninstall(); - - const resolveSpy = jasmine.createSpy('resolve'); - const rejectSpy = jasmine.createSpy('reject'); - - const finish = function () { - expect(resolveSpy).not.toHaveBeenCalled(); - expect(rejectSpy).toHaveBeenCalled(); - const reason = rejectSpy.calls.first().args[0]; - expect(reason instanceof Error).toBe(true); - expect(reason.config.method).toBe('get'); - expect(reason.config.url).toBe('http://thisisnotaserver/foo'); - expect(reason.request).toEqual(jasmine.any(XMLHttpRequest)); - - // re-enable jasmine.Ajax - jasmine.Ajax.install(); - - done(); - }; - - axios('http://thisisnotaserver/foo').then(resolveSpy, rejectSpy).then(finish, finish); - }); - - it('should reject on abort', function (done) { - const resolveSpy = jasmine.createSpy('resolve'); - const rejectSpy = jasmine.createSpy('reject'); - - const finish = function () { - expect(resolveSpy).not.toHaveBeenCalled(); - expect(rejectSpy).toHaveBeenCalled(); - const reason = rejectSpy.calls.first().args[0]; - expect(reason instanceof Error).toBe(true); - expect(reason.config.method).toBe('get'); - expect(reason.config.url).toBe('/foo'); - expect(reason.request).toEqual(jasmine.any(XMLHttpRequest)); - - done(); - }; - - axios('/foo').then(resolveSpy, rejectSpy).then(finish, finish); - - getAjaxRequest().then(function (request) { - request.abort(); - }); - }); - - it('should reject when validateStatus returns false', function (done) { - const resolveSpy = jasmine.createSpy('resolve'); - const rejectSpy = jasmine.createSpy('reject'); - - axios('/foo', { - validateStatus: function (status) { - return status !== 500; - }, - }) - .then(resolveSpy) - .catch(rejectSpy) - .then(function () { - expect(resolveSpy).not.toHaveBeenCalled(); - expect(rejectSpy).toHaveBeenCalled(); - const reason = rejectSpy.calls.first().args[0]; - expect(reason instanceof Error).toBe(true); - expect(reason.message).toBe('Request failed with status code 500'); - expect(reason.config.method).toBe('get'); - expect(reason.config.url).toBe('/foo'); - expect(reason.response.status).toBe(500); - - done(); - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 500, - }); - }); - }); - - it('should resolve when validateStatus returns true', function (done) { - const resolveSpy = jasmine.createSpy('resolve'); - const rejectSpy = jasmine.createSpy('reject'); - - axios('/foo', { - validateStatus: function (status) { - return status === 500; - }, - }) - .then(resolveSpy) - .catch(rejectSpy) - .then(function () { - expect(resolveSpy).toHaveBeenCalled(); - expect(rejectSpy).not.toHaveBeenCalled(); - done(); - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 500, - }); - }); - }); - - it('should resolve when the response status is 0 (i.e. requesting with file protocol)', function (done) { - const resolveSpy = jasmine.createSpy('resolve'); - const rejectSpy = jasmine.createSpy('reject'); - - axios('file:///xxx') - .then(resolveSpy) - .catch(rejectSpy) - .then(function () { - expect(resolveSpy).toHaveBeenCalled(); - expect(rejectSpy).not.toHaveBeenCalled(); - done(); - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 0, - responseURL: 'file:///xxx', - }); - }); - }); - - it('should resolve when validateStatus is null', function (done) { - const resolveSpy = jasmine.createSpy('resolve'); - const rejectSpy = jasmine.createSpy('reject'); - - axios('/foo', { - validateStatus: null, - }) - .then(resolveSpy) - .catch(rejectSpy) - .then(function () { - expect(resolveSpy).toHaveBeenCalled(); - expect(rejectSpy).not.toHaveBeenCalled(); - done(); - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 500, - }); - }); - }); - - it('should resolve when validateStatus is undefined', function (done) { - const resolveSpy = jasmine.createSpy('resolve'); - const rejectSpy = jasmine.createSpy('reject'); - - axios('/foo', { - validateStatus: undefined, - }) - .then(resolveSpy) - .catch(rejectSpy) - .then(function () { - expect(resolveSpy).toHaveBeenCalled(); - expect(rejectSpy).not.toHaveBeenCalled(); - done(); - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 500, - }); - }); - }); - - // https://github.com/axios/axios/issues/378 - it('should return JSON when rejecting', function (done) { - let response; - - axios( - '/api/account/signup', - { - username: null, - password: null, - }, - { - method: 'post', - headers: { - Accept: 'application/json', - }, - } - ).catch(function (error) { - response = error.response; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 400, - statusText: 'Bad Request', - responseText: '{"error": "BAD USERNAME", "code": 1}', - }); - - setTimeout(function () { - expect(typeof response.data).toEqual('object'); - expect(response.data.error).toEqual('BAD USERNAME'); - expect(response.data.code).toEqual(1); - done(); - }, 100); - }); - }); - - it('should make cross domain http request', function (done) { - let response; - - axios.post('www.someurl.com/foo').then(function (res) { - response = res; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - statusText: 'OK', - responseText: '{"foo": "bar"}', - headers: { - 'Content-Type': 'application/json', - }, - }); - - setTimeout(function () { - expect(response.data.foo).toEqual('bar'); - expect(response.status).toEqual(200); - expect(response.statusText).toEqual('OK'); - expect(response.headers['content-type']).toEqual('application/json'); - done(); - }, 100); - }); - }); - - it('should supply correct response', function (done) { - let response; - - axios.post('/foo').then(function (res) { - response = res; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - statusText: 'OK', - responseText: '{"foo": "bar"}', - headers: { - 'Content-Type': 'application/json', - }, - }); - - setTimeout(function () { - expect(response.data.foo).toEqual('bar'); - expect(response.status).toEqual(200); - expect(response.statusText).toEqual('OK'); - expect(response.headers['content-type']).toEqual('application/json'); - done(); - }, 100); - }); - }); - - it('should not modify the config url with relative baseURL', function (done) { - let config; - - axios - .get('/foo', { - baseURL: '/api', - }) - .catch(function (error) { - config = error.config; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 404, - statusText: 'NOT FOUND', - responseText: 'Resource not found', - }); - - setTimeout(function () { - expect(config.baseURL).toEqual('/api'); - expect(config.url).toEqual('/foo'); - done(); - }, 100); - }); - }); - - it('should allow overriding Content-Type header case-insensitive', function (done) { - let response; - const contentType = 'application/vnd.myapp.type+json'; - - axios - .post( - '/foo', - { prop: 'value' }, - { - headers: { - 'Content-Type': contentType, - }, - } - ) - .then(function (res) { - response = res; - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['Content-Type']).toEqual(contentType); - done(); - }); - }); - - it('should support binary data as array buffer', function (done) { - const input = new Int8Array(2); - input[0] = 1; - input[1] = 2; - - axios.post('/foo', input.buffer); - - getAjaxRequest().then(function (request) { - const output = new Int8Array(request.params); - expect(output.length).toEqual(2); - expect(output[0]).toEqual(1); - expect(output[1]).toEqual(2); - done(); - }); - }); - - it('should support binary data as array buffer view', function (done) { - const input = new Int8Array(2); - input[0] = 1; - input[1] = 2; - - axios.post('/foo', input); - - getAjaxRequest().then(function (request) { - const output = new Int8Array(request.params); - expect(output.length).toEqual(2); - expect(output[0]).toEqual(1); - expect(output[1]).toEqual(2); - done(); - }); - }); - - it('should support array buffer response', function (done) { - let response; - - function str2ab(str) { - const buff = new ArrayBuffer(str.length * 2); - const view = new Uint16Array(buff); - for (let i = 0, l = str.length; i < l; i++) { - view[i] = str.charCodeAt(i); - } - return buff; - } - - axios('/foo', { - responseType: 'arraybuffer', - }).then(function (data) { - response = data; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - response: str2ab('Hello world'), - }); - - setTimeout(function () { - expect(response.data.byteLength).toBe(22); - done(); - }, 100); - }); - }); - - it('should support URLSearchParams', function (done) { - const params = new URLSearchParams(); - params.append('param1', 'value1'); - params.append('param2', 'value2'); - - axios.post('/foo', params); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['Content-Type']).toBe( - 'application/x-www-form-urlencoded;charset=utf-8' - ); - expect(request.params).toBe('param1=value1¶m2=value2'); - done(); - }); - }); - - it('should support HTTP protocol', function (done) { - let response; - - axios.get('/foo').then(function (res) { - response = res; - }); - - getAjaxRequest().then(function (request) { - expect(request.method).toBe('GET'); - request.respondWith({ - status: 200, - }); - done(); - }); - }); - - it('should support HTTPS protocol', function (done) { - let response; - axios.get('https://www.google.com').then(function (res) { - response = res; - }); - - getAjaxRequest().then(function (request) { - expect(request.method).toBe('GET'); - request.respondWith({ - status: 200, - }); - done(); - }); - }); - - it('should return unsupported protocol error message', function () { - return axios.get('ftp:localhost').then( - function () { - fail('Does not throw'); - }, - function (error) { - expect(error.message).toEqual('Unsupported protocol ftp:'); - } - ); - }); -}); diff --git a/test/specs/transform.spec.js b/test/specs/transform.spec.js deleted file mode 100644 index f6fcaff2..00000000 --- a/test/specs/transform.spec.js +++ /dev/null @@ -1,238 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -import AxiosError from '../../lib/core/AxiosError'; - -describe('transform', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - jasmine.Ajax.uninstall(); - }); - - it('should transform JSON to string', function (done) { - const data = { - foo: 'bar', - }; - - axios.post('/foo', data); - - getAjaxRequest().then(function (request) { - expect(request.params).toEqual('{"foo":"bar"}'); - done(); - }); - }); - - it('should transform string to JSON', function (done) { - let response; - - axios('/foo').then(function (data) { - response = data; - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: '{"foo": "bar"}', - }); - - setTimeout(function () { - expect(typeof response.data).toEqual('object'); - expect(response.data.foo).toEqual('bar'); - done(); - }, 100); - }); - }); - - it('should throw a SyntaxError if JSON parsing failed and responseType is "json" if silentJSONParsing is false', function (done) { - let thrown; - - axios({ - url: '/foo', - responseType: 'json', - transitional: { silentJSONParsing: false }, - }).then( - function () { - done(new Error('should fail')); - }, - function (err) { - thrown = err; - } - ); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: '{foo": "bar"}', // JSON SyntaxError - }); - - setTimeout(function () { - expect(thrown).toBeTruthy(); - expect(thrown.name).toContain('SyntaxError'); - expect(thrown.code).toEqual(AxiosError.ERR_BAD_RESPONSE); - done(); - }, 100); - }); - }); - - it('should send data as JSON if request content-type is application/json', function (done) { - let response; - - axios.post('/foo', 123, { headers: { 'Content-Type': 'application/json' } }).then( - function (_response) { - response = _response; - }, - function (err) { - done(err); - } - ); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: '', - }); - - setTimeout(function () { - expect(response).toBeTruthy(); - expect(request.requestHeaders['Content-Type']).toBe('application/json'); - expect(JSON.parse(request.params)).toBe(123); - done(); - }, 100); - }); - }); - - it('should not assume JSON if responseType is not `json`', function (done) { - let response; - - axios - .get('/foo', { - responseType: 'text', - transitional: { - forcedJSONParsing: false, - }, - }) - .then( - function (_response) { - response = _response; - }, - function (err) { - done(err); - } - ); - - const rawData = '{"x":1}'; - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: rawData, - }); - - setTimeout(function () { - expect(response).toBeTruthy(); - expect(response.data).toBe(rawData); - done(); - }, 100); - }); - }); - - it('should override default transform', function (done) { - const data = { - foo: 'bar', - }; - - axios.post('/foo', data, { - transformRequest: function (data) { - return data; - }, - }); - - getAjaxRequest().then(function (request) { - expect(typeof request.params).toEqual('object'); - done(); - }); - }); - - it('should allow an Array of transformers', function (done) { - const data = { - foo: 'bar', - }; - - axios.post('/foo', data, { - transformRequest: axios.defaults.transformRequest.concat(function (data) { - return data.replace('bar', 'baz'); - }), - }); - - getAjaxRequest().then(function (request) { - expect(request.params).toEqual('{"foo":"baz"}'); - done(); - }); - }); - - it('should allowing mutating headers', function (done) { - const token = Math.floor(Math.random() * Math.pow(2, 64)).toString(36); - - axios('/foo', { - transformRequest: function (data, headers) { - headers['X-Authorization'] = token; - }, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['X-Authorization']).toEqual(token); - done(); - }); - }); - - it("should normalize 'content-type' header when using a custom transformRequest", function (done) { - const data = { - foo: 'bar', - }; - - axios.post('/foo', data, { - headers: { 'content-type': 'application/x-www-form-urlencoded' }, - transformRequest: [ - function () { - return 'aa=44'; - }, - ], - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders['Content-Type']).toEqual('application/x-www-form-urlencoded'); - done(); - }); - }); - - it('should return response.data as parsed JSON object when responseType is json', function (done) { - const instance = axios.create({ - baseURL: '/api', - transformResponse: [ - function (data) { - return data; - }, - ], - responseType: 'json', - }); - - instance - .get('my/endpoint', { responseType: 'json' }) - .then((response) => { - expect(typeof response).toBe('object'); - done(); - }) - .catch((err) => { - done(err); - }); - - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: '{"key1": "value1"}', - }); - }); - }); -}); diff --git a/test/specs/utils/endsWith.js b/test/specs/utils/endsWith.js deleted file mode 100644 index edc41291..00000000 --- a/test/specs/utils/endsWith.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -const { kindOf } = utils; - -describe('utils::kindOf', function () { - it('should return object tag', function () { - expect(kindOf({})).toEqual('object'); - // cached result - expect(kindOf({})).toEqual('object'); - expect(kindOf([])).toEqual('array'); - }); -}); diff --git a/test/specs/utils/extend.spec.js b/test/specs/utils/extend.spec.js deleted file mode 100644 index 5e43a02a..00000000 --- a/test/specs/utils/extend.spec.js +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -const { extend } = utils; - -describe('utils::extend', function () { - it('should be mutable', function () { - const a = {}; - const b = { foo: 123 }; - - extend(a, b); - - expect(a.foo).toEqual(b.foo); - }); - - it('should extend properties', function () { - let a = { foo: 123, bar: 456 }; - const b = { bar: 789 }; - - a = extend(a, b); - - expect(a.foo).toEqual(123); - expect(a.bar).toEqual(789); - }); - - it('should bind to thisArg', function () { - const a = {}; - const b = { - getFoo: function getFoo() { - return this.foo; - }, - }; - const thisArg = { foo: 'barbaz' }; - - extend(a, b, thisArg); - - expect(typeof a.getFoo).toEqual('function'); - expect(a.getFoo()).toEqual(thisArg.foo); - }); -}); diff --git a/test/specs/utils/forEach.spec.js b/test/specs/utils/forEach.spec.js deleted file mode 100644 index 9745c917..00000000 --- a/test/specs/utils/forEach.spec.js +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -const { forEach } = utils; - -describe('utils::forEach', function () { - it('should loop over an array', function () { - let sum = 0; - - forEach([1, 2, 3, 4, 5], function (val) { - sum += val; - }); - - expect(sum).toEqual(15); - }); - - it('should loop over object keys', function () { - let keys = ''; - let vals = 0; - const obj = { - b: 1, - a: 2, - r: 3, - }; - - forEach(obj, function (v, k) { - keys += k; - vals += v; - }); - - expect(keys).toEqual('bar'); - expect(vals).toEqual(6); - }); - - it('should handle undefined gracefully', function () { - let count = 0; - - forEach(undefined, function () { - count++; - }); - - expect(count).toEqual(0); - }); - - it('should make an array out of non-array argument', function () { - let count = 0; - - forEach( - function () {}, - function () { - count++; - } - ); - - expect(count).toEqual(1); - }); - - it('should handle non object prototype gracefully', function () { - let count = 0; - const data = Object.create(null); - data.foo = 'bar'; - - forEach(data, function () { - count++; - }); - - expect(count).toEqual(1); - }); -}); diff --git a/test/specs/utils/isX.spec.js b/test/specs/utils/isX.spec.js deleted file mode 100644 index 0033a34d..00000000 --- a/test/specs/utils/isX.spec.js +++ /dev/null @@ -1,80 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -describe('utils::isX', function () { - it('should validate Array', function () { - expect(utils.isArray([])).toEqual(true); - expect(utils.isArray({ length: 5 })).toEqual(false); - }); - - it('should validate ArrayBuffer', function () { - expect(utils.isArrayBuffer(new ArrayBuffer(2))).toEqual(true); - expect(utils.isArrayBuffer({})).toEqual(false); - }); - - it('should validate ArrayBufferView', function () { - expect(utils.isArrayBufferView(new DataView(new ArrayBuffer(2)))).toEqual(true); - }); - - it('should validate FormData', function () { - expect(utils.isFormData(new FormData())).toEqual(true); - }); - - it('should validate Blob', function () { - expect(utils.isBlob(new Blob())).toEqual(true); - }); - - it('should validate String', function () { - expect(utils.isString('')).toEqual(true); - expect( - utils.isString({ - toString: function () { - return ''; - }, - }) - ).toEqual(false); - }); - - it('should validate Number', function () { - expect(utils.isNumber(123)).toEqual(true); - expect(utils.isNumber('123')).toEqual(false); - }); - - it('should validate Undefined', function () { - expect(utils.isUndefined()).toEqual(true); - expect(utils.isUndefined(null)).toEqual(false); - }); - - it('should validate Object', function () { - expect(utils.isObject({})).toEqual(true); - expect(utils.isObject([])).toEqual(true); - expect(utils.isObject(null)).toEqual(false); - }); - - it('should validate plain Object', function () { - expect(utils.isPlainObject({})).toEqual(true); - expect(utils.isPlainObject([])).toEqual(false); - expect(utils.isPlainObject(null)).toEqual(false); - expect(utils.isPlainObject(Object.create({}))).toEqual(false); - }); - - it('should validate Date', function () { - expect(utils.isDate(new Date())).toEqual(true); - expect(utils.isDate(Date.now())).toEqual(false); - }); - - it('should validate Function', function () { - expect(utils.isFunction(function () {})).toEqual(true); - expect(utils.isFunction('function')).toEqual(false); - }); - - it('should validate URLSearchParams', function () { - expect(utils.isURLSearchParams(new URLSearchParams())).toEqual(true); - expect(utils.isURLSearchParams('foo=1&bar=2')).toEqual(false); - }); - - it('should validate TypedArray instance', function () { - expect(utils.isTypedArray(new Uint8Array([1, 2, 3]))).toEqual(true); - expect(utils.isTypedArray([1, 2, 3])).toEqual(false); - }); -}); diff --git a/test/specs/utils/kindOf.js b/test/specs/utils/kindOf.js deleted file mode 100644 index edc41291..00000000 --- a/test/specs/utils/kindOf.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -const { kindOf } = utils; - -describe('utils::kindOf', function () { - it('should return object tag', function () { - expect(kindOf({})).toEqual('object'); - // cached result - expect(kindOf({})).toEqual('object'); - expect(kindOf([])).toEqual('array'); - }); -}); diff --git a/test/specs/utils/kindOfTest.js b/test/specs/utils/kindOfTest.js deleted file mode 100644 index 7891ac47..00000000 --- a/test/specs/utils/kindOfTest.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-env mocha */ -import { kindOfTest } from '../../../lib/utils'; - -describe('utils::kindOfTest', function () { - it('should return true if the type is matched', function () { - const test = kindOfTest('number'); - - expect(test(123)).toEqual(true); - expect(test('123')).toEqual(false); - }); -}); diff --git a/test/specs/utils/merge.spec.js b/test/specs/utils/merge.spec.js deleted file mode 100644 index 0cba2efd..00000000 --- a/test/specs/utils/merge.spec.js +++ /dev/null @@ -1,97 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -const { merge } = utils; - -describe('utils::merge', function () { - it('should be immutable', function () { - const a = {}; - const b = { foo: 123 }; - const c = { bar: 456 }; - - merge(a, b, c); - - expect(typeof a.foo).toEqual('undefined'); - expect(typeof a.bar).toEqual('undefined'); - expect(typeof b.bar).toEqual('undefined'); - expect(typeof c.foo).toEqual('undefined'); - }); - - it('should merge properties', function () { - const a = { foo: 123 }; - const b = { bar: 456 }; - const c = { foo: 789 }; - const d = merge(a, b, c); - - expect(d.foo).toEqual(789); - expect(d.bar).toEqual(456); - }); - - it('should merge recursively', function () { - const a = { foo: { bar: 123 } }; - const b = { foo: { baz: 456 }, bar: { qux: 789 } }; - - expect(merge(a, b)).toEqual({ - foo: { - bar: 123, - baz: 456, - }, - bar: { - qux: 789, - }, - }); - }); - - it('should remove all references from nested objects', function () { - const a = { foo: { bar: 123 } }; - const b = {}; - const d = merge(a, b); - - expect(d).toEqual({ - foo: { - bar: 123, - }, - }); - - expect(d.foo).not.toBe(a.foo); - }); - - it('handles null and undefined arguments', function () { - expect(merge(undefined, undefined)).toEqual({}); - expect(merge(undefined, { foo: 123 })).toEqual({ foo: 123 }); - expect(merge({ foo: 123 }, undefined)).toEqual({ foo: 123 }); - - expect(merge(null, null)).toEqual({}); - expect(merge(null, { foo: 123 })).toEqual({ foo: 123 }); - expect(merge({ foo: 123 }, null)).toEqual({ foo: 123 }); - }); - - it('should replace properties with null', function () { - expect(merge({}, { a: null })).toEqual({ a: null }); - expect(merge({ a: null }, {})).toEqual({ a: null }); - }); - - it('should replace properties with arrays', function () { - expect(merge({}, { a: [1, 2, 3] })).toEqual({ a: [1, 2, 3] }); - expect(merge({ a: 2 }, { a: [1, 2, 3] })).toEqual({ a: [1, 2, 3] }); - expect(merge({ a: { b: 2 } }, { a: [1, 2, 3] })).toEqual({ a: [1, 2, 3] }); - }); - - it('should replace properties with cloned arrays', function () { - const a = [1, 2, 3]; - const d = merge({}, { a: a }); - - expect(d).toEqual({ a: [1, 2, 3] }); - expect(d.a).not.toBe(a); - }); - - it('should support caseless option', () => { - const a = { x: 1 }; - const b = { X: 2 }; - const merged = merge.call({ caseless: true }, a, b); - - expect(merged).toEqual({ - x: 2, - }); - }); -}); diff --git a/test/specs/utils/toArray.js b/test/specs/utils/toArray.js deleted file mode 100644 index 752917a4..00000000 --- a/test/specs/utils/toArray.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -const { toArray } = utils; - -describe('utils::kindOf', function () { - it('should return object tag', function () { - expect(toArray()).toEqual(null); - expect(toArray([])).toEqual([]); - expect(toArray([1])).toEqual([1]); - expect(toArray([1, 2, 3])).toEqual([1, 2, 3]); - }); -}); diff --git a/test/specs/utils/toFlatObject.js b/test/specs/utils/toFlatObject.js deleted file mode 100644 index b36e654d..00000000 --- a/test/specs/utils/toFlatObject.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -const { toFlatObject } = utils; - -describe('utils::toFlatObject', function () { - it('should resolve object proto chain to a flat object representation', function () { - const a = { x: 1 }; - const b = Object.create(a, { y: { value: 2 } }); - const c = Object.create(b, { z: { value: 3 } }); - expect(toFlatObject(c)).toEqual({ x: 1, y: 2, z: 3 }); - }); -}); diff --git a/test/specs/utils/trim.spec.js b/test/specs/utils/trim.spec.js deleted file mode 100644 index 90131a7d..00000000 --- a/test/specs/utils/trim.spec.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-env mocha */ -import utils from '../../../lib/utils'; - -describe('utils::trim', function () { - it('should trim spaces', function () { - expect(utils.trim(' foo ')).toEqual('foo'); - }); - - it('should trim tabs', function () { - expect(utils.trim('\tfoo\t')).toEqual('foo'); - }); -}); diff --git a/test/specs/xsrf.spec.js b/test/specs/xsrf.spec.js deleted file mode 100644 index 91761b91..00000000 --- a/test/specs/xsrf.spec.js +++ /dev/null @@ -1,148 +0,0 @@ -/* eslint-env mocha */ -/* global jasmine */ -import cookies from '../../lib/helpers/cookies'; - -describe('xsrf', function () { - beforeEach(function () { - jasmine.Ajax.install(); - }); - - afterEach(function () { - document.cookie = - axios.defaults.xsrfCookieName + '=;expires=' + new Date(Date.now() - 86400000).toGMTString(); - jasmine.Ajax.uninstall(); - }); - - it('should not set xsrf header if cookie is null', function (done) { - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); - done(); - }); - }); - - it('should set xsrf header if cookie is set', function (done) { - document.cookie = axios.defaults.xsrfCookieName + '=12345'; - - axios('/foo'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual('12345'); - done(); - }); - }); - - it('should not set xsrf header if xsrfCookieName is null', function (done) { - document.cookie = axios.defaults.xsrfCookieName + '=12345'; - - axios('/foo', { - xsrfCookieName: null, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); - done(); - }); - }); - - it('should not read cookies at all if xsrfCookieName is null', function (done) { - spyOn(cookies, 'read'); - - axios('/foo', { - xsrfCookieName: null, - }); - - getAjaxRequest().then(function (request) { - expect(cookies.read).not.toHaveBeenCalled(); - done(); - }); - }); - - it('should not set xsrf header for cross origin', function (done) { - document.cookie = axios.defaults.xsrfCookieName + '=12345'; - - axios('http://example.com/'); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); - done(); - }); - }); - - it('should not set xsrf header for cross origin when using withCredentials', function (done) { - document.cookie = axios.defaults.xsrfCookieName + '=12345'; - - axios('http://example.com/', { - withCredentials: true, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); - done(); - }); - }); - - describe('withXSRFToken option', function () { - it('should set xsrf header for cross origin when withXSRFToken = true', function (done) { - const token = '12345'; - - document.cookie = axios.defaults.xsrfCookieName + '=' + token; - - axios('http://example.com/', { - withXSRFToken: true, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(token); - done(); - }); - }); - - it('should not set xsrf header for the same origin when withXSRFToken = false', function (done) { - const token = '12345'; - - document.cookie = axios.defaults.xsrfCookieName + '=' + token; - - axios('/foo', { - withXSRFToken: false, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); - done(); - }); - }); - - it('should not set xsrf header for the same origin when withXSRFToken = false', function (done) { - const token = '12345'; - - document.cookie = axios.defaults.xsrfCookieName + '=' + token; - - axios('/foo', { - withXSRFToken: false, - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); - done(); - }); - }); - - it('should support function resolver', (done) => { - const token = '12345'; - - document.cookie = axios.defaults.xsrfCookieName + '=' + token; - - axios('/foo', { - withXSRFToken: (config) => config.userFlag === 'yes', - userFlag: 'yes', - }); - - getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(token); - done(); - }); - }); - }); -}); diff --git a/test/unit/adapters/adapters.js b/test/unit/adapters/adapters.js deleted file mode 100644 index c81cd301..00000000 --- a/test/unit/adapters/adapters.js +++ /dev/null @@ -1,48 +0,0 @@ -/* eslint-env mocha */ -import adapters from '../../../lib/adapters/adapters.js'; -import assert from 'assert'; - -describe('adapters', function () { - const store = { ...adapters.adapters }; - - beforeEach(() => { - Object.keys(adapters.adapters).forEach((name) => { - delete adapters.adapters[name]; - }); - - Object.assign(adapters.adapters, store); - }); - - it('should support loading by fn handle', function () { - const adapter = () => {}; - assert.strictEqual(adapters.getAdapter(adapter), adapter); - }); - - it('should support loading by name', function () { - const adapter = () => {}; - adapters.adapters['testadapter'] = adapter; - assert.strictEqual(adapters.getAdapter('testAdapter'), adapter); - }); - - it('should detect adapter unavailable status', function () { - adapters.adapters['testadapter'] = null; - assert.throws(() => adapters.getAdapter('testAdapter'), /is not available in the build/); - }); - - it('should detect adapter unsupported status', function () { - adapters.adapters['testadapter'] = false; - assert.throws(() => adapters.getAdapter('testAdapter'), /is not supported by the environment/); - }); - - it('should pick suitable adapter from the list', function () { - const adapter = () => {}; - - Object.assign(adapters.adapters, { - foo: false, - bar: null, - baz: adapter, - }); - - assert.strictEqual(adapters.getAdapter(['foo', 'bar', 'baz']), adapter); - }); -}); diff --git a/test/unit/adapters/axios.png b/test/unit/adapters/axios.png deleted file mode 100644 index 8511175953c2ef062ebb6d073df7715a4037a7f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1716 zcmah~>08o?8pUPYQWI2~NG&GZmrRXter~w0hzld6xs*aST8Ilw)5I0G%$o~2gq9Aj zh?bO^x!gOZb*EH79nCR!YYlwPQbNjGUQ{3k;beZYCD5Qq^xPzKS25=`5G3sj z6lRG>X&{h_pPwf>oEE)$yH{v^N;4-h&!vH(W&D5?aKOq;aYQKq#$lK`t0NFlU#sG4 zF8v`6f4oOv&czT*YHGM!!9=O9WWs)}peQSg`?^Cu--(hr(QFEVgOvquL|Kx*i|{Fu zVAt(*@d?+xvrvlL)t|w;yKm=Oq)#vR?ACnaX2TL=5jn|d@WqsC+p^#nzmVHe507o( zAb*~2gbvuPVkq<-G1szZXF2tvKg91b3!82GO5oTihF#A^n{Ipv&~)g}M$ zI=N2opw}&oJ;1mzRW6I<&CW2bi!iTpor4LIfu`V>f-C`>3~?N)Fj9^Bge=1F7?`+J zS?#wLH;Z%4sI{4T7Ut{H;j6Z9#g@Idrt=pY={NA1S(YJ?*zYDhvNt4?cLBhf*+tKE zRNVR@sMjcX3oZ}57O<^JrQE>nDatjwl7iysfq@;jR(Zn_M0%2fa+}KP*o*=4;rU8E zwT6?%UNrM>J$i%Fa(hl9ez~%YGbWL!~VHXG$hwYt#d- zF;#~1L%S#0W=Lk{_1f<6eKu5Rny`rhYlK%WAZ(2(n8p-06eb_HWU2`VF^1i(>HoUY z*=CJN7(C-5PzdAI=6bZmcZ_a(5&+_Q1M0!O)n2_sim+aZx~aUO#Dp-Xz?a6$0p?iq`v_>j?oI2lm-2_9TM&&C`k( ztP2t2o?%#Yc7nCmk|gbOtH(rQXC$@!W!dX9<~z3BfWd{8^QvD?InI;2wI}0{I#oQZE^Tg%ai2EibVx}3FI~> zF}a=w%+C?AnG*NewY${=_#^BU}zQt*t zQSR$-LIXvI!o3MXl)t#w|Gh1q_pT8uN9VtaURnXCn zPciy;3V>I^gDpsz+Ww5iScNF}g$WlkuX_CI#{m&UhnaoJTGUFUxl*+O&JUmB2~7sj*MJ(lr* D`%5b= diff --git a/test/unit/adapters/cert.pem b/test/unit/adapters/cert.pem deleted file mode 100644 index 42dcc29b..00000000 --- a/test/unit/adapters/cert.pem +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICpDCCAYwCCQDbqELLwgbPdDANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls -b2NhbGhvc3QwHhcNMjAwNjI2MjIxMTQ3WhcNNDcxMTExMjIxMTQ3WjAUMRIwEAYD -VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD6 -Ogt99/dZ0UgbCuVV1RZ9n28Ov3DzrJCkjperQoXomIq3Fr4RUI1a2rwe3mtl3UzE -1IVZVvWPGdEsEQHwXfAsP/jFGTwI3HDyOhcqzFQSKsjvqJWYkOOb+2r3SBrFlRZW -09k/3lC+hx2XtuuG68u4Xgn3AlUvm2vplgCN7eiYcGeNwVuf2eHdOqTRTqiYCZLi -T8GtdYMDXOrwsGZs/jUKd9U0ar/lqwMhmw07yzlVDM2MWM2tyq/asQ7Sf7vuoMFu -oAtDJ3E+bK1k/7SNhdyP4RonhyUCkWG+mzoKDS1qgXroTiQSDUksAvOCTcj8BNIT -ee+Lcn9FaTKNJiKiU9q/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFi5ZpaUj+mU -dsgOka+j2/njgNXux3cOjhm7z/N7LeTuDENAOrYa5b+j5JX/YM7RKHrkbXHsQbfs -GB3ufH6QhSiCd/AdsXp/TbCE/8gdq8ykkjwVP1bvBle9oPH7x1aO/WP/odsepYUv -o9aOZW4iNQVmwamU62ezglf3QD7HPeE4LnZueaFtuzRoC+aWT9v0MIeUPJLe3WDQ -FEySwUuthMDJEv92/TeK0YOiunmseCu2mvdiDj6E3C9xa5q2DWgl+msu7+bPgvYO -GuWaoNeQQGk7ebBO3Hk3IyaGx6Cbd8ty+YaZW7dUT+m7KCs1VkxdcDMjZJVWiJy4 -4HcEcKboG4Y= ------END CERTIFICATE----- diff --git a/test/unit/adapters/error-details.spec.js b/test/unit/adapters/error-details.spec.js deleted file mode 100644 index 003a39d0..00000000 --- a/test/unit/adapters/error-details.spec.js +++ /dev/null @@ -1,90 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import https from 'https'; -import net from 'net'; -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import axios from '../../../index.js'; - -/** __dirname replacement for ESM */ -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -/** Get a port that will refuse connections: bind to a random port and close it. */ -async function getClosedPort() { - return await new Promise((resolve) => { - const srv = net.createServer(); - srv.listen(0, '127.0.0.1', () => { - const { port } = srv.address(); - srv.close(() => resolve(port)); - }); - }); -} - -describe('adapters – network-error details', function () { - this.timeout(5000); - - it('should expose ECONNREFUSED and set error.cause on connection refusal', async function () { - const port = await getClosedPort(); - - try { - await axios.get(`http://127.0.0.1:${port}`, { timeout: 500 }); - assert.fail('request unexpectedly succeeded'); - } catch (err) { - assert.ok(err instanceof Error, 'should be an Error'); - assert.strictEqual(err.isAxiosError, true, 'isAxiosError should be true'); - - // New behavior: Node error code is surfaced and original error is linked via cause - assert.strictEqual(err.code, 'ECONNREFUSED'); - assert.ok('cause' in err, 'error.cause should exist'); - assert.ok(err.cause instanceof Error, 'cause should be an Error'); - assert.strictEqual(err.cause && err.cause.code, 'ECONNREFUSED'); - - // Message remains a string (content may include the code prefix) - assert.strictEqual(typeof err.message, 'string'); - } - }); - - it('should expose self-signed TLS error and set error.cause', async function () { - // Use the same certs already present for adapter tests in this folder - const keyPath = path.join(__dirname, 'key.pem'); - const certPath = path.join(__dirname, 'cert.pem'); - - const key = fs.readFileSync(keyPath); - const cert = fs.readFileSync(certPath); - - const httpsServer = https.createServer({ key, cert }, (req, res) => res.end('ok')); - - await new Promise((resolve) => httpsServer.listen(0, '127.0.0.1', resolve)); - const { port } = httpsServer.address(); - - try { - await axios.get(`https://127.0.0.1:${port}`, { - timeout: 500, - httpsAgent: new https.Agent({ rejectUnauthorized: true }), // Explicit: reject self-signed - }); - assert.fail('request unexpectedly succeeded'); - } catch (err) { - const codeStr = String(err.code); - // OpenSSL/Node variants: SELF_SIGNED_CERT_IN_CHAIN, DEPTH_ZERO_SELF_SIGNED_CERT, UNABLE_TO_VERIFY_LEAF_SIGNATURE - assert.ok( - /SELF_SIGNED|UNABLE_TO_VERIFY_LEAF_SIGNATURE|DEPTH_ZERO/.test(codeStr), - 'unexpected TLS code: ' + codeStr - ); - - assert.ok('cause' in err, 'error.cause should exist'); - assert.ok(err.cause instanceof Error, 'cause should be an Error'); - - const causeCode = String(err.cause && err.cause.code); - assert.ok( - /SELF_SIGNED|UNABLE_TO_VERIFY_LEAF_SIGNATURE|DEPTH_ZERO/.test(causeCode), - 'unexpected cause code: ' + causeCode - ); - - assert.strictEqual(typeof err.message, 'string'); - } finally { - await new Promise((resolve) => httpsServer.close(resolve)); - } - }); -}); diff --git a/test/unit/adapters/fetch.js b/test/unit/adapters/fetch.js deleted file mode 100644 index c18f1740..00000000 --- a/test/unit/adapters/fetch.js +++ /dev/null @@ -1,541 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import { - startHTTPServer, - stopHTTPServer, - LOCAL_SERVER_URL, - setTimeoutAsync, - makeReadableStream, - generateReadable, - makeEchoStream, -} from '../../helpers/server.js'; -import axios from '../../../index.js'; -import stream from 'stream'; -import { AbortController } from 'abortcontroller-polyfill/dist/cjs-ponyfill.js'; -import util from 'util'; - -const pipelineAsync = util.promisify(stream.pipeline); - -const fetchAxios = axios.create({ - baseURL: LOCAL_SERVER_URL, - adapter: 'fetch', -}); - -let server; - -describe('supports fetch with nodejs', function () { - before(function () { - if (typeof fetch !== 'function') { - this.skip(); - } - }); - - afterEach(async function () { - await stopHTTPServer(server); - - server = null; - }); - - describe('responses', async () => { - it(`should support text response type`, async () => { - const originalData = 'my data'; - - server = await startHTTPServer((req, res) => res.end(originalData)); - - const { data } = await fetchAxios.get('/', { - responseType: 'text', - }); - - assert.deepStrictEqual(data, originalData); - }); - - it(`should support arraybuffer response type`, async () => { - const originalData = 'my data'; - - server = await startHTTPServer((req, res) => res.end(originalData)); - - const { data } = await fetchAxios.get('/', { - responseType: 'arraybuffer', - }); - - assert.deepStrictEqual( - data, - Uint8Array.from(await new TextEncoder().encode(originalData)).buffer - ); - }); - - it(`should support blob response type`, async () => { - const originalData = 'my data'; - - server = await startHTTPServer((req, res) => res.end(originalData)); - - const { data } = await fetchAxios.get('/', { - responseType: 'blob', - }); - - assert.deepStrictEqual(data, new Blob([originalData])); - }); - - it(`should support stream response type`, async () => { - const originalData = 'my data'; - - server = await startHTTPServer((req, res) => res.end(originalData)); - - const { data } = await fetchAxios.get('/', { - responseType: 'stream', - }); - - assert.ok(data instanceof ReadableStream, 'data is not instanceof ReadableStream'); - - let response = new Response(data); - - assert.deepStrictEqual(await response.text(), originalData); - }); - - it(`should support formData response type`, async function () { - this.timeout(5000); - - const originalData = new FormData(); - - originalData.append('x', '123'); - - server = await startHTTPServer(async (req, res) => { - const response = await new Response(originalData); - - res.setHeader('Content-Type', response.headers.get('Content-Type')); - - res.end(await response.text()); - }); - - const { data } = await fetchAxios.get('/', { - responseType: 'formdata', - }); - - assert.ok(data instanceof FormData, 'data is not instanceof FormData'); - - assert.deepStrictEqual( - Object.fromEntries(data.entries()), - Object.fromEntries(originalData.entries()) - ); - }); - - it(`should support json response type`, async () => { - const originalData = { x: 'my data' }; - - server = await startHTTPServer((req, res) => res.end(JSON.stringify(originalData))); - - const { data } = await fetchAxios.get('/', { - responseType: 'json', - }); - - assert.deepStrictEqual(data, originalData); - }); - }); - - describe('progress', () => { - describe('upload', function () { - it('should support upload progress capturing', async function () { - this.timeout(15000); - - server = await startHTTPServer({ - rate: 100 * 1024, - }); - - let content = ''; - const count = 10; - const chunk = 'test'; - const chunkLength = Buffer.byteLength(chunk); - const contentLength = count * chunkLength; - - const readable = stream.Readable.from( - (async function* () { - let i = count; - - while (i-- > 0) { - await setTimeoutAsync(1100); - content += chunk; - yield chunk; - } - })() - ); - - const samples = []; - - const { data } = await fetchAxios.post('/', readable, { - onUploadProgress: ({ loaded, total, progress, bytes, upload }) => { - console.log( - `Upload Progress ${loaded} from ${total} bytes (${(progress * 100).toFixed(1)}%)` - ); - - samples.push({ - loaded, - total, - progress, - bytes, - upload, - }); - }, - headers: { - 'Content-Length': contentLength, - }, - responseType: 'text', - }); - - await setTimeoutAsync(500); - - assert.strictEqual(data, content); - - assert.deepStrictEqual( - samples, - Array.from( - (function* () { - for (let i = 1; i <= 10; i++) { - yield { - loaded: chunkLength * i, - total: contentLength, - progress: (chunkLength * i) / contentLength, - bytes: 4, - upload: true, - }; - } - })() - ) - ); - }); - - it('should not fail with get method', async () => { - server = await startHTTPServer((req, res) => res.end('OK')); - - const { data } = await fetchAxios.get('/', { - onUploadProgress() {}, - }); - - assert.strictEqual(data, 'OK'); - }); - }); - - describe('download', function () { - it('should support download progress capturing', async function () { - this.timeout(15000); - - server = await startHTTPServer({ - rate: 100 * 1024, - }); - - let content = ''; - const count = 10; - const chunk = 'test'; - const chunkLength = Buffer.byteLength(chunk); - const contentLength = count * chunkLength; - - const readable = stream.Readable.from( - (async function* () { - let i = count; - - while (i-- > 0) { - await setTimeoutAsync(1100); - content += chunk; - yield chunk; - } - })() - ); - - const samples = []; - - const { data } = await fetchAxios.post('/', readable, { - onDownloadProgress: ({ loaded, total, progress, bytes, download }) => { - console.log( - `Download Progress ${loaded} from ${total} bytes (${(progress * 100).toFixed(1)}%)` - ); - - samples.push({ - loaded, - total, - progress, - bytes, - download, - }); - }, - headers: { - 'Content-Length': contentLength, - }, - responseType: 'text', - maxRedirects: 0, - }); - - await setTimeoutAsync(500); - - assert.strictEqual(data, content); - - assert.deepStrictEqual( - samples, - Array.from( - (function* () { - for (let i = 1; i <= 10; i++) { - yield { - loaded: chunkLength * i, - total: contentLength, - progress: (chunkLength * i) / contentLength, - bytes: 4, - download: true, - }; - } - })() - ) - ); - }); - }); - }); - - it('should support basic auth', async () => { - server = await startHTTPServer((req, res) => res.end(req.headers.authorization)); - - const user = 'foo'; - const headers = { Authorization: 'Bearer 1234' }; - const res = await axios.get('http://' + user + '@localhost:4444/', { headers: headers }); - - const base64 = Buffer.from(user + ':', 'utf8').toString('base64'); - assert.equal(res.data, 'Basic ' + base64); - }); - - it('should support stream.Readable as a payload', async () => { - server = await startHTTPServer(); - - const { data } = await fetchAxios.post('/', stream.Readable.from('OK')); - - assert.strictEqual(data, 'OK'); - }); - - describe('request aborting', function () { - it('should be able to abort the request stream', async function () { - server = await startHTTPServer({ - rate: 100000, - useBuffering: true, - }); - - const controller = new AbortController(); - - setTimeout(() => { - controller.abort(); - }, 500); - - await assert.rejects(async () => { - await fetchAxios.post('/', makeReadableStream(), { - responseType: 'stream', - signal: controller.signal, - }); - }, /CanceledError/); - }); - - it('should be able to abort the response stream', async function () { - server = await startHTTPServer((req, res) => { - pipelineAsync(generateReadable(10000, 10), res); - }); - - const controller = new AbortController(); - - setTimeout(() => { - controller.abort(new Error('test')); - }, 800); - - const { data } = await fetchAxios.get('/', { - responseType: 'stream', - signal: controller.signal, - }); - - await assert.rejects(async () => { - await data.pipeTo(makeEchoStream()); - }, /^(AbortError|CanceledError):/); - }); - }); - - it('should support a timeout', async () => { - server = await startHTTPServer(async (req, res) => { - await setTimeoutAsync(1000); - res.end('OK'); - }); - - const timeout = 500; - - const ts = Date.now(); - - await assert.rejects(async () => { - await fetchAxios('/', { - timeout, - }); - }, /timeout/); - - const passed = Date.now() - ts; - - assert.ok(passed >= timeout - 5, `early cancellation detected (${passed} ms)`); - }); - - it('should combine baseURL and url', async () => { - server = await startHTTPServer(); - - const res = await fetchAxios('/foo'); - - assert.equal(res.config.baseURL, LOCAL_SERVER_URL); - assert.equal(res.config.url, '/foo'); - }); - - it('should support params', async () => { - server = await startHTTPServer((req, res) => res.end(req.url)); - - const { data } = await fetchAxios.get('/?test=1', { - params: { - foo: 1, - bar: 2, - }, - }); - - assert.strictEqual(data, '/?test=1&foo=1&bar=2'); - }); - - it('should handle fetch failed error as an AxiosError with ERR_NETWORK code', async () => { - try { - await fetchAxios('http://notExistsUrl.in.nowhere'); - assert.fail('should fail'); - } catch (err) { - assert.strictEqual(String(err), 'AxiosError: Network Error'); - assert.strictEqual(err.cause && err.cause.code, 'ENOTFOUND'); - } - }); - - it('should get response headers', async () => { - server = await startHTTPServer((req, res) => { - res.setHeader('foo', 'bar'); - res.end(req.url); - }); - - const { headers } = await fetchAxios.get('/', { - responseType: 'stream', - }); - - assert.strictEqual(headers.get('foo'), 'bar'); - }); - - describe('fetch adapter - Content-Type handling', function () { - it('should set correct Content-Type for FormData automatically', async function () { - const FormData = (await import('form-data')).default; // Node FormData - const form = new FormData(); - form.append('foo', 'bar'); - - server = await startHTTPServer((req, res) => { - const contentType = req.headers['content-type']; - assert.match(contentType, /^multipart\/form-data; boundary=/i); - res.end('OK'); - }); - - await fetchAxios.post('/form', form); - }); - }); - - describe('env config', () => { - it('should respect env fetch API configuration', async () => { - const { data, headers } = await fetchAxios.get('/', { - env: { - fetch() { - return { - headers: { - foo: '1', - }, - text: async () => 'test', - }; - }, - }, - }); - - assert.strictEqual(headers.get('foo'), '1'); - assert.strictEqual(data, 'test'); - }); - - it('should be able to request with lack of Request object', async () => { - const form = new FormData(); - - form.append('x', '1'); - - const { data, headers } = await fetchAxios.post('/', form, { - onUploadProgress() { - // dummy listener to activate streaming - }, - env: { - Request: null, - fetch() { - return { - headers: { - foo: '1', - }, - text: async () => 'test', - }; - }, - }, - }); - - assert.strictEqual(headers.get('foo'), '1'); - assert.strictEqual(data, 'test'); - }); - - it('should be able to handle response with lack of Response object', async () => { - const { data, headers } = await fetchAxios.get('/', { - onDownloadProgress() { - // dummy listener to activate streaming - }, - env: { - Request: null, - Response: null, - fetch() { - return { - headers: { - foo: '1', - }, - text: async () => 'test', - }; - }, - }, - }); - - assert.strictEqual(headers.get('foo'), '1'); - assert.strictEqual(data, 'test'); - }); - - it('should fallback to the global on undefined env value', async () => { - server = await startHTTPServer((req, res) => res.end('OK')); - - const { data } = await fetchAxios.get('/', { - env: { - fetch: undefined, - }, - }); - - assert.strictEqual(data, 'OK'); - }); - - it('should use current global fetch when env fetch is not specified', async () => { - const globalFetch = fetch; - - fetch = async () => { - return { - headers: { - foo: '1', - }, - text: async () => 'global', - }; - }; - - try { - server = await startHTTPServer((req, res) => res.end('OK')); - - const { data } = await fetchAxios.get('/', { - env: { - fetch: undefined, - }, - }); - - assert.strictEqual(data, 'global'); - } finally { - fetch = globalFetch; - } - }); - }); -}); diff --git a/test/unit/adapters/http.js b/test/unit/adapters/http.js deleted file mode 100644 index d3bd20af..00000000 --- a/test/unit/adapters/http.js +++ /dev/null @@ -1,3196 +0,0 @@ -/* eslint-env mocha */ -import axios from '../../../index.js'; -import http from 'http'; -import https from 'https'; -import net from 'net'; -import url from 'url'; -import zlib from 'zlib'; -import stream from 'stream'; -import util from 'util'; -import assert from 'assert'; -import fs from 'fs'; -import path from 'path'; -import { lookup } from 'dns'; -let server, server2, proxy; -import AxiosError from '../../../lib/core/AxiosError.js'; -import FormDataLegacy from 'form-data'; -import formidable from 'formidable'; -import express from 'express'; -import multer from 'multer'; -import bodyParser from 'body-parser'; -const isBlobSupported = typeof Blob !== 'undefined'; -import devNull from 'dev-null'; -import { AbortController } from 'abortcontroller-polyfill/dist/cjs-ponyfill.js'; -import { __setProxy } from '../../../lib/adapters/http.js'; -import { - FormData as FormDataPolyfill, - Blob as BlobPolyfill, - File as FilePolyfill, -} from 'formdata-node'; -import getStream from 'get-stream'; -import { - startHTTPServer, - stopHTTPServer, - LOCAL_SERVER_URL, - SERVER_HANDLER_STREAM_ECHO, - handleFormData, - generateReadable, -} from '../../helpers/server.js'; - -const LOCAL_SERVER_URL2 = 'https://localhost:5555'; -const SERVER_PORT = 4444; -const SERVER_PORT2 = 5555; - -const FormDataSpecCompliant = typeof FormData !== 'undefined' ? FormData : FormDataPolyfill; -const BlobSpecCompliant = typeof Blob !== 'undefined' ? Blob : BlobPolyfill; -const FileSpecCompliant = typeof File !== 'undefined' ? File : FilePolyfill; - -const __filename = url.fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -function setTimeoutAsync(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -const pipelineAsync = util.promisify(stream.pipeline); -const finishedAsync = util.promisify(stream.finished); -const gzip = util.promisify(zlib.gzip); -const deflate = util.promisify(zlib.deflate); -const deflateRaw = util.promisify(zlib.deflateRaw); -const brotliCompress = util.promisify(zlib.brotliCompress); - -function toleranceRange(positive, negative) { - const p = 1 + positive / 100; - const n = 1 - negative / 100; - - return (actualValue, value) => { - return actualValue > value ? actualValue <= value * p : actualValue >= value * n; - }; -} - -const nodeVersion = process.versions.node.split('.').map((v) => parseInt(v, 10)); -const nodeMajorVersion = nodeVersion[0]; - -var noop = () => {}; - -describe('supports http with nodejs', function () { - afterEach(async function () { - await Promise.all([stopHTTPServer(server), stopHTTPServer(server2), stopHTTPServer(proxy)]); - - server = null; - server2 = null; - proxy = null; - - delete process.env.http_proxy; - delete process.env.https_proxy; - delete process.env.no_proxy; - }); - - it('should support IPv4 literal strings', function (done) { - var data = { - firstName: 'Fred', - lastName: 'Flintstone', - emailAddr: 'fred@example.com', - }; - - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify(data)); - }) - .listen(4444, function () { - axios - .get('http://127.0.0.1:4444/') - .then(function (res) { - assert.deepEqual(res.data, data); - done(); - }) - .catch(done); - }); - }); - - it('should support IPv6 literal strings', function (done) { - var data = { - firstName: 'Fred', - lastName: 'Flintstone', - emailAddr: 'fred@example.com', - }; - - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify(data)); - }) - .listen(4444, function () { - axios - .get('http://[::1]:4444/') - .then(function (res) { - assert.deepEqual(res.data, data); - done(); - }) - .catch(done); - }); - }); - - it('should throw an error if the timeout property is not parsable as a number', function (done) { - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - var success = false, - failure = false; - var error; - - axios - .get('http://localhost:4444/', { - timeout: { strangeTimeout: 250 }, - }) - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.equal(success, false, 'request should not succeed'); - assert.equal(failure, true, 'request should fail'); - assert.equal(error.code, AxiosError.ERR_BAD_OPTION_VALUE); - assert.equal(error.message, 'error trying to parse `config.timeout` to int'); - done(); - }, 300); - }); - }); - - it('should parse the timeout property', function (done) { - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - var success = false, - failure = false; - var error; - - axios - .get('http://localhost:4444/', { - timeout: '250', - }) - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.equal(success, false, 'request should not succeed'); - assert.equal(failure, true, 'request should fail'); - assert.equal(error.code, 'ECONNABORTED'); - assert.equal(error.message, 'timeout of 250ms exceeded'); - done(); - }, 300); - }); - }); - - it('should respect the timeout property', function (done) { - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - var success = false, - failure = false; - var error; - - axios - .get('http://localhost:4444/', { - timeout: 250, - }) - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.equal(success, false, 'request should not succeed'); - assert.equal(failure, true, 'request should fail'); - assert.equal(error.code, 'ECONNABORTED'); - assert.equal(error.message, 'timeout of 250ms exceeded'); - done(); - }, 300); - }); - }); - - it('should respect the timeoutErrorMessage property', function (done) { - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - var success = false, - failure = false; - var error; - - axios - .get('http://localhost:4444/', { - timeout: 250, - timeoutErrorMessage: 'oops, timeout', - }) - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.strictEqual(success, false, 'request should not succeed'); - assert.strictEqual(failure, true, 'request should fail'); - assert.strictEqual(error.code, 'ECONNABORTED'); - assert.strictEqual(error.message, 'oops, timeout'); - done(); - }, 300); - }); - }); - - it('should allow passing JSON', function (done) { - var data = { - firstName: 'Fred', - lastName: 'Flintstone', - emailAddr: 'fred@example.com', - }; - - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify(data)); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.deepEqual(res.data, data); - done(); - }) - .catch(done); - }); - }); - - it('should allow passing JSON with BOM', function (done) { - var data = { - firstName: 'Fred', - lastName: 'Flintstone', - emailAddr: 'fred@example.com', - }; - - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'application/json'); - var bomBuffer = Buffer.from([0xef, 0xbb, 0xbf]); - var jsonBuffer = Buffer.from(JSON.stringify(data)); - res.end(Buffer.concat([bomBuffer, jsonBuffer])); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.deepEqual(res.data, data); - done(); - }) - .catch(done); - }); - }); - - it('should redirect', function (done) { - var str = 'test response'; - - server = http - .createServer(function (req, res) { - var parsed = url.parse(req.url); - - if (parsed.pathname === '/one') { - res.setHeader('Location', '/two'); - res.statusCode = 302; - res.end(); - } else { - res.end(str); - } - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/one') - .then(function (res) { - assert.equal(res.data, str); - assert.equal(res.request.path, '/two'); - done(); - }) - .catch(done); - }); - }); - - it('should not redirect', function (done) { - server = http - .createServer(function (req, res) { - res.setHeader('Location', '/foo'); - res.statusCode = 302; - res.end(); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/', { - maxRedirects: 0, - validateStatus: function () { - return true; - }, - }) - .then(function (res) { - assert.equal(res.status, 302); - assert.equal(res.headers['location'], '/foo'); - done(); - }) - .catch(done); - }); - }); - - it('should support max redirects', function (done) { - var i = 1; - server = http - .createServer(function (req, res) { - res.setHeader('Location', '/' + i); - res.statusCode = 302; - res.end(); - i++; - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/', { - maxRedirects: 3, - }) - .catch(function (error) { - assert.equal(error.code, AxiosError.ERR_FR_TOO_MANY_REDIRECTS); - assert.equal(error.message, 'Maximum number of redirects exceeded'); - done(); - }) - .catch(done); - }); - }); - - it('should support beforeRedirect', function (done) { - server = http - .createServer(function (req, res) { - res.setHeader('Location', '/foo'); - res.statusCode = 302; - res.end(); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/', { - maxRedirects: 3, - beforeRedirect: function (options, responseDetails) { - if (options.path === '/foo' && responseDetails.headers.location === '/foo') { - throw new Error('Provided path is not allowed'); - } - }, - }) - .catch(function (error) { - assert.equal(error.message, 'Redirected request failed: Provided path is not allowed'); - done(); - }) - .catch(done); - }); - }); - - it('should support beforeRedirect and proxy with redirect', async () => { - let requestCount = 0; - let totalRedirectCount = 5; - - server = await startHTTPServer( - function (req, res) { - requestCount += 1; - if (requestCount <= totalRedirectCount) { - res.setHeader('Location', 'http://localhost:4444'); - res.writeHead(302); - } - res.end(); - }, - { port: 4444 } - ); - - let proxyUseCount = 0; - proxy = await startHTTPServer( - function (req, res) { - proxyUseCount += 1; - const targetUrl = new URL(req.url, 'http://' + req.headers.host); - const opts = { - host: targetUrl.hostname, - port: targetUrl.port, - path: targetUrl.path, - method: req.method, - }; - - const request = http.get(opts, function (response) { - res.writeHead(response.statusCode, response.headers); - stream.pipeline(response, res, () => {}); - }); - - request.on('error', (err) => { - console.warn('request error', err); - res.statusCode = 500; - res.end(); - }); - }, - { port: 4000 } - ); - - let configBeforeRedirectCount = 0; - - await axios - .get('http://localhost:4444/', { - proxy: { - host: 'localhost', - port: 4000, - }, - maxRedirects: totalRedirectCount, - beforeRedirect: function (options) { - configBeforeRedirectCount += 1; - }, - }) - .then(function (res) { - assert.equal( - totalRedirectCount, - configBeforeRedirectCount, - 'should invoke config.beforeRedirect option on every redirect' - ); - assert.equal( - totalRedirectCount + 1, - proxyUseCount, - 'should go through proxy on every redirect' - ); - }); - }); - - it('should wrap HTTP errors and keep stack', async function () { - if (nodeMajorVersion <= 12) { - this.skip(); // node 12 support for async stack traces appears lacking - return; - } - - server = await startHTTPServer((req, res) => { - res.statusCode = 400; - res.end(); - }); - - return assert.rejects( - async function findMeInStackTrace() { - await axios.head('http://localhost:4444/one'); - }, - function (err) { - assert.equal(err.name, 'AxiosError'); - assert.equal(err.isAxiosError, true); - const matches = [...err.stack.matchAll(/findMeInStackTrace/g)]; - assert.equal(matches.length, 1, err.stack); - return true; - } - ); - }); - - it('should wrap interceptor errors and keep stack', function (done) { - if (nodeMajorVersion <= 12) { - this.skip(); // node 12 support for async stack traces appears lacking - return; - } - const axiosInstance = axios.create(); - axiosInstance.interceptors.request.use((res) => { - throw new Error('from request interceptor'); - }); - server = http - .createServer(function (req, res) { - res.end(); - }) - .listen(4444, function () { - void assert - .rejects( - async function findMeInStackTrace() { - await axiosInstance.get('http://localhost:4444/one'); - }, - function (err) { - assert.equal(err.name, 'Error'); - assert.equal(err.message, 'from request interceptor'); - const matches = [...err.stack.matchAll(/findMeInStackTrace/g)]; - assert.equal(matches.length, 1, err.stack); - return true; - } - ) - .then(done) - .catch(done); - }); - }); - - it('should preserve the HTTP verb on redirect', function (done) { - server = http - .createServer(function (req, res) { - if (req.method.toLowerCase() !== 'head') { - res.statusCode = 400; - res.end(); - return; - } - - var parsed = url.parse(req.url); - if (parsed.pathname === '/one') { - res.setHeader('Location', '/two'); - res.statusCode = 302; - res.end(); - } else { - res.end(); - } - }) - .listen(4444, function () { - axios - .head('http://localhost:4444/one') - .then(function (res) { - assert.equal(res.status, 200); - done(); - }) - .catch(done); - }); - }); - - describe('compression', async () => { - it('should support transparent gunzip', function (done) { - var data = { - firstName: 'Fred', - lastName: 'Flintstone', - emailAddr: 'fred@example.com', - }; - - zlib.gzip(JSON.stringify(data), function (err, zipped) { - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'application/json'); - res.setHeader('Content-Encoding', 'gzip'); - res.end(zipped); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.deepEqual(res.data, data); - done(); - }) - .catch(done); - }); - }); - }); - - it('should support gunzip error handling', async () => { - server = await startHTTPServer((req, res) => { - res.setHeader('Content-Type', 'application/json'); - res.setHeader('Content-Encoding', 'gzip'); - res.end('invalid response'); - }); - - await assert.rejects(async () => { - await axios.get(LOCAL_SERVER_URL); - }); - }); - - it('should support disabling automatic decompression of response data', function (done) { - var data = 'Test data'; - - zlib.gzip(data, function (err, zipped) { - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html;charset=utf-8'); - res.setHeader('Content-Encoding', 'gzip'); - res.end(zipped); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/', { - decompress: false, - responseType: 'arraybuffer', - }) - .then(function (res) { - assert.equal(res.data.toString('base64'), zipped.toString('base64')); - done(); - }) - .catch(done); - }); - }); - }); - - describe('algorithms', () => { - const responseBody = 'str'; - - for (const [typeName, zipped] of Object.entries({ - gzip: gzip(responseBody), - GZIP: gzip(responseBody), - compress: gzip(responseBody), - deflate: deflate(responseBody), - 'deflate-raw': deflateRaw(responseBody), - br: brotliCompress(responseBody), - })) { - const type = typeName.split('-')[0]; - - describe(`${typeName} decompression`, async () => { - it(`should support decompression`, async () => { - server = await startHTTPServer(async (req, res) => { - res.setHeader('Content-Encoding', type); - res.end(await zipped); - }); - - const { data } = await axios.get(LOCAL_SERVER_URL); - - assert.strictEqual(data, responseBody); - }); - - it(`should not fail if response content-length header is missing (${type})`, async () => { - server = await startHTTPServer(async (req, res) => { - res.setHeader('Content-Encoding', type); - res.removeHeader('Content-Length'); - res.end(await zipped); - }); - - const { data } = await axios.get(LOCAL_SERVER_URL); - - assert.strictEqual(data, responseBody); - }); - - it('should not fail with chunked responses (without Content-Length header)', async () => { - server = await startHTTPServer(async (req, res) => { - res.setHeader('Content-Encoding', type); - res.setHeader('Transfer-Encoding', 'chunked'); - res.removeHeader('Content-Length'); - res.write(await zipped); - res.end(); - }); - - const { data } = await axios.get(LOCAL_SERVER_URL); - - assert.strictEqual(data, responseBody); - }); - - it('should not fail with an empty response without content-length header (Z_BUF_ERROR)', async () => { - server = await startHTTPServer((req, res) => { - res.setHeader('Content-Encoding', type); - res.removeHeader('Content-Length'); - res.end(); - }); - - const { data } = await axios.get(LOCAL_SERVER_URL); - - assert.strictEqual(data, ''); - }); - - it('should not fail with an empty response with content-length header (Z_BUF_ERROR)', async () => { - server = await startHTTPServer((req, res) => { - res.setHeader('Content-Encoding', type); - res.end(); - }); - - await axios.get(LOCAL_SERVER_URL); - }); - }); - } - }); - }); - - it('should support UTF8', function (done) { - var str = Array(100000).join('ж'); - - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end(str); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.equal(res.data, str); - done(); - }) - .catch(done); - }); - }); - - it('should support basic auth', function (done) { - server = http - .createServer(function (req, res) { - res.end(req.headers.authorization); - }) - .listen(4444, function () { - var user = 'foo'; - var headers = { Authorization: 'Bearer 1234' }; - axios - .get('http://' + user + '@localhost:4444/', { headers: headers }) - .then(function (res) { - var base64 = Buffer.from(user + ':', 'utf8').toString('base64'); - assert.equal(res.data, 'Basic ' + base64); - done(); - }) - .catch(done); - }); - }); - - it('should support basic auth with a header', function (done) { - server = http - .createServer(function (req, res) { - res.end(req.headers.authorization); - }) - .listen(4444, function () { - var auth = { username: 'foo', password: 'bar' }; - var headers = { AuThOrIzAtIoN: 'Bearer 1234' }; // wonky casing to ensure caseless comparison - axios - .get('http://localhost:4444/', { auth: auth, headers: headers }) - .then(function (res) { - var base64 = Buffer.from('foo:bar', 'utf8').toString('base64'); - assert.equal(res.data, 'Basic ' + base64); - done(); - }) - .catch(done); - }); - }); - - it('should provides a default User-Agent header', function (done) { - server = http - .createServer(function (req, res) { - res.end(req.headers['user-agent']); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.ok( - /^axios\/[\d.]+[-]?[a-z]*[.]?[\d]+$/.test(res.data), - `User-Agent header does not match: ${res.data}` - ); - done(); - }) - .catch(done); - }); - }); - - it('should allow the User-Agent header to be overridden', function (done) { - server = http - .createServer(function (req, res) { - res.end(req.headers['user-agent']); - }) - .listen(4444, function () { - var headers = { 'UsEr-AgEnT': 'foo bar' }; // wonky casing to ensure caseless comparison - axios - .get('http://localhost:4444/', { headers }) - .then(function (res) { - assert.equal(res.data, 'foo bar'); - done(); - }) - .catch(done); - }); - }); - - it('should allow the Content-Length header to be overridden', function (done) { - server = http - .createServer(function (req, res) { - assert.strictEqual(req.headers['content-length'], '42'); - res.end(); - }) - .listen(4444, function () { - var headers = { 'CoNtEnT-lEnGtH': '42' }; // wonky casing to ensure caseless comparison - axios - .post('http://localhost:4444/', 'foo', { headers }) - .then(function () { - done(); - }) - .catch(done); - }); - }); - - it('should support max content length', async function () { - server = await startHTTPServer( - function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end(Array(5000).join('#')); - }, - { port: 4444 } - ); - - await assert.rejects(() => { - return axios.get('http://localhost:4444/', { - maxContentLength: 2000, - maxRedirects: 0, - }); - }, /maxContentLength size of 2000 exceeded/); - }); - - it('should support max content length for redirected', function (done) { - var str = Array(100000).join('ж'); - - server = http - .createServer(function (req, res) { - var parsed = url.parse(req.url); - - if (parsed.pathname === '/two') { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end(str); - } else { - res.setHeader('Location', '/two'); - res.statusCode = 302; - res.end(); - } - }) - .listen(4444, function () { - var success = false, - failure = false, - error; - - axios - .get('http://localhost:4444/one', { - maxContentLength: 2000, - }) - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.equal(success, false, 'request should not succeed'); - assert.equal(failure, true, 'request should fail'); - assert.equal(error.message, 'maxContentLength size of 2000 exceeded'); - done(); - }, 100); - }); - }); - - it('should support max body length', function (done) { - var data = Array(100000).join('ж'); - - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end(); - }) - .listen(4444, function () { - var success = false, - failure = false, - error; - - axios - .post( - 'http://localhost:4444/', - { - data: data, - }, - { - maxBodyLength: 2000, - } - ) - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.equal(success, false, 'request should not succeed'); - assert.equal(failure, true, 'request should fail'); - assert.equal(error.message, 'Request body larger than maxBodyLength limit'); - done(); - }, 100); - }); - }); - - it('should properly support default max body length (follow-redirects as well)', function (done) { - // taken from https://github.com/follow-redirects/follow-redirects/blob/22e81fc37132941fb83939d1dc4c2282b5c69521/index.js#L461 - var followRedirectsMaxBodyDefaults = 10 * 1024 * 1024; - var data = Array(2 * followRedirectsMaxBodyDefaults).join('ж'); - - server = http - .createServer(function (req, res) { - // consume the req stream - req.on('data', noop); - // and wait for the end before responding, otherwise an ECONNRESET error will be thrown - req.on('end', () => { - res.end('OK'); - }); - }) - .listen(4444, function (err) { - if (err) { - return done(err); - } - // send using the default -1 (unlimited axios maxBodyLength) - axios - .post('http://localhost:4444/', { - data: data, - }) - .then(function (res) { - assert.equal(res.data, 'OK', 'should handle response'); - done(); - }) - .catch(done); - }); - }); - - it('should display error while parsing params', function (done) { - server = http - .createServer(function () {}) - .listen(4444, function () { - axios - .get('http://localhost:4444/', { - params: { - errorParam: new Date(undefined), - }, - }) - .catch(function (err) { - assert.deepEqual(err.exists, true); - done(); - }) - .catch(done); - }); - }); - - it('should support sockets', function (done) { - // Different sockets for win32 vs darwin/linux - var socketName = './test.sock'; - - if (process.platform === 'win32') { - socketName = '\\\\.\\pipe\\libuv-test'; - } - - server = net - .createServer(function (socket) { - socket.on('data', function () { - socket.end('HTTP/1.1 200 OK\r\n\r\n'); - }); - }) - .listen(socketName, function () { - axios({ - socketPath: socketName, - url: 'http://localhost:4444/socket', - }) - .then(function (resp) { - assert.equal(resp.status, 200); - assert.equal(resp.statusText, 'OK'); - done(); - }) - .catch(done); - }); - }); - - describe('streams', function () { - it('should support streams', function (done) { - server = http - .createServer(function (req, res) { - req.pipe(res); - }) - .listen(4444, function () { - axios - .post('http://localhost:4444/', fs.createReadStream(__filename), { - responseType: 'stream', - }) - .then(function (res) { - var stream = res.data; - var string = ''; - stream.on('data', function (chunk) { - string += chunk.toString('utf8'); - }); - stream.on('end', function () { - assert.equal(string, fs.readFileSync(__filename, 'utf8')); - done(); - }); - }) - .catch(done); - }); - }); - - it('should pass errors for a failed stream', async function () { - server = await startHTTPServer(); - - var notExitPath = path.join(__dirname, 'does_not_exist'); - - try { - await axios.post(LOCAL_SERVER_URL, fs.createReadStream(notExitPath)); - assert.fail('expected ENOENT error'); - } catch (err) { - assert.equal(err.message, `ENOENT: no such file or directory, open \'${notExitPath}\'`); - } - }); - - it('should destroy the response stream with an error on request stream destroying', async function () { - server = await startHTTPServer(); - - let stream = generateReadable(); - - setTimeout(function () { - stream.destroy(); - }, 1000); - - const { data } = await axios.post(LOCAL_SERVER_URL, stream, { responseType: 'stream' }); - - let streamError; - - data.on('error', function (err) { - streamError = err; - }); - - try { - await pipelineAsync(data, devNull()); - assert.fail('stream was not aborted'); - } catch (e) { - console.log(`pipeline error: ${e}`); - } finally { - assert.strictEqual(streamError && streamError.code, 'ERR_CANCELED'); - } - }); - }); - - it('should support buffers', function (done) { - var buf = Buffer.alloc(1024, 'x'); // Unsafe buffer < Buffer.poolSize (8192 bytes) - server = http - .createServer(function (req, res) { - assert.equal(req.headers['content-length'], buf.length.toString()); - req.pipe(res); - }) - .listen(4444, function () { - axios - .post('http://localhost:4444/', buf, { - responseType: 'stream', - }) - .then(function (res) { - var stream = res.data; - var string = ''; - stream.on('data', function (chunk) { - string += chunk.toString('utf8'); - }); - stream.on('end', function () { - assert.equal(string, buf.toString()); - done(); - }); - }) - .catch(done); - }); - }); - - it('should support HTTP proxies', function (done) { - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end('12345'); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - }; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(body + '6789'); - }); - }); - }) - .listen(4000, function () { - axios - .get('http://localhost:4444/', { - proxy: { - host: 'localhost', - port: 4000, - }, - }) - .then(function (res) { - assert.equal(res.data, '123456789', 'should pass through proxy'); - done(); - }) - .catch(done); - }); - }); - }); - - it('should support HTTPS proxies', function (done) { - var options = { - key: fs.readFileSync(path.join(__dirname, 'key.pem')), - cert: fs.readFileSync(path.join(__dirname, 'cert.pem')), - }; - - server = https - .createServer(options, function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end('12345'); - }) - .listen(4444, function () { - proxy = https - .createServer(options, function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - protocol: parsed.protocol, - rejectUnauthorized: false, - }; - - https.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(body + '6789'); - }); - }); - }) - .listen(4000, function () { - axios - .get('https://localhost:4444/', { - proxy: { - host: 'localhost', - port: 4000, - protocol: 'https:', - }, - httpsAgent: new https.Agent({ - rejectUnauthorized: false, - }), - }) - .then(function (res) { - assert.equal(res.data, '123456789', 'should pass through proxy'); - done(); - }) - .catch(done); - }); - }); - }); - - it('should not pass through disabled proxy', function (done) { - // set the env variable - process.env.http_proxy = 'http://does-not-exists.example.com:4242/'; - - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end('123456789'); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/', { - proxy: false, - }) - .then(function (res) { - assert.equal(res.data, '123456789', 'should not pass through proxy'); - done(); - }) - .catch(done); - }); - }); - - it('should support proxy set via env var', function (done) { - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end('4567'); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - }; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(body + '1234'); - }); - }); - }) - .listen(4000, function () { - // set the env variable - process.env.http_proxy = 'http://localhost:4000/'; - - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.equal( - res.data, - '45671234', - 'should use proxy set by process.env.http_proxy' - ); - done(); - }) - .catch(done); - }); - }); - }); - - it('should support HTTPS proxy set via env var', function (done) { - var options = { - key: fs.readFileSync(path.join(__dirname, 'key.pem')), - cert: fs.readFileSync(path.join(__dirname, 'cert.pem')), - }; - - server = https - .createServer(options, function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end('12345'); - }) - .listen(4444, function () { - proxy = https - .createServer(options, function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - protocol: parsed.protocol, - rejectUnauthorized: false, - }; - - https.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(body + '6789'); - }); - }); - }) - .listen(4000, function () { - process.env.https_proxy = 'https://localhost:4000/'; - - axios - .get('https://localhost:4444/', { - httpsAgent: new https.Agent({ - rejectUnauthorized: false, - }), - }) - .then(function (res) { - assert.equal(res.data, '123456789', 'should pass through proxy'); - done(); - }) - .catch(done); - }); - }); - }); - - it('should re-evaluate proxy on redirect when proxy set via env var', function (done) { - process.env.http_proxy = 'http://localhost:4000'; - process.env.no_proxy = 'localhost:4000'; - - var proxyUseCount = 0; - - server = http - .createServer(function (req, res) { - res.setHeader('Location', 'http://localhost:4000/redirected'); - res.statusCode = 302; - res.end(); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - if (parsed.pathname === '/redirected') { - response.statusCode = 200; - response.end(); - return; - } - - proxyUseCount += 1; - - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - protocol: parsed.protocol, - rejectUnauthorized: false, - }; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.setHeader('Location', res.headers.location); - response.end(body); - }); - }); - }) - .listen(4000, function () { - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.equal(res.status, 200); - assert.equal(proxyUseCount, 1); - done(); - }) - .catch(done); - }); - }); - }); - - it('should not use proxy for domains in no_proxy', function (done) { - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end('4567'); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - }; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(body + '1234'); - }); - }); - }) - .listen(4000, function () { - // set the env variable - process.env.http_proxy = 'http://localhost:4000/'; - process.env.no_proxy = 'foo.com, localhost,bar.net , , quix.co'; - - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.equal(res.data, '4567', 'should not use proxy for domains in no_proxy'); - done(); - }) - .catch(done); - }); - }); - }); - - it('should use proxy for domains not in no_proxy', function (done) { - server = http - .createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html; charset=UTF-8'); - res.end('4567'); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - }; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(body + '1234'); - }); - }); - }) - .listen(4000, function () { - // set the env variable - process.env.http_proxy = 'http://localhost:4000/'; - process.env.no_proxy = 'foo.com, ,bar.net , quix.co'; - - axios - .get('http://localhost:4444/') - .then(function (res) { - assert.equal(res.data, '45671234', 'should use proxy for domains not in no_proxy'); - done(); - }) - .catch(done); - }); - }); - }); - - it('should support HTTP proxy auth', function (done) { - server = http - .createServer(function (req, res) { - res.end(); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - }; - var proxyAuth = request.headers['proxy-authorization']; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(proxyAuth); - }); - }); - }) - .listen(4000, function () { - axios - .get('http://localhost:4444/', { - proxy: { - host: 'localhost', - port: 4000, - auth: { - username: 'user', - password: 'pass', - }, - }, - }) - .then(function (res) { - var base64 = Buffer.from('user:pass', 'utf8').toString('base64'); - assert.equal(res.data, 'Basic ' + base64, 'should authenticate to the proxy'); - done(); - }) - .catch(done); - }); - }); - }); - - it('should support proxy auth from env', function (done) { - server = http - .createServer(function (req, res) { - res.end(); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - }; - var proxyAuth = request.headers['proxy-authorization']; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(proxyAuth); - }); - }); - }) - .listen(4000, function () { - process.env.http_proxy = 'http://user:pass@localhost:4000/'; - - axios - .get('http://localhost:4444/') - .then(function (res) { - var base64 = Buffer.from('user:pass', 'utf8').toString('base64'); - assert.equal( - res.data, - 'Basic ' + base64, - 'should authenticate to the proxy set by process.env.http_proxy' - ); - done(); - }) - .catch(done); - }); - }); - }); - - it('should support proxy auth with header', function (done) { - server = http - .createServer(function (req, res) { - res.end(); - }) - .listen(4444, function () { - proxy = http - .createServer(function (request, response) { - var parsed = url.parse(request.url); - var opts = { - host: parsed.hostname, - port: parsed.port, - path: parsed.path, - }; - var proxyAuth = request.headers['proxy-authorization']; - - http.get(opts, function (res) { - var body = ''; - res.on('data', function (data) { - body += data; - }); - res.on('end', function () { - response.setHeader('Content-Type', 'text/html; charset=UTF-8'); - response.end(proxyAuth); - }); - }); - }) - .listen(4000, function () { - axios - .get('http://localhost:4444/', { - proxy: { - host: 'localhost', - port: 4000, - auth: { - username: 'user', - password: 'pass', - }, - }, - headers: { - 'Proxy-Authorization': 'Basic abc123', - }, - }) - .then(function (res) { - var base64 = Buffer.from('user:pass', 'utf8').toString('base64'); - assert.equal(res.data, 'Basic ' + base64, 'should authenticate to the proxy'); - done(); - }) - .catch(done); - }); - }); - }); - - describe('when invalid proxy options are provided', function () { - it('should throw error', function () { - const proxy = { - protocol: 'http:', - host: 'hostname.abc.xyz', - port: 3300, - auth: { - username: '', - password: '', - }, - }; - - return axios.get('https://test-domain.abc', { proxy }).then( - function () { - assert.fail('Does not throw'); - }, - function (error) { - assert.strictEqual(error.message, 'Invalid proxy authorization'); - assert.strictEqual(error.code, 'ERR_BAD_OPTION'); - assert.deepStrictEqual(error.config.proxy, proxy); - } - ); - }); - }); - - context('different options for direct proxy configuration (without env variables)', () => { - const destination = 'www.example.com'; - - const testCases = [ - { - description: 'hostname and trailing colon in protocol', - proxyConfig: { hostname: '127.0.0.1', protocol: 'http:', port: 80 }, - expectedOptions: { host: '127.0.0.1', protocol: 'http:', port: 80, path: destination }, - }, - { - description: 'hostname and no trailing colon in protocol', - proxyConfig: { hostname: '127.0.0.1', protocol: 'http', port: 80 }, - expectedOptions: { host: '127.0.0.1', protocol: 'http:', port: 80, path: destination }, - }, - { - description: 'both hostname and host -> hostname takes precedence', - proxyConfig: { hostname: '127.0.0.1', host: '0.0.0.0', protocol: 'http', port: 80 }, - expectedOptions: { host: '127.0.0.1', protocol: 'http:', port: 80, path: destination }, - }, - { - description: 'only host and https protocol', - proxyConfig: { host: '0.0.0.0', protocol: 'https', port: 80 }, - expectedOptions: { host: '0.0.0.0', protocol: 'https:', port: 80, path: destination }, - }, - ]; - - for (const test of testCases) { - it(test.description, () => { - const options = { headers: {}, beforeRedirects: {} }; - __setProxy(options, test.proxyConfig, destination); - for (const [key, expected] of Object.entries(test.expectedOptions)) { - assert.equal(options[key], expected); - } - }); - } - }); - - it('should support cancel', function (done) { - var source = axios.CancelToken.source(); - server = http - .createServer(function (req, res) { - // call cancel() when the request has been sent, but a response has not been received - source.cancel('Operation has been canceled.'); - }) - .listen(4444, function () { - void assert - .rejects( - async function findMeInStackTrace() { - await axios.get('http://localhost:4444/', { - cancelToken: source.token, - }); - }, - function (thrown) { - assert.ok( - thrown instanceof axios.Cancel, - 'Promise must be rejected with a CanceledError object' - ); - assert.equal(thrown.message, 'Operation has been canceled.'); - if (nodeMajorVersion > 12) { - assert.match(thrown.stack, /findMeInStackTrace/); - } - return true; - } - ) - .then(done) - .catch(done); - }); - }); - - it('should combine baseURL and url', function (done) { - server = http - .createServer(function (req, res) { - res.end(); - }) - .listen(4444, function () { - axios - .get('/foo', { - baseURL: 'http://localhost:4444/', - }) - .then(function (res) { - assert.equal(res.config.baseURL, 'http://localhost:4444/'); - assert.equal(res.config.url, '/foo'); - done(); - }) - .catch(done); - }); - }); - - it('should support HTTP protocol', function (done) { - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - axios.get('http://localhost:4444').then(function (res) { - assert.equal(res.request.agent.protocol, 'http:'); - done(); - }); - }); - }); - - it('should support HTTPS protocol', function (done) { - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - axios.get('https://www.google.com').then(function (res) { - assert.equal(res.request.agent.protocol, 'https:'); - done(); - }); - }); - }); - - it('should return malformed URL', function (done) { - var success = false, - failure = false; - var error; - - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - axios - .get('tel:484-695-3408') - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.equal(success, false, 'request should not succeed'); - assert.equal(failure, true, 'request should fail'); - assert.equal(error.message, 'Unsupported protocol tel:'); - done(); - }, 300); - }); - }); - - it('should return unsupported protocol', function (done) { - var success = false, - failure = false; - var error; - - server = http - .createServer(function (req, res) { - setTimeout(function () { - res.end(); - }, 1000); - }) - .listen(4444, function () { - axios - .get('ftp:google.com') - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }); - - setTimeout(function () { - assert.equal(success, false, 'request should not succeed'); - assert.equal(failure, true, 'request should fail'); - assert.equal(error.message, 'Unsupported protocol ftp:'); - done(); - }, 300); - }); - }); - - it('should supply a user-agent if one is not specified', function (done) { - server = http - .createServer(function (req, res) { - assert.equal(req.headers['user-agent'], 'axios/' + axios.VERSION); - res.end(); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/') - .then(function (res) { - done(); - }) - .catch(done); - }); - }); - - it('should omit a user-agent if one is explicitly disclaimed', function (done) { - server = http - .createServer(function (req, res) { - assert.equal('user-agent' in req.headers, false); - assert.equal('User-Agent' in req.headers, false); - res.end(); - }) - .listen(4444, function () { - axios - .get('http://localhost:4444/', { - headers: { - 'User-Agent': null, - }, - }) - .then(function (res) { - done(); - }) - .catch(done); - }); - }); - - it('should throw an error if http server that aborts a chunked request', function (done) { - server = http - .createServer(function (req, res) { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.write('chunk 1'); - setTimeout(function () { - res.write('chunk 2'); - }, 100); - setTimeout(function () { - res.destroy(); - }, 200); - }) - .listen(4444, function () { - var success = false, - failure = false; - var error; - - axios - .get('http://localhost:4444/aborted', { - timeout: 500, - }) - .then(function (res) { - success = true; - }) - .catch(function (err) { - error = err; - failure = true; - }) - .then(function () { - assert.strictEqual(success, false, 'request should not succeed'); - assert.strictEqual(failure, true, 'request should fail'); - assert.strictEqual(error.code, 'ERR_BAD_RESPONSE'); - assert.strictEqual(error.message, 'stream has been aborted'); - done(); - }) - .catch(done); - }); - }); - - it('should able to cancel multiple requests with CancelToken', function (done) { - server = http - .createServer(function (req, res) { - res.end('ok'); - }) - .listen(4444, function () { - var CancelToken = axios.CancelToken; - var source = CancelToken.source(); - var canceledStack = []; - - var requests = [1, 2, 3, 4, 5].map(function (id) { - return axios.get('/foo/bar', { cancelToken: source.token }).catch(function (e) { - if (!axios.isCancel(e)) { - throw e; - } - - canceledStack.push(id); - }); - }); - - source.cancel('Aborted by user'); - - Promise.all(requests) - .then(function () { - assert.deepStrictEqual(canceledStack.sort(), [1, 2, 3, 4, 5]); - }) - .then(done, done); - }); - }); - - describe('FormData', function () { - describe('form-data instance (https://www.npmjs.com/package/form-data)', (done) => { - it('should allow passing FormData', function (done) { - var form = new FormDataLegacy(); - var file1 = Buffer.from('foo', 'utf8'); - const image = path.resolve(__dirname, './axios.png'); - const fileStream = fs.createReadStream(image); - - const stat = fs.statSync(image); - - form.append('foo', 'bar'); - form.append('file1', file1, { - filename: 'bar.jpg', - filepath: 'temp/bar.jpg', - contentType: 'image/jpeg', - }); - - form.append('fileStream', fileStream); - - server = http - .createServer(function (req, res) { - var receivedForm = new formidable.IncomingForm(); - - assert.ok(req.rawHeaders.find((header) => header.toLowerCase() === 'content-length')); - - receivedForm.parse(req, function (err, fields, files) { - if (err) { - return done(err); - } - - res.end( - JSON.stringify({ - fields: fields, - files: files, - }) - ); - }); - }) - .listen(4444, function () { - axios - .post('http://localhost:4444/', form, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - .then(function (res) { - assert.deepStrictEqual(res.data.fields, { foo: 'bar' }); - - assert.strictEqual(res.data.files.file1.mimetype, 'image/jpeg'); - assert.strictEqual(res.data.files.file1.originalFilename, 'temp/bar.jpg'); - assert.strictEqual(res.data.files.file1.size, 3); - - assert.strictEqual(res.data.files.fileStream.mimetype, 'image/png'); - assert.strictEqual(res.data.files.fileStream.originalFilename, 'axios.png'); - assert.strictEqual(res.data.files.fileStream.size, stat.size); - - done(); - }) - .catch(done); - }); - }); - }); - - describe('SpecCompliant FormData', (done) => { - it('should allow passing FormData', async function () { - server = await startHTTPServer(async (req, res) => { - const { fields, files } = await handleFormData(req); - - res.end( - JSON.stringify({ - fields, - files, - }) - ); - }); - - const form = new FormDataSpecCompliant(); - - const blobContent = 'blob-content'; - - const blob = new BlobSpecCompliant([blobContent], { type: 'image/jpeg' }); - - form.append('foo1', 'bar1'); - form.append('foo2', 'bar2'); - - form.append('file1', blob); - - const { data } = await axios.post(LOCAL_SERVER_URL, form, { - maxRedirects: 0, - }); - - assert.deepStrictEqual(data.fields, { foo1: 'bar1', foo2: 'bar2' }); - - assert.deepStrictEqual(typeof data.files.file1, 'object'); - - const { size, mimetype, originalFilename } = data.files.file1; - - assert.deepStrictEqual( - { size, mimetype, originalFilename }, - { - mimetype: 'image/jpeg', - originalFilename: 'blob', - size: Buffer.from(blobContent).byteLength, - } - ); - }); - }); - - describe('toFormData helper', function () { - it('should properly serialize nested objects for parsing with multer.js (express.js)', function (done) { - var app = express(); - - var obj = { - arr1: ['1', '2', '3'], - arr2: ['1', ['2'], '3'], - obj: { x: '1', y: { z: '1' } }, - users: [ - { name: 'Peter', surname: 'griffin' }, - { name: 'Thomas', surname: 'Anderson' }, - ], - }; - - app.post('/', multer().none(), function (req, res, next) { - res.send(JSON.stringify(req.body)); - }); - - server = app.listen(3001, function () { - // multer can parse the following key/value pairs to an array (indexes: null, false, true): - // arr: '1' - // arr: '2' - // ------------- - // arr[]: '1' - // arr[]: '2' - // ------------- - // arr[0]: '1' - // arr[1]: '2' - // ------------- - Promise.all( - [null, false, true].map(function (mode) { - return axios - .postForm('http://localhost:3001/', obj, { formSerializer: { indexes: mode } }) - .then(function (res) { - assert.deepStrictEqual(res.data, obj, 'Index mode ' + mode); - }); - }) - ).then(function () { - done(); - }, done); - }); - }); - - it('should only match explicit routes for express 5 form handlers', function (done) { - var app = express(); - - app.post('/', multer().none(), function (req, res) { - res.status(200).send(JSON.stringify({ route: 'root', body: req.body })); - }); - - app.post('/unexpected', multer().none(), function (req, res) { - res.status(418).send('wrong-route'); - }); - - server = app.listen(3001, function () { - var rootUrl = 'http://localhost:3001'; - - axios - .postForm(rootUrl, { foo: 'bar' }) - .then(function (res) { - assert.strictEqual(res.status, 200); - assert.deepStrictEqual(res.data, { route: 'root', body: { foo: 'bar' } }); - - return axios.postForm(rootUrl + '/unexpected', { foo: 'bar' }); - }) - .then(function () { - done(new Error('Expected route /unexpected to reject')); - }) - .catch(function (err) { - assert.strictEqual(err.response.status, 418); - assert.strictEqual(err.response.data, 'wrong-route'); - done(); - }); - }); - }); - }); - }); - - describe('Blob', function () { - it('should support Blob', async () => { - server = await startHTTPServer(async (req, res) => { - res.end(await getStream(req)); - }); - - const blobContent = 'blob-content'; - - const blob = new BlobSpecCompliant([blobContent], { type: 'image/jpeg' }); - - const { data } = await axios.post(LOCAL_SERVER_URL, blob, { - maxRedirects: 0, - }); - - assert.deepStrictEqual(data, blobContent); - }); - }); - - describe('URLEncoded Form', function () { - it('should post object data as url-encoded form if content-type is application/x-www-form-urlencoded', function (done) { - var app = express(); - - var obj = { - arr1: ['1', '2', '3'], - arr2: ['1', ['2'], '3'], - obj: { x: '1', y: { z: '1' } }, - users: [ - { name: 'Peter', surname: 'griffin' }, - { name: 'Thomas', surname: 'Anderson' }, - ], - }; - - app.use(bodyParser.urlencoded({ extended: true })); - - app.post('/', function (req, res, next) { - res.send(JSON.stringify(req.body)); - }); - - server = app.listen(3001, function () { - return axios - .post('http://localhost:3001/', obj, { - headers: { - 'content-type': 'application/x-www-form-urlencoded', - }, - }) - .then(function (res) { - assert.deepStrictEqual(res.data, obj); - done(); - }) - .catch(done); - }); - }); - - it('should parse nested urlencoded payloads and ignore mismatched content-type', function (done) { - var app = express(); - - app.use(bodyParser.urlencoded({ extended: true })); - - app.post('/', function (req, res) { - var parserRanBeforeHandler = Boolean(req.body && Object.keys(req.body).length); - - res.send( - JSON.stringify({ - parserRanBeforeHandler: parserRanBeforeHandler, - body: req.body, - }) - ); - }); - - server = app.listen(3001, function () { - var payload = 'user[name]=Peter&tags[]=a&tags[]=b'; - var parsedBody = { - user: { name: 'Peter' }, - tags: ['a', 'b'], - }; - - axios - .post('http://localhost:3001/', payload, { - headers: { - 'content-type': 'application/x-www-form-urlencoded', - }, - }) - .then(function (res) { - assert.deepStrictEqual(res.data, { - parserRanBeforeHandler: true, - body: parsedBody, - }); - - return axios.post('http://localhost:3001/', payload, { - headers: { - 'content-type': 'text/plain', - }, - }); - }) - .then(function (res) { - assert.strictEqual(res.data.parserRanBeforeHandler, false); - assert.notDeepStrictEqual(res.data.body, parsedBody); - done(); - }) - .catch(done); - }); - }); - }); - - it('should respect formSerializer config', function (done) { - const obj = { - arr1: ['1', '2', '3'], - arr2: ['1', ['2'], '3'], - }; - - const form = new URLSearchParams(); - - form.append('arr1[0]', '1'); - form.append('arr1[1]', '2'); - form.append('arr1[2]', '3'); - - form.append('arr2[0]', '1'); - form.append('arr2[1][0]', '2'); - form.append('arr2[2]', '3'); - - server = http - .createServer(function (req, res) { - req.pipe(res); - }) - .listen(3001, () => { - return axios - .post('http://localhost:3001/', obj, { - headers: { - 'content-type': 'application/x-www-form-urlencoded', - }, - formSerializer: { - indexes: true, - }, - }) - .then(function (res) { - assert.strictEqual(res.data, form.toString()); - done(); - }) - .catch(done); - }); - }); - - describe('Data URL', function () { - it('should support requesting data URL as a Buffer', function (done) { - const buffer = Buffer.from('123'); - - const dataURI = 'data:application/octet-stream;base64,' + buffer.toString('base64'); - - axios - .get(dataURI) - .then(({ data }) => { - assert.deepStrictEqual(data, buffer); - done(); - }) - .catch(done); - }); - - it('should support requesting data URL as a Blob (if supported by the environment)', function (done) { - if (!isBlobSupported) { - this.skip(); - return; - } - - const buffer = Buffer.from('123'); - - const dataURI = 'data:application/octet-stream;base64,' + buffer.toString('base64'); - - axios - .get(dataURI, { responseType: 'blob' }) - .then(async ({ data }) => { - assert.strictEqual(data.type, 'application/octet-stream'); - assert.deepStrictEqual(await data.text(), '123'); - done(); - }) - .catch(done); - }); - - it('should support requesting data URL as a String (text)', function (done) { - const buffer = Buffer.from('123', 'utf-8'); - - const dataURI = 'data:application/octet-stream;base64,' + buffer.toString('base64'); - - axios - .get(dataURI, { responseType: 'text' }) - .then(({ data }) => { - assert.deepStrictEqual(data, '123'); - done(); - }) - .catch(done); - }); - - it('should support requesting data URL as a Stream', function (done) { - const buffer = Buffer.from('123', 'utf-8'); - - const dataURI = 'data:application/octet-stream;base64,' + buffer.toString('base64'); - - axios - .get(dataURI, { responseType: 'stream' }) - .then(({ data }) => { - var str = ''; - - data.on('data', function (response) { - str += response.toString(); - }); - - data.on('end', function () { - assert.strictEqual(str, '123'); - done(); - }); - }) - .catch(done); - }); - }); - - describe('progress', function () { - describe('upload', function () { - it('should support upload progress capturing', async function () { - this.timeout(15000); - server = await startHTTPServer({ - rate: 100 * 1024, - }); - - let content = ''; - const count = 10; - const chunk = 'test'; - const chunkLength = Buffer.byteLength(chunk); - const contentLength = count * chunkLength; - - var readable = stream.Readable.from( - (async function* () { - let i = count; - - while (i-- > 0) { - await setTimeoutAsync(1100); - content += chunk; - yield chunk; - } - })() - ); - - const samples = []; - - const { data } = await axios.post(LOCAL_SERVER_URL, readable, { - onUploadProgress: ({ loaded, total, progress, bytes, upload }) => { - console.log('onUploadProgress', loaded, '/', total); - samples.push({ - loaded, - total, - progress, - bytes, - upload, - }); - }, - headers: { - 'Content-Length': contentLength, - }, - responseType: 'text', - }); - - assert.strictEqual(data, content); - - assert.deepStrictEqual( - samples, - Array.from( - (function* () { - for (let i = 1; i <= 10; i++) { - yield { - loaded: chunkLength * i, - total: contentLength, - progress: (chunkLength * i) / contentLength, - bytes: 4, - upload: true, - }; - } - })() - ) - ); - }); - }); - - describe('download', function () { - it('should support download progress capturing', async function () { - this.timeout(15000); - - server = await startHTTPServer({ - rate: 100 * 1024, - }); - - let content = ''; - const count = 10; - const chunk = 'test'; - const chunkLength = Buffer.byteLength(chunk); - const contentLength = count * chunkLength; - - var readable = stream.Readable.from( - (async function* () { - let i = count; - - while (i-- > 0) { - await setTimeoutAsync(1100); - content += chunk; - yield chunk; - } - })() - ); - - const samples = []; - - const { data } = await axios.post(LOCAL_SERVER_URL, readable, { - onDownloadProgress: ({ loaded, total, progress, bytes, download }) => { - console.log('onDownloadProgress', loaded, '/', total); - samples.push({ - loaded, - total, - progress, - bytes, - download, - }); - }, - headers: { - 'Content-Length': contentLength, - }, - responseType: 'text', - maxRedirects: 0, - }); - - assert.strictEqual(data, content); - - assert.deepStrictEqual( - samples, - Array.from( - (function* () { - for (let i = 1; i <= 10; i++) { - yield { - loaded: chunkLength * i, - total: contentLength, - progress: (chunkLength * i) / contentLength, - bytes: 4, - download: true, - }; - } - })() - ) - ); - }); - }); - }); - - describe('Rate limit', function () { - this.timeout(30000); - - it('should support upload rate limit', async function () { - const secs = 10; - const configRate = 100_000; - const chunkLength = configRate * secs; - - server = await startHTTPServer(); - - const buf = Buffer.alloc(chunkLength).fill('s'); - const samples = []; - const skip = 4; - const compareValues = toleranceRange(50, 50); - - const { data } = await axios.post(LOCAL_SERVER_URL, buf, { - onUploadProgress: ({ loaded, total, progress, bytes, rate }) => { - samples.push({ - loaded, - total, - progress, - bytes, - rate, - }); - }, - maxRate: [configRate], - responseType: 'text', - maxRedirects: 0, - }); - - samples.slice(skip).forEach(({ rate, progress }, i, _samples) => { - assert.ok( - compareValues(rate, configRate), - `Rate sample at index ${i} is out of the expected range (${rate} / ${configRate}) [${_samples - .map(({ rate }) => rate) - .join(', ')}]` - ); - - const progressTicksRate = 2; - const expectedProgress = (i + skip) / secs / progressTicksRate; - - assert.ok( - Math.abs(expectedProgress - progress) < 0.25, - `Progress sample at index ${i} is out of the expected range (${progress} / ${expectedProgress}) [${_samples - .map(({ progress }) => progress) - .join(', ')}]` - ); - }); - - assert.strictEqual(data, buf.toString(), 'content corrupted'); - }); - - it('should support download rate limit', async function () { - const secs = 10; - const configRate = 100_000; - const chunkLength = configRate * secs; - - server = await startHTTPServer(); - - const buf = Buffer.alloc(chunkLength).fill('s'); - const samples = []; - const skip = 4; - const compareValues = toleranceRange(50, 50); - - const { data } = await axios.post(LOCAL_SERVER_URL, buf, { - onDownloadProgress: ({ loaded, total, progress, bytes, rate }) => { - samples.push({ - loaded, - total, - progress, - bytes, - rate, - }); - }, - maxRate: [0, configRate], - responseType: 'text', - maxRedirects: 0, - }); - - samples.slice(skip).forEach(({ rate, progress }, i, _samples) => { - assert.ok( - compareValues(rate, configRate), - `Rate sample at index ${i} is out of the expected range (${rate} / ${configRate}) [${_samples - .map(({ rate }) => rate) - .join(', ')}]` - ); - - const progressTicksRate = 3; - const expectedProgress = (i + skip) / secs / progressTicksRate; - - assert.ok( - Math.abs(expectedProgress - progress) < 0.25, - `Progress sample at index ${i} is out of the expected range (${progress} / ${expectedProgress}) [${_samples - .map(({ progress }) => progress) - .join(', ')}]` - ); - }); - - assert.strictEqual(data, buf.toString(), 'content corrupted'); - }); - }); - - describe('request aborting', function () { - it('should be able to abort the response stream', async () => { - server = await startHTTPServer({ - rate: 100_000, - useBuffering: true, - }); - - const buf = Buffer.alloc(1024 * 1024); - - const controller = new AbortController(); - - const { data } = await axios.post(LOCAL_SERVER_URL, buf, { - responseType: 'stream', - signal: controller.signal, - maxRedirects: 0, - }); - - setTimeout(() => { - controller.abort(); - }, 500); - - let streamError; - - data.on('error', function (err) { - streamError = err; - }); - - await assert.rejects(() => pipelineAsync([data, devNull()])); - - assert.strictEqual(streamError && streamError.code, 'ERR_CANCELED'); - }); - }); - - it('should properly handle synchronous errors inside the adapter', function () { - return assert.rejects(() => axios.get('http://192.168.0.285'), /Invalid URL/); - }); - - it('should support function as paramsSerializer value', async () => { - server = await startHTTPServer((req, res) => res.end(req.url)); - - const { data } = await axios.post(LOCAL_SERVER_URL, 'test', { - params: { - x: 1, - }, - paramsSerializer: () => 'foo', - maxRedirects: 0, - }); - - assert.strictEqual(data, '/?foo'); - }); - - describe('DNS', function () { - it('should support a custom DNS lookup function', async function () { - server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); - - const payload = 'test'; - - let isCalled = false; - - const { data } = await axios.post(`http://fake-name.axios:4444`, payload, { - lookup: (hostname, opt, cb) => { - isCalled = true; - cb(null, '127.0.0.1', 4); - }, - }); - - assert.ok(isCalled); - - assert.strictEqual(data, payload); - }); - - it('should support a custom DNS lookup function with address entry passing', async function () { - server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); - - const payload = 'test'; - - let isCalled = false; - - const { data } = await axios.post(`http://fake-name.axios:4444`, payload, { - lookup: (hostname, opt, cb) => { - isCalled = true; - cb(null, { address: '127.0.0.1', family: 4 }); - }, - }); - - assert.ok(isCalled); - - assert.strictEqual(data, payload); - }); - - it('should support a custom DNS lookup function (async)', async function () { - server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); - - const payload = 'test'; - - let isCalled = false; - - const { data } = await axios.post(`http://fake-name.axios:4444`, payload, { - lookup: async (hostname, opt) => { - isCalled = true; - return ['127.0.0.1', 4]; - }, - }); - - assert.ok(isCalled); - - assert.strictEqual(data, payload); - }); - - it('should support a custom DNS lookup function with address entry (async)', async function () { - server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); - - const payload = 'test'; - - let isCalled = false; - - const { data } = await axios.post(`http://fake-name.axios:4444`, payload, { - lookup: async (hostname, opt) => { - isCalled = true; - return { address: '127.0.0.1', family: 4 }; - }, - }); - - assert.ok(isCalled); - - assert.strictEqual(data, payload); - }); - - it('should support a custom DNS lookup function that returns only IP address (async)', async function () { - server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); - - const payload = 'test'; - - let isCalled = false; - - const { data } = await axios.post(`http://fake-name.axios:4444`, payload, { - lookup: async (hostname, opt) => { - isCalled = true; - return '127.0.0.1'; - }, - }); - - assert.ok(isCalled); - - assert.strictEqual(data, payload); - }); - - it('should handle errors', () => { - return assert.rejects(async () => { - await axios.get('https://no-such-domain-987654.com', { - lookup, - }); - }, /ENOTFOUND/); - }); - }); - - describe('JSON', function () { - it('should support reviver on JSON.parse', async function () { - server = await startHTTPServer(async (_, res) => { - res.end( - JSON.stringify({ - foo: 'bar', - }) - ); - }); - - const { data } = await axios.get(LOCAL_SERVER_URL, { - parseReviver: (key, value) => { - return key === 'foo' ? 'success' : value; - }, - }); - - assert.deepStrictEqual(data, { foo: 'success' }); - }); - }); - - describe('HTTP2', function () { - const LOCAL_SERVER_URL = 'https://127.0.0.1:4444'; - - const http2Axios = axios.create({ - baseURL: LOCAL_SERVER_URL, - httpVersion: 2, - http2Options: { - rejectUnauthorized: false, - }, - }); - - it('should merge request http2Options with its instance config', async () => { - const { data } = await http2Axios.get('/', { - http2Options: { - foo: 'test', - }, - adapter: async (config) => { - return { - data: config.http2Options, - }; - }, - }); - - assert.deepStrictEqual(data, { - rejectUnauthorized: false, - foo: 'test', - }); - }); - - it('should support http2 transport', async () => { - server = await startHTTPServer( - (req, res) => { - res.end('OK'); - }, - { - useHTTP2: true, - } - ); - - const { data } = await http2Axios.get(LOCAL_SERVER_URL); - - assert.deepStrictEqual(data, 'OK'); - }); - - it(`should support request payload`, async () => { - server = await startHTTPServer(null, { - useHTTP2: true, - }); - - const payload = 'DATA'; - - const { data } = await http2Axios.post(LOCAL_SERVER_URL, payload); - - assert.deepStrictEqual(data, payload); - }); - - it(`should support FormData as a payload`, async function () { - if (typeof FormData !== 'function') { - this.skip(); - } - - server = await startHTTPServer( - async (req, res) => { - const { fields, files } = await handleFormData(req); - - res.end( - JSON.stringify({ - fields, - files, - }) - ); - }, - { - useHTTP2: true, - } - ); - - const form = new FormData(); - - form.append('x', 'foo'); - form.append('y', 'bar'); - - const { data } = await http2Axios.post(LOCAL_SERVER_URL, form); - - assert.deepStrictEqual(data, { - fields: { - x: 'foo', - y: 'bar', - }, - files: {}, - }); - }); - - describe('response types', () => { - const originalData = '{"test": "OK"}'; - - const fixtures = { - text: (v) => assert.strictEqual(v, originalData), - arraybuffer: (v) => assert.deepStrictEqual(v, Buffer.from(originalData)), - stream: async (v) => assert.deepStrictEqual(await getStream(v), originalData), - json: async (v) => assert.deepStrictEqual(v, JSON.parse(originalData)), - }; - - for (let [responseType, assertValue] of Object.entries(fixtures)) { - it(`should support ${responseType} response type`, async () => { - server = await startHTTPServer( - (req, res) => { - res.end(originalData); - }, - { - useHTTP2: true, - } - ); - - const { data } = await http2Axios.get(LOCAL_SERVER_URL, { - responseType, - }); - - await assertValue(data); - }); - } - }); - - it('should support request timeout', async () => { - let isAborted = false; - - let aborted; - const promise = new Promise((resolve) => (aborted = resolve)); - - server = await startHTTPServer( - (req, res) => { - setTimeout(() => { - res.end('OK'); - }, 15000); - }, - { - useHTTP2: true, - } - ); - - server.on('stream', (stream) => { - stream.once('aborted', () => { - isAborted = true; - aborted(); - }); - }); - - await assert.rejects(async () => { - await http2Axios.get(LOCAL_SERVER_URL, { - timeout: 500, - }); - }, /timeout/); - - await promise; - - assert.ok(isAborted); - }); - - it('should support request cancellation', async function () { - if (typeof AbortSignal !== 'function' || !AbortSignal.timeout) { - this.skip(); - } - - let isAborted = false; - - let aborted; - const promise = new Promise((resolve) => (aborted = resolve)); - - server = await startHTTPServer( - (req, res) => { - setTimeout(() => { - res.end('OK'); - }, 15000); - }, - { - useHTTP2: true, - } - ); - - server.on('stream', (stream) => { - stream.once('aborted', () => { - isAborted = true; - aborted(); - }); - }); - - await assert.rejects(async () => { - await http2Axios.get(LOCAL_SERVER_URL, { - signal: AbortSignal.timeout(500), - }); - }, /CanceledError: canceled/); - - await promise; - - assert.ok(isAborted); - }); - - it('should support stream response cancellation', async () => { - let isAborted = false; - var source = axios.CancelToken.source(); - - let aborted; - const promise = new Promise((resolve) => (aborted = resolve)); - - server = await startHTTPServer( - (req, res) => { - generateReadable(10000, 100, 100).pipe(res); - }, - { - useHTTP2: true, - } - ); - - server.on('stream', (stream) => { - stream.once('aborted', () => { - isAborted = true; - aborted(); - }); - }); - - const { data } = await http2Axios.get(LOCAL_SERVER_URL, { - cancelToken: source.token, - responseType: 'stream', - }); - - setTimeout(() => source.cancel()); - - await assert.rejects(() => pipelineAsync([data, devNull()]), /CanceledError: canceled/); - - await promise; - - assert.ok(isAborted); - }); - - describe('session', () => { - it('should reuse session for the target authority', async () => { - server = await startHTTPServer( - (req, res) => { - setTimeout(() => res.end('OK'), 1000); - }, - { - useHTTP2: true, - } - ); - - const [response1, response2] = await Promise.all([ - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - }), - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - }), - ]); - - assert.strictEqual(response1.data.session, response2.data.session); - - assert.deepStrictEqual( - await Promise.all([getStream(response1.data), getStream(response2.data)]), - ['OK', 'OK'] - ); - }); - - it('should use different sessions for different authorities', async () => { - server = await startHTTPServer( - (req, res) => { - setTimeout(() => { - res.end('OK'); - }, 2000); - }, - { - useHTTP2: true, - } - ); - - server2 = await startHTTPServer( - (req, res) => { - setTimeout(() => { - res.end('OK'); - }, 2000); - }, - { - useHTTP2: true, - port: SERVER_PORT2, - } - ); - - const [response1, response2] = await Promise.all([ - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - }), - http2Axios.get(LOCAL_SERVER_URL2, { - responseType: 'stream', - }), - ]); - - assert.notStrictEqual(response1.data.session, response2.data.session); - - assert.deepStrictEqual( - await Promise.all([getStream(response1.data), getStream(response2.data)]), - ['OK', 'OK'] - ); - }); - - it('should use different sessions for requests with different http2Options set', async () => { - server = await startHTTPServer( - (req, res) => { - setTimeout(() => { - res.end('OK'); - }, 1000); - }, - { - useHTTP2: true, - } - ); - - const [response1, response2] = await Promise.all([ - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - http2Options: {}, - }), - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - http2Options: { - foo: 'test', - }, - }), - ]); - - assert.notStrictEqual(response1.data.session, response2.data.session); - - assert.deepStrictEqual( - await Promise.all([getStream(response1.data), getStream(response2.data)]), - ['OK', 'OK'] - ); - }); - - it('should use the same session for request with the same resolved http2Options set', async () => { - server = await startHTTPServer( - (req, res) => { - setTimeout(() => res.end('OK'), 1000); - }, - { - useHTTP2: true, - } - ); - - const responses = await Promise.all([ - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - }), - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - http2Options: undefined, - }), - http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - http2Options: {}, - }), - ]); - - assert.strictEqual(responses[1].data.session, responses[0].data.session); - assert.strictEqual(responses[2].data.session, responses[0].data.session); - - assert.deepStrictEqual(await Promise.all(responses.map(({ data }) => getStream(data))), [ - 'OK', - 'OK', - 'OK', - ]); - }); - - it('should use different sessions after previous session timeout', async () => { - server = await startHTTPServer( - (req, res) => { - setTimeout(() => res.end('OK'), 100); - }, - { - useHTTP2: true, - } - ); - - const response1 = await http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - http2Options: { - sessionTimeout: 1000, - }, - }); - - const data1 = await getStream(response1.data); - - await setTimeoutAsync(5000); - - const response2 = await http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - http2Options: { - sessionTimeout: 1000, - }, - }); - - const data2 = await getStream(response2.data); - - assert.notStrictEqual(response1.data.session, response2.data.session); - - assert.strictEqual(data1, 'OK'); - assert.strictEqual(data2, 'OK'); - }); - - it('should close connection after sessionTimeout ends', async () => { - server = await startHTTPServer( - (req, res) => { - setTimeout(() => res.end('OK'), 100); - }, - { - useHTTP2: true, - } - ); - - const response = await http2Axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - http2Options: { - sessionTimeout: 1000, - }, - }); - - assert.strictEqual(response.data.session.closed, false); - - let sessionClosed = false; - response.data.session.once('close', () => { - sessionClosed = true; - }); - - const data = await getStream(response.data); - assert.strictEqual(data, 'OK'); - - await setTimeoutAsync(1100); - assert.strictEqual(sessionClosed, true); - }); - }); - }); - - it('should not abort stream on settle rejection', async () => { - server = await startHTTPServer((req, res) => { - res.statusCode = 404; - res.end('OK'); - }); - - try { - await axios.get(LOCAL_SERVER_URL, { - responseType: 'stream', - }); - - assert.fail('should be rejected'); - } catch (err) { - assert.strictEqual(await getStream(err.response.data), 'OK'); - } - }); - - describe('keep-alive', () => { - it('should not fail with "socket hang up" when using timeouts', async () => { - server = await startHTTPServer(async (req, res) => { - if (req.url === '/wait') { - await new Promise((resolve) => setTimeout(resolve, 5000)); - } - res.end('ok'); - }); - - const baseURL = LOCAL_SERVER_URL; - await axios.get('/1', { baseURL, timeout: 1000 }); - await axios.get(`/wait`, { baseURL, timeout: 0 }); - }, 15000); - }); -}); diff --git a/test/unit/adapters/key.pem b/test/unit/adapters/key.pem deleted file mode 100644 index 9ce05bf9..00000000 --- a/test/unit/adapters/key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEA+joLfff3WdFIGwrlVdUWfZ9vDr9w86yQpI6Xq0KF6JiKtxa+ -EVCNWtq8Ht5rZd1MxNSFWVb1jxnRLBEB8F3wLD/4xRk8CNxw8joXKsxUEirI76iV -mJDjm/tq90gaxZUWVtPZP95Qvocdl7brhuvLuF4J9wJVL5tr6ZYAje3omHBnjcFb -n9nh3Tqk0U6omAmS4k/BrXWDA1zq8LBmbP41CnfVNGq/5asDIZsNO8s5VQzNjFjN -rcqv2rEO0n+77qDBbqALQydxPmytZP+0jYXcj+EaJ4clApFhvps6Cg0taoF66E4k -Eg1JLALzgk3I/ATSE3nvi3J/RWkyjSYiolPavwIDAQABAoIBAEbMi5ndwjfAlkVI -hPEPNKjgpnymwB/CEL7utY04akkQeBcrsSWXBBfT0exuBDczMVhzxTMs/pe5t0xf -l4vaGG18wDeMV0cukCqJMyrh21u0jVv5+DHNtQjaTz6eQSzsbQCuOkbu8SuncUEO -+X8YUnDc8rbYCyBIOnVCAvAlg201uW0G5G9NEwJOu6cAKMKkogdHqv+FRX96C5hm -gtbGEzpGV2vVClgMwMcX49ucluZvqLvit/yehNVd0VOtW/kuLup4R6q0abHRapDd -95rJAhPvar4mzP+UgJrGQ9hozqhizDthBjnsmGeMBUiBCkay7OXIZpvLoCpQkti1 -WIWuikkCgYEA/oZqq71RT1nPuI7rlcjx3AeWe2EUQtKhQMJBiPx5eLLP6gII8+v2 -pD1qlmJM2eyIK0lzuskLIulTAA5Z+ejORDbvmn/DdT0CSvdrUFrcvnrRQnt2M5M2 -9VDRp6nvPE0H4kRZJrtITyLn0dv5ABf2L32i4dPCMePjKjSUygJSHrsCgYEA+61A -cIqch/lrQTk8hG7Y6p0EJzSInFVaKuZoMYpLhlDQcVvSDIQbGgRAN6BKTdxeQ+tK -hSxBSm2mze11aHig8GBGgdBFLaJOZRo6G+2fl+s1t1FCHfsaFhHwheZJONHMpKKd -Qm/7L/V35QV9YG0lPZ01TM6d5lXuKsmUNvBJTc0CgYASYajAgGqn3WeX/5JZ/eoh -ptaiUG+DJ+0HXUAYYYtwQRGs57q3yvnEAL963tyH/IIVBjf6bFyGh+07ms26s6p5 -2LHTKZj3FZHd0iKI6hb5FquYLoxpyx7z9oM9pZMmerWwDJmXp3zgYjf1uvovnItm -AJ/LyVxD+B5GxQdd028U0wKBgG4OllZglxDzJk7wa6FyI9N89Fr8oxzSSkrmVPwN -APfskSpxP8qPXpai8z4gDz47NtG2q/DOqIKWrtHwnF4iGibjwxFzdTz+dA/MR0r9 -P8QcbHIMy7/2lbK/B5JWYQDC5h28qs5pz8tqKZLyMqCfOiDWhX9f/zbBrxPw8KqR -q0ylAoGAL/0kemA/Tmxpwmp0S0oCqnA4gbCgS7qnApxB09xTewc/tuvraXc3Mzea -EvqDXLXK0R7O4E3vo0Mr23SodRVlFPevsmUUJLPJMJcxdfnSJgX+qE/UC8Ux+UMi -eYufYRDYSslfL2rt9D7abnnbqSfsHymJKukWpElIgJTklQUru4k= ------END RSA PRIVATE KEY----- diff --git a/test/unit/core/Axios.js b/test/unit/core/Axios.js deleted file mode 100644 index a0647ad3..00000000 --- a/test/unit/core/Axios.js +++ /dev/null @@ -1,54 +0,0 @@ -/* eslint-env mocha */ -import Axios from '../../../lib/core/Axios.js'; -import assert from 'assert'; - -describe('Axios', function () { - describe('handle un-writable error stack', function () { - async function testUnwritableErrorStack(stackAttributes) { - const axios = new Axios({}); - // mock axios._request to return an Error with an un-writable stack property - axios._request = () => { - const mockError = new Error('test-error'); - Object.defineProperty(mockError, 'stack', stackAttributes); - throw mockError; - }; - try { - await axios.request('test-url', {}); - } catch (e) { - assert.strictEqual(e.message, 'test-error'); - } - } - - it('should support errors with a defined but un-writable stack', async function () { - await testUnwritableErrorStack({ value: {}, writable: false }); - }); - - it('should support errors with an undefined and un-writable stack', async function () { - await testUnwritableErrorStack({ value: undefined, writable: false }); - }); - - it('should support errors with a custom getter/setter for the stack property', async function () { - await testUnwritableErrorStack({ - get: () => ({}), - set: () => { - throw new Error('read-only'); - }, - }); - }); - - it('should support errors with a custom getter/setter for the stack property (null case)', async function () { - await testUnwritableErrorStack({ - get: () => null, - set: () => { - throw new Error('read-only'); - }, - }); - }); - }); - - it('should not throw if the config argument is omitted', () => { - const axios = new Axios(); - - assert.deepStrictEqual(axios.defaults, {}); - }); -}); diff --git a/test/unit/core/AxiosHeaders.js b/test/unit/core/AxiosHeaders.js deleted file mode 100644 index 9a36f08a..00000000 --- a/test/unit/core/AxiosHeaders.js +++ /dev/null @@ -1,527 +0,0 @@ -/* eslint-env mocha */ -import AxiosHeaders from '../../../lib/core/AxiosHeaders.js'; -import assert from 'assert'; - -const [nodeMajorVersion] = process.versions.node.split('.').map((v) => parseInt(v, 10)); - -describe('AxiosHeaders', function () { - it('should support headers argument', function () { - const headers = new AxiosHeaders({ - x: 1, - y: 2, - }); - - assert.strictEqual(headers.get('x'), '1'); - assert.strictEqual(headers.get('y'), '2'); - }); - - describe('set', function () { - it('should support adding a single header', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar'); - - assert.strictEqual(headers.get('foo'), 'bar'); - }); - - it('should support adding multiple headers', function () { - const headers = new AxiosHeaders(); - - headers.set({ - foo: 'value1', - bar: 'value2', - }); - - assert.strictEqual(headers.get('foo'), 'value1'); - assert.strictEqual(headers.get('bar'), 'value2'); - }); - - it('should support adding multiple headers from raw headers string', function () { - const headers = new AxiosHeaders(); - - headers.set(`foo:value1\nbar:value2`); - - assert.strictEqual(headers.get('foo'), 'value1'); - assert.strictEqual(headers.get('bar'), 'value2'); - }); - - it('should not rewrite header the header if the value is false', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'value1'); - - headers.set('foo', 'value2', false); - - assert.strictEqual(headers.get('foo'), 'value1'); - - headers.set('foo', 'value2'); - - assert.strictEqual(headers.get('foo'), 'value2'); - - headers.set('foo', 'value3', true); - - assert.strictEqual(headers.get('foo'), 'value3'); - }); - - it('should not rewrite the header if its value is false, unless rewrite options is set to true', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', false); - headers.set('foo', 'value2'); - - assert.strictEqual(headers.get('foo'), false); - - headers.set('foo', 'value2', true); - - assert.strictEqual(headers.get('foo'), 'value2'); - }); - - it('should support iterables as a key-value source object', function () { - const headers = new AxiosHeaders(); - - headers.set(new Map([['x', '123']])); - - assert.strictEqual(headers.get('x'), '123'); - }); - - it('should trim trailing CRLF from plain object header values', function () { - const headers = new AxiosHeaders(); - - headers.set({ - 'cache-control': 'no-cache\r', - expires: '-1\r\n', - }); - - assert.strictEqual(headers.get('cache-control'), 'no-cache'); - assert.strictEqual(headers.get('expires'), '-1'); - }); - - it('should trim trailing CRLF from iterable header values', function () { - const headers = new AxiosHeaders(); - - headers.set(new Map([ - ['content-type', 'application/json; charset=utf-8\r'], - ['pragma', 'no-cache\r\n'], - ])); - - assert.strictEqual(headers.get('content-type'), 'application/json; charset=utf-8'); - assert.strictEqual(headers.get('pragma'), 'no-cache'); - }); - - it('should support setting multiple header values from an iterable source', function () { - if (nodeMajorVersion < 18) { - this.skip(); - return; - } - - const headers = new AxiosHeaders(); - - const nativeHeaders = new Headers(); - - nativeHeaders.append('set-cookie', 'foo'); - nativeHeaders.append('set-cookie', 'bar'); - nativeHeaders.append('set-cookie', 'baz'); - nativeHeaders.append('y', 'qux'); - - headers.set(nativeHeaders); - - assert.deepStrictEqual(headers.get('set-cookie'), ['foo', 'bar', 'baz']); - assert.strictEqual(headers.get('y'), 'qux'); - }); - }); - - it('should support uppercase name mapping for names overlapped by class methods', () => { - const headers = new AxiosHeaders({ - set: 'foo', - }); - - headers.set('get', 'bar'); - - assert.strictEqual(headers.get('Set'), 'foo'); - assert.strictEqual(headers.get('Get'), 'bar'); - }); - - describe('get', function () { - describe('filter', function () { - it('should support RegExp', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.get('foo', /^bar=(\w+)/)[1], 'value1'); - assert.strictEqual(headers.get('foo', /^foo=/), null); - }); - - it('should support function', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual( - headers.get('foo', (value, header) => { - assert.strictEqual(value, 'bar=value1'); - assert.strictEqual(header, 'foo'); - return value; - }), - 'bar=value1' - ); - assert.strictEqual( - headers.get('foo', () => false), - false - ); - }); - }); - }); - - describe('has', function () { - it('should return true if the header is defined, otherwise false', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.has('foo'), true); - assert.strictEqual(headers.has('bar'), false); - }); - - describe('filter', function () { - it('should support RegExp', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.has('foo', /^bar=(\w+)/), true); - assert.strictEqual(headers.has('foo', /^foo=/), false); - }); - - it('should support function', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual( - headers.has('foo', (value, header, headers) => { - assert.strictEqual(value, 'bar=value1'); - assert.strictEqual(header, 'foo'); - return true; - }), - true - ); - assert.strictEqual( - headers.has('foo', () => false), - false - ); - }); - - it('should support string pattern', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.has('foo', 'value1'), true); - assert.strictEqual(headers.has('foo', 'value2'), false); - }); - }); - }); - - describe('delete', function () { - it('should delete the header', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.has('foo'), true); - - headers.delete('foo'); - - assert.strictEqual(headers.has('foo'), false); - }); - - it('should return true if the header has been deleted, otherwise false', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.delete('bar'), false); - - assert.strictEqual(headers.delete('foo'), true); - }); - - it('should support headers array', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'x'); - headers.set('bar', 'y'); - headers.set('baz', 'z'); - - assert.strictEqual(headers.delete(['foo', 'baz']), true); - - assert.strictEqual(headers.has('foo'), false); - assert.strictEqual(headers.has('bar'), true); - assert.strictEqual(headers.has('baa'), false); - }); - - describe('filter', function () { - it('should support RegExp', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.has('foo'), true); - - headers.delete('foo', /baz=/); - - assert.strictEqual(headers.has('foo'), true); - - headers.delete('foo', /bar=/); - - assert.strictEqual(headers.has('foo'), false); - }); - - it('should support function', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - headers.delete('foo', (value, header) => { - assert.strictEqual(value, 'bar=value1'); - assert.strictEqual(header, 'foo'); - return false; - }); - - assert.strictEqual(headers.has('foo'), true); - - assert.strictEqual( - headers.delete('foo', () => true), - true - ); - - assert.strictEqual(headers.has('foo'), false); - }); - - it('should support string pattern', function () { - const headers = new AxiosHeaders(); - - headers.set('foo', 'bar=value1'); - - assert.strictEqual(headers.has('foo'), true); - - headers.delete('foo', 'baz'); - - assert.strictEqual(headers.has('foo'), true); - - headers.delete('foo', 'bar'); - - assert.strictEqual(headers.has('foo'), false); - }); - }); - }); - - describe('clear', () => { - it('should clear all headers', () => { - const headers = new AxiosHeaders({ x: 1, y: 2 }); - - headers.clear(); - - assert.deepStrictEqual({ ...headers.toJSON() }, {}); - }); - - it('should clear matching headers if a matcher was specified', () => { - const headers = new AxiosHeaders({ foo: 1, 'x-foo': 2, bar: 3 }); - - assert.deepStrictEqual({ ...headers.toJSON() }, { foo: '1', 'x-foo': '2', bar: '3' }); - - headers.clear(/^x-/); - - assert.deepStrictEqual({ ...headers.toJSON() }, { foo: '1', bar: '3' }); - }); - }); - - describe('toJSON', function () { - it('should return headers object with original headers case', function () { - const headers = new AxiosHeaders({ - Foo: 'x', - bAr: 'y', - }); - - assert.deepStrictEqual( - { ...headers.toJSON() }, - { - Foo: 'x', - bAr: 'y', - } - ); - }); - }); - - describe('accessors', function () { - it('should support get accessor', function () { - const headers = new AxiosHeaders({ - foo: 1, - }); - - headers.constructor.accessor('foo'); - - assert.strictEqual(typeof headers.getFoo, 'function'); - assert.strictEqual(headers.getFoo(), '1'); - }); - - it('should support set accessor', function () { - const headers = new AxiosHeaders({ - foo: 1, - }); - - headers.constructor.accessor('foo'); - - assert.strictEqual(typeof headers.setFoo, 'function'); - headers.setFoo(2); - assert.strictEqual(headers.getFoo(), '2'); - }); - - it('should support has accessor', function () { - const headers = new AxiosHeaders({ - foo: 1, - }); - - headers.constructor.accessor('foo'); - - assert.strictEqual(typeof headers.hasFoo, 'function'); - assert.strictEqual(headers.hasFoo(), true); - }); - }); - - it('should be caseless', function () { - const headers = new AxiosHeaders({ - fOo: 1, - }); - - assert.strictEqual(headers.get('Foo'), '1'); - assert.strictEqual(headers.get('foo'), '1'); - - headers.set('foo', 2); - - assert.strictEqual(headers.get('foO'), '2'); - assert.strictEqual(headers.get('fOo'), '2'); - - assert.strictEqual(headers.has('fOo'), true); - - headers.delete('FOO'); - - assert.strictEqual(headers.has('fOo'), false); - }); - - describe('normalize()', function () { - it('should support auto-formatting', function () { - const headers = new AxiosHeaders({ - fOo: 1, - 'x-foo': 2, - 'y-bar-bAz': 3, - }); - - assert.deepStrictEqual( - { ...headers.normalize(true).toJSON() }, - { - Foo: '1', - 'X-Foo': '2', - 'Y-Bar-Baz': '3', - } - ); - }); - - it('should support external defined values', function () { - const headers = new AxiosHeaders({ - foo: '1', - }); - - headers['Foo'] = 2; - - headers['bar'] = 3; - - assert.deepStrictEqual( - { ...headers.normalize().toJSON() }, - { - foo: '2', - bar: '3', - } - ); - }); - - it('should support array values', function () { - const headers = new AxiosHeaders({ - foo: [1, 2, 3], - }); - - assert.deepStrictEqual( - { ...headers.normalize().toJSON() }, - { - foo: ['1', '2', '3'], - } - ); - }); - }); - - describe('AxiosHeaders.concat', function () { - it('should concatenate plain headers into an AxiosHeader instance', function () { - const a = { a: 1 }; - const b = { b: 2 }; - const c = { c: 3 }; - const headers = AxiosHeaders.concat(a, b, c); - - assert.deepStrictEqual( - { ...headers.toJSON() }, - { - a: '1', - b: '2', - c: '3', - } - ); - }); - - it('should concatenate raw headers into an AxiosHeader instance', function () { - const a = 'a:1\nb:2'; - const b = 'c:3\nx:4'; - const headers = AxiosHeaders.concat(a, b); - - assert.deepStrictEqual( - { ...headers.toJSON() }, - { - a: '1', - b: '2', - c: '3', - x: '4', - } - ); - }); - - it('should concatenate Axios headers into a new AxiosHeader instance', function () { - const a = new AxiosHeaders({ x: 1 }); - const b = new AxiosHeaders({ y: 2 }); - const headers = AxiosHeaders.concat(a, b); - - assert.deepStrictEqual( - { ...headers.toJSON() }, - { - x: '1', - y: '2', - } - ); - }); - }); - - describe('toString', function () { - it('should serialize AxiosHeader instance to a raw headers string', function () { - assert.deepStrictEqual(new AxiosHeaders({ x: 1, y: 2 }).toString(), 'x: 1\ny: 2'); - }); - }); - - describe('getSetCookie', function () { - it('should return set-cookie', function () { - const headers = new AxiosHeaders('Set-Cookie: key=val;\n' + 'Set-Cookie: key2=val2;\n'); - - assert.deepStrictEqual(headers.getSetCookie(), ['key=val;', 'key2=val2;']); - }); - - it('should return empty set-cookie', function () { - assert.deepStrictEqual(new AxiosHeaders().getSetCookie(), []); - }); - }); -}); diff --git a/test/unit/core/prototypePollution.js b/test/unit/core/prototypePollution.js deleted file mode 100644 index 810fd0d8..00000000 --- a/test/unit/core/prototypePollution.js +++ /dev/null @@ -1,213 +0,0 @@ -/* eslint-disable no-prototype-builtins */ -/* eslint-env mocha */ -'use strict'; - -import assert from 'assert'; -import utils from '../../../lib/utils.js'; -import mergeConfig from '../../../lib/core/mergeConfig.js'; - -describe('Prototype Pollution Protection', function () { - afterEach(function () { - // Clean up any pollution that might have occurred - delete Object.prototype.polluted; - }); - - describe('utils.merge', function () { - it('should filter __proto__ key at top level', function () { - const result = utils.merge({}, { __proto__: { polluted: 'yes' }, safe: 'value' }); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.safe, 'value'); - assert.strictEqual(result.hasOwnProperty('__proto__'), false); - }); - - it('should filter constructor key at top level', function () { - const result = utils.merge({}, { constructor: { polluted: 'yes' }, safe: 'value' }); - - assert.strictEqual(result.safe, 'value'); - assert.strictEqual(result.hasOwnProperty('constructor'), false); - }); - - it('should filter prototype key at top level', function () { - const result = utils.merge({}, { prototype: { polluted: 'yes' }, safe: 'value' }); - - assert.strictEqual(result.safe, 'value'); - assert.strictEqual(result.hasOwnProperty('prototype'), false); - }); - - it('should filter __proto__ key in nested objects', function () { - const result = utils.merge( - {}, - { - headers: { - __proto__: { polluted: 'nested' }, - 'Content-Type': 'application/json', - }, - } - ); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.headers['Content-Type'], 'application/json'); - assert.strictEqual(result.headers.hasOwnProperty('__proto__'), false); - }); - - it('should filter constructor key in nested objects', function () { - const result = utils.merge( - {}, - { - headers: { - constructor: { prototype: { polluted: 'nested' } }, - 'Content-Type': 'application/json', - }, - } - ); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.headers['Content-Type'], 'application/json'); - assert.strictEqual(result.headers.hasOwnProperty('constructor'), false); - }); - - it('should filter prototype key in nested objects', function () { - const result = utils.merge( - {}, - { - headers: { - prototype: { polluted: 'nested' }, - 'Content-Type': 'application/json', - }, - } - ); - - assert.strictEqual(result.headers['Content-Type'], 'application/json'); - assert.strictEqual(result.headers.hasOwnProperty('prototype'), false); - }); - - it('should filter dangerous keys in deeply nested objects', function () { - const result = utils.merge( - {}, - { - level1: { - level2: { - __proto__: { polluted: 'deep' }, - prototype: { polluted: 'deep' }, - safe: 'value', - }, - }, - } - ); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.level1.level2.safe, 'value'); - assert.strictEqual(result.level1.level2.hasOwnProperty('__proto__'), false); - }); - - it('should still merge regular properties correctly', function () { - const result = utils.merge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 }); - - assert.strictEqual(result.a, 1); - assert.strictEqual(result.b.c, 2); - assert.strictEqual(result.b.d, 3); - assert.strictEqual(result.e, 4); - }); - - it('should handle JSON.parse payloads safely', function () { - const malicious = JSON.parse('{"__proto__": {"polluted": "yes"}}'); - const result = utils.merge({}, malicious); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.hasOwnProperty('__proto__'), false); - }); - - it('should handle nested JSON.parse payloads safely', function () { - const malicious = JSON.parse( - '{"headers": {"constructor": {"prototype": {"polluted": "yes"}}}}' - ); - const result = utils.merge({}, malicious); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.headers.hasOwnProperty('constructor'), false); - }); - }); - - describe('mergeConfig', function () { - it('should filter dangerous keys at top level', function () { - const result = mergeConfig( - {}, - { - __proto__: { polluted: 'yes' }, - constructor: { polluted: 'yes' }, - prototype: { polluted: 'yes' }, - url: '/api/test', - } - ); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.url, '/api/test'); - assert.strictEqual(result.hasOwnProperty('__proto__'), false); - assert.strictEqual(result.hasOwnProperty('constructor'), false); - assert.strictEqual(result.hasOwnProperty('prototype'), false); - }); - - it('should filter dangerous keys in headers', function () { - const result = mergeConfig( - {}, - { - headers: { - __proto__: { polluted: 'yes' }, - 'Content-Type': 'application/json', - }, - } - ); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.headers['Content-Type'], 'application/json'); - assert.strictEqual(result.headers.hasOwnProperty('__proto__'), false); - }); - - it('should filter dangerous keys in custom config properties', function () { - const result = mergeConfig( - {}, - { - customProp: { - __proto__: { polluted: 'yes' }, - safe: 'value', - }, - } - ); - - assert.strictEqual(Object.prototype.polluted, undefined); - assert.strictEqual(result.customProp.safe, 'value'); - assert.strictEqual(result.customProp.hasOwnProperty('__proto__'), false); - }); - - it('should still merge configs correctly', function () { - const config1 = { - baseURL: 'https://api.example.com', - timeout: 1000, - headers: { - common: { - Accept: 'application/json', - }, - }, - }; - - const config2 = { - url: '/users', - timeout: 5000, - headers: { - common: { - 'Content-Type': 'application/json', - }, - }, - }; - - const result = mergeConfig(config1, config2); - - assert.strictEqual(result.baseURL, 'https://api.example.com'); - assert.strictEqual(result.url, '/users'); - assert.strictEqual(result.timeout, 5000); - assert.strictEqual(result.headers.common.Accept, 'application/json'); - assert.strictEqual(result.headers.common['Content-Type'], 'application/json'); - }); - }); -}); diff --git a/test/unit/defaults/transformResponse.js b/test/unit/defaults/transformResponse.js deleted file mode 100644 index 5418114f..00000000 --- a/test/unit/defaults/transformResponse.js +++ /dev/null @@ -1,67 +0,0 @@ -/* eslint-env mocha */ -import defaults from '../../../lib/defaults/index.js'; -import transformData from '../../../lib/core/transformData.js'; -import assert from 'assert'; - -describe('transformResponse', function () { - describe('200 request', function () { - it('parses json', function () { - const data = '{"message": "hello, world"}'; - const result = transformData.call( - { - data, - response: { - headers: { 'content-type': 'application/json' }, - status: 200, - }, - }, - defaults.transformResponse - ); - assert.strictEqual(result.message, 'hello, world'); - }); - it('ignores XML', function () { - const data = 'hello, world'; - const result = transformData.call( - { - data, - response: { - headers: { 'content-type': 'text/xml' }, - status: 200, - }, - }, - defaults.transformResponse - ); - assert.strictEqual(result, data); - }); - }); - describe('204 request', function () { - it('does not parse the empty string', function () { - const data = ''; - const result = transformData.call( - { - data, - response: { - headers: { 'content-type': undefined }, - status: 204, - }, - }, - defaults.transformResponse - ); - assert.strictEqual(result, ''); - }); - it('does not parse undefined', function () { - const data = undefined; - const result = transformData.call( - { - data, - response: { - headers: { 'content-type': undefined }, - status: 200, - }, - }, - defaults.transformResponse - ); - assert.strictEqual(result, data); - }); - }); -}); diff --git a/test/unit/helpers/composeSignals.js b/test/unit/helpers/composeSignals.js deleted file mode 100644 index 5fe2d284..00000000 --- a/test/unit/helpers/composeSignals.js +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import composeSignals from '../../../lib/helpers/composeSignals.js'; - -describe('helpers::composeSignals', () => { - before(function () { - if (typeof AbortController !== 'function') { - this.skip(); - } - }); - - it('should abort when any of the signals abort', () => { - let called; - - const controllerA = new AbortController(); - const controllerB = new AbortController(); - - const signal = composeSignals([controllerA.signal, controllerB.signal]); - - signal.addEventListener('abort', () => { - called = true; - }); - - controllerA.abort(new Error('test')); - - assert.ok(called); - }); - - it('should abort on timeout', async () => { - const signal = composeSignals([], 100); - - await new Promise((resolve) => { - signal.addEventListener('abort', resolve); - }); - - assert.match(String(signal.reason), /timeout of 100ms exceeded/); - }); - - it('should return undefined if signals and timeout are not provided', async () => { - const signal = composeSignals([]); - - assert.strictEqual(signal, undefined); - }); -}); diff --git a/test/unit/helpers/estimateDataURLDecodedBytes.spec.js b/test/unit/helpers/estimateDataURLDecodedBytes.spec.js deleted file mode 100644 index b2f7fb85..00000000 --- a/test/unit/helpers/estimateDataURLDecodedBytes.spec.js +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import estimateDataURLDecodedBytes from '../../../lib/helpers/estimateDataURLDecodedBytes.js'; - -describe('estimateDataURLDecodedBytes', () => { - it('should return 0 for non-data URLs', () => { - assert.strictEqual(estimateDataURLDecodedBytes('http://example.com'), 0); - }); - - it('should calculate length for simple non-base64 data URL', () => { - const url = 'data:,Hello'; - assert.strictEqual(estimateDataURLDecodedBytes(url), Buffer.byteLength('Hello', 'utf8')); - }); - - it('should calculate decoded length for base64 data URL', () => { - const str = 'Hello'; - const b64 = Buffer.from(str, 'utf8').toString('base64'); - const url = `data:text/plain;base64,${b64}`; - assert.strictEqual(estimateDataURLDecodedBytes(url), str.length); - }); - - it('should handle base64 with = padding', () => { - const url = 'data:text/plain;base64,TQ=='; // "M" - assert.strictEqual(estimateDataURLDecodedBytes(url), 1); - }); - - it('should handle base64 with %3D padding', () => { - const url = 'data:text/plain;base64,TQ%3D%3D'; // "M" - assert.strictEqual(estimateDataURLDecodedBytes(url), 1); - }); -}); diff --git a/test/unit/helpers/fromDataURI.js b/test/unit/helpers/fromDataURI.js deleted file mode 100644 index 7885d8b2..00000000 --- a/test/unit/helpers/fromDataURI.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import fromDataURI from '../../../lib/helpers/fromDataURI.js'; - -describe('helpers::fromDataURI', function () { - it('should return buffer from data uri', function () { - const buffer = Buffer.from('123'); - - const dataURI = 'data:application/octet-stream;base64,' + buffer.toString('base64'); - - assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); - }); -}); diff --git a/test/unit/helpers/parseProtocol.js b/test/unit/helpers/parseProtocol.js deleted file mode 100644 index 3bcc1054..00000000 --- a/test/unit/helpers/parseProtocol.js +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import utils from '../../../lib/utils.js'; -import parseProtocol from '../../../lib/helpers/parseProtocol.js'; - -describe('helpers::parseProtocol', function () { - it('should parse protocol part if it exists', function () { - utils.forEach( - { - 'http://username:password@example.com/': 'http', - 'ftp:google.com': 'ftp', - 'sms:+15105550101?body=hello%20there': 'sms', - 'tel:0123456789': 'tel', - '//google.com': '', - 'google.com': '', - 'admin://etc/default/grub': 'admin', - 'stratum+tcp://server:port': 'stratum+tcp', - '/api/resource:customVerb': '', - 'https://stackoverflow.com/questions/': 'https', - 'mailto:jsmith@example.com': 'mailto', - 'chrome-extension://1234/.html': 'chrome-extension', - }, - (expectedProtocol, url) => { - assert.strictEqual(parseProtocol(url), expectedProtocol); - } - ); - }); -}); diff --git a/test/unit/helpers/toFormData.js b/test/unit/helpers/toFormData.js deleted file mode 100644 index c2b15845..00000000 --- a/test/unit/helpers/toFormData.js +++ /dev/null @@ -1,133 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import toFormData from '../../../lib/helpers/toFormData.js'; -import FormData from 'form-data'; - -describe('helpers::toFormData', function () { - function createRNFormDataSpy() { - const calls = []; - return { - calls, - append(key, value) { - calls.push([key, value]); - }, - getParts() { - return []; - } - }; - } - - it('should convert a flat object to FormData', function () { - const data = { - foo: 'bar', - baz: 123, - }; - - const formData = toFormData(data, new FormData()); - - assert.ok(formData instanceof FormData); - // form-data package specific checks - assert.ok(formData._streams.length > 0); - }); - - it('should convert a nested object to FormData', function () { - const data = { - foo: { - bar: 'baz', - }, - }; - - const formData = toFormData(data, new FormData()); - - assert.ok(formData instanceof FormData); - }); - - it('should throw Error on circular reference', function () { - const data = { - foo: 'bar', - }; - data.self = data; - - try { - toFormData(data, new FormData()); - assert.fail('Should have thrown an error'); - } catch (e) { - assert.strictEqual(e.message, 'Circular reference detected in self'); - } - }); - - it('should handle arrays', function () { - const data = { - arr: [1, 2, 3], - }; - - const formData = toFormData(data, new FormData()); - assert.ok(formData instanceof FormData); - }); - - it('should append root-level React Native blob without recursion', function () { - const formData = createRNFormDataSpy(); - - const blob = { - uri: 'file://test.png', - type: 'image/png', - name: 'test.png' - }; - - toFormData({ file: blob }, formData); - - assert.strictEqual(formData.calls.length, 1); - assert.strictEqual(formData.calls[0][0], 'file'); - assert.strictEqual(formData.calls[0][1], blob); - }); - - it('should append nested React Native blob without recursion', function () { - const formData = createRNFormDataSpy(); - - const blob = { - uri: 'file://nested.png', - type: 'image/png', - name: 'nested.png' - }; - - toFormData({ nested: { file: blob } }, formData); - - assert.strictEqual(formData.calls.length, 1); - assert.strictEqual(formData.calls[0][0], 'nested[file]'); - assert.strictEqual(formData.calls[0][1], blob); - }); - - it('should append deeply nested React Native blob without recursion', function () { - const formData = createRNFormDataSpy(); - - const blob = { - uri: 'file://deep.png', - name: 'deep.png' - }; - - toFormData({ a: { b: { c: blob } } }, formData); - - assert.strictEqual(formData.calls.length, 1); - assert.strictEqual(formData.calls[0][0], 'a[b][c]'); - assert.strictEqual(formData.calls[0][1], blob); - }); - - it('should NOT recurse into React Native blob properties', function () { - const formData = createRNFormDataSpy(); - - const blob = { - uri: 'file://nope.png', - type: 'image/png', - name: 'nope.png' - }; - - toFormData({ file: blob }, formData); - - const keys = formData.calls.map(call => call[0]); - - assert.deepStrictEqual(keys, ['file']); - assert.ok(!keys.some(k => k.includes('uri'))); - assert.ok(!keys.some(k => k.includes('type'))); - assert.ok(!keys.some(k => k.includes('name'))); - }); -}); diff --git a/test/unit/platform/index.js b/test/unit/platform/index.js deleted file mode 100644 index 6a5d9c3c..00000000 --- a/test/unit/platform/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-env mocha */ -import platform from '../../../lib/platform/index.js'; -import assert from 'assert'; - -describe('generateString', function () { - it('should generate a string of the specified length using the default alphabet', function () { - const size = 10; - const str = platform.generateString(size); - - assert.strictEqual(str.length, size); - }); - - it('should generate a string using only characters from the default alphabet', function () { - const size = 10; - const alphabet = platform.ALPHABET.ALPHA_DIGIT; - - const str = platform.generateString(size, alphabet); - - for (let char of str) { - assert.ok(alphabet.includes(char), `Character ${char} is not in the alphabet`); - } - }); -}); diff --git a/test/unit/regression/SNYK-JS-AXIOS-1038255.js b/test/unit/regression/SNYK-JS-AXIOS-1038255.js deleted file mode 100644 index c07a1e7f..00000000 --- a/test/unit/regression/SNYK-JS-AXIOS-1038255.js +++ /dev/null @@ -1,75 +0,0 @@ -/* eslint-env mocha */ -// https://snyk.io/vuln/SNYK-JS-AXIOS-1038255 -// https://github.com/axios/axios/issues/3407 -// https://github.com/axios/axios/issues/3369 - -import axios from '../../../index.js'; -import http from 'http'; -import assert from 'assert'; - -const PROXY_PORT = 4777; -const EVIL_PORT = 4666; - -describe('Server-Side Request Forgery (SSRF)', () => { - let fail = false; - let proxy; - let server; - let location; - beforeEach(() => { - server = http - .createServer(function (req, res) { - fail = true; - res.end('rm -rf /'); - }) - .listen(EVIL_PORT); - - proxy = http - .createServer(function (req, res) { - if ( - new URL(req.url, 'http://' + req.headers.host).toString() === - 'http://localhost:' + EVIL_PORT + '/' - ) { - return res.end( - JSON.stringify({ - msg: 'Protected', - headers: req.headers, - }) - ); - } - res.writeHead(302, { location }); - res.end(); - }) - .listen(PROXY_PORT); - }); - afterEach(() => { - server.close(); - proxy.close(); - }); - - it('obeys proxy settings when following redirects', async () => { - location = 'http://localhost:' + EVIL_PORT; - - let response = await axios({ - method: 'get', - url: 'http://www.google.com/', - proxy: { - host: 'localhost', - port: PROXY_PORT, - auth: { - username: 'sam', - password: 'password', - }, - }, - }); - - assert.strictEqual(fail, false); - assert.strictEqual(response.data.msg, 'Protected'); - assert.strictEqual(response.data.headers.host, 'localhost:' + EVIL_PORT); - assert.strictEqual( - response.data.headers['proxy-authorization'], - 'Basic ' + Buffer.from('sam:password').toString('base64') - ); - - return response; - }); -}); diff --git a/test/unit/regression/SNYK-JS-AXIOS-7361793.js b/test/unit/regression/SNYK-JS-AXIOS-7361793.js deleted file mode 100644 index 1af7a94e..00000000 --- a/test/unit/regression/SNYK-JS-AXIOS-7361793.js +++ /dev/null @@ -1,88 +0,0 @@ -/* eslint-env mocha */ -// https://security.snyk.io/vuln/SNYK-JS-AXIOS-7361793 -// https://github.com/axios/axios/issues/6463 - -import axios from '../../../index.js'; -import http from 'http'; -import assert from 'assert'; -import platform from '../../../lib/platform/index.js'; - -const GOOD_PORT = 4666; -const BAD_PORT = 4667; - -describe('Server-Side Request Forgery (SSRF)', () => { - let goodServer, badServer; - - beforeEach(() => { - goodServer = http - .createServer(function (req, res) { - res.write('good'); - res.end(); - }) - .listen(GOOD_PORT); - badServer = http - .createServer(function (req, res) { - res.write('bad'); - res.end(); - }) - .listen(BAD_PORT); - }); - - afterEach(() => { - goodServer.close(); - badServer.close(); - }); - - it('should not fetch in server-side mode', async () => { - const ssrfAxios = axios.create({ - baseURL: 'http://localhost:' + String(GOOD_PORT), - }); - - // Good payload would be `userId = '12345'` - // Malicious payload is as below. - const userId = '/localhost:' + String(BAD_PORT); - - try { - await ssrfAxios.get(`/${userId}`); - } catch (error) { - assert.ok(error.message.startsWith('Invalid URL')); - return; - } - assert.fail('Expected an error to be thrown'); - }); - - describe('should fetch in client-side mode', () => { - let hasBrowserEnv, origin; - - before(() => { - assert.ok(platform.hasBrowserEnv !== undefined); - hasBrowserEnv = platform.hasBrowserEnv; - origin = platform.origin; - platform.hasBrowserEnv = true; - platform.origin = 'http://localhost:' + String(GOOD_PORT); - }); - after(() => { - platform.hasBrowserEnv = hasBrowserEnv; - platform.origin = origin; - }); - it('should fetch in client-side mode', async () => { - platform.hasBrowserEnv = true; - const ssrfAxios = axios.create({ - baseURL: 'http://localhost:' + String(GOOD_PORT), - }); - - // Good payload would be `userId = '12345'` - // Malicious payload is as below. - const userId = '/localhost:' + String(BAD_PORT); - - const response = await ssrfAxios.get(`/${userId}`); - assert.strictEqual(response.data, 'bad'); - assert.strictEqual(response.config.baseURL, 'http://localhost:' + String(GOOD_PORT)); - assert.strictEqual(response.config.url, '//localhost:' + String(BAD_PORT)); - assert.strictEqual( - response.request.res.responseUrl, - 'http://localhost:' + String(BAD_PORT) + '/' - ); - }); - }); -}); diff --git a/test/unit/regression/bugs.js b/test/unit/regression/bugs.js deleted file mode 100644 index 4e709ab6..00000000 --- a/test/unit/regression/bugs.js +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import http from 'http'; -import axios from '../../../index.js'; - -describe('issues', function () { - describe('4999', function () { - it('should not fail with query parsing', async function () { - const { data } = await axios.get('https://postman-echo.com/get?foo1=bar1&foo2=bar2'); - - assert.strictEqual(data.args.foo1, 'bar1'); - assert.strictEqual(data.args.foo2, 'bar2'); - }); - }); - - describe('5028', function () { - it('should handle set-cookie headers as an array', async function () { - const cookie1 = - 'something=else; path=/; expires=Wed, 12 Apr 2023 12:03:42 GMT; samesite=lax; secure; httponly'; - const cookie2 = - 'something-ssr.sig=n4MlwVAaxQAxhbdJO5XbUpDw-lA; path=/; expires=Wed, 12 Apr 2023 12:03:42 GMT; samesite=lax; secure; httponly'; - - const server = http - .createServer((req, res) => { - //res.setHeader('Set-Cookie', 'my=value'); - res.setHeader('Set-Cookie', [cookie1, cookie2]); - res.writeHead(200); - res.write('Hi there'); - res.end(); - }) - .listen(0); - - const request = axios.create(); - - request.interceptors.response.use((res) => { - assert.deepStrictEqual(res.headers['set-cookie'], [cookie1, cookie2]); - }); - - try { - await request({ url: `http://localhost:${server.address().port}` }); - } finally { - server.close(); - } - }); - }); - - describe('7364', function () { - it('fetch: should have status code in axios error', async function () { - const isFetchSupported = typeof fetch === 'function'; - if (!isFetchSupported) { - this.skip(); - } - - const server = http - .createServer((req, res) => { - res.statusCode = 400; - res.end(); - }) - .listen(0); - - const instance = axios.create({ - baseURL: `http://localhost:${server.address().port}`, - adapter: 'fetch', - }); - - try { - await instance.get('/status/400'); - } catch (error) { - assert.equal(error.name, 'AxiosError'); - assert.equal(error.isAxiosError, true); - assert.equal(error.status, 400); - } finally { - server.close(); - } - }); - - it('http: should have status code in axios error', async function () { - const server = http - .createServer((req, res) => { - res.statusCode = 400; - res.end(); - }) - .listen(0); - - const instance = axios.create({ - baseURL: `http://localhost:${server.address().port}`, - adapter: 'http', - }); - - try { - await instance.get('/status/400'); - } catch (error) { - assert.equal(error.name, 'AxiosError'); - assert.equal(error.isAxiosError, true); - assert.equal(error.status, 400); - } finally { - server.close(); - } - }); - }); -}); diff --git a/test/unit/utils/utils.js b/test/unit/utils/utils.js deleted file mode 100644 index f0a89801..00000000 --- a/test/unit/utils/utils.js +++ /dev/null @@ -1,177 +0,0 @@ -/* eslint-env mocha */ -import assert from 'assert'; -import utils from '../../../lib/utils.js'; -import FormData from 'form-data'; -import stream from 'stream'; - -describe('utils', function () { - it('should validate Stream', function () { - assert.strictEqual(utils.isStream(new stream.Readable()), true); - assert.strictEqual(utils.isStream({ foo: 'bar' }), false); - }); - - it('should validate Buffer', function () { - assert.strictEqual(utils.isBuffer(Buffer.from('a')), true); - assert.strictEqual(utils.isBuffer(null), false); - assert.strictEqual(utils.isBuffer(undefined), false); - }); - - describe('utils::isFormData', function () { - it('should detect the FormData instance provided by the `form-data` package', function () { - [1, 'str', {}, new RegExp()].forEach(function (thing) { - assert.equal(utils.isFormData(thing), false); - }); - assert.equal(utils.isFormData(new FormData()), true); - }); - - it('should not call toString method on built-in objects instances', () => { - const buf = Buffer.from('123'); - - buf.toString = () => assert.fail('should not be called'); - - assert.equal(utils.isFormData(buf), false); - }); - - it('should not call toString method on built-in objects instances, even if append method exists', () => { - const buf = Buffer.from('123'); - - buf.append = () => {}; - - buf.toString = () => assert.fail('should not be called'); - - assert.equal(utils.isFormData(buf), false); - }); - - it('should detect custom FormData instances by toStringTag signature and append method presence', () => { - class FormData { - append() {} - - get [Symbol.toStringTag]() { - return 'FormData'; - } - } - assert.equal(utils.isFormData(new FormData()), true); - }); - }); - - describe('toJSON', function () { - it('should convert to a plain object without circular references', function () { - const obj = { a: [0] }; - const source = { x: 1, y: 2, obj }; - source.circular1 = source; - obj.a[1] = obj; - - assert.deepStrictEqual(utils.toJSONObject(source), { - x: 1, - y: 2, - obj: { a: [0] }, - }); - }); - - it('should use objects with defined toJSON method without rebuilding', function () { - const objProp = {}; - const obj = { - objProp, - toJSON() { - return { ok: 1 }; - }, - }; - const source = { x: 1, y: 2, obj }; - - const jsonObject = utils.toJSONObject(source); - - assert.strictEqual(jsonObject.obj.objProp, objProp); - assert.strictEqual( - JSON.stringify(jsonObject), - JSON.stringify({ x: 1, y: 2, obj: { ok: 1 } }) - ); - }); - }); - - describe('Buffer RangeError Fix', function () { - it('should handle large Buffer in isEmptyObject without RangeError', function () { - // Create a big buffer that used to cause the error - const largeBuffer = Buffer.alloc(1024 * 1024 * 200); // 200MB - - // This used to throw: RangeError: Invalid array length - // Now it should work fine - const result = utils.isEmptyObject(largeBuffer); - - // Buffer should not be considered an empty object - assert.strictEqual(result, false); - }); - - it('should handle large Buffer in forEach without RangeError', function () { - const largeBuffer = Buffer.alloc(1024 * 1024 * 200); // 200MB - let count = 0; - - // This should skip the buffer (not iterate through it) - utils.forEach(largeBuffer, () => count++); - - // Count should be 0 because forEach skips Buffers - assert.strictEqual(count, 0); - }); - - it('should handle large Buffer in findKey without RangeError', function () { - const largeBuffer = Buffer.alloc(1024 * 1024 * 200); // 200MB - - // Should return null for Buffers - const result = utils.findKey(largeBuffer, 'test'); - - assert.strictEqual(result, null); - }); - }); - - describe('utils::isReactNativeBlob', function () { - it('should return true for objects with uri property', function () { - assert.strictEqual(utils.isReactNativeBlob({ uri: 'file://path/to/file' }), true); - assert.strictEqual(utils.isReactNativeBlob({ uri: 'content://media/image' }), true); - }); - - it('should return true for React Native blob-like objects with optional name and type', function () { - assert.strictEqual(utils.isReactNativeBlob({ - uri: 'file://path/to/file', - name: 'image.png', - type: 'image/png' - }), true); - }); - - it('should return false for objects without uri property', function () { - assert.strictEqual(utils.isReactNativeBlob({ path: 'file://path' }), false); - assert.strictEqual(utils.isReactNativeBlob({ url: 'http://example.com' }), false); - assert.strictEqual(utils.isReactNativeBlob({}), false); - }); - - it('should return false for non-objects', function () { - assert.strictEqual(utils.isReactNativeBlob(null), false); - assert.strictEqual(utils.isReactNativeBlob(undefined), false); - assert.strictEqual(utils.isReactNativeBlob('string'), false); - assert.strictEqual(utils.isReactNativeBlob(123), false); - assert.strictEqual(utils.isReactNativeBlob(false), false); - }); - - it('should return true even if uri is empty string', function () { - assert.strictEqual(utils.isReactNativeBlob({ uri: '' }), true); - }); - }); - - describe('utils::isReactNative', function () { - it('should return true for FormData with getParts method', function () { - const mockReactNativeFormData = { - append: function() {}, - getParts: function() { return []; } - }; - assert.strictEqual(utils.isReactNative(mockReactNativeFormData), true); - }); - - it('should return false for standard FormData without getParts method', function () { - const standardFormData = new FormData(); - assert.strictEqual(utils.isReactNative(standardFormData), false); - }); - - it('should return false for objects without getParts method', function () { - assert.strictEqual(utils.isReactNative({ append: function() {} }), false); - assert.strictEqual(utils.isReactNative({}), false); - }); - }); -}); diff --git a/test/module/typings/cjs/index.ts b/tests/module/cjs/tests/helpers/cjs-typing.ts similarity index 99% rename from test/module/typings/cjs/index.ts rename to tests/module/cjs/tests/helpers/cjs-typing.ts index e4ee57f9..46509f57 100644 --- a/test/module/typings/cjs/index.ts +++ b/tests/module/cjs/tests/helpers/cjs-typing.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import axios = require('axios'); const config: axios.AxiosRequestConfig = { diff --git a/test/module/ts-require-default/index.ts b/tests/module/cjs/tests/helpers/ts-require-default.ts similarity index 98% rename from test/module/ts-require-default/index.ts rename to tests/module/cjs/tests/helpers/ts-require-default.ts index fe3a19d7..676ac6c7 100644 --- a/test/module/ts-require-default/index.ts +++ b/tests/module/cjs/tests/helpers/ts-require-default.ts @@ -1,3 +1,4 @@ +// @ts-nocheck const assert = require('assert'); const axios = require('axios').default; const { diff --git a/test/module/ts-require/index.ts b/tests/module/cjs/tests/helpers/ts-require.ts similarity index 98% rename from test/module/ts-require/index.ts rename to tests/module/cjs/tests/helpers/ts-require.ts index 097b6f41..50af7c33 100644 --- a/test/module/ts-require/index.ts +++ b/tests/module/cjs/tests/helpers/ts-require.ts @@ -1,3 +1,4 @@ +// @ts-nocheck const assert = require('assert'); const axios = require('axios'); const { diff --git a/tests/module/cjs/tests/ts-require-default.module.test.cjs b/tests/module/cjs/tests/ts-require-default.module.test.cjs index 1acea2cd..ca72d38c 100644 --- a/tests/module/cjs/tests/ts-require-default.module.test.cjs +++ b/tests/module/cjs/tests/ts-require-default.module.test.cjs @@ -20,7 +20,7 @@ const tsconfig = { describe('module ts-require-default compatibility', () => { it('compiles and executes require("axios").default imports', () => { - const sourcePath = path.join(repoRoot, 'test/module/ts-require-default/index.ts'); + const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/ts-require-default.ts'); const fixturePath = createTempFixture(suiteRoot, 'ts-require-default', sourcePath, tsconfig); try { diff --git a/tests/module/cjs/tests/ts-require.module.test.cjs b/tests/module/cjs/tests/ts-require.module.test.cjs index 1183a5b6..d1e3eec0 100644 --- a/tests/module/cjs/tests/ts-require.module.test.cjs +++ b/tests/module/cjs/tests/ts-require.module.test.cjs @@ -20,7 +20,7 @@ const tsconfig = { describe('module ts-require compatibility', () => { it('compiles and executes require("axios") imports', () => { - const sourcePath = path.join(repoRoot, 'test/module/ts-require/index.ts'); + const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/ts-require.ts'); const fixturePath = createTempFixture(suiteRoot, 'ts-require', sourcePath, tsconfig); try { diff --git a/tests/module/cjs/tests/typings.module.test.cjs b/tests/module/cjs/tests/typings.module.test.cjs index 98664670..b9936d78 100644 --- a/tests/module/cjs/tests/typings.module.test.cjs +++ b/tests/module/cjs/tests/typings.module.test.cjs @@ -16,7 +16,7 @@ const tsconfig = { describe('module cjs typings compatibility', () => { it('type-checks commonjs axios typings', () => { - const sourcePath = path.join(repoRoot, 'test/module/typings/cjs/index.ts'); + const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/cjs-typing.ts'); const fixturePath = createTempFixture(suiteRoot, 'typings-cjs', sourcePath, tsconfig); try { diff --git a/test/module/ts/index.ts b/tests/module/esm/tests/helpers/esm-functions.ts similarity index 98% rename from test/module/ts/index.ts rename to tests/module/esm/tests/helpers/esm-functions.ts index 57dc9cd1..b521566d 100644 --- a/test/module/ts/index.ts +++ b/tests/module/esm/tests/helpers/esm-functions.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import assert from 'assert'; import axios, { CanceledError, diff --git a/test/module/typings/esm/index.ts b/tests/module/esm/tests/helpers/esm-index.ts similarity index 99% rename from test/module/typings/esm/index.ts rename to tests/module/esm/tests/helpers/esm-index.ts index fd59a10b..ba38a8aa 100644 --- a/test/module/typings/esm/index.ts +++ b/tests/module/esm/tests/helpers/esm-index.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import axios, { AxiosRequestConfig, AxiosHeaders, diff --git a/tests/module/esm/tests/ts.module.test.js b/tests/module/esm/tests/ts.module.test.js index 1c1c7935..8639986c 100644 --- a/tests/module/esm/tests/ts.module.test.js +++ b/tests/module/esm/tests/ts.module.test.js @@ -21,7 +21,7 @@ const tsconfig = { describe('module ts compatibility', () => { it('compiles and executes import axios syntax', () => { - const sourcePath = path.join(repoRoot, 'test/module/ts/index.ts'); + const sourcePath = path.join(repoRoot, 'tests/module/esm/tests/helpers/esm-functions.ts'); const fixturePath = createTempFixture(suiteRoot, 'ts', sourcePath, tsconfig, { type: 'commonjs', }); diff --git a/tests/module/esm/tests/typings.module.test.js b/tests/module/esm/tests/typings.module.test.js index 8f8c1f4d..84a2a060 100644 --- a/tests/module/esm/tests/typings.module.test.js +++ b/tests/module/esm/tests/typings.module.test.js @@ -17,7 +17,7 @@ const tsconfig = { describe('module esm typings compatibility', () => { it('type-checks esm axios typings', () => { - const sourcePath = path.join(repoRoot, 'test/module/typings/esm/index.ts'); + const sourcePath = path.join(repoRoot, 'tests/module/esm/tests/helpers/esm-index.ts'); const fixturePath = createTempFixture(suiteRoot, 'typings-esm', sourcePath, tsconfig, { type: 'module', });