@angular-wave/angular.ts 0.0.16 → 0.0.18

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 (299) hide show
  1. package/README.md +5 -3
  2. package/dist/angular-ts.esm.js +1 -1
  3. package/dist/angular-ts.umd.js +1 -1
  4. package/index.html +66 -57
  5. package/package.json +1 -1
  6. package/rollup.config.js +2 -6
  7. package/src/animations/animate-children-directive.js +1 -1
  8. package/src/animations/animate-css-driver.js +1 -1
  9. package/src/animations/animate-css.js +220 -15
  10. package/src/animations/animate-js-driver.js +1 -1
  11. package/src/animations/animate-js.js +2 -2
  12. package/src/animations/animate-queue.js +3 -4
  13. package/src/animations/animation.js +1 -1
  14. package/src/animations/module.js +750 -0
  15. package/src/animations/shared.js +15 -4
  16. package/src/core/animate-runner.js +1 -1
  17. package/src/core/animate.js +4 -5
  18. package/src/core/compile.js +6 -7
  19. package/src/core/controller.js +4 -3
  20. package/src/core/filter.js +1 -1
  21. package/src/core/interpolate.js +1 -1
  22. package/src/core/interval-factory.js +1 -1
  23. package/src/core/interval.js +1 -1
  24. package/src/core/location.js +1 -1
  25. package/src/core/parser/parse.js +1 -1
  26. package/src/core/q.js +2 -3
  27. package/src/core/root-scope.js +1 -1
  28. package/src/core/sanitize-uri.js +1 -1
  29. package/src/core/sce.js +1 -1
  30. package/src/core/task-tracker-factory.js +1 -1
  31. package/src/core/timeout.js +1 -1
  32. package/src/core/urlUtils.js +1 -1
  33. package/src/directive/attrs.js +1 -1
  34. package/src/directive/bind.js +1 -1
  35. package/src/directive/class.js +2 -2
  36. package/src/directive/events.js +1 -1
  37. package/src/directive/form.js +1 -1
  38. package/src/directive/include.js +1 -1
  39. package/src/directive/input.js +1 -1
  40. package/src/directive/list.js +2 -2
  41. package/src/directive/model-options.js +1 -1
  42. package/src/directive/model.js +1 -1
  43. package/src/directive/options.js +2 -3
  44. package/src/directive/ref.js +1 -1
  45. package/src/directive/repeat.js +1 -1
  46. package/src/directive/select.js +1 -1
  47. package/src/directive/switch.js +1 -1
  48. package/src/directive/transclude.js +1 -1
  49. package/src/directive/validators.js +1 -1
  50. package/src/exts/aria.js +1 -1
  51. package/src/exts/messages.js +3 -3
  52. package/src/exts/messages.md +28 -31
  53. package/src/filters/filter.js +2 -3
  54. package/src/filters/filters.js +1 -1
  55. package/src/filters/limit-to.js +1 -1
  56. package/src/filters/order-by.js +2 -3
  57. package/src/injector.js +8 -9
  58. package/src/jqLite.js +3 -4
  59. package/src/loader.js +2 -4
  60. package/src/public.js +1 -1
  61. package/src/router/common/coreservices.js +5 -0
  62. package/src/router/{core/common → common}/queue.js +1 -1
  63. package/src/router/{core/common → common}/trace.js +21 -19
  64. package/src/router/{adapter/directives → directives}/stateDirectives.js +24 -28
  65. package/src/router/{adapter/directives → directives}/viewDirective.js +10 -9
  66. package/src/router/{core/globals.js → globals.js} +13 -3
  67. package/src/router/{core/hooks → hooks}/coreResolvables.js +6 -4
  68. package/src/router/{core/hooks → hooks}/lazyLoad.js +5 -2
  69. package/src/router/{core/hooks → hooks}/redirectTo.js +1 -1
  70. package/src/router/{core/hooks → hooks}/resolve.js +5 -4
  71. package/src/router/{core/hooks → hooks}/updateGlobals.js +1 -1
  72. package/src/router/{core/hooks → hooks}/views.js +2 -3
  73. package/src/router/index.js +60 -0
  74. package/src/router/{adapter/injectables.js → injectables.js} +9 -9
  75. package/src/router/{adapter/locationServices.js → locationServices.js} +19 -12
  76. package/src/router/{core/params → params}/param.js +5 -10
  77. package/src/router/{core/params → params}/paramType.js +4 -4
  78. package/src/router/{core/params → params}/paramTypes.js +4 -3
  79. package/src/router/{core/params → params}/stateParams.js +1 -1
  80. package/src/router/{core/path → path}/pathNode.js +2 -2
  81. package/src/router/{core/path → path}/pathUtils.js +13 -7
  82. package/src/router/{core/resolve → resolve}/resolvable.js +5 -5
  83. package/src/router/{core/resolve → resolve}/resolveContext.js +16 -6
  84. package/src/router/router.js +171 -72
  85. package/src/router/{adapter/services.js → services.js} +47 -27
  86. package/src/router/{core/state → state}/stateBuilder.js +14 -10
  87. package/src/router/{core/state → state}/stateMatcher.js +2 -3
  88. package/src/router/{core/state → state}/stateObject.js +8 -6
  89. package/src/router/{core/state → state}/stateQueueManager.js +3 -3
  90. package/src/router/{core/state → state}/stateRegistry.js +6 -7
  91. package/src/router/{core/state → state}/stateService.js +12 -15
  92. package/src/router/{core/state → state}/targetState.js +2 -2
  93. package/src/router/{adapter/statebuilders → state}/views.js +17 -15
  94. package/src/router/{adapter/stateProvider.js → stateProvider.js} +51 -9
  95. package/src/router/{adapter/templateFactory.js → templateFactory.js} +10 -19
  96. package/src/router/{core/transition → transition}/hookBuilder.js +4 -3
  97. package/src/router/{core/transition → transition}/hookRegistry.js +3 -6
  98. package/src/router/{core/transition → transition}/rejectFactory.js +4 -5
  99. package/src/router/{core/transition → transition}/transition.js +10 -12
  100. package/src/router/{core/transition → transition}/transitionHook.js +4 -4
  101. package/src/router/{core/transition → transition}/transitionService.js +13 -13
  102. package/src/router/{core/url → url}/urlConfig.js +28 -19
  103. package/src/router/{core/url → url}/urlMatcher.js +14 -16
  104. package/src/router/{core/url → url}/urlMatcherFactory.js +7 -6
  105. package/src/router/{core/url → url}/urlRouter.js +6 -30
  106. package/src/router/{core/url → url}/urlRule.js +3 -3
  107. package/src/router/{core/url → url}/urlRules.js +10 -11
  108. package/src/router/{core/url → url}/urlService.js +12 -6
  109. package/src/router/{core/view → view}/view.js +32 -27
  110. package/src/router/{adapter/viewScroll.js → viewScroll.js} +3 -0
  111. package/src/services/anchor-scroll.js +1 -1
  112. package/src/services/browser.js +1 -1
  113. package/src/services/cache-factory.js +7 -1
  114. package/src/services/cookie-reader.js +1 -1
  115. package/src/services/http-backend.js +6 -1
  116. package/src/services/http.js +4 -5
  117. package/src/services/log.js +1 -1
  118. package/src/services/template-request.js +2 -2
  119. package/src/{router/core/common → shared}/common.js +35 -16
  120. package/src/{router/core/common → shared}/predicates.js +2 -12
  121. package/src/{router/core/common → shared}/strings.js +5 -13
  122. package/src/{core → shared}/utils.js +13 -29
  123. package/test/angular.spec.js +1 -31
  124. package/test/{ng → core}/animate.spec.js +1 -1
  125. package/test/{ng → core}/compile.spec.js +2 -3
  126. package/test/{ng → core}/http.spec.js +2 -2
  127. package/test/{ng → core}/on.spec.js +1 -1
  128. package/test/{ng → core}/parse.spec.js +1 -1
  129. package/test/{ng → core}/prop.spec.js +1 -1
  130. package/test/{ng → core}/scope.spec.js +1 -1
  131. package/test/{ng/directive → directive}/a.spec.js +4 -4
  132. package/test/{ng/directive → directive}/bind.spec.js +3 -3
  133. package/test/{ng/directive → directive}/boolean.spec.js +2 -2
  134. package/test/{ng/directive → directive}/change.spec.js +3 -3
  135. package/test/{ng/directive → directive}/class.spec.js +4 -4
  136. package/test/{ng/directive → directive}/click.spec.js +3 -3
  137. package/test/{ng/directive → directive}/cloak.spec.js +4 -4
  138. package/test/{ng/directive → directive}/constoller.spec.js +5 -5
  139. package/test/{ng/directive → directive}/element-style.spec.js +3 -3
  140. package/test/{ng/directive → directive}/event.spec.js +4 -4
  141. package/test/{ng/directive → directive}/form.spec.js +5 -5
  142. package/test/{ng/directive → directive}/href.spec.js +4 -4
  143. package/test/{ng/directive → directive}/if.spec.js +5 -5
  144. package/test/{ng/directive → directive}/include.spec.js +5 -5
  145. package/test/{ng/directive → directive}/init.spec.js +4 -4
  146. package/test/{ng/directive → directive}/input.spec.js +5 -5
  147. package/test/{ng/directive → directive}/list.spec.js +3 -3
  148. package/test/{ng/directive → directive}/model-options.spec.js +6 -6
  149. package/test/{ng/directive → directive}/model.spec.js +8 -8
  150. package/test/{ng/directive → directive}/non-bindable.spec.js +3 -3
  151. package/test/{ng/directive → directive}/options.spec.js +5 -5
  152. package/test/{ng/directive → directive}/ref.spec.js +2 -2
  153. package/test/{ng/directive → directive}/repeat.spec.js +5 -5
  154. package/test/{ng/directive → directive}/script.spec.js +3 -3
  155. package/test/{ng/directive → directive}/scrset.spec.js +3 -3
  156. package/test/{ng/directive → directive}/select.spec.js +5 -5
  157. package/test/{ng/directive → directive}/show-hide.spec.js +3 -3
  158. package/test/{ng/directive → directive}/src.spec.js +3 -3
  159. package/test/{ng/directive → directive}/style.spec.js +3 -3
  160. package/test/{ng/directive → directive}/switch.spec.js +3 -3
  161. package/test/{ng/directive → directive}/validators.spec.js +3 -3
  162. package/test/{ng/filter → filter}/filter.spec.js +4 -4
  163. package/test/{ng/filter → filter}/filters.spec.js +3 -3
  164. package/test/{ng/filter → filter}/limit-to.spec.js +3 -3
  165. package/test/{ng/filter → filter}/order-by.spec.js +2 -2
  166. package/test/injector.spec.js +1 -1
  167. package/test/jqlite.spec.js +1 -1
  168. package/test/messages/messages.spec.js +1 -1
  169. package/test/min-err.spec.js +1 -1
  170. package/test/original-test.html +4 -4
  171. package/test/router/glob.spec.js +78 -0
  172. package/test/router/state.spec.js +1010 -0
  173. package/test/sanitize/bing-html.spec.js +1 -1
  174. package/test/shared/common.spec.js +283 -0
  175. package/test/shared/hof.spec.js +60 -0
  176. package/test/shared/strings.spec.js +40 -0
  177. package/test/{ng → shared}/utils.spec.js +1 -1
  178. package/types/index.d.ts +1 -1
  179. package/types/router/angular.d.ts +1 -0
  180. package/types/router/core/common/common.d.ts +370 -0
  181. package/types/router/core/common/coreservices.d.ts +80 -0
  182. package/types/router/core/common/glob.d.ts +60 -0
  183. package/types/router/core/common/hof.d.ts +160 -0
  184. package/types/router/core/common/index.d.ts +8 -0
  185. package/types/router/core/common/predicates.d.ts +25 -0
  186. package/types/router/core/common/queue.d.ts +15 -0
  187. package/types/router/core/common/safeConsole.d.ts +5 -0
  188. package/types/router/core/common/strings.d.ts +64 -0
  189. package/types/router/core/common/trace.d.ts +114 -0
  190. package/types/router/core/globals.d.ts +45 -0
  191. package/types/router/core/hooks/coreResolvables.d.ts +4 -0
  192. package/types/router/core/hooks/ignoredTransition.d.ts +2 -0
  193. package/types/router/core/hooks/invalidTransition.d.ts +2 -0
  194. package/types/router/core/hooks/lazyLoad.d.ts +12 -0
  195. package/types/router/core/hooks/onEnterExitRetain.d.ts +4 -0
  196. package/types/router/core/hooks/redirectTo.d.ts +2 -0
  197. package/types/router/core/hooks/resolve.d.ts +5 -0
  198. package/types/router/core/hooks/updateGlobals.d.ts +2 -0
  199. package/types/router/core/hooks/url.d.ts +2 -0
  200. package/types/router/core/hooks/views.d.ts +3 -0
  201. package/types/router/core/index.d.ts +12 -0
  202. package/types/router/core/interface.d.ts +102 -0
  203. package/types/router/core/params/index.d.ts +12 -0
  204. package/types/router/core/params/interface.d.ts +606 -0
  205. package/types/router/core/params/param.d.ts +65 -0
  206. package/types/router/core/params/paramType.d.ts +65 -0
  207. package/types/router/core/params/paramTypes.d.ts +190 -0
  208. package/types/router/core/params/stateParams.d.ts +15 -0
  209. package/types/router/core/path/index.d.ts +2 -0
  210. package/types/router/core/path/pathNode.d.ts +60 -0
  211. package/types/router/core/path/pathUtils.d.ts +79 -0
  212. package/types/router/core/resolve/index.d.ts +3 -0
  213. package/types/router/core/resolve/interface.d.ts +210 -0
  214. package/types/router/core/resolve/resolvable.d.ts +69 -0
  215. package/types/router/core/resolve/resolveContext.d.ts +92 -0
  216. package/types/router/core/router.d.ts +95 -0
  217. package/types/router/core/state/index.d.ts +28 -0
  218. package/types/router/core/state/interface.d.ts +708 -0
  219. package/types/router/core/state/stateBuilder.d.ts +104 -0
  220. package/types/router/core/state/stateMatcher.d.ts +11 -0
  221. package/types/router/core/state/stateObject.d.ts +155 -0
  222. package/types/router/core/state/stateQueueManager.d.ts +24 -0
  223. package/types/router/core/state/stateRegistry.d.ts +136 -0
  224. package/types/router/core/state/stateService.d.ts +350 -0
  225. package/types/router/core/state/targetState.d.ts +100 -0
  226. package/types/router/core/transition/hookBuilder.d.ts +45 -0
  227. package/types/router/core/transition/hookRegistry.d.ts +93 -0
  228. package/types/router/core/transition/index.d.ts +20 -0
  229. package/types/router/core/transition/interface.d.ts +819 -0
  230. package/types/router/core/transition/rejectFactory.d.ts +103 -0
  231. package/types/router/core/transition/transition.d.ts +527 -0
  232. package/types/router/core/transition/transitionEventType.d.ts +17 -0
  233. package/types/router/core/transition/transitionHook.d.ts +88 -0
  234. package/types/router/core/transition/transitionService.d.ts +187 -0
  235. package/types/router/core/url/index.d.ts +8 -0
  236. package/types/router/core/url/interface.d.ts +156 -0
  237. package/types/router/core/url/urlConfig.d.ts +141 -0
  238. package/types/router/core/url/urlMatcher.d.ts +180 -0
  239. package/types/router/core/url/urlMatcherFactory.d.ts +52 -0
  240. package/types/router/core/url/urlRouter.d.ts +85 -0
  241. package/types/router/core/url/urlRule.d.ts +120 -0
  242. package/types/router/core/url/urlRules.d.ts +244 -0
  243. package/types/router/core/url/urlService.d.ts +206 -0
  244. package/types/router/core/vanilla.d.ts +1 -0
  245. package/types/router/core/view/index.d.ts +2 -0
  246. package/types/router/core/view/interface.d.ts +46 -0
  247. package/types/router/core/view/view.d.ts +167 -0
  248. package/types/router/directives/stateDirectives.d.ts +3 -0
  249. package/types/router/directives/viewDirective.d.ts +143 -0
  250. package/types/router/index.d.ts +19 -0
  251. package/types/router/interface.d.ts +491 -0
  252. package/types/router/legacy/resolveService.d.ts +44 -0
  253. package/types/router/legacy/stateEvents.d.ts +123 -0
  254. package/types/router/locationServices.d.ts +43 -0
  255. package/types/router/services.d.ts +15 -0
  256. package/types/router/stateFilters.d.ts +11 -0
  257. package/types/router/stateProvider.d.ts +254 -0
  258. package/types/router/statebuilders/onEnterExitRetain.d.ts +12 -0
  259. package/types/router/statebuilders/views.d.ts +41 -0
  260. package/types/router/templateFactory.d.ts +84 -0
  261. package/types/router/viewScroll.d.ts +9 -0
  262. package/src/animations/animate.css.md +0 -263
  263. package/src/animations/animate.md +0 -933
  264. package/src/router/adapter/statebuilders/onEnterExitRetain.js +0 -29
  265. package/src/router/core/common/coreservices.js +0 -15
  266. package/src/router/core/common/safeConsole.js +0 -37
  267. package/src/router/core/interface.js +0 -3
  268. package/src/router/core/resolve/interface.js +0 -10
  269. package/src/router/core/router.js +0 -203
  270. package/src/router/core/url/interface.js +0 -1
  271. package/src/router/core/view/interface.js +0 -1
  272. /package/src/router/{core/common → common}/glob.js +0 -0
  273. /package/src/router/{core/hooks → hooks}/ignoredTransition.js +0 -0
  274. /package/src/router/{core/hooks → hooks}/invalidTransition.js +0 -0
  275. /package/src/router/{core/hooks → hooks}/onEnterExitRetain.js +0 -0
  276. /package/src/router/{core/hooks → hooks}/url.js +0 -0
  277. /package/src/router/{core/params → params}/README.md +0 -0
  278. /package/src/router/{core/state → state}/README.md +0 -0
  279. /package/src/router/{adapter/stateFilters.js → stateFilters.js} +0 -0
  280. /package/src/router/{core/transition → transition}/interface.js +0 -0
  281. /package/src/router/{core/transition → transition}/transitionEventType.js +0 -0
  282. /package/src/{router/core/common → shared}/hof.js +0 -0
  283. /package/test/{ng → core}/cache-factor.spec.js +0 -0
  284. /package/test/{ng → core}/controller-provider.spec.js +0 -0
  285. /package/test/{ng → core}/cookie-reader.spec.js +0 -0
  286. /package/test/{ng → core}/document.spec.js +0 -0
  287. /package/test/{ng → core}/filter.spec.js +0 -0
  288. /package/test/{ng → core}/http-backend.spec.js +0 -0
  289. /package/test/{ng → core}/interpolate.spec.js +0 -0
  290. /package/test/{ng → core}/interval.spec.js +0 -0
  291. /package/test/{ng → core}/location.spec.js +0 -0
  292. /package/test/{ng → core}/q.spec.js +0 -0
  293. /package/test/{ng → core}/root-element.spec.js +0 -0
  294. /package/test/{ng → core}/sanitize-uri.spec.js +0 -0
  295. /package/test/{ng → core}/sce.spec.js +0 -0
  296. /package/test/{ng → core}/template-request.spec.js +0 -0
  297. /package/test/{ng → core}/timeout.spec.js +0 -0
  298. /package/test/{ng → core}/url-utils.spec.js +0 -0
  299. /package/{src/router/adapter/interface.js → types/router/injectables.d.ts} +0 -0
@@ -0,0 +1,1010 @@
1
+ import { dealoc, jqLite } from "../../src/jqLite";
2
+ import { Angular } from "../../src/loader";
3
+ import { publishExternalAPI } from "../../src/public";
4
+ import { isFunction } from "../../src/shared/utils";
5
+ import { wait } from "../test-utils";
6
+
7
+ describe("$state", () => {
8
+ let $router, $injector, template, ctrlName, $provide, $compile, module;
9
+
10
+ /** @type {import("../../src/router/stateProvider").StateProvider} */
11
+ let $stateProvider;
12
+
13
+ function $get(what) {
14
+ return $injector.get(what);
15
+ }
16
+
17
+ async function initStateTo(state, params) {
18
+ const $state = $get("$state"),
19
+ $q = $get("$q");
20
+ return $state.transitionTo(state, params || {});
21
+ }
22
+
23
+ const A = {
24
+ name: "A",
25
+ data: {},
26
+ controller: function () {
27
+ log += "controller;";
28
+ },
29
+ template: "a",
30
+ },
31
+ B = { name: "B", template: "b" },
32
+ C = { name: "C", template: "c" },
33
+ D = { name: "D", params: { x: null, y: null }, template: "d" },
34
+ DD = {
35
+ name: "DD",
36
+ parent: D,
37
+ params: { x: null, y: null, z: null },
38
+ template: "dd",
39
+ },
40
+ DDDD = {
41
+ name: "DDDD",
42
+ parent: D,
43
+ controller: function () {},
44
+ template: "hey",
45
+ },
46
+ E = { name: "E", params: { i: {} }, template: "e" },
47
+ F = {
48
+ name: "F",
49
+ params: { a: "", b: false, c: 0, d: undefined, e: -1 },
50
+ template: "f",
51
+ },
52
+ H = { name: "H", data: { propA: "propA", propB: "propB" }, template: "h" },
53
+ HH = { name: "HH", parent: H, template: "hh" },
54
+ HHH = {
55
+ name: "HHH",
56
+ parent: HH,
57
+ data: { propA: "overriddenA", propC: "propC" },
58
+ template: "hhh",
59
+ },
60
+ RS = {
61
+ name: "RS",
62
+ url: "^/search?term",
63
+ reloadOnSearch: false,
64
+ template: "rs",
65
+ },
66
+ OPT = {
67
+ name: "OPT",
68
+ url: "/opt/:param",
69
+ params: { param: "100" },
70
+ template: "opt",
71
+ },
72
+ OPT2 = {
73
+ name: "OPT2",
74
+ url: "/opt2/:param2/:param3",
75
+ params: { param3: "300", param4: "400" },
76
+ template: "opt2",
77
+ },
78
+ ISS2101 = {
79
+ name: "ISS2101",
80
+ params: { bar: { squash: false, value: "qux" } },
81
+ url: "/2101/{bar:string}",
82
+ },
83
+ URLLESS = {
84
+ name: "URLLESS",
85
+ url: "/urllessparams",
86
+ params: { myparam: { type: "int" } },
87
+ },
88
+ AppInjectable = {};
89
+
90
+ let log, logEvents, logEnterExit;
91
+ function callbackLogger(state, what) {
92
+ return function () {
93
+ if (logEnterExit) log += state.name + "." + what + ";";
94
+ };
95
+ }
96
+
97
+ afterEach(() => {
98
+ dealoc(document.getElementById("dummy"));
99
+ });
100
+
101
+ describe("provider", () => {
102
+ beforeEach(() => {
103
+ dealoc(document.getElementById("dummy"));
104
+ jqLite.CACHE.clear(); // some tests are polluting the cache
105
+ window.angular = new Angular();
106
+ publishExternalAPI();
107
+ module = window.angular.module("defaultModule", ["ui.router"]);
108
+ module.config((_$stateProvider_, _$provide_) => {
109
+ $stateProvider = _$stateProvider_;
110
+ });
111
+ window.angular.bootstrap(document.getElementById("dummy"), [
112
+ "defaultModule",
113
+ ]);
114
+ });
115
+
116
+ afterEach(() => {
117
+ dealoc(document.getElementById("dummy"));
118
+ });
119
+
120
+ it("should be available at config", () => {
121
+ expect($stateProvider).toBeDefined();
122
+ });
123
+
124
+ it("should should not allow states that are already registerred", () => {
125
+ expect(() => {
126
+ $stateProvider.state({ name: "toString", url: "/to-string" });
127
+ }).not.toThrow();
128
+ expect(() => {
129
+ $stateProvider.state({ name: "toString", url: "/to-string" });
130
+ }).toThrowError(/stateinvalid/);
131
+ });
132
+
133
+ it("should should not allow states that have invalid keys", () => {
134
+ expect(() => {
135
+ $stateProvider.state({ name: "faulty", faulturl: "/to-string" });
136
+ }).toThrowError(/stateinvalid/);
137
+ });
138
+
139
+ it("should requred `name` if state definition object is passed", () => {
140
+ expect(() => {
141
+ $stateProvider.state({ url: "/to-string" });
142
+ }).toThrowError(/stateinvalid/);
143
+ expect(() => {
144
+ $stateProvider.state({ name: "hasName", url: "/to-string" });
145
+ }).not.toThrowError(/stateinvalid/);
146
+ });
147
+ });
148
+
149
+ describe(".transitionTo()", function () {
150
+ let $rootScope, $state, $stateParams, $transitions, $q, $location;
151
+
152
+ beforeEach(() => {
153
+ dealoc(document.getElementById("dummy"));
154
+ window.angular = new Angular();
155
+ publishExternalAPI();
156
+ module = window.angular.module("defaultModule", ["ui.router"]);
157
+ module.config((_$stateProvider_, _$provide_) => {
158
+ $stateProvider = _$stateProvider_;
159
+ $provide = _$provide_;
160
+
161
+ [A, B, C, D, DD, E, H, HH, HHH].forEach(function (state) {
162
+ state.onEnter = callbackLogger(state, "onEnter");
163
+ state.onExit = callbackLogger(state, "onExit");
164
+ });
165
+
166
+ $stateProvider
167
+ .state(A)
168
+ .state(B)
169
+ .state(C)
170
+ .state(D)
171
+ .state(DD)
172
+ .state(DDDD)
173
+ .state(E)
174
+ .state(F)
175
+ .state(H)
176
+ .state(HH)
177
+ .state(HHH)
178
+ .state(RS)
179
+ .state(OPT)
180
+ .state(OPT2)
181
+ .state(ISS2101)
182
+ .state(URLLESS)
183
+ .state({ name: "home", url: "/" })
184
+ .state({ name: "home.item", url: "front/:id" })
185
+ .state({
186
+ name: "about",
187
+ url: "/about",
188
+ resolve: {
189
+ stateInfo: function ($transition$) {
190
+ return [$transition$.from().name, $transition$.to().name];
191
+ },
192
+ },
193
+ onEnter: function (stateInfo) {
194
+ log = stateInfo.join(" => ");
195
+ },
196
+ })
197
+ .state({ name: "about.person", url: "/:person" })
198
+ .state({ name: "about.person.item", url: "/:id" })
199
+ .state({ name: "about.sidebar" })
200
+ .state({
201
+ name: "about.sidebar.item",
202
+ url: "/:item",
203
+ templateUrl: function (params) {
204
+ templateParams = params;
205
+ return "/templates/" + params.item + ".html";
206
+ },
207
+ })
208
+ .state({
209
+ name: "dynamicTemplate",
210
+ url: "/dynamicTemplate/:type",
211
+ templateProvider: function ($stateParams, foo) {
212
+ template = $stateParams.type + foo + "Template";
213
+ return template;
214
+ },
215
+ resolve: {
216
+ foo: function () {
217
+ return "Foo";
218
+ },
219
+ },
220
+ })
221
+ .state({
222
+ name: "dynamicController",
223
+ url: "/dynamicController/:type",
224
+ template: "a",
225
+ controllerProvider: [
226
+ "$stateParams",
227
+ function ($stateParams) {
228
+ ctrlName = $stateParams.type + "Controller";
229
+ return ctrlName;
230
+ },
231
+ ],
232
+ })
233
+ .state({
234
+ name: "home.redirect",
235
+ url: "redir",
236
+ onEnter: function ($state) {
237
+ $state.transitionTo("about");
238
+ },
239
+ })
240
+ .state({
241
+ name: "resolveFail",
242
+ url: "/resolve-fail",
243
+ resolve: {
244
+ badness: function ($q) {
245
+ return $q.reject("!");
246
+ },
247
+ },
248
+ onEnter: function (badness) {},
249
+ })
250
+ .state({
251
+ name: "resolveTimeout",
252
+ url: "/resolve-timeout/:foo",
253
+ resolve: {
254
+ value: function ($timeout) {
255
+ return $timeout(function () {
256
+ log += "Success!";
257
+ }, 1);
258
+ },
259
+ },
260
+ onEnter: function (value) {},
261
+ template: "-",
262
+ controller: function () {
263
+ log += "controller;";
264
+ },
265
+ })
266
+ .state({ name: "badParam", url: "/bad/{param:int}" })
267
+ .state({ name: "badParam2", url: "/bad2/{param:[0-9]{5}}" })
268
+
269
+ .state({ name: "json", url: "/jsonstate/{param:json}" })
270
+
271
+ .state({ name: "first", url: "^/first/subpath" })
272
+ .state({ name: "second", url: "^/second" })
273
+
274
+ // State param inheritance tests. param1 is inherited by sub1 & sub2;
275
+ // param2 should not be transferred (unless explicitly set).
276
+ .state({ name: "root", url: "^/root?param1" })
277
+ .state({ name: "root.sub1", url: "/1?param2" })
278
+ .state({
279
+ name: "logA",
280
+ url: "/logA",
281
+ template: "<div> <div ui-view/></div>",
282
+ controller: function () {
283
+ log += "logA;";
284
+ },
285
+ })
286
+ .state({
287
+ name: "logA.logB",
288
+ url: "/logB",
289
+ views: {
290
+ $default: {
291
+ template: "<div> <div ui-view/></div>",
292
+ controller: function () {
293
+ log += "logB;";
294
+ },
295
+ },
296
+ },
297
+ })
298
+ .state({
299
+ name: "logA.logB.logC",
300
+ url: "/logC",
301
+ views: {
302
+ $default: {
303
+ template: "<div> <div ui-view/></div>",
304
+ controller: function () {
305
+ log += "logC;";
306
+ },
307
+ },
308
+ },
309
+ })
310
+ .state({ name: "root.sub2", url: "/2?param2" });
311
+
312
+ $provide.value("AppInjectable", AppInjectable);
313
+ });
314
+
315
+ $injector = window.angular.bootstrap(document.getElementById("dummy"), [
316
+ "defaultModule",
317
+ ]);
318
+
319
+ $injector.invoke(
320
+ (
321
+ _$rootScope_,
322
+ _$state_,
323
+ _$stateParams_,
324
+ _$transitions_,
325
+ _$q_,
326
+ _$location_,
327
+ _$compile_,
328
+ _$router_,
329
+ ) => {
330
+ $rootScope = _$rootScope_;
331
+ $state = _$state_;
332
+ $stateParams = _$stateParams_;
333
+ $transitions = _$transitions_;
334
+ $q = _$q_;
335
+ $location = _$location_;
336
+ $compile = _$compile_;
337
+ $router = _$router_;
338
+ },
339
+ );
340
+ });
341
+
342
+ afterEach(() => {
343
+ dealoc(document.getElementById("dummy"));
344
+ });
345
+
346
+ it("returns a promise for the target state", () => {
347
+ const promise = $state.transitionTo(A, {});
348
+ expect(isFunction(promise.then)).toBeTruthy();
349
+ expect(promise.transition.to()).toBe(A);
350
+ });
351
+
352
+ it("returns a promise for the target state", () => {
353
+ const promise = $state.transitionTo(A, {});
354
+ expect(isFunction(promise.then)).toBeTruthy();
355
+ expect(promise.transition.to()).toBe(A);
356
+ });
357
+
358
+ it("show return promise with an error on invalid state", (done) => {
359
+ let res = $state.transitionTo("about.person.item", { id: 5 });
360
+ setTimeout(() => {
361
+ expect(res.$$state.status).toEqual(2);
362
+ done();
363
+ }, 100);
364
+ });
365
+
366
+ it("allows transitions by name", (done) => {
367
+ $state.transitionTo("A", {});
368
+ setTimeout(() => {
369
+ expect($state.current).toBe(A);
370
+ done();
371
+ });
372
+ });
373
+
374
+ describe("dynamic transitions", function () {
375
+ let dynlog, paramsChangedLog;
376
+ let dynamicstate, childWithParam, childNoParam;
377
+
378
+ beforeEach(async () => {
379
+ dynlog = paramsChangedLog = "";
380
+ dynamicstate = {
381
+ name: "dyn",
382
+ url: "^/dynstate/:path/:pathDyn?search&searchDyn",
383
+ params: {
384
+ pathDyn: { dynamic: true },
385
+ searchDyn: { dynamic: true },
386
+ },
387
+ template: "dyn state. <div ui-view></div>",
388
+ controller: function () {
389
+ this.uiOnParamsChanged = function (updatedParams) {
390
+ const paramNames = Object.keys(updatedParams).sort();
391
+ const keyValues = paramNames.map(function (key) {
392
+ return key + "=" + updatedParams[key];
393
+ });
394
+ dynlog += "[" + keyValues.join(",") + "];";
395
+ paramsChangedLog += paramNames.join(",") + ";";
396
+ };
397
+ },
398
+ };
399
+
400
+ childWithParam = {
401
+ name: "dyn.child",
402
+ url: "/child",
403
+ params: {
404
+ config: "c1", // allow empty
405
+ configDyn: { value: null, dynamic: true },
406
+ },
407
+ template: "dyn.child state",
408
+ controller: function () {
409
+ this.uiOnParamsChanged = function (updatedParams) {
410
+ const paramNames = Object.keys(updatedParams).sort();
411
+ const keyValues = paramNames.map(function (key) {
412
+ return key + "=" + updatedParams[key];
413
+ });
414
+ dynlog += "{" + keyValues.join(",") + "};";
415
+ paramsChangedLog += paramNames.join(",") + ";";
416
+ };
417
+ },
418
+ };
419
+
420
+ childNoParam = {
421
+ name: "dyn.noparams",
422
+ url: "/noparams",
423
+ template: "dyn.noparams state",
424
+ controller: function () {
425
+ this.uiOnParamsChanged = function (updatedParams) {
426
+ const paramNames = Object.keys(updatedParams).sort();
427
+ const keyValues = paramNames.map(function (key) {
428
+ return key + "=" + updatedParams[key];
429
+ });
430
+ dynlog += "<" + keyValues.join(",") + ">;";
431
+ paramsChangedLog += paramNames.join(",") + ";";
432
+ };
433
+ },
434
+ };
435
+
436
+ $stateProvider.state(dynamicstate);
437
+ $stateProvider.state(childWithParam);
438
+ $stateProvider.state(childNoParam);
439
+
440
+ $transitions.onEnter({}, function (trans, state) {
441
+ dynlog += "enter:" + state.name + ";";
442
+ });
443
+ $transitions.onExit({}, function (trans, state) {
444
+ dynlog += "exit:" + state.name + ";";
445
+ });
446
+ $transitions.onSuccess({}, function () {
447
+ dynlog += "success;";
448
+ });
449
+
450
+ $compile("<div><ui-view></ui-view></div>")($rootScope.$new());
451
+ await initStateTo(dynamicstate, {
452
+ path: "p1",
453
+ pathDyn: "pd1",
454
+ search: "s1",
455
+ searchDyn: "sd1",
456
+ });
457
+ expect(dynlog.endsWith("enter:dyn;success;")).toBeTrue();
458
+ Object.entries({
459
+ path: "p1",
460
+ pathDyn: "pd1",
461
+ search: "s1",
462
+ searchDyn: "sd1",
463
+ }).forEach(([k, v]) => {
464
+ expect($stateParams[k]).toEqual(v);
465
+ });
466
+ expect($location.url()).toEqual(
467
+ "/dynstate/p1/pd1?search=s1&searchDyn=sd1",
468
+ );
469
+ });
470
+
471
+ describe("[ transition.dynamic() ]:", function () {
472
+ it("is considered fully dynamic when only dynamic params have changed", function () {
473
+ const promise = $state.go(".", { pathDyn: "pd2", searchDyn: "sd2" });
474
+ expect(promise.transition.dynamic()).toBeTruthy();
475
+ });
476
+
477
+ it("is not considered fully dynamic if any state is entered", function () {
478
+ const promise = $state.go(childWithParam);
479
+ expect(promise.transition.dynamic()).toBeFalsy();
480
+ });
481
+
482
+ it("is not considered fully dynamic if any state is exited", async () => {
483
+ await initStateTo(childWithParam, {
484
+ config: "p1",
485
+ path: "p1",
486
+ pathDyn: "pd1",
487
+ search: "s1",
488
+ searchDyn: "sd1",
489
+ });
490
+ const promise = $state.go(dynamicstate);
491
+ expect(promise.transition.dynamic()).toBeFalsy();
492
+ });
493
+
494
+ it("is not considered fully dynamic if any state is reloaded", function () {
495
+ const promise = $state.go(dynamicstate, null, { reload: true });
496
+ expect(promise.transition.dynamic()).toBeFalsy();
497
+ });
498
+
499
+ it("is not considered fully dynamic if any non-dynamic parameter changes", function () {
500
+ const promise = $state.go(dynamicstate, { path: "p2" });
501
+ expect(promise.transition.dynamic()).toBeFalsy();
502
+ });
503
+ });
504
+
505
+ describe("[ promises ]", function () {
506
+ beforeEach(() => (dynlog = ""));
507
+ it("runs successful transition when fully dynamic", async () => {
508
+ let transSuccess,
509
+ promise = $state.go(dynamicstate, { searchDyn: "sd2" }),
510
+ transition = promise.transition;
511
+ transition.promise.then(function (result) {
512
+ transSuccess = true;
513
+ });
514
+ await promise;
515
+ expect(transition.dynamic()).toBeTruthy();
516
+ expect(transSuccess).toBeTruthy();
517
+ expect(dynlog).toBe("success;[searchDyn=sd2];");
518
+ });
519
+
520
+ it("resolves the $state.go() promise with the original/final state, when fully dynamic", async () => {
521
+ initStateTo(dynamicstate, {
522
+ path: "p1",
523
+ pathDyn: "pd1",
524
+ search: "s1",
525
+ searchDyn: "sd1",
526
+ });
527
+ let destState,
528
+ promise = $state.go(dynamicstate, {
529
+ pathDyn: "pd2",
530
+ searchDyn: "sd2",
531
+ });
532
+ promise.then(function (result) {
533
+ destState = result;
534
+ });
535
+ await promise;
536
+ expect(promise.transition.dynamic()).toBeTruthy();
537
+ expect($state.current).toBe(dynamicstate);
538
+ expect(destState).toBe(dynamicstate);
539
+ });
540
+ });
541
+
542
+ describe("[ enter/exit ]", function () {
543
+ beforeEach(() => (dynlog = ""));
544
+ it("does not exit nor enter any states when fully dynamic", async () => {
545
+ const promise = $state.go(dynamicstate, { searchDyn: "sd2" });
546
+ await promise;
547
+ expect(promise.transition.dynamic()).toBeTruthy();
548
+ expect(promise.transition.treeChanges().entering.length).toBe(0);
549
+ expect(promise.transition.treeChanges().exiting.length).toBe(0);
550
+ expect(promise.transition.treeChanges().retained.length).toBe(2);
551
+ expect(dynlog).toBe("success;[searchDyn=sd2];");
552
+ Object.entries({
553
+ path: "p1",
554
+ pathDyn: "pd1",
555
+ search: "s1",
556
+ searchDyn: "sd2",
557
+ }).forEach(([k, v]) => {
558
+ expect($stateParams[k]).toEqual(v);
559
+ });
560
+ });
561
+
562
+ it("does not exit nor enter the state when only dynamic search params change", async () => {
563
+ const promise = $state.go(dynamicstate, { searchDyn: "sd2" });
564
+ await promise;
565
+ expect(promise.transition.dynamic()).toBeTruthy();
566
+ expect(dynlog).toBe("success;[searchDyn=sd2];");
567
+ Object.entries({
568
+ path: "p1",
569
+ pathDyn: "pd1",
570
+ search: "s1",
571
+ searchDyn: "sd2",
572
+ }).forEach(([k, v]) => {
573
+ expect($stateParams[k]).toEqual(v);
574
+ });
575
+ });
576
+
577
+ it("does not exit nor enter the state when only dynamic path params change", async () => {
578
+ const promise = $state.go(dynamicstate, { pathDyn: "pd2" });
579
+ await promise;
580
+ expect(promise.transition.dynamic()).toBeTruthy();
581
+ expect(dynlog).toBe("success;[pathDyn=pd2];");
582
+ Object.entries({
583
+ path: "p1",
584
+ pathDyn: "pd2",
585
+ search: "s1",
586
+ searchDyn: "sd1",
587
+ }).forEach(([k, v]) => {
588
+ expect($stateParams[k]).toEqual(v);
589
+ });
590
+ });
591
+
592
+ it("exits and enters a state when a non-dynamic search param changes", async () => {
593
+ const promise = $state.go(dynamicstate, { search: "s2" });
594
+ await promise;
595
+ expect(promise.transition.dynamic()).toBeFalsy();
596
+ expect(dynlog).toBe("exit:dyn;enter:dyn;success;");
597
+ Object.entries({
598
+ path: "p1",
599
+ pathDyn: "pd1",
600
+ search: "s2",
601
+ searchDyn: "sd1",
602
+ }).forEach(([k, v]) => {
603
+ expect($stateParams[k]).toEqual(v);
604
+ });
605
+ });
606
+
607
+ it("exits and enters a state when a non-dynamic path param changes", async () => {
608
+ const promise = $state.go(dynamicstate, { path: "p2" });
609
+ await promise;
610
+ expect(promise.transition.dynamic()).toBeFalsy();
611
+ expect(dynlog).toBe("exit:dyn;enter:dyn;success;");
612
+ Object.entries({
613
+ path: "p2",
614
+ pathDyn: "pd1",
615
+ search: "s1",
616
+ searchDyn: "sd1",
617
+ }).forEach(([k, v]) => {
618
+ expect($stateParams[k]).toEqual(v);
619
+ });
620
+ });
621
+
622
+ it("does not exit nor enter a state when only dynamic params change (triggered via url)", async () => {
623
+ $location.search({ search: "s1", searchDyn: "sd2" });
624
+ $rootScope.$broadcast("$locationChangeSuccess");
625
+ await wait(10);
626
+ expect(dynlog).toBe("success;[searchDyn=sd2];");
627
+ });
628
+
629
+ it("exits and enters a state when any non-dynamic params change (triggered via url)", async () => {
630
+ $location.search({ search: "s2", searchDyn: "sd2" });
631
+ $rootScope.$broadcast("$locationChangeSuccess");
632
+ await wait(10);
633
+ expect(dynlog).toBe("exit:dyn;enter:dyn;success;");
634
+ });
635
+
636
+ it("does not exit nor enter a state when only dynamic params change (triggered via $state transition)", async () => {
637
+ await $state.go(".", { searchDyn: "sd2" }, { inherit: true });
638
+ expect(dynlog).toBe("success;[searchDyn=sd2];");
639
+ });
640
+ });
641
+
642
+ describe("[ global $stateParams service ]", function () {
643
+ it("updates the global $stateParams object", async () => {
644
+ await $state.go(dynamicstate, { searchDyn: "sd2" });
645
+
646
+ Object.entries({
647
+ path: "p1",
648
+ pathDyn: "pd1",
649
+ search: "s1",
650
+ searchDyn: "sd2",
651
+ }).forEach(([k, v]) => {
652
+ expect($stateParams[k]).toEqual(v);
653
+ });
654
+ });
655
+
656
+ it("updates $stateParams and $location.search when only dynamic params change (triggered via url)", async () => {
657
+ $location.search({ search: "s1", searchDyn: "sd2" });
658
+ $rootScope.$broadcast("$locationChangeSuccess");
659
+ await wait(10);
660
+ expect($stateParams.search).toBe("s1");
661
+ expect($stateParams.searchDyn).toBe("sd2");
662
+ expect($location.search()).toEqual({
663
+ search: "s1",
664
+ searchDyn: "sd2",
665
+ });
666
+ });
667
+
668
+ it("updates $stateParams and $location.search when only dynamic params change (triggered via $state transition)", async () => {
669
+ await $state.go(".", { searchDyn: "sd2" });
670
+ expect($stateParams.search).toBe("s1");
671
+ expect($stateParams.searchDyn).toBe("sd2");
672
+ expect($location.search()).toEqual({
673
+ search: "s1",
674
+ searchDyn: "sd2",
675
+ });
676
+ });
677
+
678
+ it("dynamic param changes can be observed by watching the global $stateParams", async () => {
679
+ let observedParamValue;
680
+ function stateParamsTerm() {
681
+ return $stateParams.searchDyn;
682
+ }
683
+ $rootScope.$watch(stateParamsTerm, function (newval, oldval) {
684
+ observedParamValue = newval;
685
+ });
686
+ await wait(10);
687
+
688
+ $location.search({ search: "s1", searchDyn: "sd2" });
689
+ $rootScope.$broadcast("$locationChangeSuccess");
690
+ await wait(10);
691
+
692
+ expect(observedParamValue).toBe("sd2");
693
+ });
694
+ });
695
+
696
+ describe("[ uiOnParamsChanged ]", function () {
697
+ beforeEach(() => (dynlog = ""));
698
+ it("should be called when dynamic parameter values change", async () => {
699
+ await $state.go(".", { searchDyn: "sd2" });
700
+
701
+ expect(paramsChangedLog).toBe("searchDyn;");
702
+ });
703
+
704
+ it("should not be called if a non-dynamic parameter changes (causing the controller's state to exit/enter)", async () => {
705
+ await $state.go(".", { search: "s2", searchDyn: "sd2" });
706
+
707
+ expect(paramsChangedLog).toBe("");
708
+ });
709
+
710
+ it("should not be called, when entering a new state, if no parameter values change", async () => {
711
+ await $state.go(childNoParam);
712
+
713
+ expect(paramsChangedLog).toBe("");
714
+ });
715
+
716
+ it("should be called, when entering a new state, if any dynamic parameter value changed", async () => {
717
+ await $state.go(childNoParam, { searchDyn: "sd2" });
718
+
719
+ expect(paramsChangedLog).toBe("searchDyn;");
720
+ });
721
+
722
+ it("should be called, when entering a new state, if a new parameter value is added", async () => {
723
+ await $state.go(childWithParam, { config: "c2" });
724
+
725
+ expect(paramsChangedLog).toBe("config,configDyn;");
726
+ });
727
+
728
+ it("should be called, when reactivating the uiOnParamsChanged state, if a dynamic parameter changed", async () => {
729
+ await initStateTo(childNoParam, {
730
+ path: "p1",
731
+ pathDyn: "pd1",
732
+ search: "s1",
733
+ searchDyn: "sd1",
734
+ });
735
+ dynlog = paramsChangedLog = "";
736
+
737
+ await $state.go(dynamicstate, { pathDyn: "pd2" });
738
+
739
+ expect(paramsChangedLog).toBe("pathDyn;");
740
+ });
741
+
742
+ it('should not be called, when reactivating the uiOnParamsChanged state "dyn", if any of dyns non-dynamic parameters changed', async () => {
743
+ await initStateTo(childNoParam, {
744
+ path: "p1",
745
+ pathDyn: "pd1",
746
+ search: "s1",
747
+ searchDyn: "sd1",
748
+ });
749
+ dynlog = paramsChangedLog = "";
750
+
751
+ await $state.go(dynamicstate, { path: "p2" });
752
+
753
+ expect(paramsChangedLog).toBe("");
754
+ });
755
+
756
+ it("should be called with an object containing only the changed params", async () => {
757
+ await $state.go(dynamicstate, { pathDyn: "pd2" });
758
+
759
+ expect(dynlog).toBe("success;[pathDyn=pd2];");
760
+
761
+ await $state.go(dynamicstate, { pathDyn: "pd3", searchDyn: "sd2" });
762
+
763
+ expect(dynlog).toBe(
764
+ "success;[pathDyn=pd2];success;[pathDyn=pd3,searchDyn=sd2];",
765
+ );
766
+ });
767
+
768
+ it("should be called on all active controllers that have a uiOnParamsChanged", async () => {
769
+ await initStateTo(childWithParam, {
770
+ path: "p1",
771
+ pathDyn: "pd1",
772
+ search: "s1",
773
+ searchDyn: "sd1",
774
+ config: "p1",
775
+ configDyn: "c1",
776
+ });
777
+ dynlog = paramsChangedLog = "";
778
+
779
+ await $state.go(childWithParam, { pathDyn: "pd2" });
780
+
781
+ expect(dynlog).toBe("success;[pathDyn=pd2];{pathDyn=pd2};");
782
+
783
+ dynlog = paramsChangedLog = "";
784
+ await $state.go(childWithParam, {
785
+ pathDyn: "pd2",
786
+ searchDyn: "sd2",
787
+ configDyn: "cd2",
788
+ });
789
+
790
+ expect(dynlog).toBe(
791
+ "success;[configDyn=cd2,searchDyn=sd2];{configDyn=cd2,searchDyn=sd2};",
792
+ );
793
+ });
794
+ });
795
+ });
796
+
797
+ describe("(with dynamic params because reloadOnSearch=false)", function () {
798
+ describe("and only query params changed", () => {
799
+ let entered = false;
800
+ beforeEach(async () => {
801
+ await initStateTo(RS);
802
+ $transitions.onEnter({ entering: "RS" }, function () {
803
+ entered = true;
804
+ });
805
+ });
806
+
807
+ // this passes in isolation
808
+ xit("updates $stateParams", async () => {
809
+ await initStateTo(RS);
810
+ $location.search({ term: "hello" });
811
+ $rootScope.$broadcast("$locationChangeSuccess");
812
+ await wait(10);
813
+ expect($stateParams.term).toEqual("hello");
814
+ expect(entered).toBeFalsy();
815
+ });
816
+
817
+ it("doesn't re-enter state (triggered by url change)", async () => {
818
+ $location.search({ term: "hello" });
819
+ $rootScope.$broadcast("$locationChangeSuccess");
820
+
821
+ expect($location.search()).toEqual({ term: "hello" });
822
+ expect(entered).toBeFalsy();
823
+ });
824
+
825
+ it("doesn't re-enter state (triggered by $state transition)", async () => {
826
+ await initStateTo(RS);
827
+ const promise = $state.go(".", { term: "hello" });
828
+ await promise;
829
+ let success = false,
830
+ transition = promise.transition;
831
+ await transition.promise.then(async () => {
832
+ success = true;
833
+ });
834
+
835
+ expect($state.current).toBe(RS);
836
+ expect(entered).toBeFalsy();
837
+ expect(success).toBeTruthy();
838
+ expect($location.search()).toEqual({ term: "hello" });
839
+ });
840
+
841
+ it("updates URL when (triggered by $state transition)", async () => {
842
+ await initStateTo(RS);
843
+ await $state.go(".", { term: "goodbye" });
844
+
845
+ expect($stateParams.term).toEqual("goodbye");
846
+ expect($location.url()).toEqual("/search?term=goodbye");
847
+ expect(entered).toBeFalsy();
848
+ });
849
+ });
850
+ });
851
+
852
+ it("ignores non-applicable state parameters", async () => {
853
+ await $state.transitionTo("A", { w00t: "hi mom!" });
854
+
855
+ expect($state.current).toBe(A);
856
+ });
857
+
858
+ it("is a no-op when passing the current state and identical parameters", async () => {
859
+ await initStateTo(A);
860
+ const promise = $state.transitionTo(A, {}); // no-op
861
+ expect(promise).toBeDefined(); // but we still get a valid promise
862
+ await promise;
863
+ expect(promise.$$state.value).toBe(A);
864
+ expect($state.current).toBe(A);
865
+ });
866
+
867
+ it("aborts pending transitions (last call wins)", async () => {
868
+ await initStateTo(A);
869
+ logEvents = true;
870
+
871
+ const superseded = $state.transitionTo(B, {});
872
+ await superseded;
873
+ await $state.transitionTo(C, {});
874
+
875
+ expect($state.current).toBe(C);
876
+ expect(superseded.$$state.status).toBeTruthy();
877
+ });
878
+
879
+ it("aborts pending transitions even when going back to the current state", async () => {
880
+ await initStateTo(A);
881
+ logEvents = true;
882
+
883
+ const superseded = $state.transitionTo(B, {});
884
+ await superseded;
885
+ await $state.transitionTo(A, {});
886
+
887
+ expect($state.current).toBe(A);
888
+ expect(superseded.$$state.status).toBeTruthy();
889
+ });
890
+
891
+ xit("aborts pending transitions when aborted from callbacks", () => {
892
+ $state.transitionTo("home.redirect");
893
+ expect($state.current.name).toBe("about");
894
+ });
895
+
896
+ it("triggers onEnter and onExit callbacks", async () => {
897
+ log = "";
898
+ await initStateTo(A);
899
+ logEnterExit = true;
900
+ await $state.transitionTo(D, {});
901
+
902
+ log += $state.current.name + ";";
903
+ await $state.transitionTo(DD, {});
904
+
905
+ log += $state.current.name + ";";
906
+ await $state.transitionTo(A, {});
907
+
908
+ expect(log).toBe(
909
+ "A.onExit;" +
910
+ "D.onEnter;" +
911
+ "D;" +
912
+ "DD.onEnter;" +
913
+ "DD;" +
914
+ "DD.onExit;" +
915
+ "D.onExit;" +
916
+ "A.onEnter;",
917
+ );
918
+ });
919
+
920
+ // // test for #3081
921
+ it("injects resolve values from the exited state into onExit", async () => {
922
+ const registry = $router.stateRegistry;
923
+ registry.register({
924
+ name: "design",
925
+ url: "/design",
926
+ resolve: {
927
+ cc: function () {
928
+ return "cc resolve";
929
+ },
930
+ },
931
+ onExit: function (cc, $state$, $transition$) {
932
+ expect($transition$.to().name).toBe("A");
933
+ expect($transition$.from().name).toBe("design");
934
+
935
+ expect($state$).toBe(registry.get("design"));
936
+
937
+ expect(cc).toBe("cc resolve");
938
+ },
939
+ });
940
+
941
+ await $state.go("design");
942
+
943
+ await $state.go("A");
944
+ });
945
+
946
+ it("doesn't transition to parent state when child has no URL", async () => {
947
+ await $state.transitionTo("about.sidebar");
948
+
949
+ expect($state.current.name).toEqual("about.sidebar");
950
+ });
951
+
952
+ it("notifies on failed relative state resolution", async () => {
953
+ await $state.transitionTo(DD);
954
+
955
+ let actual,
956
+ err = "Could not resolve '^.Z' from state 'DD'";
957
+ await $state
958
+ .transitionTo("^.Z", null, { relative: $state.$current })
959
+ .catch(function (err) {
960
+ actual = err;
961
+ });
962
+
963
+ expect(actual.detail).toEqual(err);
964
+ });
965
+
966
+ it("uses the templateProvider to get template dynamically", async () => {
967
+ await $state.transitionTo("dynamicTemplate", { type: "Acme" });
968
+
969
+ expect(template).toEqual("AcmeFooTemplate");
970
+ });
971
+
972
+ it("uses the controllerProvider to get controller dynamically", async () => {
973
+ await $state.transitionTo("dynamicController", { type: "Acme" });
974
+
975
+ expect(ctrlName).toEqual("AcmeController");
976
+ });
977
+
978
+ it("updates the location #fragment", async () => {
979
+ await $state.transitionTo("home.item", { id: "world", "#": "frag" });
980
+
981
+ expect($location.url()).toBe("/front/world#frag");
982
+ expect($location.hash()).toBe("frag");
983
+ });
984
+
985
+ // passes in isolation. on success callback being polluted
986
+ xit("runs a transition when the location #fragment is updated", (done) => {
987
+ let transitionCount = 0;
988
+ $transitions.onSuccess({}, function () {
989
+ transitionCount++;
990
+ done();
991
+ });
992
+
993
+ $state.transitionTo("home.item", { id: "world", "#": "frag" });
994
+ expect($location.hash()).toBe("frag");
995
+ expect(transitionCount).toBeGreaterThan(0);
996
+
997
+ $state.transitionTo("home.item", { id: "world", "#": "blarg" });
998
+
999
+ expect($location.hash()).toBe("blarg");
1000
+ expect(transitionCount).toBeGreaterThan(1);
1001
+ });
1002
+
1003
+ it("injects $transition$ into resolves", async () => {
1004
+ await $state.transitionTo("home");
1005
+ await $state.transitionTo("about");
1006
+
1007
+ expect(log).toBe("home => about");
1008
+ });
1009
+ });
1010
+ });