mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
test(core): add admin-user route UT (#252)
* test(core): add admin-user route ut add admin-user route ut * fix(ut): remove redundent code remove mockKoaAuthMiddleware * feat(core): update pnpm.lock update pnpm.lock
This commit is contained in:
parent
47ccb4da02
commit
8fa169cba1
6 changed files with 283 additions and 34 deletions
|
@ -59,6 +59,7 @@
|
|||
"@types/lodash.pick": "^4.4.6",
|
||||
"@types/node": "^16.3.1",
|
||||
"@types/oidc-provider": "^7.8.0",
|
||||
"@types/supertest": "^2.0.11",
|
||||
"codecov": "^3.8.3",
|
||||
"eslint": "^8.1.0",
|
||||
"jest": "^27.0.6",
|
||||
|
@ -67,6 +68,7 @@
|
|||
"nock": "^13.2.2",
|
||||
"openapi-types": "^9.1.0",
|
||||
"prettier": "^2.3.2",
|
||||
"supertest": "^6.2.2",
|
||||
"ts-jest": "^27.0.5",
|
||||
"tsc-watch": "^4.4.0",
|
||||
"typescript": "^4.5.5"
|
||||
|
|
|
@ -1,29 +1,11 @@
|
|||
import { User, userInfoSelectFields } from '@logto/schemas';
|
||||
import pick from 'lodash.pick';
|
||||
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import * as userQueries from '@/queries/user';
|
||||
import { createContextWithRouteParameters } from '@/utils/test-utils';
|
||||
import { mockUser, mockUserResponse, createContextWithRouteParameters } from '@/utils/test-utils';
|
||||
|
||||
import koaUserInfo from './koa-user-info';
|
||||
|
||||
const findUserByIdSpy = jest.spyOn(userQueries, 'findUserById');
|
||||
|
||||
const mockUser: User = {
|
||||
id: 'foo',
|
||||
username: 'foo',
|
||||
primaryEmail: 'foo@logto.io',
|
||||
primaryPhone: '111111',
|
||||
roleNames: ['admin'],
|
||||
passwordEncrypted: null,
|
||||
passwordEncryptionMethod: null,
|
||||
passwordEncryptionSalt: null,
|
||||
name: null,
|
||||
avatar: null,
|
||||
identities: {},
|
||||
customData: {},
|
||||
};
|
||||
|
||||
describe('koaUserInfo middleware', () => {
|
||||
const next = jest.fn();
|
||||
|
||||
|
@ -38,7 +20,7 @@ describe('koaUserInfo middleware', () => {
|
|||
|
||||
await koaUserInfo()(ctx, next);
|
||||
|
||||
expect(ctx.userInfo).toEqual(pick(mockUser, ...userInfoSelectFields));
|
||||
expect(ctx.userInfo).toEqual(mockUserResponse);
|
||||
});
|
||||
|
||||
it('should throw if is not authenticated', async () => {
|
||||
|
|
162
packages/core/src/routes/admin-user.test.ts
Normal file
162
packages/core/src/routes/admin-user.test.ts
Normal file
|
@ -0,0 +1,162 @@
|
|||
import { CreateUser, User } from '@logto/schemas';
|
||||
import Koa from 'koa';
|
||||
import Router from 'koa-router';
|
||||
import request from 'supertest';
|
||||
|
||||
import { hasUser, findUserById } from '@/queries/user';
|
||||
import { mockUser, mockUserResponse } from '@/utils/test-utils';
|
||||
|
||||
import adminUserRoutes from './admin-user';
|
||||
import { AuthedRouter } from './types';
|
||||
|
||||
jest.mock('@/queries/user', () => ({
|
||||
findTotalNumberOfUsers: jest.fn(async () => ({ count: 10 })),
|
||||
findAllUsers: jest.fn(async (): Promise<User[]> => [mockUser]),
|
||||
findUserById: jest.fn(async (): Promise<User> => mockUser),
|
||||
hasUser: jest.fn(async () => false),
|
||||
updateUserById: jest.fn(
|
||||
async (_, data: Partial<CreateUser>): Promise<User> => ({
|
||||
...mockUser,
|
||||
...data,
|
||||
})
|
||||
),
|
||||
insertUser: jest.fn(
|
||||
async (user: CreateUser): Promise<User> => ({
|
||||
...mockUser,
|
||||
...user,
|
||||
})
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('@/lib/user', () => ({
|
||||
generateUserId: jest.fn(() => 'fooId'),
|
||||
encryptUserPassword: jest.fn(() => ({
|
||||
passwordEncryptionSalt: 'salt',
|
||||
passwordEncrypted: 'password',
|
||||
passwordEncryptionMethod: 'saltAndPepper',
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('adminUserRoutes', () => {
|
||||
const app = new Koa();
|
||||
const router: AuthedRouter = new Router();
|
||||
|
||||
adminUserRoutes(router);
|
||||
app.use(router.routes()).use(router.allowedMethods());
|
||||
|
||||
const userRequest = request(app.callback());
|
||||
|
||||
it('GET /users', async () => {
|
||||
const response = await userRequest.get('/users');
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.body).toEqual([mockUserResponse]);
|
||||
});
|
||||
|
||||
it('GET /users/:userId', async () => {
|
||||
const response = await userRequest.get('/users/foo');
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.body).toEqual(mockUserResponse);
|
||||
});
|
||||
|
||||
it('POST /users', async () => {
|
||||
const username = 'MJ@logto.io';
|
||||
const password = 'PASSWORD';
|
||||
const name = 'Micheal';
|
||||
|
||||
const response = await userRequest.post('/users').send({ username, password, name });
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.body).toEqual({
|
||||
...mockUserResponse,
|
||||
id: 'fooId',
|
||||
username,
|
||||
name,
|
||||
});
|
||||
});
|
||||
|
||||
it('POST /users should throw with invalid input params', async () => {
|
||||
const username = 'MJ@logto.io';
|
||||
const password = 'PASSWORD';
|
||||
const name = 'Micheal';
|
||||
|
||||
// Missing input
|
||||
await expect(userRequest.post('/users').send({})).resolves.toHaveProperty('status', 400);
|
||||
await expect(userRequest.post('/users').send({ username, password })).resolves.toHaveProperty(
|
||||
'status',
|
||||
400
|
||||
);
|
||||
await expect(userRequest.post('/users').send({ username, name })).resolves.toHaveProperty(
|
||||
'status',
|
||||
400
|
||||
);
|
||||
await expect(userRequest.post('/users').send({ password, name })).resolves.toHaveProperty(
|
||||
'status',
|
||||
400
|
||||
);
|
||||
|
||||
// Invalid input format
|
||||
await expect(
|
||||
userRequest.post('/users').send({ username: 'xy', password, name })
|
||||
).resolves.toHaveProperty('status', 400);
|
||||
await expect(
|
||||
userRequest.post('/users').send({ username, password: 'abc', name })
|
||||
).resolves.toHaveProperty('status', 400);
|
||||
await expect(
|
||||
userRequest.post('/users').send({ username, password, name: 'xy' })
|
||||
).resolves.toHaveProperty('status', 400);
|
||||
});
|
||||
|
||||
it('POST /users should throw if username exist', async () => {
|
||||
const mockHasUser = hasUser as jest.Mock;
|
||||
mockHasUser.mockImplementationOnce(async () => Promise.resolve(true));
|
||||
|
||||
const username = 'MJ@logto.io';
|
||||
const password = 'PASSWORD';
|
||||
const name = 'Micheal';
|
||||
|
||||
await expect(
|
||||
userRequest.post('/users').send({ username, password, name })
|
||||
).resolves.toHaveProperty('status', 422);
|
||||
});
|
||||
|
||||
it('PATCH /users/:userId', async () => {
|
||||
const name = 'Micheal';
|
||||
const avatar = 'http://www.micheal.png';
|
||||
|
||||
const response = await userRequest.patch('/users/foo').send({ name, avatar });
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.body).toEqual({
|
||||
...mockUserResponse,
|
||||
name,
|
||||
avatar,
|
||||
});
|
||||
});
|
||||
|
||||
it('PATCH /users/:userId throw with invalid input params', async () => {
|
||||
const name = 'Micheal';
|
||||
const avatar = 'http://www.micheal.png';
|
||||
|
||||
await expect(userRequest.patch('/users/foo').send({ avatar })).resolves.toHaveProperty(
|
||||
'status',
|
||||
200
|
||||
);
|
||||
|
||||
await expect(
|
||||
userRequest.patch('/users/foo').send({ name, avatar: 'non url' })
|
||||
).resolves.toHaveProperty('status', 400);
|
||||
});
|
||||
|
||||
it('PATCH /users/:userId throw if user not found', async () => {
|
||||
const name = 'Micheal';
|
||||
const avatar = 'http://www.micheal.png';
|
||||
|
||||
const mockFindUserById = findUserById as jest.Mock;
|
||||
mockFindUserById.mockImplementationOnce(() => {
|
||||
throw new Error(' ');
|
||||
});
|
||||
|
||||
await expect(userRequest.patch('/users/foo').send({ name, avatar })).resolves.toHaveProperty(
|
||||
'status',
|
||||
500
|
||||
);
|
||||
});
|
||||
});
|
|
@ -39,6 +39,7 @@ export default function adminUserRoutes<T extends AuthedRouter>(router: T) {
|
|||
|
||||
router.get(
|
||||
'/users/:userId',
|
||||
// TODO: No need to guard
|
||||
koaGuard({
|
||||
params: object({ userId: string() }),
|
||||
}),
|
||||
|
@ -66,7 +67,6 @@ export default function adminUserRoutes<T extends AuthedRouter>(router: T) {
|
|||
}),
|
||||
async (ctx, next) => {
|
||||
const { username, password, name } = ctx.guard.body;
|
||||
|
||||
assertThat(
|
||||
!(await hasUser(username)),
|
||||
new RequestError({
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
import { User, userInfoSelectFields } from '@logto/schemas';
|
||||
import { createMockContext, Options } from '@shopify/jest-koa-mocks';
|
||||
import { MiddlewareType, Context } from 'koa';
|
||||
import Router, { IRouterParamContext } from 'koa-router';
|
||||
import pick from 'lodash.pick';
|
||||
import { createMockPool, createMockQueryResult, QueryResultRowType } from 'slonik';
|
||||
import { PrimitiveValueExpressionType } from 'slonik/dist/src/types.d';
|
||||
|
||||
export const mockUser: User = {
|
||||
id: 'foo',
|
||||
username: 'foo',
|
||||
primaryEmail: 'foo@logto.io',
|
||||
primaryPhone: '111111',
|
||||
roleNames: ['admin'],
|
||||
passwordEncrypted: null,
|
||||
passwordEncryptionMethod: null,
|
||||
passwordEncryptionSalt: null,
|
||||
name: null,
|
||||
avatar: null,
|
||||
identities: {},
|
||||
customData: {},
|
||||
};
|
||||
|
||||
export const mockUserResponse = pick(mockUser, ...userInfoSelectFields);
|
||||
|
||||
export const createTestPool = <T extends QueryResultRowType>(
|
||||
expectSql?: string,
|
||||
returning?: T | ((sql: string, values: readonly PrimitiveValueExpressionType[]) => T)
|
||||
|
@ -25,18 +44,6 @@ export const createTestPool = <T extends QueryResultRowType>(
|
|||
},
|
||||
});
|
||||
|
||||
export const envVariablesSetUp = () => {
|
||||
const OIDC_PROVIDER_PRIVATE_KEY_BASE64 =
|
||||
'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDV2dJQkFBS0JnR3pLendQcVp6Q3dncjR5a0U1NTN2aWw3QTZYM2l1VnJ3TVJtbVJDTVNBL3lkUm04bXA1CjlHZUYyMlRCSVBtUEVNM29Lbnk4KytFL2FDRnByWXVDa0loREhodVR5N1diT25nd3kyb3JpYnNEQm1OS3FybTkKM0xkYWYrZm1aU2tsL0FMUjZNeUhNV2dTUkQrbFhxVnplNFdSRGIzVTlrTyt3RmVXUlNZNmlRL2pBZ01CQUFFQwpnWUJOZkczUjVpUTFJNk1iZ0x3VGlPM3N2NURRSEE3YmtETWt4bWJtdmRacmw4TlRDemZoNnBiUEhTSFVNMUlmCkxXelVtMldYanFzQUZiOCsvUnZrWDh3OHI3SENNUUdLVGs0ay9adkZ5YUhkM2tIUXhjSkJPakNOUUtjS2NZalUKRGdnTUVJeW5PblNZNjJpWEV6RExKVTJEMVUrY3JEbTZXUTVHaG1NS1p2Vnl3UUpCQU1lcFBFV2gwakNDOEdmQwpQQU1yT1JvOHJYeHYwVEdXNlJWYmxad0ppdjhNeGZacnpZT1cwZUFPek9IK0ZRWE90SjNTdUZONzdEcVQ5TDI3CmN2M3QySkVDUVFDTGZZeVl2ZUg0UnY2bnVET0RnckkzRUJHMFNJbURHcC94UUV2NEk5Z0hrRFF0aFF4bW5xNTEKZ1QxajhFN1lmRHEwMTkvN2htL3dmMXNzMERQNkpic3pBa0JqOEUzKy9MVGRHMjJDUWpNUDB2N09KemtmWkVqdAo3WC9WOVBXNkdQeStGWUt4aWR4ZzFZbFFBWmlFTms0SGppUFNLN3VmN2hPY2JwcStyYWt0ZVhSQkFrQmhaaFFECkh5c20wbVBFTnNGNWhZdnRHTUpUOFFaYnpmNTZWUnYyc3dpSUYyL25qT3hneDFJbjZFczJlamlEdnhLNjdiV1AKQ29zbEViaFhMVFh0NStTekFrQjJQOUYzNExubE9tVjh4Zjk1VmVlcXNPbDFmWWx2Uy9vUUx1a2ZxVkJsTmtzNgpzdmNLVDJOQjlzSHlCeE8vY3Zqa0ZpWXdHR2MzNjlmQklkcDU1S2IwCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0t';
|
||||
const UI_SIGN_IN_ROUTE = '/sign-in';
|
||||
|
||||
process.env = {
|
||||
...process.env,
|
||||
OIDC_PROVIDER_PRIVATE_KEY_BASE64,
|
||||
UI_SIGN_IN_ROUTE,
|
||||
};
|
||||
};
|
||||
|
||||
export const emptyMiddleware =
|
||||
<StateT, ContextT>(): MiddlewareType<StateT, ContextT> =>
|
||||
// Intend to mock the async middleware
|
||||
|
|
|
@ -80,6 +80,7 @@ importers:
|
|||
'@types/lodash.pick': ^4.4.6
|
||||
'@types/node': ^16.3.1
|
||||
'@types/oidc-provider': ^7.8.0
|
||||
'@types/supertest': ^2.0.11
|
||||
codecov: ^3.8.3
|
||||
dayjs: ^1.10.5
|
||||
decamelize: ^5.0.0
|
||||
|
@ -111,6 +112,7 @@ importers:
|
|||
slonik: ^23.8.3
|
||||
slonik-interceptor-preset: ^1.2.10
|
||||
snakecase-keys: ^5.1.0
|
||||
supertest: ^6.2.2
|
||||
ts-jest: ^27.0.5
|
||||
tsc-watch: ^4.4.0
|
||||
typescript: ^4.5.5
|
||||
|
@ -156,6 +158,7 @@ importers:
|
|||
'@types/lodash.pick': 4.4.6
|
||||
'@types/node': 16.11.12
|
||||
'@types/oidc-provider': 7.8.1
|
||||
'@types/supertest': 2.0.11
|
||||
codecov: 3.8.3
|
||||
eslint: 8.4.1
|
||||
jest: 27.4.4
|
||||
|
@ -164,6 +167,7 @@ importers:
|
|||
nock: 13.2.2
|
||||
openapi-types: 9.3.1
|
||||
prettier: 2.5.1
|
||||
supertest: 6.2.2
|
||||
ts-jest: 27.1.1_0ef321b3552d50570980838f9f6677eb
|
||||
tsc-watch: 4.5.0_typescript@4.5.5
|
||||
typescript: 4.5.5
|
||||
|
@ -3074,6 +3078,10 @@ packages:
|
|||
resolution: {integrity: sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==}
|
||||
dev: true
|
||||
|
||||
/@types/cookiejar/2.1.2:
|
||||
resolution: {integrity: sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==}
|
||||
dev: true
|
||||
|
||||
/@types/cookies/0.7.7:
|
||||
resolution: {integrity: sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==}
|
||||
dependencies:
|
||||
|
@ -3354,6 +3362,19 @@ packages:
|
|||
resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
|
||||
dev: true
|
||||
|
||||
/@types/superagent/4.1.15:
|
||||
resolution: {integrity: sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==}
|
||||
dependencies:
|
||||
'@types/cookiejar': 2.1.2
|
||||
'@types/node': 16.11.12
|
||||
dev: true
|
||||
|
||||
/@types/supertest/2.0.11:
|
||||
resolution: {integrity: sha512-uci4Esokrw9qGb9bvhhSVEjd6rkny/dk5PK/Qz4yxKiyppEI+dOPlNrZBahE3i+PoKFYyDxChVXZ/ysS/nrm1Q==}
|
||||
dependencies:
|
||||
'@types/superagent': 4.1.15
|
||||
dev: true
|
||||
|
||||
/@types/unist/2.0.6:
|
||||
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
|
||||
dev: true
|
||||
|
@ -4416,6 +4437,10 @@ packages:
|
|||
dot-prop: 5.3.0
|
||||
dev: true
|
||||
|
||||
/component-emitter/1.3.0:
|
||||
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
|
||||
dev: true
|
||||
|
||||
/concat-map/0.0.1:
|
||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||
|
||||
|
@ -4553,6 +4578,10 @@ packages:
|
|||
safe-buffer: 5.1.2
|
||||
dev: true
|
||||
|
||||
/cookiejar/2.1.3:
|
||||
resolution: {integrity: sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==}
|
||||
dev: true
|
||||
|
||||
/cookies/0.8.0:
|
||||
resolution: {integrity: sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
@ -5787,6 +5816,10 @@ packages:
|
|||
boolean: 3.1.4
|
||||
dev: false
|
||||
|
||||
/fast-safe-stringify/2.1.1:
|
||||
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
|
||||
dev: true
|
||||
|
||||
/fast-url-parser/1.1.3:
|
||||
resolution: {integrity: sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=}
|
||||
dependencies:
|
||||
|
@ -5907,11 +5940,29 @@ packages:
|
|||
mime-types: 2.1.34
|
||||
dev: true
|
||||
|
||||
/form-data/4.0.0:
|
||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.34
|
||||
dev: true
|
||||
|
||||
/formidable/1.2.6:
|
||||
resolution: {integrity: sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==}
|
||||
deprecated: 'Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau'
|
||||
dev: false
|
||||
|
||||
/formidable/2.0.1:
|
||||
resolution: {integrity: sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==}
|
||||
dependencies:
|
||||
dezalgo: 1.0.3
|
||||
hexoid: 1.0.0
|
||||
once: 1.4.0
|
||||
qs: 6.9.3
|
||||
dev: true
|
||||
|
||||
/fresh/0.5.2:
|
||||
resolution: {integrity: sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
@ -6313,6 +6364,11 @@ packages:
|
|||
dependencies:
|
||||
function-bind: 1.1.1
|
||||
|
||||
/hexoid/1.0.0:
|
||||
resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/history/4.10.1:
|
||||
resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==}
|
||||
dependencies:
|
||||
|
@ -8196,7 +8252,7 @@ packages:
|
|||
dependencies:
|
||||
universalify: 2.0.0
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.8
|
||||
graceful-fs: 4.2.9
|
||||
dev: true
|
||||
|
||||
/jsonparse/1.3.1:
|
||||
|
@ -8889,6 +8945,12 @@ packages:
|
|||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/mime/2.6.0:
|
||||
resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/mimic-fn/2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -10735,6 +10797,11 @@ packages:
|
|||
engines: {node: '>=0.6'}
|
||||
dev: true
|
||||
|
||||
/qs/6.9.3:
|
||||
resolution: {integrity: sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==}
|
||||
engines: {node: '>=0.6'}
|
||||
dev: true
|
||||
|
||||
/query-string/6.14.1:
|
||||
resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -12027,6 +12094,35 @@ packages:
|
|||
postcss: 7.0.39
|
||||
dev: true
|
||||
|
||||
/superagent/7.1.1:
|
||||
resolution: {integrity: sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ==}
|
||||
engines: {node: '>=6.4.0 <13 || >=14'}
|
||||
dependencies:
|
||||
component-emitter: 1.3.0
|
||||
cookiejar: 2.1.3
|
||||
debug: 4.3.3
|
||||
fast-safe-stringify: 2.1.1
|
||||
form-data: 4.0.0
|
||||
formidable: 2.0.1
|
||||
methods: 1.1.2
|
||||
mime: 2.6.0
|
||||
qs: 6.10.2
|
||||
readable-stream: 3.6.0
|
||||
semver: 7.3.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/supertest/6.2.2:
|
||||
resolution: {integrity: sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dependencies:
|
||||
methods: 1.1.2
|
||||
superagent: 7.1.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/supports-color/5.5.0:
|
||||
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
Loading…
Reference in a new issue