@angular-wave/angular.ts 0.9.4 → 0.9.6

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 (645) hide show
  1. package/@types/index.d.ts +1 -84
  2. package/{src/index.ts → @types/namespace.d.ts} +4 -24
  3. package/@types/router/template-factory.d.ts +2 -2
  4. package/dist/angular-ts.esm.js +3 -3
  5. package/dist/angular-ts.umd.js +3 -3
  6. package/dist/angular-ts.umd.min.js +1 -1
  7. package/package.json +9 -2
  8. package/.github/workflows/ci.yml +0 -104
  9. package/.github/workflows/gh-pages.yml +0 -75
  10. package/.husky/pre-commit +0 -5
  11. package/.prettierignore +0 -9
  12. package/CHANGELOG.md +0 -17667
  13. package/CODE_OF_CONDUCT.md +0 -3
  14. package/CONTRIBUTING.md +0 -247
  15. package/DEVELOPERS.md +0 -499
  16. package/Makefile +0 -60
  17. package/RELEASE.md +0 -86
  18. package/TRIAGING.md +0 -127
  19. package/docs/.cspell.yml +0 -8
  20. package/docs/.github/dependabot.yml +0 -14
  21. package/docs/.nvmrc +0 -1
  22. package/docs/CONTRIBUTING.md +0 -28
  23. package/docs/Dockerfile +0 -4
  24. package/docs/LICENSE +0 -201
  25. package/docs/README.md +0 -217
  26. package/docs/assets/icons/logo.svg +0 -1
  27. package/docs/assets/scss/_variables_project.scss +0 -12
  28. package/docs/assets/scss/_variables_project_after_bs.scss +0 -8
  29. package/docs/assets/scss/index.scss +0 -48
  30. package/docs/config.yaml +0 -15
  31. package/docs/content/_index.md +0 -28
  32. package/docs/content/docs/_index.md +0 -61
  33. package/docs/content/docs/directive/_index.md +0 -4
  34. package/docs/content/docs/directive/app.md +0 -11
  35. package/docs/content/docs/directive/aria.md +0 -0
  36. package/docs/content/docs/directive/bind.md +0 -72
  37. package/docs/content/docs/directive/blur.md +0 -38
  38. package/docs/content/docs/directive/channel.md +0 -37
  39. package/docs/content/docs/directive/class-even.md +0 -47
  40. package/docs/content/docs/directive/class-odd.md +0 -48
  41. package/docs/content/docs/directive/class.md +0 -64
  42. package/docs/content/docs/directive/click.md +0 -41
  43. package/docs/content/docs/directive/cloak.md +0 -74
  44. package/docs/content/docs/directive/copy.md +0 -38
  45. package/docs/content/docs/directive/cut.md +0 -40
  46. package/docs/content/docs/directive/dblclick.md +0 -41
  47. package/docs/content/docs/directive/focus.md +0 -38
  48. package/docs/content/docs/directive/get.md +0 -203
  49. package/docs/content/docs/directive/include.md +0 -7
  50. package/docs/content/docs/directive/keydown.md +0 -38
  51. package/docs/content/docs/directive/keyup.md +0 -38
  52. package/docs/content/docs/directive/load.md +0 -43
  53. package/docs/content/docs/directive/mousedown.md +0 -38
  54. package/docs/content/docs/directive/mouseenter.md +0 -38
  55. package/docs/content/docs/directive/mouseleave.md +0 -38
  56. package/docs/content/docs/directive/mousemove.md +0 -38
  57. package/docs/content/docs/directive/mouseout.md +0 -38
  58. package/docs/content/docs/directive/mouseover.md +0 -38
  59. package/docs/content/docs/directive/mouseup.md +0 -38
  60. package/docs/content/docs/directive/non-bindable.md +0 -28
  61. package/docs/content/docs/filter/_index.md +0 -4
  62. package/docs/content/docs/filter/filter.md +0 -78
  63. package/docs/content/docs/filter/json.md +0 -19
  64. package/docs/content/docs/filter/limit-to.md +0 -30
  65. package/docs/content/docs/filter/order-by.md +0 -123
  66. package/docs/content/docs/provider/_index.md +0 -4
  67. package/docs/content/docs/provider/eventBusProvider.md +0 -35
  68. package/docs/content/docs/provider/locationProvider.md +0 -26
  69. package/docs/content/docs/provider/logProvider.md +0 -59
  70. package/docs/content/docs/provider/sceProvider.md +0 -194
  71. package/docs/content/docs/provider/templateCacheProvider.md +0 -100
  72. package/docs/content/docs/provider/templateRequestProvider.md +0 -5
  73. package/docs/content/docs/service/_index.md +0 -4
  74. package/docs/content/docs/service/compile.md +0 -5
  75. package/docs/content/docs/service/controller.md +0 -5
  76. package/docs/content/docs/service/eventBus.md +0 -56
  77. package/docs/content/docs/service/http.md +0 -161
  78. package/docs/content/docs/service/interpolation.md +0 -5
  79. package/docs/content/docs/service/location.md +0 -57
  80. package/docs/content/docs/service/log.md +0 -113
  81. package/docs/content/docs/service/parse.md +0 -5
  82. package/docs/content/docs/service/rootElement.md +0 -5
  83. package/docs/content/docs/service/rootScope.md +0 -5
  84. package/docs/content/docs/service/sce.md +0 -194
  85. package/docs/content/docs/service/templateCache.md +0 -64
  86. package/docs/content/docs/service/templateRequest.md +0 -5
  87. package/docs/content/docs/service/url.md +0 -5
  88. package/docs/content/docs/values/_index.md +0 -4
  89. package/docs/content/docs/values/document.md +0 -29
  90. package/docs/content/docs/values/window.md +0 -29
  91. package/docs/docker-compose.yaml +0 -12
  92. package/docs/docsy.work +0 -5
  93. package/docs/docsy.work.sum +0 -0
  94. package/docs/go.mod +0 -5
  95. package/docs/go.sum +0 -6
  96. package/docs/hugo-disabled.toml +0 -220
  97. package/docs/hugo.yaml +0 -200
  98. package/docs/layouts/404.html +0 -13
  99. package/docs/layouts/_markup/render-heading.html +0 -1
  100. package/docs/layouts/partials/hooks/head-end.html +0 -3
  101. package/docs/layouts/shortcodes/showcss.html +0 -2
  102. package/docs/layouts/shortcodes/showhtml.html +0 -2
  103. package/docs/layouts/shortcodes/showjs.html +0 -2
  104. package/docs/layouts/shortcodes/showraw.html +0 -1
  105. package/docs/layouts/shortcodes/version.html +0 -1
  106. package/docs/package-lock.json +0 -2293
  107. package/docs/package.json +0 -53
  108. package/docs/static/examples/counter/counter-test.html +0 -13
  109. package/docs/static/examples/counter/counter.html +0 -5
  110. package/docs/static/examples/counter/counter.test.js +0 -28
  111. package/docs/static/examples/document/document.html +0 -3
  112. package/docs/static/examples/eventbus/eventbus-test.html +0 -15
  113. package/docs/static/examples/eventbus/eventbus.html +0 -13
  114. package/docs/static/examples/eventbus/eventbus.js +0 -15
  115. package/docs/static/examples/eventbus/eventbus.test.js +0 -19
  116. package/docs/static/examples/i18n/i18n.html +0 -77
  117. package/docs/static/examples/ng-bind/ng-bind.html +0 -9
  118. package/docs/static/examples/ng-blur/ng-blur.html +0 -9
  119. package/docs/static/examples/ng-channel/ng-channel-test.html +0 -17
  120. package/docs/static/examples/ng-channel/ng-channel.html +0 -24
  121. package/docs/static/examples/ng-channel/ng-channel.test.js +0 -31
  122. package/docs/static/examples/ng-class/ng-class.html +0 -71
  123. package/docs/static/examples/ng-class-even/ng-class-even.html +0 -8
  124. package/docs/static/examples/ng-class-odd/ng-class-odd.html +0 -8
  125. package/docs/static/examples/ng-click/ng-click.html +0 -6
  126. package/docs/static/examples/ng-copy/ng-copy.html +0 -6
  127. package/docs/static/examples/ng-cut/ng-cut.html +0 -6
  128. package/docs/static/examples/ng-dblclick/ng-dblclick.html +0 -10
  129. package/docs/static/examples/ng-focus/ng-focus.html +0 -9
  130. package/docs/static/examples/ng-keydown/ng-keydown.html +0 -9
  131. package/docs/static/examples/ng-keyup/ng-keyup.html +0 -9
  132. package/docs/static/examples/ng-load/ng-load.html +0 -8
  133. package/docs/static/examples/ng-mousedown/ng-mousedown.html +0 -6
  134. package/docs/static/examples/ng-mouseenter/ng-mouseenter.html +0 -4
  135. package/docs/static/examples/ng-mouseleave/ng-mouseleave.html +0 -4
  136. package/docs/static/examples/ng-mousemove/ng-mousemove.html +0 -4
  137. package/docs/static/examples/ng-mouseout/ng-mouseout.html +0 -4
  138. package/docs/static/examples/ng-mouseover/ng-mouseover.html +0 -4
  139. package/docs/static/examples/ng-mouseup/ng-mouseup.html +0 -4
  140. package/docs/static/examples/ng-non-bindable/ng-non-bindable-test.html +0 -13
  141. package/docs/static/examples/ng-non-bindable/ng-non-bindable.html +0 -3
  142. package/docs/static/examples/ng-non-bindable/ng-non-bindable.test.js +0 -11
  143. package/docs/static/examples/window/window.html +0 -4
  144. package/docs/static/typedoc/.nojekyll +0 -1
  145. package/docs/static/typedoc/assets/hierarchy.js +0 -1
  146. package/docs/static/typedoc/assets/highlight.css +0 -29
  147. package/docs/static/typedoc/assets/icons.js +0 -18
  148. package/docs/static/typedoc/assets/icons.svg +0 -1
  149. package/docs/static/typedoc/assets/main.js +0 -60
  150. package/docs/static/typedoc/assets/navigation.js +0 -1
  151. package/docs/static/typedoc/assets/search.js +0 -1
  152. package/docs/static/typedoc/assets/style.css +0 -1633
  153. package/docs/static/typedoc/classes/Location.html +0 -55
  154. package/docs/static/typedoc/classes/LocationProvider.html +0 -20
  155. package/docs/static/typedoc/classes/LogProvider.html +0 -6
  156. package/docs/static/typedoc/classes/PubSub.html +0 -71
  157. package/docs/static/typedoc/classes/PubSubProvider.html +0 -4
  158. package/docs/static/typedoc/classes/TemplateCacheProvider.html +0 -5
  159. package/docs/static/typedoc/hierarchy.html +0 -1
  160. package/docs/static/typedoc/index.html +0 -1
  161. package/docs/static/typedoc/interfaces/DefaultPorts.html +0 -5
  162. package/docs/static/typedoc/interfaces/Html5Mode.html +0 -23
  163. package/docs/static/typedoc/interfaces/HttpHeadersGetter.html +0 -1
  164. package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +0 -31
  165. package/docs/static/typedoc/interfaces/HttpRequestConfigHeaders.html +0 -6
  166. package/docs/static/typedoc/interfaces/HttpRequestTransformer.html +0 -1
  167. package/docs/static/typedoc/interfaces/HttpResponse.html +0 -7
  168. package/docs/static/typedoc/interfaces/HttpResponseTransformer.html +0 -1
  169. package/docs/static/typedoc/interfaces/HttpService.html +0 -38
  170. package/docs/static/typedoc/interfaces/LogService.html +0 -12
  171. package/docs/static/typedoc/interfaces/RequestConfig.html +0 -48
  172. package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +0 -38
  173. package/docs/static/typedoc/interfaces/ServiceProvider.html +0 -5
  174. package/docs/static/typedoc/interfaces/UrlParts.html +0 -9
  175. package/docs/static/typedoc/types/HttpParamSerializer.html +0 -2
  176. package/docs/static/typedoc/types/HttpParams.html +0 -2
  177. package/docs/static/typedoc/types/HttpPromise.html +0 -1
  178. package/docs/static/typedoc/types/HttpResponseStatus.html +0 -1
  179. package/docs/static/typedoc/types/LogCall.html +0 -2
  180. package/docs/static/typedoc/types/LogServiceFactory.html +0 -2
  181. package/docs/static/typedoc/types/UrlChangeListener.html +0 -5
  182. package/docs/static/typedoc/variables/EventBus.html +0 -1
  183. package/docs/static/version.js +0 -13
  184. package/docs/test-results/.last-run.json +0 -4
  185. package/docs/test-results/static-examples-counter-counter-counter-example/error-context.md +0 -50
  186. package/eslint.config.js +0 -26
  187. package/images/android-chrome-192x192.png +0 -0
  188. package/images/android-chrome-512x512.png +0 -0
  189. package/images/apple-touch-icon.png +0 -0
  190. package/images/favicon-16x16.png +0 -0
  191. package/images/favicon-32x32.png +0 -0
  192. package/images/favicon.ico +0 -0
  193. package/images/site.webmanifest +0 -19
  194. package/index.html +0 -86
  195. package/legacy.d.ts +0 -1678
  196. package/playwright.config.ts +0 -81
  197. package/public/jasmine/boot0.js +0 -66
  198. package/public/jasmine/boot1.js +0 -134
  199. package/public/jasmine/jasmine-html.js +0 -970
  200. package/public/jasmine/jasmine.css +0 -323
  201. package/public/jasmine/jasmine.js +0 -11406
  202. package/public/public/README.md +0 -1
  203. package/public/public/circle.html +0 -1
  204. package/public/public/jasmine-helper.css +0 -9
  205. package/public/public/my_child_directive.html +0 -1
  206. package/public/public/my_directive.html +0 -1
  207. package/public/public/my_other_directive.html +0 -1
  208. package/public/public/test.html +0 -1
  209. package/rollup.config.js +0 -51
  210. package/src/angular.js +0 -286
  211. package/src/angular.spec.js +0 -1191
  212. package/src/animations/animate-cache.js +0 -80
  213. package/src/animations/animate-children-directive.js +0 -32
  214. package/src/animations/animate-children-directive.md +0 -80
  215. package/src/animations/animate-css-driver.js +0 -284
  216. package/src/animations/animate-css.html +0 -58
  217. package/src/animations/animate-css.js +0 -915
  218. package/src/animations/animate-css.md +0 -263
  219. package/src/animations/animate-js-driver.js +0 -60
  220. package/src/animations/animate-js.html +0 -47
  221. package/src/animations/animate-js.js +0 -371
  222. package/src/animations/animate-queue.js +0 -859
  223. package/src/animations/animate-runner.js +0 -193
  224. package/src/animations/animate-swap.js +0 -33
  225. package/src/animations/animate-swap.md +0 -88
  226. package/src/animations/animate.html +0 -19
  227. package/src/animations/animate.js +0 -546
  228. package/src/animations/animate.md +0 -933
  229. package/src/animations/animate.spec.js +0 -490
  230. package/src/animations/animation.js +0 -519
  231. package/src/animations/animations.test.js +0 -10
  232. package/src/animations/interface.ts +0 -19
  233. package/src/animations/raf-scheduler.html +0 -19
  234. package/src/animations/raf-scheduler.js +0 -92
  235. package/src/animations/raf-scheduler.spec.js +0 -98
  236. package/src/animations/shared.js +0 -341
  237. package/src/binding.html +0 -19
  238. package/src/binding.spec.js +0 -474
  239. package/src/binding.test.js +0 -10
  240. package/src/core/compile/attributes.js +0 -337
  241. package/src/core/compile/compile.html +0 -19
  242. package/src/core/compile/compile.js +0 -3271
  243. package/src/core/compile/compile.md +0 -1128
  244. package/src/core/compile/compile.spec.js +0 -15574
  245. package/src/core/compile/compile.test.js +0 -12
  246. package/src/core/controller/controller.html +0 -22
  247. package/src/core/controller/controller.js +0 -193
  248. package/src/core/controller/controller.spec.js +0 -334
  249. package/src/core/controller/controller.test.js +0 -12
  250. package/src/core/controller/interface.ts +0 -6
  251. package/src/core/core.html +0 -20
  252. package/src/core/core.test.js +0 -12
  253. package/src/core/di/injector.html +0 -19
  254. package/src/core/di/injector.js +0 -307
  255. package/src/core/di/injector.md +0 -740
  256. package/src/core/di/injector.spec.js +0 -2310
  257. package/src/core/di/injector.test.js +0 -12
  258. package/src/core/di/internal-injector.js +0 -286
  259. package/src/core/di/ng-module.html +0 -19
  260. package/src/core/di/ng-module.js +0 -229
  261. package/src/core/di/ng-module.spec.js +0 -263
  262. package/src/core/di/ng-module.test.js +0 -12
  263. package/src/core/filter/filter.html +0 -19
  264. package/src/core/filter/filter.js +0 -55
  265. package/src/core/filter/filter.md +0 -132
  266. package/src/core/filter/filter.spec.js +0 -149
  267. package/src/core/filter/filter.test.js +0 -12
  268. package/src/core/interpolate/interface.ts +0 -14
  269. package/src/core/interpolate/interpolate.html +0 -22
  270. package/src/core/interpolate/interpolate.js +0 -410
  271. package/src/core/interpolate/interpolate.spec.js +0 -601
  272. package/src/core/interpolate/interpolate.test.js +0 -12
  273. package/src/core/parse/ast/ast-node.ts +0 -81
  274. package/src/core/parse/ast/ast.html +0 -19
  275. package/src/core/parse/ast/ast.js +0 -574
  276. package/src/core/parse/ast/ast.spec.js +0 -1453
  277. package/src/core/parse/ast/ast.test.js +0 -10
  278. package/src/core/parse/ast-type.js +0 -23
  279. package/src/core/parse/interface.ts +0 -84
  280. package/src/core/parse/interpreter.js +0 -915
  281. package/src/core/parse/lexer/lexer.html +0 -19
  282. package/src/core/parse/lexer/lexer.js +0 -338
  283. package/src/core/parse/lexer/lexer.spec.js +0 -303
  284. package/src/core/parse/lexer/lexer.test.js +0 -10
  285. package/src/core/parse/lexer/token.ts +0 -22
  286. package/src/core/parse/parse.html +0 -19
  287. package/src/core/parse/parse.js +0 -337
  288. package/src/core/parse/parse.md +0 -57
  289. package/src/core/parse/parse.spec.js +0 -2107
  290. package/src/core/parse/parse.test.js +0 -10
  291. package/src/core/parse/parser/parser.html +0 -19
  292. package/src/core/parse/parser/parser.js +0 -64
  293. package/src/core/parse/parser/parser.spec.js +0 -8
  294. package/src/core/parse/parser/parser.test.js +0 -10
  295. package/src/core/prop.spec.js +0 -775
  296. package/src/core/root-element.spec.js +0 -14
  297. package/src/core/sanitize/interface.ts +0 -10
  298. package/src/core/sanitize/sanitize-uri.js +0 -75
  299. package/src/core/sanitize/sanitize-uri.spec.js +0 -249
  300. package/src/core/sanitize/sanitize-uri.test.js +0 -12
  301. package/src/core/sanitize/sanitize.html +0 -22
  302. package/src/core/scope/scope.html +0 -19
  303. package/src/core/scope/scope.js +0 -1252
  304. package/src/core/scope/scope.spec.js +0 -3000
  305. package/src/core/scope/scope.test.js +0 -12
  306. package/src/directive/aria/aria.html +0 -19
  307. package/src/directive/aria/aria.js +0 -382
  308. package/src/directive/aria/aria.md +0 -145
  309. package/src/directive/aria/aria.spec.js +0 -1241
  310. package/src/directive/aria/aria.test.js +0 -12
  311. package/src/directive/attrs/attrs.html +0 -19
  312. package/src/directive/attrs/attrs.js +0 -106
  313. package/src/directive/attrs/attrs.md +0 -224
  314. package/src/directive/attrs/attrs.spec.js +0 -71
  315. package/src/directive/attrs/attrs.test.js +0 -12
  316. package/src/directive/attrs/boolean.html +0 -19
  317. package/src/directive/attrs/boolean.spec.js +0 -137
  318. package/src/directive/attrs/boolean.test.js +0 -12
  319. package/src/directive/attrs/element-style.html +0 -22
  320. package/src/directive/attrs/element-style.spec.js +0 -85
  321. package/src/directive/attrs/element-style.test.js +0 -12
  322. package/src/directive/attrs/src.html +0 -19
  323. package/src/directive/attrs/src.spec.js +0 -163
  324. package/src/directive/attrs/src.test.js +0 -12
  325. package/src/directive/bind/bind-html.spec.js +0 -36
  326. package/src/directive/bind/bind.html +0 -20
  327. package/src/directive/bind/bind.js +0 -78
  328. package/src/directive/bind/bind.md +0 -142
  329. package/src/directive/bind/bind.spec.js +0 -314
  330. package/src/directive/bind/bind.test.js +0 -12
  331. package/src/directive/channel/channel.html +0 -19
  332. package/src/directive/channel/channel.js +0 -30
  333. package/src/directive/channel/channel.spec.js +0 -67
  334. package/src/directive/channel/channel.test.js +0 -10
  335. package/src/directive/class/class-test.html +0 -23
  336. package/src/directive/class/class.html +0 -19
  337. package/src/directive/class/class.js +0 -184
  338. package/src/directive/class/class.spec.js +0 -704
  339. package/src/directive/class/class.test.js +0 -12
  340. package/src/directive/cloak/cloak.html +0 -19
  341. package/src/directive/cloak/cloak.js +0 -11
  342. package/src/directive/cloak/cloak.spec.js +0 -44
  343. package/src/directive/cloak/cloak.test.js +0 -12
  344. package/src/directive/controller/controller.html +0 -22
  345. package/src/directive/controller/controller.js +0 -11
  346. package/src/directive/controller/controller.md +0 -46
  347. package/src/directive/controller/controller.spec.js +0 -175
  348. package/src/directive/controller/controller.test.js +0 -12
  349. package/src/directive/events/click.spec.js +0 -35
  350. package/src/directive/events/event.spec.js +0 -267
  351. package/src/directive/events/events-test.html +0 -36
  352. package/src/directive/events/events.html +0 -20
  353. package/src/directive/events/events.js +0 -65
  354. package/src/directive/events/events.md +0 -125
  355. package/src/directive/events/events.test.js +0 -12
  356. package/src/directive/form/form.html +0 -19
  357. package/src/directive/form/form.js +0 -669
  358. package/src/directive/form/form.spec.js +0 -1515
  359. package/src/directive/form/form.test.js +0 -12
  360. package/src/directive/http/delete.spec.js +0 -23
  361. package/src/directive/http/form-router-test.html +0 -44
  362. package/src/directive/http/form-test.html +0 -18
  363. package/src/directive/http/get.spec.js +0 -488
  364. package/src/directive/http/http.html +0 -22
  365. package/src/directive/http/http.js +0 -342
  366. package/src/directive/http/http.test.js +0 -12
  367. package/src/directive/http/interface.ts +0 -36
  368. package/src/directive/http/post-example.html +0 -30
  369. package/src/directive/http/post.spec.js +0 -521
  370. package/src/directive/http/put.spec.js +0 -23
  371. package/src/directive/if/if-animate-css.html +0 -57
  372. package/src/directive/if/if-animate-svg.html +0 -25
  373. package/src/directive/if/if.html +0 -19
  374. package/src/directive/if/if.js +0 -72
  375. package/src/directive/if/if.md +0 -76
  376. package/src/directive/if/if.spec.js +0 -293
  377. package/src/directive/if/if.test.js +0 -114
  378. package/src/directive/include/include.html +0 -19
  379. package/src/directive/include/include.js +0 -151
  380. package/src/directive/include/include.md +0 -87
  381. package/src/directive/include/include.spec.js +0 -734
  382. package/src/directive/include/include.test.js +0 -12
  383. package/src/directive/init/init.html +0 -19
  384. package/src/directive/init/init.js +0 -22
  385. package/src/directive/init/init.md +0 -41
  386. package/src/directive/init/init.spec.js +0 -68
  387. package/src/directive/init/init.test.js +0 -12
  388. package/src/directive/inject/inject.html +0 -19
  389. package/src/directive/inject/inject.js +0 -35
  390. package/src/directive/inject/inject.spec.js +0 -108
  391. package/src/directive/inject/inject.test.js +0 -12
  392. package/src/directive/input/input-example.html +0 -15
  393. package/src/directive/input/input.html +0 -19
  394. package/src/directive/input/input.js +0 -1078
  395. package/src/directive/input/input.md +0 -706
  396. package/src/directive/input/input.spec.js +0 -3700
  397. package/src/directive/input/input.test.js +0 -12
  398. package/src/directive/messages/messages.html +0 -22
  399. package/src/directive/messages/messages.js +0 -349
  400. package/src/directive/messages/messages.md +0 -543
  401. package/src/directive/messages/messages.spec.js +0 -1083
  402. package/src/directive/messages/messages.test.js +0 -12
  403. package/src/directive/model/change.md +0 -25
  404. package/src/directive/model/model.html +0 -19
  405. package/src/directive/model/model.js +0 -1170
  406. package/src/directive/model/model.spec.js +0 -1976
  407. package/src/directive/model/model.test.js +0 -12
  408. package/src/directive/model-options/model-option.test.js +0 -12
  409. package/src/directive/model-options/model-options.html +0 -22
  410. package/src/directive/model-options/model-options.js +0 -142
  411. package/src/directive/model-options/model-options.md +0 -407
  412. package/src/directive/model-options/model-options.spec.js +0 -1022
  413. package/src/directive/non-bindable/non-bindable.html +0 -22
  414. package/src/directive/non-bindable/non-bindable.js +0 -9
  415. package/src/directive/non-bindable/non-bindable.spec.js +0 -59
  416. package/src/directive/non-bindable/non-bindable.test.js +0 -12
  417. package/src/directive/observe/observe-demo.html +0 -184
  418. package/src/directive/observe/observe.html +0 -19
  419. package/src/directive/observe/observe.js +0 -41
  420. package/src/directive/observe/observe.spec.js +0 -106
  421. package/src/directive/observe/observe.test.js +0 -10
  422. package/src/directive/on/on.html +0 -19
  423. package/src/directive/on/on.spec.js +0 -215
  424. package/src/directive/on/on.test.js +0 -12
  425. package/src/directive/options/options-example.html +0 -17
  426. package/src/directive/options/options.html +0 -22
  427. package/src/directive/options/options.js +0 -542
  428. package/src/directive/options/options.md +0 -179
  429. package/src/directive/options/options.spec.js +0 -3554
  430. package/src/directive/options/options.test.js +0 -12
  431. package/src/directive/ref/href.html +0 -19
  432. package/src/directive/ref/href.spec.js +0 -141
  433. package/src/directive/ref/href.test.js +0 -19
  434. package/src/directive/ref/ref.html +0 -19
  435. package/src/directive/ref/ref.js +0 -89
  436. package/src/directive/ref/ref.spec.js +0 -546
  437. package/src/directive/repeat/repeat.html +0 -19
  438. package/src/directive/repeat/repeat.js +0 -333
  439. package/src/directive/repeat/repeat.md +0 -330
  440. package/src/directive/repeat/repeat.spec.js +0 -1209
  441. package/src/directive/repeat/repeat.test.js +0 -12
  442. package/src/directive/script/script.html +0 -19
  443. package/src/directive/script/script.js +0 -17
  444. package/src/directive/script/script.md +0 -11
  445. package/src/directive/script/script.spec.js +0 -47
  446. package/src/directive/script/script.test.js +0 -12
  447. package/src/directive/select/select.html +0 -19
  448. package/src/directive/select/select.js +0 -594
  449. package/src/directive/select/select.md +0 -74
  450. package/src/directive/select/select.spec.js +0 -2566
  451. package/src/directive/select/select.test.js +0 -12
  452. package/src/directive/setter/setter.html +0 -19
  453. package/src/directive/setter/setter.js +0 -59
  454. package/src/directive/setter/setter.spec.js +0 -100
  455. package/src/directive/setter/setter.test.js +0 -12
  456. package/src/directive/show-hide/show-hide.html +0 -22
  457. package/src/directive/show-hide/show-hide.js +0 -65
  458. package/src/directive/show-hide/show-hide.md +0 -255
  459. package/src/directive/show-hide/show-hide.spec.js +0 -268
  460. package/src/directive/show-hide/show-hide.test.js +0 -12
  461. package/src/directive/style/style.html +0 -19
  462. package/src/directive/style/style.js +0 -27
  463. package/src/directive/style/style.md +0 -23
  464. package/src/directive/style/style.spec.js +0 -183
  465. package/src/directive/style/style.test.js +0 -12
  466. package/src/directive/switch/switch.html +0 -19
  467. package/src/directive/switch/switch.js +0 -133
  468. package/src/directive/switch/switch.md +0 -66
  469. package/src/directive/switch/switch.spec.js +0 -509
  470. package/src/directive/switch/switch.test.js +0 -12
  471. package/src/directive/transclude/transclude.js +0 -122
  472. package/src/directive/validators/validators.html +0 -22
  473. package/src/directive/validators/validators.js +0 -346
  474. package/src/directive/validators/validators.spec.js +0 -740
  475. package/src/directive/validators/validators.test.js +0 -12
  476. package/src/filters/filter.js +0 -213
  477. package/src/filters/filter.spec.js +0 -719
  478. package/src/filters/filters.html +0 -22
  479. package/src/filters/filters.js +0 -239
  480. package/src/filters/filters.spec.js +0 -36
  481. package/src/filters/filters.test.js +0 -12
  482. package/src/filters/interface.ts +0 -9
  483. package/src/filters/limit-to.js +0 -55
  484. package/src/filters/limit-to.spec.js +0 -252
  485. package/src/filters/order-by.js +0 -181
  486. package/src/filters/order-by.spec.js +0 -883
  487. package/src/index.js +0 -6
  488. package/src/index.spec.js +0 -11
  489. package/src/injection-tokens.js +0 -81
  490. package/src/interface.ts +0 -430
  491. package/src/ng.js +0 -291
  492. package/src/ng.spec.js +0 -45
  493. package/src/router/common/trace.js +0 -240
  494. package/src/router/directives/component-example.html +0 -37
  495. package/src/router/directives/state-directives.html +0 -22
  496. package/src/router/directives/state-directives.js +0 -393
  497. package/src/router/directives/state-directives.md +0 -435
  498. package/src/router/directives/state-directives.spec.js +0 -1091
  499. package/src/router/directives/state-directives.test.js +0 -10
  500. package/src/router/directives/view-directive.js +0 -489
  501. package/src/router/directives/view-directive.spec.js +0 -1921
  502. package/src/router/directives/view-directive.test.js +0 -10
  503. package/src/router/directives/view-directives.html +0 -22
  504. package/src/router/glob/glob.html +0 -19
  505. package/src/router/glob/glob.js +0 -102
  506. package/src/router/glob/glob.spec.js +0 -108
  507. package/src/router/glob/glob.test.js +0 -12
  508. package/src/router/hooks/core-resolvables.js +0 -38
  509. package/src/router/hooks/ignored-transition.js +0 -25
  510. package/src/router/hooks/invalid-transition.js +0 -14
  511. package/src/router/hooks/lazy-load.js +0 -104
  512. package/src/router/hooks/on-enter-exit-retain.js +0 -55
  513. package/src/router/hooks/redirect-to.js +0 -38
  514. package/src/router/hooks/resolve.js +0 -57
  515. package/src/router/hooks/update-globals.js +0 -34
  516. package/src/router/hooks/url.js +0 -34
  517. package/src/router/hooks/views.js +0 -41
  518. package/src/router/params/interface.ts +0 -626
  519. package/src/router/params/param-factory.js +0 -23
  520. package/src/router/params/param-type.js +0 -133
  521. package/src/router/params/param-types.js +0 -153
  522. package/src/router/params/param.js +0 -243
  523. package/src/router/params/state-params.js +0 -36
  524. package/src/router/path/path-node.js +0 -78
  525. package/src/router/path/path-utils.js +0 -207
  526. package/src/router/resolve/interface.ts +0 -208
  527. package/src/router/resolve/resolvable.js +0 -123
  528. package/src/router/resolve/resolve-context.js +0 -190
  529. package/src/router/router-test-hashbang.html +0 -45
  530. package/src/router/router-test.html +0 -41
  531. package/src/router/router.html +0 -22
  532. package/src/router/router.js +0 -54
  533. package/src/router/router.test.js +0 -12
  534. package/src/router/services.spec.js +0 -52
  535. package/src/router/state/interface.ts +0 -1007
  536. package/src/router/state/state-builder.js +0 -376
  537. package/src/router/state/state-builder.spec.js +0 -86
  538. package/src/router/state/state-matcher.js +0 -64
  539. package/src/router/state/state-object.js +0 -118
  540. package/src/router/state/state-queue-manager.js +0 -95
  541. package/src/router/state/state-registry.js +0 -262
  542. package/src/router/state/state-service.js +0 -687
  543. package/src/router/state/state.html +0 -23
  544. package/src/router/state/state.spec.js +0 -1002
  545. package/src/router/state/state.test.js +0 -12
  546. package/src/router/state/target-state.js +0 -162
  547. package/src/router/state/views.js +0 -195
  548. package/src/router/state-filter.spec.js +0 -139
  549. package/src/router/state-filters.js +0 -46
  550. package/src/router/template-factory.html +0 -19
  551. package/src/router/template-factory.js +0 -249
  552. package/src/router/template-factory.spec.js +0 -146
  553. package/src/router/template-factory.test.js +0 -12
  554. package/src/router/transition/hook-builder.js +0 -137
  555. package/src/router/transition/hook-registry.js +0 -181
  556. package/src/router/transition/interface.js +0 -18
  557. package/src/router/transition/interface.ts +0 -922
  558. package/src/router/transition/reject-factory.js +0 -122
  559. package/src/router/transition/transition-event-type.js +0 -26
  560. package/src/router/transition/transition-hook.js +0 -199
  561. package/src/router/transition/transition-service.js +0 -297
  562. package/src/router/transition/transition.js +0 -653
  563. package/src/router/url/url-config.js +0 -155
  564. package/src/router/url/url-matcher.js +0 -532
  565. package/src/router/url/url-rule.js +0 -231
  566. package/src/router/url/url-rules.js +0 -350
  567. package/src/router/url/url-service.js +0 -446
  568. package/src/router/url/url-service.spec.js +0 -1288
  569. package/src/router/url/url.html +0 -19
  570. package/src/router/url/url.test.js +0 -12
  571. package/src/router/view/interface.ts +0 -51
  572. package/src/router/view/view.html +0 -19
  573. package/src/router/view/view.js +0 -262
  574. package/src/router/view/view.spec.js +0 -100
  575. package/src/router/view/view.test.js +0 -12
  576. package/src/router/view-hook.spec.js +0 -215
  577. package/src/router/view-scroll.js +0 -33
  578. package/src/router/view-scroll.spec.js +0 -72
  579. package/src/services/anchor-scroll/anchor-scroll.html +0 -76
  580. package/src/services/anchor-scroll/anchor-scroll.js +0 -147
  581. package/src/services/exception/exception-handler.js +0 -75
  582. package/src/services/exception/interface.ts +0 -7
  583. package/src/services/http/http.html +0 -23
  584. package/src/services/http/http.js +0 -1109
  585. package/src/services/http/http.spec.js +0 -4320
  586. package/src/services/http/http.test.js +0 -11
  587. package/src/services/http/interface.ts +0 -256
  588. package/src/services/http/template-request.spec.js +0 -220
  589. package/src/services/location/interface.ts +0 -70
  590. package/src/services/location/location.html +0 -22
  591. package/src/services/location/location.js +0 -1006
  592. package/src/services/location/location.spec.js +0 -3792
  593. package/src/services/location/location.test.js +0 -12
  594. package/src/services/log/interface.ts +0 -39
  595. package/src/services/log/log.html +0 -19
  596. package/src/services/log/log.js +0 -74
  597. package/src/services/log/log.spec.js +0 -64
  598. package/src/services/log/log.test.js +0 -12
  599. package/src/services/pubsub/pubsub.html +0 -19
  600. package/src/services/pubsub/pubsub.js +0 -349
  601. package/src/services/pubsub/pubsub.spec.js +0 -400
  602. package/src/services/pubsub/pubsub.test.js +0 -12
  603. package/src/services/sce/sce.html +0 -19
  604. package/src/services/sce/sce.js +0 -852
  605. package/src/services/sce/sce.spec.js +0 -617
  606. package/src/services/sce/sce.test.js +0 -12
  607. package/src/services/template-cache/template-cache.html +0 -22
  608. package/src/services/template-cache/template-cache.js +0 -15
  609. package/src/services/template-cache/template-cache.spec.js +0 -134
  610. package/src/services/template-cache/template-cache.test.js +0 -12
  611. package/src/services/template-request/interface.ts +0 -23
  612. package/src/services/template-request/template-request.js +0 -142
  613. package/src/shared/cache.js +0 -7
  614. package/src/shared/common.js +0 -365
  615. package/src/shared/common.spec.js +0 -294
  616. package/src/shared/constants.js +0 -21
  617. package/src/shared/dom.js +0 -716
  618. package/src/shared/hof.js +0 -157
  619. package/src/shared/hof.spec.js +0 -60
  620. package/src/shared/interface.ts +0 -21
  621. package/src/shared/min-err.spec.js +0 -178
  622. package/src/shared/noderef.js +0 -225
  623. package/src/shared/predicates.js +0 -34
  624. package/src/shared/queue.js +0 -105
  625. package/src/shared/queue.spec.js +0 -80
  626. package/src/shared/shared.html +0 -24
  627. package/src/shared/shared.test.js +0 -12
  628. package/src/shared/strings.js +0 -142
  629. package/src/shared/strings.spec.js +0 -40
  630. package/src/shared/test-utils.js +0 -47
  631. package/src/shared/url-utils/interface.ts +0 -54
  632. package/src/shared/url-utils/url-utils.html +0 -22
  633. package/src/shared/url-utils/url-utils.js +0 -122
  634. package/src/shared/url-utils/url-utils.spec.js +0 -148
  635. package/src/shared/url-utils/url-utils.test.js +0 -12
  636. package/src/shared/utils.js +0 -1255
  637. package/src/shared/utils.spec.js +0 -178
  638. package/src/src.html +0 -21
  639. package/src/src.test.js +0 -10
  640. package/tsconfig.json +0 -19
  641. package/tsconfig.types.json +0 -14
  642. package/typedoc.json +0 -8
  643. package/utils/express.js +0 -203
  644. package/utils/version.cjs +0 -23
  645. package/vite.config.js +0 -14
@@ -1,2566 +0,0 @@
1
- import { Angular } from "../../angular.js";
2
- import {
3
- createElementFromHTML,
4
- dealoc,
5
- getController,
6
- } from "../../shared/dom.js";
7
- import { hashKey, equals, isNumberNaN } from "../../shared/utils.js";
8
- import { browserTrigger, wait } from "../../shared/test-utils.js";
9
-
10
- describe("select", () => {
11
- let scope;
12
- let formElement;
13
- let element;
14
- let $compile;
15
- let ngModelCtrl;
16
- let selectCtrl;
17
- let renderSpy;
18
- let $rootScope;
19
- const optionAttributesList = [];
20
- let errors = [];
21
-
22
- async function compile(html) {
23
- formElement = createElementFromHTML(`<form name="form">${html}</form>`);
24
- element = formElement.querySelector("select");
25
- $compile(formElement)(scope);
26
- await wait();
27
- ngModelCtrl = getController(element, "ngModel");
28
- }
29
-
30
- function setSelectValue(selectElement, optionIndex) {
31
- const option = selectElement.querySelectorAll("option")[optionIndex];
32
- selectElement.value = option.value;
33
- browserTrigger(element, "change");
34
- }
35
-
36
- function compileRepeatedOptions() {
37
- compile(
38
- '<select ng-model="robot">' +
39
- '<option value="{{item.value}}" ng-repeat="item in robots">{{item.label}}</option>' +
40
- "</select>",
41
- );
42
- }
43
-
44
- function compileGroupedOptions() {
45
- compile(
46
- '<select ng-model="mySelect">' +
47
- '<option ng-repeat="item in values">{{item.name}}</option>' +
48
- '<optgroup ng-repeat="group in groups" label="{{group.name}}">' +
49
- '<option ng-repeat="item in group.values">{{item.name}}</option>' +
50
- "</optgroup>" +
51
- "</select>",
52
- );
53
- }
54
-
55
- function unknownValue(value) {
56
- return `? ${hashKey(value)} ?`;
57
- }
58
-
59
- beforeEach(() => {
60
- dealoc(document.getElementById("app"));
61
- errors = [];
62
- window.angular = new Angular();
63
- window.angular
64
- .module("myModule", ["ng"])
65
- .decorator("$exceptionHandler", function () {
66
- return (exception) => {
67
- errors.push(exception.message);
68
- };
69
- });
70
- let injector = window.angular.bootstrap(document.getElementById("app"), [
71
- "myModule",
72
- ($compileProvider) => {
73
- $compileProvider.directive("spyOnWriteValue", () => ({
74
- require: "select",
75
- link: {
76
- pre(scope, element, attrs, ctrl) {
77
- selectCtrl = ctrl;
78
- renderSpy = jasmine.createSpy("renderSpy");
79
- selectCtrl.ngModelCtrl.$render = renderSpy.and.callFake(
80
- selectCtrl.ngModelCtrl.$render,
81
- );
82
- spyOn(selectCtrl, "writeValue").and.callThrough();
83
- },
84
- },
85
- }));
86
- $compileProvider.directive("myOptions", () => ({
87
- scope: { myOptions: "=" },
88
- replace: true,
89
- template:
90
- '<option value="{{ option.value }}" ng-repeat="option in myOptions">' +
91
- "{{ options.label }}" +
92
- "</option>",
93
- }));
94
-
95
- $compileProvider.directive("exposeAttributes", () => ({
96
- require: "^^select",
97
- link: {
98
- pre(scope, element, attrs, ctrl) {
99
- optionAttributesList.push(attrs);
100
- },
101
- },
102
- }));
103
- },
104
- ]);
105
- injector.invoke((_$rootScope_, _$compile_) => {
106
- scope = _$rootScope_.$new(); // create a child scope because the root scope can't be $destroy-ed
107
- $rootScope = _$rootScope_;
108
- $compile = _$compile_;
109
- formElement = element = null;
110
- });
111
- });
112
-
113
- afterEach(() => {
114
- scope.$destroy(); // disables unknown option work during destruction
115
- dealoc(formElement);
116
- ngModelCtrl = null;
117
- });
118
-
119
- beforeEach(() => {
120
- jasmine.addMatchers({
121
- toEqualSelectWithOptions() {
122
- return {
123
- compare(actual, expected) {
124
- const actualValues = {};
125
- let optionGroup;
126
- let optionValue;
127
- let options = actual.querySelectorAll("option");
128
- for (let i = 0; i < options.length; i++) {
129
- let option = options[i];
130
- optionGroup = option.parentNode.label || "";
131
- actualValues[optionGroup] = actualValues[optionGroup] || [];
132
- // IE9 doesn't populate the label property from the text property like other browsers
133
- optionValue = option.label || option.text;
134
- actualValues[optionGroup].push(
135
- option.selected ? [optionValue] : optionValue,
136
- );
137
- }
138
-
139
- const message = function () {
140
- return `Expected ${toJson(actualValues)} to equal ${toJson(expected)}.`;
141
- };
142
-
143
- return {
144
- pass: equals(expected, actualValues),
145
- message,
146
- };
147
- },
148
- };
149
- },
150
- });
151
- });
152
-
153
- it("should not add options to the select if ngModel is not present", () => {
154
- const scope = $rootScope;
155
- scope.d = "d";
156
- scope.e = "e";
157
- scope.f = "f";
158
-
159
- compile(
160
- "<select>" +
161
- "<option ng-value=\"'a'\">alabel</option>" +
162
- '<option value="b">blabel</option>' +
163
- "<option >c</option>" +
164
- '<option ng-value="d">dlabel</option>' +
165
- '<option value="{{e}}">elabel</option>' +
166
- "<option>{{f}}</option>" +
167
- "</select>",
168
- );
169
-
170
- const selectCtrl = getController(element, "select");
171
-
172
- expect(selectCtrl.hasOption("a")).toBe(false);
173
- expect(selectCtrl.hasOption("b")).toBe(false);
174
- expect(selectCtrl.hasOption("c")).toBe(false);
175
- expect(selectCtrl.hasOption("d")).toBe(false);
176
- expect(selectCtrl.hasOption("e")).toBe(false);
177
- expect(selectCtrl.hasOption("f")).toBe(false);
178
- });
179
-
180
- describe("select-one", () => {
181
- it("should compile children of a select without a ngModel, but not create a model for it", async () => {
182
- compile(
183
- "<select>" +
184
- '<option selected="true">{{a}}</option>' +
185
- '<option value="">{{b}}</option>' +
186
- "<option>C</option>" +
187
- "</select>",
188
- );
189
- scope.a = "foo";
190
- scope.b = "bar";
191
- await wait();
192
- expect(element.textContent).toBe("foobarC");
193
- });
194
-
195
- it("should not interfere with selection via selected attr if ngModel directive is not present", () => {
196
- compile(
197
- "<select>" +
198
- "<option>not me</option>" +
199
- "<option selected>me!</option>" +
200
- "<option>nah</option>" +
201
- "</select>",
202
- );
203
- expect(element.value).toBe("me!");
204
- });
205
-
206
- describe("required state", () => {
207
- it("should set the error if the empty option is selected", async () => {
208
- compile(
209
- '<select name="select" ng-model="selection" required>' +
210
- '<option value=""></option>' +
211
- '<option value="a">A</option>' +
212
- '<option value="b">B</option>' +
213
- "</select>",
214
- );
215
-
216
- scope.selection = "a";
217
- await wait();
218
- expect(element.classList.contains("ng-valid")).toBeTrue();
219
- expect(ngModelCtrl.$error.required).toBeFalsy();
220
-
221
- let options = element.querySelectorAll("option");
222
-
223
- // view -> model
224
- setSelectValue(element, 0);
225
- expect(element.classList.contains("ng-invalid")).toBeTrue();
226
- expect(ngModelCtrl.$error.required).toBeTruthy();
227
-
228
- setSelectValue(element, 1);
229
- expect(element.classList.contains("ng-valid")).toBeTrue();
230
- expect(ngModelCtrl.$error.required).toBeFalsy();
231
-
232
- // // model -> view
233
- scope.$apply("selection = null");
234
- await wait();
235
- options = element.querySelectorAll("option");
236
- expect(options[0].selected).toBe(true);
237
- expect(element.classList.contains("ng-invalid")).toBeTrue();
238
- expect(ngModelCtrl.$error.required).toBeTruthy();
239
- });
240
-
241
- it("should validate with empty option and bound ngRequired", async () => {
242
- compile(
243
- '<select name="select" ng-model="selection" ng-required="required">' +
244
- '<option value=""></option>' +
245
- '<option value="a">A</option>' +
246
- '<option value="b">B</option>' +
247
- "</select>",
248
- );
249
-
250
- scope.required = false;
251
- await wait();
252
- const options = element.querySelectorAll("option");
253
-
254
- setSelectValue(element, 0);
255
- expect(element.classList.contains("ng-valid")).toBeTrue();
256
-
257
- scope.$apply("required = true");
258
- await wait();
259
- expect(element.classList.contains("ng-invalid")).toBeTrue();
260
-
261
- scope.$apply('selection = "a"');
262
- await wait();
263
- expect(element.classList.contains("ng-valid")).toBeTrue();
264
- expect(element.value).toBe("a");
265
-
266
- setSelectValue(element, 0);
267
- expect(element.classList.contains("ng-invalid")).toBeTrue();
268
-
269
- scope.$apply("required = false");
270
- await wait();
271
- expect(element.classList.contains("ng-valid")).toBeTrue();
272
- });
273
-
274
- it("should not be invalid if no required attribute is present", async () => {
275
- compile(
276
- '<select name="select" ng-model="selection">' +
277
- '<option value=""></option>' +
278
- '<option value="c">C</option>' +
279
- "</select>",
280
- );
281
- await wait();
282
- expect(element.classList.contains("ng-valid")).toBeTrue();
283
- expect(element.classList.contains("ng-pristine")).toBeTrue();
284
- });
285
-
286
- it("should NOT set the error if the unknown option is selected", async () => {
287
- compile(
288
- '<select name="select" ng-model="selection" required>' +
289
- '<option value="a">A</option>' +
290
- '<option value="b">B</option>' +
291
- "</select>",
292
- );
293
- scope.selection = "a";
294
- await wait();
295
-
296
- expect(element.classList.contains("ng-valid")).toBeTrue();
297
- expect(ngModelCtrl.$error.required).toBeFalsy();
298
-
299
- scope.$apply('selection = "c"');
300
- await wait();
301
- expect(element.value).toBe(unknownValue("c"));
302
- expect(element.classList.contains("ng-valid")).toBeTrue();
303
- expect(ngModelCtrl.$error.required).toBeFalsy();
304
- });
305
- });
306
-
307
- it("should work with repeated value options", async () => {
308
- scope.robots = ["c3p0", "r2d2"];
309
- scope.robot = "r2d2";
310
- compile(
311
- '<select ng-model="robot">' +
312
- '<option ng-repeat="r in robots">{{r}}</option>' +
313
- "</select>",
314
- );
315
- await wait();
316
- expect(element.value).toBe("r2d2");
317
-
318
- setSelectValue(element, 0);
319
- expect(element.value).toBe("c3p0");
320
- expect(scope.robot).toBe("c3p0");
321
-
322
- scope.robots.unshift("wallee");
323
- await wait();
324
- expect(element.value).toBe("c3p0");
325
- expect(scope.robot).toBe("c3p0");
326
-
327
- scope.robots = ["c3p0+", "r2d2+"];
328
- scope.robot = "r2d2+";
329
- await wait();
330
- expect(element.value).toBe("r2d2+");
331
- expect(scope.robot).toBe("r2d2+");
332
- });
333
-
334
- it("should interpolate select names", async () => {
335
- scope.robots = ["c3p0", "r2d2"];
336
- scope.name = "r2d2";
337
- scope.nameID = 47;
338
- compile(
339
- '<form name="form"><select ng-model="name" name="name{{nameID}}">' +
340
- '<option ng-repeat="r in robots">{{r}}</option>' +
341
- "</select></form>",
342
- );
343
- await wait();
344
- expect(scope.form.name47.$pristine).toBeTruthy();
345
- setSelectValue(element, 0);
346
- expect(scope.form.name47.$dirty).toBeTruthy();
347
- expect(scope.name).toBe("c3p0");
348
- });
349
-
350
- it("should rename select controls in form when interpolated name changes", async () => {
351
- scope.nameID = "A";
352
- compile('<select ng-model="name" name="name{{nameID}}"></select>');
353
- expect(scope.form.nameA.$name).toBe("nameA");
354
- const oldModel = scope.form.nameA;
355
- scope.nameID = "B";
356
- await wait();
357
- expect(scope.form.nameA).toBeUndefined();
358
- expect(scope.form.nameB).toBe(oldModel);
359
- expect(scope.form.nameB.$name).toBe("nameB");
360
- });
361
-
362
- it("should select options in a group when there is a linebreak before an option", async () => {
363
- scope.mySelect = "B";
364
- await wait();
365
-
366
- const select = createElementFromHTML(
367
- '<select ng-model="mySelect">' +
368
- '<optgroup label="first">' +
369
- '<option value="A">A</option>' +
370
- "</optgroup>" +
371
- '<optgroup label="second">\n' +
372
- '<option value="B">B</option>' +
373
- "</optgroup> " +
374
- "</select>",
375
- );
376
-
377
- $compile(select)(scope);
378
- await wait();
379
- expect(select).toEqualSelectWithOptions({
380
- first: ["A"],
381
- second: [["B"]],
382
- });
383
- });
384
-
385
- it("should only call selectCtrl.writeValue after a digest has occurred", async () => {
386
- scope.mySelect = "B";
387
- await wait();
388
- const select = createElementFromHTML(
389
- '<select spy-on-write-value ng-model="mySelect">' +
390
- '<optgroup label="first">' +
391
- '<option value="A">A</option>' +
392
- "</optgroup>" +
393
- '<optgroup label="second">\n' +
394
- '<option value="B">B</option>' +
395
- "</optgroup> " +
396
- "</select>",
397
- );
398
-
399
- $compile(select)(scope);
400
- expect(selectCtrl.writeValue).not.toHaveBeenCalled();
401
- await wait();
402
-
403
- expect(selectCtrl.writeValue).toHaveBeenCalled();
404
- dealoc(select);
405
- });
406
-
407
- it('should remove the "selected" attribute from the previous option when the model changes', async () => {
408
- compile(
409
- '<select name="select" ng-model="selected">' +
410
- '<option value="">--empty--</option>' +
411
- '<option value="a">A</option>' +
412
- '<option value="b">B</option>' +
413
- "</select>",
414
- );
415
- await wait();
416
- let options = element.querySelectorAll("option");
417
- expect(options[0].selected).toBeTrue();
418
- expect(options[1].selected).toBeFalse();
419
- expect(options[2].selected).toBeFalse();
420
-
421
- scope.selected = "a";
422
- await wait();
423
- options = element.querySelectorAll("option");
424
- expect(options.length).toBe(3);
425
- expect(options[0].selected).toBeFalse();
426
- expect(options[1].selected).toBeTrue();
427
- expect(options[2].selected).toBeFalse();
428
-
429
- scope.selected = "b";
430
- await wait();
431
- options = element.querySelectorAll("option");
432
- expect(options[0].selected).toBeFalse();
433
- expect(options[1].selected).toBeFalse();
434
- expect(options[2].selected).toBeTrue();
435
-
436
- // This will select the empty option
437
- scope.selected = null;
438
- await wait();
439
- expect(options[0].selected).toBeTrue();
440
- expect(options[1].selected).toBeFalse();
441
- expect(options[2].selected).toBeFalse();
442
-
443
- // This will add and select the unknown option
444
- scope.selected = "unmatched value";
445
- await wait();
446
- options = element.querySelectorAll("option");
447
-
448
- expect(options[0].selected).toBeTrue();
449
- expect(options[1].selected).toBeFalse();
450
- expect(options[2].selected).toBeFalse();
451
- expect(options[3].selected).toBeFalse();
452
-
453
- // Back to matched value
454
- scope.selected = "b";
455
- await wait();
456
- options = element.querySelectorAll("option");
457
-
458
- expect(options[0].selected).toBeFalse();
459
- expect(options[1].selected).toBeFalse();
460
- expect(options[2].selected).toBeTrue();
461
- });
462
-
463
- describe("empty option", () => {
464
- it("should allow empty option to be added and removed dynamically", async () => {
465
- scope.dynamicOptions = [];
466
- scope.robot = "";
467
- compile(
468
- '<select ng-model="robot">' +
469
- '<option ng-repeat="opt in dynamicOptions" value="{{opt.val}}">{{opt.display}}</option>' +
470
- "</select>",
471
- );
472
- await wait();
473
- expect(element.value).toBe("? string: ?");
474
-
475
- scope.dynamicOptions = [
476
- { val: "", display: "--empty--" },
477
- { val: "x", display: "robot x" },
478
- { val: "y", display: "robot y" },
479
- ];
480
-
481
- await wait();
482
- expect(element.value).toBe("");
483
-
484
- scope.robot = "x";
485
- await wait();
486
- expect(element.value).toBe("x");
487
-
488
- scope.dynamicOptions.shift();
489
- await wait();
490
- expect(element.value).toBe("x");
491
-
492
- scope.robot = undefined;
493
- await wait();
494
-
495
- expect(element.value).toBe("");
496
- });
497
-
498
- it("should cope use a dynamic empty option that is added to a static empty option", async () => {
499
- // We do not make any special provisions for multiple empty options, so this behavior is
500
- // largely untested
501
- scope.dynamicOptions = [];
502
- scope.robot = "x";
503
- compile(
504
- '<select ng-model="robot">' +
505
- '<option value="">--static-select--</option>' +
506
- '<option ng-repeat="opt in dynamicOptions" value="{{opt.val}}">{{opt.display}}</option>' +
507
- "</select>",
508
- );
509
- await wait();
510
- expect(element.value).toBe(unknownValue("x"));
511
-
512
- scope.robot = undefined;
513
- await wait();
514
- expect(element.querySelectorAll("option")[0].selected).toBe(true);
515
- expect(element.querySelectorAll("option")[0].textContent).toBe(
516
- "--static-select--",
517
- );
518
-
519
- scope.dynamicOptions = [
520
- { val: "", display: "--dynamic-select--" },
521
- { val: "x", display: "robot x" },
522
- { val: "y", display: "robot y" },
523
- ];
524
- await wait();
525
- expect(element.value).toBe("");
526
-
527
- scope.dynamicOptions = [];
528
- await wait();
529
- expect(element.value).toBe("");
530
- });
531
-
532
- it("should select the empty option when model is undefined", async () => {
533
- compile(
534
- '<select ng-model="robot">' +
535
- '<option value="">--select--</option>' +
536
- '<option value="x">robot x</option>' +
537
- '<option value="y">robot y</option>' +
538
- "</select>",
539
- );
540
- await wait();
541
- expect(element.value).toBe("");
542
- });
543
-
544
- it("should support defining an empty option anywhere in the option list", async () => {
545
- compile(
546
- '<select ng-model="robot">' +
547
- '<option value="x">robot x</option>' +
548
- '<option value="">--select--</option>' +
549
- '<option value="y">robot y</option>' +
550
- "</select>",
551
- );
552
- await wait();
553
- expect(element.value).toBe("");
554
- });
555
-
556
- it("should set the model to empty string when empty option is selected", async () => {
557
- scope.robot = "x";
558
- compile(
559
- '<select ng-model="robot">' +
560
- '<option value="">--select--</option>' +
561
- '<option value="x">robot x</option>' +
562
- '<option value="y">robot y</option>' +
563
- "</select>",
564
- );
565
- await wait();
566
- expect(element.value).toBe("x");
567
- setSelectValue(element, 0);
568
- await wait();
569
- expect(element.value).toBe("");
570
- expect(scope.robot).toBe("");
571
- });
572
-
573
- it("should remove unknown option when model is undefined", async () => {
574
- scope.robot = "other";
575
- compile(
576
- '<select ng-model="robot">' +
577
- '<option value="">--select--</option>' +
578
- '<option value="x">robot x</option>' +
579
- '<option value="y">robot y</option>' +
580
- "</select>",
581
- );
582
- await wait();
583
- expect(element.value).toBe(unknownValue("other"));
584
-
585
- scope.robot = undefined;
586
- await wait();
587
- expect(element.value).toBe("");
588
- });
589
-
590
- it("should support option without a value attribute", async () => {
591
- compile(
592
- '<select ng-model="robot">' +
593
- "<option>--select--</option>" +
594
- '<option value="x">robot x</option>' +
595
- '<option value="y">robot y</option>' +
596
- "</select>",
597
- );
598
- await wait();
599
- expect(element.value).toBe("? undefined:undefined ?");
600
- });
601
-
602
- it("should support option without a value with other HTML attributes", async () => {
603
- compile(
604
- '<select ng-model="robot">' +
605
- '<option data-foo="bar">--select--</option>' +
606
- '<option value="x">robot x</option>' +
607
- '<option value="y">robot y</option>' +
608
- "</select>",
609
- );
610
- await wait();
611
- expect(element.value).toBe("? undefined:undefined ?");
612
- });
613
-
614
- xdescribe("interactions with repeated options", () => {
615
- it("should select empty option when model is undefined", async () => {
616
- scope.robots = ["c3p0", "r2d2"];
617
- compile(
618
- '<select ng-model="robot">' +
619
- '<option value="">--select--</option>' +
620
- '<option ng-repeat="r in robots">{{r}}</option>' +
621
- "</select>",
622
- );
623
- await wait();
624
- expect(element.value).toBe("");
625
- });
626
-
627
- it("should set model to empty string when selected", async () => {
628
- scope.robots = ["c3p0", "r2d2"];
629
- compile(
630
- '<select ng-model="robot">' +
631
- '<option value="">--select--</option>' +
632
- '<option ng-repeat="r in robots">{{r}}</option>' +
633
- "</select>",
634
- );
635
- await wait();
636
- setSelectValue(element, 1);
637
- expect(element.value).toBe("c3p0");
638
- expect(scope.robot).toBe("c3p0");
639
-
640
- setSelectValue(element, 0);
641
- await wait();
642
- expect(element.value).toBe("");
643
- expect(scope.robot).toBe("");
644
- });
645
-
646
- it("should not break if both the select and repeater models change at once", async () => {
647
- scope.robots = ["c3p0", "r2d2"];
648
- scope.robot = "c3p0";
649
- compile(
650
- '<select ng-model="robot">' +
651
- '<option value="">--select--</option>' +
652
- '<option ng-repeat="r in robots">{{r}}</option>' +
653
- "</select>",
654
- );
655
- await wait();
656
- expect(element.value).toBe("c3p0");
657
-
658
- scope.robots = ["wallee"];
659
- scope.robot = "";
660
- await wait();
661
- expect(element.value).toBe("");
662
- });
663
- });
664
-
665
- it('should add/remove the "selected" attribute when the empty option is selected/unselected', async () => {
666
- compile(
667
- '<select name="select" ng-model="selected">' +
668
- '<option value="">--select--</option>' +
669
- '<option value="a">A</option>' +
670
- '<option value="b">B</option>' +
671
- "</select>",
672
- );
673
- await wait();
674
- let options = element.querySelectorAll("option");
675
- expect(options.length).toBe(3);
676
- expect(options[0].selected).toBeTrue();
677
- expect(options[1].selected).toBeFalse();
678
- expect(options[2].selected).toBeFalse();
679
-
680
- scope.selected = "a";
681
- await wait();
682
- options = element.querySelectorAll("option");
683
- expect(options.length).toBe(3);
684
- expect(options[0].selected).toBeFalse();
685
- expect(options[1].selected).toBeTrue();
686
- expect(options[2].selected).toBeFalse();
687
-
688
- scope.selected = "no match";
689
- await wait();
690
- options = element.querySelectorAll("option");
691
- expect(options[0].selected).toBeTrue();
692
- expect(options[1].selected).toBeFalse();
693
- expect(options[2].selected).toBeFalse();
694
- });
695
- });
696
-
697
- describe("unknown option", () => {
698
- it("should insert&select temporary unknown option when no options-model match", async () => {
699
- compile(
700
- '<select ng-model="robot">' +
701
- "<option>c3p0</option>" +
702
- "<option>r2d2</option>" +
703
- "</select>",
704
- );
705
- await wait();
706
- expect(element.value).toBe(`? undefined:undefined ?`);
707
-
708
- scope.$apply(() => {
709
- scope.robot = "r2d2";
710
- });
711
- await wait();
712
- expect(element.value).toBe("r2d2");
713
-
714
- scope.$apply(() => {
715
- scope.robot = "wallee";
716
- });
717
- await wait();
718
- expect(element.value).toBe(unknownValue("wallee"));
719
- });
720
-
721
- it("should NOT insert temporary unknown option when model is undefined and empty options is present", async () => {
722
- compile(
723
- '<select ng-model="robot">' +
724
- '<option value="">--select--</option>' +
725
- "<option>c3p0</option>" +
726
- "<option>r2d2</option>" +
727
- "</select>",
728
- );
729
- await wait();
730
- expect(element.value).toBe("");
731
- expect(scope.robot).toBeUndefined();
732
-
733
- scope.$apply(() => {
734
- scope.robot = null;
735
- });
736
- await wait();
737
- expect(element.value).toBe("");
738
-
739
- scope.$apply(() => {
740
- scope.robot = "r2d2";
741
- });
742
- await wait();
743
- expect(element.value).toBe("r2d2");
744
-
745
- scope.$apply(() => {
746
- delete scope.robot;
747
- });
748
- await wait();
749
- expect(element.value).toBe("");
750
- });
751
-
752
- it(
753
- "should insert&select temporary unknown option when no options-model match, empty " +
754
- "option is present and model is defined",
755
- async () => {
756
- scope.robot = "wallee";
757
- compile(
758
- '<select ng-model="robot">' +
759
- '<option value="">--select--</option>' +
760
- "<option>c3p0</option>" +
761
- "<option>r2d2</option>" +
762
- "</select>",
763
- );
764
- await wait();
765
- expect(element.value).toBe(unknownValue("wallee"));
766
-
767
- scope.$apply(() => {
768
- scope.robot = "r2d2";
769
- });
770
- await wait();
771
- expect(element.value).toBe("r2d2");
772
- },
773
- );
774
-
775
- describe("interactions with repeated options", () => {
776
- it("should work with repeated options", async () => {
777
- compile(
778
- '<select ng-model="robot">' +
779
- '<option ng-repeat="r in robots">{{r}}</option>' +
780
- "</select>",
781
- );
782
- await wait();
783
- expect(element.value).toBe(`? undefined:undefined ?`);
784
- expect(scope.robot).toBeUndefined();
785
-
786
- scope.$apply(() => {
787
- scope.robot = "r2d2";
788
- });
789
- await wait();
790
- expect(element.value).toBe(unknownValue("r2d2"));
791
- expect(scope.robot).toBe("r2d2");
792
-
793
- scope.$apply(() => {
794
- scope.robots = ["c3p0", "r2d2"];
795
- });
796
- await wait();
797
- expect(element.value).toBe("r2d2");
798
- expect(scope.robot).toBe("r2d2");
799
- });
800
-
801
- it("should work with empty option and repeated options", async () => {
802
- compile(
803
- '<select ng-model="robot">' +
804
- '<option value="">--select--</option>' +
805
- '<option ng-repeat="r in robots">{{r}}</option>' +
806
- "</select>",
807
- );
808
- await wait();
809
- expect(element.value).toBe("");
810
- expect(scope.robot).toBeUndefined();
811
-
812
- scope.$apply(() => {
813
- scope.robot = "r2d2";
814
- });
815
- await wait();
816
- expect(element.value).toBe(unknownValue("r2d2"));
817
- expect(scope.robot).toBe("r2d2");
818
-
819
- scope.$apply(() => {
820
- scope.robots = ["c3p0", "r2d2"];
821
- });
822
- await wait();
823
- expect(element.value).toBe("r2d2");
824
- expect(scope.robot).toBe("r2d2");
825
- });
826
-
827
- it("should insert unknown element when repeater shrinks and selected option is unavailable", async () => {
828
- scope.robots = ["c3p0", "r2d2"];
829
- scope.robot = "r2d2";
830
- compile(
831
- '<select ng-model="robot">' +
832
- '<option ng-repeat="r in robots">{{r}}</option>' +
833
- "</select>",
834
- );
835
- await wait();
836
- expect(element.value).toBe("r2d2");
837
- expect(scope.robot).toBe("r2d2");
838
-
839
- scope.robots = ["c3p0"];
840
- await wait();
841
-
842
- expect(element.value).toBe("c3p0");
843
-
844
- // TODO we can add a mutation observer to trigger the render but it seems like an overkill for this case
845
- // as none of the behavior below is 'expected' when mutating the array of robots.
846
- // expect(scope.robot).toBe(null);
847
-
848
- // scope.$apply(() => {
849
- // scope.robots.unshift("r2d2");
850
- // });
851
- // await wait();
852
- // expect(element.value).toBe("r2d2");
853
- // expect(scope.robot).toBe(null);
854
-
855
- // scope.$apply(() => {
856
- // scope.robot = "r2d2";
857
- // });
858
- // await wait();
859
- // expect(element.value).toBe("r2d2");
860
-
861
- // scope.$apply(() => {
862
- // delete scope.robots;
863
- // });
864
- // await wait();
865
- // expect(element.value).toBe(unknownValue(null));
866
- // expect(scope.robot).toBe(null);
867
- });
868
- });
869
- });
870
-
871
- it("should not break when adding options via a directive with `replace: true` and a structural directive in its template", async () => {
872
- scope.options = [
873
- { value: "1", label: "Option 1" },
874
- { value: "2", label: "Option 2" },
875
- { value: "3", label: "Option 3" },
876
- ];
877
- compile(
878
- '<select ng-model="mySelect"><option my-options="options"></option></select>',
879
- );
880
- await wait();
881
- expect(element.value).toBe("? undefined:undefined ?");
882
- });
883
-
884
- it("should not throw when removing the element and all its children", async () => {
885
- const template =
886
- '<select ng-model="mySelect" ng-if="visible">' +
887
- '<option value="">--- Select ---</option>' +
888
- "</select>";
889
- scope.visible = true;
890
-
891
- compile(template);
892
-
893
- // It should not throw when removing the element
894
- scope.$apply("visible = false");
895
- await wait();
896
- expect(true).toBeTruthy();
897
- });
898
- });
899
-
900
- describe("selectController", () => {
901
- it("should expose .$hasEmptyOption(), .$isEmptyOptionSelected(), and .$isUnknownOptionSelected()", async () => {
902
- compile('<select ng-model="mySelect"></select>');
903
-
904
- const selectCtrl = getController(element, "select");
905
- await wait();
906
- expect(selectCtrl.$hasEmptyOption).toEqual(jasmine.any(Function));
907
- expect(selectCtrl.$isEmptyOptionSelected).toEqual(jasmine.any(Function));
908
- expect(selectCtrl.$isUnknownOptionSelected).toEqual(
909
- jasmine.any(Function),
910
- );
911
- });
912
-
913
- it("should reflect the status of empty and unknown option", async () => {
914
- scope.dynamicOptions = [];
915
- scope.selected = "";
916
- compile(
917
- '<select ng-model="selected">' +
918
- '<option ng-if="empty" value="">--no selection--</option>' +
919
- '<option ng-repeat="opt in dynamicOptions" value="{{opt.val}}">{{opt.display}}</option>' +
920
- "</select>",
921
- );
922
- await wait();
923
- const selectCtrl = getController(element, "select");
924
- expect(element.value).toBe("? string: ?");
925
- expect(selectCtrl.$hasEmptyOption()).toBe(false);
926
- expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
927
-
928
- scope.dynamicOptions = [
929
- { val: "x", display: "robot x" },
930
- { val: "y", display: "robot y" },
931
- ];
932
- scope.empty = true;
933
- await wait();
934
- expect(element.value).toBe("");
935
- expect(selectCtrl.$hasEmptyOption()).toBe(true);
936
- expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
937
- expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
938
-
939
- // empty -> selection
940
- scope.$apply('selected = "x"');
941
- await wait();
942
- expect(element.value).toBe("x");
943
- expect(selectCtrl.$hasEmptyOption()).toBe(true);
944
- expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
945
- expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
946
-
947
- // // remove empty
948
- // scope.$apply("empty = false");
949
- // await wait();
950
- // expect(element.value).toBe("x");
951
- // expect(selectCtrl.$hasEmptyOption()).toBe(false);
952
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
953
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
954
-
955
- // // selection -> unknown
956
- // scope.$apply('selected = "unmatched"');
957
- // await wait();
958
- // expect(element.value).toBe(unknownValue("unmatched"));
959
- // expect(selectCtrl.$hasEmptyOption()).toBe(false);
960
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
961
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
962
-
963
- // // add empty
964
- // scope.$apply("empty = true");
965
- // await wait();
966
- // expect(element.value).toBe(unknownValue("unmatched"));
967
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
968
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
969
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
970
-
971
- // // unknown -> empty
972
- // scope.$apply("selected = null");
973
- // await wait();
974
- // expect(element.value).toBe("");
975
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
976
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
977
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
978
-
979
- // // empty -> unknown
980
- // scope.$apply('selected = "unmatched"');
981
- // await wait();
982
- // expect(element.value).toBe(unknownValue("unmatched"));
983
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
984
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
985
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
986
-
987
- // // unknown -> selection
988
- // scope.$apply('selected = "y"');
989
- // await wait();
990
- // expect(element.value).toBe("y");
991
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
992
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
993
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
994
-
995
- // // selection -> empty
996
- // scope.$apply("selected = null");
997
- // await wait();
998
- // expect(element.value).toBe("");
999
- // expect(selectCtrl.$hasEmptyOption()).toBe(true);
1000
- // expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
1001
- // expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
1002
- });
1003
- });
1004
-
1005
- describe("selectController.hasOption", () => {
1006
- describe("flat options", () => {
1007
- it("should return false for options shifted via ngRepeat", async () => {
1008
- scope.robots = [
1009
- { value: 1, label: "c3p0" },
1010
- { value: 2, label: "r2d2" },
1011
- ];
1012
-
1013
- compileRepeatedOptions();
1014
-
1015
- const selectCtrl = getController(element, "select");
1016
-
1017
- scope.$apply(() => {
1018
- scope.robots.shift();
1019
- });
1020
- await wait();
1021
- expect(selectCtrl.hasOption("1")).toBe(false);
1022
- expect(selectCtrl.hasOption("2")).toBe(true);
1023
- });
1024
-
1025
- xit("should return false for options popped via ngRepeat", async () => {
1026
- scope.robots = [
1027
- { value: 1, label: "c3p0" },
1028
- { value: 2, label: "r2d2" },
1029
- ];
1030
-
1031
- compileRepeatedOptions();
1032
- await wait();
1033
- const selectCtrl = getController(element, "select");
1034
-
1035
- scope.$apply(() => {
1036
- scope.robots.pop();
1037
- });
1038
- await wait();
1039
- expect(selectCtrl.hasOption("1")).toBe(true);
1040
- expect(selectCtrl.hasOption("2")).toBe(false);
1041
- });
1042
-
1043
- it("should return true for options added via ngRepeat", async () => {
1044
- scope.robots = [{ value: 2, label: "r2d2" }];
1045
-
1046
- compileRepeatedOptions();
1047
-
1048
- const selectCtrl = getController(element, "select");
1049
-
1050
- scope.$apply(() => {
1051
- scope.robots.unshift({ value: 1, label: "c3p0" });
1052
- });
1053
- await wait();
1054
- expect(selectCtrl.hasOption("1")).toBe(true);
1055
- expect(selectCtrl.hasOption("2")).toBe(true);
1056
- });
1057
-
1058
- it("should keep all the options when changing the model", async () => {
1059
- compile(
1060
- "<select ng-model=\"mySelect\"><option ng-repeat=\"o in ['A','B','C']\">{{o}}</option></select>",
1061
- );
1062
-
1063
- const selectCtrl = getController(element, "select");
1064
-
1065
- scope.$apply(() => {
1066
- scope.mySelect = "C";
1067
- });
1068
- await wait();
1069
- expect(selectCtrl.hasOption("A")).toBe(true);
1070
- expect(selectCtrl.hasOption("B")).toBe(true);
1071
- expect(selectCtrl.hasOption("C")).toBe(true);
1072
- expect(element).toEqualSelectWithOptions({ "": ["A", "B", ["C"]] });
1073
- });
1074
- });
1075
-
1076
- describe("grouped options", () => {
1077
- it("should be able to detect when elements move from a previous group", async () => {
1078
- scope.values = [{ name: "A" }];
1079
- scope.groups = [
1080
- {
1081
- name: "first",
1082
- values: [{ name: "B" }, { name: "C" }, { name: "D" }],
1083
- },
1084
- {
1085
- name: "second",
1086
- values: [{ name: "E" }],
1087
- },
1088
- ];
1089
-
1090
- compileGroupedOptions();
1091
-
1092
- const selectCtrl = getController(element, "select");
1093
-
1094
- scope.$apply(() => {
1095
- const itemD = scope.groups[0].values.pop();
1096
- scope.groups[1].values.unshift(itemD);
1097
- scope.values.shift();
1098
- });
1099
- await wait();
1100
- expect(selectCtrl.hasOption("A")).toBe(false);
1101
- expect(selectCtrl.hasOption("B")).toBe(true);
1102
- expect(selectCtrl.hasOption("C")).toBe(true);
1103
- expect(selectCtrl.hasOption("D")).toBe(true);
1104
- expect(selectCtrl.hasOption("E")).toBe(true);
1105
- expect(element).toEqualSelectWithOptions({
1106
- "": [[""]],
1107
- first: ["B", "C"],
1108
- second: ["D", "E"],
1109
- });
1110
- });
1111
-
1112
- it("should be able to detect when elements move from a following group", async () => {
1113
- scope.values = [{ name: "A" }];
1114
- scope.groups = [
1115
- {
1116
- name: "first",
1117
- values: [{ name: "B" }, { name: "C" }],
1118
- },
1119
- {
1120
- name: "second",
1121
- values: [{ name: "D" }, { name: "E" }],
1122
- },
1123
- ];
1124
-
1125
- compileGroupedOptions();
1126
-
1127
- const selectCtrl = getController(element, "select");
1128
-
1129
- scope.$apply(() => {
1130
- const itemD = scope.groups[1].values.shift();
1131
- scope.groups[0].values.push(itemD);
1132
- scope.values.shift();
1133
- });
1134
- await wait();
1135
- expect(selectCtrl.hasOption("A")).toBe(false);
1136
- expect(selectCtrl.hasOption("B")).toBe(true);
1137
- expect(selectCtrl.hasOption("C")).toBe(true);
1138
- expect(selectCtrl.hasOption("D")).toBe(true);
1139
- expect(selectCtrl.hasOption("E")).toBe(true);
1140
- expect(element).toEqualSelectWithOptions({
1141
- "": [[""]],
1142
- first: ["B", "C", "D"],
1143
- second: ["E"],
1144
- });
1145
- });
1146
-
1147
- it("should be able to detect when an element is replaced with an element from a previous group", async () => {
1148
- scope.values = [{ name: "A" }];
1149
- scope.groups = [
1150
- {
1151
- name: "first",
1152
- values: [{ name: "B" }, { name: "C" }, { name: "D" }],
1153
- },
1154
- {
1155
- name: "second",
1156
- values: [{ name: "E" }, { name: "F" }],
1157
- },
1158
- ];
1159
-
1160
- compileGroupedOptions();
1161
-
1162
- const selectCtrl = getController(element, "select");
1163
-
1164
- scope.$apply(() => {
1165
- const itemD = scope.groups[0].values.pop();
1166
- scope.groups[1].values.unshift(itemD);
1167
- scope.groups[1].values.pop();
1168
- });
1169
- await wait();
1170
- expect(selectCtrl.hasOption("A")).toBe(true);
1171
- expect(selectCtrl.hasOption("B")).toBe(true);
1172
- expect(selectCtrl.hasOption("C")).toBe(true);
1173
- expect(selectCtrl.hasOption("D")).toBe(true);
1174
- expect(selectCtrl.hasOption("E")).toBe(true);
1175
- expect(selectCtrl.hasOption("F")).toBe(false);
1176
- expect(element).toEqualSelectWithOptions({
1177
- "": [[""], "A"],
1178
- first: ["B", "C"],
1179
- second: ["D", "E"],
1180
- });
1181
- });
1182
-
1183
- it("should be able to detect when element is replaced with an element from a following group", async () => {
1184
- scope.values = [{ name: "A" }];
1185
- scope.groups = [
1186
- {
1187
- name: "first",
1188
- values: [{ name: "B" }, { name: "C" }],
1189
- },
1190
- {
1191
- name: "second",
1192
- values: [{ name: "D" }, { name: "E" }],
1193
- },
1194
- ];
1195
-
1196
- compileGroupedOptions();
1197
-
1198
- const selectCtrl = getController(element, "select");
1199
-
1200
- scope.$apply(() => {
1201
- scope.groups[0].values.pop();
1202
- const itemD = scope.groups[1].values.shift();
1203
- scope.groups[0].values.push(itemD);
1204
- });
1205
- await wait();
1206
- expect(selectCtrl.hasOption("A")).toBe(true);
1207
- expect(selectCtrl.hasOption("B")).toBe(true);
1208
- expect(selectCtrl.hasOption("C")).toBe(false);
1209
- expect(selectCtrl.hasOption("D")).toBe(true);
1210
- expect(selectCtrl.hasOption("E")).toBe(true);
1211
- expect(element).toEqualSelectWithOptions({
1212
- "": [[""], "A"],
1213
- first: ["B", "D"],
1214
- second: ["E"],
1215
- });
1216
- });
1217
-
1218
- xit("should be able to detect when an element is removed", async () => {
1219
- scope.values = [{ name: "A" }];
1220
- scope.groups = [
1221
- {
1222
- name: "first",
1223
- values: [{ name: "B" }, { name: "C" }],
1224
- },
1225
- {
1226
- name: "second",
1227
- values: [{ name: "D" }, { name: "E" }],
1228
- },
1229
- ];
1230
-
1231
- compileGroupedOptions();
1232
- await wait();
1233
- const selectCtrl = getController(element, "select");
1234
-
1235
- scope.groups[1].values.shift();
1236
- await wait();
1237
- expect(selectCtrl.hasOption("A")).toBe(true);
1238
- expect(selectCtrl.hasOption("B")).toBe(true);
1239
- expect(selectCtrl.hasOption("C")).toBe(true);
1240
- expect(selectCtrl.hasOption("D")).toBe(false);
1241
- expect(selectCtrl.hasOption("E")).toBe(true);
1242
- expect(element).toEqualSelectWithOptions({
1243
- "": [[""], "A"],
1244
- first: ["B", "C"],
1245
- second: ["E"],
1246
- });
1247
- });
1248
-
1249
- it("should be able to detect when a group is removed", async () => {
1250
- scope.values = [{ name: "A" }];
1251
- scope.groups = [
1252
- {
1253
- name: "first",
1254
- values: [{ name: "B" }, { name: "C" }],
1255
- },
1256
- {
1257
- name: "second",
1258
- values: [{ name: "D" }, { name: "E" }],
1259
- },
1260
- ];
1261
-
1262
- compileGroupedOptions();
1263
-
1264
- const selectCtrl = getController(element, "select");
1265
-
1266
- scope.$apply(() => {
1267
- scope.groups.pop();
1268
- });
1269
- await wait();
1270
- expect(selectCtrl.hasOption("A")).toBe(true);
1271
- expect(selectCtrl.hasOption("B")).toBe(true);
1272
- expect(selectCtrl.hasOption("C")).toBe(true);
1273
- expect(selectCtrl.hasOption("D")).toBe(false);
1274
- expect(selectCtrl.hasOption("E")).toBe(false);
1275
- expect(element).toEqualSelectWithOptions({
1276
- "": [[""], "A"],
1277
- first: ["B", "C"],
1278
- });
1279
- });
1280
- });
1281
- });
1282
-
1283
- describe("select-multiple", () => {
1284
- xit('should support type="select-multiple"', async () => {
1285
- compile(
1286
- '<select ng-model="selection" multiple>' +
1287
- "<option>A</option>" +
1288
- "<option>B</option>" +
1289
- "</select>",
1290
- );
1291
-
1292
- scope.$apply(() => {
1293
- scope.selection = ["A"];
1294
- });
1295
- await wait();
1296
- let optionElements = element.querySelectorAll("option");
1297
-
1298
- expect(element.value).toBe("A");
1299
- expect(optionElements[0].selected).toBeTrue();
1300
- expect(optionElements[1].selected).toBeFalse();
1301
-
1302
- scope.$apply(() => {
1303
- scope.selection.push("B");
1304
- });
1305
- await wait();
1306
- optionElements = element.querySelectorAll("option");
1307
-
1308
- expect(element.value).toBe("A");
1309
- expect(optionElements[0].selected).toBeTrue();
1310
- expect(optionElements[1].selected).toBeTrue();
1311
- });
1312
-
1313
- it("should work with optgroups", async () => {
1314
- compile(
1315
- '<select ng-model="selection" multiple>' +
1316
- '<optgroup label="group1">' +
1317
- "<option>A</option>" +
1318
- "<option>B</option>" +
1319
- "</optgroup>" +
1320
- "</select>",
1321
- );
1322
- await wait();
1323
- expect(element.value).toBe("");
1324
- expect(scope.selection).toBeUndefined();
1325
-
1326
- scope.$apply(() => {
1327
- scope.selection = ["A"];
1328
- });
1329
- await wait();
1330
- expect(element.value).toBe("A");
1331
-
1332
- scope.$apply(() => {
1333
- scope.selection.push("B");
1334
- });
1335
- await wait();
1336
- expect(element.value).toBe("A");
1337
- });
1338
-
1339
- it("should require", async () => {
1340
- compile(
1341
- '<select name="select" ng-model="selection" multiple required>' +
1342
- "<option>A</option>" +
1343
- "<option>B</option>" +
1344
- "</select>",
1345
- );
1346
-
1347
- scope.$apply(() => {
1348
- scope.selection = [];
1349
- });
1350
- await wait();
1351
- expect(scope.form.select.$error.required).toBeTruthy();
1352
- expect(element.classList.contains("ng-invalid")).toBeTrue();
1353
- expect(element.classList.contains("ng-pristine")).toBeTrue();
1354
-
1355
- scope.$apply(() => {
1356
- scope.selection = ["A"];
1357
- });
1358
- await wait();
1359
- expect(element.classList.contains("ng-valid")).toBeTrue();
1360
- expect(element.classList.contains("ng-pristine")).toBeTrue();
1361
-
1362
- element.value = "B";
1363
- browserTrigger(element, "change");
1364
- expect(element.classList.contains("ng-valid")).toBeTrue();
1365
- expect(element.classList.contains("ng-dirty")).toBeTrue();
1366
- });
1367
-
1368
- describe("calls to $render", () => {
1369
- let ngModelCtrl;
1370
-
1371
- beforeEach(() => {
1372
- compile(
1373
- '<select name="select" ng-model="selection" multiple>' +
1374
- "<option>A</option>" +
1375
- "<option>B</option>" +
1376
- "</select>",
1377
- );
1378
-
1379
- ngModelCtrl = getController(element, "ngModel");
1380
- spyOn(ngModelCtrl, "$render").and.callThrough();
1381
- });
1382
-
1383
- xit("should call $render once when the reference to the viewValue changes", async () => {
1384
- scope.$apply(() => {
1385
- scope.selection = ["A"];
1386
- });
1387
- await wait();
1388
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(1);
1389
-
1390
- scope.$apply(() => {
1391
- scope.selection = ["A", "B"];
1392
- });
1393
- await wait();
1394
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(2);
1395
-
1396
- scope.$apply(() => {
1397
- scope.selection = [];
1398
- });
1399
- await wait();
1400
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(3);
1401
- });
1402
-
1403
- xit("should call $render once when the viewValue deep-changes", async () => {
1404
- scope.$apply(() => {
1405
- scope.selection = ["A"];
1406
- });
1407
- await wait();
1408
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(1);
1409
-
1410
- scope.$apply(() => {
1411
- scope.selection.push("B");
1412
- });
1413
- await wait();
1414
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(2);
1415
-
1416
- scope.$apply(() => {
1417
- scope.selection.length = 0;
1418
- });
1419
- await wait();
1420
- expect(ngModelCtrl.$render).toHaveBeenCalledTimes(3);
1421
- });
1422
- });
1423
- });
1424
-
1425
- describe("option", () => {
1426
- it("should populate a missing value attribute with the option text", async () => {
1427
- compile('<select ng-model="x"><option selected>abc</option></select>');
1428
- await wait();
1429
- expect(element.value).toBe(`? undefined:undefined ?`);
1430
- });
1431
-
1432
- it("should ignore the option text if the value attribute exists", async () => {
1433
- compile('<select ng-model="x"><option value="abc">xyz</option></select>');
1434
- await wait();
1435
- expect(element.value).toBe(`? undefined:undefined ?`);
1436
- });
1437
-
1438
- it("should set value even if self closing HTML", async () => {
1439
- scope.x = "hello";
1440
- compile('<select ng-model="x"><option>hello</select>');
1441
- await wait();
1442
- expect(element.value).toBe("hello");
1443
- });
1444
-
1445
- it("should add options with interpolated value attributes", async () => {
1446
- scope.option1 = "option1";
1447
- scope.option2 = "option2";
1448
-
1449
- compile(
1450
- '<select ng-model="selected">' +
1451
- '<option value="{{option1}}">Option 1</option>' +
1452
- '<option value="{{option2}}">Option 2</option>' +
1453
- "</select>",
1454
- );
1455
- await wait();
1456
- expect(scope.selected).toBeUndefined();
1457
-
1458
- setSelectValue(element, 0);
1459
- await wait();
1460
- expect(scope.selected).toBe("option1");
1461
-
1462
- scope.selected = "option2";
1463
- await wait();
1464
- expect(element.querySelectorAll("option")[0].selected).toBe(false);
1465
- expect(element.querySelectorAll("option")[0].textContent).toBe(
1466
- "Option 1",
1467
- );
1468
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1469
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1470
- "Option 2",
1471
- );
1472
- });
1473
-
1474
- it("should update the option when the interpolated value attribute changes", async () => {
1475
- scope.option1 = "option1";
1476
- scope.option2 = "";
1477
-
1478
- compile(
1479
- '<select ng-model="selected">' +
1480
- '<option value="{{option1}}">Option 1</option>' +
1481
- '<option value="{{option2}}">Option 2</option>' +
1482
- "</select>",
1483
- );
1484
- await wait();
1485
- const selectCtrl = getController(element, "select");
1486
- spyOn(selectCtrl, "removeOption").and.callThrough();
1487
-
1488
- expect(scope.selected).toBeUndefined();
1489
- expect(selectCtrl.removeOption).not.toHaveBeenCalled();
1490
-
1491
- // Change value of option2
1492
- scope.option2 = "option2Changed";
1493
- scope.selected = "option2Changed";
1494
- await wait();
1495
- expect(selectCtrl.removeOption).toHaveBeenCalledWith("");
1496
- expect(element.querySelectorAll("option")[0].selected).toBe(false);
1497
- expect(element.querySelectorAll("option")[0].textContent).toBe(
1498
- "Option 1",
1499
- );
1500
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1501
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1502
- "Option 2",
1503
- );
1504
- });
1505
-
1506
- it("should add options with interpolated text", async () => {
1507
- scope.option1 = "Option 1";
1508
- scope.option2 = "Option 2";
1509
-
1510
- compile(
1511
- '<select ng-model="selected">' +
1512
- "<option>{{option1}}</option>" +
1513
- "<option>{{option2}}</option>" +
1514
- "</select>",
1515
- );
1516
-
1517
- await wait();
1518
- expect(scope.selected).toBeUndefined();
1519
- setSelectValue(element, 0);
1520
- await wait();
1521
- expect(element.querySelectorAll("option")[0].selected).toBe(true);
1522
- expect(element.querySelectorAll("option")[0].textContent).toBe(
1523
- "Option 1",
1524
- );
1525
- expect(scope.selected).toBe("Option 1");
1526
-
1527
- scope.selected = "Option 2";
1528
- await wait();
1529
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1530
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1531
- "Option 2",
1532
- );
1533
- });
1534
-
1535
- xit("should update options when their interpolated text changes", async () => {
1536
- scope.option1 = "Option 1";
1537
- scope.option2 = "";
1538
-
1539
- compile(
1540
- '<select ng-model="selected">' +
1541
- "<option>{{option1}}</option>" +
1542
- "<option>{{option2}}</option>" +
1543
- "</select>",
1544
- );
1545
- await wait();
1546
- const selectCtrl = getController(element, "select");
1547
- spyOn(selectCtrl, "removeOption").and.callThrough();
1548
-
1549
- expect(scope.selected).toBeUndefined();
1550
- expect(selectCtrl.removeOption).not.toHaveBeenCalled();
1551
-
1552
- // Change value of option2
1553
- scope.option2 = "Option 2 Changed";
1554
- scope.selected = "Option 2 Changed";
1555
- await wait();
1556
- expect(selectCtrl.removeOption).toHaveBeenCalledWith("");
1557
- expect(element.querySelectorAll("option")[1].selected).toBe(true);
1558
- expect(element.querySelectorAll("option")[1].textContent).toBe(
1559
- "Option 2 Changed",
1560
- );
1561
- });
1562
-
1563
- xit("should not blow up when option directive is found inside of a datalist", async () => {
1564
- const element = $compile(
1565
- "<div>" +
1566
- "<datalist><option>some val</option></datalist>" +
1567
- "<span>{{foo}}</span>" +
1568
- "</div>",
1569
- )($rootScope);
1570
-
1571
- $rootScope.foo = "success";
1572
- await wait();
1573
- expect(element.querySelectorAll("span").textContent).toBe("success");
1574
- });
1575
-
1576
- it('should throw an exception if an option value interpolates to "hasOwnProperty"', async () => {
1577
- scope.hasOwnPropertyOption = "hasOwnProperty";
1578
- compile(
1579
- '<select ng-model="x">' +
1580
- "<option>{{hasOwnPropertyOption}}</option>" +
1581
- "</select>",
1582
- );
1583
- expect(errors[0]).toMatch(/badname/);
1584
- });
1585
-
1586
- describe("with ngValue (and non-primitive values)", () => {
1587
- [
1588
- "string",
1589
- undefined,
1590
- 1,
1591
- true,
1592
- null,
1593
- { prop: "value" },
1594
- ["a"],
1595
- NaN,
1596
- ].forEach((prop) => {
1597
- xit("should set the option attribute and select it for value $prop", async () => {
1598
- scope.option1 = prop;
1599
- scope.option2 = "red";
1600
- scope.selected = "NOMATCH";
1601
-
1602
- compile(
1603
- '<select ng-model="selected">' +
1604
- '<option ng-value="option1">{{option1}}</option>' +
1605
- '<option ng-value="option2">{{option2}}</option>' +
1606
- "</select>",
1607
- );
1608
- await wait();
1609
- expect(element.querySelectorAll("option")[0].value).toBe(
1610
- "? string:NOMATCH ?",
1611
- );
1612
-
1613
- scope.selected = prop;
1614
- await wait();
1615
- expect(element.querySelectorAll("option")[0].value).toBe(
1616
- hashKey(prop),
1617
- );
1618
-
1619
- // Reset
1620
- scope.selected = false;
1621
- await wait();
1622
- expect(element.querySelectorAll("option")[0].value).toBe(
1623
- "? boolean:false ?",
1624
- );
1625
-
1626
- setSelectValue(element, 0);
1627
- await wait();
1628
- if (isNumberNaN(prop)) {
1629
- expect(scope.selected).toBeNaN();
1630
- } else {
1631
- expect(scope.selected).toBe(prop);
1632
- }
1633
- });
1634
- });
1635
-
1636
- [
1637
- "string",
1638
- undefined,
1639
- 1,
1640
- true,
1641
- null,
1642
- { prop: "value" },
1643
- ["a"],
1644
- NaN,
1645
- ].forEach((prop) => {
1646
- xit("should update the option attribute and select it for value $prop", async () => {
1647
- scope.option = prop;
1648
- scope.option2 = "red";
1649
- scope.selected = "NOMATCH";
1650
-
1651
- compile(
1652
- '<select ng-model="selected">' +
1653
- '<option ng-value="option">{{option}}</option>' +
1654
- '<option ng-value="option2">{{option2}}</option>' +
1655
- "</select>",
1656
- );
1657
- await wait();
1658
- const selectController = getController(element, "select");
1659
- spyOn(selectController, "removeOption").and.callThrough();
1660
-
1661
- expect(selectController.removeOption).not.toHaveBeenCalled();
1662
- expect(element.querySelectorAll("option")[0].value).toBe(
1663
- "? string:NOMATCH ?",
1664
- );
1665
-
1666
- scope.selected = prop;
1667
- await wait();
1668
- expect(element.querySelectorAll("option")[0].value).toBe(
1669
- hashKey(prop),
1670
- );
1671
- expect(element.selectedIndex).toBe(0);
1672
-
1673
- scope.option = "UPDATEDVALUE";
1674
- await wait();
1675
- expect(selectController.removeOption.calls.count()).toBe(1);
1676
-
1677
- // Updating the option value currently does not update the select model
1678
- if (isNumberNaN(prop)) {
1679
- expect(selectController.removeOption.calls.argsFor(0)[0]).toBeNaN();
1680
- } else {
1681
- expect(selectController.removeOption.calls.argsFor(0)[0]).toBe(
1682
- prop,
1683
- );
1684
- }
1685
-
1686
- expect(scope.selected).toBe(null);
1687
- expect(element.selectedIndex).toBe(0);
1688
- expect(element.querySelectorAll("option").length).toBe(3);
1689
- expect(element.querySelectorAll("option")[0][0].selected).toBe(true);
1690
- expect(element.querySelectorAll("option")[0].value).toBe(
1691
- unknownValue(prop),
1692
- );
1693
- expect(element.querySelectorAll("option")[1].selected).toBe(false);
1694
- expect(element.querySelectorAll("option")[1].value).toBe(
1695
- "string:UPDATEDVALUE",
1696
- );
1697
-
1698
- scope.selected = "UPDATEDVALUE";
1699
- await wait();
1700
- expect(element.selectedIndex).toBe(0);
1701
- expect(element.querySelectorAll("option")[0].value).toBe(
1702
- "string:UPDATEDVALUE",
1703
- );
1704
- });
1705
- });
1706
- it("should interact with custom attribute $observe and $set calls", async () => {
1707
- const log = [];
1708
- let optionAttr;
1709
-
1710
- compile(
1711
- '<select ng-model="selected">' +
1712
- '<option expose-attributes ng-value="option">{{option}}</option>' +
1713
- "</select>",
1714
- );
1715
- await wait();
1716
- optionAttr = optionAttributesList[0];
1717
- optionAttr.$observe("value", (newVal) => {
1718
- log.push(newVal);
1719
- });
1720
-
1721
- scope.option = "init";
1722
- await wait();
1723
- expect(log[0]).toBe("init");
1724
- expect(element.querySelectorAll("option")[1].value).toBe("string:init");
1725
-
1726
- optionAttr.$set("value", "update");
1727
- await wait();
1728
- expect(log[1]).toBe("update");
1729
- expect(element.querySelectorAll("option")[1].value).toBe(
1730
- "string:update",
1731
- );
1732
- });
1733
-
1734
- it("should ignore the option text / value attribute if the ngValue attribute exists", async () => {
1735
- scope.ngvalue = "abc";
1736
- scope.value = "def";
1737
- scope.textvalue = "ghi";
1738
-
1739
- compile(
1740
- '<select ng-model="x"><option ng-value="ngvalue" value="{{value}}">{{textvalue}}</option></select>',
1741
- );
1742
- await wait();
1743
- expect(element.value).toBe(`? undefined:undefined ?`);
1744
- });
1745
-
1746
- it("should ignore option text with multiple interpolations if the ngValue attribute exists", async () => {
1747
- scope.ngvalue = "abc";
1748
- scope.textvalue = "def";
1749
- scope.textvalue2 = "ghi";
1750
-
1751
- compile(
1752
- '<select ng-model="x"><option ng-value="ngvalue">{{textvalue}} {{textvalue2}}</option></select>',
1753
- );
1754
- await wait();
1755
- expect(element.value).toBe(`? undefined:undefined ?`);
1756
- });
1757
-
1758
- it("should select the first option if it is `undefined`", async () => {
1759
- scope.selected = undefined;
1760
-
1761
- scope.option1 = undefined;
1762
- scope.option2 = "red";
1763
-
1764
- compile(
1765
- '<select ng-model="selected">' +
1766
- '<option ng-value="option1">{{option1}}</option>' +
1767
- '<option ng-value="option2">{{option2}}</option>' +
1768
- "</select>",
1769
- );
1770
- await wait();
1771
- expect(element.value).toBe("? undefined:undefined ?");
1772
- });
1773
-
1774
- describe("and select[multiple]", () => {
1775
- xit("should allow multiple selection", async () => {
1776
- scope.options = {
1777
- a: "string",
1778
- b: undefined,
1779
- c: 1,
1780
- d: true,
1781
- e: null,
1782
- f: NaN,
1783
- };
1784
- scope.selected = [];
1785
-
1786
- compile(
1787
- '<select multiple ng-model="selected">' +
1788
- '<option ng-value="options.a">{{options.a}}</option>' +
1789
- '<option ng-value="options.b">{{options.b}}</option>' +
1790
- '<option ng-value="options.c">{{options.c}}</option>' +
1791
- '<option ng-value="options.d">{{options.d}}</option>' +
1792
- '<option ng-value="options.e">{{options.e}}</option>' +
1793
- '<option ng-value="options.f">{{options.f}}</option>' +
1794
- "</select>",
1795
- );
1796
- await wait();
1797
- expect(
1798
- Object.values(element.childNodes)
1799
- .map((x) => x.value)
1800
- .join(""),
1801
- ).toBe(
1802
- [
1803
- "string:string",
1804
- "undefined:undefined",
1805
- "number:1",
1806
- "boolean:true",
1807
- "object:null",
1808
- "number:NaN",
1809
- ].join(""),
1810
- );
1811
-
1812
- scope.selected = ["string", 1];
1813
- await wait();
1814
- expect(element.querySelectorAll("option")[0][0].selected).toBe(true);
1815
- expect(element.querySelectorAll("option")[2][0].selected).toBe(true);
1816
-
1817
- setSelectValue(element, 1);
1818
- await wait();
1819
- expect(scope.selected).toEqual([undefined]);
1820
-
1821
- // reset
1822
- scope.selected = [];
1823
- await wait();
1824
- let elems = element.querySelectorAll("option");
1825
-
1826
- for (let i = 0; i < elems.length; i++) {
1827
- elems[i][0].selected = true;
1828
- }
1829
- browserTrigger(element, "change");
1830
- await wait();
1831
- const arrayVal = ["a"];
1832
- arrayVal.$$hashKey = "object:4";
1833
- await wait();
1834
- expect(scope.selected).toEqual([
1835
- "string",
1836
- undefined,
1837
- 1,
1838
- true,
1839
- null,
1840
- NaN,
1841
- ]);
1842
- });
1843
- });
1844
- });
1845
-
1846
- describe("updating the model and selection when option elements are manipulated", () => {
1847
- ["ngValue", "interpolatedValue", "interpolatedText"].forEach((prop) => {
1848
- xit("should set the model to null when the currently selected option with $prop is removed", async () => {
1849
- const A = { name: "A" };
1850
- const B = { name: "B" };
1851
- const C = { name: "C" };
1852
-
1853
- scope.options = [A, B, C];
1854
- scope.obj = {};
1855
-
1856
- let optionString = "";
1857
-
1858
- switch (prop) {
1859
- case "ngValue":
1860
- optionString =
1861
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
1862
- break;
1863
- case "interpolatedValue":
1864
- optionString =
1865
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
1866
- break;
1867
- case "interpolatedText":
1868
- optionString =
1869
- '<option ng-repeat="option in options">{{option.name}}</option>';
1870
- break;
1871
- }
1872
-
1873
- compile(`<select ng-model="obj.value">${optionString}</select>`);
1874
- await wait();
1875
- let optionElements = element.querySelectorAll("option");
1876
- expect(optionElements.length).toEqual(4);
1877
- setSelectValue(optionElements, 0);
1878
- await wait();
1879
- optionElements = element.querySelectorAll("option");
1880
- expect(optionElements.length).toEqual(3);
1881
- expect(scope.obj.value).toBe(prop === "ngValue" ? A : "A");
1882
-
1883
- scope.options.shift();
1884
- await wait();
1885
- optionElements = element.querySelectorAll("option");
1886
- expect(optionElements.length).toEqual(3);
1887
- expect(scope.obj.value).toBe(null);
1888
- expect(element.value).toBe("? object:null ?");
1889
- });
1890
-
1891
- xit("should set the model to null when the currently selected option with $prop changes its value", async () => {
1892
- const A = { name: "A" };
1893
- const B = { name: "B" };
1894
- const C = { name: "C" };
1895
-
1896
- scope.options = [A, B, C];
1897
- scope.obj = {};
1898
-
1899
- let optionString = "";
1900
-
1901
- switch (prop) {
1902
- case "ngValue":
1903
- optionString =
1904
- '<option ng-repeat="option in options" ng-value="option.name">{{$index}}</option>';
1905
- break;
1906
- case "interpolatedValue":
1907
- optionString =
1908
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
1909
- break;
1910
- case "interpolatedText":
1911
- optionString =
1912
- '<option ng-repeat="option in options">{{option.name}}</option>';
1913
- break;
1914
- }
1915
-
1916
- compile(`<select ng-model="obj.value">${optionString}</select>`);
1917
- await wait();
1918
- let optionElements = element.querySelectorAll("option");
1919
- expect(optionElements.length).toEqual(4);
1920
- setSelectValue(optionElements, 0);
1921
- await wait();
1922
- optionElements = element.querySelectorAll("option");
1923
- expect(optionElements.length).toEqual(3);
1924
- expect(scope.obj.value).toBe("A");
1925
-
1926
- A.name = "X";
1927
- optionElements = element.querySelectorAll("option");
1928
- await wait();
1929
- expect(optionElements.length).toEqual(4);
1930
- expect(scope.obj.value).toBe(null);
1931
- expect(element.value).toBe("? string:A ?");
1932
- });
1933
-
1934
- xit("should set the model to null when the currently selected option with $prop is disabled", async () => {
1935
- const A = { name: "A" };
1936
- const B = { name: "B" };
1937
- const C = { name: "C" };
1938
-
1939
- scope.options = [A, B, C];
1940
- scope.obj = {};
1941
-
1942
- let optionString = "";
1943
-
1944
- switch (prop) {
1945
- case "ngValue":
1946
- optionString =
1947
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
1948
- break;
1949
- case "interpolatedValue":
1950
- optionString =
1951
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
1952
- break;
1953
- case "interpolatedText":
1954
- optionString =
1955
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
1956
- break;
1957
- }
1958
-
1959
- compile(`<select ng-model="obj.value">${optionString}</select>`);
1960
- await wait();
1961
- let optionElements = element.querySelectorAll("option");
1962
- expect(optionElements.length).toEqual(4);
1963
- setSelectValue(optionElements, 0);
1964
- await wait();
1965
- optionElements = element.querySelectorAll("option");
1966
- expect(optionElements.length).toEqual(3);
1967
- expect(scope.obj.value).toBe("A");
1968
-
1969
- A.disabled = true;
1970
- optionElements = element.querySelectorAll("option");
1971
- await wait();
1972
- expect(optionElements.length).toEqual(4);
1973
- expect(scope.obj.value).toBe(null);
1974
- expect(element.value).toBe("? object:null ?");
1975
- });
1976
-
1977
- xit("should select a disabled option with $prop when the model is set to the matching value", async () => {
1978
- const A = { name: "A" };
1979
- const B = { name: "B" };
1980
- const C = { name: "C" };
1981
-
1982
- scope.options = [A, B, C];
1983
- scope.obj = {};
1984
-
1985
- let optionString = "";
1986
-
1987
- switch (prop) {
1988
- case "ngValue":
1989
- optionString =
1990
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
1991
- break;
1992
- case "interpolatedValue":
1993
- optionString =
1994
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
1995
- break;
1996
- case "interpolatedText":
1997
- optionString =
1998
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
1999
- break;
2000
- }
2001
-
2002
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2003
- await wait();
2004
- let optionElements = element.querySelectorAll("option");
2005
- expect(optionElements.length).toEqual(4);
2006
- expect(optionElements[0].value).toEqual(`? undefined:undefined ?`);
2007
-
2008
- B.disabled = true;
2009
- optionElements = element.querySelectorAll("option");
2010
- await wait();
2011
- expect(optionElements.length).toEqual(4);
2012
- expect(optionElements[0].value).toEqual(`? undefined:undefined ?`);
2013
-
2014
- scope.obj.value = "B";
2015
- optionElements = element.querySelectorAll("option");
2016
- await wait();
2017
- expect(optionElements.length).toEqual(3);
2018
- expect(scope.obj.value).toBe("B");
2019
- // jQuery returns null for val() when the option is disabled, see
2020
- // https://bugs.jquery.com/ticket/13097
2021
- expect(element.value).toBe(prop === "ngValue" ? "string:B" : "B");
2022
- expect(optionElements[1].selected).toBe(true);
2023
- });
2024
-
2025
- xit("should ignore an option with $prop that becomes enabled and does not match the model", async () => {
2026
- const A = { name: "A" };
2027
- const B = { name: "B" };
2028
- const C = { name: "C" };
2029
-
2030
- scope.options = [A, B, C];
2031
- scope.obj = {};
2032
-
2033
- let optionString = "";
2034
-
2035
- switch (prop) {
2036
- case "ngValue":
2037
- optionString =
2038
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
2039
- break;
2040
- case "interpolatedValue":
2041
- optionString =
2042
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
2043
- break;
2044
- case "interpolatedText":
2045
- optionString =
2046
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
2047
- break;
2048
- }
2049
-
2050
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2051
- await wait();
2052
- let optionElements = element.querySelectorAll("option");
2053
- expect(optionElements.length).toEqual(4);
2054
- setSelectValue(optionElements, 0);
2055
- await wait();
2056
- optionElements = element.querySelectorAll("option");
2057
- expect(optionElements.length).toEqual(3);
2058
- expect(scope.obj.value).toBe("A");
2059
-
2060
- A.disabled = true;
2061
- optionElements = element.querySelectorAll("option");
2062
- await wait();
2063
- expect(optionElements.length).toEqual(4);
2064
- expect(scope.obj.value).toBe(null);
2065
- expect(element.value).toBe("? object:null ?");
2066
-
2067
- A.disabled = false;
2068
- optionElements = element.querySelectorAll("option");
2069
- await wait();
2070
- expect(optionElements.length).toEqual(4);
2071
- expect(scope.obj.value).toBe(null);
2072
- expect(element.value).toBe("? object:null ?");
2073
- });
2074
-
2075
- xit("should select a newly added option with $prop when it matches the current model", async () => {
2076
- const A = { name: "A" };
2077
- const B = { name: "B" };
2078
- const C = { name: "C" };
2079
-
2080
- scope.options = [A, B];
2081
- scope.obj = {
2082
- value: prop === "ngValue" ? C : "C",
2083
- };
2084
-
2085
- let optionString = "";
2086
-
2087
- switch (prop) {
2088
- case "ngValue":
2089
- optionString =
2090
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
2091
- break;
2092
- case "interpolatedValue":
2093
- optionString =
2094
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2095
- break;
2096
- case "interpolatedText":
2097
- optionString =
2098
- '<option ng-repeat="option in options">{{option.name}}</option>';
2099
- break;
2100
- }
2101
-
2102
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2103
- await wait();
2104
- let optionElements = element.querySelectorAll("option");
2105
- expect(optionElements.length).toEqual(3);
2106
-
2107
- scope.options.push(C);
2108
- await wait();
2109
- optionElements = element.querySelectorAll("option");
2110
- expect(optionElements.length).toEqual(3);
2111
- expect(optionElements[2].selected).toBe(true);
2112
- });
2113
-
2114
- xit("should keep selection and model when repeated options with track by are replaced with equal options", async () => {
2115
- const A = { name: "A" };
2116
- const B = { name: "B" };
2117
- const C = { name: "C" };
2118
-
2119
- scope.options = [A, B, C];
2120
- scope.obj = {
2121
- value: "C",
2122
- };
2123
-
2124
- let optionString = "";
2125
-
2126
- switch (prop) {
2127
- case "ngValue":
2128
- optionString =
2129
- '<option ng-repeat="option in options track by option.name" ng-value="option.name">{{$index}}</option>';
2130
- break;
2131
- case "interpolatedValue":
2132
- optionString =
2133
- '<option ng-repeat="option in options track by option.name" value="{{option.name}}">{{$index}}</option>';
2134
- break;
2135
- case "interpolatedText":
2136
- optionString =
2137
- '<option ng-repeat="option in options track by option.name">{{option.name}}</option>';
2138
- break;
2139
- }
2140
-
2141
- compile(`<select ng-model="obj.value">${optionString}</select>`);
2142
- await wait();
2143
- let optionElements = element.querySelectorAll("option");
2144
- expect(optionElements.length).toEqual(3);
2145
-
2146
- scope.obj.value = "C";
2147
- optionElements = element.querySelectorAll("option");
2148
- await wait();
2149
- expect(element.value).toBe(prop === "ngValue" ? "string:C" : "C");
2150
- expect(optionElements.length).toEqual(3);
2151
- expect(optionElements[2].selected).toBe(true);
2152
- expect(scope.obj.value).toBe("C");
2153
-
2154
- scope.options = [{ name: "A" }, { name: "B" }, { name: "C" }];
2155
- optionElements = element.querySelectorAll("option");
2156
- await wait();
2157
- expect(element.value).toBe(prop === "ngValue" ? "string:C" : "C");
2158
- expect(optionElements.length).toEqual(3);
2159
- expect(optionElements[2].selected).toBe(true);
2160
- expect(scope.obj.value).toBe("C");
2161
- });
2162
- });
2163
-
2164
- describe("when multiple", () => {
2165
- ["ngValue", "interpolatedValue", "interpolatedText"].forEach((prop) => {
2166
- xit("should set the model to null when the currently selected option with $prop is removed", async () => {
2167
- const A = { name: "A" };
2168
- const B = { name: "B" };
2169
- const C = { name: "C" };
2170
-
2171
- scope.options = [A, B, C];
2172
- scope.obj = {};
2173
-
2174
- let optionString = "";
2175
-
2176
- switch (prop) {
2177
- case "ngValue":
2178
- optionString =
2179
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
2180
- break;
2181
- case "interpolatedValue":
2182
- optionString =
2183
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2184
- break;
2185
- case "interpolatedText":
2186
- optionString =
2187
- '<option ng-repeat="option in options">{{option.name}}</option>';
2188
- break;
2189
- }
2190
-
2191
- compile(
2192
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2193
- );
2194
- await wait();
2195
- const ngModelCtrl = getController(element, "ngModel");
2196
- const ngModelCtrlSpy = spyOn(
2197
- ngModelCtrl,
2198
- "$setViewValue",
2199
- ).and.callThrough();
2200
-
2201
- let optionElements = element.querySelectorAll("option");
2202
- expect(optionElements.length).toEqual(3);
2203
- await wait();
2204
- optionElements[0][0].selected = true;
2205
- optionElements[2][0].selected = true;
2206
- browserTrigger(element);
2207
- await wait();
2208
- optionElements = element.querySelectorAll("option");
2209
- expect(optionElements.length).toEqual(3);
2210
-
2211
- ngModelCtrlSpy.calls.reset();
2212
- scope.options.shift();
2213
- scope.options.pop();
2214
- await wait();
2215
- optionElements = element.querySelectorAll("option");
2216
- expect(optionElements.length).toEqual(1);
2217
- expect(scope.obj.value).toEqual([]);
2218
-
2219
- // Cover both jQuery 3.x ([]) and 2.x (null) behavior.
2220
- let val = element.value;
2221
- if (val === null) {
2222
- val = [];
2223
- }
2224
- expect(val).toEqual([]);
2225
-
2226
- expect(ngModelCtrlSpy).toHaveBeenCalledTimes(1);
2227
- });
2228
-
2229
- xit("should set the model to null when the currently selected option with $prop changes its value", async () => {
2230
- const A = { name: "A" };
2231
- const B = { name: "B" };
2232
- const C = { name: "C" };
2233
-
2234
- scope.options = [A, B, C];
2235
- scope.obj = {};
2236
-
2237
- let optionString = "";
2238
-
2239
- switch (prop) {
2240
- case "ngValue":
2241
- optionString =
2242
- '<option ng-repeat="option in options" ng-value="option.name">{{$index}}</option>';
2243
- break;
2244
- case "interpolatedValue":
2245
- optionString =
2246
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2247
- break;
2248
- case "interpolatedText":
2249
- optionString =
2250
- '<option ng-repeat="option in options">{{option.name}}</option>';
2251
- break;
2252
- }
2253
-
2254
- compile(
2255
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2256
- );
2257
-
2258
- const ngModelCtrl = getController(element, "ngModel");
2259
- const ngModelCtrlSpy = spyOn(
2260
- ngModelCtrl,
2261
- "$setViewValue",
2262
- ).and.callThrough();
2263
- await wait();
2264
- let optionElements = element.querySelectorAll("option");
2265
- expect(optionElements.length).toEqual(3);
2266
-
2267
- optionElements[0][0].selected = true;
2268
- optionElements[2][0].selected = true;
2269
- browserTrigger(element, "change");
2270
- await wait();
2271
- optionElements = element.querySelectorAll("option");
2272
- expect(optionElements.length).toEqual(3);
2273
- expect(scope.obj.value).toEqual(["A", "C"]);
2274
-
2275
- ngModelCtrlSpy.calls.reset();
2276
- A.name = "X";
2277
- C.name = "Z";
2278
- optionElements = element.querySelectorAll("option");
2279
- await wait();
2280
- expect(optionElements.length).toEqual(3);
2281
- expect(scope.obj.value).toEqual([]);
2282
-
2283
- // Cover both jQuery 3.x ([]) and 2.x (null) behavior.
2284
- let val = element.value;
2285
- if (val === null) {
2286
- val = [];
2287
- }
2288
- expect(val).toEqual([]);
2289
-
2290
- expect(ngModelCtrlSpy).toHaveBeenCalledTimes(1);
2291
- });
2292
-
2293
- xit("should set the model to null when the currently selected option with $prop becomes disabled", async () => {
2294
- const A = { name: "A" };
2295
- const B = { name: "B" };
2296
- const C = { name: "C" };
2297
- const D = { name: "D" };
2298
-
2299
- scope.options = [A, B, C, D];
2300
- scope.obj = {};
2301
-
2302
- let optionString = "";
2303
-
2304
- switch (prop) {
2305
- case "ngValue":
2306
- optionString =
2307
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option.name">{{$index}}</option>';
2308
- break;
2309
- case "interpolatedValue":
2310
- optionString =
2311
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
2312
- break;
2313
- case "interpolatedText":
2314
- optionString =
2315
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
2316
- break;
2317
- }
2318
-
2319
- compile(
2320
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2321
- );
2322
-
2323
- const ngModelCtrl = getController(element, "ngModel");
2324
- const ngModelCtrlSpy = spyOn(
2325
- ngModelCtrl,
2326
- "$setViewValue",
2327
- ).and.callThrough();
2328
- await wait();
2329
- let optionElements = element.querySelectorAll("option");
2330
- expect(optionElements.length).toEqual(4);
2331
-
2332
- optionElements[0][0].selected = true;
2333
- optionElements[2][0].selected = true;
2334
- optionElements.eq(3)[0].selected = true;
2335
- await wait();
2336
- browserTrigger(element, "change");
2337
-
2338
- optionElements = element.querySelectorAll("option");
2339
- expect(optionElements.length).toEqual(4);
2340
- expect(scope.obj.value).toEqual(["A", "C", "D"]);
2341
-
2342
- ngModelCtrlSpy.calls.reset();
2343
- A.disabled = true;
2344
- C.disabled = true;
2345
- await wait();
2346
- optionElements = element.querySelectorAll("option");
2347
- expect(optionElements.length).toEqual(4);
2348
- expect(scope.obj.value).toEqual(["D"]);
2349
- expect(element.value).toEqual(
2350
- prop === "ngValue" ? ["string:D"] : ["D"],
2351
- );
2352
- expect(ngModelCtrlSpy).toHaveBeenCalledTimes(1);
2353
- });
2354
-
2355
- xit("should select disabled options with $prop when the model is set to matching values", async () => {
2356
- const A = { name: "A" };
2357
- const B = { name: "B" };
2358
- const C = { name: "C" };
2359
- const D = { name: "D" };
2360
-
2361
- scope.options = [A, B, C, D];
2362
- scope.obj = {};
2363
-
2364
- let optionString = "";
2365
-
2366
- switch (prop) {
2367
- case "ngValue":
2368
- optionString =
2369
- '<option ng-repeat="option in options" ng-disabled="option.disabled" ng-value="option">{{$index}}</option>';
2370
- break;
2371
- case "interpolatedValue":
2372
- optionString =
2373
- '<option ng-repeat="option in options" ng-disabled="option.disabled" value="{{option.name}}">{{$index}}</option>';
2374
- break;
2375
- case "interpolatedText":
2376
- optionString =
2377
- '<option ng-repeat="option in options" ng-disabled="option.disabled">{{option.name}}</option>';
2378
- break;
2379
- }
2380
-
2381
- compile(
2382
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2383
- );
2384
- await wait();
2385
- let optionElements = element.querySelectorAll("option");
2386
- expect(optionElements.length).toEqual(4);
2387
- expect(element.value).toBe("");
2388
-
2389
- A.disabled = true;
2390
- D.disabled = true;
2391
- await wait();
2392
- optionElements = element.querySelectorAll("option");
2393
- expect(optionElements.length).toEqual(4);
2394
- expect(element.value).toBe("");
2395
-
2396
- scope.obj.value = prop === "ngValue" ? [A, C, D] : ["A", "C", "D"];
2397
- await wait();
2398
- optionElements = element.querySelectorAll("option");
2399
- expect(optionElements.length).toEqual(4);
2400
- expect(optionElements[0][0].selected).toBe(true);
2401
- expect(optionElements[2][0].selected).toBe(true);
2402
- expect(optionElements.eq(3)[0].selected).toBe(true);
2403
- });
2404
-
2405
- xit("should select a newly added option with $prop when it matches the current model", async () => {
2406
- const A = { name: "A" };
2407
- const B = { name: "B" };
2408
- const C = { name: "C" };
2409
-
2410
- scope.options = [A, B];
2411
- scope.obj = {
2412
- value: prop === "ngValue" ? [B, C] : ["B", "C"],
2413
- };
2414
-
2415
- let optionString = "";
2416
-
2417
- switch (prop) {
2418
- case "ngValue":
2419
- optionString =
2420
- '<option ng-repeat="option in options" ng-value="option">{{$index}}</option>';
2421
- break;
2422
- case "interpolatedValue":
2423
- optionString =
2424
- '<option ng-repeat="option in options" value="{{option.name}}">{{$index}}</option>';
2425
- break;
2426
- case "interpolatedText":
2427
- optionString =
2428
- '<option ng-repeat="option in options">{{option.name}}</option>';
2429
- break;
2430
- }
2431
-
2432
- compile(
2433
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2434
- );
2435
- await wait();
2436
- let optionElements = element.querySelectorAll("option");
2437
- expect(optionElements.length).toEqual(2);
2438
- expect(optionElements[1].selected).toBe(true);
2439
-
2440
- scope.options.push(C);
2441
- await wait();
2442
- optionElements = element.querySelectorAll("option");
2443
-
2444
- expect(optionElements.length).toEqual(3);
2445
- expect(optionElements[1].selected).toBe(true);
2446
- expect(optionElements[2].selected).toBe(true);
2447
- });
2448
-
2449
- xit("should keep selection and model when a repeated options with track by are replaced with equal options", async () => {
2450
- const A = { name: "A" };
2451
- const B = { name: "B" };
2452
- const C = { name: "C" };
2453
-
2454
- scope.options = [A, B, C];
2455
- scope.obj = {
2456
- value: "C",
2457
- };
2458
-
2459
- let optionString = "";
2460
-
2461
- switch (prop) {
2462
- case "ngValue":
2463
- optionString =
2464
- '<option ng-repeat="option in options track by option.name" ng-value="option.name">{{$index}}</option>';
2465
- break;
2466
- case "interpolatedValue":
2467
- optionString =
2468
- '<option ng-repeat="option in options track by option.name" value="{{option.name}}">{{$index}}</option>';
2469
- break;
2470
- case "interpolatedText":
2471
- optionString =
2472
- '<option ng-repeat="option in options track by option.name">{{option.name}}</option>';
2473
- break;
2474
- }
2475
-
2476
- compile(
2477
- `<select ng-model="obj.value" multiple>${optionString}</select>`,
2478
- );
2479
- await wait();
2480
- let optionElements = element.querySelectorAll("option");
2481
- expect(optionElements.length).toEqual(3);
2482
-
2483
- scope.obj.value = ["B", "C"];
2484
- await wait();
2485
- optionElements = element.querySelectorAll("option");
2486
-
2487
- expect(optionElements.length).toEqual(3);
2488
- expect(optionElements[1].selected).toBe(true);
2489
- expect(optionElements[2].selected).toBe(true);
2490
- expect(scope.obj.value).toEqual(["B", "C"]);
2491
-
2492
- scope.options = [{ name: "A" }, { name: "B" }, { name: "C" }];
2493
- await wait();
2494
- optionElements = element.querySelectorAll("option");
2495
-
2496
- expect(optionElements.length).toEqual(3);
2497
- expect(optionElements[1].selected).toBe(true);
2498
- expect(optionElements[2].selected).toBe(true);
2499
- expect(scope.obj.value).toEqual(["B", "C"]);
2500
- });
2501
- });
2502
- });
2503
-
2504
- it("should keep the ngModel value when the selected option is recreated by ngRepeat", async () => {
2505
- scope.options = [{ name: "A" }, { name: "B" }, { name: "C" }];
2506
- scope.obj = {
2507
- value: "B",
2508
- };
2509
-
2510
- compile(
2511
- '<select ng-model="obj.value">' +
2512
- '<option ng-repeat="option in options" value="{{option.name}}">{{option.name}}</option>' +
2513
- "</select>",
2514
- );
2515
- await wait();
2516
- let optionElements = element.querySelectorAll("option");
2517
- expect(optionElements.length).toEqual(3);
2518
- expect(optionElements[0].value).toBe("A");
2519
- expect(optionElements[1].selected).toBeTrue();
2520
- expect(scope.obj.value).toBe("B");
2521
-
2522
- scope.$apply(() => {
2523
- // Only when new objects are used, ngRepeat re-creates the element from scratch
2524
- scope.options = [{ name: "B" }, { name: "C" }, { name: "D" }];
2525
- });
2526
- await wait();
2527
- const previouslySelectedOptionElement = optionElements[1];
2528
- optionElements = element.querySelectorAll("option");
2529
-
2530
- expect(optionElements.length).toEqual(3);
2531
- expect(optionElements[0].value).toBe("B");
2532
- expect(optionElements[0].selected).toBeTrue();
2533
- expect(scope.obj.value).toBe("B");
2534
- // Ensure the assumption that the element is re-created is true
2535
- expect(previouslySelectedOptionElement).not.toBe(optionElements[0]);
2536
- });
2537
-
2538
- xit("should validate when the options change", async () => {
2539
- scope.values = ["A", "B"];
2540
- scope.selection = "A";
2541
-
2542
- compile(
2543
- '<select ng-model="selection" required>' +
2544
- '<option value="">--select--</option>' +
2545
- '<option ng-repeat="option in values" value="{{option}}">{{option}}</option>' +
2546
- "</select>",
2547
- );
2548
- await wait();
2549
- expect(element.value).toBe("A");
2550
- expect(element.classList.contains("ng-valid")).toBeTrue();
2551
- expect(ngModelCtrl.$error.required).toBeFalsy();
2552
-
2553
- scope.$apply(() => {
2554
- // Only when new objects are used, ngRepeat re-creates the element from scratch
2555
- scope.values = ["B", "C"];
2556
- });
2557
- await wait();
2558
- expect(element.value).toBe("");
2559
- expect(element.classList.contains("ng-invalid")).toBeTrue();
2560
- expect(ngModelCtrl.$error.required).toBeTruthy();
2561
- // ngModel sets undefined for invalid values
2562
- expect(scope.selection).toBeUndefined();
2563
- });
2564
- });
2565
- });
2566
- });