@angular-wave/angular.ts 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/angular-ts.esm.js +1 -1
  2. package/dist/angular-ts.umd.js +1 -1
  3. package/index.html +6 -2
  4. package/package.json +1 -1
  5. package/src/core/compile.js +2 -3
  6. package/src/core/parser/parse.js +2 -3
  7. package/src/filters/order-by.js +8 -8
  8. package/src/router/directives/{stateDirectives.js → state-directives.js} +1 -2
  9. package/src/router/directives/{viewDirective.js → view-directive.js} +4 -12
  10. package/src/router/globals.js +1 -1
  11. package/src/router/hooks/{ignoredTransition.js → ignored-transition.js} +1 -1
  12. package/src/router/hooks/{redirectTo.js → redirect-to.js} +1 -1
  13. package/src/router/hooks/resolve.js +1 -1
  14. package/src/router/index.js +6 -8
  15. package/src/router/params/{paramTypes.js → param-types.js} +3 -4
  16. package/src/router/params/param.js +1 -1
  17. package/src/router/path/{pathUtils.js → path-utils.js} +2 -2
  18. package/src/router/resolve/resolvable.js +2 -2
  19. package/src/router/resolve/{resolveContext.js → resolve-context.js} +1 -1
  20. package/src/router/router.js +8 -8
  21. package/src/router/services.js +3 -3
  22. package/src/router/state/{stateBuilder.js → state-builder.js} +2 -3
  23. package/src/router/state/{stateQueueManager.js → state-queue-manager.js} +2 -1
  24. package/src/router/state/{stateRegistry.js → state-registry.js} +3 -3
  25. package/src/router/state/{stateService.js → state-service.js} +7 -7
  26. package/src/router/state/views.js +1 -1
  27. package/src/router/{stateProvider.js → state-provider.js} +8 -0
  28. package/src/router/{templateFactory.js → template-factory.js} +93 -51
  29. package/src/router/transition/{hookBuilder.js → hook-builder.js} +3 -3
  30. package/src/router/transition/{transitionEventType.js → transition-event-type.js} +1 -1
  31. package/src/router/transition/{transitionHook.js → transition-hook.js} +2 -2
  32. package/src/router/transition/{transitionService.js → transition-service.js} +10 -10
  33. package/src/router/transition/transition.js +12 -9
  34. package/src/router/url/{urlConfig.js → url-config.js} +1 -1
  35. package/src/router/url/{urlMatcherFactory.js → url-matcher-factory.js} +1 -1
  36. package/src/router/url/{urlMatcher.js → url-matcher.js} +0 -2
  37. package/src/router/url/{urlRouter.js → url-router.js} +1 -1
  38. package/src/router/url/{urlRule.js → url-rule.js} +13 -5
  39. package/src/router/url/{urlRules.js → url-rules.js} +3 -3
  40. package/src/router/url/{urlService.js → url-service.js} +6 -6
  41. package/src/services/browser.js +3 -18
  42. package/src/shared/strings.js +2 -2
  43. package/test/router/ng-state-builder.spec.js +81 -0
  44. package/test/router/services.spec.js +0 -1
  45. package/test/router/state-directives.spec.js +867 -893
  46. package/test/router/template-factory.spec.js +146 -0
  47. package/test/router/url-matcher-factory.spec.js +1313 -0
  48. package/test/router/view-directive.spec.js +2013 -0
  49. package/test/router/view-hook.spec.js +217 -0
  50. package/test/router/view-scroll.spec.js +77 -0
  51. package/test/router/view.spec.js +117 -0
  52. package/test/test-utils.js +9 -0
  53. package/types/router/legacy/resolveService.d.ts +1 -1
  54. package/types/router/statebuilders/onEnterExitRetain.d.ts +1 -1
  55. package/types/router/statebuilders/views.d.ts +1 -2
  56. /package/src/router/hooks/{coreResolvables.js → core-resolvables.js} +0 -0
  57. /package/src/router/hooks/{invalidTransition.js → invalid-transition.js} +0 -0
  58. /package/src/router/hooks/{lazyLoad.js → lazy-load.js} +0 -0
  59. /package/src/router/hooks/{onEnterExitRetain.js → on-enter-exit-retain.js} +0 -0
  60. /package/src/router/hooks/{updateGlobals.js → update-globals.js} +0 -0
  61. /package/src/router/{locationServices.js → location-services.js} +0 -0
  62. /package/src/router/params/{paramType.js → param-type.js} +0 -0
  63. /package/src/router/params/{stateParams.js → state-params.js} +0 -0
  64. /package/src/router/path/{pathNode.js → path-node.js} +0 -0
  65. /package/src/router/state/{stateMatcher.js → state-matcher.js} +0 -0
  66. /package/src/router/state/{stateObject.js → state-object.js} +0 -0
  67. /package/src/router/state/{targetState.js → target-state.js} +0 -0
  68. /package/src/router/{stateFilters.js → state-filters.js} +0 -0
  69. /package/src/router/transition/{hookRegistry.js → hook-registry.js} +0 -0
  70. /package/src/router/transition/{rejectFactory.js → reject-factory.js} +0 -0
  71. /package/src/router/{viewScroll.js → view-scroll.js} +0 -0
@@ -3,7 +3,8 @@ import { Angular } from "../../src/loader";
3
3
  import { publishExternalAPI } from "../../src/public";
4
4
  import { browserTrigger, wait } from "../test-utils";
5
5
 
6
- describe("uiStateRef", function () {
6
+ describe("uiStateRef", () => {
7
+ window.location.hash = "#!";
7
8
  let el,
8
9
  el2,
9
10
  template,
@@ -59,7 +60,7 @@ describe("uiStateRef", function () {
59
60
 
60
61
  afterEach(() => (window.location.hash = "#!"));
61
62
 
62
- describe("links with promises", function () {
63
+ describe("links with promises", () => {
63
64
  it("should update the href when promises on parameters change before scope is applied", async () => {
64
65
  const defer = $q.defer();
65
66
  el = jqLite(
@@ -77,6 +78,7 @@ describe("uiStateRef", function () {
77
78
  });
78
79
 
79
80
  function buildDOM() {
81
+ window.location.hash = "#";
80
82
  el = jqLite(
81
83
  '<a ui-sref="contacts.item.detail({ id: contact.id })">Details</a>',
82
84
  );
@@ -90,16 +92,16 @@ describe("uiStateRef", function () {
90
92
  scope.$digest();
91
93
  }
92
94
 
93
- describe("links", function () {
95
+ describe("links", () => {
94
96
  beforeEach(() => buildDOM());
95
97
  afterEach(() => (window.location.hash = ""));
96
98
 
97
- it("should generate the correct href", function () {
99
+ it("should generate the correct href", () => {
98
100
  expect(el.attr("href")).toBe("#/contacts/5");
99
101
  expect(el2.attr("href")).toBe("#");
100
102
  });
101
103
 
102
- it("should update the href when parameters change", function () {
104
+ it("should update the href when parameters change", () => {
103
105
  expect(el.attr("href")).toBe("#/contacts/5");
104
106
  scope.contact.id = 6;
105
107
  scope.$apply();
@@ -151,6 +153,7 @@ describe("uiStateRef", function () {
151
153
  expect($stateParams.id).toBeUndefined();
152
154
  });
153
155
 
156
+ // TODO investigate further why this fails
154
157
  xit("should not transition states when alt-clicked", async () => {
155
158
  expect($state.current.name).toEqual("");
156
159
 
@@ -186,83 +189,86 @@ describe("uiStateRef", function () {
186
189
  });
187
190
 
188
191
  // // Test for #1031
189
- // it('should allow passing params to current state', async () => {
190
- // $state.go('other', { id: 'abc' });
191
- // $rootScope.$index = 'def';
192
- // $rootScope.$digest();
193
-
194
- // el = jqLite('<a ui-sref="{id: $index}">Details</a>');
195
- // $compile(el)($rootScope);
196
- // $rootScope.$digest();
197
-
198
- // expect($state.current.name).toBe('other');
199
- // expect($state.params).toEqual(expect.objectContaining({ id: 'abc' });
200
- // expect(el.attr('href')).toBe('#/other/def');
192
+ it("should allow passing params to current state", async () => {
193
+ $state.go("other", { id: "abc" });
194
+ $rootScope.$index = "def";
195
+ $rootScope.$digest();
201
196
 
202
- // triggerClick(el);
203
- // timeoutFlush();
204
- // $q.flush();
197
+ el = jqLite('<a ui-sref="{id: $index}">Details</a>');
198
+ $compile(el)($rootScope);
199
+ $rootScope.$digest();
205
200
 
206
- // expect($state.current.name).toBe('other');
207
- // expect($state.params).toEqual(expect.objectContaining({ id: 'def' });
201
+ expect($state.current.name).toBe("other");
202
+ expect($state.params.id).toEqual("abc");
203
+ expect(el.attr("href")).toBe("#/other/def");
208
204
 
209
- // $rootScope.$index = 'ghi';
210
- // $state.go('other.detail');
211
- // $rootScope.$digest();
205
+ browserTrigger(el, "click");
206
+ await wait(100);
207
+ expect($state.current.name).toBe("other");
208
+ expect($state.params.id).toEqual("def");
212
209
 
213
- // expect($state.current.name).toBe('other.detail');
214
- // expect($state.params).toEqual(expect.objectContaining({ id: 'def' });
210
+ $rootScope.$index = "ghi";
211
+ $state.go("other.detail");
212
+ $rootScope.$digest();
215
213
 
216
- // expect(el.attr('href')).toBe('#/other/ghi/detail');
214
+ expect($state.current.name).toBe("other.detail");
215
+ expect($state.params.id).toEqual("def");
217
216
 
218
- // triggerClick(el);
219
- // timeoutFlush();
220
- // $q.flush();
217
+ expect(el.attr("href")).toBe("#/other/ghi/detail");
221
218
 
222
- // expect($state.current.name).toBe('other.detail');
223
- // expect($state.params).toEqual(expect.objectContaining({ id: 'ghi' });
224
- // });
219
+ browserTrigger(el, "click");
220
+ await wait(100);
221
+ expect($state.current.name).toBe("other.detail");
222
+ expect($state.params.id).toEqual("ghi");
223
+ });
225
224
 
226
- // it('should allow multi-line attribute values when passing params to current state', async () => {
227
- // $state.go('contacts.item.detail', { id: '123' });
228
- // $rootScope.$digest();
225
+ it("should allow multi-line attribute values when passing params to current state", async () => {
226
+ $state.go("contacts.item.detail", { id: "123" });
227
+ $rootScope.$digest();
229
228
 
230
- // el = jqLite('<a ui-sref="{\n\tid: $index\n}">Details</a>');
231
- // $rootScope.$index = 3;
232
- // $rootScope.$apply();
229
+ el = jqLite('<a ui-sref="{\n\tid: $index\n}">Details</a>');
230
+ $rootScope.$index = 3;
231
+ $rootScope.$apply();
233
232
 
234
- // $compile(el)($rootScope);
235
- // $rootScope.$digest();
236
- // expect(el.attr('href')).toBe('#/contacts/3');
237
- // });
233
+ $compile(el)($rootScope);
234
+ $rootScope.$digest();
235
+ expect(el.attr("href")).toBe("#/contacts/3");
236
+ });
238
237
 
239
- // it('should take an object as a parameter and update properly on digest churns', async () => {
240
- // el = jqLite('<div><a ui-sref="contacts.item.detail(urlParams)">Contacts</a></div>');
241
- // template = $compile(el)($rootScope);
238
+ it("should take an object as a parameter and update properly on digest churns", async () => {
239
+ el = jqLite(
240
+ '<div><a ui-sref="contacts.item.detail(urlParams)">Contacts</a></div>',
241
+ );
242
+ template = $compile(el)($rootScope);
242
243
 
243
- // $rootScope.urlParams = { id: 1 };
244
- // $rootScope.$digest();
245
- // expect(jqLite(template[0].querySelector('a')).attr('href')).toBe('#/contacts/1');
244
+ $rootScope.urlParams = { id: 1 };
245
+ $rootScope.$digest();
246
+ expect(jqLite(template[0].querySelector("a")).attr("href")).toBe(
247
+ "#/contacts/1",
248
+ );
246
249
 
247
- // $rootScope.urlParams.id = 2;
248
- // $rootScope.$digest();
249
- // expect(jqLite(template[0].querySelector('a')).attr('href')).toBe('#/contacts/2');
250
- // });
250
+ $rootScope.urlParams.id = 2;
251
+ $rootScope.$digest();
252
+ expect(jqLite(template[0].querySelector("a")).attr("href")).toBe(
253
+ "#/contacts/2",
254
+ );
255
+ });
251
256
  });
252
257
 
253
- // describe('links in html5 mode', function () {
254
- // beforeEach(function () {
258
+ // TODO: Since this is HTML5 mode, we would want to test this with actual backend
259
+ // describe('links in html5 mode', () => {
260
+ // beforeEach(() => {
255
261
  // _locationProvider.html5Mode(true);
256
262
  // });
257
263
 
258
264
  // beforeEach(inject(buildDOM));
259
265
 
260
- // it('should generate the correct href', function () {
266
+ // it('should generate the correct href', () => {
261
267
  // expect(el.attr('href')).toBe('/contacts/5');
262
268
  // expect(el2.attr('href')).toBe('');
263
269
  // });
264
270
 
265
- // it('should update the href when parameters change', function () {
271
+ // it('should update the href when parameters change', () => {
266
272
  // expect(el.attr('href')).toBe('/contacts/5');
267
273
  // scope.contact.id = 6;
268
274
  // scope.$apply();
@@ -275,934 +281,902 @@ describe("uiStateRef", function () {
275
281
 
276
282
  // triggerClick(el2);
277
283
  // timeoutFlush();
278
- // $q.flush();
284
+ // await wait(10);
279
285
 
280
286
  // expect($state.current.name).toEqual('top');
281
287
  // expect(obj($stateParams)).toEqual({});
282
288
  // });
283
289
  // });
284
290
 
285
- // describe('links with dynamic state definitions', function () {
286
- // let template, $state;
287
-
288
- // beforeEach(inject(function ($rootScope, $compile, _$state_) {
289
- // $state = _$state_;
290
- // el = jqLite(
291
- // '<a ui-sref-active="active" ui-sref-active-eq="activeeq" ui-state="state" ui-state-params="params">state</a>'
292
- // );
293
- // scope = $rootScope;
294
- // angular.extend(scope, { state: 'contacts', params: {} });
295
- // template = $compile(el)(scope);
296
- // scope.$digest();
297
- // });
291
+ describe("links with dynamic state definitions", () => {
292
+ let template;
298
293
 
299
- // it('sets the correct initial href', function () {
300
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts');
301
- // });
294
+ beforeEach(() => {
295
+ el = jqLite(
296
+ '<a ui-sref-active="active" ui-sref-active-eq="activeeq" ui-state="state" ui-state-params="params">state</a>',
297
+ );
298
+ scope = $rootScope;
299
+ Object.assign(scope, { state: "contacts", params: {} });
300
+ template = $compile(el)(scope);
301
+ scope.$digest();
302
+ });
302
303
 
303
- // it('updates to the new href', function () {
304
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts');
304
+ it("sets the correct initial href", () => {
305
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts");
306
+ });
305
307
 
306
- // scope.state = 'contacts.item';
307
- // scope.params = { id: 5 };
308
- // scope.$digest();
309
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/5');
308
+ it("updates to the new href", () => {
309
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts");
310
310
 
311
- // scope.params.id = 25;
312
- // scope.$digest();
313
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/25');
314
- // });
311
+ scope.state = "contacts.item";
312
+ scope.params = { id: 5 };
313
+ scope.$digest();
314
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/5");
315
315
 
316
- // it('updates a linked ui-sref-active', inject(function ($timeout) {
317
- // function tick() {
318
- // scope.$digest();
319
- // try {
320
- // $timeout.flush();
321
- // } catch (error) {}
322
- // }
323
- // expect(template[0].className).not.toContain('active');
324
- // expect(template[0].className).not.toContain('activeeq');
325
-
326
- // $state.go('contacts');
327
- // tick();
328
- // expect(template[0].className).toContain('active activeeq');
329
-
330
- // scope.state = 'contacts.item';
331
- // scope.params = { id: 5 };
332
- // tick();
333
- // expect(template[0].className).not.toContain('active');
334
- // expect(template[0].className).not.toContain('activeeq');
335
-
336
- // $state.go('contacts.item', { id: -5 });
337
- // tick();
338
- // expect(template[0].className).not.toContain('active');
339
- // expect(template[0].className).not.toContain('activeeq');
340
-
341
- // $state.go('contacts.item', { id: 5 });
342
- // tick();
343
- // expect(template[0].className).toContain('active activeeq');
344
-
345
- // scope.state = 'contacts';
346
- // scope.params = {};
347
- // tick();
348
- // expect(template[0].className).toContain('active');
349
- // expect(template[0].className).not.toContain('activeeq');
350
- // });
316
+ scope.params.id = 25;
317
+ scope.$digest();
318
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/25");
319
+ });
351
320
 
352
- // it('updates to a new href when it points to a new state', function () {
353
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts');
354
- // scope.state = 'other';
355
- // scope.params = { id: '123' };
356
- // scope.$digest();
357
- // expect(jqLite(template[0]).attr('href')).toBe('#/other/123');
358
- // });
321
+ it("updates a linked ui-sref-active", async () => {
322
+ expect(template[0].className).not.toContain("active");
323
+ expect(template[0].className).not.toContain("activeeq");
324
+
325
+ $state.go("contacts");
326
+ scope.$digest();
327
+ await wait(10);
328
+ expect(template[0].className).toContain("active activeeq");
329
+
330
+ scope.state = "contacts.item";
331
+ scope.params = { id: 5 };
332
+ scope.$digest();
333
+ await wait(10);
334
+ expect(template[0].className).not.toContain("active");
335
+ expect(template[0].className).not.toContain("activeeq");
336
+
337
+ $state.go("contacts.item", { id: -5 });
338
+ scope.$digest();
339
+ await wait(10);
340
+ expect(template[0].className).not.toContain("active");
341
+ expect(template[0].className).not.toContain("activeeq");
342
+
343
+ $state.go("contacts.item", { id: 5 });
344
+ scope.$digest();
345
+ await wait(10);
346
+ expect(template[0].className).toContain("active activeeq");
347
+
348
+ scope.state = "contacts";
349
+ scope.params = {};
350
+ scope.$digest();
351
+ await wait(10);
352
+ expect(template[0].className).toContain("active");
353
+ expect(template[0].className).not.toContain("activeeq");
354
+ });
359
355
 
360
- // // Test for #1031
361
- // it('should allow passing params to current state using empty ui-state', inject(function (
362
- // $compile,
363
- // $rootScope,
364
- // $state,
365
- // $q
366
- // ) {
367
- // $state.go('other', { id: 'abc' });
368
- // $rootScope.$index = 'def';
369
- // $rootScope.$digest();
370
-
371
- // el = jqLite('<a ui-state="" ui-state-params="{id: $index}">Details</a>');
372
- // $compile(el)($rootScope);
373
- // $rootScope.$digest();
374
-
375
- // expect($state.current.name).toBe('other');
376
- // expect($state.params).toEqual(expect.objectContaining({ id: 'abc' });
377
- // expect(el.attr('href')).toBe('#/other/def');
378
-
379
- // triggerClick(el);
380
- // timeoutFlush();
381
- // $q.flush();
356
+ it("updates to a new href when it points to a new state", () => {
357
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts");
358
+ scope.state = "other";
359
+ scope.params = { id: "123" };
360
+ scope.$digest();
361
+ expect(jqLite(template[0]).attr("href")).toBe("#/other/123");
362
+ });
382
363
 
383
- // expect($state.current.name).toBe('other');
384
- // expect($state.params).toEqual(expect.objectContaining({ id: 'def' });
364
+ it("should allow passing params to current state using empty ui-state", async () => {
365
+ $state.go("other", { id: "abc" });
366
+ $rootScope.$index = "def";
367
+ $rootScope.$digest();
385
368
 
386
- // $rootScope.$index = 'ghi';
387
- // $state.go('other.detail');
388
- // $rootScope.$digest();
369
+ el = jqLite('<a ui-state="" ui-state-params="{id: $index}">Details</a>');
370
+ $compile(el)($rootScope);
371
+ $rootScope.$digest();
389
372
 
390
- // expect($state.current.name).toBe('other.detail');
391
- // expect($state.params).toEqual(expect.objectContaining({ id: 'def' });
373
+ expect($state.current.name).toBe("other");
374
+ expect($state.params.id).toEqual("abc");
375
+ expect(el.attr("href")).toBe("#/other/def");
392
376
 
393
- // expect(el.attr('href')).toBe('#/other/ghi/detail');
377
+ browserTrigger(el, "click");
378
+ await wait(10);
394
379
 
395
- // triggerClick(el);
396
- // timeoutFlush();
397
- // $q.flush();
380
+ expect($state.current.name).toBe("other");
381
+ expect($state.params.id).toEqual("def");
398
382
 
399
- // expect($state.current.name).toBe('other.detail');
400
- // expect($state.params).toEqual(expect.objectContaining({ id: 'ghi' });
401
- // });
383
+ $rootScope.$index = "ghi";
384
+ $state.go("other.detail");
385
+ $rootScope.$digest();
402
386
 
403
- // it('retains the old href if the new points to a non-state', function () {
404
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts');
405
- // scope.state = 'nostate';
406
- // scope.$digest();
407
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts');
408
- // });
387
+ expect($state.current.name).toBe("other.detail");
388
+ expect($state.params.id).toEqual("def");
409
389
 
410
- // it('accepts param overrides', inject(function ($compile) {
411
- // scope.state = 'contacts.item';
412
- // scope.params = { id: 10 };
413
- // scope.$digest();
414
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/10');
415
- // });
390
+ expect(el.attr("href")).toBe("#/other/ghi/detail");
416
391
 
417
- // it('accepts param overrides', inject(function ($compile) {
418
- // scope.state = 'contacts.item';
419
- // scope.params = { id: 10 };
420
- // scope.$digest();
421
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/10');
392
+ browserTrigger(el, "click");
393
+ await wait(10);
422
394
 
423
- // scope.params.id = 22;
424
- // scope.$digest();
425
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/22');
426
- // });
395
+ expect($state.current.name).toBe("other.detail");
396
+ expect($state.params.id).toEqual("ghi");
397
+ });
427
398
 
428
- // it('watches attributes', inject(function ($compile) {
429
- // el = jqLite('<a ui-state="{{exprvar}}" ui-state-params="params">state</a>');
430
- // template = $compile(el)(scope);
399
+ it("retains the old href if the new points to a non-state", () => {
400
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts");
401
+ scope.state = "nostate";
402
+ scope.$digest();
403
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts");
404
+ });
431
405
 
432
- // scope.exprvar = 'state1';
433
- // scope.state1 = 'contacts.item';
434
- // scope.state2 = 'other';
435
- // scope.params = { id: 10 };
436
- // scope.$digest();
437
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/10');
406
+ it("accepts param overrides", () => {
407
+ scope.state = "contacts.item";
408
+ scope.params = { id: 10 };
409
+ scope.$digest();
410
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/10");
411
+ });
438
412
 
439
- // scope.exprvar = 'state2';
440
- // scope.$digest();
441
- // expect(jqLite(template[0]).attr('href')).toBe('#/other/10');
442
- // });
413
+ it("accepts param overrides", () => {
414
+ scope.state = "contacts.item";
415
+ scope.params = { id: 10 };
416
+ scope.$digest();
417
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/10");
443
418
 
444
- // if (angular.version.minor >= 3) {
445
- // it('allows one-time-binding on ng1.3+', inject(function ($compile) {
446
- // el = jqLite('<a ui-state="::state" ui-state-params="::params">state</a>');
419
+ scope.params.id = 22;
420
+ scope.$digest();
421
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/22");
422
+ });
447
423
 
448
- // scope.state = 'contacts.item';
449
- // scope.params = { id: 10 };
450
- // template = $compile(el)(scope);
451
- // scope.$digest();
452
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/10');
424
+ it("watches attributes", () => {
425
+ el = jqLite(
426
+ '<a ui-state="{{exprvar}}" ui-state-params="params">state</a>',
427
+ );
428
+ template = $compile(el)(scope);
429
+
430
+ scope.exprvar = "state1";
431
+ scope.state1 = "contacts.item";
432
+ scope.state2 = "other";
433
+ scope.params = { id: 10 };
434
+ scope.$digest();
435
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/10");
436
+
437
+ scope.exprvar = "state2";
438
+ scope.$digest();
439
+ expect(jqLite(template[0]).attr("href")).toBe("#/other/10");
440
+ });
453
441
 
454
- // scope.state = 'other';
455
- // scope.params = { id: 22 };
442
+ it("allows one-time-binding on ng1.3+", () => {
443
+ el = jqLite('<a ui-state="::state" ui-state-params="::params">state</a>');
456
444
 
457
- // scope.$digest();
458
- // expect(jqLite(template[0]).attr('href')).toBe('#/contacts/10');
459
- // });
460
- // }
445
+ scope.state = "contacts.item";
446
+ scope.params = { id: 10 };
447
+ template = $compile(el)(scope);
448
+ scope.$digest();
449
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/10");
461
450
 
462
- // it('accepts option overrides', inject(function ($compile, $timeout, $state) {
463
- // let transitionOptions;
451
+ scope.state = "other";
452
+ scope.params = { id: 22 };
464
453
 
465
- // el = jqLite('<a ui-state="state" ui-state-opts="opts">state</a>');
466
- // scope.state = 'contacts';
467
- // scope.opts = { reload: true };
468
- // template = $compile(el)(scope);
469
- // scope.$digest();
454
+ scope.$digest();
455
+ expect(jqLite(template[0]).attr("href")).toBe("#/contacts/10");
456
+ });
470
457
 
471
- // spyOn($state, 'go').and.callFake(function (state, params, options) {
472
- // transitionOptions = options;
473
- // });
458
+ it("accepts option overrides", async () => {
459
+ let transitionOptions;
474
460
 
475
- // triggerClick(template);
476
- // $timeout.flush();
461
+ el = jqLite('<a ui-state="state" ui-state-opts="opts">state</a>');
462
+ scope.state = "contacts";
463
+ scope.opts = { reload: true };
464
+ template = $compile(el)(scope);
465
+ scope.$digest();
477
466
 
478
- // expect(transitionOptions.reload).toEqual(true);
479
- // expect(transitionOptions.absolute).toBeUndefined();
480
- // });
467
+ spyOn($state, "go").and.callFake(function (state, params, options) {
468
+ transitionOptions = options;
469
+ });
481
470
 
482
- // describe('option event', function () {
483
- // it('should bind click event by default', inject(function ($compile, $state, $timeout) {
484
- // expect($state.current.name).toBe('top');
471
+ browserTrigger(template, "click");
472
+ await wait(10);
485
473
 
486
- // el = jqLite('<a ui-state="state"></a>');
474
+ expect(transitionOptions.reload).toEqual(true);
475
+ expect(transitionOptions.absolute).toBeUndefined();
476
+ });
487
477
 
488
- // scope.state = 'contacts';
489
- // $compile(el)(scope);
490
- // scope.$digest();
478
+ describe("option event", () => {
479
+ beforeEach(() => (window.location.hash = ""));
480
+ it("should bind click event by default", async () => {
481
+ expect($state.current.name).toBe("top");
491
482
 
492
- // triggerClick(el);
493
- // $timeout.flush();
483
+ el = jqLite('<a ui-state="state"></a>');
494
484
 
495
- // expect($state.current.name).toBe('contacts');
496
- // });
485
+ scope.state = "contacts";
486
+ $compile(el)(scope);
487
+ scope.$digest();
497
488
 
498
- // it('should bind single HTML events', inject(function ($compile, $state, $timeout) {
499
- // expect($state.current.name).toEqual('top');
489
+ browserTrigger(el, "click");
490
+ await wait(10);
500
491
 
501
- // el = jqLite('<input type="text" ui-state="state" ui-state-opts="{ events: [\'change\'] }">');
492
+ expect($state.current.name).toBe("contacts");
493
+ });
502
494
 
503
- // scope.state = 'contacts';
504
- // $compile(el)(scope);
505
- // scope.$digest();
495
+ it("should bind single HTML events", async () => {
496
+ expect($state.current.name).toEqual("top");
506
497
 
507
- // triggerHTMLEvent('change');
508
- // $timeout.flush();
498
+ el = jqLite(
499
+ '<input type="text" ui-state="state" ui-state-opts="{ events: [\'change\'] }">',
500
+ );
509
501
 
510
- // expect($state.current.name).toEqual('contacts');
511
- // });
502
+ scope.state = "contacts";
503
+ $compile(el)(scope);
504
+ scope.$digest();
512
505
 
513
- // it('should bind multiple HTML events', inject(function ($compile, $state, $timeout) {
514
- // expect($state.current.name).toEqual('top');
506
+ browserTrigger(el, "change");
507
+ await wait(10);
515
508
 
516
- // el = jqLite('<input type="text" ui-state="state" ui-state-opts="{ events: [\'change\', \'blur\'] }">');
509
+ expect($state.current.name).toEqual("contacts");
510
+ });
517
511
 
518
- // scope.state = 'contacts';
519
- // $compile(el)(scope);
520
- // scope.$digest();
512
+ it("should bind multiple HTML events", async () => {
513
+ expect($state.current.name).toEqual("top");
521
514
 
522
- // triggerHTMLEvent('change');
523
- // $timeout.flush();
524
- // expect($state.current.name).toEqual('contacts');
515
+ el = jqLite(
516
+ '<input type="text" ui-state="state" ui-state-opts="{ events: [\'change\', \'blur\'] }">',
517
+ );
525
518
 
526
- // $state.go('top');
527
- // scope.$digest();
519
+ scope.state = "contacts";
520
+ $compile(el)(scope);
521
+ scope.$digest();
528
522
 
529
- // expect($state.current.name).toEqual('top');
523
+ browserTrigger(el, "change");
524
+ await wait(10);
525
+ expect($state.current.name).toEqual("contacts");
530
526
 
531
- // triggerHTMLEvent('blur');
532
- // $timeout.flush();
533
- // expect($state.current.name).toEqual('contacts');
534
- // });
527
+ $state.go("top");
528
+ scope.$digest();
535
529
 
536
- // it('should bind multiple Mouse events', inject(function ($compile, $state, $timeout) {
537
- // expect($state.current.name).toEqual('top');
530
+ expect($state.current.name).toEqual("top");
538
531
 
539
- // el = jqLite('<a ui-state="state" ui-state-opts="{ events: [\'mouseover\', \'mousedown\'] }">');
532
+ browserTrigger(el, "blur");
533
+ await wait(10);
540
534
 
541
- // scope.state = 'contacts';
542
- // $compile(el)(scope);
543
- // scope.$digest();
535
+ expect($state.current.name).toEqual("contacts");
536
+ });
544
537
 
545
- // triggerMouseEvent('mouseover');
546
- // $timeout.flush();
547
- // expect($state.current.name).toEqual('contacts');
538
+ it("should bind multiple Mouse events", async () => {
539
+ expect($state.current.name).toEqual("top");
548
540
 
549
- // $state.go('top');
550
- // scope.$digest();
541
+ el = jqLite(
542
+ "<a ui-state=\"state\" ui-state-opts=\"{ events: ['mouseover', 'mousedown'] }\">",
543
+ );
551
544
 
552
- // expect($state.current.name).toEqual('top');
545
+ scope.state = "contacts";
546
+ $compile(el)(scope);
547
+ scope.$digest();
553
548
 
554
- // triggerMouseEvent('mousedown');
555
- // $timeout.flush();
556
- // expect($state.current.name).toEqual('contacts');
557
- // });
558
- // });
559
- // });
549
+ browserTrigger(el, "mouseover");
550
+ await wait(10);
551
+ expect($state.current.name).toEqual("contacts");
560
552
 
561
- // describe('forms', function () {
562
- // let el, scope;
553
+ $state.go("top");
554
+ scope.$digest();
563
555
 
564
- // beforeEach(inject(function ($rootScope, $compile) {
565
- // el = angular.element('<form ui-sref="contacts.item.detail({ id: contact.id })"></form>');
566
- // scope = $rootScope;
567
- // scope.contact = { id: 5 };
568
- // scope.$apply();
556
+ expect($state.current.name).toEqual("top");
569
557
 
570
- // $compile(el)(scope);
571
- // scope.$digest();
572
- // });
558
+ browserTrigger(el, "mousedown");
559
+ await wait(10);
560
+ expect($state.current.name).toEqual("contacts");
561
+ });
562
+ });
563
+ });
573
564
 
574
- // it('should generate the correct action', function () {
575
- // expect(el.attr('action')).toBe('#/contacts/5');
576
- // });
577
- // });
565
+ describe("forms", () => {
566
+ let el, scope;
578
567
 
579
- // describe('relative transitions', function () {
580
- // beforeEach(inject(function ($rootScope, $compile, $state) {
581
- // $state.transitionTo('contacts.item', { id: 5 });
582
- // el = angular.element('<a ui-sref=".detail">Details</a>');
583
- // scope = $rootScope;
584
- // scope.$apply();
568
+ beforeEach(() => {
569
+ el = jqLite(
570
+ '<form ui-sref="contacts.item.detail({ id: contact.id })"></form>',
571
+ );
572
+ scope = $rootScope;
573
+ scope.contact = { id: 5 };
574
+ scope.$apply();
585
575
 
586
- // $compile(el)(scope);
587
- // template = $compile(angular.element('<div><ui-view></ui-view><div>'))(scope);
588
- // scope.$digest();
589
- // });
576
+ $compile(el)(scope);
577
+ scope.$digest();
578
+ });
590
579
 
591
- // it('should work', inject(function ($state, $stateParams, $q, $timeout) {
592
- // triggerClick(el);
593
- // $timeout.flush();
594
- // $q.flush();
580
+ it("should generate the correct action", () => {
581
+ expect(el.attr("action")).toBe("#/contacts/5");
582
+ });
583
+ });
595
584
 
596
- // expect($state.$current.name).toBe('contacts.item.detail');
597
- // expect(obj($state.params)).toEqual({ id: 5 });
598
- // });
585
+ describe("relative transitions", () => {
586
+ beforeEach(() => {
587
+ $state.transitionTo("contacts.item", { id: 5 });
588
+ el = jqLite('<a ui-sref=".detail">Details</a>');
589
+ scope = $rootScope;
590
+ scope.$apply();
599
591
 
600
- // it('should resolve states from parent uiView', inject(function ($state, $stateParams, $q, $timeout) {
601
- // $state.transitionTo('contacts');
602
- // $q.flush();
592
+ $compile(el)(scope);
593
+ template = $compile(jqLite("<div><ui-view></ui-view><div>"))(scope);
594
+ scope.$digest();
595
+ });
603
596
 
604
- // const parentToChild = angular.element(template[0].querySelector('a.item'));
605
- // triggerClick(parentToChild);
606
- // $timeout.flush();
607
- // $q.flush();
608
- // expect($state.$current.name).toBe('contacts.item');
597
+ it("should work", async () => {
598
+ browserTrigger(el, "click");
599
+ await wait(10);
609
600
 
610
- // const childToGrandchild = angular.element(template[0].querySelector('a.item-detail'));
611
- // const childToParent = angular.element(template[0].querySelector('a.item-parent'));
601
+ expect($state.$current.name).toBe("contacts.item.detail");
602
+ expect($state.params.id).toEqual(5);
603
+ });
612
604
 
613
- // triggerClick(childToGrandchild);
614
- // $timeout.flush();
615
- // $q.flush();
605
+ it("should resolve states from parent uiView", async () => {
606
+ $state.transitionTo("contacts");
616
607
 
617
- // const grandchildToParent = angular.element(template[0].querySelector('a.item-parent2'));
618
- // expect($state.$current.name).toBe('contacts.item.detail');
608
+ const parentToChild = jqLite(template[0].querySelector("a.item"));
609
+ browserTrigger(parentToChild, "click");
610
+ await wait(10);
619
611
 
620
- // triggerClick(grandchildToParent);
621
- // $timeout.flush();
622
- // $q.flush();
623
- // expect($state.$current.name).toBe('contacts.item');
612
+ expect($state.$current.name).toBe("contacts.item");
624
613
 
625
- // $state.transitionTo('contacts.item.detail', { id: 3 });
626
- // triggerClick(childToParent);
627
- // $timeout.flush();
628
- // $q.flush();
629
- // expect($state.$current.name).toBe('contacts');
630
- // });
631
- // });
614
+ const childToGrandchild = jqLite(
615
+ template[0].querySelector("a.item-detail"),
616
+ );
617
+ const childToParent = jqLite(template[0].querySelector("a.item-parent"));
632
618
 
633
- // describe('option event', function () {
634
- // it('should bind click event by default', inject(function ($rootScope, $compile, $state, $timeout) {
635
- // el = angular.element('<a ui-sref="contacts"></a>');
636
- // $compile(el)($rootScope);
637
- // $rootScope.$digest();
619
+ browserTrigger(childToGrandchild, "click");
620
+ await wait(10);
638
621
 
639
- // expect($state.current.name).toEqual('top');
622
+ const grandchildToParent = jqLite(
623
+ template[0].querySelector("a.item-parent2"),
624
+ );
625
+ expect($state.$current.name).toBe("contacts.item.detail");
640
626
 
641
- // triggerClick(el);
642
- // $timeout.flush();
627
+ browserTrigger(grandchildToParent, "click");
628
+ await wait(10);
643
629
 
644
- // expect($state.current.name).toEqual('contacts');
645
- // });
630
+ expect($state.$current.name).toBe("contacts.item");
646
631
 
647
- // it('should bind single HTML events', inject(function ($rootScope, $compile, $state, $timeout) {
648
- // el = angular.element('<input type="text" ui-sref="contacts" ui-sref-opts="{ events: [\'change\'] }">');
649
- // $compile(el)($rootScope);
650
- // $rootScope.$digest();
632
+ $state.transitionTo("contacts.item.detail", { id: 3 });
633
+ browserTrigger(childToParent, "click");
634
+ await wait(10);
635
+ expect($state.$current.name).toBe("contacts");
636
+ });
637
+ });
651
638
 
652
- // expect($state.current.name).toEqual('top');
639
+ describe("option event", () => {
640
+ beforeEach(() => (window.location.hash = ""));
641
+ it("should bind click event by default", async () => {
642
+ el = jqLite('<a ui-sref="contacts"></a>');
643
+ $compile(el)($rootScope);
644
+ $rootScope.$digest();
653
645
 
654
- // triggerHTMLEvent('change');
655
- // $timeout.flush();
646
+ expect($state.current.name).toEqual("top");
656
647
 
657
- // expect($state.current.name).toEqual('contacts');
658
- // });
648
+ browserTrigger(el, "click");
649
+ await wait(10);
659
650
 
660
- // it('should bind multiple HTML events', inject(function ($rootScope, $compile, $state, $timeout) {
661
- // el = angular.element('<input type="text" ui-sref="contacts" ui-sref-opts="{ events: [\'change\', \'blur\'] }">');
662
- // $compile(el)($rootScope);
663
- // $rootScope.$digest();
651
+ expect($state.current.name).toEqual("contacts");
652
+ });
664
653
 
665
- // expect($state.current.name).toEqual('top');
654
+ it("should bind single HTML events", async () => {
655
+ el = jqLite(
656
+ '<input type="text" ui-sref="contacts" ui-sref-opts="{ events: [\'change\'] }">',
657
+ );
658
+ $compile(el)($rootScope);
659
+ $rootScope.$digest();
666
660
 
667
- // triggerHTMLEvent('change');
668
- // $timeout.flush();
669
- // expect($state.current.name).toEqual('contacts');
661
+ expect($state.current.name).toEqual("top");
670
662
 
671
- // $state.go('top');
672
- // $rootScope.$digest();
663
+ browserTrigger(el, "change");
664
+ await wait(10);
673
665
 
674
- // expect($state.current.name).toEqual('top');
666
+ expect($state.current.name).toEqual("contacts");
667
+ });
675
668
 
676
- // triggerHTMLEvent('blur');
677
- // $timeout.flush();
678
- // expect($state.current.name).toEqual('contacts');
679
- // });
669
+ it("should bind multiple HTML events", async () => {
670
+ el = jqLite(
671
+ '<input type="text" ui-sref="contacts" ui-sref-opts="{ events: [\'change\', \'blur\'] }">',
672
+ );
673
+ $compile(el)($rootScope);
674
+ $rootScope.$digest();
680
675
 
681
- // it('should bind multiple Mouse events', inject(function ($rootScope, $compile, $state, $timeout) {
682
- // el = angular.element('<a ui-sref="contacts" ui-sref-opts="{ events: [\'mouseover\', \'mousedown\'] }">');
683
- // $compile(el)($rootScope);
684
- // $rootScope.$digest();
676
+ expect($state.current.name).toEqual("top");
685
677
 
686
- // expect($state.current.name).toEqual('top');
678
+ browserTrigger(el, "change");
679
+ await wait(10);
680
+ expect($state.current.name).toEqual("contacts");
687
681
 
688
- // triggerMouseEvent('mouseover');
689
- // $timeout.flush();
690
- // expect($state.current.name).toEqual('contacts');
682
+ $state.go("top");
683
+ $rootScope.$digest();
691
684
 
692
- // $state.go('top');
693
- // $rootScope.$digest();
685
+ expect($state.current.name).toEqual("top");
694
686
 
695
- // expect($state.current.name).toEqual('top');
687
+ browserTrigger(el, "blur");
688
+ await wait(10);
689
+ expect($state.current.name).toEqual("contacts");
690
+ });
696
691
 
697
- // triggerMouseEvent('mousedown');
698
- // $timeout.flush();
699
- // expect($state.current.name).toEqual('contacts');
700
- // });
701
- // });
692
+ it("should bind multiple Mouse events", async () => {
693
+ el = jqLite(
694
+ "<a ui-sref=\"contacts\" ui-sref-opts=\"{ events: ['mouseover', 'mousedown'] }\">",
695
+ );
696
+ $compile(el)($rootScope);
697
+ $rootScope.$digest();
698
+
699
+ expect($state.current.name).toEqual("top");
700
+
701
+ browserTrigger(el, "mouseover");
702
+ await wait(10);
703
+ expect($state.current.name).toEqual("contacts");
704
+
705
+ $state.go("top");
706
+ $rootScope.$digest();
707
+
708
+ expect($state.current.name).toEqual("top");
709
+
710
+ browserTrigger(el, "mousedown");
711
+ await wait(10);
712
+ expect($state.current.name).toEqual("contacts");
713
+ });
714
+ });
702
715
  });
703
716
 
704
- // describe('uiSrefActive', function () {
705
- // let el, template, scope, document, _stateProvider;
706
-
707
- // beforeEach(module('ui.router'));
708
-
709
- // beforeEach(
710
- // module(function ($stateProvider) {
711
- // _stateProvider = $stateProvider;
712
- // $stateProvider
713
- // .state({name: 'top', url: '',
714
- // })
715
- // .state({name: 'contacts', url: '/contacts',
716
- // views: {
717
- // $default: {
718
- // template: '<a ui-sref=".item({ id: 6 })" ui-sref-active="active">Contacts</a>',
719
- // },
720
- // },
721
- // })
722
- // .state({name: 'contacts.item', url: '/:id',
723
- // })
724
- // .state({name: 'contacts.item.detail', url: '/detail/:foo',
725
- // })
726
- // .state({name: 'contacts.item.edit', url: '/edit',
727
- // })
728
- // .state({name: 'admin', url: '/admin',
729
- // abstract: true,
730
- // template: '<ui-view/>',
731
- // })
732
- // .state({name: 'admin.roles', url: '/roles?page',
733
- // })
734
- // .state({name: 'arrayparam', url: '/arrayparam?{foo:int}&bar',
735
- // template: '<div></div>',
736
- // });
737
- // })
738
- // );
739
-
740
- // beforeEach(inject(function ($document, $timeout) {
741
- // document = $document[0];
742
- // timeoutFlush = function () {
743
- // try {
744
- // $timeout.flush();
745
- // } catch (e) {
746
- // // Angular 1.0.8 throws 'No deferred tasks to be flushed' if there is nothing in queue.
747
- // // Behave as Angular >=1.1.5 and do nothing in such case.
748
- // }
749
- // };
750
- // });
751
-
752
- // it('should update class for sibling uiSref', inject(function ($rootScope, $q, $compile, $state) {
753
- // el = angular.element(
754
- // '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active">Contacts</a><a ui-sref="contacts.item({ id: 2 })" ui-sref-active="active">Contacts</a></div>'
755
- // );
756
- // template = $compile(el)($rootScope);
757
- // $rootScope.$digest();
758
-
759
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
760
- // $state.transitionTo('contacts.item', { id: 1 });
761
- // $q.flush();
762
- // timeoutFlush();
763
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
764
-
765
- // $state.transitionTo('contacts.item', { id: 2 });
766
- // $q.flush();
767
- // timeoutFlush();
768
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
769
- // });
770
-
771
- // it("should match state's parameters", inject(function ($rootScope, $q, $compile, $state) {
772
- // el = angular.element(
773
- // '<div><a ui-sref="contacts.item.detail({ foo: \'bar\' })" ui-sref-active="active">Contacts</a></div>'
774
- // );
775
- // template = $compile(el)($rootScope);
776
- // $rootScope.$digest();
777
-
778
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
779
- // $state.transitionTo('contacts.item.detail', { id: 5, foo: 'bar' });
780
- // $q.flush();
781
- // timeoutFlush();
782
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
783
-
784
- // $state.transitionTo('contacts.item.detail', { id: 5, foo: 'baz' });
785
- // $q.flush();
786
- // timeoutFlush();
787
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
788
- // });
789
-
790
- // // Test for #2696
791
- // it('should compare using typed parameters', inject(function ($rootScope, $q, $compile, $state) {
792
- // el = angular.element('<div><a ui-sref="arrayparam({ foo: [1,2,3] })" ui-sref-active="active">foo 123</a></div>');
793
- // template = $compile(el)($rootScope);
794
- // $rootScope.$digest();
795
-
796
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
797
-
798
- // $state.transitionTo('arrayparam', { foo: [1, 2, 3] });
799
- // $q.flush();
800
- // timeoutFlush();
801
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
802
-
803
- // $state.transitionTo('arrayparam', { foo: [1, 2, 3], bar: 'asdf' });
804
- // $q.flush();
805
- // timeoutFlush();
806
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
807
-
808
- // $state.transitionTo('arrayparam', { foo: [1, 2] });
809
- // $q.flush();
810
- // timeoutFlush();
811
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
812
- // });
813
-
814
- // // Test for #3154
815
- // it('should compare ui-sref-active-eq using typed parameters', inject(function ($rootScope, $q, $compile, $state) {
816
- // el = angular.element('<div><a ui-sref="arrayparam({ foo: [1,2,3] })" ui-sref-active-eq="active">foo 123</a></div>');
817
- // template = $compile(el)($rootScope);
818
- // $rootScope.$digest();
819
-
820
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
821
-
822
- // $state.transitionTo('arrayparam', { foo: [1, 2, 3] });
823
- // $q.flush();
824
- // timeoutFlush();
825
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
826
-
827
- // $state.transitionTo('arrayparam', { foo: [1, 2, 3], bar: 'asdf' });
828
- // $q.flush();
829
- // timeoutFlush();
830
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
831
-
832
- // $state.transitionTo('arrayparam', { foo: [1, 2] });
833
- // $q.flush();
834
- // timeoutFlush();
835
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
836
- // });
837
-
838
- // it('should update in response to ui-sref param expression changes', inject(function (
839
- // $rootScope,
840
- // $q,
841
- // $compile,
842
- // $state
843
- // ) {
844
- // el = angular.element(
845
- // '<div><a ui-sref="contacts.item.detail({ foo: fooId })" ui-sref-active="active">Contacts</a></div>'
846
- // );
847
- // template = $compile(el)($rootScope);
848
- // $rootScope.fooId = 'bar';
849
- // $rootScope.$digest();
850
-
851
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
852
- // $state.transitionTo('contacts.item.detail', { id: 5, foo: 'bar' });
853
- // $q.flush();
854
- // timeoutFlush();
855
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
856
-
857
- // $rootScope.fooId = 'baz';
858
- // $q.flush();
859
- // timeoutFlush();
860
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
861
- // });
862
-
863
- // it('should match on child states', inject(function ($rootScope, $q, $compile, $state) {
864
- // template = $compile('<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active">Contacts</a></div>')(
865
- // $rootScope
866
- // );
867
- // $rootScope.$digest();
868
- // const a = angular.element(template[0].getElementsByTagName('a')[0]);
869
-
870
- // $state.transitionTo('contacts.item.edit', { id: 1 });
871
- // $q.flush();
872
- // timeoutFlush();
873
- // expect($state.params.id).toBe('1');
874
- // expect(a.attr('class')).toMatch(/active/);
875
-
876
- // $state.transitionTo('contacts.item.edit', { id: 4 });
877
- // $q.flush();
878
- // timeoutFlush();
879
- // expect($state.params.id).toBe('4');
880
- // expect(a.attr('class')).not.toMatch(/active/);
881
- // });
882
-
883
- // it('should NOT match on child states when active-equals is used', inject(function ($rootScope, $q, $compile, $state) {
884
- // template = $compile('<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active-eq="active">Contacts</a></div>')(
885
- // $rootScope
886
- // );
887
- // $rootScope.$digest();
888
- // const a = angular.element(template[0].getElementsByTagName('a')[0]);
889
-
890
- // $state.transitionTo('contacts.item', { id: 1 });
891
- // $q.flush();
892
- // timeoutFlush();
893
- // expect(a.attr('class')).toMatch(/active/);
894
-
895
- // $state.transitionTo('contacts.item.edit', { id: 1 });
896
- // $q.flush();
897
- // timeoutFlush();
898
- // expect(a.attr('class')).not.toMatch(/active/);
899
- // });
900
-
901
- // it('should match on child states when active-equals and active-equals-eq is used', inject(function (
902
- // $rootScope,
903
- // $q,
904
- // $compile,
905
- // $state,
906
- // $timeout
907
- // ) {
908
- // template = $compile(
909
- // '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active" ui-sref-active-eq="active-eq">Contacts</a></div>'
910
- // )($rootScope);
911
- // $rootScope.$digest();
912
- // const a = angular.element(template[0].getElementsByTagName('a')[0]);
913
-
914
- // $state.transitionTo('contacts.item', { id: 1 });
915
- // $q.flush();
916
- // timeoutFlush();
917
- // expect(a.attr('class')).toMatch(/active/);
918
- // expect(a.attr('class')).toMatch(/active-eq/);
919
-
920
- // $state.transitionTo('contacts.item.edit', { id: 1 });
921
- // $q.flush();
922
- // timeoutFlush();
923
- // expect(a.attr('class')).toMatch(/active/);
924
- // expect(a.attr('class')).not.toMatch(/active-eq/);
925
- // });
926
-
927
- // it('should resolve relative state refs', inject(function ($rootScope, $q, $compile, $state) {
928
- // el = angular.element('<section><div ui-view></div></section>');
929
- // template = $compile(el)($rootScope);
930
- // $rootScope.$digest();
931
-
932
- // $state.transitionTo('contacts');
933
- // $q.flush();
934
- // timeoutFlush();
935
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('ng-scope');
936
-
937
- // $state.transitionTo('contacts.item', { id: 6 });
938
- // $q.flush();
939
- // timeoutFlush();
940
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('ng-scope active');
941
-
942
- // $state.transitionTo('contacts.item', { id: 5 });
943
- // $q.flush();
944
- // timeoutFlush();
945
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('ng-scope');
946
- // });
947
-
948
- // it('should match on any child state refs', inject(function ($rootScope, $q, $compile, $state) {
949
- // el = angular.element(
950
- // '<div ui-sref-active="active"><a ui-sref="contacts.item({ id: 1 })">Contacts</a><a ui-sref="contacts.item({ id: 2 })">Contacts</a></div>'
951
- // );
952
- // template = $compile(el)($rootScope);
953
- // $rootScope.$digest();
954
-
955
- // expect(angular.element(template[0]).attr('class')).toBe('ng-scope');
956
-
957
- // $state.transitionTo('contacts.item', { id: 1 });
958
- // $q.flush();
959
- // timeoutFlush();
960
- // expect(angular.element(template[0]).attr('class')).toBe('ng-scope active');
961
-
962
- // $state.transitionTo('contacts.item', { id: 2 });
963
- // $q.flush();
964
- // timeoutFlush();
965
- // expect(angular.element(template[0]).attr('class')).toBe('ng-scope active');
966
- // });
967
-
968
- // it('should match fuzzy on lazy loaded states', inject(function ($rootScope, $q, $compile, $state) {
969
- // el = angular.element('<div><a ui-sref="contacts.lazy" ui-sref-active="active">Lazy Contact</a></div>');
970
- // template = $compile(el)($rootScope);
971
- // $q.flush();
972
-
973
- // _stateProvider.onInvalid(function ($to$) {
974
- // if ($to$.name() === 'contacts.lazy') {
975
- // _stateProvider.state({name: 'contacts.lazy', {});
976
- // return $to$;
977
- // }
978
- // });
979
-
980
- // $state.transitionTo('contacts.item', { id: 1 });
981
- // $q.flush();
982
- // timeoutFlush();
983
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
984
-
985
- // $state.transitionTo('contacts.lazy');
986
- // $q.flush();
987
- // timeoutFlush();
988
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
989
- // });
990
-
991
- // it('should match exactly on lazy loaded states', inject(function ($transitions, $rootScope, $q, $compile, $state) {
992
- // el = angular.element('<div><a ui-sref="contacts.lazy" ui-sref-active-eq="active">Lazy Contact</a></div>');
993
- // template = $compile(el)($rootScope);
994
- // $q.flush();
995
-
996
- // _stateProvider.onInvalid(function ($to$) {
997
- // if ($to$.name() === 'contacts.lazy') {
998
- // _stateProvider.state({name: 'contacts.lazy', {});
999
- // return $to$;
1000
- // }
1001
- // });
1002
-
1003
- // $state.transitionTo('contacts.item', { id: 1 });
1004
- // $q.flush();
1005
- // timeoutFlush();
1006
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBeFalsy();
1007
-
1008
- // $state.transitionTo('contacts.lazy');
1009
- // $q.flush();
1010
- // timeoutFlush();
1011
- // expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('active');
1012
- // });
1013
-
1014
- // it('should allow multiple classes to be supplied', inject(function ($rootScope, $q, $compile, $state) {
1015
- // template = $compile(
1016
- // '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active also-active">Contacts</a></div>'
1017
- // )($rootScope);
1018
- // $rootScope.$digest();
1019
- // const a = angular.element(template[0].getElementsByTagName('a')[0]);
1020
-
1021
- // $state.transitionTo('contacts.item.edit', { id: 1 });
1022
- // $q.flush();
1023
- // timeoutFlush();
1024
- // expect(a.attr('class')).toMatch(/active also-active/);
1025
- // });
1026
-
1027
- // it('should not match fuzzy on lazy loaded future states', inject(function ($rootScope, $compile, $q, $state) {
1028
- // _stateProvider.state({name: 'contacts.lazy.**', {
1029
- // url: '/lazy',
1030
- // lazyLoad: function () {
1031
- // return $q.when().then(function () {
1032
- // _stateProvider
1033
- // .state({name: 'contacts.lazy', {
1034
- // abstract: true,
1035
- // url: '/lazy',
1036
- // })
1037
- // .state({name: 'contacts.lazy.s1', {
1038
- // url: '/s1',
1039
- // })
1040
- // .state({name: 'contacts.lazy.s2', {
1041
- // url: '/s2',
1042
- // });
1043
- // });
1044
- // },
1045
- // });
1046
- // template = $compile(
1047
- // '<div ui-sref-active="active"><a ui-sref="contacts.lazy.s1">Lazy</a></div><div ui-sref-active="active"><a ui-sref="contacts.lazy.s2"></a></div>'
1048
- // )($rootScope);
1049
- // $rootScope.$digest();
1050
- // $state.transitionTo('contacts.lazy.s1');
1051
- // $q.flush();
1052
- // timeoutFlush();
1053
- // expect(template.eq(0).hasClass('active')).toBeTruthy();
1054
- // expect(template.eq(1).hasClass('active')).toBeFalsy();
1055
- // });
1056
-
1057
- // describe('ng-{class,style} interface', function () {
1058
- // it('should match on abstract states that are included by the current state', inject(function (
1059
- // $rootScope,
1060
- // $compile,
1061
- // $state,
1062
- // $q
1063
- // ) {
1064
- // el = $compile(
1065
- // '<div ui-sref-active="{active: \'admin.*\'}"><a ui-sref-active="active" ui-sref="admin.roles">Roles</a></div>'
1066
- // )($rootScope);
1067
- // $state.transitionTo('admin.roles');
1068
- // $q.flush();
1069
- // timeoutFlush();
1070
- // const abstractParent = el[0];
1071
- // expect(abstractParent.className).toMatch(/active/);
1072
- // const child = el[0].querySelector('a');
1073
- // expect(child.className).toMatch(/active/);
1074
- // });
1075
-
1076
- // it('should match on state parameters', async () => {
1077
- // el = $compile('<div ui-sref-active="{active: \'admin.roles({page: 1})\'}"></div>')($rootScope);
1078
- // $state.transitionTo('admin.roles', { page: 1 });
1079
- // $q.flush();
1080
- // timeoutFlush();
1081
- // expect(el[0].className).toMatch(/active/);
1082
- // });
1083
-
1084
- // it('should shadow the state provided by ui-sref', async () => {
1085
- // el = $compile('<div ui-sref-active="{active: \'admin.roles({page: 1})\'}"><a ui-sref="admin.roles"></a></div>')(
1086
- // $rootScope
1087
- // );
1088
- // $state.transitionTo('admin.roles');
1089
- // $q.flush();
1090
- // timeoutFlush();
1091
- // expect(el[0].className).not.toMatch(/active/);
1092
- // $state.transitionTo('admin.roles', { page: 1 });
1093
- // $q.flush();
1094
- // timeoutFlush();
1095
- // expect(el[0].className).toMatch(/active/);
1096
- // });
1097
-
1098
- // it('should support multiple <className, stateOrName> pairs', async () => {
1099
- // el = $compile("<div ui-sref-active=\"{contacts: 'contacts.**', admin: 'admin.roles({page: 1})'}\"></div>")(
1100
- // $rootScope
1101
- // );
1102
- // $state.transitionTo('contacts');
1103
- // $q.flush();
1104
- // timeoutFlush();
1105
- // expect(el[0].className).toMatch(/contacts/);
1106
- // expect(el[0].className).not.toMatch(/admin/);
1107
- // $state.transitionTo('admin.roles', { page: 1 });
1108
- // $q.flush();
1109
- // timeoutFlush();
1110
- // expect(el[0].className).toMatch(/admin/);
1111
- // expect(el[0].className).not.toMatch(/contacts/);
1112
- // });
1113
-
1114
- // it('should update the active classes when compiled', inject(function ($compile, $rootScope, $document, $state, $q) {
1115
- // $state.transitionTo('admin.roles');
1116
- // $q.flush();
1117
- // timeoutFlush();
1118
- // el = $compile('<div ui-sref-active="{active: \'admin.roles\'}"/>')($rootScope);
1119
- // $rootScope.$digest();
1120
- // timeoutFlush();
1121
- // expect(el.hasClass('active')).toBeTruthy();
1122
- // });
1123
-
1124
- // it('should not match fuzzy on lazy loaded future states', inject(function ($rootScope, $compile, $q, $state) {
1125
- // _stateProvider.state({name: 'contacts.lazy.**', {
1126
- // url: '/lazy',
1127
- // lazyLoad: function () {
1128
- // return $q.when().then(function () {
1129
- // _stateProvider
1130
- // .state({name: 'contacts.lazy', {
1131
- // abstract: true,
1132
- // url: '/lazy',
1133
- // })
1134
- // .state({name: 'contacts.lazy.s1', {
1135
- // url: '/s1',
1136
- // })
1137
- // .state({name: 'contacts.lazy.s2', {
1138
- // url: '/s2',
1139
- // });
1140
- // });
1141
- // },
1142
- // });
1143
- // template = $compile(
1144
- // '<div ui-sref-active="{ active: \'contacts.lazy.s1\' }"><a ui-sref="contacts.lazy.s1">Lazy</a></div><div ui-sref-active="{ active: \'contacts.lazy.s2\' }"></div>'
1145
- // )($rootScope);
1146
- // $rootScope.$digest();
1147
- // $state.transitionTo('contacts.lazy.s1');
1148
- // $q.flush();
1149
- // timeoutFlush();
1150
- // expect(template.eq(0).hasClass('active')).toBeTruthy();
1151
- // expect(template.eq(1).hasClass('active')).toBeFalsy();
1152
- // });
1153
- // });
1154
-
1155
- // describe('ng-{class,style} interface, and handle values as arrays', function () {
1156
- // it('should match on abstract states that are included by the current state', inject(function (
1157
- // $rootScope,
1158
- // $compile,
1159
- // $state,
1160
- // $q
1161
- // ) {
1162
- // el = $compile(
1163
- // '<div ui-sref-active="{active: [\'randomState.**\', \'admin.roles\']}"><a ui-sref-active="active" ui-sref="admin.roles">Roles</a></div>'
1164
- // )($rootScope);
1165
- // $state.transitionTo('admin.roles');
1166
- // $q.flush();
1167
- // timeoutFlush();
1168
- // const abstractParent = el[0];
1169
- // expect(abstractParent.className).toMatch(/active/);
1170
- // const child = el[0].querySelector('a');
1171
- // expect(child.className).toMatch(/active/);
1172
- // });
1173
-
1174
- // it('should match on state parameters', async () => {
1175
- // el = $compile('<div ui-sref-active="{active: [\'admin.roles({page: 1})\']}"></div>')($rootScope);
1176
- // $state.transitionTo('admin.roles', { page: 1 });
1177
- // $q.flush();
1178
- // timeoutFlush();
1179
- // expect(el[0].className).toMatch(/active/);
1180
- // });
1181
-
1182
- // it('should support multiple <className, stateOrName> pairs', async () => {
1183
- // el = $compile(
1184
- // "<div ui-sref-active=\"{contacts: ['contacts.item', 'contacts.item.detail'], admin: 'admin.roles({page: 1})'}\"></div>"
1185
- // )($rootScope);
1186
- // $state.transitionTo('contacts.item.detail', { id: 1, foo: 'bar' });
1187
- // $q.flush();
1188
- // timeoutFlush();
1189
- // expect(el[0].className).toMatch(/contacts/);
1190
- // expect(el[0].className).not.toMatch(/admin/);
1191
- // $state.transitionTo('admin.roles', { page: 1 });
1192
- // $q.flush();
1193
- // timeoutFlush();
1194
- // expect(el[0].className).toMatch(/admin/);
1195
- // expect(el[0].className).not.toMatch(/contacts/);
1196
- // });
1197
-
1198
- // it('should update the active classes when compiled', inject(function ($compile, $rootScope, $document, $state, $q) {
1199
- // $state.transitionTo('admin.roles');
1200
- // $q.flush();
1201
- // timeoutFlush();
1202
- // el = $compile("<div ui-sref-active=\"{active: ['admin.roles', 'admin.someOtherState']}\"/>")($rootScope);
1203
- // $rootScope.$digest();
1204
- // timeoutFlush();
1205
- // expect(el.hasClass('active')).toBeTruthy();
1206
- // });
1207
- // });
1208
- // });
717
+ describe("uiSrefActive", () => {
718
+ window.location.hash = "#!";
719
+ let el,
720
+ el2,
721
+ template,
722
+ scope,
723
+ _locationProvider,
724
+ $rootScope,
725
+ $compile,
726
+ $q,
727
+ $injector,
728
+ $timeout,
729
+ $state,
730
+ $stateParams,
731
+ _stateProvider;
732
+
733
+ beforeEach(() => {
734
+ window.location.hash = "#!";
735
+ window.angular = new Angular();
736
+ publishExternalAPI();
737
+ let module = window.angular.module("defaultModule", ["ui.router"]);
738
+ module.config(function ($stateProvider) {
739
+ _stateProvider = $stateProvider;
740
+ $stateProvider
741
+ .state({ name: "top", url: "" })
742
+ .state({
743
+ name: "contacts",
744
+ url: "/contacts",
745
+ views: {
746
+ $default: {
747
+ template:
748
+ '<a ui-sref=".item({ id: 6 })" ui-sref-active="active">Contacts</a>',
749
+ },
750
+ },
751
+ })
752
+ .state({ name: "contacts.item", url: "/:id" })
753
+ .state({ name: "contacts.item.detail", url: "/detail/:foo" })
754
+ .state({ name: "contacts.item.edit", url: "/edit" })
755
+ .state({
756
+ name: "admin",
757
+ url: "/admin",
758
+ abstract: true,
759
+ template: "<ui-view/>",
760
+ })
761
+ .state({ name: "admin.roles", url: "/roles?page" })
762
+ .state({
763
+ name: "arrayparam",
764
+ url: "/arrayparam?{foo:int}&bar",
765
+ template: "<div></div>",
766
+ });
767
+ });
768
+ $injector = window.angular.bootstrap(document.getElementById("dummy"), [
769
+ "defaultModule",
770
+ ]);
771
+ $q = $injector.get("$q");
772
+ $rootScope = $injector.get("$rootScope");
773
+ $compile = $injector.get("$compile");
774
+ $timeout = $injector.get("$timeout");
775
+ $state = $injector.get("$state");
776
+ $stateParams = $injector.get("$stateParams");
777
+ });
778
+
779
+ it("should update class for sibling uiSref", async () => {
780
+ el = jqLite(
781
+ '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active">Contacts</a><a ui-sref="contacts.item({ id: 2 })" ui-sref-active="active">Contacts</a></div>',
782
+ );
783
+ template = $compile(el)($rootScope);
784
+ $rootScope.$digest();
785
+
786
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
787
+ $state.transitionTo("contacts.item", { id: 1 });
788
+ await wait(10);
789
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
790
+
791
+ $state.transitionTo("contacts.item", { id: 2 });
792
+ await wait(10);
793
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
794
+ });
795
+
796
+ it("should match state's parameters", async () => {
797
+ el = jqLite(
798
+ '<div><a ui-sref="contacts.item.detail({ foo: \'bar\' })" ui-sref-active="active">Contacts</a></div>',
799
+ );
800
+ template = $compile(el)($rootScope);
801
+ $rootScope.$digest();
802
+
803
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
804
+ $state.transitionTo("contacts.item.detail", { id: 5, foo: "bar" });
805
+ await wait(10);
806
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
807
+
808
+ $state.transitionTo("contacts.item.detail", { id: 5, foo: "baz" });
809
+ await wait(10);
810
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
811
+ });
812
+
813
+ // Test for #2696
814
+ it("should compare using typed parameters", async () => {
815
+ el = jqLite(
816
+ '<div><a ui-sref="arrayparam({ foo: [1,2,3] })" ui-sref-active="active">foo 123</a></div>',
817
+ );
818
+ template = $compile(el)($rootScope);
819
+ $rootScope.$digest();
820
+
821
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
822
+
823
+ $state.transitionTo("arrayparam", { foo: [1, 2, 3] });
824
+ await wait(10);
825
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
826
+
827
+ $state.transitionTo("arrayparam", { foo: [1, 2, 3], bar: "asdf" });
828
+ await wait(10);
829
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
830
+
831
+ $state.transitionTo("arrayparam", { foo: [1, 2] });
832
+ await wait(10);
833
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
834
+ });
835
+
836
+ // Test for #3154
837
+ it("should compare ui-sref-active-eq using typed parameters", async () => {
838
+ el = jqLite(
839
+ '<div><a ui-sref="arrayparam({ foo: [1,2,3] })" ui-sref-active-eq="active">foo 123</a></div>',
840
+ );
841
+ template = $compile(el)($rootScope);
842
+ $rootScope.$digest();
843
+
844
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
845
+
846
+ $state.transitionTo("arrayparam", { foo: [1, 2, 3] });
847
+ await wait(10);
848
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
849
+
850
+ $state.transitionTo("arrayparam", { foo: [1, 2, 3], bar: "asdf" });
851
+ await wait(10);
852
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
853
+
854
+ $state.transitionTo("arrayparam", { foo: [1, 2] });
855
+ await wait(10);
856
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
857
+ });
858
+
859
+ it("should update in response to ui-sref param expression changes", async () => {
860
+ el = jqLite(
861
+ '<div><a ui-sref="contacts.item.detail({ foo: fooId })" ui-sref-active="active">Contacts</a></div>',
862
+ );
863
+ template = $compile(el)($rootScope);
864
+ $rootScope.fooId = "bar";
865
+ $rootScope.$digest();
866
+
867
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
868
+ $state.transitionTo("contacts.item.detail", { id: 5, foo: "bar" });
869
+ await wait(10);
870
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
871
+
872
+ $rootScope.fooId = "baz";
873
+ $rootScope.$digest();
874
+ await wait(10);
875
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
876
+ });
877
+
878
+ it("should match on child states", async () => {
879
+ template = $compile(
880
+ '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active">Contacts</a></div>',
881
+ )($rootScope);
882
+ $rootScope.$digest();
883
+ const a = jqLite(template[0].getElementsByTagName("a")[0]);
884
+
885
+ $state.transitionTo("contacts.item.edit", { id: 1 });
886
+ await wait(10);
887
+ expect($state.params.id).toBe("1");
888
+ expect(a.attr("class")).toMatch(/active/);
889
+
890
+ $state.transitionTo("contacts.item.edit", { id: 4 });
891
+ await wait(10);
892
+ expect($state.params.id).toBe("4");
893
+ expect(a.attr("class")).not.toMatch(/active/);
894
+ });
895
+
896
+ it("should NOT match on child states when active-equals is used", async () => {
897
+ template = $compile(
898
+ '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active-eq="active">Contacts</a></div>',
899
+ )($rootScope);
900
+ $rootScope.$digest();
901
+ const a = jqLite(template[0].getElementsByTagName("a")[0]);
902
+
903
+ $state.transitionTo("contacts.item", { id: 1 });
904
+ await wait(10);
905
+ expect(a.attr("class")).toMatch(/active/);
906
+
907
+ $state.transitionTo("contacts.item.edit", { id: 1 });
908
+ await wait(10);
909
+ expect(a.attr("class")).not.toMatch(/active/);
910
+ });
911
+
912
+ it("should match on child states when active-equals and active-equals-eq is used", async () => {
913
+ template = $compile(
914
+ '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active" ui-sref-active-eq="active-eq">Contacts</a></div>',
915
+ )($rootScope);
916
+ $rootScope.$digest();
917
+ const a = jqLite(template[0].getElementsByTagName("a")[0]);
918
+
919
+ $state.transitionTo("contacts.item", { id: 1 });
920
+ await wait(10);
921
+ expect(a.attr("class")).toMatch(/active/);
922
+ expect(a.attr("class")).toMatch(/active-eq/);
923
+
924
+ $state.transitionTo("contacts.item.edit", { id: 1 });
925
+ await wait(10);
926
+ expect(a.attr("class")).toMatch(/active/);
927
+ expect(a.attr("class")).not.toMatch(/active-eq/);
928
+ });
929
+
930
+ it("should resolve relative state refs", async () => {
931
+ el = jqLite("<section><div ui-view></div></section>");
932
+ template = $compile(el)($rootScope);
933
+ $rootScope.$digest();
934
+
935
+ $state.transitionTo("contacts");
936
+ await wait(10);
937
+ expect(
938
+ jqLite(template[0].querySelector("a")).attr("class"),
939
+ ).toBeUndefined();
940
+
941
+ $state.transitionTo("contacts.item", { id: 6 });
942
+ await wait(10);
943
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
944
+
945
+ $state.transitionTo("contacts.item", { id: 5 });
946
+ await wait(10);
947
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("");
948
+ });
949
+
950
+ it("should match on any child state refs", async () => {
951
+ el = jqLite(
952
+ '<div ui-sref-active="active"><a ui-sref="contacts.item({ id: 1 })">Contacts</a><a ui-sref="contacts.item({ id: 2 })">Contacts</a></div>',
953
+ );
954
+ template = $compile(el)($rootScope);
955
+ $rootScope.$digest();
956
+
957
+ expect(jqLite(template[0]).attr("class")).toBeUndefined();
958
+
959
+ $state.transitionTo("contacts.item", { id: 1 });
960
+ await wait(10);
961
+ expect(jqLite(template[0]).attr("class")).toBe("active");
962
+
963
+ $state.transitionTo("contacts.item", { id: 2 });
964
+ await wait(10);
965
+ expect(jqLite(template[0]).attr("class")).toBe("active");
966
+ });
967
+
968
+ it("should match fuzzy on lazy loaded states", async () => {
969
+ el = jqLite(
970
+ '<div><a ui-sref="contacts.lazy" ui-sref-active="active">Lazy Contact</a></div>',
971
+ );
972
+ template = $compile(el)($rootScope);
973
+ await wait(10);
974
+
975
+ _stateProvider.onInvalid(function ($to$) {
976
+ if ($to$.name() === "contacts.lazy") {
977
+ _stateProvider.state({ name: "contacts.lazy" });
978
+ return $to$;
979
+ }
980
+ });
981
+
982
+ $state.transitionTo("contacts.item", { id: 1 });
983
+ await wait(10);
984
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
985
+
986
+ $state.transitionTo("contacts.lazy");
987
+ await wait(10);
988
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
989
+ });
990
+
991
+ it("should match exactly on lazy loaded states", async () => {
992
+ el = jqLite(
993
+ '<div><a ui-sref="contacts.lazy" ui-sref-active-eq="active">Lazy Contact</a></div>',
994
+ );
995
+ template = $compile(el)($rootScope);
996
+ await wait(10);
997
+
998
+ _stateProvider.onInvalid(function ($to$) {
999
+ if ($to$.name() === "contacts.lazy") {
1000
+ _stateProvider.state({ name: "contacts.lazy" });
1001
+ return $to$;
1002
+ }
1003
+ });
1004
+
1005
+ $state.transitionTo("contacts.item", { id: 1 });
1006
+ await wait(10);
1007
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBeFalsy();
1008
+
1009
+ $state.transitionTo("contacts.lazy");
1010
+ await wait(10);
1011
+ expect(jqLite(template[0].querySelector("a")).attr("class")).toBe("active");
1012
+ });
1013
+
1014
+ it("should allow multiple classes to be supplied", async () => {
1015
+ template = $compile(
1016
+ '<div><a ui-sref="contacts.item({ id: 1 })" ui-sref-active="active also-active">Contacts</a></div>',
1017
+ )($rootScope);
1018
+ $rootScope.$digest();
1019
+ const a = jqLite(template[0].getElementsByTagName("a")[0]);
1020
+
1021
+ $state.transitionTo("contacts.item.edit", { id: 1 });
1022
+ await wait(10);
1023
+ expect(a.attr("class")).toMatch(/active also-active/);
1024
+ });
1025
+
1026
+ // TODO does not work
1027
+ xit("should not match fuzzy on lazy loaded future states", async () => {
1028
+ _stateProvider.state({
1029
+ name: "contacts.lazy.**",
1030
+ url: "/lazy",
1031
+ lazyLoad: () => {
1032
+ return $q.when().then(() => {
1033
+ _stateProvider
1034
+ .state({ name: "contacts.lazy", abstract: true, url: "/lazy" })
1035
+ .state({ name: "contacts.lazy.s1", url: "/s1" })
1036
+ .state({ name: "contacts.lazy.s2", url: "/s2" });
1037
+ });
1038
+ },
1039
+ });
1040
+ template = $compile(
1041
+ '<div ui-sref-active="active"><a ui-sref="contacts.lazy.s1">Lazy</a></div><div ui-sref-active="active"><a ui-sref="contacts.lazy.s2"></a></div>',
1042
+ )($rootScope);
1043
+ $rootScope.$digest();
1044
+ $state.transitionTo("contacts.lazy.s1");
1045
+ await wait(10);
1046
+
1047
+ expect(template.eq(0)[0].hasClass("active")).toBeTruthy();
1048
+ //expect(template.eq(1).hasClass("active")).toBeFalsy();
1049
+ });
1050
+
1051
+ // TODO investigate why transitions error out
1052
+ xdescribe("ng-{class,style} interface", () => {
1053
+ it("should match on abstract states that are included by the current state", async () => {
1054
+ el = $compile(
1055
+ '<div ui-sref-active="{active: \'admin.*\'}"><a ui-sref-active="active" ui-sref="admin.roles">Roles</a></div>',
1056
+ )($rootScope);
1057
+ $state.transitionTo("admin.roles");
1058
+ await wait(10);
1059
+ const abstractParent = el[0];
1060
+ expect(abstractParent.className).toMatch(/active/);
1061
+ const child = el[0].querySelector("a");
1062
+ expect(child.className).toMatch(/active/);
1063
+ });
1064
+
1065
+ it("should match on state parameters", async () => {
1066
+ el = $compile(
1067
+ "<div ui-sref-active=\"{active: 'admin.roles({page: 1})'}\"></div>",
1068
+ )($rootScope);
1069
+ $state.transitionTo("admin.roles", { page: 1 });
1070
+ await wait(10);
1071
+ expect(el[0].className).toMatch(/active/);
1072
+ });
1073
+
1074
+ it("should shadow the state provided by ui-sref", async () => {
1075
+ el = $compile(
1076
+ '<div ui-sref-active="{active: \'admin.roles({page: 1})\'}"><a ui-sref="admin.roles"></a></div>',
1077
+ )($rootScope);
1078
+ $state.transitionTo("admin.roles");
1079
+ await wait(10);
1080
+ expect(el[0].className).not.toMatch(/active/);
1081
+ $state.transitionTo("admin.roles", { page: 1 });
1082
+ await wait(10);
1083
+ expect(el[0].className).toMatch(/active/);
1084
+ });
1085
+
1086
+ it("should support multiple <className, stateOrName> pairs", async () => {
1087
+ el = $compile(
1088
+ "<div ui-sref-active=\"{contacts: 'contacts.**', admin: 'admin.roles({page: 1})'}\"></div>",
1089
+ )($rootScope);
1090
+ $state.transitionTo("contacts");
1091
+ await wait(10);
1092
+ expect(el[0].className).toMatch(/contacts/);
1093
+ expect(el[0].className).not.toMatch(/admin/);
1094
+ $state.transitionTo("admin.roles", { page: 1 });
1095
+ await wait(10);
1096
+ expect(el[0].className).toMatch(/admin/);
1097
+ expect(el[0].className).not.toMatch(/contacts/);
1098
+ });
1099
+
1100
+ it("should update the active classes when compiled", async () => {
1101
+ $state.transitionTo("admin.roles");
1102
+ await wait(10);
1103
+ el = $compile("<div ui-sref-active=\"{active: 'admin.roles'}\"/>")(
1104
+ $rootScope,
1105
+ );
1106
+ $rootScope.$digest();
1107
+ timeoutFlush();
1108
+ expect(el.hasClass("active")).toBeTruthy();
1109
+ });
1110
+
1111
+ it("should not match fuzzy on lazy loaded future states", async () => {
1112
+ _stateProvider.state({
1113
+ name: "contacts.lazy.**",
1114
+ url: "/lazy",
1115
+ lazyLoad: () => {
1116
+ return $q.when().then(() => {
1117
+ _stateProvider
1118
+ .state({ name: "contacts.lazy", abstract: true, url: "/lazy" })
1119
+ .state({ name: "contacts.lazy.s1", url: "/s1" })
1120
+ .state({ name: "contacts.lazy.s2", url: "/s2" });
1121
+ });
1122
+ },
1123
+ });
1124
+ template = $compile(
1125
+ '<div ui-sref-active="{ active: \'contacts.lazy.s1\' }"><a ui-sref="contacts.lazy.s1">Lazy</a></div><div ui-sref-active="{ active: \'contacts.lazy.s2\' }"></div>',
1126
+ )($rootScope);
1127
+ $rootScope.$digest();
1128
+ $state.transitionTo("contacts.lazy.s1");
1129
+ await wait(10);
1130
+ expect(template.eq(0).hasClass("active")).toBeTruthy();
1131
+ expect(template.eq(1).hasClass("active")).toBeFalsy();
1132
+ });
1133
+ });
1134
+
1135
+ xdescribe("ng-{class,style} interface, and handle values as arrays", () => {
1136
+ it("should match on abstract states that are included by the current state", async () => {
1137
+ el = $compile(
1138
+ '<div ui-sref-active="{active: [\'randomState.**\', \'admin.roles\']}"><a ui-sref-active="active" ui-sref="admin.roles">Roles</a></div>',
1139
+ )($rootScope);
1140
+ $state.transitionTo("admin.roles");
1141
+ await wait(10);
1142
+ const abstractParent = el[0];
1143
+ expect(abstractParent.className).toMatch(/active/);
1144
+ const child = el[0].querySelector("a");
1145
+ expect(child.className).toMatch(/active/);
1146
+ });
1147
+
1148
+ it("should match on state parameters", async () => {
1149
+ el = $compile(
1150
+ "<div ui-sref-active=\"{active: ['admin.roles({page: 1})']}\"></div>",
1151
+ )($rootScope);
1152
+ $state.transitionTo("admin.roles", { page: 1 });
1153
+ await wait(10);
1154
+ expect(el[0].className).toMatch(/active/);
1155
+ });
1156
+
1157
+ it("should support multiple <className, stateOrName> pairs", async () => {
1158
+ el = $compile(
1159
+ "<div ui-sref-active=\"{contacts: ['contacts.item', 'contacts.item.detail'], admin: 'admin.roles({page: 1})'}\"></div>",
1160
+ )($rootScope);
1161
+ $state.transitionTo("contacts.item.detail", { id: 1, foo: "bar" });
1162
+ await wait(10);
1163
+ expect(el[0].className).toMatch(/contacts/);
1164
+ expect(el[0].className).not.toMatch(/admin/);
1165
+ $state.transitionTo("admin.roles", { page: 1 });
1166
+ await wait(10);
1167
+ expect(el[0].className).toMatch(/admin/);
1168
+ expect(el[0].className).not.toMatch(/contacts/);
1169
+ });
1170
+
1171
+ it("should update the active classes when compiled", async () => {
1172
+ $state.transitionTo("admin.roles");
1173
+ await wait(10);
1174
+ el = $compile(
1175
+ "<div ui-sref-active=\"{active: ['admin.roles', 'admin.someOtherState']}\"/>",
1176
+ )($rootScope);
1177
+ $rootScope.$digest();
1178
+ timeoutFlush();
1179
+ expect(el.hasClass("active")).toBeTruthy();
1180
+ });
1181
+ });
1182
+ });