Skip to content

Commit

Permalink
fix(lazyLoad): StateBuilder should not mutate the state declaration
Browse files Browse the repository at this point in the history
Fixed repeated {remainder:any} params error when future state is registered repeatedly. This scenario is typically happened during unit test.

Related: 3cd5a2a#r31260154
  • Loading branch information
JLHwung committed Nov 29, 2018
1 parent 404dd31 commit 1478a3c
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 6 deletions.
15 changes: 9 additions & 6 deletions src/state/stateBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @publicapi @module state */ /** */
import { applyPairs, extend, identity, inherit, mapObj, noop, Obj, omit, tail, values } from '../common/common';
import { applyPairs, extend, identity, inherit, mapObj, noop, Obj, omit, tail, values, copy } from '../common/common';
import { isArray, isDefined, isFunction, isString } from '../common/predicates';
import { stringify } from '../common/strings';
import { is, pattern, pipe, prop, val } from '../common/hof';
Expand Down Expand Up @@ -57,17 +57,20 @@ function dataBuilder(state: StateObject) {

const getUrlBuilder = ($urlMatcherFactoryProvider: UrlMatcherFactory, root: () => StateObject) =>
function urlBuilder(stateObject: StateObject) {
const state: StateDeclaration = stateObject.self;
let stateDec: StateDeclaration = stateObject.self;

// For future states, i.e., states whose name ends with `.**`,
// match anything that starts with the url prefix
if (state && state.url && state.name && state.name.match(/\.\*\*$/)) {
state.url += '{remainder:any}'; // match any path (.*)
if (stateDec && stateDec.url && stateDec.name && stateDec.name.match(/\.\*\*$/)) {
const newStateDec: StateDeclaration = {};
copy(stateDec, newStateDec);
newStateDec.url += '{remainder:any}'; // match any path (.*)
stateDec = newStateDec;
}

const parent = stateObject.parent;
const parsed = parseUrl(state.url);
const url = !parsed ? state.url : $urlMatcherFactoryProvider.compile(parsed.val, { state });
const parsed = parseUrl(stateDec.url);
const url = !parsed ? stateDec.url : $urlMatcherFactoryProvider.compile(parsed.val, { state: stateDec });

if (!url) return null;
if (!$urlMatcherFactoryProvider.isMatcher(url)) throw new Error(`Invalid url '${url}' in state '${stateObject}'`);
Expand Down
6 changes: 6 additions & 0 deletions test/lazyLoadSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ describe('future state', function() {
expect($registry.get(state)).toBe(statedef);
});

it('should not change the url of future states', () => {
const statedef = { name: 'future.**', url: '/future' };
const state = $registry.register(statedef);
expect($registry.get(state).url).toBe('/future');
});

it('should replace a future state when a normal state of the same name is registered', () => {
const state = $registry.register({ name: 'future.**' });

Expand Down

0 comments on commit 1478a3c

Please sign in to comment.