UNPKG

bali-component-framework

Version:

This library provides a JavaScript based implementation of the Bali Nebula™ Component Framework.

538 lines (464 loc) 25.5 kB
/************************************************************************ * Copyright (c) Crater Dog Technologies(TM). All Rights Reserved. * ************************************************************************ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * * * This code is free software; you can redistribute it and/or modify it * * under the terms of The MIT License (MIT), as published by the Open * * Source Initiative. (See http://opensource.org/licenses/MIT) * ************************************************************************/ const debug = 0; const mocha = require('mocha'); const expect = require('chai').expect; const bali = require('../').api(); const comparator = bali.comparator(debug); describe('Bali Nebula™ Component Framework - Comparator', function() { describe('Test undefined comparisons', function() { it('should handle two undefined objects', function() { expect(comparator.ranking()).to.equal(0); }); it('should handle one undefined object', function() { expect(comparator.ranking('foobar')).to.equal(1); expect(comparator.ranking(undefined, 'foobar')).to.equal(-1); }); it('should compare patterns for equality', function() { expect(comparator.areEqual(bali.pattern(), bali.pattern.NONE)).to.equal(true); expect(comparator.areEqual(bali.pattern.NONE, bali.component('none'))).to.equal(true); expect(comparator.areEqual(bali.pattern.ANY, bali.component('any'))).to.equal(true); }); }); describe('Test the comparator doesMatch method', function() { it('the none pattern should only match the none pattern', function() { expect(comparator.doesMatch(bali.pattern(), bali.pattern.NONE)).to.equal(true); expect(comparator.doesMatch(bali.pattern('^none$'), bali.pattern.NONE)).to.equal(true); expect(comparator.doesMatch(bali.pattern.NONE, bali.pattern.NONE)).to.equal(true); }); it('nothing else should match the none pattern', function() { expect(comparator.doesMatch(bali.pattern.ANY, bali.pattern.NONE)).to.equal(false); expect(comparator.doesMatch(bali.text('any'), bali.pattern.NONE)).to.equal(false); expect(comparator.doesMatch(bali.text('none'), bali.pattern.NONE)).to.equal(false); expect(comparator.doesMatch(bali.text('foobar'), bali.pattern.NONE)).to.equal(false); }); it('should match the any pattern', function() { expect(comparator.doesMatch(bali.pattern(), bali.pattern.ANY)).to.equal(true); expect(comparator.doesMatch(bali.pattern.NONE, bali.pattern.ANY)).to.equal(true); expect(comparator.doesMatch(bali.pattern.ANY, bali.pattern.ANY)).to.equal(true); expect(comparator.doesMatch(bali.text('any'), bali.pattern.ANY)).to.equal(true); expect(comparator.doesMatch(bali.text('none'), bali.pattern.ANY)).to.equal(true); expect(comparator.doesMatch(bali.text('foobar'), bali.pattern.ANY)).to.equal(true); }); it('should match matching patterns', function() { expect(comparator.doesMatch(bali.text('foobar'), bali.text('foobar'))).to.equal(true); expect(comparator.doesMatch(bali.range(1, '..', 5), bali.range(1, '..', 5))).to.equal(true); expect(comparator.doesMatch(bali.list(['"foo"', '"bar"', '"baz"']), bali.list([bali.pattern('^"fo+"')]))).to.equal(true); expect(comparator.doesMatch(bali.catalog({ $foo: '"bar"', $bar: '"baz"', $baz: '"foo"' }), bali.catalog({ $baz: '"foo"', $foo: 'any' // should match (order doesn't matter) }))).to.equal(true); expect(comparator.doesMatch(bali.catalog({ $foo: [1, 2, 3], $bar: { $alpha: '$a', $omega: 'none', $beta: '$b', $delta: '$d', $theta: 'none' } }), bali.catalog({ $foo: [2], $bar: { $delta: '$d', $theta: 'none', // should match since the actual value is also 'none' $beta: 'any', // should match (order doesn't matter) $epsilon: 'any', // should match even if the actual value doesn't exist $omega: 'any', // should match even if the actual value is 'none' $gamma: 'none' // should match since there is no actual value for that key } }))).to.equal(true); }); it('should not match mismatched patterns', function() { expect(comparator.doesMatch(bali.text('foobar'), bali.text('foobaz'))).to.equal(false); expect(comparator.doesMatch(bali.range(1, '..', 5), bali.range(0, '..', 5))).to.equal(false); expect(comparator.doesMatch(bali.list(['"foo"', '"bar"', '"baz"']), bali.list([bali.pattern('bo+')]))).to.equal(false); expect(comparator.doesMatch(bali.catalog({ $foo: '"bar"', $bar: '"baz"', $baz: '"foo"' }), bali.catalog({ $baz: '"foo"', $foo: 'none' // should fail since there is an actual value for that key }))).to.equal(false); expect(comparator.doesMatch(bali.catalog({ $foo: [1, 2, 3], $bar: { $alpha: '$a', $beta: '$b', $delta: '$d' } }), bali.catalog({ $foo: [4], $bar: { $beta: '$b', $gamma: '$g', // should fail since there is not actual value for that key $delta: '$d' } }))).to.equal(false); }); }); describe('Test numeric comparisons', function() { const angle = bali.angle.PI; const number = bali.number(3, 4); const percentage = bali.percentage(25); const probability = bali.probability(0.5); expect(comparator.getHash()).to.exist; it('should handle angles', function() { expect(comparator.ranking(angle, angle)).to.equal(0); expect(comparator.ranking(angle, number)).to.equal(-1); expect(comparator.ranking(angle, percentage)).to.equal(-1); expect(comparator.ranking(angle, probability)).to.equal(-1); }); it('should handle numbers', function() { expect(comparator.ranking(number, angle)).to.equal(1); expect(comparator.ranking(number, number)).to.equal(0); expect(comparator.ranking(number, percentage)).to.equal(-1); expect(comparator.ranking(number, probability)).to.equal(-1); }); it('should handle percentages', function() { expect(comparator.ranking(percentage, angle)).to.equal(1); expect(comparator.ranking(percentage, number)).to.equal(1); expect(comparator.ranking(percentage, percentage)).to.equal(0); expect(comparator.ranking(percentage, probability)).to.equal(-1); }); it('should handle probabilities', function() { expect(comparator.ranking(probability, angle)).to.equal(1); expect(comparator.ranking(probability, number)).to.equal(1); expect(comparator.ranking(probability, percentage)).to.equal(1); expect(comparator.ranking(probability, probability)).to.equal(0); }); }); describe('Test boolean comparisons', function() { it('should handle probabilities', function() { const probability = bali.probability(0.5); expect(comparator.ranking(probability, true)).to.equal(1); expect(comparator.ranking(true, probability)).to.equal(-1); expect(comparator.ranking(probability, false)).to.equal(1); expect(comparator.ranking(false, probability)).to.equal(-1); }); }); describe('Test string comparisons', function() { it('should handle angles', function() { const angle = bali.angle.PI; expect(comparator.ranking(angle, '~π')).to.equal(0); expect(comparator.ranking('~0', angle)).to.equal(-1); }); it('should handle binaries', function() { const binary = bali.binary(Buffer.from([1, 2, 3, 4])); expect(comparator.ranking(binary, "'0410610'")).to.equal(0); expect(comparator.ranking("'0410618'", binary)).to.equal(1); }); it('should handle durations', function() { const duration = bali.duration('~P1W'); expect(comparator.ranking(duration, '~P1D')).to.equal(1); expect(comparator.ranking('~PT1H', duration)).to.equal(-1); }); it('should handle moments', function() { const moment = bali.moment('2020-04-01T13:24:56.789'); expect(comparator.ranking(moment, '<2020-04-01T13:24:56.789>')).to.equal(0); expect(comparator.ranking('<2020-04-01T13:24:56.790>', moment)).to.equal(1); }); it('should handle names', function() { const name = bali.name(['bali', 'collections', 'Set', 'v1']); expect(comparator.ranking(name, '/nebula/collections/Set/v2')).to.equal(-1); expect(comparator.ranking('/nebula/collections/Stack/v1', name)).to.equal(1); }); it('should handle numbers', function() { const number = bali.number(3, 4); expect(comparator.ranking(number, '(3, 4i)')).to.equal(0); expect(comparator.ranking('(3, 5i)', number)).to.equal(1); }); it('should handle patterns', function() { const pattern = bali.pattern(); expect(comparator.ranking(pattern, '"^none$"?')).to.equal(0); expect(comparator.ranking('any', pattern)).to.equal(-1); }); it('should handle percentages', function() { const percentage = bali.percentage(25); expect(comparator.ranking(percentage, '25%')).to.equal(0); expect(comparator.ranking('5%', percentage)).to.equal(-1); }); it('should handle probabilities', function() { const probability = bali.probability(0.5); expect(comparator.ranking(probability, 'false')).to.equal(1); expect(comparator.ranking('true', probability)).to.equal(-1); }); it('should handle ranges', function() { const range = bali.range(); expect(comparator.ranking(range, '[..0]')).to.equal(1); expect(comparator.ranking('[..0]', range)).to.equal(-1); expect(comparator.ranking(range, '[0..]')).to.equal(-1); expect(comparator.ranking('[0..]', range)).to.equal(1); }); it('should handle resources', function() { const resource = bali.resource('https://google.com'); expect(comparator.ranking(resource, '<https://amazon.com>')).to.equal(1); expect(comparator.ranking('<https://apple.com>', resource)).to.equal(-1); }); it('should handle procedures', function() { const procedure = bali.component('{ $foo := "bar" }'); expect(comparator.ranking(procedure, '{ }')).to.equal(1); expect(comparator.ranking('{ break loop }', procedure)).to.equal(-1); }); it('should handle symbols', function() { const symbol = bali.symbol('foobar'); expect(comparator.ranking(symbol, '$foobar')).to.equal(0); expect(comparator.ranking('$foobaz', symbol)).to.equal(1); }); it('should handle tags', function() { const tag = bali.tag('34VWNHPBAC8MH89L727W3VGYYVGC7CRK'); expect(comparator.ranking(tag, 'YF79WQV7NTWH4FGA2JW12GVGHYBJWAYG')).to.equal(-1); expect(comparator.ranking('GC95LWMGL87XQMVG5NNZ4NL31CWYVTXH', tag)).to.equal(1); }); it('should handle text', function() { const text = bali.text('foobar'); expect(comparator.ranking(text, 'foobar')).to.equal(0); expect(comparator.ranking('foobaz', text)).to.equal(1); }); it('should handle versions', function() { const version = bali.version([1, 2, 3]); expect(comparator.ranking(version, 'v1.2')).to.equal(1); expect(comparator.ranking('v1.2.3.4', version)).to.equal(1); }); }); describe('Test array comparisons', function() { it('should handle numbers', function() { const array = [1, 2, 3]; expect(comparator.ranking(array, [1, 3])).to.equal(-1); expect(comparator.ranking(array, array)).to.equal(0); expect(comparator.ranking([1, 2, 3, 4], array)).to.equal(1); }); it('should handle strings', function() { const array = ['alpha', 'beta', 'gamma']; expect(comparator.ranking(array, ['alpha', 'delta'])).to.equal(-1); expect(comparator.ranking(array, array)).to.equal(0); expect(comparator.ranking(['alpha', 'beta', 'delta', 'gamma'], array)).to.equal(-1); }); }); describe('Test composite comparisons', function() { it('should handle Bali exceptions', function() { const bad = bali.exception({ $text: 'Something bad happened.' }); const worse = bali.exception({ $text: 'Something worse happened.' }); expect(comparator.ranking(bad, worse)).to.equal(-1); expect(comparator.ranking(bad, bad)).to.equal(0); expect(comparator.ranking(worse, bad)).to.equal(1); }); it('should handle procedures', function() { const bar = bali.component('{ $foo := "bar" }'); const baz = bali.component('{ $foo := "baz" }'); expect(comparator.ranking(bar, baz)).to.equal(-1); expect(comparator.ranking(bar, bar)).to.equal(0); expect(comparator.ranking(baz, bar)).to.equal(1); }); it('should handle associations', function() { const foobar = bali.association('$foo', "bar"); const foobaz = bali.association('$foo', "baz"); const footbar = bali.association('$foot', "bar"); const footbaz = bali.association('$foot', "baz"); expect(comparator.ranking(foobar, foobar)).to.equal(0); expect(comparator.ranking(foobar, foobaz)).to.equal(-1); expect(comparator.ranking(foobar, footbar)).to.equal(-1); expect(comparator.ranking(foobar, footbaz)).to.equal(-1); expect(comparator.ranking(foobaz, foobar)).to.equal(1); expect(comparator.ranking(foobaz, footbar)).to.equal(-1); expect(comparator.ranking(foobaz, footbaz)).to.equal(-1); expect(comparator.ranking(footbar, foobar)).to.equal(1); expect(comparator.ranking(footbar, foobaz)).to.equal(1); expect(comparator.ranking(footbar, footbaz)).to.equal(-1); expect(comparator.ranking(footbaz, foobar)).to.equal(1); expect(comparator.ranking(footbaz, foobaz)).to.equal(1); expect(comparator.ranking(footbaz, footbar)).to.equal(1); }); }); describe('Test collection comparisons', function() { it('should handle lists', function() { const short = bali.list([1, 2]); const medium = bali.list([1, 2, 3]); const next = bali.list([1, 2, 4]); const long = bali.list([1, 2, 3, 4]); expect(comparator.ranking(short, short)).to.equal(0); expect(comparator.ranking(short, medium)).to.equal(-1); expect(comparator.ranking(short, next)).to.equal(-1); expect(comparator.ranking(short, long)).to.equal(-1); expect(comparator.ranking(medium, short)).to.equal(1); expect(comparator.ranking(medium, next)).to.equal(-1); expect(comparator.ranking(medium, long)).to.equal(-1); expect(comparator.ranking(next, short)).to.equal(1); expect(comparator.ranking(next, medium)).to.equal(1); expect(comparator.ranking(next, long)).to.equal(1); expect(comparator.ranking(long, short)).to.equal(1); expect(comparator.ranking(long, medium)).to.equal(1); expect(comparator.ranking(long, next)).to.equal(-1); }); it('should handle catalogs', function() { const short = bali.catalog({$alpha: 1, $beta: 2}); const medium = bali.catalog({$alpha: 1, $beta: 2, $gamma: 3}); const next = bali.catalog({$alpha: 1, $beta: 2, $gamma: 4}); const long = bali.catalog({$alpha: 1, $beta: 2, $gamma: 3, $delta: 4}); expect(comparator.ranking(short, short)).to.equal(0); expect(comparator.ranking(short, medium)).to.equal(-1); expect(comparator.ranking(short, next)).to.equal(-1); expect(comparator.ranking(short, long)).to.equal(-1); expect(comparator.ranking(medium, short)).to.equal(1); expect(comparator.ranking(medium, next)).to.equal(-1); expect(comparator.ranking(medium, long)).to.equal(-1); expect(comparator.ranking(next, short)).to.equal(1); expect(comparator.ranking(next, medium)).to.equal(1); expect(comparator.ranking(next, long)).to.equal(1); expect(comparator.ranking(long, short)).to.equal(1); expect(comparator.ranking(long, medium)).to.equal(1); expect(comparator.ranking(long, next)).to.equal(-1); }); }); describe('Test element comparisons', function() { it('should handle angles', function() { const first = bali.angle(); const second = bali.angle.PI; expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle binaries', function() { const first = bali.binary(Buffer.from([1, 2, 3, 4])); const second = bali.binary(Buffer.from([1, 2, 4])); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle durations', function() { const first = bali.duration('~P1W'); const second = bali.duration('~P1M'); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle moments', function() { const first = bali.moment('2020-04-01T13:24:56.789'); const second = bali.moment('2020-04-01T13:24:56.790'); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle names', function() { const first = bali.name(['bali', 'collections', 'Set', 'v2']); const second = bali.name(['bali', 'collections', 'Stack', 'v1']); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle numbers', function() { const first = bali.number(3, 4); const second = bali.number(3, 5); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle patterns', function() { const first = bali.pattern.ANY; const second = bali.pattern.NONE; expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle percentages', function() { const first = bali.percentage(25); const second = bali.percentage(75); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle probabilities', function() { const first = bali.probability.IMPOSSIBLE; const second = bali.probability(0.5); const third = bali.probability.CERTAIN; expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); expect(comparator.ranking(second, second)).to.equal(0); expect(comparator.ranking(second, third)).to.equal(-1); expect(comparator.ranking(third, second)).to.equal(1); expect(comparator.ranking(third, third)).to.equal(0); expect(comparator.ranking(third, first)).to.equal(1); expect(comparator.ranking(first, third)).to.equal(-1); }); it('should handle ranges', function() { const first = bali.range(undefined, '..', 0); const second = bali.range(); const third = bali.range(0); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); expect(comparator.ranking(second, second)).to.equal(0); expect(comparator.ranking(second, third)).to.equal(-1); expect(comparator.ranking(third, second)).to.equal(1); expect(comparator.ranking(third, third)).to.equal(0); expect(comparator.ranking(third, first)).to.equal(1); expect(comparator.ranking(first, third)).to.equal(-1); }); it('should handle resources', function() { const first = bali.resource('https://apple.com'); const second = bali.resource('https://google.com'); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle procedures', function() { const first = bali.component('{ $foo := "bar" }'); const second = bali.component('{ $foo := "baz" }'); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle symbols', function() { const first = bali.symbol('foobar'); const second = bali.symbol('foobaz'); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle tags', function() { const first = bali.tag('34VWNHPBAC8MH89L727W3VGYYVGC7CRK'); const second = bali.tag('LSK9A6TQYW0X5RZTY7TCAWT9R9KFNNTP'); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle text', function() { const first = bali.text('foobar'); const second = bali.text('foobaz'); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); }); it('should handle versions', function() { const first = bali.version([1, 2]); const second = bali.version([1, 3]); const third = bali.version([1, 3, 1]); expect(comparator.ranking(first, first)).to.equal(0); expect(comparator.ranking(first, second)).to.equal(-1); expect(comparator.ranking(second, first)).to.equal(1); expect(comparator.ranking(second, second)).to.equal(0); expect(comparator.ranking(second, third)).to.equal(-1); expect(comparator.ranking(third, second)).to.equal(1); expect(comparator.ranking(third, third)).to.equal(0); expect(comparator.ranking(third, first)).to.equal(1); expect(comparator.ranking(first, third)).to.equal(-1); }); }); });