catberry
Advanced tools
Comparing version 8.2.0 to 8.3.0
@@ -21,2 +21,3 @@ /** | ||
const routeDefinitions = '__routeDefinitions' || []; | ||
const routeDescriptors = '__routes' || []; | ||
@@ -55,2 +56,5 @@ const Catberry = require('./node_modules/catberry/browser/Catberry.js'); | ||
routeDescriptors.forEach(routeDescriptor => | ||
locator.registerInstance('routeDescriptor', routeDescriptor)); | ||
stores.forEach(store => locator.registerInstance('store', store)); | ||
@@ -57,0 +61,0 @@ |
@@ -24,3 +24,3 @@ 'use strict'; | ||
*/ | ||
this.version = '8.2.0'; | ||
this.version = '8.3.0'; | ||
@@ -27,0 +27,0 @@ /** |
@@ -81,2 +81,13 @@ 'use strict'; | ||
} | ||
/** | ||
* Gets URI for the named route and specified parameters. | ||
* @param {string} name Name of the route. | ||
* @param {Object} values Set of route parameter values. | ||
* @returns {string} URI string. | ||
*/ | ||
getRouteURI(name, values) { | ||
const stateProvider = this.locator.resolve('stateProvider'); | ||
return stateProvider.getRouteURI(name, values); | ||
} | ||
} | ||
@@ -83,0 +94,0 @@ |
@@ -8,2 +8,3 @@ 'use strict'; | ||
const requireHelper = require('../helpers/requireHelper'); | ||
const RouteParser = require('../tokenizers/RouteParser'); | ||
@@ -14,2 +15,3 @@ const BOOTSTRAPPER_FILENAME = 'Bootstrapper.js'; | ||
const COMPONENTS_REPLACE = '/** __components **/'; | ||
const ROUTE_DESCRIPTORS_REPLACE = '\'__routes\''; | ||
const ROUTE_DEFINITIONS_REPLACE = '\'__routeDefinitions\''; | ||
@@ -42,2 +44,9 @@ const ROUTE_DEFINITIONS_FILENAME = 'routes.js'; | ||
this._templateProvider = locator.resolve('templateProvider'); | ||
/** | ||
* Current route parser. | ||
* @type {RouteParser} | ||
* @private | ||
*/ | ||
this._routeParser = new RouteParser(); | ||
} | ||
@@ -85,7 +94,24 @@ | ||
const requireString = isExists ? `require('./${filePath}')` : 'null'; | ||
const routeDescriptors = []; | ||
if (isExists) { | ||
const routeDefinitions = require(routeDefinitionsPath); | ||
/* eslint max-nested-callbacks: 0 */ | ||
routeDefinitions.forEach(definition => { | ||
if (typeof (definition) === 'string') { | ||
routeDescriptors.push(this._routeParser.parseRouteExpression(definition)); | ||
} | ||
if (typeof (definition) === 'object' && | ||
typeof (definition.expression) === 'string') { | ||
routeDescriptors.push(this._routeParser.parseRouteExpression(definition.expression)); | ||
} | ||
}); | ||
} | ||
return context.file | ||
.replace(COMPONENTS_REPLACE, context.components) | ||
.replace(STORES_REPLACE, context.stores) | ||
.replace(ROUTE_DEFINITIONS_REPLACE, requireString); | ||
.replace(ROUTE_DEFINITIONS_REPLACE, requireString) | ||
.replace(ROUTE_DESCRIPTORS_REPLACE, JSON.stringify(routeDescriptors)); | ||
}) | ||
@@ -92,0 +118,0 @@ ) |
@@ -21,3 +21,3 @@ 'use strict'; | ||
${userAgent || 'Unknown browser'};<br/> | ||
Catberry@8.2.0 ( | ||
Catberry@8.3.0 ( | ||
<a href="https://github.com/catberry/catberry/issues" target="_blank"> | ||
@@ -24,0 +24,0 @@ report an issue |
'use strict'; | ||
const routeHelper = require('./../helpers/routeHelper'); | ||
const catberryUri = require('catberry-uri'); | ||
const URI = catberryUri.URI; | ||
const StateProviderBase = require('../base/StateProviderBase'); | ||
const RouteParser = require('../tokenizers/RouteParser'); | ||
@@ -10,65 +9,6 @@ /** | ||
*/ | ||
class StateProvider { | ||
class StateProvider extends StateProviderBase { | ||
/** | ||
* Create a new instance of the state provider. | ||
* @param {ServiceLocator} locator Service locator for resolving URI mappers. | ||
*/ | ||
constructor(locator) { | ||
/** | ||
* Current list of URI mappers. | ||
* @type {Array} | ||
* @private | ||
*/ | ||
this._uriMappers = this._getUriMappers(locator); | ||
} | ||
/** | ||
* Gets a state by the specified location URI. | ||
* @param {URI} location The URI location. | ||
* @returns {Object|null} The state object. | ||
*/ | ||
getStateByUri(location) { | ||
if (this._uriMappers.length === 0) { | ||
return null; | ||
} | ||
location = location.clone(); | ||
location.path = routeHelper.removeEndSlash(location.path); | ||
const state = this._mapState(location); | ||
if (!state) { | ||
return null; | ||
} | ||
// make state object immutable | ||
Object.keys(state).forEach(storeName => Object.freeze(state[storeName])); | ||
Object.freeze(state); | ||
return state; | ||
} | ||
/** | ||
* Maps the state. | ||
* @param {URI} location URI that describes the state. | ||
* @returns {Object|null} The state from URI. | ||
* @private | ||
*/ | ||
_mapState(location) { | ||
var state = null; | ||
this._uriMappers.some(mapper => { | ||
if (mapper.expression.test(location.path)) { | ||
state = mapper.map(location) || Object.create(null); | ||
return true; | ||
} | ||
return false; | ||
}); | ||
return state; | ||
} | ||
/** | ||
* Gets a list of URI mappers. | ||
* Gets a list of route descriptors. | ||
* @param {ServiceLocator} serviceLocator The Service locator | ||
@@ -79,4 +19,5 @@ * for getting route definitions. | ||
*/ | ||
_getUriMappers(serviceLocator) { | ||
const uriMappers = []; | ||
_getRouteDescriptors(serviceLocator) { | ||
const descriptors = []; | ||
const parser = new RouteParser(); | ||
@@ -95,5 +36,3 @@ var routeDefinitions; | ||
if (typeof (route) === 'string') { | ||
const routeUri = new URI(route); | ||
routeUri.path = routeHelper.removeEndSlash(routeUri.path); | ||
uriMappers.push(routeHelper.compileRoute(routeUri)); | ||
descriptors.push(parser.parseRouteExpression(route)); | ||
return; | ||
@@ -104,17 +43,15 @@ } | ||
if (typeof (route) === 'object' && | ||
(typeof (route.expression) === 'string') && | ||
(route.map instanceof Function)) { | ||
typeof (route.expression) === 'string') { | ||
const mapperUri = new URI(route.expression); | ||
mapperUri.path = routeHelper.removeEndSlash(mapperUri.path); | ||
const descriptor = parser.parseRouteExpression(route.expression); | ||
const mapper = routeHelper.compileRoute(mapperUri); | ||
if (typeof (route.name) === 'string') { | ||
descriptor.name = route.name; | ||
} | ||
uriMappers.push({ | ||
expression: mapper.expression, | ||
map: uri => { | ||
const state = mapper.map(uri); | ||
return route.map(state); | ||
} | ||
}); | ||
if (route.map instanceof Function) { | ||
descriptor.map = route.map; | ||
} | ||
descriptors.push(descriptor); | ||
return; | ||
@@ -127,6 +64,6 @@ } | ||
(route.map instanceof Function)) { | ||
uriMappers.push(route); | ||
descriptors.push(route); | ||
} | ||
}); | ||
return uriMappers; | ||
return descriptors; | ||
} | ||
@@ -133,0 +70,0 @@ } |
@@ -195,2 +195,11 @@ 'use strict'; | ||
parameters = parameters || Object.create(null); | ||
const stores = this._storeLoader.getStoresByNames(); | ||
const parameterNames = Object.keys(parameters); | ||
parameterNames.forEach(storeName => { | ||
if (!(storeName in stores)) { | ||
this._eventBus.emit('warn', `Store "${storeName}" does not exist (might be a typo in a route)`); | ||
} | ||
}); | ||
if (!this._lastState) { | ||
@@ -211,3 +220,3 @@ this._currentBasicContext = basicContext; | ||
Object.keys(parameters) | ||
parameterNames | ||
.forEach(storeName => { | ||
@@ -214,0 +223,0 @@ // new parameters were set for store |
{ | ||
"name": "catberry", | ||
"version": "8.2.0", | ||
"version": "8.3.0", | ||
"author": { | ||
@@ -73,2 +73,3 @@ "name": "Denis Rechkunov", | ||
"./lib/providers/ModuleApiProvider.js": "./browser/providers/ModuleApiProvider.js", | ||
"./lib/providers/StateProvider.js": "./browser/providers/StateProvider.js", | ||
"./lib/loaders/ComponentLoader.js": "./browser/loaders/ComponentLoader.js", | ||
@@ -75,0 +76,0 @@ "./lib/loaders/StoreLoader.js": "./browser/loaders/StoreLoader.js", |
@@ -12,3 +12,3 @@ # Catberry | ||
Catberry was developed to help create ["isomorphic/Universal" Web applications](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md#isomorphicuniversal-applications). | ||
Catberry was developed to help create ["isomorphic/Universal" Web applications](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md#isomorphicuniversal-applications). | ||
@@ -45,5 +45,5 @@ Long story short, isomorphic/universal applications are apps that use the same codebase on both the server and client environments to render what the client would see as a "[Single Page Application](http://en.wikipedia.org/wiki/Single_Page_Application)". | ||
* [Catberry Documentation](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md) | ||
* [Get Started Guide](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md#get-started) | ||
* [Plugins and Tools](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md#plugins-and-tools) | ||
* [Catberry Documentation](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md) | ||
* [Get Started Guide](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md#get-started) | ||
* [Plugins and Tools](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md#plugins-and-tools) | ||
* [Catberry's homepage](http://catberry.org) and its [source code](https://github.com/catberry/catberry-homepage) | ||
@@ -57,4 +57,4 @@ * [Todo application](https://github.com/catberry/catberry-todomvc) | ||
* The entire architecture of the framework is built using the [Service Locator](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md#service-locator) pattern – which helps to manage module dependencies and [create plugins](https://github.com/catberry/catberry/) – and [Flux](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md#flux), for the data layer | ||
* [Cat-components](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md#cat-components) – similar to [web-components](http://webcomponents.org/) but organized as directories, can be rendered on the server and published/installed as NPM packages | ||
* The entire architecture of the framework is built using the [Service Locator](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md#service-locator) pattern – which helps to manage module dependencies and [create plugins](https://github.com/catberry/catberry/) – and [Flux](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md#flux), for the data layer | ||
* [Cat-components](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md#cat-components) – similar to [web-components](http://webcomponents.org/) but organized as directories, can be rendered on the server and published/installed as NPM packages | ||
* Catberry builds a bundle for running the application in a browser as a [Single Page Application](http://en.wikipedia.org/wiki/Single_Page_Application) | ||
@@ -71,6 +71,6 @@ * [ES2015/ES6 support](https://nodejs.org/en/docs/es6/) – native on the server/Node.js and using [Babel](http://babeljs.io/) for a browser | ||
* [Handlebars](https://github.com/catberry/catberry-handlebars), [Dust](https://github.com/catberry/catberry-dust) and | ||
[Jade](https://github.com/catberry/catberry-jade) template engines are [officially supported](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md#template-engines) (and you can implement your own provider to support any other) | ||
[Jade](https://github.com/catberry/catberry-jade) template engines are [officially supported](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md#template-engines) (and you can implement your own provider to support any other) | ||
* Efficient DOM event listening using [event delegation](http://davidwalsh.name/event-delegate) | ||
For more details please proceed to [Catberry Documentation](https://github.com/catberry/catberry/blob/8.2.0/docs/index.md). | ||
For more details please proceed to [Catberry Documentation](https://github.com/catberry/catberry/blob/8.3.0/docs/index.md). | ||
@@ -214,5 +214,5 @@ ### Typical Cat-component example | ||
* [Submit a bug or a feature request](https://github.com/catberry/catberry/issues) | ||
* [Submit a PR](https://github.com/catberry/catberry/blob/8.2.0/CONTRIBUTING.md) | ||
* [Submit a PR](https://github.com/catberry/catberry/blob/8.3.0/CONTRIBUTING.md) | ||
* If you like the logo, you might want to buy a Catberry [T-Shirt](http://www.redbubble.com/people/catberryjs/works/14439373-catberry-js-framework-logo?p=t-shirt) or a [sticker](http://www.redbubble.com/people/catberryjs/works/14439373-catberry-js-framework-logo?p=sticker) | ||
Denis Rechkunov <denis.rechkunov@gmail.com> |
@@ -42,2 +42,9 @@ 'use strict'; | ||
}); | ||
describe('#getRouteURI', function() { | ||
it('should call state provider', function() { | ||
assert.strictEqual(api.getRouteURI('name', {some: 'value'}), 'testURI:name:{"some":"value"}'); | ||
}); | ||
}); | ||
describe('#clearFragment', function() { | ||
@@ -90,2 +97,7 @@ it('should clear URI hash', function(done) { | ||
locator.registerInstance('requestRouter', requestRouter); | ||
locator.registerInstance('stateProvider', { | ||
getRouteURI(name, parameters) { | ||
return `testURI:${name}:${JSON.stringify(parameters)}`; | ||
} | ||
}); | ||
@@ -92,0 +104,0 @@ const templateProvider = new UniversalMock(['render']); |
@@ -63,2 +63,62 @@ { | ||
{ | ||
"name": "should return the correct state for correct URI if the route is an object", | ||
"routes": [{ | ||
"expression": "/state/:arg1[Store1, Store2]/:arg2[Store2]?a=:arg3[Store1]&b=:arg4[Store3]" | ||
}], | ||
"uri": "/state/val1/val2?a=val3&b=val4", | ||
"expectedState": { | ||
"Store1": { | ||
"arg1": "val1", | ||
"arg3": "val3" | ||
}, | ||
"Store2": { | ||
"arg1": "val1", | ||
"arg2": "val2" | ||
}, | ||
"Store3": { | ||
"arg4": "val4" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "should return the correct state for correct URI and store names which contains slash", | ||
"routes": [ | ||
"/state/:arg1[group1/Store1, group2/Store2]/:arg2[group2/Store2]?a=:arg3[group1/Store1]&b=:arg4[group3/Store3]" | ||
], | ||
"uri": "/state/val1/val2?a=val3&b=val4", | ||
"expectedState": { | ||
"group1/Store1": { | ||
"arg1": "val1", | ||
"arg3": "val3" | ||
}, | ||
"group2/Store2": { | ||
"arg1": "val1", | ||
"arg2": "val2" | ||
}, | ||
"group3/Store3": { | ||
"arg4": "val4" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "should return the correct state for correct URI and store names which contains dashes", | ||
"routes": [ | ||
"/state/:arg1[group-1/Store1, group-2/Store2]/:arg2[group-2/Store2]?a=:arg3[group-1/Store1]&b=:arg4[group-3/Store3]" | ||
], | ||
"uri": "/state/val1/val2?a=val3&b=val4", | ||
"expectedState": { | ||
"group-1/Store1": { | ||
"arg1": "val1", | ||
"arg3": "val3" | ||
}, | ||
"group-2/Store2": { | ||
"arg1": "val1", | ||
"arg2": "val2" | ||
}, | ||
"group-3/Store3": { | ||
"arg4": "val4" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "should return the state if one query string parameter is not specified", | ||
@@ -299,3 +359,3 @@ "routes": [ | ||
{ | ||
"name": "should support overriding path parameters by query string parameters", | ||
"name": "should support collecting several values into the list", | ||
"routes": [ | ||
@@ -308,3 +368,6 @@ "/state/:arg1[Store1, Store2]/:arg3[Store1]?a=:arg3[Store1]&b=:arg4[Store3]" | ||
"arg1": "val1", | ||
"arg3": "valX" | ||
"arg3": [ | ||
"val2", | ||
"valX" | ||
] | ||
}, | ||
@@ -362,3 +425,3 @@ "Store2": { | ||
"routes": [ | ||
"/state/w:arg1[Store1, Store2]q/q:arg2[Store2]s?a=a:arg3[Store1]z&b=x:arg4[Store3]y" | ||
"/state:noop/w:arg1[Store1, Store2]q/q:arg2[Store2]s?a=a:arg3[Store1]z&b=x:arg4[Store3]y" | ||
], | ||
@@ -397,2 +460,17 @@ "uri": "/state/wq/qs?a=az&b=xy", | ||
{ | ||
"name": "should support parameters without values in query", | ||
"routes": [ | ||
"/state?a:arg1[Store1]&b:arg2[Store2]=x:arg3[Store3]&b=some" | ||
], | ||
"uri": "/state?aval1&bval2", | ||
"expectedState": { | ||
"Store1": { | ||
"arg1": "val1" | ||
}, | ||
"Store2": { | ||
"arg2": "val2" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "should return null if partial parameters are absent in path", | ||
@@ -405,3 +483,209 @@ "routes": [ | ||
} | ||
], | ||
"getRouteURI": [ | ||
{ | ||
"name": "should throw an error when there is no such route", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/:section[Store1, Store2]/:subsection[Store2]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "wrong", | ||
"parameters": { | ||
"section": "test-section", | ||
"subsection": "test-subsection" | ||
} | ||
}, | ||
"expectedError": "There is no such route called \"wrong\"" | ||
}, | ||
{ | ||
"name": "should throw an error when a path parameter has an array value", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/:section[Store1, Store2]/:subsection[Store2]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"section": ["test-section"], | ||
"subsection": "test-subsection" | ||
} | ||
}, | ||
"expectedError": "Array value is not supported for the parameter \"section\"" | ||
}, | ||
{ | ||
"name": "should throw an error when a quern name parameter has an array value", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/some?:qParam1[Store2]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"qParam1": ["test-section"] | ||
} | ||
}, | ||
"expectedError": "Array value is not supported for the parameter \"qParam1\"" | ||
}, | ||
{ | ||
"name": "should paste an empty string when there is no parameter in the path", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/:section[Store1, Store2]/:subsection[Store2]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"subsection": "test-subsection" | ||
} | ||
}, | ||
"expectedURI": "//test-subsection" | ||
}, | ||
{ | ||
"name": "should return URI for path parameters", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/:section[Store1, Store2]/:subsection[Store2]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"section": "test-section", | ||
"subsection": "test-subsection" | ||
} | ||
}, | ||
"expectedURI": "/test-section/test-subsection" | ||
}, | ||
{ | ||
"name": "should encode path parameters", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/:section[Store1, Store2]/:subsection[Store2]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"section": "test/section", | ||
"subsection": "test/subsection" | ||
} | ||
}, | ||
"expectedURI": "/test%2Fsection/test%2Fsubsection" | ||
}, | ||
{ | ||
"name": "should return URI for path and query parameters", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/:param1[Store1, Store2]/:param2[Store2]?:qParam1[Store2]=value&query=:qParam2[Store2]&:qParam3[Store3]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"param1": "value1", | ||
"param2": "value2", | ||
"qParam1": "qValue1", | ||
"qParam2": "qValue2", | ||
"qParam3": "qValue3" | ||
} | ||
}, | ||
"expectedURI": "/value1/value2?qValue1=value&query=qValue2&qValue3" | ||
}, | ||
{ | ||
"name": "should return URI for path and query parameters surrounded by text", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/pa:param1[Store1]th1/pa:param2[Store2]th2?que:qParam1[Store2]ry1=value&query=va:qParam2[Store2]lue1&que:qParam3[Store3]ry2&que:qParam4[Store4]ry3=val:qParam5[Store5]ue2" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"param1": "!value1!", | ||
"param2": "!value2!", | ||
"qParam1": "!qValue1!", | ||
"qParam2": "!qValue2!", | ||
"qParam3": "!qValue3!", | ||
"qParam4": "!qValue4!", | ||
"qParam5": ["!qValue5-1!", "!qValue5-2!", "!qValue5-3!"] | ||
} | ||
}, | ||
"expectedURI": "/pa!value1!th1/pa!value2!th2?que!qValue1!ry1=value&query=va!qValue2!lue1&que!qValue3!ry2&que!qValue4!ry3=val!qValue5-1!ue2&que!qValue4!ry3=val!qValue5-2!ue2&que!qValue4!ry3=val!qValue5-3!ue2" | ||
}, | ||
{ | ||
"name": "should return URI for path and query parameters with array values", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/some?:qParam1[Store2]=:qParam2[Store2]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"qParam1": "qValue1", | ||
"qParam2": ["qValue2-1", "qValue2-2", "qValue2-3"] | ||
} | ||
}, | ||
"expectedURI": "/some?qValue1=qValue2-1&qValue1=qValue2-2&qValue1=qValue2-3" | ||
}, | ||
{ | ||
"name": "should return URI for path and optional query parameters", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/:param1[Store1, Store2]/:param2[Store2]?:qParam1[Store2]=value&query=:qParam2[Store2]&:qParam3[Store3]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": { | ||
"param1": "value1", | ||
"param2": "value2", | ||
"qParam2": "qValue2" | ||
} | ||
}, | ||
"expectedURI": "/value1/value2?query=qValue2" | ||
}, | ||
{ | ||
"name": "should return URI without query string if parameters=undefined for optional parameters", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/some?:qParam1[Store2]=value&query=:qParam2[Store2]&:qParam3[Store3]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test" | ||
}, | ||
"expectedURI": "/some" | ||
}, | ||
{ | ||
"name": "should return URI without query parameter if the value was not specified", | ||
"routes": [ | ||
{ | ||
"name": "test", | ||
"expression": "/some?qParam=:qValue[Store]" | ||
} | ||
], | ||
"arguments": { | ||
"name": "test", | ||
"parameters": {} | ||
}, | ||
"expectedURI": "/some" | ||
} | ||
] | ||
} |
@@ -26,2 +26,7 @@ 'use strict'; | ||
locator.registerInstance('serviceLocator', locator); | ||
locator.registerInstance('stateProvider', { | ||
getRouteURI(name, parameters) { | ||
return `testURI:${name}:${JSON.stringify(parameters)}`; | ||
} | ||
}); | ||
locator.registerInstance('eventBus', new events.EventEmitter()); | ||
@@ -133,2 +138,8 @@ api = new ModuleApiProvider(locator); | ||
describe('#getRouteURI', function() { | ||
it('should call state provider', function() { | ||
assert.strictEqual(api.getRouteURI('name', {some: 'value'}), 'testURI:name:{"some":"value"}'); | ||
}); | ||
}); | ||
describe('#clearFragment', function(done) { | ||
@@ -135,0 +146,0 @@ it('should save flag that hash has been cleared', function() { |
@@ -44,3 +44,32 @@ 'use strict'; | ||
}); | ||
it('should throw an error in case of wrong syntax', function() { | ||
const locator = createLocator([ | ||
'/:wrong[some' | ||
]); | ||
assert.throws(() => { | ||
const provider = new StateProvider(locator); | ||
}, /Illegal/); | ||
}); | ||
}); | ||
describe('#getRouteURI', function() { | ||
testCases.getRouteURI.forEach(testCase => { | ||
it(testCase.name, function() { | ||
const locator = createLocator(testCase.routes); | ||
const provider = new StateProvider(locator); | ||
if (testCase.expectedError) { | ||
assert.throws( | ||
() => provider.getRouteURI(testCase.arguments.name, testCase.arguments.parameters), | ||
error => error.message === testCase.expectedError | ||
); | ||
} else { | ||
const uri = provider.getRouteURI(testCase.arguments.name, testCase.arguments.parameters); | ||
assert.strictEqual(uri, testCase.expectedURI); | ||
} | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -52,2 +81,5 @@ | ||
routeDefinitions.forEach(function(routeDefinition) { | ||
if (typeof (routeDefinition) === 'object' && typeof (routeDefinition.expression) === 'string') { | ||
routeDefinition.map = state => state; | ||
} | ||
locator.registerInstance('routeDefinition', routeDefinition); | ||
@@ -54,0 +86,0 @@ }); |
@@ -584,2 +584,31 @@ 'use strict'; | ||
}); | ||
it('should trigger warning if the store does not exist', function(done) { | ||
const stores = { | ||
store: { | ||
name: 'store', | ||
constructor: storeMocks.SyncDataStore | ||
} | ||
}; | ||
const locator = createLocator(stores); | ||
const eventBus = locator.resolve('eventBus'); | ||
const dispatcher = locator.resolve('storeDispatcher'); | ||
const initState = { | ||
wrong: {} | ||
}; | ||
eventBus | ||
.once('error', done) | ||
.once('warn', message => { | ||
try { | ||
assert.strictEqual(message, 'Store "wrong" does not exist (might be a typo in a route)'); | ||
done(); | ||
} catch (e) { | ||
done(e); | ||
} | ||
}); | ||
dispatcher.setState(initState, context); | ||
}); | ||
}); | ||
@@ -586,0 +615,0 @@ |
'use strict'; | ||
const assert = require('assert'); | ||
const tests = require('../../cases/lib/streams/HTMLTagTokenizer.json'); | ||
const tests = require('../../cases/lib/tokenizers/HTMLTagTokenizer.json'); | ||
const HTMLTagTokenizer = require('../../../lib/tokenizers/HTMLTagTokenizer'); | ||
@@ -6,0 +6,0 @@ |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
472966
186
15736
15