Nunjuck resolution in order of property definitions (#1863)

* Add breaking test

* Remove preferential ordering of tags over variables in nunjucks

* Remove preferential ordering of tags over variables in nunjucks

* simplify nunjucks sort

* Add breaking test for incorrect order

* Update json-order and consume

* Refine test with dataPropertyOrder

* Tests

* add note

* Add to test

* Missed the await
This commit is contained in:
Opender Singh authored and GitHub committed 2020-03-09 11:20:22 -07:00
1 parent 64b6825e53
commit 1aba4cb2cf
8 files changed
+169 -70

No files matched your search

+70 -28
View File
@@ -74,6 +74,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@@ -111,7 +112,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@@ -132,12 +134,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -152,17 +156,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -279,7 +286,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@@ -291,6 +299,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -305,6 +314,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -312,12 +322,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -336,6 +348,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -416,7 +429,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -428,6 +442,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -513,7 +528,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -549,6 +565,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -568,6 +585,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -611,12 +629,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@@ -647,7 +667,8 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
"dev": true,
"optional": true
},
"is-glob": {
"version": "4.0.1",
@@ -7550,7 +7571,7 @@
},
"callsites": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
"resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
"integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
"dev": true
},
@@ -9820,7 +9841,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@@ -9841,12 +9863,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -9861,17 +9885,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -9988,7 +10015,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@@ -10000,6 +10028,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -10014,6 +10043,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -10021,12 +10051,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -10045,6 +10077,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -10125,7 +10158,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -10137,6 +10171,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -10222,7 +10257,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -10258,6 +10294,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -10277,6 +10314,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -10320,12 +10358,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@@ -16131,7 +16171,8 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
"dev": true
"dev": true,
"optional": true
},
"braces": {
"version": "2.3.2",
@@ -16394,7 +16435,8 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
"dev": true
"dev": true,
"optional": true
},
"micromatch": {
"version": "3.1.10",
@@ -16622,7 +16664,7 @@
},
"resolve": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
"resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
"dev": true
},
@@ -17062,7 +17104,7 @@
},
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
}
@@ -31,6 +31,35 @@ describe('render()', () => {
expect(err.message).toContain('expected variable end');
}
});
it('handles variables using tag before tag is defined as expected (incorrect order)', async () => {
const rootEnvironment = {
type: models.environment.type,
data: {
consume: '{{ replaced }}',
hashed: "{% hash 'md5', 'hex', value %}",
replaced: "{{ hashed | replace('f67565de946a899a534fd908e7eef872', 'cat') }}",
value: 'ThisIsATopSecretValue',
},
dataPropertyOrder: {
'&': ['value', 'replaced', 'hashed', 'consume'],
},
};
const context = await renderUtils.buildRenderContext([], rootEnvironment);
expect(context).toEqual({
value: 'ThisIsATopSecretValue',
hashed: 'f67565de946a899a534fd908e7eef872',
replaced: 'f67565de946a899a534fd908e7eef872',
consume: 'f67565de946a899a534fd908e7eef872',
});
// In runtime, this context is used to render, which re-evaluates the expression for replaced in the rootEnvironment by using the built context
// Regression test from issue 1917 - https://github.com/Kong/insomnia/issues/1917
const renderExpression = await renderUtils.render(rootEnvironment.data.replaced, context);
expect(renderExpression).toBe('cat');
});
});
describe('buildRenderContext()', () => {
@@ -399,6 +428,30 @@ describe('buildRenderContext()', () => {
});
});
it('handles variables using tag after tag is defined as expected (correct order)', async () => {
const rootEnvironment = {
type: models.environment.type,
data: {
consume: '{{ replaced }}',
hashed: "{% hash 'md5', 'hex', value %}",
replaced: "{{ hashed | replace('f67565de946a899a534fd908e7eef872', 'cat') }}",
value: 'ThisIsATopSecretValue',
},
dataPropertyOrder: {
'&': ['value', 'hashed', 'replaced', 'consume'],
},
};
const context = await renderUtils.buildRenderContext([], rootEnvironment);
expect(context).toEqual({
value: 'ThisIsATopSecretValue',
hashed: 'f67565de946a899a534fd908e7eef872',
replaced: 'cat',
consume: 'cat',
});
});
it('handles variables being used in tags', async () => {
const rootEnvironment = {
type: models.environment.type,
@@ -177,6 +177,10 @@ export const AUTH_ASAP = 'asap';
export const HAWK_ALGORITHM_SHA256 = 'sha256';
export const HAWK_ALGORITHM_SHA1 = 'sha1';
// json-order constants
export const JSON_ORDER_PREFIX = '&';
export const JSON_ORDER_SEPARATOR = `~|`;
const authTypesMap = {
[AUTH_BASIC]: ['Basic', 'Basic Auth'],
[AUTH_DIGEST]: ['Digest', 'Digest Auth'],
+26 -13
View File
@@ -5,11 +5,12 @@ import type { BaseModel } from '../models/index';
import { setDefaultProtocol } from 'insomnia-url';
import clone from 'clone';
import * as models from '../models';
import { CONTENT_TYPE_GRAPHQL } from '../common/constants';
import { CONTENT_TYPE_GRAPHQL, JSON_ORDER_PREFIX } from '../common/constants';
import * as db from './database';
import * as templating from '../templating';
import type { CookieJar } from '../models/cookie-jar';
import type { Environment } from '../models/environment';
import orderedJSON from 'json-order';
export const KEEP_ON_ERROR = 'keep';
export const THROW_ON_ERROR = 'throw';
@@ -36,23 +37,41 @@ export async function buildRenderContext(
): Object {
const envObjects = [];
// Get root environment keys in correct order
// Then get sub environment keys in correct order
// Then get ancestor (folder) environment keys in correct order
if (rootEnvironment) {
envObjects.push(rootEnvironment.data);
const ordered = orderedJSON.order(
rootEnvironment.data,
rootEnvironment.dataPropertyOrder,
JSON_ORDER_PREFIX,
);
envObjects.push(ordered);
}
if (subEnvironment) {
envObjects.push(subEnvironment.data);
const ordered = orderedJSON.order(
subEnvironment.data,
subEnvironment.dataPropertyOrder,
JSON_ORDER_PREFIX,
);
envObjects.push(ordered);
}
for (const doc of (ancestors || []).reverse()) {
const environment = (doc: any).environment;
const ancestor: any = doc;
const { environment, environmentPropertyOrder } = ancestor;
if (typeof environment === 'object' && environment !== null) {
envObjects.push(environment);
const ordered = orderedJSON.order(environment, environmentPropertyOrder, JSON_ORDER_PREFIX);
envObjects.push(ordered);
}
}
// At this point, environments is a list of environments ordered
// from top-most parent to bottom-most child
// from top-most parent to bottom-most child, and they keys in each environment
// ordered by its property map.
// Do an Object.assign, but render each property as it overwrites. This
// way we can keep same-name variables from the parent context.
let renderContext = baseContext;
@@ -437,13 +456,7 @@ export async function getRenderedRequest(
* @returns {number}
*/
function _nunjucksSortValue(v) {
if (v && v.match && v.match(/({%)/)) {
return 3;
} else if (v && v.match && v.match(/({{)/)) {
return 2;
} else {
return 1;
}
return v && v.match && v.match(/({{|{%)/) ? 2 : 1;
}
function _getOrderedEnvironmentKeys(finalRenderContext: Object): Array<string> {
@@ -3,6 +3,7 @@ import * as React from 'react';
import autobind from 'autobind-decorator';
import CodeEditor from '../codemirror/code-editor';
import orderedJSON from 'json-order';
import { JSON_ORDER_PREFIX, JSON_ORDER_SEPARATOR } from '../../../common/constants';
export type EnvironmentInfo = {
object: Object,
@@ -77,7 +78,11 @@ class EnvironmentEditor extends React.PureComponent<Props, State> {
getValue(): EnvironmentInfo | null {
if (this._editor) {
const data = orderedJSON.parse(this._editor.getValue(), '&', `~|`);
const data = orderedJSON.parse(
this._editor.getValue(),
JSON_ORDER_PREFIX,
JSON_ORDER_SEPARATOR,
);
return {
object: data.object,
@@ -111,7 +116,7 @@ class EnvironmentEditor extends React.PureComponent<Props, State> {
const defaultValue = orderedJSON.stringify(
environmentInfo.object,
environmentInfo.propertyOrder || null,
'~|',
JSON_ORDER_SEPARATOR,
);
return (
+5
View File
@@ -14,6 +14,11 @@ declare module 'json-order' {
separator?: string,
space?: number | void,
) => string,
order: (
sourceObject: Object,
map: { [key: string]: Array<string> } | null,
separator?: string,
) => Object,
};
declare module.exports: orderedJSON;
+3 -26
View File
@@ -8004,11 +8004,6 @@
"buffer-indexof": "^1.0.0"
}
},
"docopt": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
"integrity": "sha1-so6eIiDaXsSffqW7JKR3h0Be6xE="
},
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -8088,15 +8083,6 @@
"domelementtype": "1"
}
},
"dot-json": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/dot-json/-/dot-json-1.1.0.tgz",
"integrity": "sha512-PiQZW9/C8xILPYK2bOye/cbPZrakNEkt28jFb8RlPCwsoMAHYYw9T8JoACxgttHL9Y2AmdqVvibbZJHtLgeqTQ==",
"requires": {
"docopt": "~0.6.2",
"underscore-keypath": "~0.0.22"
}
},
"dot-prop": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
@@ -12000,11 +11986,10 @@
"dev": true
},
"json-order": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/json-order/-/json-order-1.0.12.tgz",
"integrity": "sha512-MLopfzLoZ71XfI04Ox68N1PbIti2phuTyu4TvZaTok/Eq90iBq5e/3Bd9NbW+lXpe3GxdsijC/UsyAwTLmCoUA==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/json-order/-/json-order-1.1.0.tgz",
"integrity": "sha512-xiULVQOg6+JbST7xwGvhoBUJJ6kOiBUM6zgeGSp5TisNpPd0iyqJDWPNi0Kd7K88A/I6784O+AXaczURK3SSLg==",
"requires": {
"dot-json": "^1.1.0",
"lodash.clonedeep": "^4.5.0"
}
},
@@ -18262,14 +18247,6 @@
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
},
"underscore-keypath": {
"version": "0.0.22",
"resolved": "https://registry.npmjs.org/underscore-keypath/-/underscore-keypath-0.0.22.tgz",
"integrity": "sha1-SKUoOSu278QkvhyqVtpLX6zPJk0=",
"requires": {
"underscore": "*"
}
},
"unfetch": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.1.0.tgz",
+1 -1
View File
@@ -155,7 +155,7 @@
"insomnia-prettify": "^2.1.4",
"insomnia-url": "^2.1.4",
"insomnia-xpath": "^2.1.4",
"json-order": "^1.0.12",
"json-order": "^1.1.0",
"jsonlint": "^1.6.3",
"jsonpath": "^1.0.2",
"jwt-authentication": "^0.4.0",