mirror of
https://github.com/ansible/awx.git
synced 2026-01-20 06:01:25 -03:30
Merge pull request #284 from joefiorini/system-tracking--displayKeys
Adds support for formatting individual fact values
This commit is contained in:
commit
ef0e7d8f0d
16
awx/ui/static/js/shared/format-epoch/format-epoch.filter.js
Normal file
16
awx/ui/static/js/shared/format-epoch/format-epoch.filter.js
Normal file
@ -0,0 +1,16 @@
|
||||
export default
|
||||
[ 'moment',
|
||||
function(moment) {
|
||||
return function(seconds, formatStr) {
|
||||
if (!formatStr) {
|
||||
formatStr = 'll LT';
|
||||
}
|
||||
|
||||
var millis = seconds * 1000;
|
||||
|
||||
return moment(millis).format(formatStr);
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
9
awx/ui/static/js/shared/format-epoch/main.js
Normal file
9
awx/ui/static/js/shared/format-epoch/main.js
Normal file
@ -0,0 +1,9 @@
|
||||
import formatEpoch from './format-epoch.filter';
|
||||
import moment from 'tower/shared/moment/main';
|
||||
|
||||
export default
|
||||
angular.module('formatEpoch',
|
||||
[ moment.name
|
||||
])
|
||||
.filter('formatEpoch', formatEpoch);
|
||||
|
||||
@ -6,27 +6,48 @@
|
||||
|
||||
import compareNestedFacts from './compare-facts/nested';
|
||||
import compareFlatFacts from './compare-facts/flat';
|
||||
import FactTemplate from './compare-facts/fact-template';
|
||||
|
||||
export function compareFacts(module, facts) {
|
||||
if (module.displayType === 'nested') {
|
||||
return { factData: compareNestedFacts(facts),
|
||||
isNestedDisplay: true
|
||||
};
|
||||
} else {
|
||||
|
||||
|
||||
var renderOptions = _.merge({}, module);
|
||||
|
||||
// If the module has a template or includes a list of keys to display,
|
||||
// then perform a flat comparison, otherwise assume nested
|
||||
//
|
||||
if (renderOptions.factTemplate || renderOptions.nameKey) {
|
||||
// For flat structures we compare left-to-right, then right-to-left to
|
||||
// make sure we get a good comparison between both hosts
|
||||
var compare = _.partialRight(compareFlatFacts, module.nameKey, module.compareKey, module.factTemplate);
|
||||
var leftToRight = compare(facts[0], facts[1]);
|
||||
var rightToLeft = compare(facts[1], facts[0]);
|
||||
|
||||
if (_.isPlainObject(renderOptions.factTemplate)) {
|
||||
renderOptions.factTemplate =
|
||||
_.mapValues(renderOptions.factTemplate, function(template) {
|
||||
if (typeof template === 'string' || typeof template === 'function') {
|
||||
return new FactTemplate(template);
|
||||
} else {
|
||||
return template;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
renderOptions.factTemplate = new FactTemplate(renderOptions.factTemplate);
|
||||
}
|
||||
|
||||
var leftToRight = compareFlatFacts(facts[0], facts[1], renderOptions);
|
||||
var rightToLeft = compareFlatFacts(facts[1], facts[0], renderOptions);
|
||||
|
||||
return _(leftToRight)
|
||||
.concat(rightToLeft)
|
||||
.unique('displayKeyPath')
|
||||
.thru(function(result) {
|
||||
return { factData: result,
|
||||
isNestedDisplay: _.isUndefined(module.factTemplate)
|
||||
isNestedDisplay: _.isPlainObject(renderOptions.factTemplate)
|
||||
};
|
||||
})
|
||||
.value();
|
||||
} else {
|
||||
return { factData: compareNestedFacts(facts),
|
||||
isNestedDisplay: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
import stringFilters from 'tower/shared/string-filters/main';
|
||||
import formatEpoch from 'tower/shared/format-epoch/main';
|
||||
|
||||
var $injector = angular.injector(['ng', stringFilters.name, formatEpoch.name]);
|
||||
var $interpolate = $injector.get('$interpolate');
|
||||
|
||||
function FactTemplate(templateString) {
|
||||
this.templateString = templateString;
|
||||
}
|
||||
|
||||
function loadFactTemplate(factTemplate, fact) {
|
||||
if (_.isFunction(factTemplate)) {
|
||||
return factTemplate(fact);
|
||||
} else {
|
||||
return factTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
FactTemplate.prototype.render = function(factData) {
|
||||
|
||||
if (_.isUndefined(factData) || _.isEmpty(factData)) {
|
||||
return 'absent';
|
||||
}
|
||||
|
||||
var template = loadFactTemplate(this.templateString, factData);
|
||||
return $interpolate(template)(factData);
|
||||
};
|
||||
|
||||
FactTemplate.prototype.hasTemplate = function() {
|
||||
return !_.isUndefined(this.templateString);
|
||||
};
|
||||
|
||||
export default FactTemplate;
|
||||
@ -4,23 +4,6 @@
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import stringFilters from 'tower/shared/string-filters/main';
|
||||
|
||||
var $injector = angular.injector(['ng', stringFilters.name]);
|
||||
var $interpolate = $injector.get('$interpolate');
|
||||
|
||||
function getFactTemplate(factTemplate, fact) {
|
||||
if (_.isFunction(factTemplate)) {
|
||||
return factTemplate(fact);
|
||||
} else {
|
||||
return factTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
function renderFactTemplate(template, fact) {
|
||||
return $interpolate(template)(fact);
|
||||
}
|
||||
|
||||
function slotFactValues(basisPosition, basisValue, comparatorValue) {
|
||||
var leftValue, rightValue;
|
||||
|
||||
@ -38,92 +21,122 @@ function slotFactValues(basisPosition, basisValue, comparatorValue) {
|
||||
}
|
||||
|
||||
export default
|
||||
function flatCompare(basisFacts, comparatorFacts, nameKey, compareKeys, factTemplate) {
|
||||
function flatCompare(basisFacts,
|
||||
comparatorFacts, renderOptions) {
|
||||
|
||||
var nameKey = renderOptions.nameKey;
|
||||
var compareKeys = renderOptions.compareKey;
|
||||
var keyNameMap = renderOptions.keyNameMap;
|
||||
var factTemplate = renderOptions.factTemplate;
|
||||
|
||||
|
||||
return basisFacts.facts.reduce(function(arr, basisFact) {
|
||||
var searcher = {};
|
||||
searcher[nameKey] = basisFact[nameKey];
|
||||
|
||||
var basisTemplate, comparatorTemplate, slottedValues, basisValue, comparatorValue;
|
||||
|
||||
var matchingFact = _.where(comparatorFacts.facts, searcher);
|
||||
var diffs;
|
||||
|
||||
if (_.isEmpty(matchingFact)) {
|
||||
// Perform comparison and get back comparisonResults; like:
|
||||
// { 'value':
|
||||
// { leftValue: 'blah',
|
||||
// rightValue: 'doo'
|
||||
// }
|
||||
// };
|
||||
//
|
||||
var comparisonResults =
|
||||
_.reduce(compareKeys, function(result, compareKey) {
|
||||
|
||||
if (!_.isUndefined(factTemplate)) {
|
||||
var comparatorFact = matchingFact[0] || {};
|
||||
var isNestedDisplay = false;
|
||||
|
||||
basisTemplate = getFactTemplate(factTemplate, basisFact);
|
||||
|
||||
basisValue = renderFactTemplate(basisTemplate, basisFact);
|
||||
slottedValues = slotFactValues(basisFacts.position, basisValue, 'absent');
|
||||
|
||||
diffs =
|
||||
{ keyName: basisFact[nameKey],
|
||||
value1: slottedValues.left,
|
||||
value2: slottedValues.right
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
diffs =
|
||||
_.map(basisFact, function(value, key) {
|
||||
var slottedValues = slotFactValues(basisFacts.position, value, 'absent');
|
||||
|
||||
return { keyName: key,
|
||||
value1: slottedValues.left,
|
||||
value1IsAbsent: slottedValues.left === 'absent',
|
||||
value2: slottedValues.right,
|
||||
value2IsAbsent: slotFactValues.right === 'absent'
|
||||
};
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
||||
matchingFact = matchingFact[0];
|
||||
|
||||
if (!_.isUndefined(factTemplate)) {
|
||||
|
||||
basisTemplate = getFactTemplate(factTemplate, basisFact);
|
||||
comparatorTemplate = getFactTemplate(factTemplate, matchingFact);
|
||||
|
||||
basisValue = renderFactTemplate(basisTemplate, basisFact);
|
||||
comparatorValue = renderFactTemplate(comparatorTemplate, matchingFact);
|
||||
|
||||
slottedValues = slotFactValues(basisFacts.position, basisValue, comparatorValue);
|
||||
|
||||
if (basisValue !== comparatorValue) {
|
||||
|
||||
diffs =
|
||||
{ keyName: basisFact[nameKey],
|
||||
value1: slottedValues.left,
|
||||
value2: slottedValues.right
|
||||
};
|
||||
var slottedValues = slotFactValues(basisFacts.position,
|
||||
basisFact[compareKey],
|
||||
comparatorFact[compareKey]);
|
||||
|
||||
if (_.isUndefined(slottedValues.left) && _.isUndefined(slottedValues.right)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
} else {
|
||||
var template = factTemplate;
|
||||
|
||||
diffs = _(compareKeys)
|
||||
.map(function(key) {
|
||||
var slottedValues = slotFactValues(basisFacts.position,
|
||||
basisFact[key],
|
||||
matchingFact[key]);
|
||||
if (_.isObject(template) && template.hasOwnProperty(compareKey)) {
|
||||
template = template[compareKey];
|
||||
|
||||
if (slottedValues.left !== slottedValues.right) {
|
||||
return {
|
||||
keyName: key,
|
||||
value1: slottedValues.left,
|
||||
value2: slottedValues.right
|
||||
// 'true' means render the key without formatting
|
||||
if (template === true) {
|
||||
template =
|
||||
{ render: function(fact) { return fact[compareKey]; }
|
||||
};
|
||||
}
|
||||
|
||||
isNestedDisplay = true;
|
||||
} else if (typeof template.hasTemplate === 'function' && !template.hasTemplate()) {
|
||||
template =
|
||||
{ render: function(fact) { return fact[compareKey]; }
|
||||
};
|
||||
isNestedDisplay = true;
|
||||
} else if (typeof factTemplate.render === 'function') {
|
||||
template = factTemplate;
|
||||
} else if (!template.hasOwnProperty(compareKey)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (basisFacts.position === 'left') {
|
||||
slottedValues.left = template.render(basisFact);
|
||||
slottedValues.right = template.render(comparatorFact);
|
||||
} else {
|
||||
slottedValues.left = template.render(comparatorFact);
|
||||
slottedValues.right = template.render(basisFact);
|
||||
}
|
||||
|
||||
if (slottedValues.left !== slottedValues.right) {
|
||||
slottedValues.isDivergent = true;
|
||||
} else {
|
||||
slottedValues.isDivergent = false;
|
||||
}
|
||||
|
||||
if (isNestedDisplay) {
|
||||
result[compareKey] = slottedValues;
|
||||
} else {
|
||||
result = slottedValues;
|
||||
}
|
||||
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
var hasDiffs =
|
||||
_.any(comparisonResults, { isDivergent: true }) ||
|
||||
comparisonResults.isDivergent === true;
|
||||
|
||||
if (hasDiffs && typeof factTemplate.render === 'function') {
|
||||
|
||||
diffs =
|
||||
{ keyName: basisFact[nameKey],
|
||||
value1: comparisonResults.left,
|
||||
value2: comparisonResults.right
|
||||
};
|
||||
|
||||
} else if (hasDiffs) {
|
||||
|
||||
diffs =
|
||||
_(comparisonResults).map(function(slottedValues, key) {
|
||||
|
||||
var keyName = key;
|
||||
|
||||
if (keyNameMap && keyNameMap[key]) {
|
||||
keyName = keyNameMap[key];
|
||||
}
|
||||
|
||||
return { keyName: keyName,
|
||||
value1: slottedValues.left,
|
||||
value2: slottedValues.right,
|
||||
isDivergent: slottedValues.isDivergent
|
||||
};
|
||||
}).compact()
|
||||
.value();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var descriptor =
|
||||
{ displayKeyPath: basisFact[nameKey],
|
||||
nestingLevel: 0,
|
||||
|
||||
@ -2,29 +2,34 @@ var moduleConfig =
|
||||
{ 'packages':
|
||||
{ compareKey: ['release', 'version'],
|
||||
nameKey: 'name',
|
||||
displayType: 'flat',
|
||||
sortKey: 1,
|
||||
factTemplate: "{{epoch|append:':'}}{{version}}-{{release}}{{arch|prepend:'.'}}"
|
||||
},
|
||||
'services':
|
||||
{ compareKey: ['state', 'source'],
|
||||
nameKey: 'name',
|
||||
displayType: 'flat',
|
||||
factTemplate: '{{state}} ({{source}})',
|
||||
sortKey: 2
|
||||
},
|
||||
'files':
|
||||
{ compareKey: ['size', 'mode', 'md5', 'mtime', 'gid', 'uid'],
|
||||
keyNameMap:
|
||||
{ 'uid': 'ownership'
|
||||
},
|
||||
factTemplate:
|
||||
{ 'uid': 'user id: {{uid}}, group id: {{gid}}',
|
||||
'mode': true,
|
||||
'md5': true,
|
||||
'mtime': '{{mtime|formatEpoch}}'
|
||||
},
|
||||
nameKey: 'path',
|
||||
displayType: 'flat',
|
||||
sortKey: 3
|
||||
},
|
||||
'ansible':
|
||||
{ displayType: 'nested',
|
||||
sortKey: 4
|
||||
{ sortKey: 4
|
||||
},
|
||||
'custom':
|
||||
{ displayType: 'nested'
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
450
awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js
Normal file
450
awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js
Normal file
@ -0,0 +1,450 @@
|
||||
import compareFacts from 'tower/system-tracking/compare-facts/flat';
|
||||
|
||||
/* jshint node: true */
|
||||
/* globals -expect, -_ */
|
||||
|
||||
var _, expect;
|
||||
|
||||
// This makes this test runnable in node OR karma. The sheer
|
||||
// number of times I had to run this test made the karma
|
||||
// workflow just too dang slow for me. Maybe this can
|
||||
// be a pattern going forward? Not sure...
|
||||
//
|
||||
(function(global) {
|
||||
var chai = global.chai || require('chai');
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
var chaiThings = global.chaiThings || require('chai-things');
|
||||
chai.use(chaiThings);
|
||||
}
|
||||
|
||||
_ = global._ || require('lodash');
|
||||
expect = global.expect || chai.expect;
|
||||
|
||||
global.expect = expect;
|
||||
|
||||
|
||||
|
||||
global._ = _;
|
||||
|
||||
})(typeof window === 'undefined' ? global : window);
|
||||
|
||||
describe('CompareFacts.Flat', function() {
|
||||
|
||||
function options(overrides) {
|
||||
return _.merge({}, defaultOptions, overrides);
|
||||
}
|
||||
|
||||
var defaultTemplate =
|
||||
{ hasTemplate: function() { return false; }
|
||||
};
|
||||
|
||||
var defaultOptions =
|
||||
{ factTemplate: defaultTemplate,
|
||||
nameKey: 'name'
|
||||
};
|
||||
|
||||
it('returns empty array with empty basis facts', function() {
|
||||
var result = compareFacts({ facts: [] }, { facts: [] }, defaultOptions);
|
||||
|
||||
expect(result).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('returns empty array when no differences', function() {
|
||||
var result = compareFacts(
|
||||
{ facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar'
|
||||
}]
|
||||
},
|
||||
{ facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar'
|
||||
}]
|
||||
}, options({ nameKey: 'name',
|
||||
compareKey: ['value'],
|
||||
}));
|
||||
|
||||
expect(result).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('returns empty array with multiple compare keys and no differences', function() {
|
||||
var result = compareFacts(
|
||||
{ facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar'
|
||||
}]
|
||||
},
|
||||
{ facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar'
|
||||
}]
|
||||
}, options({ compareKey: ['name', 'value']
|
||||
}));
|
||||
|
||||
expect(result).to.deep.equal([]);
|
||||
});
|
||||
|
||||
context('when both collections contain facts', function() {
|
||||
it('includes each compare key value when a compareKey differs', function() {
|
||||
var result = compareFacts(
|
||||
{ position: 'left',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
},
|
||||
{ position: 'right',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'baz',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
}, options({ compareKey: ['value', 'extra'] }));
|
||||
|
||||
expect(result).to.deep.equal(
|
||||
[{ displayKeyPath: 'foo',
|
||||
nestingLevel: 0,
|
||||
facts:
|
||||
[{ keyName: 'value',
|
||||
value1: 'bar',
|
||||
value2: 'baz',
|
||||
isDivergent: true
|
||||
},
|
||||
{ keyName: 'extra',
|
||||
value1: 'doo',
|
||||
value2: 'doo',
|
||||
isDivergent: false
|
||||
}]
|
||||
}]);
|
||||
});
|
||||
|
||||
it('ignores compare keys with no values in fact', function() {
|
||||
var result = compareFacts(
|
||||
{ position: 'left',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
},
|
||||
{ position: 'right',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'baz',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
}, options({ compareKey: ['value', 'extra', 'blah'] }));
|
||||
|
||||
expect(result).to.deep.equal(
|
||||
[{ displayKeyPath: 'foo',
|
||||
nestingLevel: 0,
|
||||
facts:
|
||||
[{ keyName: 'value',
|
||||
value1: 'bar',
|
||||
value2: 'baz',
|
||||
isDivergent: true
|
||||
},
|
||||
{ keyName: 'extra',
|
||||
value1: 'doo',
|
||||
value2: 'doo',
|
||||
isDivergent: false
|
||||
}]
|
||||
}]);
|
||||
|
||||
});
|
||||
|
||||
it('allows mapping key names with keyNameMap parameter', function() {
|
||||
var keyNameMap =
|
||||
{ 'extra': 'blah'
|
||||
};
|
||||
|
||||
var result = compareFacts(
|
||||
{ position: 'left',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
},
|
||||
{ position: 'right',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'baz',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
}, options({ compareKey: ['value', 'extra', 'blah'],
|
||||
keyNameMap: keyNameMap
|
||||
}));
|
||||
|
||||
expect(result[0].facts).to.include.something.that.deep.equals(
|
||||
{ keyName: 'blah',
|
||||
value1: 'doo',
|
||||
value2: 'doo',
|
||||
isDivergent: false
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('allows flattening values with factTemplate parameter', function() {
|
||||
var factTemplate =
|
||||
{ hasTemplate:
|
||||
function() {
|
||||
return true;
|
||||
},
|
||||
render: function(fact) {
|
||||
return 'value: ' + fact.value;
|
||||
}
|
||||
};
|
||||
|
||||
var result = compareFacts(
|
||||
{ position: 'left',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
},
|
||||
{ position: 'right',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'baz',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
}, options({ compareKey: ['value'],
|
||||
factTemplate: factTemplate
|
||||
}));
|
||||
|
||||
expect(result[0].facts).to.deep.equal(
|
||||
{ keyName: 'foo',
|
||||
value1: 'value: bar',
|
||||
value2: 'value: baz'
|
||||
});
|
||||
});
|
||||
|
||||
it('allows formatting values with factTemplate parameter', function() {
|
||||
var values = ['value1', 'value2'];
|
||||
var factTemplate =
|
||||
{ 'value':
|
||||
{ hasTemplate: function() {
|
||||
return true;
|
||||
},
|
||||
render: function() {
|
||||
return values.shift();
|
||||
}
|
||||
},
|
||||
'extra': true
|
||||
};
|
||||
|
||||
var result = compareFacts(
|
||||
{ position: 'left',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
},
|
||||
{ position: 'right',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'baz',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
}, options({ compareKey: ['value'],
|
||||
factTemplate: factTemplate
|
||||
}));
|
||||
|
||||
expect(result[0].facts).to.include.something.that.deep.equals(
|
||||
{ keyName: 'value',
|
||||
value1: 'value1',
|
||||
value2: 'value2',
|
||||
isDivergent: true
|
||||
},
|
||||
{ keyName: 'extra',
|
||||
value1: 'doo',
|
||||
value2: 'doo',
|
||||
isDivergent: false
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('compares values using the formatted values, not the raw ones', function() {
|
||||
var values = ['value1', 'value2'];
|
||||
var factTemplate =
|
||||
{ 'extra':
|
||||
{ render: function() {
|
||||
return values.shift();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = compareFacts(
|
||||
{ position: 'left',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
},
|
||||
{ position: 'right',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]
|
||||
}, options({ factTemplate: factTemplate,
|
||||
compareKey: ['extra']
|
||||
}));
|
||||
|
||||
expect(result.length).to.be.greaterThan(0);
|
||||
expect(result[0].facts).to.include.something.that.deep.equals(
|
||||
{ keyName: 'extra',
|
||||
value1: 'value1',
|
||||
value2: 'value2',
|
||||
isDivergent: true
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
context('when value for nameKey is present in one collection but not the other', function() {
|
||||
|
||||
function factData(leftFacts) {
|
||||
var facts = [{ position: 'left',
|
||||
facts: leftFacts
|
||||
},
|
||||
{ position: 'right',
|
||||
facts: []
|
||||
}];
|
||||
|
||||
return facts;
|
||||
}
|
||||
|
||||
it('keeps missing values as undefined', function() {
|
||||
|
||||
var facts = factData([{ 'name': 'foo',
|
||||
'value': 'bar'
|
||||
}]);
|
||||
|
||||
var result = compareFacts(facts[0], facts[1],
|
||||
options({ compareKey: ['value']
|
||||
}));
|
||||
|
||||
expect(result).to.deep.equal(
|
||||
[{ displayKeyPath: 'foo',
|
||||
nestingLevel: 0,
|
||||
facts:
|
||||
[{ keyName: 'value',
|
||||
value1: 'bar',
|
||||
value2: undefined,
|
||||
isDivergent: true
|
||||
}]
|
||||
}]);
|
||||
});
|
||||
|
||||
it('still keeps missing values as undefined when using a template', function() {
|
||||
|
||||
var factTemplate =
|
||||
{ hasTemplate:
|
||||
function() {
|
||||
return true;
|
||||
},
|
||||
render:
|
||||
function(fact) {
|
||||
return fact.value;
|
||||
}
|
||||
};
|
||||
|
||||
var facts = factData([{ 'name': 'foo',
|
||||
'value': 'bar'
|
||||
}]);
|
||||
|
||||
var result = compareFacts(facts[0], facts[1],
|
||||
options({ compareKey: ['value'],
|
||||
factTemplate: factTemplate
|
||||
}));
|
||||
|
||||
expect(result).to.deep.equal(
|
||||
[{ displayKeyPath: 'foo',
|
||||
nestingLevel: 0,
|
||||
facts:
|
||||
{ keyName: 'foo',
|
||||
value1: 'bar',
|
||||
value2: undefined
|
||||
}
|
||||
}]);
|
||||
});
|
||||
|
||||
it('includes given compare keys from basisFacts', function() {
|
||||
var facts = factData([{ 'name': 'foo',
|
||||
'value': 'bar',
|
||||
'extra': 'doo'
|
||||
}]);
|
||||
|
||||
var result = compareFacts(facts[0], facts[1],
|
||||
options({ compareKey: ['value', 'extra']
|
||||
}));
|
||||
|
||||
expect(result).to.deep.equal(
|
||||
[{ displayKeyPath: 'foo',
|
||||
nestingLevel: 0,
|
||||
facts:
|
||||
[{ keyName: 'value',
|
||||
value1: 'bar',
|
||||
value2: undefined,
|
||||
isDivergent: true
|
||||
},
|
||||
{ keyName: 'extra',
|
||||
value1: 'doo',
|
||||
value2: undefined,
|
||||
isDivergent: true
|
||||
}]
|
||||
}]);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
context('with factTemplate', function() {
|
||||
var factData;
|
||||
|
||||
beforeEach(function() {
|
||||
factData = [{ position: 'left',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'bar'
|
||||
}]
|
||||
},
|
||||
{ position: 'right',
|
||||
facts:
|
||||
[{ 'name': 'foo',
|
||||
'value': 'baz'
|
||||
}]
|
||||
}];
|
||||
});
|
||||
|
||||
it('renders the template with each provided fact', function() {
|
||||
|
||||
var renderCalledWith = [];
|
||||
var factTemplate =
|
||||
{ render: function(fact) {
|
||||
renderCalledWith.push(fact);
|
||||
},
|
||||
hasTemplate: function() { return true; },
|
||||
template: ""
|
||||
};
|
||||
|
||||
compareFacts(factData[0], factData[1],
|
||||
options({ compareKey: ['value'],
|
||||
factTemplate: factTemplate
|
||||
}));
|
||||
|
||||
expect(renderCalledWith).to.include(factData[0].facts[0]);
|
||||
expect(renderCalledWith).to.include(factData[1].facts[0]);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user