@angular-wave/angular.ts 0.9.4 → 0.9.5
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.
- package/@types/index.d.ts +1 -84
- package/{src/index.ts → @types/namespace.d.ts} +4 -24
- package/@types/router/template-factory.d.ts +2 -2
- package/dist/angular-ts.esm.js +3 -3
- package/dist/angular-ts.umd.js +3 -3
- package/dist/angular-ts.umd.min.js +1 -1
- package/package.json +8 -1
- package/.github/workflows/ci.yml +0 -104
- package/.github/workflows/gh-pages.yml +0 -75
- package/.husky/pre-commit +0 -5
- package/.prettierignore +0 -9
- package/CHANGELOG.md +0 -17667
- package/CODE_OF_CONDUCT.md +0 -3
- package/CONTRIBUTING.md +0 -247
- package/DEVELOPERS.md +0 -499
- package/Makefile +0 -60
- package/RELEASE.md +0 -86
- package/TRIAGING.md +0 -127
- package/docs/.cspell.yml +0 -8
- package/docs/.github/dependabot.yml +0 -14
- package/docs/.nvmrc +0 -1
- package/docs/CONTRIBUTING.md +0 -28
- package/docs/Dockerfile +0 -4
- package/docs/LICENSE +0 -201
- package/docs/README.md +0 -217
- package/docs/assets/icons/logo.svg +0 -1
- package/docs/assets/scss/_variables_project.scss +0 -12
- package/docs/assets/scss/_variables_project_after_bs.scss +0 -8
- package/docs/assets/scss/index.scss +0 -48
- package/docs/config.yaml +0 -15
- package/docs/content/_index.md +0 -28
- package/docs/content/docs/_index.md +0 -61
- package/docs/content/docs/directive/_index.md +0 -4
- package/docs/content/docs/directive/app.md +0 -11
- package/docs/content/docs/directive/aria.md +0 -0
- package/docs/content/docs/directive/bind.md +0 -72
- package/docs/content/docs/directive/blur.md +0 -38
- package/docs/content/docs/directive/channel.md +0 -37
- package/docs/content/docs/directive/class-even.md +0 -47
- package/docs/content/docs/directive/class-odd.md +0 -48
- package/docs/content/docs/directive/class.md +0 -64
- package/docs/content/docs/directive/click.md +0 -41
- package/docs/content/docs/directive/cloak.md +0 -74
- package/docs/content/docs/directive/copy.md +0 -38
- package/docs/content/docs/directive/cut.md +0 -40
- package/docs/content/docs/directive/dblclick.md +0 -41
- package/docs/content/docs/directive/focus.md +0 -38
- package/docs/content/docs/directive/get.md +0 -203
- package/docs/content/docs/directive/include.md +0 -7
- package/docs/content/docs/directive/keydown.md +0 -38
- package/docs/content/docs/directive/keyup.md +0 -38
- package/docs/content/docs/directive/load.md +0 -43
- package/docs/content/docs/directive/mousedown.md +0 -38
- package/docs/content/docs/directive/mouseenter.md +0 -38
- package/docs/content/docs/directive/mouseleave.md +0 -38
- package/docs/content/docs/directive/mousemove.md +0 -38
- package/docs/content/docs/directive/mouseout.md +0 -38
- package/docs/content/docs/directive/mouseover.md +0 -38
- package/docs/content/docs/directive/mouseup.md +0 -38
- package/docs/content/docs/directive/non-bindable.md +0 -28
- package/docs/content/docs/filter/_index.md +0 -4
- package/docs/content/docs/filter/filter.md +0 -78
- package/docs/content/docs/filter/json.md +0 -19
- package/docs/content/docs/filter/limit-to.md +0 -30
- package/docs/content/docs/filter/order-by.md +0 -123
- package/docs/content/docs/provider/_index.md +0 -4
- package/docs/content/docs/provider/eventBusProvider.md +0 -35
- package/docs/content/docs/provider/locationProvider.md +0 -26
- package/docs/content/docs/provider/logProvider.md +0 -59
- package/docs/content/docs/provider/sceProvider.md +0 -194
- package/docs/content/docs/provider/templateCacheProvider.md +0 -100
- package/docs/content/docs/provider/templateRequestProvider.md +0 -5
- package/docs/content/docs/service/_index.md +0 -4
- package/docs/content/docs/service/compile.md +0 -5
- package/docs/content/docs/service/controller.md +0 -5
- package/docs/content/docs/service/eventBus.md +0 -56
- package/docs/content/docs/service/http.md +0 -161
- package/docs/content/docs/service/interpolation.md +0 -5
- package/docs/content/docs/service/location.md +0 -57
- package/docs/content/docs/service/log.md +0 -113
- package/docs/content/docs/service/parse.md +0 -5
- package/docs/content/docs/service/rootElement.md +0 -5
- package/docs/content/docs/service/rootScope.md +0 -5
- package/docs/content/docs/service/sce.md +0 -194
- package/docs/content/docs/service/templateCache.md +0 -64
- package/docs/content/docs/service/templateRequest.md +0 -5
- package/docs/content/docs/service/url.md +0 -5
- package/docs/content/docs/values/_index.md +0 -4
- package/docs/content/docs/values/document.md +0 -29
- package/docs/content/docs/values/window.md +0 -29
- package/docs/docker-compose.yaml +0 -12
- package/docs/docsy.work +0 -5
- package/docs/docsy.work.sum +0 -0
- package/docs/go.mod +0 -5
- package/docs/go.sum +0 -6
- package/docs/hugo-disabled.toml +0 -220
- package/docs/hugo.yaml +0 -200
- package/docs/layouts/404.html +0 -13
- package/docs/layouts/_markup/render-heading.html +0 -1
- package/docs/layouts/partials/hooks/head-end.html +0 -3
- package/docs/layouts/shortcodes/showcss.html +0 -2
- package/docs/layouts/shortcodes/showhtml.html +0 -2
- package/docs/layouts/shortcodes/showjs.html +0 -2
- package/docs/layouts/shortcodes/showraw.html +0 -1
- package/docs/layouts/shortcodes/version.html +0 -1
- package/docs/package-lock.json +0 -2293
- package/docs/package.json +0 -53
- package/docs/static/examples/counter/counter-test.html +0 -13
- package/docs/static/examples/counter/counter.html +0 -5
- package/docs/static/examples/counter/counter.test.js +0 -28
- package/docs/static/examples/document/document.html +0 -3
- package/docs/static/examples/eventbus/eventbus-test.html +0 -15
- package/docs/static/examples/eventbus/eventbus.html +0 -13
- package/docs/static/examples/eventbus/eventbus.js +0 -15
- package/docs/static/examples/eventbus/eventbus.test.js +0 -19
- package/docs/static/examples/i18n/i18n.html +0 -77
- package/docs/static/examples/ng-bind/ng-bind.html +0 -9
- package/docs/static/examples/ng-blur/ng-blur.html +0 -9
- package/docs/static/examples/ng-channel/ng-channel-test.html +0 -17
- package/docs/static/examples/ng-channel/ng-channel.html +0 -24
- package/docs/static/examples/ng-channel/ng-channel.test.js +0 -31
- package/docs/static/examples/ng-class/ng-class.html +0 -71
- package/docs/static/examples/ng-class-even/ng-class-even.html +0 -8
- package/docs/static/examples/ng-class-odd/ng-class-odd.html +0 -8
- package/docs/static/examples/ng-click/ng-click.html +0 -6
- package/docs/static/examples/ng-copy/ng-copy.html +0 -6
- package/docs/static/examples/ng-cut/ng-cut.html +0 -6
- package/docs/static/examples/ng-dblclick/ng-dblclick.html +0 -10
- package/docs/static/examples/ng-focus/ng-focus.html +0 -9
- package/docs/static/examples/ng-keydown/ng-keydown.html +0 -9
- package/docs/static/examples/ng-keyup/ng-keyup.html +0 -9
- package/docs/static/examples/ng-load/ng-load.html +0 -8
- package/docs/static/examples/ng-mousedown/ng-mousedown.html +0 -6
- package/docs/static/examples/ng-mouseenter/ng-mouseenter.html +0 -4
- package/docs/static/examples/ng-mouseleave/ng-mouseleave.html +0 -4
- package/docs/static/examples/ng-mousemove/ng-mousemove.html +0 -4
- package/docs/static/examples/ng-mouseout/ng-mouseout.html +0 -4
- package/docs/static/examples/ng-mouseover/ng-mouseover.html +0 -4
- package/docs/static/examples/ng-mouseup/ng-mouseup.html +0 -4
- package/docs/static/examples/ng-non-bindable/ng-non-bindable-test.html +0 -13
- package/docs/static/examples/ng-non-bindable/ng-non-bindable.html +0 -3
- package/docs/static/examples/ng-non-bindable/ng-non-bindable.test.js +0 -11
- package/docs/static/examples/window/window.html +0 -4
- package/docs/static/typedoc/.nojekyll +0 -1
- package/docs/static/typedoc/assets/hierarchy.js +0 -1
- package/docs/static/typedoc/assets/highlight.css +0 -29
- package/docs/static/typedoc/assets/icons.js +0 -18
- package/docs/static/typedoc/assets/icons.svg +0 -1
- package/docs/static/typedoc/assets/main.js +0 -60
- package/docs/static/typedoc/assets/navigation.js +0 -1
- package/docs/static/typedoc/assets/search.js +0 -1
- package/docs/static/typedoc/assets/style.css +0 -1633
- package/docs/static/typedoc/classes/Location.html +0 -55
- package/docs/static/typedoc/classes/LocationProvider.html +0 -20
- package/docs/static/typedoc/classes/LogProvider.html +0 -6
- package/docs/static/typedoc/classes/PubSub.html +0 -71
- package/docs/static/typedoc/classes/PubSubProvider.html +0 -4
- package/docs/static/typedoc/classes/TemplateCacheProvider.html +0 -5
- package/docs/static/typedoc/hierarchy.html +0 -1
- package/docs/static/typedoc/index.html +0 -1
- package/docs/static/typedoc/interfaces/DefaultPorts.html +0 -5
- package/docs/static/typedoc/interfaces/Html5Mode.html +0 -23
- package/docs/static/typedoc/interfaces/HttpHeadersGetter.html +0 -1
- package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +0 -31
- package/docs/static/typedoc/interfaces/HttpRequestConfigHeaders.html +0 -6
- package/docs/static/typedoc/interfaces/HttpRequestTransformer.html +0 -1
- package/docs/static/typedoc/interfaces/HttpResponse.html +0 -7
- package/docs/static/typedoc/interfaces/HttpResponseTransformer.html +0 -1
- package/docs/static/typedoc/interfaces/HttpService.html +0 -38
- package/docs/static/typedoc/interfaces/LogService.html +0 -12
- package/docs/static/typedoc/interfaces/RequestConfig.html +0 -48
- package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +0 -38
- package/docs/static/typedoc/interfaces/ServiceProvider.html +0 -5
- package/docs/static/typedoc/interfaces/UrlParts.html +0 -9
- package/docs/static/typedoc/types/HttpParamSerializer.html +0 -2
- package/docs/static/typedoc/types/HttpParams.html +0 -2
- package/docs/static/typedoc/types/HttpPromise.html +0 -1
- package/docs/static/typedoc/types/HttpResponseStatus.html +0 -1
- package/docs/static/typedoc/types/LogCall.html +0 -2
- package/docs/static/typedoc/types/LogServiceFactory.html +0 -2
- package/docs/static/typedoc/types/UrlChangeListener.html +0 -5
- package/docs/static/typedoc/variables/EventBus.html +0 -1
- package/docs/static/version.js +0 -13
- package/docs/test-results/.last-run.json +0 -4
- package/docs/test-results/static-examples-counter-counter-counter-example/error-context.md +0 -50
- package/eslint.config.js +0 -26
- package/images/android-chrome-192x192.png +0 -0
- package/images/android-chrome-512x512.png +0 -0
- package/images/apple-touch-icon.png +0 -0
- package/images/favicon-16x16.png +0 -0
- package/images/favicon-32x32.png +0 -0
- package/images/favicon.ico +0 -0
- package/images/site.webmanifest +0 -19
- package/index.html +0 -86
- package/legacy.d.ts +0 -1678
- package/playwright.config.ts +0 -81
- package/public/jasmine/boot0.js +0 -66
- package/public/jasmine/boot1.js +0 -134
- package/public/jasmine/jasmine-html.js +0 -970
- package/public/jasmine/jasmine.css +0 -323
- package/public/jasmine/jasmine.js +0 -11406
- package/public/public/README.md +0 -1
- package/public/public/circle.html +0 -1
- package/public/public/jasmine-helper.css +0 -9
- package/public/public/my_child_directive.html +0 -1
- package/public/public/my_directive.html +0 -1
- package/public/public/my_other_directive.html +0 -1
- package/public/public/test.html +0 -1
- package/rollup.config.js +0 -51
- package/src/angular.js +0 -286
- package/src/angular.spec.js +0 -1191
- package/src/animations/animate-cache.js +0 -80
- package/src/animations/animate-children-directive.js +0 -32
- package/src/animations/animate-children-directive.md +0 -80
- package/src/animations/animate-css-driver.js +0 -284
- package/src/animations/animate-css.html +0 -58
- package/src/animations/animate-css.js +0 -915
- package/src/animations/animate-css.md +0 -263
- package/src/animations/animate-js-driver.js +0 -60
- package/src/animations/animate-js.html +0 -47
- package/src/animations/animate-js.js +0 -371
- package/src/animations/animate-queue.js +0 -859
- package/src/animations/animate-runner.js +0 -193
- package/src/animations/animate-swap.js +0 -33
- package/src/animations/animate-swap.md +0 -88
- package/src/animations/animate.html +0 -19
- package/src/animations/animate.js +0 -546
- package/src/animations/animate.md +0 -933
- package/src/animations/animate.spec.js +0 -490
- package/src/animations/animation.js +0 -519
- package/src/animations/animations.test.js +0 -10
- package/src/animations/interface.ts +0 -19
- package/src/animations/raf-scheduler.html +0 -19
- package/src/animations/raf-scheduler.js +0 -92
- package/src/animations/raf-scheduler.spec.js +0 -98
- package/src/animations/shared.js +0 -341
- package/src/binding.html +0 -19
- package/src/binding.spec.js +0 -474
- package/src/binding.test.js +0 -10
- package/src/core/compile/attributes.js +0 -337
- package/src/core/compile/compile.html +0 -19
- package/src/core/compile/compile.js +0 -3271
- package/src/core/compile/compile.md +0 -1128
- package/src/core/compile/compile.spec.js +0 -15574
- package/src/core/compile/compile.test.js +0 -12
- package/src/core/controller/controller.html +0 -22
- package/src/core/controller/controller.js +0 -193
- package/src/core/controller/controller.spec.js +0 -334
- package/src/core/controller/controller.test.js +0 -12
- package/src/core/controller/interface.ts +0 -6
- package/src/core/core.html +0 -20
- package/src/core/core.test.js +0 -12
- package/src/core/di/injector.html +0 -19
- package/src/core/di/injector.js +0 -307
- package/src/core/di/injector.md +0 -740
- package/src/core/di/injector.spec.js +0 -2310
- package/src/core/di/injector.test.js +0 -12
- package/src/core/di/internal-injector.js +0 -286
- package/src/core/di/ng-module.html +0 -19
- package/src/core/di/ng-module.js +0 -229
- package/src/core/di/ng-module.spec.js +0 -263
- package/src/core/di/ng-module.test.js +0 -12
- package/src/core/filter/filter.html +0 -19
- package/src/core/filter/filter.js +0 -55
- package/src/core/filter/filter.md +0 -132
- package/src/core/filter/filter.spec.js +0 -149
- package/src/core/filter/filter.test.js +0 -12
- package/src/core/interpolate/interface.ts +0 -14
- package/src/core/interpolate/interpolate.html +0 -22
- package/src/core/interpolate/interpolate.js +0 -410
- package/src/core/interpolate/interpolate.spec.js +0 -601
- package/src/core/interpolate/interpolate.test.js +0 -12
- package/src/core/parse/ast/ast-node.ts +0 -81
- package/src/core/parse/ast/ast.html +0 -19
- package/src/core/parse/ast/ast.js +0 -574
- package/src/core/parse/ast/ast.spec.js +0 -1453
- package/src/core/parse/ast/ast.test.js +0 -10
- package/src/core/parse/ast-type.js +0 -23
- package/src/core/parse/interface.ts +0 -84
- package/src/core/parse/interpreter.js +0 -915
- package/src/core/parse/lexer/lexer.html +0 -19
- package/src/core/parse/lexer/lexer.js +0 -338
- package/src/core/parse/lexer/lexer.spec.js +0 -303
- package/src/core/parse/lexer/lexer.test.js +0 -10
- package/src/core/parse/lexer/token.ts +0 -22
- package/src/core/parse/parse.html +0 -19
- package/src/core/parse/parse.js +0 -337
- package/src/core/parse/parse.md +0 -57
- package/src/core/parse/parse.spec.js +0 -2107
- package/src/core/parse/parse.test.js +0 -10
- package/src/core/parse/parser/parser.html +0 -19
- package/src/core/parse/parser/parser.js +0 -64
- package/src/core/parse/parser/parser.spec.js +0 -8
- package/src/core/parse/parser/parser.test.js +0 -10
- package/src/core/prop.spec.js +0 -775
- package/src/core/root-element.spec.js +0 -14
- package/src/core/sanitize/interface.ts +0 -10
- package/src/core/sanitize/sanitize-uri.js +0 -75
- package/src/core/sanitize/sanitize-uri.spec.js +0 -249
- package/src/core/sanitize/sanitize-uri.test.js +0 -12
- package/src/core/sanitize/sanitize.html +0 -22
- package/src/core/scope/scope.html +0 -19
- package/src/core/scope/scope.js +0 -1252
- package/src/core/scope/scope.spec.js +0 -3000
- package/src/core/scope/scope.test.js +0 -12
- package/src/directive/aria/aria.html +0 -19
- package/src/directive/aria/aria.js +0 -382
- package/src/directive/aria/aria.md +0 -145
- package/src/directive/aria/aria.spec.js +0 -1241
- package/src/directive/aria/aria.test.js +0 -12
- package/src/directive/attrs/attrs.html +0 -19
- package/src/directive/attrs/attrs.js +0 -106
- package/src/directive/attrs/attrs.md +0 -224
- package/src/directive/attrs/attrs.spec.js +0 -71
- package/src/directive/attrs/attrs.test.js +0 -12
- package/src/directive/attrs/boolean.html +0 -19
- package/src/directive/attrs/boolean.spec.js +0 -137
- package/src/directive/attrs/boolean.test.js +0 -12
- package/src/directive/attrs/element-style.html +0 -22
- package/src/directive/attrs/element-style.spec.js +0 -85
- package/src/directive/attrs/element-style.test.js +0 -12
- package/src/directive/attrs/src.html +0 -19
- package/src/directive/attrs/src.spec.js +0 -163
- package/src/directive/attrs/src.test.js +0 -12
- package/src/directive/bind/bind-html.spec.js +0 -36
- package/src/directive/bind/bind.html +0 -20
- package/src/directive/bind/bind.js +0 -78
- package/src/directive/bind/bind.md +0 -142
- package/src/directive/bind/bind.spec.js +0 -314
- package/src/directive/bind/bind.test.js +0 -12
- package/src/directive/channel/channel.html +0 -19
- package/src/directive/channel/channel.js +0 -30
- package/src/directive/channel/channel.spec.js +0 -67
- package/src/directive/channel/channel.test.js +0 -10
- package/src/directive/class/class-test.html +0 -23
- package/src/directive/class/class.html +0 -19
- package/src/directive/class/class.js +0 -184
- package/src/directive/class/class.spec.js +0 -704
- package/src/directive/class/class.test.js +0 -12
- package/src/directive/cloak/cloak.html +0 -19
- package/src/directive/cloak/cloak.js +0 -11
- package/src/directive/cloak/cloak.spec.js +0 -44
- package/src/directive/cloak/cloak.test.js +0 -12
- package/src/directive/controller/controller.html +0 -22
- package/src/directive/controller/controller.js +0 -11
- package/src/directive/controller/controller.md +0 -46
- package/src/directive/controller/controller.spec.js +0 -175
- package/src/directive/controller/controller.test.js +0 -12
- package/src/directive/events/click.spec.js +0 -35
- package/src/directive/events/event.spec.js +0 -267
- package/src/directive/events/events-test.html +0 -36
- package/src/directive/events/events.html +0 -20
- package/src/directive/events/events.js +0 -65
- package/src/directive/events/events.md +0 -125
- package/src/directive/events/events.test.js +0 -12
- package/src/directive/form/form.html +0 -19
- package/src/directive/form/form.js +0 -669
- package/src/directive/form/form.spec.js +0 -1515
- package/src/directive/form/form.test.js +0 -12
- package/src/directive/http/delete.spec.js +0 -23
- package/src/directive/http/form-router-test.html +0 -44
- package/src/directive/http/form-test.html +0 -18
- package/src/directive/http/get.spec.js +0 -488
- package/src/directive/http/http.html +0 -22
- package/src/directive/http/http.js +0 -342
- package/src/directive/http/http.test.js +0 -12
- package/src/directive/http/interface.ts +0 -36
- package/src/directive/http/post-example.html +0 -30
- package/src/directive/http/post.spec.js +0 -521
- package/src/directive/http/put.spec.js +0 -23
- package/src/directive/if/if-animate-css.html +0 -57
- package/src/directive/if/if-animate-svg.html +0 -25
- package/src/directive/if/if.html +0 -19
- package/src/directive/if/if.js +0 -72
- package/src/directive/if/if.md +0 -76
- package/src/directive/if/if.spec.js +0 -293
- package/src/directive/if/if.test.js +0 -114
- package/src/directive/include/include.html +0 -19
- package/src/directive/include/include.js +0 -151
- package/src/directive/include/include.md +0 -87
- package/src/directive/include/include.spec.js +0 -734
- package/src/directive/include/include.test.js +0 -12
- package/src/directive/init/init.html +0 -19
- package/src/directive/init/init.js +0 -22
- package/src/directive/init/init.md +0 -41
- package/src/directive/init/init.spec.js +0 -68
- package/src/directive/init/init.test.js +0 -12
- package/src/directive/inject/inject.html +0 -19
- package/src/directive/inject/inject.js +0 -35
- package/src/directive/inject/inject.spec.js +0 -108
- package/src/directive/inject/inject.test.js +0 -12
- package/src/directive/input/input-example.html +0 -15
- package/src/directive/input/input.html +0 -19
- package/src/directive/input/input.js +0 -1078
- package/src/directive/input/input.md +0 -706
- package/src/directive/input/input.spec.js +0 -3700
- package/src/directive/input/input.test.js +0 -12
- package/src/directive/messages/messages.html +0 -22
- package/src/directive/messages/messages.js +0 -349
- package/src/directive/messages/messages.md +0 -543
- package/src/directive/messages/messages.spec.js +0 -1083
- package/src/directive/messages/messages.test.js +0 -12
- package/src/directive/model/change.md +0 -25
- package/src/directive/model/model.html +0 -19
- package/src/directive/model/model.js +0 -1170
- package/src/directive/model/model.spec.js +0 -1976
- package/src/directive/model/model.test.js +0 -12
- package/src/directive/model-options/model-option.test.js +0 -12
- package/src/directive/model-options/model-options.html +0 -22
- package/src/directive/model-options/model-options.js +0 -142
- package/src/directive/model-options/model-options.md +0 -407
- package/src/directive/model-options/model-options.spec.js +0 -1022
- package/src/directive/non-bindable/non-bindable.html +0 -22
- package/src/directive/non-bindable/non-bindable.js +0 -9
- package/src/directive/non-bindable/non-bindable.spec.js +0 -59
- package/src/directive/non-bindable/non-bindable.test.js +0 -12
- package/src/directive/observe/observe-demo.html +0 -184
- package/src/directive/observe/observe.html +0 -19
- package/src/directive/observe/observe.js +0 -41
- package/src/directive/observe/observe.spec.js +0 -106
- package/src/directive/observe/observe.test.js +0 -10
- package/src/directive/on/on.html +0 -19
- package/src/directive/on/on.spec.js +0 -215
- package/src/directive/on/on.test.js +0 -12
- package/src/directive/options/options-example.html +0 -17
- package/src/directive/options/options.html +0 -22
- package/src/directive/options/options.js +0 -542
- package/src/directive/options/options.md +0 -179
- package/src/directive/options/options.spec.js +0 -3554
- package/src/directive/options/options.test.js +0 -12
- package/src/directive/ref/href.html +0 -19
- package/src/directive/ref/href.spec.js +0 -141
- package/src/directive/ref/href.test.js +0 -19
- package/src/directive/ref/ref.html +0 -19
- package/src/directive/ref/ref.js +0 -89
- package/src/directive/ref/ref.spec.js +0 -546
- package/src/directive/repeat/repeat.html +0 -19
- package/src/directive/repeat/repeat.js +0 -333
- package/src/directive/repeat/repeat.md +0 -330
- package/src/directive/repeat/repeat.spec.js +0 -1209
- package/src/directive/repeat/repeat.test.js +0 -12
- package/src/directive/script/script.html +0 -19
- package/src/directive/script/script.js +0 -17
- package/src/directive/script/script.md +0 -11
- package/src/directive/script/script.spec.js +0 -47
- package/src/directive/script/script.test.js +0 -12
- package/src/directive/select/select.html +0 -19
- package/src/directive/select/select.js +0 -594
- package/src/directive/select/select.md +0 -74
- package/src/directive/select/select.spec.js +0 -2566
- package/src/directive/select/select.test.js +0 -12
- package/src/directive/setter/setter.html +0 -19
- package/src/directive/setter/setter.js +0 -59
- package/src/directive/setter/setter.spec.js +0 -100
- package/src/directive/setter/setter.test.js +0 -12
- package/src/directive/show-hide/show-hide.html +0 -22
- package/src/directive/show-hide/show-hide.js +0 -65
- package/src/directive/show-hide/show-hide.md +0 -255
- package/src/directive/show-hide/show-hide.spec.js +0 -268
- package/src/directive/show-hide/show-hide.test.js +0 -12
- package/src/directive/style/style.html +0 -19
- package/src/directive/style/style.js +0 -27
- package/src/directive/style/style.md +0 -23
- package/src/directive/style/style.spec.js +0 -183
- package/src/directive/style/style.test.js +0 -12
- package/src/directive/switch/switch.html +0 -19
- package/src/directive/switch/switch.js +0 -133
- package/src/directive/switch/switch.md +0 -66
- package/src/directive/switch/switch.spec.js +0 -509
- package/src/directive/switch/switch.test.js +0 -12
- package/src/directive/transclude/transclude.js +0 -122
- package/src/directive/validators/validators.html +0 -22
- package/src/directive/validators/validators.js +0 -346
- package/src/directive/validators/validators.spec.js +0 -740
- package/src/directive/validators/validators.test.js +0 -12
- package/src/filters/filter.js +0 -213
- package/src/filters/filter.spec.js +0 -719
- package/src/filters/filters.html +0 -22
- package/src/filters/filters.js +0 -239
- package/src/filters/filters.spec.js +0 -36
- package/src/filters/filters.test.js +0 -12
- package/src/filters/interface.ts +0 -9
- package/src/filters/limit-to.js +0 -55
- package/src/filters/limit-to.spec.js +0 -252
- package/src/filters/order-by.js +0 -181
- package/src/filters/order-by.spec.js +0 -883
- package/src/index.js +0 -6
- package/src/index.spec.js +0 -11
- package/src/injection-tokens.js +0 -81
- package/src/interface.ts +0 -430
- package/src/ng.js +0 -291
- package/src/ng.spec.js +0 -45
- package/src/router/common/trace.js +0 -240
- package/src/router/directives/component-example.html +0 -37
- package/src/router/directives/state-directives.html +0 -22
- package/src/router/directives/state-directives.js +0 -393
- package/src/router/directives/state-directives.md +0 -435
- package/src/router/directives/state-directives.spec.js +0 -1091
- package/src/router/directives/state-directives.test.js +0 -10
- package/src/router/directives/view-directive.js +0 -489
- package/src/router/directives/view-directive.spec.js +0 -1921
- package/src/router/directives/view-directive.test.js +0 -10
- package/src/router/directives/view-directives.html +0 -22
- package/src/router/glob/glob.html +0 -19
- package/src/router/glob/glob.js +0 -102
- package/src/router/glob/glob.spec.js +0 -108
- package/src/router/glob/glob.test.js +0 -12
- package/src/router/hooks/core-resolvables.js +0 -38
- package/src/router/hooks/ignored-transition.js +0 -25
- package/src/router/hooks/invalid-transition.js +0 -14
- package/src/router/hooks/lazy-load.js +0 -104
- package/src/router/hooks/on-enter-exit-retain.js +0 -55
- package/src/router/hooks/redirect-to.js +0 -38
- package/src/router/hooks/resolve.js +0 -57
- package/src/router/hooks/update-globals.js +0 -34
- package/src/router/hooks/url.js +0 -34
- package/src/router/hooks/views.js +0 -41
- package/src/router/params/interface.ts +0 -626
- package/src/router/params/param-factory.js +0 -23
- package/src/router/params/param-type.js +0 -133
- package/src/router/params/param-types.js +0 -153
- package/src/router/params/param.js +0 -243
- package/src/router/params/state-params.js +0 -36
- package/src/router/path/path-node.js +0 -78
- package/src/router/path/path-utils.js +0 -207
- package/src/router/resolve/interface.ts +0 -208
- package/src/router/resolve/resolvable.js +0 -123
- package/src/router/resolve/resolve-context.js +0 -190
- package/src/router/router-test-hashbang.html +0 -45
- package/src/router/router-test.html +0 -41
- package/src/router/router.html +0 -22
- package/src/router/router.js +0 -54
- package/src/router/router.test.js +0 -12
- package/src/router/services.spec.js +0 -52
- package/src/router/state/interface.ts +0 -1007
- package/src/router/state/state-builder.js +0 -376
- package/src/router/state/state-builder.spec.js +0 -86
- package/src/router/state/state-matcher.js +0 -64
- package/src/router/state/state-object.js +0 -118
- package/src/router/state/state-queue-manager.js +0 -95
- package/src/router/state/state-registry.js +0 -262
- package/src/router/state/state-service.js +0 -687
- package/src/router/state/state.html +0 -23
- package/src/router/state/state.spec.js +0 -1002
- package/src/router/state/state.test.js +0 -12
- package/src/router/state/target-state.js +0 -162
- package/src/router/state/views.js +0 -195
- package/src/router/state-filter.spec.js +0 -139
- package/src/router/state-filters.js +0 -46
- package/src/router/template-factory.html +0 -19
- package/src/router/template-factory.js +0 -249
- package/src/router/template-factory.spec.js +0 -146
- package/src/router/template-factory.test.js +0 -12
- package/src/router/transition/hook-builder.js +0 -137
- package/src/router/transition/hook-registry.js +0 -181
- package/src/router/transition/interface.js +0 -18
- package/src/router/transition/interface.ts +0 -922
- package/src/router/transition/reject-factory.js +0 -122
- package/src/router/transition/transition-event-type.js +0 -26
- package/src/router/transition/transition-hook.js +0 -199
- package/src/router/transition/transition-service.js +0 -297
- package/src/router/transition/transition.js +0 -653
- package/src/router/url/url-config.js +0 -155
- package/src/router/url/url-matcher.js +0 -532
- package/src/router/url/url-rule.js +0 -231
- package/src/router/url/url-rules.js +0 -350
- package/src/router/url/url-service.js +0 -446
- package/src/router/url/url-service.spec.js +0 -1288
- package/src/router/url/url.html +0 -19
- package/src/router/url/url.test.js +0 -12
- package/src/router/view/interface.ts +0 -51
- package/src/router/view/view.html +0 -19
- package/src/router/view/view.js +0 -262
- package/src/router/view/view.spec.js +0 -100
- package/src/router/view/view.test.js +0 -12
- package/src/router/view-hook.spec.js +0 -215
- package/src/router/view-scroll.js +0 -33
- package/src/router/view-scroll.spec.js +0 -72
- package/src/services/anchor-scroll/anchor-scroll.html +0 -76
- package/src/services/anchor-scroll/anchor-scroll.js +0 -147
- package/src/services/exception/exception-handler.js +0 -75
- package/src/services/exception/interface.ts +0 -7
- package/src/services/http/http.html +0 -23
- package/src/services/http/http.js +0 -1109
- package/src/services/http/http.spec.js +0 -4320
- package/src/services/http/http.test.js +0 -11
- package/src/services/http/interface.ts +0 -256
- package/src/services/http/template-request.spec.js +0 -220
- package/src/services/location/interface.ts +0 -70
- package/src/services/location/location.html +0 -22
- package/src/services/location/location.js +0 -1006
- package/src/services/location/location.spec.js +0 -3792
- package/src/services/location/location.test.js +0 -12
- package/src/services/log/interface.ts +0 -39
- package/src/services/log/log.html +0 -19
- package/src/services/log/log.js +0 -74
- package/src/services/log/log.spec.js +0 -64
- package/src/services/log/log.test.js +0 -12
- package/src/services/pubsub/pubsub.html +0 -19
- package/src/services/pubsub/pubsub.js +0 -349
- package/src/services/pubsub/pubsub.spec.js +0 -400
- package/src/services/pubsub/pubsub.test.js +0 -12
- package/src/services/sce/sce.html +0 -19
- package/src/services/sce/sce.js +0 -852
- package/src/services/sce/sce.spec.js +0 -617
- package/src/services/sce/sce.test.js +0 -12
- package/src/services/template-cache/template-cache.html +0 -22
- package/src/services/template-cache/template-cache.js +0 -15
- package/src/services/template-cache/template-cache.spec.js +0 -134
- package/src/services/template-cache/template-cache.test.js +0 -12
- package/src/services/template-request/interface.ts +0 -23
- package/src/services/template-request/template-request.js +0 -142
- package/src/shared/cache.js +0 -7
- package/src/shared/common.js +0 -365
- package/src/shared/common.spec.js +0 -294
- package/src/shared/constants.js +0 -21
- package/src/shared/dom.js +0 -716
- package/src/shared/hof.js +0 -157
- package/src/shared/hof.spec.js +0 -60
- package/src/shared/interface.ts +0 -21
- package/src/shared/min-err.spec.js +0 -178
- package/src/shared/noderef.js +0 -225
- package/src/shared/predicates.js +0 -34
- package/src/shared/queue.js +0 -105
- package/src/shared/queue.spec.js +0 -80
- package/src/shared/shared.html +0 -24
- package/src/shared/shared.test.js +0 -12
- package/src/shared/strings.js +0 -142
- package/src/shared/strings.spec.js +0 -40
- package/src/shared/test-utils.js +0 -47
- package/src/shared/url-utils/interface.ts +0 -54
- package/src/shared/url-utils/url-utils.html +0 -22
- package/src/shared/url-utils/url-utils.js +0 -122
- package/src/shared/url-utils/url-utils.spec.js +0 -148
- package/src/shared/url-utils/url-utils.test.js +0 -12
- package/src/shared/utils.js +0 -1255
- package/src/shared/utils.spec.js +0 -178
- package/src/src.html +0 -21
- package/src/src.test.js +0 -10
- package/tsconfig.json +0 -19
- package/tsconfig.types.json +0 -14
- package/typedoc.json +0 -8
- package/utils/express.js +0 -203
- package/utils/version.cjs +0 -23
- 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
|
-
});
|