Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const response = { test: 123 };
requests.forEach((request, index) => {
const context = new Context({ request });
context.updateExternalMeta = jest.fn(context.updateExternalMeta.bind(context));
context.updateInternalMeta = jest.fn(context.updateInternalMeta.bind(context));
plugin.init(context, next, null);
expect(context.updateInternalMeta).toHaveBeenCalledWith(metaTypes.CACHE, { key: request.url });
if (request.url === 'first' && index !== 0) {
expect(context.updateExternalMeta).toHaveBeenCalledWith(metaTypes.CACHE, { deduplicated: true });
}
});
expect(next).toHaveBeenCalledTimes(2);
plugin.complete(new Context({ response, request: requests[0], status: Status.COMPLETE }), next, null);
expect(next).toHaveBeenCalledTimes(5); // 4 requests init + 1 complete
requests.forEach((request) => {
expect(next).toHaveBeenCalledWith({ response, status: Status.COMPLETE, error: null });
});
});
import { Context, Status } from '@tinkoff/request-core';
import { VALIDATE } from './constants';
import validate from './validate';
const validator = ({ response }) => {
if (response.error) {
return new Error(response.error);
}
};
const errorValidator = ({ error }) => {
return !!error.valid;
};
const plugin = validate({ validator, errorValidator });
const context = new Context();
context.setState = jest.fn(context.setState.bind(context));
context.updateExternalMeta = jest.fn(context.updateExternalMeta.bind(context));
describe('plugins/validate/validate', () => {
beforeEach(() => {
// @ts-ignore
context.setState.mockClear();
// @ts-ignore
context.updateExternalMeta.mockClear();
});
it('if validator returns undefined plugin should not return any state or call next callback', () => {
context.setState({ response: { a: 1 } });
(context.setState as jest.Mock).mockClear();
const next = jest.fn();
const error = new Error('text');
requests.forEach((request, index) => {
const context = new Context({ request });
context.updateExternalMeta = jest.fn(context.updateExternalMeta.bind(context));
context.updateInternalMeta = jest.fn(context.updateInternalMeta.bind(context));
plugin.init(context, next, null);
expect(context.updateInternalMeta).toHaveBeenCalledWith(metaTypes.CACHE, { key: request.url });
if (request.url === 'first' && index !== 0) {
expect(context.updateExternalMeta).toHaveBeenCalledWith(metaTypes.CACHE, { deduplicated: true });
}
});
expect(next).toHaveBeenCalledTimes(2);
plugin.error(new Context({ error, request: requests[0], status: Status.ERROR }), next, null);
expect(next).toHaveBeenCalledTimes(5); // 4 requests init + 1 complete
requests.forEach((request) => {
expect(next).toHaveBeenCalledWith({ error, status: Status.ERROR, response: null });
});
});
});
init: (context, next, makeRequest) => {
const cacheKey = getCacheKeyUtil(context, getCacheKey);
if (lruCache.has(cacheKey)) {
context.updateExternalMeta(metaTypes.CACHE, {
memoryCache: true,
memoryCacheOutdated: false,
});
return next({
status: Status.COMPLETE,
response: lruCache.get(cacheKey),
});
}
const allowOutdated = propOr('memoryCacheAllowStale', allowStale, context.getRequest());
const outdated = allowOutdated && lruCache.peek(cacheKey);
if (outdated) {
const request = context.getRequest();
context.updateExternalMeta(metaTypes.CACHE, {
memoryCache: true,
memoryCacheOutdated: true,
});
lruCache.set(cacheKey, outdated, staleTtl); // remember outdated value, to prevent losing it
it('test common option `cacheForce` complete state', () => {
expect(isActive(generate({ cache: false, cacheForce: true }, Status.COMPLETE))).toBe(dflt);
expect(isActive(generate({ cache: false, cacheForce: false }, Status.COMPLETE))).toBe(false);
expect(isActive(generate({ cache: false, cacheForce: false, testCacheForce: false }, Status.COMPLETE))).toBe(
false
);
expect(isActive(generate({ cache: false, cacheForce: false, testCacheForce: true }, Status.COMPLETE))).toBe(
true
);
expect(isActive(generate({ cache: false, cacheForce: true, testCacheForce: false }, Status.COMPLETE))).toBe(
false
);
expect(isActive(generate({ cache: false, cacheForce: true, testCacheForce: true }, Status.COMPLETE))).toBe(
true
);
});
});
mockLru.has.mockImplementation(() => false);
mockLru.peek.mockImplementation(() => response);
plugin.init(context, next, makeRequest);
jest.runAllTimers();
expect(mockLru.get).not.toHaveBeenCalledWith('test');
expect(makeRequest).toHaveBeenCalledWith({ url: 'test', memoryCacheForce: true });
expect(context.updateMeta).toHaveBeenCalledWith(metaTypes.CACHE, {
memoryCache: true,
memoryCacheOutdated: true,
});
expect(next).toHaveBeenCalledWith({
response,
status: Status.COMPLETE,
});
});
it('error: if request failed with 304 status return value from cache', () => {
const response = { a: 1 };
context.updateInternalMeta(ETAG, {
value: response,
});
context.setState({ error: Object.assign(new Error(), { status: 304 }) });
plugin.error(context, next, null);
expect(context.updateExternalMeta).toHaveBeenCalledWith(metaTypes.CACHE, {
etagCache: true,
});
expect(next).toHaveBeenCalledWith({
status: Status.COMPLETE,
response,
});
});
});
it('on complete requests check testCacheForce', () => {
expect(isActive(generate({}, Status.COMPLETE))).toBe(dflt);
expect(isActive(generate({ testCacheForce: true }, Status.COMPLETE))).toBe(true);
});
}
http({ agent: { http: new MockedAgent() as any, https: new MockedAgent() as any } }).init(
new Context({ request: { url: 'http://test.com/api' } }),
next,
null
);
await new Promise((res) => {
next.mockImplementation(res);
});
expect(mockResponse).toBeCalled();
expect(next).toHaveBeenLastCalledWith({
response,
status: Status.COMPLETE,
});
});
headers: {
'Content-type': 'application/json;',
},
},
})
);
fetch.mockResponse(mockResponse);
class MockedAgent {
requests() {}
destroy() {}
}
http({ agent: { http: new MockedAgent() as any, https: new MockedAgent() as any } }).init(
new Context({ request: { url: 'http://test.com/api' } }),
next,
null
);
await new Promise((res) => {
next.mockImplementation(res);
});
expect(mockResponse).toBeCalled();
expect(next).toHaveBeenLastCalledWith({
response,
status: Status.COMPLETE,
});
});