mirror of
https://github.com/tenrok/axios.git
synced 2026-06-23 20:40:40 +03:00
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
This commit is contained in:
@@ -6,7 +6,7 @@ on:
|
|||||||
types:
|
types:
|
||||||
- webhook
|
- webhook
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 1 * * *"
|
- cron: '0 1 * * *'
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
run: npm ci
|
run: npm ci
|
||||||
- name: Check if sponsors require updates
|
- name: Check if sponsors require updates
|
||||||
id: sponsors-requires-update
|
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
|
- name: Check tracked README sponsor diff
|
||||||
id: readme-tracked-change
|
id: readme-tracked-change
|
||||||
run: |
|
run: |
|
||||||
@@ -58,8 +58,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
branch: sponsors
|
branch: sponsors
|
||||||
delete-branch: true
|
delete-branch: true
|
||||||
commit-message: "chore(sponsor): update sponsor block"
|
commit-message: 'chore(sponsor): update sponsor block'
|
||||||
title: "chore(docs): update sponsor block"
|
title: 'chore(docs): update sponsor block'
|
||||||
body: |
|
body: |
|
||||||
**New sponsor block update:**
|
**New sponsor block update:**
|
||||||
${{ env.CONTENT }}
|
${{ env.CONTENT }}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
-134
@@ -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;
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import GithubAPI from './GithubAPI.js';
|
|
||||||
|
|
||||||
export default new GithubAPI('axios', 'axios');
|
|
||||||
@@ -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');
|
|
||||||
@@ -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 };
|
|
||||||
@@ -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('');
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
@@ -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)
|
|
||||||
);
|
|
||||||
@@ -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) : '<unknown>'
|
|
||||||
);
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
-40
@@ -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/);
|
|
||||||
};
|
|
||||||
@@ -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`);
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import gulp from 'gulp';
|
import gulp from 'gulp';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import axios from './bin/githubAxios.js';
|
import axios from './scripts/axios-build-instance.js';
|
||||||
import minimist from 'minimist';
|
import minimist from 'minimist';
|
||||||
|
|
||||||
const argv = minimist(process.argv.slice(2));
|
const argv = minimist(process.argv.slice(2));
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import axios from '../index.js';
|
import axios from '../index.js';
|
||||||
import { colorize } from './helpers/colorize.js';
|
|
||||||
|
|
||||||
const { GITHUB_TOKEN } = process.env;
|
const { GITHUB_TOKEN } = process.env;
|
||||||
|
|
||||||
@@ -12,8 +11,9 @@ export default axios.create({
|
|||||||
defaultTransform[0],
|
defaultTransform[0],
|
||||||
function (data) {
|
function (data) {
|
||||||
console.log(
|
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;
|
return data;
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import _axios from '../../index.js';
|
import _axios from '../index.js';
|
||||||
|
|
||||||
const axios = _axios.create({
|
const axios = _axios.create({
|
||||||
headers: {
|
headers: {
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{{#if authors}}
|
|
||||||
### Contributors to this release
|
|
||||||
|
|
||||||
{{#each authors}}
|
|
||||||
{{#unless isBot}}
|
|
||||||
{{#if login}}
|
|
||||||
- {{#if avatar_url}}<img src="{{avatar_url_sm}}" alt="avatar" width="18"/>{{/if}} [{{displayName}}]({{html_url}} "+{{insertions}}/-{{deletions}} ({{#each prs}}#{{this}} {{/each}})")
|
|
||||||
{{else}}
|
|
||||||
- {{displayName}}
|
|
||||||
{{/if}}
|
|
||||||
{{/unless}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
@@ -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}}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Hi, @{{ author.login }}! This PR has been published in [{{ release.tag }}]({{ release.url }}) release. Thank you for your contribution ❤️!
|
|
||||||
@@ -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}}
|
|
||||||
@@ -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);
|
|
||||||
};
|
|
||||||
@@ -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 }
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
An alert should be shown with the <code>{"name":"axios"}</code>
|
|
||||||
|
|
||||||
<script src="promise.js"></script>
|
|
||||||
<script src="../../dist/axios.js"></script>
|
|
||||||
<script>
|
|
||||||
axios.get('./fixture.json').then(function (response) {
|
|
||||||
console.log(response);
|
|
||||||
alert(JSON.stringify(response.data));
|
|
||||||
alert('response headers:\n\n' + JSON.stringify(response.headers));
|
|
||||||
}, function (err) { console.log(err) });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
An alert should be shown with <code>{"status":"ok"}</code>
|
|
||||||
|
|
||||||
<script src="promise.js"></script>
|
|
||||||
<script src="../../dist/axios.js"></script>
|
|
||||||
<script>
|
|
||||||
axios.get('http://cors-test.appspot.com/test').then(function (response) {
|
|
||||||
alert(JSON.stringify(response.data));
|
|
||||||
alert('response headers:\n\n' + JSON.stringify(response.headers));
|
|
||||||
}, function (err) { console.log(err) });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "axios"
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
See your console
|
|
||||||
<script src="../../dist/axios.js"></script>
|
|
||||||
<script>
|
|
||||||
const data = new Int8Array(10 * 1024 * 1024);
|
|
||||||
|
|
||||||
data.fill(123);
|
|
||||||
|
|
||||||
console.log('Starting...');
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
await axios.post('http://httpbin.org/post', data, {
|
|
||||||
adapter: 'xhr',
|
|
||||||
onUploadProgress: (e) => console.log('xhr upload', e),
|
|
||||||
onDownloadProgress: (e) => console.log('xhr download', e),
|
|
||||||
}).then(data => {
|
|
||||||
console.log(`Done: `, data);
|
|
||||||
}).catch(e => console.warn('xhr', e));
|
|
||||||
|
|
||||||
await axios.post('https://httpbin.org/post', data, {
|
|
||||||
adapter: 'fetch',
|
|
||||||
onUploadProgress: (e) => console.log('fetch upload', e),
|
|
||||||
onDownloadProgress: (e) => console.log('fetch download', e)
|
|
||||||
}).then(data => {
|
|
||||||
console.log(`Done: `, data);
|
|
||||||
}).catch(e => console.warn('fetch', e));
|
|
||||||
})();
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,11 +0,0 @@
|
|||||||
const axios = require('axios');
|
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const { CanceledError, AxiosError, AxiosHeaders } = axios;
|
|
||||||
|
|
||||||
assert.strictEqual(typeof axios, 'function');
|
|
||||||
assert.strictEqual(typeof CanceledError, 'function');
|
|
||||||
assert.strictEqual(typeof AxiosError, 'function');
|
|
||||||
assert.strictEqual(typeof AxiosHeaders, 'function');
|
|
||||||
|
|
||||||
console.log('CommonJS importing test passed');
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "cjs-entrypoint-test",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "npm i --no-save --no-package-lock && node index.js"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "file:../../.."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import assert from 'assert';
|
|
||||||
import axios, { CanceledError, AxiosError, AxiosHeaders } from 'axios';
|
|
||||||
import settle from 'axios/unsafe/core/settle.js';
|
|
||||||
|
|
||||||
assert.strictEqual(typeof axios, 'function');
|
|
||||||
assert.strictEqual(typeof CanceledError, 'function');
|
|
||||||
assert.strictEqual(typeof AxiosError, 'function');
|
|
||||||
assert.strictEqual(typeof AxiosHeaders, 'function');
|
|
||||||
|
|
||||||
assert.strictEqual(axios.CanceledError, CanceledError);
|
|
||||||
assert.strictEqual(axios.AxiosError, AxiosError);
|
|
||||||
assert.strictEqual(axios.AxiosHeaders, AxiosHeaders);
|
|
||||||
|
|
||||||
assert.strictEqual(typeof settle, 'function');
|
|
||||||
|
|
||||||
console.log('ESM importing test passed');
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "esm-entrypoint-test",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"test": "npm i --no-save --no-package-lock && node index.js"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "file:../../.."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
import assert from 'assert';
|
|
||||||
import * as axios from '../../index.js';
|
|
||||||
import axiosFactory from '../../lib/axios.js';
|
|
||||||
import utils from '../../lib/utils.js';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import path from 'path';
|
|
||||||
import util from 'util';
|
|
||||||
import cp from 'child_process';
|
|
||||||
import fs from 'fs-extra';
|
|
||||||
|
|
||||||
const BACKUP_PATH = './backup/';
|
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
const exec = util.promisify(cp.exec);
|
|
||||||
|
|
||||||
const spawn = (command, args) =>
|
|
||||||
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',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 '<reference>'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. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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');
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 '<reference>'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. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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');
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 '<reference>'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. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"checkJs": true,
|
|
||||||
"module": "node16"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"checkJs": true,
|
|
||||||
"module": "node16"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
})();
|
|
||||||
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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.');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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/');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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:');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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"}',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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 });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -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-----
|
|
||||||
@@ -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));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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-----
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user