diff options
Diffstat (limited to 'test/test_template.js')
-rw-r--r-- | test/test_template.js | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/test/test_template.js b/test/test_template.js new file mode 100644 index 000000000..16db0179e --- /dev/null +++ b/test/test_template.js @@ -0,0 +1,411 @@ +(function() { + 'use strict'; + /*global window, URITemplate, URITemplate_pre_lib, test, equal, strictEqual, raises */ + // FIXME: v2.0.0 renamce non-camelCase properties to uppercase + /*jshint camelcase: false, loopfunc: true, newcap: false */ + + var levels = { + // http://tools.ietf.org/html/rfc6570#section-1.2 + 'Level 1' : { + expressions : { + 'Simple string expansion' : { + '{var}' : 'value', + '{hello}' : 'Hello%20World%21' + } + }, + values : { + 'var' : 'value', + 'hello' : 'Hello World!' + } + }, + 'Level 2' : { + expressions : { + 'Reserved string expansion' : { + '{+var}' : 'value', + '{+hello}' : 'Hello%20World!', + '{+path}/here' : '/foo/bar/here', + 'here?ref={+path}' : 'here?ref=/foo/bar' + }, + 'Fragment expansion, crosshatch-prefixed' : { + 'X{#var}' : 'X#value', + 'X{#hello}' : 'X#Hello%20World!' + } + }, + values : { + 'var' : 'value', + 'hello' : 'Hello World!', + 'path' : '/foo/bar' + } + }, + 'Level 3' : { + expressions : { + 'String expansion with multiple variables' : { + 'map?{x,y}' : 'map?1024,768', + '{x,hello,y}' : '1024,Hello%20World%21,768' + }, + 'Reserved expansion with multiple variables' : { + '{+x,hello,y}' : '1024,Hello%20World!,768', + '{+path,x}/here' : '/foo/bar,1024/here' + }, + 'Fragment expansion with multiple variables' : { + '{#x,hello,y}' : '#1024,Hello%20World!,768', + '{#path,x}/here' : '#/foo/bar,1024/here' + }, + 'Label expansion, dot-prefixed' : { + 'X{.var}' : 'X.value', + 'X{.x,y}' : 'X.1024.768' + }, + 'Path segments, slash-prefixed' : { + '{/var}' : '/value', + '{/var,x}/here' : '/value/1024/here' + }, + 'Path-style parameters, semicolon-prefixed' : { + '{;x,y}' : ';x=1024;y=768', + '{;x,y,empty}' : ';x=1024;y=768;empty' + }, + 'Form-style query, ampersand-separated' : { + '{?x,y}' : '?x=1024&y=768', + '{?x,y,empty}' : '?x=1024&y=768&empty=' + }, + 'Form-style query continuation' : { + '?fixed=yes{&x}' : '?fixed=yes&x=1024', + '{&x,y,empty}' : '&x=1024&y=768&empty=' + } + }, + values : { + 'var' : 'value', + 'hello' : 'Hello World!', + 'empty' : '', + 'path' : '/foo/bar', + 'x' : '1024', + 'y' : '768' + } + }, + 'Level 4' : { + expressions : { + 'String expansion with value modifiers' : { + '{var:3}' : 'val', + '{var:30}' : 'value', + '{list}' : 'red,green,blue', + '{list*}' : 'red,green,blue', + '{keys}' : 'semi,%3B,dot,.,comma,%2C', + '{keys*}' : 'semi=%3B,dot=.,comma=%2C' + }, + 'Reserved expansion with value modifiers' : { + '{+path:6}/here' : '/foo/b/here', + '{+list}' : 'red,green,blue', + '{+list*}' : 'red,green,blue', + '{+keys}' : 'semi,;,dot,.,comma,,', + '{+keys*}' : 'semi=;,dot=.,comma=,' + }, + 'Fragment expansion with value modifiers' : { + '{#path:6}/here' : '#/foo/b/here', + '{#list}' : '#red,green,blue', + '{#list*}' : '#red,green,blue', + '{#keys}' : '#semi,;,dot,.,comma,,', + '{#keys*}' : '#semi=;,dot=.,comma=,' + }, + 'Label expansion, dot-prefixed' : { + 'X{.var:3}' : 'X.val', + 'X{.list}' : 'X.red,green,blue', + 'X{.list*}' : 'X.red.green.blue', + 'X{.keys}' : 'X.semi,%3B,dot,.,comma,%2C', + 'X{.keys*}' : 'X.semi=%3B.dot=..comma=%2C' + }, + 'Path segments, slash-prefixed' : { + '{/var:1,var}' : '/v/value', + '{/list}' : '/red,green,blue', + '{/list*}' : '/red/green/blue', + '{/list*,path:4}' : '/red/green/blue/%2Ffoo', + '{/keys}' : '/semi,%3B,dot,.,comma,%2C', + '{/keys*}' : '/semi=%3B/dot=./comma=%2C' + }, + 'Path-style parameters, semicolon-prefixed' : { + '{;hello:5}' : ';hello=Hello', + '{;list}' : ';list=red,green,blue', + '{;list*}' : ';list=red;list=green;list=blue', + '{;keys}' : ';keys=semi,%3B,dot,.,comma,%2C', + '{;keys*}' : ';semi=%3B;dot=.;comma=%2C' + }, + + 'Form-style query, ampersand-separated' : { + '{?var:3}' : '?var=val', + '{?list}' : '?list=red,green,blue', + '{?list*}' : '?list=red&list=green&list=blue', + '{?keys}' : '?keys=semi,%3B,dot,.,comma,%2C', + '{?keys*}' : '?semi=%3B&dot=.&comma=%2C' + }, + 'Form-style query continuation' : { + '{&var:3}' : '&var=val', + '{&list}' : '&list=red,green,blue', + '{&list*}' : '&list=red&list=green&list=blue', + '{&keys}' : '&keys=semi,%3B,dot,.,comma,%2C', + '{&keys*}' : '&semi=%3B&dot=.&comma=%2C' + } + }, + values : { + 'var' : 'value', + 'hello' : 'Hello World!', + 'path' : '/foo/bar', + 'list' : ['red', 'green', 'blue'], + 'keys' : { + 'semi' : ';', + 'dot' : '.', + 'comma' : ',' + } + } + }, + // http://tools.ietf.org/html/rfc6570#section-3 + 'Expression Expansion' : { + expressions : { + 'Variable Expansion' : { + '{count}' : 'one,two,three', + '{count*}' : 'one,two,three', + '{/count}' : '/one,two,three', + '{/count*}' : '/one/two/three', + '{;count}' : ';count=one,two,three', + '{;count*}' : ';count=one;count=two;count=three', + '{?count}' : '?count=one,two,three', + '{?count*}' : '?count=one&count=two&count=three', + '{&count*}' : '&count=one&count=two&count=three' + }, + 'Simple String Expansion' : { + '{var}' : 'value', + '{hello}' : 'Hello%20World%21', + '{half}' : '50%25', + 'O{empty}X' : 'OX', + 'O{undef}X' : 'OX', + '{x,y}' : '1024,768', + '{x,hello,y}' : '1024,Hello%20World%21,768', + '?{x,empty}' : '?1024,', + '?{x,undef}' : '?1024', + '?{undef,y}' : '?768', + '{var:3}' : 'val', + '{var:30}' : 'value', + '{list}' : 'red,green,blue', + '{list*}' : 'red,green,blue', + '{keys}' : 'semi,%3B,dot,.,comma,%2C', + '{keys*}' : 'semi=%3B,dot=.,comma=%2C' + }, + 'Reserved Expansion' : { + '{+var}' : 'value', + '{+hello}' : 'Hello%20World!', + '{+half}' : '50%25', + '{base}index' : 'http%3A%2F%2Fexample.com%2Fhome%2Findex', + '{+base}index' : 'http://example.com/home/index', + 'O{+empty}X' : 'OX', + 'O{+undef}X' : 'OX', + '{+path}/here' : '/foo/bar/here', + 'here?ref={+path}' : 'here?ref=/foo/bar', + 'up{+path}{var}/here' : 'up/foo/barvalue/here', + '{+x,hello,y}' : '1024,Hello%20World!,768', + '{+path,x}/here' : '/foo/bar,1024/here', + '{+path:6}/here' : '/foo/b/here', + '{+list}' : 'red,green,blue', + '{+list*}' : 'red,green,blue', + '{+keys}' : 'semi,;,dot,.,comma,,', + '{+keys*}' : 'semi=;,dot=.,comma=,' + }, + 'Fragment Expansion' : { + '{#var}' : '#value', + '{#hello}' : '#Hello%20World!', + '{#half}' : '#50%25', + 'foo{#empty}' : 'foo#', + 'foo{#undef}' : 'foo', + '{#x,hello,y}' : '#1024,Hello%20World!,768', + '{#path,x}/here' : '#/foo/bar,1024/here', + '{#path:6}/here' : '#/foo/b/here', + '{#list}' : '#red,green,blue', + '{#list*}' : '#red,green,blue', + '{#keys}' : '#semi,;,dot,.,comma,,', + '{#keys*}' : '#semi=;,dot=.,comma=,' + }, + 'Label Expansion with Dot-Prefix' : { + '{.who}' : '.fred', + '{.who,who}' : '.fred.fred', + '{.half,who}' : '.50%25.fred', + 'www{.dom*}' : 'www.example.com', + 'X{.var}' : 'X.value', + 'X{.empty}' : 'X.', + 'X{.undef}' : 'X', + 'X{.var:3}' : 'X.val', + 'X{.list}' : 'X.red,green,blue', + 'X{.list*}' : 'X.red.green.blue', + 'X{.keys}' : 'X.semi,%3B,dot,.,comma,%2C', + 'X{.keys*}' : 'X.semi=%3B.dot=..comma=%2C', + 'X{.empty_keys}' : 'X', + 'X{.empty_keys*}' : 'X' + }, + 'Path Segment Expansion' : { + '{/who}' : '/fred', + '{/who,who}' : '/fred/fred', + '{/half,who}' : '/50%25/fred', + '{/who,dub}' : '/fred/me%2Ftoo', + '{/var}' : '/value', + '{/var,empty}' : '/value/', + '{/var,undef}' : '/value', + '{/var,x}/here' : '/value/1024/here', + '{/var:1,var}' : '/v/value', + '{/list}' : '/red,green,blue', + '{/list*}' : '/red/green/blue', + '{/list*,path:4}' : '/red/green/blue/%2Ffoo', + '{/keys}' : '/semi,%3B,dot,.,comma,%2C', + '{/keys*}' : '/semi=%3B/dot=./comma=%2C' + }, + 'Path-Style Parameter Expansion' : { + '{;who}' : ';who=fred', + '{;half}' : ';half=50%25', + '{;empty}' : ';empty', + '{;v,empty,who}' : ';v=6;empty;who=fred', + '{;v,bar,who}' : ';v=6;who=fred', + '{;x,y}' : ';x=1024;y=768', + '{;x,y,empty}' : ';x=1024;y=768;empty', + '{;x,y,undef}' : ';x=1024;y=768', + '{;hello:5}' : ';hello=Hello', + '{;list}' : ';list=red,green,blue', + '{;list*}' : ';list=red;list=green;list=blue', + '{;keys}' : ';keys=semi,%3B,dot,.,comma,%2C', + '{;keys*}' : ';semi=%3B;dot=.;comma=%2C' + }, + 'Form-Style Query Expansion' : { + '{?who}' : '?who=fred', + '{?half}' : '?half=50%25', + '{?x,y}' : '?x=1024&y=768', + '{?x,y,empty}' : '?x=1024&y=768&empty=', + '{?x,y,undef}' : '?x=1024&y=768', + '{?var:3}' : '?var=val', + '{?list}' : '?list=red,green,blue', + '{?list*}' : '?list=red&list=green&list=blue', + '{?keys}' : '?keys=semi,%3B,dot,.,comma,%2C', + '{?keys*}' : '?semi=%3B&dot=.&comma=%2C' + }, + 'Form-Style Query Continuation' : { + '{&who}' : '&who=fred', + '{&half}' : '&half=50%25', + '?fixed=yes{&x}' : '?fixed=yes&x=1024', + '{&x,y,empty}' : '&x=1024&y=768&empty=', + '{&x,y,undef}' : '&x=1024&y=768', + '{&var:3}' : '&var=val', + '{&list}' : '&list=red,green,blue', + '{&list*}' : '&list=red&list=green&list=blue', + '{&keys}' : '&keys=semi,%3B,dot,.,comma,%2C', + '{&keys*}' : '&semi=%3B&dot=.&comma=%2C' + } + }, + values : { + 'count' : ['one', 'two', 'three'], + 'dom' : ['example', 'com'], + 'dub' : 'me/too', + 'hello' : 'Hello World!', + 'half' : '50%', + 'var' : 'value', + 'who' : 'fred', + 'base' : 'http://example.com/home/', + 'path' : '/foo/bar', + 'list' : ['red', 'green', 'blue'], + 'keys' : { + 'semi' : ';', + 'dot' : '.', + 'comma' : ',' + }, + 'v' : '6', + 'x' : '1024', + 'y' : '768', + 'empty' : '', + 'empty_keys' : [], + 'undef' : null + } + } + }; + + module('URITemplate'); + // [].forEach() no IE, lacking interest in polyfilling this... + for (var i in levels) { + (function(level, data){ + test(level, function() { + var combined_expression = '', + combined_expansion = '', + template, expression, expansion; + + for (var type in data.expressions) { + for (expression in data.expressions[type]) { + combined_expression += '/' + expression; + combined_expansion += '/' + data.expressions[type][expression]; + + template = new URITemplate(expression); + expansion = template.expand(data.values); + equal(expansion, data.expressions[type][expression], type + ': ' + expression); + } + } + + template = new URITemplate(combined_expression); + expansion = template.expand(data.values); + equal(expansion, combined_expansion, type + ': combined'); + }); + })(i, levels[i]); + } + test('Data Callbacks', function() { + var template = new URITemplate('{var}'); + var global = function(key) { + var data = {'var': 'hello world.html'}; + return data[key]; + }; + var local = function() { + return 'hello world.html'; + }; + + equal(template.expand(global), 'hello%20world.html', 'global callback'); + equal(template.expand({'var': local}), 'hello%20world.html', 'local callback'); + }); + + test('Parse errors', function() { + raises(function() { + URITemplate('AB{var$}IJ').parse(); + }, Error, 'Failing invalid variable name'); + + raises(function() { + URITemplate('AB{$var}IJ').parse(); + }, Error, 'Failing invalid operator'); + + raises(function() { + URITemplate('AB{var:3IJ').parse(); + }, Error, 'Failing missing closing }'); + + raises(function() { + URITemplate('AB{var:3*}IJ').parse(); + }, Error, 'Failing invalid modifier'); + }); + + test('Expansion errors', function() { + raises(function() { + var data = {'composite_var': ['multiple', 'values']}; + URITemplate('{composite_var:3}').expand(data); + }, Error, 'Failing prefix modifier after composite variable'); + }); + + test('noConflict mode', function() { + var actual_lib = URITemplate; // actual library; after loading, before noConflict() + var unconflicted = URITemplate.noConflict(); + + strictEqual( unconflicted, actual_lib, 'noConflict() returns the URITemplate object' ); + strictEqual( URITemplate, URITemplate_pre_lib, 'noConflict() restores the `URITemplate` variable' ); + + // restore for other tests + window.URITemplate = actual_lib; + }); + + test('Periods in varnames', function() { + var template = new URITemplate('{hello.world.var}'); + var literal = 'replacement'; + var data = {'hello.world.var': literal}; + var expansion = template.expand(data); + equal(expansion, literal, 'period in varname'); + }); + + test('Invalid literals', function () { + raises(function() { + URITemplate('invalid.char}acter').parse(); + }, Error, 'Failing invalid literal'); + }); + +})(); |