Skip to content

Commit 5446cc7

Browse files
test(statehelper): Split out specs for stateBuilder, stateMatcher, TargetState
1 parent c927d4e commit 5446cc7

File tree

3 files changed

+156
-146
lines changed

3 files changed

+156
-146
lines changed

test/stateBuilderSpec.ts

+79-146
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { StateMatcher, StateBuilder, UrlMatcher, TargetState, extend } from "../src/index";
1+
import { StateMatcher, StateBuilder, UrlMatcher, extend } from "../src/index";
22
import { ParamTypes } from "../src/params/paramTypes";
33

4-
var paramTypes = new ParamTypes();
5-
describe('state helpers', function() {
4+
let paramTypes = new ParamTypes();
5+
describe('StateBuilder', function() {
66

7-
var states;
7+
let states;
88

99
beforeEach(function() {
1010
states = {};
@@ -31,173 +31,106 @@ describe('state helpers', function() {
3131
};
3232
});
3333

34-
describe('StateMatcher', function() {
35-
it('should find states by name', function() {
36-
var states = {}, matcher = new StateMatcher(states), home = { name: 'home' };
37-
expect(matcher.find('home')).toBeUndefined();
34+
let builder, matcher, urlMatcherFactoryProvider: any = {
35+
compile: function() {},
36+
isMatcher: function() {}
37+
};
3838

39-
states['home'] = home;
40-
expect(matcher.find('home')).toBe(home);
41-
expect(matcher.find(home)).toBe(home);
42-
43-
expect(matcher.find('home.about')).toBeUndefined();
44-
45-
states['home.about'] = { name: 'home.about' };
46-
expect(matcher.find('home.about')).toEqual({ name: 'home.about' });
47-
48-
expect(matcher.find(undefined)).toBeUndefined();
49-
expect(matcher.find('')).toBeUndefined();
50-
expect(matcher.find(null)).toBeUndefined();
51-
});
52-
53-
it('should determine whether a path is relative', function() {
54-
var matcher = new StateMatcher({});
55-
expect(matcher.isRelative('.')).toBe(true);
56-
expect(matcher.isRelative('.foo')).toBe(true);
57-
expect(matcher.isRelative('^')).toBe(true);
58-
expect(matcher.isRelative('^foo')).toBe(true);
59-
expect(matcher.isRelative('^.foo')).toBe(true);
60-
expect(matcher.isRelative('foo')).toBe(false);
61-
});
62-
63-
it('should resolve relative paths', function() {
64-
var matcher = new StateMatcher(states);
65-
66-
expect(matcher.find('.', states['home.about'])).toBe(states['home.about']);
67-
expect(matcher.find('^', states['home.about'])).toBe(states.home);
68-
expect(matcher.find('^.company', states['home.about.people'])).toBe(states['home.about.company']);
69-
expect(matcher.find('^.^.company', states['home.about.people.person'])).toBe(states['home.about.company']);
70-
expect(matcher.find('^.foo', states.home)).toBeUndefined();
71-
expect(matcher.find('^.other.foo', states.home)).toBe(states['other.foo']);
72-
expect(function() { matcher.find('^.^', states.home); }).toThrowError(Error, "Path '^.^' not valid for state 'home'");
73-
});
39+
beforeEach(function() {
40+
matcher = new StateMatcher(states);
41+
builder = new StateBuilder(matcher, urlMatcherFactoryProvider);
42+
builder.builder('views', (state, parent) => { return state.views || { $default: {} }; });
43+
// builder.builder('resolve', uiRouter.ng1ResolveBuilder);
7444
});
7545

76-
describe('StateBuilder', function() {
77-
var builder, matcher, urlMatcherFactoryProvider: any = {
78-
compile: function() {},
79-
isMatcher: function() {}
80-
};
81-
82-
beforeEach(function() {
83-
matcher = new StateMatcher(states);
84-
builder = new StateBuilder(matcher, urlMatcherFactoryProvider);
85-
builder.builder('views', (state, parent) => { return state.views || { $default: {} }; });
86-
// builder.builder('resolve', uiRouter.ng1ResolveBuilder);
87-
});
88-
89-
describe('interface', function() {
90-
describe('name()', function() {
91-
it('should return dot-separated paths', function() {
92-
expect(builder.name(states['home.about.people'])).toBe('home.about.people');
93-
expect(builder.name(states['home.about'])).toBe('home.about');
94-
expect(builder.name(states['home'])).toBe('home');
95-
});
96-
97-
it('should concatenate parent names', function() {
98-
expect(builder.name({ name: "bar", parent: "foo" })).toBe("foo.bar");
99-
expect(builder.name({ name: "bar", parent: { name: "foo" } })).toBe("foo.bar");
100-
});
46+
describe('interface', function() {
47+
describe('name()', function() {
48+
it('should return dot-separated paths', function() {
49+
expect(builder.name(states['home.about.people'])).toBe('home.about.people');
50+
expect(builder.name(states['home.about'])).toBe('home.about');
51+
expect(builder.name(states['home'])).toBe('home');
10152
});
10253

103-
describe('parentName()', function() {
104-
it('should parse dot-separated paths', function() {
105-
expect(builder.parentName(states['other.foo.bar'])).toBe('other.foo');
106-
});
107-
it('should always return parent name as string', function() {
108-
expect(builder.parentName(states['other.foo'])).toBe('other');
109-
});
110-
it('should return empty string if state has no parent', function() {
111-
expect(builder.parentName(states[''])).toBe("");
112-
});
113-
it('should error if parent: is specified *AND* the state name has a dot (.) in it', function() {
114-
expect(() => builder.parentName(states['home.error'])).toThrowError();
115-
});
54+
it('should concatenate parent names', function() {
55+
expect(builder.name({ name: "bar", parent: "foo" })).toBe("foo.bar");
56+
expect(builder.name({ name: "bar", parent: { name: "foo" } })).toBe("foo.bar");
11657
});
11758
});
11859

119-
describe('state building', function() {
120-
it('should build parent property', function() {
121-
expect(builder.builder('parent')({ name: 'home.about' })).toBe(states['home']);
60+
describe('parentName()', function() {
61+
it('should parse dot-separated paths', function() {
62+
expect(builder.parentName(states['other.foo.bar'])).toBe('other.foo');
12263
});
123-
124-
it('should inherit parent data', function() {
125-
var state = extend(states['home.withData.child'], { self: {} });
126-
expect(builder.builder('data')(state)).toEqualData({ val1: "foo", val2: "baz" });
127-
128-
state = extend(states['home.withData'], { self: {} });
129-
expect(builder.builder('data')(state)).toEqualData({ val1: "foo", val2: "bar" });
64+
it('should always return parent name as string', function() {
65+
expect(builder.parentName(states['other.foo'])).toBe('other');
13066
});
131-
132-
it('should compile a UrlMatcher for ^ URLs', function() {
133-
var url = new UrlMatcher('/', paramTypes, null);
134-
spyOn(urlMatcherFactoryProvider, 'compile').and.returnValue(url);
135-
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(true);
136-
137-
expect(builder.builder('url')({ url: "^/foo" })).toBe(url);
138-
expect(urlMatcherFactoryProvider.compile).toHaveBeenCalledWith("/foo", {
139-
params: {},
140-
paramMap: jasmine.any(Function)
141-
});
142-
expect(urlMatcherFactoryProvider.isMatcher).toHaveBeenCalledWith(url);
67+
it('should return empty string if state has no parent', function() {
68+
expect(builder.parentName(states[''])).toBe("");
14369
});
70+
it('should error if parent: is specified *AND* the state name has a dot (.) in it', function() {
71+
expect(() => builder.parentName(states['home.error'])).toThrowError();
72+
});
73+
});
74+
});
14475

145-
it('should concatenate URLs from root', function() {
146-
var root = states[''] = { url: { append: function() {} } }, url = {};
147-
spyOn(root.url, 'append').and.returnValue(url);
148-
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(true);
149-
spyOn(urlMatcherFactoryProvider, 'compile').and.returnValue(url);
76+
describe('state building', function() {
77+
it('should build parent property', function() {
78+
expect(builder.builder('parent')({ name: 'home.about' })).toBe(states['home']);
79+
});
15080

151-
expect(builder.builder('url')({ url: "/foo" })).toBe(url);
152-
expect(root.url.append).toHaveBeenCalledWith(url);
153-
});
81+
it('should inherit parent data', function() {
82+
let state = extend(states['home.withData.child'], { self: {} });
83+
expect(builder.builder('data')(state)).toEqualData({ val1: "foo", val2: "baz" });
15484

155-
it('should pass through empty URLs', function() {
156-
expect(builder.builder('url')({ url: null })).toBeNull();
157-
});
85+
state = extend(states['home.withData'], { self: {} });
86+
expect(builder.builder('data')(state)).toEqualData({ val1: "foo", val2: "bar" });
87+
});
15888

159-
it('should pass through custom UrlMatchers', function() {
160-
var root = states[''] = { url: { append: function() {} } };
161-
var url = new UrlMatcher("/", paramTypes, null);
162-
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(true);
163-
spyOn(root.url, 'append').and.returnValue(url);
164-
expect(builder.builder('url')({ url: url })).toBe(url);
165-
expect(urlMatcherFactoryProvider.isMatcher).toHaveBeenCalledWith(url);
166-
expect(root.url.append).toHaveBeenCalledWith(url);
89+
it('should compile a UrlMatcher for ^ URLs', function() {
90+
let url = new UrlMatcher('/', paramTypes, null);
91+
spyOn(urlMatcherFactoryProvider, 'compile').and.returnValue(url);
92+
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(true);
93+
94+
expect(builder.builder('url')({ url: "^/foo" })).toBe(url);
95+
expect(urlMatcherFactoryProvider.compile).toHaveBeenCalledWith("/foo", {
96+
params: {},
97+
paramMap: jasmine.any(Function)
16798
});
99+
expect(urlMatcherFactoryProvider.isMatcher).toHaveBeenCalledWith(url);
100+
});
168101

169-
it('should throw on invalid UrlMatchers', function() {
170-
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(false);
102+
it('should concatenate URLs from root', function() {
103+
let root = states[''] = { url: { append: function() {} } }, url = {};
104+
spyOn(root.url, 'append').and.returnValue(url);
105+
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(true);
106+
spyOn(urlMatcherFactoryProvider, 'compile').and.returnValue(url);
171107

172-
expect(function() {
173-
builder.builder('url')({ toString: function() { return "foo"; }, url: { foo: "bar" } });
174-
}).toThrowError(Error, "Invalid url '[object Object]' in state 'foo'");
108+
expect(builder.builder('url')({ url: "/foo" })).toBe(url);
109+
expect(root.url.append).toHaveBeenCalledWith(url);
110+
});
175111

176-
expect(urlMatcherFactoryProvider.isMatcher).toHaveBeenCalledWith({ foo: "bar" });
177-
});
112+
it('should pass through empty URLs', function() {
113+
expect(builder.builder('url')({ url: null })).toBeNull();
178114
});
179-
});
180115

181-
describe('TargetState', function () {
182-
it('should be callable and return the correct values', function() {
183-
var state: any = { name: "foo.bar" }, ref = new TargetState(state.name, state, {});
184-
expect(ref.identifier()).toBe("foo.bar");
185-
expect(ref.$state()).toBe(state);
186-
expect(ref.params()).toEqual({});
116+
it('should pass through custom UrlMatchers', function() {
117+
let root = states[''] = { url: { append: function() {} } };
118+
let url = new UrlMatcher("/", paramTypes, null);
119+
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(true);
120+
spyOn(root.url, 'append').and.returnValue(url);
121+
expect(builder.builder('url')({ url: url })).toBe(url);
122+
expect(urlMatcherFactoryProvider.isMatcher).toHaveBeenCalledWith(url);
123+
expect(root.url.append).toHaveBeenCalledWith(url);
187124
});
188125

189-
it('should validate state definition', function() {
190-
var ref = new TargetState("foo", null, {}, { relative: {} });
191-
expect(ref.valid()).toBe(false);
192-
expect(ref.error()).toBe("Could not resolve 'foo' from state '[object Object]'");
126+
it('should throw on invalid UrlMatchers', function() {
127+
spyOn(urlMatcherFactoryProvider, 'isMatcher').and.returnValue(false);
193128

194-
ref = new TargetState("foo");
195-
expect(ref.valid()).toBe(false);
196-
expect(ref.error()).toBe("No such state 'foo'");
129+
expect(function() {
130+
builder.builder('url')({ toString: function() { return "foo"; }, url: { foo: "bar" } });
131+
}).toThrowError(Error, "Invalid url '[object Object]' in state 'foo'");
197132

198-
ref = new TargetState("foo", <any> { name: "foo" });
199-
expect(ref.valid()).toBe(false);
200-
expect(ref.error()).toBe("State 'foo' has an invalid definition");
133+
expect(urlMatcherFactoryProvider.isMatcher).toHaveBeenCalledWith({ foo: "bar" });
201134
});
202135
});
203136
});

test/stateMatcherSpec.ts

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { StateMatcher } from "../src/index";
2+
import { UIRouter } from "../src/router";
3+
4+
describe('StateMatcher', function() {
5+
let router: UIRouter;
6+
beforeEach(() => router = new UIRouter());
7+
8+
it('should find states by name', function() {
9+
let registry = router.stateRegistry;
10+
let matcher = registry.matcher;
11+
expect(matcher.find('home')).toBeUndefined();
12+
13+
let home = { name: 'home' }, _home = registry.register(home);
14+
expect(matcher.find('home')).toBe(_home);
15+
expect(matcher.find(home)).toBe(_home);
16+
17+
expect(matcher.find('home.about')).toBeUndefined();
18+
19+
let about = { name: 'home.about' }, _about = registry.register(about);
20+
expect(matcher.find('home.about')).toBe(_about);
21+
22+
expect(matcher.find('')).toBe(registry.root());
23+
expect(matcher.find(undefined)).toBeUndefined();
24+
expect(matcher.find('asdfasdf')).toBeUndefined();
25+
expect(matcher.find(null)).toBeUndefined();
26+
});
27+
28+
it('should determine whether a path is relative', function() {
29+
let matcher = new StateMatcher({});
30+
expect(matcher.isRelative('.')).toBe(true);
31+
expect(matcher.isRelative('.foo')).toBe(true);
32+
expect(matcher.isRelative('^')).toBe(true);
33+
expect(matcher.isRelative('^foo')).toBe(true);
34+
expect(matcher.isRelative('^.foo')).toBe(true);
35+
expect(matcher.isRelative('foo')).toBe(false);
36+
});
37+
38+
it('should resolve relative paths', function() {
39+
let states = ['other', 'other.foo', 'other.foo.bar', 'home.error',
40+
'home', 'home.about', 'home.about.company', 'home.about.people', 'home.about.people.person' ];
41+
states.forEach(statename => router.stateRegistry.register({ name: statename }));
42+
43+
let matcher = router.stateRegistry.matcher;
44+
45+
expect(matcher.find('.', 'home.about').name).toBe('home.about');
46+
expect(matcher.find('^', 'home.about').name).toBe('home');
47+
expect(matcher.find('^.company', 'home.about.people').name).toBe('home.about.company');
48+
expect(matcher.find('^.^.company', 'home.about.people.person').name).toBe('home.about.company');
49+
expect(matcher.find('^.foo', 'home')).toBeUndefined();
50+
expect(matcher.find('^.other.foo', 'home').name).toBe('other.foo');
51+
expect(function() { matcher.find('^.^', 'home'); }).toThrowError(Error, "Path '^.^' not valid for state 'home'");
52+
});
53+
});

test/targetStateSpec.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { TargetState } from "../src/index";
2+
3+
describe('TargetState object', function() {
4+
it('should be callable and return the correct values', function() {
5+
let state: any = { name: "foo.bar" }, ref = new TargetState(state.name, state, {});
6+
expect(ref.identifier()).toBe("foo.bar");
7+
expect(ref.$state()).toBe(state);
8+
expect(ref.params()).toEqual({});
9+
});
10+
11+
it('should validate state definition', function() {
12+
let ref = new TargetState("foo", null, {}, { relative: {} });
13+
expect(ref.valid()).toBe(false);
14+
expect(ref.error()).toBe("Could not resolve 'foo' from state '[object Object]'");
15+
16+
ref = new TargetState("foo");
17+
expect(ref.valid()).toBe(false);
18+
expect(ref.error()).toBe("No such state 'foo'");
19+
20+
ref = new TargetState("foo", <any> { name: "foo" });
21+
expect(ref.valid()).toBe(false);
22+
expect(ref.error()).toBe("State 'foo' has an invalid definition");
23+
});
24+
});

0 commit comments

Comments
 (0)