Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,63 @@ describe('test CookieJar', () => {
cookieList.upsert(upsertedC1);
expect(cookieList.one('c1')).toEqual(upsertedC1.valueOf());
});

it('toObject returns {} when there are no cookies', () => {
expect(new CookieList([]).toObject()).toEqual({});
expect(new CookieObject(null).toObject()).toEqual({});
});

it('toObject returns a key-value map when there are cookies', () => {
const cookieList = new CookieList([new Cookie({ key: 'c1', value: 'v1' }), new Cookie({ key: 'c2', value: 'v2' })]);
expect(cookieList.toObject()).toEqual({ c1: 'v1', c2: 'v2' });

const cookieObject = new CookieObject({
_id: '',
type: 'CookieJar',
parentId: '',
modified: 0,
created: 0,
isPrivate: false,
name: 'my jar',
cookies: [
{ id: '1', key: 'c1', value: 'v1', domain: 'inso.com', expires: null, path: '/', secure: false, httpOnly: false },
{ id: '2', key: 'c2', value: 'v2', domain: 'inso.com', expires: null, path: '/', secure: false, httpOnly: false },
],
});
expect(cookieObject.toObject()).toEqual({ c1: 'v1', c2: 'v2' });
});

it('toObject includes disabled cookies by default but excludes them when excludeDisabled is true', () => {
const c1 = new Cookie({ key: 'c1', value: 'v1' });
const c2 = new Cookie({ key: 'c2', value: 'v2' });
c2.disabled = true;
const cookieList = new CookieList([c1, c2]);

expect(cookieList.toObject()).toEqual({ c1: 'v1', c2: 'v2' });
expect(cookieList.toObject(true)).toEqual({ c1: 'v1' });
});

it('toObject collapses duplicate keys to the last value by default, but collects them into an array when multiValue is true', () => {
const cookieList = new CookieList([
new Cookie({ key: 'c1', value: 'v1' }),
new Cookie({ key: 'c1', value: 'v1b' }),
new Cookie({ key: 'c2', value: 'v2' }),
]);

expect(cookieList.toObject()).toEqual({ c1: 'v1b', c2: 'v2' });
expect(cookieList.toObject(false, false, true)).toEqual({ c1: ['v1', 'v1b'], c2: 'v2' });
});

it('toObject does not pollute the prototype for dangerous cookie keys', () => {
const cookieList = new CookieList([
new Cookie({ key: '__proto__', value: 'polluted' }),
new Cookie({ key: 'constructor', value: 'polluted' }),
]);

const obj = cookieList.toObject();
expect(Object.getPrototypeOf(obj)).toBeNull();
expect(({} as any).polluted).toBeUndefined();
expect(obj.__proto__).toEqual('polluted');
expect(obj.constructor).toEqual('polluted');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,38 @@ describe('test Header object', () => {
headerList.upsert(upserted);
expect(headerList.one('h1')).toEqual(upserted.value);
});

it('toObject returns {} when there are no headers', () => {
expect(new HeaderList(undefined, []).toObject()).toEqual({});
});

it('toObject returns a key-value map when there are headers', () => {
const headerList = new HeaderList(undefined, [
new Header({ key: 'h1', value: 'v1' }),
new Header({ key: 'h2', value: 'v2' }),
]);

expect(headerList.toObject()).toEqual({ h1: 'v1', h2: 'v2' });
});

it('toObject includes disabled headers by default but excludes them when excludeDisabled is true', () => {
const headerList = new HeaderList(undefined, [
new Header({ key: 'h1', value: 'v1' }),
new Header({ key: 'h2', value: 'v2', disabled: true }),
]);

expect(headerList.toObject()).toEqual({ h1: 'v1', h2: 'v2' });
expect(headerList.toObject(true)).toEqual({ h1: 'v1' });
});

it('toObject collapses duplicate keys to the last value by default, but collects them into an array when multiValue is true', () => {
const headerList = new HeaderList(undefined, [
new Header({ key: 'h1', value: 'v1' }),
new Header({ key: 'h1', value: 'v1b' }),
new Header({ key: 'h2', value: 'v2' }),
]);

expect(headerList.toObject()).toEqual({ h1: 'v1b', h2: 'v2' });
expect(headerList.toObject(false, false, true)).toEqual({ h1: ['v1', 'v1b'], h2: 'v2' });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,108 @@ describe('test ProxyConfig object', () => {
it('throws on a malformed proxy host when the proxy is enabled', () => {
expect(() => transformToSdkProxyOptions('', 'fasdf', '', true, '')).toThrow(/Failed to parse proxy/);
});

it('toObject returns {} when there are no proxy configs', () => {
expect(new ProxyConfigList<ProxyConfig>(undefined, []).toObject()).toEqual({});
});

it('toObject returns a map keyed by match pattern when there are proxy configs', () => {
const proxyConfig1 = new ProxyConfig({
match: 'http+https://*.example.com:80/*',
host: 'proxy.com',
port: 8080,
tunnel: true,
disabled: false,
authenticate: true,
username: 'proxy_username',
password: 'proxy_password',
protocol: 'https:',
});
const proxyConfig2 = new ProxyConfig({
match: 'https://*.example2.com:80/*',
host: 'proxy2.com',
port: 8081,
tunnel: false,
disabled: false,
authenticate: false,
username: '',
password: '',
protocol: 'https:',
});

const configList = new ProxyConfigList<ProxyConfig>(undefined, [proxyConfig1, proxyConfig2]);

expect(configList.toObject()).toEqual({
[proxyConfig1.match]: proxyConfig1.toJSON(),
[proxyConfig2.match]: proxyConfig2.toJSON(),
});
});

it('toObject includes disabled proxy configs by default but excludes them when excludeDisabled is true', () => {
const proxyConfig1 = new ProxyConfig({
match: 'http+https://*.example.com:80/*',
host: 'proxy.com',
port: 8080,
tunnel: true,
disabled: false,
authenticate: true,
username: 'proxy_username',
password: 'proxy_password',
protocol: 'https:',
});
const proxyConfig2 = new ProxyConfig({
match: 'https://*.example2.com:80/*',
host: 'proxy2.com',
port: 8081,
tunnel: false,
disabled: true,
authenticate: false,
username: '',
password: '',
protocol: 'https:',
});

const configList = new ProxyConfigList<ProxyConfig>(undefined, [proxyConfig1, proxyConfig2]);

expect(configList.toObject()).toEqual({
[proxyConfig1.match]: proxyConfig1.toJSON(),
[proxyConfig2.match]: proxyConfig2.toJSON(),
});
expect(configList.toObject(true)).toEqual({
[proxyConfig1.match]: proxyConfig1.toJSON(),
});
});

it('toObject collapses duplicate match patterns to the last value by default, but collects them into an array when multiValue is true', () => {
const match = 'https://*.example.com:80/*';
const proxyConfig1 = new ProxyConfig({
match,
host: 'proxy.com',
port: 8080,
tunnel: true,
disabled: false,
authenticate: true,
username: 'proxy_username',
password: 'proxy_password',
protocol: 'https:',
});
const proxyConfig2 = new ProxyConfig({
match,
host: 'proxy2.com',
port: 8081,
tunnel: false,
disabled: false,
authenticate: false,
username: '',
password: '',
protocol: 'https:',
});

const configList = new ProxyConfigList<ProxyConfig>(undefined, [proxyConfig1, proxyConfig2]);

expect(configList.toObject()).toEqual({ [match]: proxyConfig2.toJSON() });
expect(configList.toObject(false, false, true)).toEqual({
[match]: [proxyConfig1.toJSON(), proxyConfig2.toJSON()],
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,38 @@ describe('test Variables object', () => {
varList.upsert(upserted);
expect(varList.one('h1')).toEqual(upserted);
});

it('toObject returns {} when there are no variables', () => {
expect(new VariableList(undefined, []).toObject()).toEqual({});
});

it('toObject returns a key-value map when there are variables', () => {
const varList = new VariableList(undefined, [
new Variable({ key: 'h1', value: 'v1' }),
new Variable({ key: 'h2', value: 'v2' }),
]);

expect(varList.toObject()).toEqual({ h1: 'v1', h2: 'v2' });
});

it('toObject includes disabled variables by default but excludes them when excludeDisabled is true', () => {
const varList = new VariableList(undefined, [
new Variable({ key: 'h1', value: 'v1' }),
new Variable({ key: 'h2', value: 'v2', disabled: true }),
]);

expect(varList.toObject()).toEqual({ h1: 'v1', h2: 'v2' });
expect(varList.toObject(true)).toEqual({ h1: 'v1' });
});

it('toObject collapses duplicate keys to the last value by default, but collects them into an array when multiValue is true', () => {
const varList = new VariableList(undefined, [
new Variable({ key: 'h1', value: 'v1' }),
new Variable({ key: 'h1', value: 'v1b' }),
new Variable({ key: 'h2', value: 'v2' }),
]);

expect(varList.toObject()).toEqual({ h1: 'v1b', h2: 'v2' });
expect(varList.toObject(false, false, true)).toEqual({ h1: ['v1', 'v1b'], h2: 'v2' });
});
});
17 changes: 17 additions & 0 deletions packages/insomnia-scripting-environment/src/objects/cookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,23 @@ export class CookieList extends PropertyList<Cookie> {
static isCookieList(obj: object) {
return '_kind' in obj && obj._kind === 'CookieList';
}

override toObject(excludeDisabled?: boolean, _caseSensitive?: boolean, multiValue?: boolean, _sanitizeKeys?: boolean) {
const obj: Record<string, string | string[]> = Object.create(null);
this.list.forEach(cookie => {
if (excludeDisabled && cookie.disabled) {
return;
}
const value = cookie.valueOf();
if (multiValue && cookie.key in obj) {
const existing = obj[cookie.key];
obj[cookie.key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
} else {
obj[cookie.key] = value;
}
});
return obj;
}
}

export class CookieObject extends CookieList {
Expand Down
17 changes: 17 additions & 0 deletions packages/insomnia-scripting-environment/src/objects/headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,21 @@ export class HeaderList<T extends Header> extends PropertyList<T> {
.map(headerStr => headerStr.length) // TODO: handle special characters
.reduce((totalSize, headerSize) => totalSize + headerSize, 0);
}

override toObject(excludeDisabled?: boolean, _caseSensitive?: boolean, multiValue?: boolean, _sanitizeKeys?: boolean) {
const obj: Record<string, string | string[]> = Object.create(null);
this.list.forEach(header => {
if (excludeDisabled && header.disabled) {
return;
}
const value = header.valueOf();
if (multiValue && header.key in obj) {
const existing = obj[header.key];
obj[header.key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
} else {
obj[header.key] = value;
}
});
return obj;
}
}
16 changes: 11 additions & 5 deletions packages/insomnia-scripting-environment/src/objects/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,17 @@ export class PropertyList<T extends Property> {
this.populate(items);
}

// TODO: unsupported yet

toObject(_excludeDisabled?: boolean, _caseSensitive?: boolean, _multiValue?: boolean, _sanitizeKeys?: boolean) {
// it just dump all properties of each element without arguments
// then user is able to handle them by themself
// Fallback for lists whose items have no natural key (e.g. UrlMatchPatternList, or a
// PropertyList used directly rather than through a subclass) - just dumps each element's
// JSON and ignores all arguments. Subclasses backed by keyed items (CookieList, HeaderList,
// VariableList, ProxyConfigList) override this with a real key/value map that supports
// excludeDisabled and multiValue; caseSensitive and sanitizeKeys remain unsupported there too.
toObject(
_excludeDisabled?: boolean,
_caseSensitive?: boolean,
_multiValue?: boolean,
_sanitizeKeys?: boolean,
): Record<string, any> | Record<string, any>[] {
return this.list.map(elem => elem.toJSON());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,23 @@ export class ProxyConfigList<T extends ProxyConfig> extends PropertyList<T> {
}
return null;
}

override toObject(excludeDisabled?: boolean, _caseSensitive?: boolean, multiValue?: boolean, _sanitizeKeys?: boolean) {
const obj: Record<string, any> = Object.create(null);
this.list.forEach(proxyConfig => {
if (excludeDisabled && proxyConfig.disabled) {
return;
}
const value = proxyConfig.toJSON();
if (multiValue && proxyConfig.match in obj) {
const existing = obj[proxyConfig.match];
obj[proxyConfig.match] = Array.isArray(existing) ? [...existing, value] : [existing, value];
} else {
obj[proxyConfig.match] = value;
}
});
return obj;
}
}

/** @ignore */
Expand Down
17 changes: 17 additions & 0 deletions packages/insomnia-scripting-environment/src/objects/variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,21 @@ export class VariableList<T extends Variable> extends PropertyList<T> {
static isVariableList(obj: any) {
return '_kind' in obj && obj._kind === 'VariableList';
}

override toObject(excludeDisabled?: boolean, _caseSensitive?: boolean, multiValue?: boolean, _sanitizeKeys?: boolean) {
const obj: Record<string, any> = Object.create(null);
this.list.forEach(variable => {
if (excludeDisabled && variable.disabled) {
return;
}
const value = variable.get();
if (multiValue && variable.key in obj) {
const existing = obj[variable.key];
obj[variable.key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
} else {
obj[variable.key] = value;
}
});
return obj;
}
}
Loading