Files
directus/packages/sdk/tests/base/transport.test.ts
José Varela 23f6baa4db SDK: refactor constructors (#9080)
* refactor: more intuitive interfaces

* refactor: simpler refresh
before: on every request we were debouncing a refresh request
after: call refresh only once before now() + 'expires'

* refactor: prefix on base storage

* fixup! refactor: simpler refresh before: on every request we were debouncing a refresh request after: call refresh only once before now() + 'expires'

* refactor: simpler axios transport
before: handle auth headers
after: auth headers are handled on directus instance

* refactor: simpler usage of Directus constructor

* fixup! refactor: simpler refresh before: on every request we were debouncing a refresh request after: call refresh only once before now() + 'expires'

* refactor: fix tests based on previous changes

* refactor: better auth constructor
before: depends on SDK instance
after: depends on Transport and Storage instance

* accept staticToken from auth

* make transport and storage as optional on options

* fix type auth refresh

* simplify transport

* fix test for previous changes

* improve auth class

* revert some IAuth props because tests

* allow to force memory of localstorage on storage

* add tests for previous change

* document everything and simplify some things

* fix override headers on request

* better name typing

* fix private axios

* removed boolean from CLI auth.refresh()

* fix missing url in some examples

* soem grammar updates

Co-authored-by: Jay Cammarano <jay.cammarano@gmail.com>
Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
2021-11-04 13:30:30 -04:00

129 lines
3.8 KiB
TypeScript

/**
* @jest-environment node
*/
import nock from 'nock';
import { Transport } from '../../src/base/transport';
import { TransportResponse, TransportError } from '../../src/transport';
describe('default transport', function () {
const URL = 'http://localhost';
nock.disableNetConnect();
function expectResponse<T>(response: TransportResponse<T>, expected: Partial<TransportResponse<T>>) {
if (expected.status) {
expect(response.status).toBe(expected.status);
}
if (expected.statusText) {
expect(response.statusText).toBe(expected.statusText);
}
if (expected.data) {
expect(response.data).toMatchObject<T | T[]>(expected.data);
}
if (expected.headers) {
expect(response.headers).toMatchObject(expected.headers);
}
}
['get', 'delete', 'head', 'options', 'put', 'post', 'patch'].forEach((method) => {
it(`${method} should return a response object`, async () => {
const route = `/${method}/response`;
(nock(URL) as any)[method](route).reply(200);
const transport = new Transport({ url: URL }) as any;
const response = await transport[method](route);
expectResponse(response, {
status: 200,
});
});
it(`${method} should throw on response errors`, async function () {
const route = `/${method}/500`;
(nock(URL) as any)[method](route).reply(500);
const transport = new Transport({ url: URL }) as any;
try {
await transport[method](route);
fail();
} catch (err: any) {
expect(err).toBeInstanceOf(TransportError);
}
});
it(`${method} should carry response error information`, async function () {
const route = `/${method}/403/error`;
(nock(URL) as any)[method](route).reply(403, {
errors: [
{
message: 'You don\'t have permission access to "contacts" collection.',
extensions: {
code: 'FORBIDDEN',
},
},
],
});
const transport = new Transport({ url: URL }) as any;
try {
await transport[method](route);
fail();
} catch (err: any) {
const terr = err as TransportError;
expect(terr).toBeInstanceOf(TransportError);
expect(terr.response?.status).toBe(403);
expect(terr.message).toBe('You don\'t have permission access to "contacts" collection.');
expect(terr.errors.length).toBe(1);
expect(terr.errors[0]?.message).toBe('You don\'t have permission access to "contacts" collection.');
expect(terr.errors[0]?.extensions?.code).toBe('FORBIDDEN');
}
});
it('get should throw non response errors', async function () {
const route = `/${method}/this/raises/error`;
(nock(URL) as any)[method](route).replyWithError('Random error');
const transport = new Transport({ url: URL }) as any;
try {
await transport[method](route);
fail();
} catch (err: any) {
const terr = err as TransportError;
expect(terr).toBeInstanceOf(TransportError);
expect(terr.response).toBeUndefined();
expect(terr.message).toBe('Random error');
expect(terr.parent).not.toBeUndefined();
expect(terr.parent?.message).toBe('Random error');
}
});
});
it('returns the configured url', async function () {
const transport = new Transport({ url: URL });
expect(transport.url).toBe(URL);
});
it('non axios errors are set in parent', async function () {
const transport = new Transport({ url: URL });
const mock = jest.spyOn(transport, 'beforeRequest');
mock.mockImplementation(() => {
throw new Error('this is not an axios error');
});
try {
await transport.get('/route');
fail();
} catch (err: any) {
const terr = err as TransportError;
expect(terr).toBeInstanceOf(TransportError);
expect(terr.response).toBeUndefined();
expect(terr.message).toBe('this is not an axios error');
expect(terr.parent).not.toBeUndefined();
expect(terr.parent?.message).toBe('this is not an axios error');
}
});
});