@exodus/networking-spec
Version:
Platform-agnostic test suites for networking related features
164 lines (163 loc) • 7.36 kB
JavaScript
import { CONTROL_CHARACTERS, SEPARATORS } from '@exodus/networking-common/cookie/constants';
export function testsuite(getInstance, unrestrictedAccess = true) {
describe('CookieJar', () => {
let cookieJar;
beforeEach(async () => {
cookieJar = getInstance();
await cookieJar.removeAll();
});
function normalize(value) {
if (Array.isArray(value))
return value;
return [value];
}
const url = 'https://my-domain.com';
it('should set a cookie', async () => {
const cookie = {
name: 'csrf',
httpOnly: false,
value: 'abcd1234',
};
await cookieJar.set(cookie, url);
const actual = normalize(await cookieJar.get({ url, name: 'csrf' }));
expect(actual[0]?.value).toEqual(cookie.value);
});
describe('invalid characters', () => {
describe('name', () => {
const forbidden = new Set([...CONTROL_CHARACTERS, ...SEPARATORS]);
forbidden.forEach((character) => {
it(`should throw when it contains ${character}`, async () => {
const cookie = {
name: `name${character}`,
value: 'abcdefgh',
};
try {
await cookieJar.set(cookie, url);
expect(true).toEqual(false);
}
catch (e) {
expect(e.message).toContain('invalid character');
}
});
});
});
describe('value', () => {
const forbidden = new Set([...CONTROL_CHARACTERS, ' ', '"', ',', ';', '\\']);
forbidden.forEach((character) => {
it(`should throw when it contains ${character}`, async () => {
const cookie = {
name: 'csrf',
value: `value${character}`,
};
try {
await cookieJar.set(cookie, url);
expect(true).toEqual(false);
}
catch (e) {
expect(e.message).toContain('invalid character');
}
});
});
});
});
it('should set a cookie with = in its value', async () => {
const cookie = {
name: 'csrf',
value: 'abc=def',
};
await cookieJar.set(cookie, url);
const actual = normalize(await cookieJar.get({ url, name: 'csrf' }));
expect(actual[0]?.value).toEqual(cookie.value);
});
it('should set a cookie from response header', async () => {
const headerValue = 'name=bruce; SameSite=Lax';
await cookieJar.set(headerValue, url);
const [actual] = normalize(await cookieJar.get({ url, name: 'name' }));
expect(actual?.value).toEqual('bruce');
});
describe('with cookies', () => {
const cookies = [
{
name: 'csrf',
httpOnly: false,
value: 'abcd1234',
maxAge: 100,
version: '0.1',
},
{
name: 'session_id',
httpOnly: false,
value: 'abcd1234',
secure: true,
},
];
beforeEach(async () => {
await Promise.all(cookies.map((cookie) => cookieJar.set(cookie, url)));
});
if (unrestrictedAccess) {
describe('unrestricted access', () => {
describe('get', () => {
it('should get cookies for url and name', async () => {
const actual = await cookieJar.get({ url, name: 'csrf' });
expect(actual).toEqual([cookies[0]]);
});
it('should get no cookies for other domain and name', async () => {
expect(await cookieJar.get({ url: 'https://visit-arkham.com', name: 'csrf' })).toEqual([]);
});
it('should get no cookies for other name', async () => {
expect(await cookieJar.get({ url, name: 'dr. who' })).toEqual([]);
});
});
describe('getAll', () => {
it('should return all cookies', async () => {
const actual = await cookieJar.getAll();
expect(actual).toEqual(cookies);
});
it('should return all cookies for a url', async () => {
const otherUrl = 'https://wayne-foundation.com';
const veryTastyCookie = { name: 'recipe', value: 'bat-cookie-blend-heat-ready' };
await cookieJar.set(veryTastyCookie, otherUrl);
const actual = await cookieJar.getAll({ url });
expect(actual).toEqual(cookies);
});
});
});
}
else {
describe('restricted access', () => {
let jar;
beforeEach(() => {
jar = cookieJar;
});
describe('get', () => {
it('should get cookie by name', async () => {
const { name, value } = cookies[0] ?? {};
const actual = await jar.get({ name: 'csrf' });
expect(actual).toEqual({ name, value });
});
it('should get no cookies for other name', async () => {
expect(await jar.get({ name: 'dr. who' })).toBeUndefined();
});
});
describe('getAll', () => {
it('should return all cookies', async () => {
const actual = await cookieJar.getAll();
expect(actual).toEqual(cookies.map(({ name, value }) => ({ name, value })));
});
});
});
}
it('should remove a cookie', async () => {
await cookieJar.remove({ url, name: 'session_id' });
const remaining = await cookieJar.getAll({ url });
expect(remaining.length).toEqual(1);
expect(remaining[0]?.name).toEqual('csrf');
});
it('should remove all cookies', async () => {
await cookieJar.removeAll();
const cookies = await cookieJar.getAll({ url });
expect(cookies.length).toEqual(0);
});
});
});
}