@angular-wave/angular.ts 0.9.3 → 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/angular.d.ts +4 -19
- package/@types/animations/animate.d.ts +2 -2
- package/@types/animations/animation.d.ts +1 -1
- package/@types/core/compile/attributes.d.ts +1 -1
- package/@types/core/compile/compile.d.ts +2 -2
- package/@types/core/controller/controller.d.ts +1 -1
- package/@types/core/controller/interface.d.ts +6 -0
- package/@types/core/di/ng-module.d.ts +27 -26
- package/@types/core/filter/filter.d.ts +5 -5
- package/@types/core/interpolate/interface.d.ts +13 -0
- package/@types/core/interpolate/interpolate.d.ts +1 -13
- package/@types/core/scope/scope.d.ts +4 -1
- package/@types/directive/http/http.d.ts +16 -16
- package/@types/directive/http/interface.d.ts +27 -0
- package/@types/directive/include/include.d.ts +4 -4
- package/@types/directive/inject/inject.d.ts +12 -0
- package/@types/directive/model/model.d.ts +1 -1
- package/@types/directive/script/script.d.ts +2 -2
- package/@types/directive/setter/setter.d.ts +4 -4
- package/@types/filters/filter.d.ts +2 -2
- package/@types/filters/filters.d.ts +2 -2
- package/@types/filters/interface.d.ts +8 -0
- package/@types/filters/limit-to.d.ts +2 -2
- package/@types/filters/order-by.d.ts +2 -2
- package/@types/interface.d.ts +105 -82
- package/@types/namespace.d.ts +76 -0
- package/@types/router/state/interface.d.ts +8 -8
- package/@types/router/state-filters.d.ts +4 -4
- package/@types/router/template-factory.d.ts +8 -8
- package/@types/router/transition/hook-builder.d.ts +5 -2
- package/@types/router/transition/hook-registry.d.ts +11 -2
- package/@types/router/transition/transition-service.d.ts +6 -2
- package/@types/router/transition/transition.d.ts +2 -2
- package/@types/router/view/view.d.ts +1 -8
- package/@types/router/view-scroll.d.ts +4 -2
- package/@types/services/{anchor-scroll.d.ts → anchor-scroll/anchor-scroll.d.ts} +2 -2
- package/@types/services/exception/exception-handler.d.ts +2 -2
- package/@types/services/exception/interface.d.ts +1 -1
- package/@types/services/http/http.d.ts +40 -2
- package/@types/services/http/interface.d.ts +11 -0
- package/@types/services/location/location.d.ts +1 -4
- package/@types/services/sce/sce.d.ts +3 -4
- package/@types/services/template-cache/template-cache.d.ts +4 -4
- package/@types/services/template-request/interface.d.ts +22 -0
- package/@types/services/{template-request.d.ts → template-request/template-request.d.ts} +4 -7
- package/@types/shared/common.d.ts +8 -69
- package/@types/shared/hof.d.ts +7 -7
- package/dist/angular-ts.esm.js +510 -570
- package/dist/angular-ts.umd.js +510 -570
- 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/@types/services/cookie-reader.d.ts +0 -4
- package/@types/services/http-backend/http-backend.d.ts +0 -58
- package/@types/services/template-cache/interface.d.ts +0 -10
- 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/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/templateCacheProvider.md +0 -100
- package/docs/content/docs/service/_index.md +0 -4
- package/docs/content/docs/service/eventBus.md +0 -56
- package/docs/content/docs/service/location.md +0 -57
- package/docs/content/docs/service/log.md +0 -113
- package/docs/content/docs/service/templateCache.md +0 -64
- package/docs/content/docs/service/url.md +0 -5
- 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/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/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/typedoc/.nojekyll +0 -1
- package/docs/static/typedoc/assets/hierarchy.js +0 -1
- package/docs/static/typedoc/assets/highlight.css +0 -78
- 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 -3
- 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/ChangesObject.html +0 -6
- package/docs/static/typedoc/interfaces/ComponentOptions.html +0 -16
- package/docs/static/typedoc/interfaces/Controller.html +0 -12
- package/docs/static/typedoc/interfaces/DefaultPorts.html +0 -5
- package/docs/static/typedoc/interfaces/Directive.html +0 -37
- package/docs/static/typedoc/interfaces/DirectivePrePost.html +0 -4
- 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/NgModelController.html +0 -30
- package/docs/static/typedoc/interfaces/NgModelOptions.html +0 -16
- package/docs/static/typedoc/interfaces/Provider.html +0 -34
- 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/TemplateCache.html +0 -7
- package/docs/static/typedoc/interfaces/TranscludeFunctionObject.html +0 -8
- package/docs/static/typedoc/interfaces/UrlParts.html +0 -9
- package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +0 -1
- package/docs/static/typedoc/types/AnnotatedFactory.html +0 -8
- package/docs/static/typedoc/types/CloneAttachFunction.html +0 -2
- package/docs/static/typedoc/types/ControllerConstructor.html +0 -2
- package/docs/static/typedoc/types/DirectiveCompileFn.html +0 -2
- package/docs/static/typedoc/types/DirectiveController.html +0 -2
- package/docs/static/typedoc/types/DirectiveFactory.html +0 -1
- package/docs/static/typedoc/types/DirectiveFactoryFn.html +0 -1
- package/docs/static/typedoc/types/DirectiveLinkFn.html +0 -2
- package/docs/static/typedoc/types/ExpandoStore.html +0 -2
- package/docs/static/typedoc/types/Expression.html +0 -6
- package/docs/static/typedoc/types/FilterFactory.html +0 -2
- package/docs/static/typedoc/types/FilterFn.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/Injectable.html +0 -4
- package/docs/static/typedoc/types/InjectableClass.html +0 -1
- package/docs/static/typedoc/types/InjectableFactory.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/OnChangesObject.html +0 -2
- package/docs/static/typedoc/types/SwapModeType.html +0 -2
- package/docs/static/typedoc/types/TController.html +0 -2
- package/docs/static/typedoc/types/UrlChangeListener.html +0 -5
- package/docs/static/typedoc/variables/EventBus.html +0 -1
- package/docs/static/typedoc/variables/SwapMode.html +0 -11
- 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 -2599
- 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 -293
- 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 -3270
- 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 -189
- package/src/core/controller/controller.spec.js +0 -334
- package/src/core/controller/controller.test.js +0 -12
- 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 -284
- package/src/core/di/ng-module.html +0 -19
- package/src/core/di/ng-module.js +0 -226
- 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/interpolate.html +0 -22
- package/src/core/interpolate/interpolate.js +0 -408
- 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 -1249
- 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 -26
- 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/post-example.html +0 -30
- package/src/directive/http/post.spec.js +0 -521
- package/src/directive/http/put.spec.js +0 -26
- 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/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.md +0 -69
- 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/json.md +0 -16
- package/src/filters/limit-to.js +0 -55
- package/src/filters/limit-to.md +0 -19
- package/src/filters/limit-to.spec.js +0 -252
- package/src/filters/order-by.js +0 -181
- package/src/filters/order-by.md +0 -83
- 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 -78
- package/src/interface.ts +0 -421
- package/src/ng.js +0 -289
- package/src/ng.spec.js +0 -33
- 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 -1937
- 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/README.md +0 -21
- 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 -257
- package/src/router/state/state-service.js +0 -699
- 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 -155
- package/src/router/template-factory.test.js +0 -12
- package/src/router/transition/hook-builder.js +0 -133
- package/src/router/transition/hook-registry.js +0 -172
- 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 -302
- package/src/router/transition/transition.js +0 -652
- 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 -274
- 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.html +0 -76
- package/src/services/anchor-scroll.js +0 -147
- package/src/services/cookie-reader.js +0 -48
- 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 -922
- package/src/services/http/http.md +0 -413
- package/src/services/http/http.spec.js +0 -3941
- package/src/services/http/http.test.js +0 -11
- package/src/services/http/interface.ts +0 -243
- package/src/services/http/template-request.spec.js +0 -220
- package/src/services/http-backend/http-backend.html +0 -22
- package/src/services/http-backend/http-backend.js +0 -158
- package/src/services/http-backend/http-backend.spec.js +0 -389
- package/src/services/http-backend/http-backend.test.js +0 -12
- 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 -847
- package/src/services/sce/sce.md +0 -300
- package/src/services/sce/sce.spec.js +0 -617
- package/src/services/sce/sce.test.js +0 -12
- package/src/services/template-cache/interface.ts +0 -10
- 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.js +0 -142
- package/src/shared/cache.js +0 -7
- package/src/shared/common.js +0 -438
- 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 -151
- 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,3554 +0,0 @@
|
|
|
1
|
-
import { createInjector } from "../../core/di/injector.js";
|
|
2
|
-
import { dealoc, getController } from "../../shared/dom.js";
|
|
3
|
-
import { Angular } from "../../angular.js";
|
|
4
|
-
import {
|
|
5
|
-
isBoolean,
|
|
6
|
-
hashKey,
|
|
7
|
-
equals,
|
|
8
|
-
isString,
|
|
9
|
-
isFunction,
|
|
10
|
-
} from "../../shared/utils.js";
|
|
11
|
-
import { browserTrigger, wait } from "../../shared/test-utils.js";
|
|
12
|
-
|
|
13
|
-
describe("ngOptions", () => {
|
|
14
|
-
let scope;
|
|
15
|
-
let formElement;
|
|
16
|
-
let element;
|
|
17
|
-
let $compile;
|
|
18
|
-
let linkLog;
|
|
19
|
-
let childListMutationObserver;
|
|
20
|
-
let ngModelCtrl;
|
|
21
|
-
let injector;
|
|
22
|
-
let errors = [];
|
|
23
|
-
|
|
24
|
-
async function compile(html) {
|
|
25
|
-
element.innerHTML = `<form name="form">${html}</form>`;
|
|
26
|
-
formElement = $compile(element)(scope);
|
|
27
|
-
await wait();
|
|
28
|
-
element = formElement.querySelector("select");
|
|
29
|
-
ngModelCtrl = getController(element, "ngModel");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function setSelectValue(selectElement, optionIndex) {
|
|
33
|
-
const option = selectElement.querySelector("option")[optionIndex];
|
|
34
|
-
selectElement.value = option.value;
|
|
35
|
-
browserTrigger(element, "change");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
beforeEach(() => {
|
|
39
|
-
jasmine.addMatchers({
|
|
40
|
-
toEqualSelectValue() {
|
|
41
|
-
return {
|
|
42
|
-
compare(_actual_, value, multiple) {
|
|
43
|
-
const errors = [];
|
|
44
|
-
let actual = _actual_.value;
|
|
45
|
-
|
|
46
|
-
if (multiple) {
|
|
47
|
-
value = value.map((val) => hashKey(val));
|
|
48
|
-
actual = actual || [];
|
|
49
|
-
} else {
|
|
50
|
-
value = hashKey(value);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (!equals(actual, value)) {
|
|
54
|
-
errors.push(
|
|
55
|
-
`Expected select value "${actual}" to equal "${value}"`,
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
const message = function () {
|
|
59
|
-
return errors.join("\n");
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
return { pass: errors.length === 0, message };
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
},
|
|
66
|
-
toEqualOption() {
|
|
67
|
-
return {
|
|
68
|
-
compare(actual, value, text, label) {
|
|
69
|
-
const errors = [];
|
|
70
|
-
const hash = hashKey(value);
|
|
71
|
-
if (actual.getAttribute("value") !== hash) {
|
|
72
|
-
errors.push(
|
|
73
|
-
`Expected option value "${actual.getAttribute("value")}" to equal "${hash}"`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
if (text && actual.textContent !== text) {
|
|
77
|
-
errors.push(
|
|
78
|
-
`Expected option text "${actual.textContent}" to equal "${text}"`,
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
if (label && actual.getAttribute("label") !== label) {
|
|
82
|
-
errors.push(
|
|
83
|
-
`Expected option label "${actual.getAttribute("label")}" to equal "${label}"`,
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const message = function () {
|
|
88
|
-
return errors.join("\n");
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
return { pass: errors.length === 0, message };
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
},
|
|
95
|
-
toEqualTrackedOption() {
|
|
96
|
-
return {
|
|
97
|
-
compare(actual, value, text, label) {
|
|
98
|
-
const errors = [];
|
|
99
|
-
if (actual.getAttribute("value") !== `${value}`) {
|
|
100
|
-
errors.push(
|
|
101
|
-
`Expected option value "${actual.getAttribute("value")}" to equal "${value}"`,
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
if (text && actual.textContent !== text) {
|
|
105
|
-
errors.push(
|
|
106
|
-
`Expected option text "${actual.textContent}" to equal "${text}"`,
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
if (label && actual.getAttribute("label") !== label) {
|
|
110
|
-
errors.push(
|
|
111
|
-
`Expected option label "${actual.getAttribute("label")}" to equal "${label}"`,
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const message = function () {
|
|
116
|
-
return errors.join("\n");
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
return { pass: errors.length === 0, message };
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
},
|
|
123
|
-
toEqualUnknownOption() {
|
|
124
|
-
return {
|
|
125
|
-
compare(actual) {
|
|
126
|
-
const errors = [];
|
|
127
|
-
if (actual.getAttribute("value") !== "?") {
|
|
128
|
-
errors.push(
|
|
129
|
-
`Expected option value "${actual.getAttribute("value")}" to equal "?"`,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const message = function () {
|
|
134
|
-
return errors.join("\n");
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
return { pass: errors.length === 0, message };
|
|
138
|
-
},
|
|
139
|
-
};
|
|
140
|
-
},
|
|
141
|
-
toEqualUnknownValue() {
|
|
142
|
-
return {
|
|
143
|
-
compare(actual, value) {
|
|
144
|
-
const errors = [];
|
|
145
|
-
if (actual !== "?") {
|
|
146
|
-
errors.push(`Expected select value "${actual}" to equal "?"`);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const message = function () {
|
|
150
|
-
return errors.join("\n");
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
return { pass: errors.length === 0, message };
|
|
154
|
-
},
|
|
155
|
-
};
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
beforeEach(() => {
|
|
161
|
-
errors = [];
|
|
162
|
-
element = document.getElementById("app");
|
|
163
|
-
element.innerHTML = "test";
|
|
164
|
-
dealoc(document.getElementById("app"));
|
|
165
|
-
window.angular = new Angular();
|
|
166
|
-
window.angular
|
|
167
|
-
.module("myModule", ["ng"])
|
|
168
|
-
.decorator("$exceptionHandler", function () {
|
|
169
|
-
return (exception) => {
|
|
170
|
-
console.error(exception.message);
|
|
171
|
-
errors.push(exception.message);
|
|
172
|
-
};
|
|
173
|
-
});
|
|
174
|
-
injector = createInjector([
|
|
175
|
-
"myModule",
|
|
176
|
-
($compileProvider, $provide) => {
|
|
177
|
-
linkLog = [];
|
|
178
|
-
|
|
179
|
-
$compileProvider
|
|
180
|
-
.directive("customSelect", () => ({
|
|
181
|
-
restrict: "E",
|
|
182
|
-
replace: true,
|
|
183
|
-
scope: {
|
|
184
|
-
ngModel: "=",
|
|
185
|
-
options: "=",
|
|
186
|
-
},
|
|
187
|
-
templateUrl: "select_template.html",
|
|
188
|
-
link(scope) {
|
|
189
|
-
scope.selectable_options = scope.options;
|
|
190
|
-
},
|
|
191
|
-
}))
|
|
192
|
-
|
|
193
|
-
.directive("oCompileContents", () => ({
|
|
194
|
-
link(scope, element) {
|
|
195
|
-
linkLog.push("linkCompileContents");
|
|
196
|
-
$compile(element.childNodes)(scope);
|
|
197
|
-
},
|
|
198
|
-
}))
|
|
199
|
-
|
|
200
|
-
.directive("observeChildList", () => ({
|
|
201
|
-
link(scope, element) {
|
|
202
|
-
const config = { childList: true };
|
|
203
|
-
|
|
204
|
-
childListMutationObserver = new window.MutationObserver(() => {});
|
|
205
|
-
childListMutationObserver.observe(element, config);
|
|
206
|
-
},
|
|
207
|
-
}));
|
|
208
|
-
|
|
209
|
-
$provide.decorator("ngOptionsDirective", ($delegate) => {
|
|
210
|
-
const origPreLink = $delegate[0].link.pre;
|
|
211
|
-
const origPostLink = $delegate[0].link.post;
|
|
212
|
-
|
|
213
|
-
$delegate[0].compile = function () {
|
|
214
|
-
return {
|
|
215
|
-
pre: origPreLink,
|
|
216
|
-
post() {
|
|
217
|
-
linkLog.push("linkNgOptions");
|
|
218
|
-
origPostLink.apply(this, arguments);
|
|
219
|
-
},
|
|
220
|
-
};
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
return $delegate;
|
|
224
|
-
});
|
|
225
|
-
},
|
|
226
|
-
]);
|
|
227
|
-
$compile = injector.get("$compile");
|
|
228
|
-
scope = injector.get("$rootScope").$new(); // create a child scope because the root scope can't be $destroy-ed
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
afterEach(() => {
|
|
232
|
-
// scope.$destroy(); // disables unknown option work during destruction
|
|
233
|
-
// dealoc(formElement);
|
|
234
|
-
// ngModelCtrl = null;
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
async function createSelect(attrs, blank, unknown) {
|
|
238
|
-
let html = "<select";
|
|
239
|
-
Object.entries(attrs).forEach(([key, value]) => {
|
|
240
|
-
if (isBoolean(value)) {
|
|
241
|
-
if (value) html += ` ${key}`;
|
|
242
|
-
} else {
|
|
243
|
-
html += ` ${key}="${value}"`;
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
html += `>${
|
|
247
|
-
blank ? (isString(blank) ? blank : '<option value="">blank</option>') : ""
|
|
248
|
-
}${
|
|
249
|
-
unknown
|
|
250
|
-
? isString(unknown)
|
|
251
|
-
? unknown
|
|
252
|
-
: '<option value="?">unknown</option>'
|
|
253
|
-
: ""
|
|
254
|
-
}</select>`;
|
|
255
|
-
element.innerHTML = html;
|
|
256
|
-
|
|
257
|
-
await compile(element);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function createSingleSelect(blank, unknown) {
|
|
261
|
-
createSelect(
|
|
262
|
-
{
|
|
263
|
-
"ng-model": "selected",
|
|
264
|
-
"ng-options": "value.name for value in values",
|
|
265
|
-
},
|
|
266
|
-
blank,
|
|
267
|
-
unknown,
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function createMultiSelect(blank, unknown) {
|
|
272
|
-
createSelect(
|
|
273
|
-
{
|
|
274
|
-
"ng-model": "selected",
|
|
275
|
-
multiple: true,
|
|
276
|
-
"ng-options": "value.name for value in values",
|
|
277
|
-
},
|
|
278
|
-
blank,
|
|
279
|
-
unknown,
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
fit('should throw when not formated "? for ? in ?"', async () => {
|
|
284
|
-
compile('<select ng-model="selected" ng-options="i dont parse"></select>');
|
|
285
|
-
await wait();
|
|
286
|
-
expect(errors[0]).toMatch("iexp");
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
fit("should have a dependency on ngModel", async () => {
|
|
290
|
-
try {
|
|
291
|
-
await compile('<select ng-options="item in items"></select>');
|
|
292
|
-
await wait();
|
|
293
|
-
} catch (error) {
|
|
294
|
-
expect(error.message).toMatch("ngModel");
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
fit("should render a list", async () => {
|
|
299
|
-
compile(
|
|
300
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>',
|
|
301
|
-
);
|
|
302
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
303
|
-
scope.selected = scope.values[1];
|
|
304
|
-
await wait();
|
|
305
|
-
const options = element.querySelectorAll("option");
|
|
306
|
-
expect(options.length).toEqual(3);
|
|
307
|
-
expect(options[0]).toEqualOption(scope.values[0], "A");
|
|
308
|
-
expect(options[1]).toEqualOption(scope.values[1], "B");
|
|
309
|
-
expect(options[2]).toEqualOption(scope.values[2], "C");
|
|
310
|
-
expect(options[1].selected).toEqual(true);
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
fit("should not include properties with non-numeric keys in array-like collections when using array syntax", async () => {
|
|
314
|
-
compile(
|
|
315
|
-
'<select ng-model="selected" ng-options="value for value in values"></select>',
|
|
316
|
-
);
|
|
317
|
-
scope.values = { 0: "X", 1: "Y", 2: "Z", a: "A", length: 3 };
|
|
318
|
-
await wait();
|
|
319
|
-
scope.selected = scope.values[1];
|
|
320
|
-
await wait();
|
|
321
|
-
const options = element.querySelectorAll("option");
|
|
322
|
-
expect(options.length).toEqual(3);
|
|
323
|
-
expect(options[0]).toEqualOption("X");
|
|
324
|
-
expect(options[1]).toEqualOption("Y");
|
|
325
|
-
expect(options[2]).toEqualOption("Z");
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
fit("should include properties with non-numeric keys in array-like collections when using object syntax", async () => {
|
|
329
|
-
compile(
|
|
330
|
-
'<select ng-model="selected" ng-options="value for (key, value) in values"></select>',
|
|
331
|
-
);
|
|
332
|
-
scope.values = { 0: "X", 1: "Y", 2: "Z", a: "A", length: 3 };
|
|
333
|
-
scope.selected = scope.values[1];
|
|
334
|
-
await wait();
|
|
335
|
-
const options = element.querySelectorAll("option");
|
|
336
|
-
expect(options.length).toEqual(5);
|
|
337
|
-
expect(options[0]).toEqualOption("X");
|
|
338
|
-
expect(options[1]).toEqualOption("Y");
|
|
339
|
-
expect(options[2]).toEqualOption("Z");
|
|
340
|
-
expect(options[3]).toEqualOption("A");
|
|
341
|
-
expect(options[4]).toEqualOption(3);
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
fit("should render an object", async () => {
|
|
345
|
-
compile(
|
|
346
|
-
'<select ng-model="selected" ng-options="value as key for (key, value) in object"></select>',
|
|
347
|
-
);
|
|
348
|
-
scope.object = { red: "FF0000", green: "00FF00", blue: "0000FF" };
|
|
349
|
-
scope.selected = scope.object.green;
|
|
350
|
-
await wait();
|
|
351
|
-
|
|
352
|
-
let options = element.querySelectorAll("option");
|
|
353
|
-
expect(options.length).toEqual(3);
|
|
354
|
-
expect(options[0]).toEqualOption("FF0000", "red");
|
|
355
|
-
expect(options[1]).toEqualOption("00FF00", "green");
|
|
356
|
-
expect(options[2]).toEqualOption("0000FF", "blue");
|
|
357
|
-
expect(options[1].selected).toEqual(true);
|
|
358
|
-
scope.$apply('object.azur = "8888FF"');
|
|
359
|
-
await wait();
|
|
360
|
-
options = element.querySelectorAll("option");
|
|
361
|
-
expect(options[1].selected).toEqual(true);
|
|
362
|
-
await wait();
|
|
363
|
-
scope.$apply("selected = object.azur");
|
|
364
|
-
await wait();
|
|
365
|
-
options = element.querySelectorAll("option");
|
|
366
|
-
expect(options[3].selected).toEqual(true);
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
fit('should set the "selected" attribute and property on selected options', async () => {
|
|
370
|
-
compile(
|
|
371
|
-
'<select ng-model="selected" ng-options="option.id as option.display for option in values"></select>',
|
|
372
|
-
);
|
|
373
|
-
scope.values = [
|
|
374
|
-
{
|
|
375
|
-
id: "FF0000",
|
|
376
|
-
display: "red",
|
|
377
|
-
},
|
|
378
|
-
{
|
|
379
|
-
id: "0000FF",
|
|
380
|
-
display: "blue",
|
|
381
|
-
},
|
|
382
|
-
];
|
|
383
|
-
scope.selected = "FF0000";
|
|
384
|
-
await wait();
|
|
385
|
-
|
|
386
|
-
const options = element.querySelectorAll("option");
|
|
387
|
-
expect(options.length).toEqual(2);
|
|
388
|
-
expect(options[0]).toEqualOption("FF0000", "red");
|
|
389
|
-
expect(options[1]).toEqualOption("0000FF", "blue");
|
|
390
|
-
|
|
391
|
-
expect(options[0].getAttribute("selected")).toBe("selected");
|
|
392
|
-
expect(options[0].getAttribute("selected")).toBe("selected");
|
|
393
|
-
expect(options[0].selected).toBe(true);
|
|
394
|
-
expect(options[0].selected).toBe(true);
|
|
395
|
-
|
|
396
|
-
scope.selected = "0000FF";
|
|
397
|
-
await wait();
|
|
398
|
-
expect(options[1].getAttribute("selected")).toBe("selected");
|
|
399
|
-
expect(options[1].getAttribute("selected")).toBe("selected");
|
|
400
|
-
expect(options[1].selected).toBe(true);
|
|
401
|
-
expect(options[1].selected).toBe(true);
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
fit("should render zero as a valid display value", async () => {
|
|
405
|
-
compile(
|
|
406
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>',
|
|
407
|
-
);
|
|
408
|
-
|
|
409
|
-
scope.values = [{ name: 0 }, { name: 1 }, { name: 2 }];
|
|
410
|
-
await wait();
|
|
411
|
-
|
|
412
|
-
scope.selected = scope.values[0];
|
|
413
|
-
await wait();
|
|
414
|
-
|
|
415
|
-
const options = element.querySelectorAll("option");
|
|
416
|
-
expect(options.length).toEqual(3);
|
|
417
|
-
expect(options[0]).toEqualOption(scope.values[0], "0");
|
|
418
|
-
expect(options[1]).toEqualOption(scope.values[1], "1");
|
|
419
|
-
expect(options[2]).toEqualOption(scope.values[2], "2");
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
fit("should not be set when an option is selected and options are set asynchronously", async () => {
|
|
423
|
-
compile(
|
|
424
|
-
'<select ng-model="model" ng-options="opt.id as opt.label for opt in options"></select>',
|
|
425
|
-
);
|
|
426
|
-
await wait();
|
|
427
|
-
scope.model = 0;
|
|
428
|
-
scope.options = [
|
|
429
|
-
{ id: 0, label: "x" },
|
|
430
|
-
{ id: 1, label: "y" },
|
|
431
|
-
];
|
|
432
|
-
await wait();
|
|
433
|
-
const options = element.querySelectorAll("option");
|
|
434
|
-
expect(options.length).toEqual(2);
|
|
435
|
-
expect(options[0]).toEqualOption(0, "x");
|
|
436
|
-
expect(options[1]).toEqualOption(1, "y");
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
fit("should grow list", async () => {
|
|
440
|
-
compile(
|
|
441
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>',
|
|
442
|
-
);
|
|
443
|
-
await wait();
|
|
444
|
-
scope.values = [];
|
|
445
|
-
await wait();
|
|
446
|
-
expect(element.querySelectorAll("option").length).toEqual(1); // because we add special unknown option
|
|
447
|
-
expect(element.querySelectorAll("option")[0]).toEqualUnknownOption();
|
|
448
|
-
|
|
449
|
-
scope.values.push({ name: "A" });
|
|
450
|
-
scope.selected = scope.values[0];
|
|
451
|
-
await wait();
|
|
452
|
-
expect(element.querySelectorAll("option").length).toEqual(1);
|
|
453
|
-
expect(element.querySelectorAll("option")[0]).toEqualOption(
|
|
454
|
-
scope.values[0],
|
|
455
|
-
"A",
|
|
456
|
-
);
|
|
457
|
-
|
|
458
|
-
scope.values.push({ name: "B" });
|
|
459
|
-
await wait();
|
|
460
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
461
|
-
expect(element.querySelectorAll("option")[0]).toEqualOption(
|
|
462
|
-
scope.values[0],
|
|
463
|
-
"A",
|
|
464
|
-
);
|
|
465
|
-
expect(element.querySelectorAll("option")[1]).toEqualOption(
|
|
466
|
-
scope.values[1],
|
|
467
|
-
"B",
|
|
468
|
-
);
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
fit("should shrink list", async () => {
|
|
472
|
-
compile(
|
|
473
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>',
|
|
474
|
-
);
|
|
475
|
-
await wait();
|
|
476
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
477
|
-
scope.selected = scope.values[0];
|
|
478
|
-
await wait();
|
|
479
|
-
expect(element.querySelectorAll("option").length).toEqual(3);
|
|
480
|
-
|
|
481
|
-
scope.values.pop();
|
|
482
|
-
await wait();
|
|
483
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
484
|
-
expect(element.querySelectorAll("option")[0]).toEqualOption(
|
|
485
|
-
scope.values[0],
|
|
486
|
-
"A",
|
|
487
|
-
);
|
|
488
|
-
expect(element.querySelectorAll("option")[1]).toEqualOption(
|
|
489
|
-
scope.values[1],
|
|
490
|
-
"B",
|
|
491
|
-
);
|
|
492
|
-
scope.values.pop();
|
|
493
|
-
await wait();
|
|
494
|
-
|
|
495
|
-
expect(element.querySelectorAll("option").length).toEqual(1);
|
|
496
|
-
expect(element.querySelectorAll("option")[0]).toEqualOption(
|
|
497
|
-
scope.values[0],
|
|
498
|
-
"A",
|
|
499
|
-
);
|
|
500
|
-
|
|
501
|
-
scope.values.pop();
|
|
502
|
-
scope.selected = null;
|
|
503
|
-
await wait();
|
|
504
|
-
|
|
505
|
-
expect(element.querySelectorAll("option").length).toEqual(1); // we add back the special empty option
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
it("should shrink and then grow list", async () => {
|
|
509
|
-
element.innerHTML =
|
|
510
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
511
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
512
|
-
scope = injector.get("$rootScope");
|
|
513
|
-
await wait();
|
|
514
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
515
|
-
await wait();
|
|
516
|
-
scope.selected = scope.values[0];
|
|
517
|
-
await wait();
|
|
518
|
-
expect(element.querySelectorAll("option").length).toEqual(3);
|
|
519
|
-
|
|
520
|
-
scope.values = [{ name: "1" }, { name: "2" }];
|
|
521
|
-
await wait();
|
|
522
|
-
scope.selected = scope.values[0];
|
|
523
|
-
await wait();
|
|
524
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
525
|
-
|
|
526
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
527
|
-
await wait();
|
|
528
|
-
scope.selected = scope.values[0];
|
|
529
|
-
await wait();
|
|
530
|
-
expect(element.querySelectorAll("option").length).toEqual(3);
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
it("should update list", async () => {
|
|
534
|
-
element.innerHTML =
|
|
535
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
536
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
537
|
-
scope = injector.get("$rootScope");
|
|
538
|
-
|
|
539
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
540
|
-
await wait();
|
|
541
|
-
scope.selected = scope.values[0];
|
|
542
|
-
await wait();
|
|
543
|
-
scope.values = [{ name: "B" }, { name: "C" }, { name: "D" }];
|
|
544
|
-
await wait();
|
|
545
|
-
scope.selected = scope.values[0];
|
|
546
|
-
await wait();
|
|
547
|
-
const options = element.querySelectorAll("option");
|
|
548
|
-
expect(options.length).toEqual(3);
|
|
549
|
-
expect(options[0]).toEqualOption(scope.values[0], "B");
|
|
550
|
-
expect(options[1]).toEqualOption(scope.values[1], "C");
|
|
551
|
-
expect(options[2]).toEqualOption(scope.values[2], "D");
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
it("should preserve pre-existing empty option", async () => {
|
|
555
|
-
element.innerHTML =
|
|
556
|
-
'<select ng-model="selected" ng-options="value.name for value in values"><option value="">blank</option></select>';
|
|
557
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
558
|
-
scope = injector.get("$rootScope");
|
|
559
|
-
await wait();
|
|
560
|
-
scope.values = [];
|
|
561
|
-
await wait();
|
|
562
|
-
expect(element.querySelectorAll("option").length).toEqual(1);
|
|
563
|
-
scope.values = [{ name: "A" }];
|
|
564
|
-
await wait();
|
|
565
|
-
scope.selected = scope.values[0];
|
|
566
|
-
await wait();
|
|
567
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
568
|
-
expect(element.querySelectorAll("option")[0].textContent).toEqual("blank");
|
|
569
|
-
expect(element.querySelectorAll("option")[1].textContent).toEqual("A");
|
|
570
|
-
|
|
571
|
-
scope.values = [];
|
|
572
|
-
await wait();
|
|
573
|
-
scope.selected = null;
|
|
574
|
-
await wait();
|
|
575
|
-
expect(element.querySelectorAll("option").length).toEqual(1);
|
|
576
|
-
expect(element.querySelectorAll("option")[0].textContent).toEqual("blank");
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
it("should ignore $ and $$ properties", async () => {
|
|
580
|
-
element.innerHTML =
|
|
581
|
-
'<select ng-model="selected" ng-options="key as value for (key, value) in object"></select>';
|
|
582
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
583
|
-
scope = injector.get("$rootScope");
|
|
584
|
-
|
|
585
|
-
scope.object = {
|
|
586
|
-
regularProperty: "visible",
|
|
587
|
-
$$private: "invisible",
|
|
588
|
-
$property: "invisible",
|
|
589
|
-
};
|
|
590
|
-
scope.selected = "regularProperty";
|
|
591
|
-
await wait();
|
|
592
|
-
const options = element.querySelectorAll("option");
|
|
593
|
-
expect(options.length).toEqual(1);
|
|
594
|
-
expect(options[0]).toEqualOption("regularProperty", "visible");
|
|
595
|
-
});
|
|
596
|
-
|
|
597
|
-
it("should not watch non-numeric array properties", async () => {
|
|
598
|
-
element.innerHTML = $compile(
|
|
599
|
-
'<select ng-model="selected" ng-options="value as createLabel(value) for value in array"></select>',
|
|
600
|
-
)(scope);
|
|
601
|
-
scope.createLabel = jasmine
|
|
602
|
-
.createSpy("createLabel")
|
|
603
|
-
.and.callFake((value) => value);
|
|
604
|
-
scope.array = ["a", "b", "c"];
|
|
605
|
-
scope.array.$$private = "do not watch";
|
|
606
|
-
scope.array.$property = "do not watch";
|
|
607
|
-
scope.array.other = "do not watch";
|
|
608
|
-
scope.array.fn = function () {};
|
|
609
|
-
scope.selected = "b";
|
|
610
|
-
await wait();
|
|
611
|
-
expect(scope.createLabel).toHaveBeenCalledWith("a");
|
|
612
|
-
expect(scope.createLabel).toHaveBeenCalledWith("b");
|
|
613
|
-
expect(scope.createLabel).toHaveBeenCalledWith("c");
|
|
614
|
-
expect(scope.createLabel).not.toHaveBeenCalledWith("do not watch");
|
|
615
|
-
expect(scope.createLabel).not.toHaveBeenCalledWith(jasmine.any(Function));
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
it("should not watch object properties that start with $ or $$", async () => {
|
|
619
|
-
element.innerHTML = $compile(
|
|
620
|
-
'<select ng-model="selected" ng-options="key as createLabel(key) for (key, value) in object"></select>',
|
|
621
|
-
)(scope);
|
|
622
|
-
scope.createLabel = jasmine
|
|
623
|
-
.createSpy("createLabel")
|
|
624
|
-
.and.callFake((value) => value);
|
|
625
|
-
scope.object = {
|
|
626
|
-
regularProperty: "visible",
|
|
627
|
-
$$private: "invisible",
|
|
628
|
-
$property: "invisible",
|
|
629
|
-
};
|
|
630
|
-
scope.selected = "regularProperty";
|
|
631
|
-
await wait();
|
|
632
|
-
expect(scope.createLabel).toHaveBeenCalledWith("regularProperty");
|
|
633
|
-
expect(scope.createLabel).not.toHaveBeenCalledWith("$$private");
|
|
634
|
-
expect(scope.createLabel).not.toHaveBeenCalledWith("$property");
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
xit("should allow expressions over multiple lines", async () => {
|
|
638
|
-
scope.isNotFoo = function (item) {
|
|
639
|
-
return item.name !== "Foo";
|
|
640
|
-
};
|
|
641
|
-
scope.values = [
|
|
642
|
-
{ id: 1, name: "Foo" },
|
|
643
|
-
{ id: 2, name: "Bar" },
|
|
644
|
-
{ id: 3, name: "Baz" },
|
|
645
|
-
];
|
|
646
|
-
element.innerHTML = $compile(
|
|
647
|
-
'<select ng-model="selected" ng-options="key.id for key in values | filter:isNotFoo"></select>',
|
|
648
|
-
)(scope);
|
|
649
|
-
|
|
650
|
-
await wait();
|
|
651
|
-
|
|
652
|
-
scope.selected = scope.values[0];
|
|
653
|
-
await wait();
|
|
654
|
-
const options = element.querySelectorAll("option");
|
|
655
|
-
expect(options.length).toEqual(3);
|
|
656
|
-
expect(options[1]).toEqualOption(scope.values[1], "2");
|
|
657
|
-
expect(options[2]).toEqualOption(scope.values[2], "3");
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
xit("should not update selected property of an option element on digest with no change event", async () => {
|
|
661
|
-
// ng-options="value.name for value in values"
|
|
662
|
-
// ng-model="selected"
|
|
663
|
-
element.innerHTML = $compile(
|
|
664
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>',
|
|
665
|
-
)(scope);
|
|
666
|
-
await wait();
|
|
667
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
668
|
-
scope.selected = scope.values[0];
|
|
669
|
-
await wait();
|
|
670
|
-
const options = element.querySelectorAll("option");
|
|
671
|
-
|
|
672
|
-
expect(scope.selected).toEqual(jasmine.objectContaining({ name: "A" }));
|
|
673
|
-
expect(options[0][0].selected).toBe(true);
|
|
674
|
-
expect(options[1][0].selected).toBe(false);
|
|
675
|
-
|
|
676
|
-
const optionToSelect = options[1];
|
|
677
|
-
await wait();
|
|
678
|
-
expect(optionToSelect.textContent).toBe("B");
|
|
679
|
-
|
|
680
|
-
optionToSelect[0].selected = true;
|
|
681
|
-
await wait();
|
|
682
|
-
expect(optionToSelect[0].selected).toBe(true);
|
|
683
|
-
expect(scope.selected).toBe(scope.values[0]);
|
|
684
|
-
});
|
|
685
|
-
|
|
686
|
-
// bug fix #9621
|
|
687
|
-
xit("should update the label property", async () => {
|
|
688
|
-
// ng-options="value.name for value in values"
|
|
689
|
-
// ng-model="selected"
|
|
690
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
691
|
-
scope.selected = scope.values[0];
|
|
692
|
-
await wait();
|
|
693
|
-
element.innerHTML = $compile(
|
|
694
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>',
|
|
695
|
-
)(scope);
|
|
696
|
-
await wait();
|
|
697
|
-
const options = element.querySelectorAll("option");
|
|
698
|
-
expect(options[0][0].label).toEqual("A");
|
|
699
|
-
expect(options[1][0].label).toEqual("B");
|
|
700
|
-
expect(options[2][0].label).toEqual("C");
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
it("should update the label if only the property has changed", async () => {
|
|
704
|
-
// ng-options="value.name for value in values"
|
|
705
|
-
// ng-model="selected"
|
|
706
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
707
|
-
// scope.selected = scope.values[0];
|
|
708
|
-
element.innerHTML = $compile(
|
|
709
|
-
'<div><select ng-model="selected" ng-options="value.name for value in values"></select>',
|
|
710
|
-
)(scope);
|
|
711
|
-
await wait();
|
|
712
|
-
// let options = element.querySelectorAll("option");
|
|
713
|
-
// expect(options[0][0].label).toEqual("A");
|
|
714
|
-
// expect(options[1][0].label).toEqual("B");
|
|
715
|
-
// expect(options[2][0].label).toEqual("C");
|
|
716
|
-
|
|
717
|
-
// scope.$apply('values[0].name = "X"');
|
|
718
|
-
|
|
719
|
-
// options = element.querySelectorAll("option");
|
|
720
|
-
// expect(options[0][0].label).toEqual("X");
|
|
721
|
-
});
|
|
722
|
-
|
|
723
|
-
// bug fix #9714
|
|
724
|
-
it("should select the matching option when the options are updated", () => {
|
|
725
|
-
// first set up a select with no options
|
|
726
|
-
scope.selected = "";
|
|
727
|
-
createSelect({
|
|
728
|
-
"ng-options": "val.id as val.label for val in values",
|
|
729
|
-
"ng-model": "selected",
|
|
730
|
-
});
|
|
731
|
-
let options = element.querySelectorAll("option");
|
|
732
|
-
// we expect the selected option to be the "unknown" option
|
|
733
|
-
expect(options[0]).toEqualUnknownOption("");
|
|
734
|
-
expect(options[0][0].selected).toEqual(true);
|
|
735
|
-
|
|
736
|
-
// now add some real options - one of which matches the selected value
|
|
737
|
-
scope.$apply(
|
|
738
|
-
'values = [{id:"",label:"A"},{id:"1",label:"B"},{id:"2",label:"C"}]',
|
|
739
|
-
);
|
|
740
|
-
|
|
741
|
-
// we expect the selected option to be the one that matches the correct item
|
|
742
|
-
// and for the unknown option to have been removed
|
|
743
|
-
options = element.querySelectorAll("option");
|
|
744
|
-
expect(element).toEqualSelectValue("");
|
|
745
|
-
expect(options[0]).toEqualOption("", "A");
|
|
746
|
-
});
|
|
747
|
-
|
|
748
|
-
it('should remove the "selected" attribute from the previous option when the model changes', () => {
|
|
749
|
-
scope.values = [
|
|
750
|
-
{ id: 10, label: "ten" },
|
|
751
|
-
{ id: 20, label: "twenty" },
|
|
752
|
-
];
|
|
753
|
-
|
|
754
|
-
createSelect(
|
|
755
|
-
{
|
|
756
|
-
"ng-model": "selected",
|
|
757
|
-
"ng-options": "item.label for item in values",
|
|
758
|
-
},
|
|
759
|
-
true,
|
|
760
|
-
);
|
|
761
|
-
|
|
762
|
-
let options = element.querySelectorAll("option");
|
|
763
|
-
expect(options[0].selected).toBe(true);
|
|
764
|
-
expect(options[1].selected).not.toBe(true);
|
|
765
|
-
expect(options[2].selected).not.toBe(true);
|
|
766
|
-
|
|
767
|
-
scope.selected = scope.values[0];
|
|
768
|
-
expect(options[0].selected).not.toBe(true);
|
|
769
|
-
expect(options[1].selected).toBe(true);
|
|
770
|
-
expect(options[2].selected).not.toBe(true);
|
|
771
|
-
|
|
772
|
-
scope.selected = scope.values[1];
|
|
773
|
-
expect(options[0].selected).not.toBe(true);
|
|
774
|
-
expect(options[1].selected).not.toBe(true);
|
|
775
|
-
expect(options[2].selected).toBe(true);
|
|
776
|
-
|
|
777
|
-
// This will select the empty option
|
|
778
|
-
scope.selected = null;
|
|
779
|
-
expect(options[0].selected).toBe(true);
|
|
780
|
-
expect(options[1].selected).not.toBe(true);
|
|
781
|
-
expect(options[2].selected).not.toBe(true);
|
|
782
|
-
|
|
783
|
-
// This will add and select the unknown option
|
|
784
|
-
scope.selected = "unmatched value";
|
|
785
|
-
options = element.querySelectorAll("option");
|
|
786
|
-
|
|
787
|
-
expect(options[0].selected).toBe(true);
|
|
788
|
-
expect(options[1].selected).not.toBe(true);
|
|
789
|
-
expect(options[2].selected).not.toBe(true);
|
|
790
|
-
expect(options[3].selected).not.toBe(true);
|
|
791
|
-
|
|
792
|
-
// Back to matched value
|
|
793
|
-
scope.selected = scope.values[1];
|
|
794
|
-
options = element.querySelectorAll("option");
|
|
795
|
-
|
|
796
|
-
expect(options[0].selected).not.toBe(true);
|
|
797
|
-
expect(options[1].selected).not.toBe(true);
|
|
798
|
-
expect(options[2].selected).toBe(true);
|
|
799
|
-
});
|
|
800
|
-
|
|
801
|
-
if (window.MutationObserver) {
|
|
802
|
-
// IE9 and IE10 do not support MutationObserver
|
|
803
|
-
// Since the feature is only needed for a test, it's okay to skip these browsers
|
|
804
|
-
it("should render the initial options only one time", () => {
|
|
805
|
-
scope.value = "black";
|
|
806
|
-
scope.values = ["black", "white", "red"];
|
|
807
|
-
// observe-child-list adds a MutationObserver that we will read out after ngOptions
|
|
808
|
-
// has been compiled
|
|
809
|
-
createSelect({
|
|
810
|
-
"ng-model": "value",
|
|
811
|
-
"ng-options": "value.name for value in values",
|
|
812
|
-
"observe-child-list": "",
|
|
813
|
-
});
|
|
814
|
-
|
|
815
|
-
const optionEls = element.querySelectorAll("option");
|
|
816
|
-
const records = childListMutationObserver.takeRecords();
|
|
817
|
-
|
|
818
|
-
expect(records.length).toBe(1);
|
|
819
|
-
expect(records[0].addedNodes).toEqual(optionEls);
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
describe("disableWhen expression", () => {
|
|
824
|
-
describe("on single select", () => {
|
|
825
|
-
it("should disable options", () => {
|
|
826
|
-
scope.selected = "";
|
|
827
|
-
scope.options = [
|
|
828
|
-
{ name: "white", value: "#FFFFFF" },
|
|
829
|
-
{ name: "one", value: 1, unavailable: true },
|
|
830
|
-
{ name: "notTrue", value: false },
|
|
831
|
-
{ name: "thirty", value: 30, unavailable: false },
|
|
832
|
-
];
|
|
833
|
-
createSelect({
|
|
834
|
-
"ng-options":
|
|
835
|
-
"o.value as o.name disable when o.unavailable for o in options",
|
|
836
|
-
"ng-model": "selected",
|
|
837
|
-
});
|
|
838
|
-
const options = element.querySelectorAll("option");
|
|
839
|
-
|
|
840
|
-
expect(options.length).toEqual(5);
|
|
841
|
-
expect(options[1][0].disabled).toEqual(false);
|
|
842
|
-
expect(options[2][0].disabled).toEqual(true);
|
|
843
|
-
expect(options.eq(3)[0].disabled).toEqual(false);
|
|
844
|
-
expect(options.eq(4)[0].disabled).toEqual(false);
|
|
845
|
-
});
|
|
846
|
-
|
|
847
|
-
it("should select disabled options when model changes", () => {
|
|
848
|
-
scope.options = [
|
|
849
|
-
{ name: "white", value: "#FFFFFF" },
|
|
850
|
-
{ name: "one", value: 1, unavailable: true },
|
|
851
|
-
{ name: "notTrue", value: false },
|
|
852
|
-
{ name: "thirty", value: 30, unavailable: false },
|
|
853
|
-
];
|
|
854
|
-
createSelect({
|
|
855
|
-
"ng-options":
|
|
856
|
-
"o.value as o.name disable when o.unavailable for o in options",
|
|
857
|
-
"ng-model": "selected",
|
|
858
|
-
});
|
|
859
|
-
|
|
860
|
-
// Initially the model is set to an enabled option
|
|
861
|
-
scope.$apply("selected = 30");
|
|
862
|
-
let options = element.querySelectorAll("option");
|
|
863
|
-
expect(options.eq(3)[0].selected).toEqual(true);
|
|
864
|
-
|
|
865
|
-
// Now set the model to a disabled option
|
|
866
|
-
scope.$apply("selected = 1");
|
|
867
|
-
options = element.querySelectorAll("option");
|
|
868
|
-
|
|
869
|
-
// jQuery returns null for val() when the option is disabled, see
|
|
870
|
-
// https://bugs.jquery.com/ticket/13097
|
|
871
|
-
expect(element.value).toBe("number:1");
|
|
872
|
-
expect(options.length).toEqual(4);
|
|
873
|
-
expect(options[0][0].selected).toEqual(false);
|
|
874
|
-
expect(options[1][0].selected).toEqual(true);
|
|
875
|
-
expect(options[2][0].selected).toEqual(false);
|
|
876
|
-
expect(options.eq(3)[0].selected).toEqual(false);
|
|
877
|
-
});
|
|
878
|
-
|
|
879
|
-
it("should select options in model when they become enabled", () => {
|
|
880
|
-
scope.options = [
|
|
881
|
-
{ name: "white", value: "#FFFFFF" },
|
|
882
|
-
{ name: "one", value: 1, unavailable: true },
|
|
883
|
-
{ name: "notTrue", value: false },
|
|
884
|
-
{ name: "thirty", value: 30, unavailable: false },
|
|
885
|
-
];
|
|
886
|
-
createSelect({
|
|
887
|
-
"ng-options":
|
|
888
|
-
"o.value as o.name disable when o.unavailable for o in options",
|
|
889
|
-
"ng-model": "selected",
|
|
890
|
-
});
|
|
891
|
-
|
|
892
|
-
// Set the model to a disabled option
|
|
893
|
-
scope.$apply("selected = 1");
|
|
894
|
-
let options = element.querySelectorAll("option");
|
|
895
|
-
|
|
896
|
-
// jQuery returns null for val() when the option is disabled, see
|
|
897
|
-
// https://bugs.jquery.com/ticket/13097
|
|
898
|
-
expect(element.value).toBe("number:1");
|
|
899
|
-
expect(options.length).toEqual(4);
|
|
900
|
-
expect(options[0][0].selected).toEqual(false);
|
|
901
|
-
expect(options[1][0].selected).toEqual(true);
|
|
902
|
-
expect(options[2][0].selected).toEqual(false);
|
|
903
|
-
expect(options.eq(3)[0].selected).toEqual(false);
|
|
904
|
-
|
|
905
|
-
// Now enable that option
|
|
906
|
-
scope.$apply(() => {
|
|
907
|
-
scope.options[1].unavailable = false;
|
|
908
|
-
});
|
|
909
|
-
|
|
910
|
-
expect(element).toEqualSelectValue(1);
|
|
911
|
-
options = element.querySelectorAll("option");
|
|
912
|
-
expect(options.length).toEqual(4);
|
|
913
|
-
expect(options[1][0].selected).toEqual(true);
|
|
914
|
-
expect(options.eq(3)[0].selected).toEqual(false);
|
|
915
|
-
});
|
|
916
|
-
});
|
|
917
|
-
|
|
918
|
-
describe("on multi select", () => {
|
|
919
|
-
it("should disable options", () => {
|
|
920
|
-
scope.selected = [];
|
|
921
|
-
scope.options = [
|
|
922
|
-
{ name: "a", value: 0 },
|
|
923
|
-
{ name: "b", value: 1, unavailable: true },
|
|
924
|
-
{ name: "c", value: 2 },
|
|
925
|
-
{ name: "d", value: 3, unavailable: false },
|
|
926
|
-
];
|
|
927
|
-
createSelect({
|
|
928
|
-
"ng-options":
|
|
929
|
-
"o.value as o.name disable when o.unavailable for o in options",
|
|
930
|
-
multiple: true,
|
|
931
|
-
"ng-model": "selected",
|
|
932
|
-
});
|
|
933
|
-
const options = element.querySelectorAll("option");
|
|
934
|
-
|
|
935
|
-
expect(options[0][0].disabled).toEqual(false);
|
|
936
|
-
expect(options[1][0].disabled).toEqual(true);
|
|
937
|
-
expect(options[2][0].disabled).toEqual(false);
|
|
938
|
-
expect(options.eq(3)[0].disabled).toEqual(false);
|
|
939
|
-
});
|
|
940
|
-
|
|
941
|
-
it("should select disabled options when model changes", () => {
|
|
942
|
-
scope.options = [
|
|
943
|
-
{ name: "a", value: 0 },
|
|
944
|
-
{ name: "b", value: 1, unavailable: true },
|
|
945
|
-
{ name: "c", value: 2 },
|
|
946
|
-
{ name: "d", value: 3, unavailable: false },
|
|
947
|
-
];
|
|
948
|
-
createSelect({
|
|
949
|
-
"ng-options":
|
|
950
|
-
"o.value as o.name disable when o.unavailable for o in options",
|
|
951
|
-
multiple: true,
|
|
952
|
-
"ng-model": "selected",
|
|
953
|
-
});
|
|
954
|
-
|
|
955
|
-
// Initially the model is set to an enabled option
|
|
956
|
-
scope.$apply("selected = [3]");
|
|
957
|
-
let options = element.querySelectorAll("option");
|
|
958
|
-
expect(options[0][0].selected).toEqual(false);
|
|
959
|
-
expect(options[1][0].selected).toEqual(false);
|
|
960
|
-
expect(options[2][0].selected).toEqual(false);
|
|
961
|
-
expect(options.eq(3)[0].selected).toEqual(true);
|
|
962
|
-
|
|
963
|
-
// Now add a disabled option
|
|
964
|
-
scope.$apply("selected = [1,3]");
|
|
965
|
-
options = element.querySelectorAll("option");
|
|
966
|
-
expect(options[0][0].selected).toEqual(false);
|
|
967
|
-
expect(options[1][0].selected).toEqual(true);
|
|
968
|
-
expect(options[2][0].selected).toEqual(false);
|
|
969
|
-
expect(options.eq(3)[0].selected).toEqual(true);
|
|
970
|
-
|
|
971
|
-
// Now only select the disabled option
|
|
972
|
-
scope.$apply("selected = [1]");
|
|
973
|
-
expect(options[0][0].selected).toEqual(false);
|
|
974
|
-
expect(options[1][0].selected).toEqual(true);
|
|
975
|
-
expect(options[2][0].selected).toEqual(false);
|
|
976
|
-
expect(options.eq(3)[0].selected).toEqual(false);
|
|
977
|
-
});
|
|
978
|
-
|
|
979
|
-
it("should select options in model when they become enabled", () => {
|
|
980
|
-
scope.options = [
|
|
981
|
-
{ name: "a", value: 0 },
|
|
982
|
-
{ name: "b", value: 1, unavailable: true },
|
|
983
|
-
{ name: "c", value: 2 },
|
|
984
|
-
{ name: "d", value: 3, unavailable: false },
|
|
985
|
-
];
|
|
986
|
-
createSelect({
|
|
987
|
-
"ng-options":
|
|
988
|
-
"o.value as o.name disable when o.unavailable for o in options",
|
|
989
|
-
multiple: true,
|
|
990
|
-
"ng-model": "selected",
|
|
991
|
-
});
|
|
992
|
-
|
|
993
|
-
// Set the model to a disabled option
|
|
994
|
-
scope.$apply("selected = [1]");
|
|
995
|
-
let options = element.querySelectorAll("option");
|
|
996
|
-
|
|
997
|
-
expect(options[0][0].selected).toEqual(false);
|
|
998
|
-
expect(options[1][0].selected).toEqual(true);
|
|
999
|
-
expect(options[2][0].selected).toEqual(false);
|
|
1000
|
-
expect(options.eq(3)[0].selected).toEqual(false);
|
|
1001
|
-
|
|
1002
|
-
// Now enable that option
|
|
1003
|
-
scope.$apply(() => {
|
|
1004
|
-
scope.options[1].unavailable = false;
|
|
1005
|
-
});
|
|
1006
|
-
|
|
1007
|
-
expect(element).toEqualSelectValue([1], true);
|
|
1008
|
-
options = element.querySelectorAll("option");
|
|
1009
|
-
expect(options[0][0].selected).toEqual(false);
|
|
1010
|
-
expect(options[1][0].selected).toEqual(true);
|
|
1011
|
-
expect(options[2][0].selected).toEqual(false);
|
|
1012
|
-
expect(options.eq(3)[0].selected).toEqual(false);
|
|
1013
|
-
});
|
|
1014
|
-
});
|
|
1015
|
-
});
|
|
1016
|
-
|
|
1017
|
-
describe("selectAs expression", () => {
|
|
1018
|
-
beforeEach(() => {
|
|
1019
|
-
scope.arr = [
|
|
1020
|
-
{ id: 10, label: "ten" },
|
|
1021
|
-
{ id: 20, label: "twenty" },
|
|
1022
|
-
];
|
|
1023
|
-
scope.obj = {
|
|
1024
|
-
10: { score: 10, label: "ten" },
|
|
1025
|
-
20: { score: 20, label: "twenty" },
|
|
1026
|
-
};
|
|
1027
|
-
});
|
|
1028
|
-
|
|
1029
|
-
it("should support single select with array source", () => {
|
|
1030
|
-
createSelect({
|
|
1031
|
-
"ng-model": "selected",
|
|
1032
|
-
"ng-options": "item.id as item.label for item in arr",
|
|
1033
|
-
});
|
|
1034
|
-
|
|
1035
|
-
scope.$apply(() => {
|
|
1036
|
-
scope.selected = 10;
|
|
1037
|
-
});
|
|
1038
|
-
expect(element).toEqualSelectValue(10);
|
|
1039
|
-
|
|
1040
|
-
setSelectValue(element, 1);
|
|
1041
|
-
expect(scope.selected).toBe(20);
|
|
1042
|
-
});
|
|
1043
|
-
|
|
1044
|
-
it("should support multi select with array source", () => {
|
|
1045
|
-
createSelect({
|
|
1046
|
-
"ng-model": "selected",
|
|
1047
|
-
multiple: true,
|
|
1048
|
-
"ng-options": "item.id as item.label for item in arr",
|
|
1049
|
-
});
|
|
1050
|
-
|
|
1051
|
-
scope.$apply(() => {
|
|
1052
|
-
scope.selected = [10, 20];
|
|
1053
|
-
});
|
|
1054
|
-
expect(element).toEqualSelectValue([10, 20], true);
|
|
1055
|
-
expect(scope.selected).toEqual([10, 20]);
|
|
1056
|
-
|
|
1057
|
-
element.children()[0].selected = false;
|
|
1058
|
-
browserTrigger(element, "change");
|
|
1059
|
-
expect(scope.selected).toEqual([20]);
|
|
1060
|
-
expect(element).toEqualSelectValue([20], true);
|
|
1061
|
-
});
|
|
1062
|
-
|
|
1063
|
-
it("should re-render if an item in an array source is added/removed", () => {
|
|
1064
|
-
createSelect({
|
|
1065
|
-
"ng-model": "selected",
|
|
1066
|
-
multiple: true,
|
|
1067
|
-
"ng-options": "item.id as item.label for item in arr",
|
|
1068
|
-
});
|
|
1069
|
-
|
|
1070
|
-
scope.$apply(() => {
|
|
1071
|
-
scope.selected = [10];
|
|
1072
|
-
});
|
|
1073
|
-
expect(element).toEqualSelectValue([10], true);
|
|
1074
|
-
|
|
1075
|
-
scope.$apply(() => {
|
|
1076
|
-
scope.selected.push(20);
|
|
1077
|
-
});
|
|
1078
|
-
expect(element).toEqualSelectValue([10, 20], true);
|
|
1079
|
-
|
|
1080
|
-
scope.$apply(() => {
|
|
1081
|
-
scope.selected.shift();
|
|
1082
|
-
});
|
|
1083
|
-
expect(element).toEqualSelectValue([20], true);
|
|
1084
|
-
});
|
|
1085
|
-
|
|
1086
|
-
it("should handle a options containing circular references", () => {
|
|
1087
|
-
scope.arr[0].ref = scope.arr[0];
|
|
1088
|
-
scope.selected = [scope.arr[0]];
|
|
1089
|
-
createSelect({
|
|
1090
|
-
"ng-model": "selected",
|
|
1091
|
-
multiple: true,
|
|
1092
|
-
"ng-options": "item as item.label for item in arr",
|
|
1093
|
-
});
|
|
1094
|
-
expect(element).toEqualSelectValue([scope.arr[0]], true);
|
|
1095
|
-
|
|
1096
|
-
scope.$apply(() => {
|
|
1097
|
-
scope.selected.push(scope.arr[1]);
|
|
1098
|
-
});
|
|
1099
|
-
expect(element).toEqualSelectValue([scope.arr[0], scope.arr[1]], true);
|
|
1100
|
-
|
|
1101
|
-
scope.$apply(() => {
|
|
1102
|
-
scope.selected.pop();
|
|
1103
|
-
});
|
|
1104
|
-
expect(element).toEqualSelectValue([scope.arr[0]], true);
|
|
1105
|
-
});
|
|
1106
|
-
|
|
1107
|
-
it("should support single select with object source", () => {
|
|
1108
|
-
createSelect({
|
|
1109
|
-
"ng-model": "selected",
|
|
1110
|
-
"ng-options": "val.score as val.label for (key, val) in obj",
|
|
1111
|
-
});
|
|
1112
|
-
|
|
1113
|
-
scope.$apply(() => {
|
|
1114
|
-
scope.selected = 10;
|
|
1115
|
-
});
|
|
1116
|
-
expect(element).toEqualSelectValue(10);
|
|
1117
|
-
|
|
1118
|
-
setSelectValue(element, 1);
|
|
1119
|
-
expect(scope.selected).toBe(20);
|
|
1120
|
-
});
|
|
1121
|
-
|
|
1122
|
-
it("should support multi select with object source", () => {
|
|
1123
|
-
createSelect({
|
|
1124
|
-
"ng-model": "selected",
|
|
1125
|
-
multiple: true,
|
|
1126
|
-
"ng-options": "val.score as val.label for (key, val) in obj",
|
|
1127
|
-
});
|
|
1128
|
-
|
|
1129
|
-
scope.$apply(() => {
|
|
1130
|
-
scope.selected = [10, 20];
|
|
1131
|
-
});
|
|
1132
|
-
expect(element).toEqualSelectValue([10, 20], true);
|
|
1133
|
-
|
|
1134
|
-
element.children()[0].selected = false;
|
|
1135
|
-
browserTrigger(element, "change");
|
|
1136
|
-
expect(scope.selected).toEqual([20]);
|
|
1137
|
-
expect(element).toEqualSelectValue([20], true);
|
|
1138
|
-
});
|
|
1139
|
-
});
|
|
1140
|
-
|
|
1141
|
-
describe("trackBy expression", () => {
|
|
1142
|
-
beforeEach(() => {
|
|
1143
|
-
scope.arr = [
|
|
1144
|
-
{ id: 10, label: "ten" },
|
|
1145
|
-
{ id: 20, label: "twenty" },
|
|
1146
|
-
];
|
|
1147
|
-
scope.obj = {
|
|
1148
|
-
1: { score: 10, label: "ten" },
|
|
1149
|
-
2: { score: 20, label: "twenty" },
|
|
1150
|
-
};
|
|
1151
|
-
});
|
|
1152
|
-
|
|
1153
|
-
it("should set the result of track by expression to element value", () => {
|
|
1154
|
-
createSelect({
|
|
1155
|
-
"ng-model": "selected",
|
|
1156
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1157
|
-
});
|
|
1158
|
-
|
|
1159
|
-
expect(element.value).toEqualUnknownValue();
|
|
1160
|
-
|
|
1161
|
-
scope.$apply(() => {
|
|
1162
|
-
scope.selected = scope.arr[0];
|
|
1163
|
-
});
|
|
1164
|
-
expect(element.value).toBe("10");
|
|
1165
|
-
|
|
1166
|
-
scope.$apply(() => {
|
|
1167
|
-
scope.arr[0] = { id: 10, label: "new ten" };
|
|
1168
|
-
});
|
|
1169
|
-
expect(element.value).toBe("10");
|
|
1170
|
-
|
|
1171
|
-
element.children()[1].selected = "selected";
|
|
1172
|
-
browserTrigger(element, "change");
|
|
1173
|
-
expect(scope.selected).toEqual(scope.arr[1]);
|
|
1174
|
-
});
|
|
1175
|
-
|
|
1176
|
-
it("should use the tracked expression as option value", () => {
|
|
1177
|
-
createSelect({
|
|
1178
|
-
"ng-model": "selected",
|
|
1179
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1180
|
-
});
|
|
1181
|
-
|
|
1182
|
-
const options = element.querySelectorAll("option");
|
|
1183
|
-
expect(options.length).toEqual(3);
|
|
1184
|
-
expect(options[0]).toEqualUnknownOption();
|
|
1185
|
-
expect(options[1]).toEqualTrackedOption(10, "ten");
|
|
1186
|
-
expect(options[2]).toEqualTrackedOption(20, "twenty");
|
|
1187
|
-
});
|
|
1188
|
-
|
|
1189
|
-
it("should update the selected option even if only the tracked property on the selected object changes (single)", () => {
|
|
1190
|
-
createSelect({
|
|
1191
|
-
"ng-model": "selected",
|
|
1192
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1193
|
-
});
|
|
1194
|
-
|
|
1195
|
-
scope.$apply(() => {
|
|
1196
|
-
scope.selected = { id: 10, label: "ten" };
|
|
1197
|
-
});
|
|
1198
|
-
|
|
1199
|
-
expect(element.value).toEqual("10");
|
|
1200
|
-
|
|
1201
|
-
// Update the properties on the selected object, rather than replacing the whole object
|
|
1202
|
-
scope.$apply(() => {
|
|
1203
|
-
scope.selected.id = 20;
|
|
1204
|
-
scope.selected.label = "new twenty";
|
|
1205
|
-
});
|
|
1206
|
-
|
|
1207
|
-
// The value of the select should change since the id property changed
|
|
1208
|
-
expect(element.value).toEqual("20");
|
|
1209
|
-
|
|
1210
|
-
// But the label of the selected option does not change
|
|
1211
|
-
const option = element.querySelectorAll("option")[1];
|
|
1212
|
-
expect(option[0].selected).toEqual(true);
|
|
1213
|
-
expect(option.textContent).toEqual("twenty"); // not 'new twenty'
|
|
1214
|
-
});
|
|
1215
|
-
|
|
1216
|
-
it(
|
|
1217
|
-
"should update the selected options even if only the tracked properties on the objects in the " +
|
|
1218
|
-
"selected collection change (multi)",
|
|
1219
|
-
() => {
|
|
1220
|
-
createSelect({
|
|
1221
|
-
"ng-model": "selected",
|
|
1222
|
-
multiple: true,
|
|
1223
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1224
|
-
});
|
|
1225
|
-
|
|
1226
|
-
scope.$apply(() => {
|
|
1227
|
-
scope.selected = [{ id: 10, label: "ten" }];
|
|
1228
|
-
});
|
|
1229
|
-
|
|
1230
|
-
expect(element.value).toEqual(["10"]);
|
|
1231
|
-
|
|
1232
|
-
// Update the tracked property on the object in the selected array, rather than replacing the whole object
|
|
1233
|
-
scope.$apply(() => {
|
|
1234
|
-
scope.selected[0].id = 20;
|
|
1235
|
-
});
|
|
1236
|
-
|
|
1237
|
-
// The value of the select should change since the id property changed
|
|
1238
|
-
expect(element.value).toEqual(["20"]);
|
|
1239
|
-
|
|
1240
|
-
// But the label of the selected option does not change
|
|
1241
|
-
const option = element.querySelectorAll("option")[1];
|
|
1242
|
-
expect(option[0].selected).toEqual(true);
|
|
1243
|
-
expect(option.textContent).toEqual("twenty"); // not 'new twenty'
|
|
1244
|
-
},
|
|
1245
|
-
);
|
|
1246
|
-
|
|
1247
|
-
it("should prevent changes to the selected object from modifying the options objects (single)", () => {
|
|
1248
|
-
createSelect({
|
|
1249
|
-
"ng-model": "selected",
|
|
1250
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1251
|
-
});
|
|
1252
|
-
|
|
1253
|
-
element.value = "10";
|
|
1254
|
-
browserTrigger(element, "change");
|
|
1255
|
-
|
|
1256
|
-
expect(scope.selected).toEqual(scope.arr[0]);
|
|
1257
|
-
|
|
1258
|
-
scope.$apply(() => {
|
|
1259
|
-
scope.selected.id = 20;
|
|
1260
|
-
});
|
|
1261
|
-
|
|
1262
|
-
expect(scope.selected).not.toEqual(scope.arr[0]);
|
|
1263
|
-
expect(element.value).toEqual("20");
|
|
1264
|
-
expect(scope.arr).toEqual([
|
|
1265
|
-
{ id: 10, label: "ten" },
|
|
1266
|
-
{ id: 20, label: "twenty" },
|
|
1267
|
-
]);
|
|
1268
|
-
});
|
|
1269
|
-
|
|
1270
|
-
it("should preserve value even when reference has changed (single&array)", () => {
|
|
1271
|
-
createSelect({
|
|
1272
|
-
"ng-model": "selected",
|
|
1273
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1274
|
-
});
|
|
1275
|
-
|
|
1276
|
-
scope.$apply(() => {
|
|
1277
|
-
scope.selected = scope.arr[0];
|
|
1278
|
-
});
|
|
1279
|
-
expect(element.value).toBe("10");
|
|
1280
|
-
|
|
1281
|
-
scope.$apply(() => {
|
|
1282
|
-
scope.arr[0] = { id: 10, label: "new ten" };
|
|
1283
|
-
});
|
|
1284
|
-
expect(element.value).toBe("10");
|
|
1285
|
-
|
|
1286
|
-
element.children()[1].selected = 1;
|
|
1287
|
-
browserTrigger(element, "change");
|
|
1288
|
-
expect(scope.selected).toEqual(scope.arr[1]);
|
|
1289
|
-
});
|
|
1290
|
-
|
|
1291
|
-
it("should preserve value even when reference has changed (multi&array)", () => {
|
|
1292
|
-
createSelect({
|
|
1293
|
-
"ng-model": "selected",
|
|
1294
|
-
multiple: true,
|
|
1295
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1296
|
-
});
|
|
1297
|
-
|
|
1298
|
-
scope.$apply(() => {
|
|
1299
|
-
scope.selected = scope.arr;
|
|
1300
|
-
});
|
|
1301
|
-
expect(element.value).toEqual(["10", "20"]);
|
|
1302
|
-
|
|
1303
|
-
scope.$apply(() => {
|
|
1304
|
-
scope.arr[0] = { id: 10, label: "new ten" };
|
|
1305
|
-
});
|
|
1306
|
-
expect(element.value).toEqual(["10", "20"]);
|
|
1307
|
-
|
|
1308
|
-
element.children()[0].selected = false;
|
|
1309
|
-
browserTrigger(element, "change");
|
|
1310
|
-
expect(scope.selected).toEqual([scope.arr[1]]);
|
|
1311
|
-
});
|
|
1312
|
-
|
|
1313
|
-
it("should preserve value even when reference has changed (single&object)", () => {
|
|
1314
|
-
createSelect({
|
|
1315
|
-
"ng-model": "selected",
|
|
1316
|
-
"ng-options": "val.label for (key, val) in obj track by val.score",
|
|
1317
|
-
});
|
|
1318
|
-
|
|
1319
|
-
scope.$apply(() => {
|
|
1320
|
-
scope.selected = scope.obj["1"];
|
|
1321
|
-
});
|
|
1322
|
-
expect(element.value).toBe("10");
|
|
1323
|
-
|
|
1324
|
-
scope.$apply(() => {
|
|
1325
|
-
scope.obj["1"] = { score: 10, label: "ten" };
|
|
1326
|
-
});
|
|
1327
|
-
expect(element.value).toBe("10");
|
|
1328
|
-
|
|
1329
|
-
setSelectValue(element, 1);
|
|
1330
|
-
expect(scope.selected).toEqual(scope.obj["2"]);
|
|
1331
|
-
});
|
|
1332
|
-
|
|
1333
|
-
it("should preserve value even when reference has changed (multi&object)", () => {
|
|
1334
|
-
createSelect({
|
|
1335
|
-
"ng-model": "selected",
|
|
1336
|
-
multiple: true,
|
|
1337
|
-
"ng-options": "val.label for (key, val) in obj track by val.score",
|
|
1338
|
-
});
|
|
1339
|
-
|
|
1340
|
-
scope.$apply(() => {
|
|
1341
|
-
scope.selected = [scope.obj["1"]];
|
|
1342
|
-
});
|
|
1343
|
-
expect(element.value).toEqual(["10"]);
|
|
1344
|
-
|
|
1345
|
-
scope.$apply(() => {
|
|
1346
|
-
scope.obj["1"] = { score: 10, label: "ten" };
|
|
1347
|
-
});
|
|
1348
|
-
expect(element.value).toEqual(["10"]);
|
|
1349
|
-
|
|
1350
|
-
element.children()[1].selected = "selected";
|
|
1351
|
-
browserTrigger(element, "change");
|
|
1352
|
-
expect(scope.selected).toEqual([scope.obj["1"], scope.obj["2"]]);
|
|
1353
|
-
});
|
|
1354
|
-
|
|
1355
|
-
it("should prevent infinite digest if track by expression is stable", () => {
|
|
1356
|
-
scope.makeOptions = function () {
|
|
1357
|
-
const options = [];
|
|
1358
|
-
for (let i = 0; i < 5; i++) {
|
|
1359
|
-
options.push({ label: `Value = ${i}`, value: i });
|
|
1360
|
-
}
|
|
1361
|
-
return options;
|
|
1362
|
-
};
|
|
1363
|
-
scope.selected = { label: "Value = 1", value: 1 };
|
|
1364
|
-
expect(() => {
|
|
1365
|
-
createSelect({
|
|
1366
|
-
"ng-model": "selected",
|
|
1367
|
-
"ng-options":
|
|
1368
|
-
"item.label for item in makeOptions() track by item.value",
|
|
1369
|
-
});
|
|
1370
|
-
}).not.toThrow();
|
|
1371
|
-
});
|
|
1372
|
-
|
|
1373
|
-
it("should re-render if the tracked property of the model is changed when using trackBy", () => {
|
|
1374
|
-
createSelect({
|
|
1375
|
-
"ng-model": "selected",
|
|
1376
|
-
"ng-options": "item for item in arr track by item.id",
|
|
1377
|
-
});
|
|
1378
|
-
|
|
1379
|
-
scope.$apply(() => {
|
|
1380
|
-
scope.selected = { id: 10, label: "ten" };
|
|
1381
|
-
});
|
|
1382
|
-
|
|
1383
|
-
spyOn(element.controller("ngModel"), "$render");
|
|
1384
|
-
|
|
1385
|
-
scope.$apply(() => {
|
|
1386
|
-
scope.arr[0].id = 20;
|
|
1387
|
-
});
|
|
1388
|
-
|
|
1389
|
-
// update render due to equality watch
|
|
1390
|
-
expect(element.controller("ngModel").$render).toHaveBeenCalled();
|
|
1391
|
-
});
|
|
1392
|
-
|
|
1393
|
-
it("should not set view value again if the tracked property of the model has not changed when using trackBy", () => {
|
|
1394
|
-
createSelect({
|
|
1395
|
-
"ng-model": "selected",
|
|
1396
|
-
"ng-options": "item for item in arr track by item.id",
|
|
1397
|
-
});
|
|
1398
|
-
|
|
1399
|
-
scope.$apply(() => {
|
|
1400
|
-
scope.selected = { id: 10, label: "ten" };
|
|
1401
|
-
});
|
|
1402
|
-
|
|
1403
|
-
spyOn(element.controller("ngModel"), "$setViewValue");
|
|
1404
|
-
|
|
1405
|
-
scope.$apply(() => {
|
|
1406
|
-
scope.arr[0] = { id: 10, label: "ten" };
|
|
1407
|
-
});
|
|
1408
|
-
|
|
1409
|
-
expect(
|
|
1410
|
-
element.controller("ngModel").$setViewValue,
|
|
1411
|
-
).not.toHaveBeenCalled();
|
|
1412
|
-
});
|
|
1413
|
-
|
|
1414
|
-
it("should not re-render if a property of the model is changed when not using trackBy", () => {
|
|
1415
|
-
createSelect({
|
|
1416
|
-
"ng-model": "selected",
|
|
1417
|
-
"ng-options": "item for item in arr",
|
|
1418
|
-
});
|
|
1419
|
-
|
|
1420
|
-
scope.$apply(() => {
|
|
1421
|
-
scope.selected = scope.arr[0];
|
|
1422
|
-
});
|
|
1423
|
-
|
|
1424
|
-
spyOn(element.controller("ngModel"), "$render");
|
|
1425
|
-
|
|
1426
|
-
scope.$apply(() => {
|
|
1427
|
-
scope.selected.label = "changed";
|
|
1428
|
-
});
|
|
1429
|
-
|
|
1430
|
-
// no render update as no equality watch
|
|
1431
|
-
expect(element.controller("ngModel").$render).not.toHaveBeenCalled();
|
|
1432
|
-
});
|
|
1433
|
-
|
|
1434
|
-
it("should handle options containing circular references (single)", () => {
|
|
1435
|
-
scope.arr[0].ref = scope.arr[0];
|
|
1436
|
-
createSelect({
|
|
1437
|
-
"ng-model": "selected",
|
|
1438
|
-
"ng-options": "item for item in arr track by item.id",
|
|
1439
|
-
});
|
|
1440
|
-
|
|
1441
|
-
expect(() => {
|
|
1442
|
-
scope.$apply(() => {
|
|
1443
|
-
scope.selected = scope.arr[0];
|
|
1444
|
-
});
|
|
1445
|
-
}).not.toThrow();
|
|
1446
|
-
});
|
|
1447
|
-
|
|
1448
|
-
it("should handle options containing circular references (multiple)", () => {
|
|
1449
|
-
scope.arr[0].ref = scope.arr[0];
|
|
1450
|
-
createSelect({
|
|
1451
|
-
"ng-model": "selected",
|
|
1452
|
-
multiple: true,
|
|
1453
|
-
"ng-options": "item for item in arr track by item.id",
|
|
1454
|
-
});
|
|
1455
|
-
|
|
1456
|
-
expect(() => {
|
|
1457
|
-
scope.$apply(() => {
|
|
1458
|
-
scope.selected = [scope.arr[0]];
|
|
1459
|
-
});
|
|
1460
|
-
|
|
1461
|
-
scope.$apply(() => {
|
|
1462
|
-
scope.selected.push(scope.arr[1]);
|
|
1463
|
-
});
|
|
1464
|
-
}).not.toThrow();
|
|
1465
|
-
});
|
|
1466
|
-
|
|
1467
|
-
it('should remove the "selected" attribute when the model changes', () => {
|
|
1468
|
-
createSelect({
|
|
1469
|
-
"ng-model": "selected",
|
|
1470
|
-
"ng-options": "item.label for item in arr track by item.id",
|
|
1471
|
-
});
|
|
1472
|
-
|
|
1473
|
-
const options = element.querySelectorAll("option");
|
|
1474
|
-
element.selectedIndex = 2;
|
|
1475
|
-
element.dispatchEvent(new Event("change"));
|
|
1476
|
-
expect(scope.selected).toEqual(scope.arr[1]);
|
|
1477
|
-
|
|
1478
|
-
scope.selected = {};
|
|
1479
|
-
expect(options[0].selected).toBeTrue();
|
|
1480
|
-
expect(options[1].selected).not.toBeTrue();
|
|
1481
|
-
expect(options[2].selected).not.toBeTrue();
|
|
1482
|
-
});
|
|
1483
|
-
});
|
|
1484
|
-
|
|
1485
|
-
/**
|
|
1486
|
-
* This behavior is broken and should probably be cleaned up later as track by and select as
|
|
1487
|
-
* aren't compatible.
|
|
1488
|
-
*/
|
|
1489
|
-
describe("selectAs+trackBy expression", () => {
|
|
1490
|
-
beforeEach(() => {
|
|
1491
|
-
scope.arr = [
|
|
1492
|
-
{ subItem: { label: "ten", id: 10 } },
|
|
1493
|
-
{ subItem: { label: "twenty", id: 20 } },
|
|
1494
|
-
];
|
|
1495
|
-
scope.obj = {
|
|
1496
|
-
10: { subItem: { id: 10, label: "ten" } },
|
|
1497
|
-
20: { subItem: { id: 20, label: "twenty" } },
|
|
1498
|
-
};
|
|
1499
|
-
});
|
|
1500
|
-
|
|
1501
|
-
it(
|
|
1502
|
-
'It should use the "value" variable to represent items in the array as well as for the ' +
|
|
1503
|
-
"selected values in track by expression (single&array)",
|
|
1504
|
-
() => {
|
|
1505
|
-
createSelect({
|
|
1506
|
-
"ng-model": "selected",
|
|
1507
|
-
"ng-options":
|
|
1508
|
-
"item.subItem as item.subItem.label for item in arr track by (item.id || item.subItem.id)",
|
|
1509
|
-
});
|
|
1510
|
-
|
|
1511
|
-
// First test model -> view
|
|
1512
|
-
|
|
1513
|
-
scope.$apply(() => {
|
|
1514
|
-
scope.selected = scope.arr[0].subItem;
|
|
1515
|
-
});
|
|
1516
|
-
expect(element.value).toEqual("10");
|
|
1517
|
-
|
|
1518
|
-
scope.$apply(() => {
|
|
1519
|
-
scope.selected = scope.arr[1].subItem;
|
|
1520
|
-
});
|
|
1521
|
-
expect(element.value).toEqual("20");
|
|
1522
|
-
|
|
1523
|
-
// Now test view -> model
|
|
1524
|
-
|
|
1525
|
-
element.value = "10";
|
|
1526
|
-
browserTrigger(element, "change");
|
|
1527
|
-
expect(scope.selected).toEqual(scope.arr[0].subItem);
|
|
1528
|
-
|
|
1529
|
-
// Now reload the array
|
|
1530
|
-
scope.$apply(() => {
|
|
1531
|
-
scope.arr = [
|
|
1532
|
-
{
|
|
1533
|
-
subItem: { label: "new ten", id: 10 },
|
|
1534
|
-
},
|
|
1535
|
-
{
|
|
1536
|
-
subItem: { label: "new twenty", id: 20 },
|
|
1537
|
-
},
|
|
1538
|
-
];
|
|
1539
|
-
});
|
|
1540
|
-
expect(element.value).toBe("10");
|
|
1541
|
-
expect(scope.selected.id).toBe(10);
|
|
1542
|
-
},
|
|
1543
|
-
);
|
|
1544
|
-
|
|
1545
|
-
it(
|
|
1546
|
-
'It should use the "value" variable to represent items in the array as well as for the ' +
|
|
1547
|
-
"selected values in track by expression (multiple&array)",
|
|
1548
|
-
() => {
|
|
1549
|
-
createSelect({
|
|
1550
|
-
"ng-model": "selected",
|
|
1551
|
-
multiple: true,
|
|
1552
|
-
"ng-options":
|
|
1553
|
-
"item.subItem as item.subItem.label for item in arr track by (item.id || item.subItem.id)",
|
|
1554
|
-
});
|
|
1555
|
-
|
|
1556
|
-
// First test model -> view
|
|
1557
|
-
|
|
1558
|
-
scope.$apply(() => {
|
|
1559
|
-
scope.selected = [scope.arr[0].subItem];
|
|
1560
|
-
});
|
|
1561
|
-
expect(element.value).toEqual(["10"]);
|
|
1562
|
-
|
|
1563
|
-
scope.$apply(() => {
|
|
1564
|
-
scope.selected = [scope.arr[1].subItem];
|
|
1565
|
-
});
|
|
1566
|
-
expect(element.value).toEqual(["20"]);
|
|
1567
|
-
|
|
1568
|
-
// Now test view -> model
|
|
1569
|
-
|
|
1570
|
-
element.querySelectorAll("option")[0].selected = true;
|
|
1571
|
-
element.querySelectorAll("option")[1].selected = false;
|
|
1572
|
-
browserTrigger(element, "change");
|
|
1573
|
-
expect(scope.selected).toEqual([scope.arr[0].subItem]);
|
|
1574
|
-
|
|
1575
|
-
// Now reload the array
|
|
1576
|
-
scope.$apply(() => {
|
|
1577
|
-
scope.arr = [
|
|
1578
|
-
{
|
|
1579
|
-
subItem: { label: "new ten", id: 10 },
|
|
1580
|
-
},
|
|
1581
|
-
{
|
|
1582
|
-
subItem: { label: "new twenty", id: 20 },
|
|
1583
|
-
},
|
|
1584
|
-
];
|
|
1585
|
-
});
|
|
1586
|
-
expect(element.value).toEqual(["10"]);
|
|
1587
|
-
expect(scope.selected[0].id).toEqual(10);
|
|
1588
|
-
expect(scope.selected.length).toBe(1);
|
|
1589
|
-
},
|
|
1590
|
-
);
|
|
1591
|
-
|
|
1592
|
-
it(
|
|
1593
|
-
'It should use the "value" variable to represent items in the array as well as for the ' +
|
|
1594
|
-
"selected values in track by expression (multiple&object)",
|
|
1595
|
-
() => {
|
|
1596
|
-
createSelect({
|
|
1597
|
-
"ng-model": "selected",
|
|
1598
|
-
multiple: true,
|
|
1599
|
-
"ng-options":
|
|
1600
|
-
"val.subItem as val.subItem.label for (key, val) in obj track by (val.id || val.subItem.id)",
|
|
1601
|
-
});
|
|
1602
|
-
|
|
1603
|
-
// First test model -> view
|
|
1604
|
-
|
|
1605
|
-
scope.$apply(() => {
|
|
1606
|
-
scope.selected = [scope.obj["10"].subItem];
|
|
1607
|
-
});
|
|
1608
|
-
expect(element.value).toEqual(["10"]);
|
|
1609
|
-
|
|
1610
|
-
scope.$apply(() => {
|
|
1611
|
-
scope.selected = [scope.obj["10"].subItem];
|
|
1612
|
-
});
|
|
1613
|
-
expect(element.value).toEqual(["10"]);
|
|
1614
|
-
|
|
1615
|
-
// Now test view -> model
|
|
1616
|
-
|
|
1617
|
-
element.querySelectorAll("option")[0].selected = true;
|
|
1618
|
-
element.querySelectorAll("option")[1].selected = false;
|
|
1619
|
-
browserTrigger(element, "change");
|
|
1620
|
-
expect(scope.selected).toEqual([scope.obj["10"].subItem]);
|
|
1621
|
-
|
|
1622
|
-
// Now reload the object
|
|
1623
|
-
scope.$apply(() => {
|
|
1624
|
-
scope.obj = {
|
|
1625
|
-
10: {
|
|
1626
|
-
subItem: { label: "new ten", id: 10 },
|
|
1627
|
-
},
|
|
1628
|
-
20: {
|
|
1629
|
-
subItem: { label: "new twenty", id: 20 },
|
|
1630
|
-
},
|
|
1631
|
-
};
|
|
1632
|
-
});
|
|
1633
|
-
expect(element.value).toEqual(["10"]);
|
|
1634
|
-
expect(scope.selected[0].id).toBe(10);
|
|
1635
|
-
expect(scope.selected.length).toBe(1);
|
|
1636
|
-
},
|
|
1637
|
-
);
|
|
1638
|
-
|
|
1639
|
-
it(
|
|
1640
|
-
'It should use the "value" variable to represent items in the array as well as for the ' +
|
|
1641
|
-
"selected values in track by expression (single&object)",
|
|
1642
|
-
() => {
|
|
1643
|
-
createSelect({
|
|
1644
|
-
"ng-model": "selected",
|
|
1645
|
-
"ng-options":
|
|
1646
|
-
"val.subItem as val.subItem.label for (key, val) in obj track by (val.id || val.subItem.id)",
|
|
1647
|
-
});
|
|
1648
|
-
|
|
1649
|
-
// First test model -> view
|
|
1650
|
-
|
|
1651
|
-
scope.$apply(() => {
|
|
1652
|
-
scope.selected = scope.obj["10"].subItem;
|
|
1653
|
-
});
|
|
1654
|
-
expect(element.value).toEqual("10");
|
|
1655
|
-
|
|
1656
|
-
scope.$apply(() => {
|
|
1657
|
-
scope.selected = scope.obj["10"].subItem;
|
|
1658
|
-
});
|
|
1659
|
-
expect(element.value).toEqual("10");
|
|
1660
|
-
|
|
1661
|
-
// Now test view -> model
|
|
1662
|
-
|
|
1663
|
-
element.querySelectorAll("option")[0].selected = true;
|
|
1664
|
-
browserTrigger(element, "change");
|
|
1665
|
-
expect(scope.selected).toEqual(scope.obj["10"].subItem);
|
|
1666
|
-
|
|
1667
|
-
// Now reload the object
|
|
1668
|
-
scope.$apply(() => {
|
|
1669
|
-
scope.obj = {
|
|
1670
|
-
10: {
|
|
1671
|
-
subItem: { label: "new ten", id: 10 },
|
|
1672
|
-
},
|
|
1673
|
-
20: {
|
|
1674
|
-
subItem: { label: "new twenty", id: 20 },
|
|
1675
|
-
},
|
|
1676
|
-
};
|
|
1677
|
-
});
|
|
1678
|
-
expect(element.value).toEqual("10");
|
|
1679
|
-
expect(scope.selected.id).toBe(10);
|
|
1680
|
-
},
|
|
1681
|
-
);
|
|
1682
|
-
});
|
|
1683
|
-
|
|
1684
|
-
describe("binding", () => {
|
|
1685
|
-
it("should bind to scope value", () => {
|
|
1686
|
-
element.innerHTML =
|
|
1687
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
1688
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
1689
|
-
scope = injector.get("$rootScope");
|
|
1690
|
-
|
|
1691
|
-
scope.$apply(() => {
|
|
1692
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
1693
|
-
scope.selected = scope.values[0];
|
|
1694
|
-
});
|
|
1695
|
-
|
|
1696
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
1697
|
-
|
|
1698
|
-
scope.$apply(() => {
|
|
1699
|
-
scope.selected = scope.values[1];
|
|
1700
|
-
});
|
|
1701
|
-
|
|
1702
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
1703
|
-
});
|
|
1704
|
-
|
|
1705
|
-
it("should bind to scope value and group", () => {
|
|
1706
|
-
createSelect({
|
|
1707
|
-
"ng-model": "selected",
|
|
1708
|
-
"ng-options": "item.name group by item.group for item in values",
|
|
1709
|
-
});
|
|
1710
|
-
|
|
1711
|
-
scope.$apply(() => {
|
|
1712
|
-
scope.values = [
|
|
1713
|
-
{ name: "A" },
|
|
1714
|
-
{ name: "B", group: 0 },
|
|
1715
|
-
{ name: "C", group: "first" },
|
|
1716
|
-
{ name: "D", group: "second" },
|
|
1717
|
-
{ name: "E", group: 0 },
|
|
1718
|
-
{ name: "F", group: "first" },
|
|
1719
|
-
{ name: "G", group: "second" },
|
|
1720
|
-
];
|
|
1721
|
-
scope.selected = scope.values[3];
|
|
1722
|
-
});
|
|
1723
|
-
|
|
1724
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
1725
|
-
|
|
1726
|
-
const optgroups = element.querySelectorAll("optgroup");
|
|
1727
|
-
expect(optgroups.length).toBe(3);
|
|
1728
|
-
|
|
1729
|
-
const zero = optgroups[0];
|
|
1730
|
-
const b = zero.querySelector("option")[0];
|
|
1731
|
-
const e = zero.querySelector("option")[1];
|
|
1732
|
-
expect(zero.getAttribute("label")).toEqual("0");
|
|
1733
|
-
expect(b.textContent).toEqual("B");
|
|
1734
|
-
expect(e.textContent).toEqual("E");
|
|
1735
|
-
|
|
1736
|
-
const first = optgroups[1];
|
|
1737
|
-
const c = first.querySelector("option")[0];
|
|
1738
|
-
const f = first.querySelector("option")[1];
|
|
1739
|
-
expect(first.getAttribute("label")).toEqual("first");
|
|
1740
|
-
expect(c.textContent).toEqual("C");
|
|
1741
|
-
expect(f.textContent).toEqual("F");
|
|
1742
|
-
|
|
1743
|
-
const second = optgroups[2];
|
|
1744
|
-
const d = second.querySelector("option")[0];
|
|
1745
|
-
const g = second.querySelector("option")[1];
|
|
1746
|
-
expect(second.getAttribute("label")).toEqual("second");
|
|
1747
|
-
expect(d.textContent).toEqual("D");
|
|
1748
|
-
expect(g.textContent).toEqual("G");
|
|
1749
|
-
|
|
1750
|
-
scope.$apply(() => {
|
|
1751
|
-
scope.selected = scope.values[0];
|
|
1752
|
-
});
|
|
1753
|
-
|
|
1754
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
1755
|
-
});
|
|
1756
|
-
|
|
1757
|
-
it("should group when the options are available on compile time", () => {
|
|
1758
|
-
scope.values = [
|
|
1759
|
-
{ name: "C", group: "first" },
|
|
1760
|
-
{ name: "D", group: "second" },
|
|
1761
|
-
{ name: "F", group: "first" },
|
|
1762
|
-
{ name: "G", group: "second" },
|
|
1763
|
-
];
|
|
1764
|
-
scope.selected = scope.values[3];
|
|
1765
|
-
|
|
1766
|
-
createSelect({
|
|
1767
|
-
"ng-model": "selected",
|
|
1768
|
-
"ng-options":
|
|
1769
|
-
"item as item.name group by item.group for item in values",
|
|
1770
|
-
});
|
|
1771
|
-
|
|
1772
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
1773
|
-
|
|
1774
|
-
const optgroups = element.querySelectorAll("optgroup");
|
|
1775
|
-
expect(optgroups.length).toBe(2);
|
|
1776
|
-
|
|
1777
|
-
const first = optgroups[0];
|
|
1778
|
-
const c = first.querySelector("option")[0];
|
|
1779
|
-
const f = first.querySelector("option")[1];
|
|
1780
|
-
expect(first.getAttribute("label")).toEqual("first");
|
|
1781
|
-
expect(c.textContent).toEqual("C");
|
|
1782
|
-
expect(f.textContent).toEqual("F");
|
|
1783
|
-
|
|
1784
|
-
const second = optgroups[1];
|
|
1785
|
-
const d = second.querySelector("option")[0];
|
|
1786
|
-
const g = second.querySelector("option")[1];
|
|
1787
|
-
expect(second.getAttribute("label")).toEqual("second");
|
|
1788
|
-
expect(d.textContent).toEqual("D");
|
|
1789
|
-
expect(g.textContent).toEqual("G");
|
|
1790
|
-
|
|
1791
|
-
scope.$apply(() => {
|
|
1792
|
-
scope.selected = scope.values[0];
|
|
1793
|
-
});
|
|
1794
|
-
|
|
1795
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
1796
|
-
});
|
|
1797
|
-
|
|
1798
|
-
it("should group when the options are updated", () => {
|
|
1799
|
-
let optgroups;
|
|
1800
|
-
let one;
|
|
1801
|
-
let two;
|
|
1802
|
-
let three;
|
|
1803
|
-
let alpha;
|
|
1804
|
-
let beta;
|
|
1805
|
-
let gamma;
|
|
1806
|
-
let delta;
|
|
1807
|
-
let epsilon;
|
|
1808
|
-
|
|
1809
|
-
createSelect({
|
|
1810
|
-
"ng-model": "selected",
|
|
1811
|
-
"ng-options": "i.name group by i.cls for i in list",
|
|
1812
|
-
});
|
|
1813
|
-
|
|
1814
|
-
scope.list = [
|
|
1815
|
-
{ cls: "one", name: "Alpha" },
|
|
1816
|
-
{ cls: "one", name: "Beta" },
|
|
1817
|
-
{ cls: "two", name: "Gamma" },
|
|
1818
|
-
];
|
|
1819
|
-
optgroups = element.querySelectorAll("optgroup");
|
|
1820
|
-
expect(optgroups.length).toBe(2);
|
|
1821
|
-
|
|
1822
|
-
one = optgroups[0];
|
|
1823
|
-
expect(one.children("option").length).toBe(2);
|
|
1824
|
-
|
|
1825
|
-
alpha = one.querySelector("option")[0];
|
|
1826
|
-
beta = one.querySelector("option")[1];
|
|
1827
|
-
expect(one.getAttribute("label")).toEqual("one");
|
|
1828
|
-
expect(alpha.textContent).toEqual("Alpha");
|
|
1829
|
-
expect(beta.textContent).toEqual("Beta");
|
|
1830
|
-
|
|
1831
|
-
two = optgroups[1];
|
|
1832
|
-
expect(two.children("option").length).toBe(1);
|
|
1833
|
-
|
|
1834
|
-
gamma = two.querySelector("option")[0];
|
|
1835
|
-
expect(two.getAttribute("label")).toEqual("two");
|
|
1836
|
-
expect(gamma.textContent).toEqual("Gamma");
|
|
1837
|
-
|
|
1838
|
-
// Remove item from first group, add item to second group, add new group
|
|
1839
|
-
scope.list.shift();
|
|
1840
|
-
scope.list.push(
|
|
1841
|
-
{ cls: "two", name: "Delta" },
|
|
1842
|
-
{ cls: "three", name: "Epsilon" },
|
|
1843
|
-
);
|
|
1844
|
-
optgroups = element.querySelectorAll("optgroup");
|
|
1845
|
-
expect(optgroups.length).toBe(3);
|
|
1846
|
-
|
|
1847
|
-
// Group with removed item
|
|
1848
|
-
one = optgroups[0];
|
|
1849
|
-
expect(one.children("option").length).toBe(1);
|
|
1850
|
-
|
|
1851
|
-
beta = one.querySelector("option")[0];
|
|
1852
|
-
expect(one.getAttribute("label")).toEqual("one");
|
|
1853
|
-
expect(beta.textContent).toEqual("Beta");
|
|
1854
|
-
|
|
1855
|
-
// Group with new item
|
|
1856
|
-
two = optgroups[1];
|
|
1857
|
-
expect(two.children("option").length).toBe(2);
|
|
1858
|
-
|
|
1859
|
-
gamma = two.querySelector("option")[0];
|
|
1860
|
-
expect(two.getAttribute("label")).toEqual("two");
|
|
1861
|
-
expect(gamma.textContent).toEqual("Gamma");
|
|
1862
|
-
delta = two.querySelector("option")[1];
|
|
1863
|
-
expect(two.getAttribute("label")).toEqual("two");
|
|
1864
|
-
expect(delta.textContent).toEqual("Delta");
|
|
1865
|
-
|
|
1866
|
-
// New group
|
|
1867
|
-
three = optgroups[2];
|
|
1868
|
-
expect(three.children("option").length).toBe(1);
|
|
1869
|
-
|
|
1870
|
-
epsilon = three.querySelector("option")[0];
|
|
1871
|
-
expect(three.getAttribute("label")).toEqual("three");
|
|
1872
|
-
expect(epsilon.textContent).toEqual("Epsilon");
|
|
1873
|
-
});
|
|
1874
|
-
|
|
1875
|
-
it("should place non-grouped items in the list where they appear", () => {
|
|
1876
|
-
createSelect({
|
|
1877
|
-
"ng-model": "selected",
|
|
1878
|
-
"ng-options": "item.name group by item.group for item in values",
|
|
1879
|
-
});
|
|
1880
|
-
|
|
1881
|
-
scope.$apply(() => {
|
|
1882
|
-
scope.values = [
|
|
1883
|
-
{ name: "A" },
|
|
1884
|
-
{ name: "B", group: "first" },
|
|
1885
|
-
{ name: "C", group: "second" },
|
|
1886
|
-
{ name: "D" },
|
|
1887
|
-
{ name: "E", group: "first" },
|
|
1888
|
-
{ name: "F" },
|
|
1889
|
-
{ name: "G" },
|
|
1890
|
-
{ name: "H", group: "second" },
|
|
1891
|
-
];
|
|
1892
|
-
scope.selected = scope.values[0];
|
|
1893
|
-
});
|
|
1894
|
-
|
|
1895
|
-
const children = element.children();
|
|
1896
|
-
expect(children.length).toEqual(6);
|
|
1897
|
-
|
|
1898
|
-
expect(children[0].nodeName.toLowerCase()).toEqual("option");
|
|
1899
|
-
expect(children[1].nodeName.toLowerCase()).toEqual("optgroup");
|
|
1900
|
-
expect(children[2].nodeName.toLowerCase()).toEqual("optgroup");
|
|
1901
|
-
expect(children[3].nodeName.toLowerCase()).toEqual("option");
|
|
1902
|
-
expect(children[4].nodeName.toLowerCase()).toEqual("option");
|
|
1903
|
-
expect(children[5].nodeName.toLowerCase()).toEqual("option");
|
|
1904
|
-
});
|
|
1905
|
-
|
|
1906
|
-
it("should group if the group has a falsy value (except undefined)", () => {
|
|
1907
|
-
createSelect({
|
|
1908
|
-
"ng-model": "selected",
|
|
1909
|
-
"ng-options": "item.name group by item.group for item in values",
|
|
1910
|
-
});
|
|
1911
|
-
|
|
1912
|
-
scope.$apply(() => {
|
|
1913
|
-
scope.values = [
|
|
1914
|
-
{ name: "A" },
|
|
1915
|
-
{ name: "B", group: "" },
|
|
1916
|
-
{ name: "C", group: null },
|
|
1917
|
-
{ name: "D", group: false },
|
|
1918
|
-
{ name: "E", group: 0 },
|
|
1919
|
-
];
|
|
1920
|
-
scope.selected = scope.values[0];
|
|
1921
|
-
});
|
|
1922
|
-
|
|
1923
|
-
const optgroups = element.querySelectorAll("optgroup");
|
|
1924
|
-
const options = element.querySelectorAll("option");
|
|
1925
|
-
|
|
1926
|
-
expect(optgroups.length).toEqual(4);
|
|
1927
|
-
expect(options.length).toEqual(5);
|
|
1928
|
-
|
|
1929
|
-
expect(optgroups[0].label).toBe("");
|
|
1930
|
-
expect(optgroups[1].label).toBe("null");
|
|
1931
|
-
expect(optgroups[2].label).toBe("false");
|
|
1932
|
-
expect(optgroups[3].label).toBe("0");
|
|
1933
|
-
|
|
1934
|
-
expect(options[0].textContent).toBe("A");
|
|
1935
|
-
expect(options[0].parentNode).toBe(element);
|
|
1936
|
-
|
|
1937
|
-
expect(options[1].textContent).toBe("B");
|
|
1938
|
-
expect(options[1].parentNode).toBe(optgroups[0]);
|
|
1939
|
-
|
|
1940
|
-
expect(options[2].textContent).toBe("C");
|
|
1941
|
-
expect(options[2].parentNode).toBe(optgroups[1]);
|
|
1942
|
-
|
|
1943
|
-
expect(options[3].textContent).toBe("D");
|
|
1944
|
-
expect(options[3].parentNode).toBe(optgroups[2]);
|
|
1945
|
-
|
|
1946
|
-
expect(options[4].textContent).toBe("E");
|
|
1947
|
-
expect(options[4].parentNode).toBe(optgroups[3]);
|
|
1948
|
-
});
|
|
1949
|
-
|
|
1950
|
-
it("should not duplicate a group with a falsy value when the options are updated", () => {
|
|
1951
|
-
scope.$apply(() => {
|
|
1952
|
-
scope.values = [
|
|
1953
|
-
{ value: "A", group: "" },
|
|
1954
|
-
{ value: "B", group: "First" },
|
|
1955
|
-
];
|
|
1956
|
-
scope.selected = scope.values[0];
|
|
1957
|
-
});
|
|
1958
|
-
|
|
1959
|
-
createSelect({
|
|
1960
|
-
"ng-model": "selected",
|
|
1961
|
-
"ng-options": "item.value group by item.group for item in values",
|
|
1962
|
-
});
|
|
1963
|
-
|
|
1964
|
-
scope.$apply(() => {
|
|
1965
|
-
scope.values.push({ value: "C", group: false });
|
|
1966
|
-
});
|
|
1967
|
-
|
|
1968
|
-
const optgroups = element.querySelectorAll("optgroup");
|
|
1969
|
-
const options = element.querySelectorAll("option");
|
|
1970
|
-
|
|
1971
|
-
expect(optgroups.length).toEqual(3);
|
|
1972
|
-
expect(options.length).toEqual(3);
|
|
1973
|
-
|
|
1974
|
-
expect(optgroups[0].label).toBe("");
|
|
1975
|
-
expect(optgroups[1].label).toBe("First");
|
|
1976
|
-
expect(optgroups[2].label).toBe("false");
|
|
1977
|
-
|
|
1978
|
-
expect(options[0].textContent).toBe("A");
|
|
1979
|
-
expect(options[0].parentNode).toBe(optgroups[0]);
|
|
1980
|
-
|
|
1981
|
-
expect(options[1].textContent).toBe("B");
|
|
1982
|
-
expect(options[1].parentNode).toBe(optgroups[1]);
|
|
1983
|
-
|
|
1984
|
-
expect(options[2].textContent).toBe("C");
|
|
1985
|
-
expect(options[2].parentNode).toBe(optgroups[2]);
|
|
1986
|
-
});
|
|
1987
|
-
|
|
1988
|
-
it("should bind to scope value and track/identify objects", () => {
|
|
1989
|
-
createSelect({
|
|
1990
|
-
"ng-model": "selected",
|
|
1991
|
-
"ng-options": "item.name for item in values track by item.id",
|
|
1992
|
-
});
|
|
1993
|
-
|
|
1994
|
-
scope.$apply(() => {
|
|
1995
|
-
scope.values = [
|
|
1996
|
-
{ id: 1, name: "first" },
|
|
1997
|
-
{ id: 2, name: "second" },
|
|
1998
|
-
{ id: 3, name: "third" },
|
|
1999
|
-
{ id: 4, name: "forth" },
|
|
2000
|
-
];
|
|
2001
|
-
scope.selected = scope.values[1];
|
|
2002
|
-
});
|
|
2003
|
-
|
|
2004
|
-
expect(element.value).toEqual("2");
|
|
2005
|
-
|
|
2006
|
-
const first = element.querySelectorAll("option")[0];
|
|
2007
|
-
expect(first.textContent).toEqual("first");
|
|
2008
|
-
expect(first.getAttribute("value")).toEqual("1");
|
|
2009
|
-
const forth = element.querySelectorAll("option")[3];
|
|
2010
|
-
expect(forth.textContent).toEqual("forth");
|
|
2011
|
-
expect(forth.getAttribute("value")).toEqual("4");
|
|
2012
|
-
|
|
2013
|
-
scope.$apply(() => {
|
|
2014
|
-
scope.selected = scope.values[3];
|
|
2015
|
-
});
|
|
2016
|
-
|
|
2017
|
-
expect(element.value).toEqual("4");
|
|
2018
|
-
});
|
|
2019
|
-
|
|
2020
|
-
it("should bind to scope value through expression", () => {
|
|
2021
|
-
createSelect({
|
|
2022
|
-
"ng-model": "selected",
|
|
2023
|
-
"ng-options": "item.id as item.name for item in values",
|
|
2024
|
-
});
|
|
2025
|
-
|
|
2026
|
-
scope.$apply(() => {
|
|
2027
|
-
scope.values = [
|
|
2028
|
-
{ id: 10, name: "A" },
|
|
2029
|
-
{ id: 20, name: "B" },
|
|
2030
|
-
];
|
|
2031
|
-
scope.selected = scope.values[0].id;
|
|
2032
|
-
});
|
|
2033
|
-
|
|
2034
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2035
|
-
|
|
2036
|
-
scope.$apply(() => {
|
|
2037
|
-
scope.selected = scope.values[1].id;
|
|
2038
|
-
});
|
|
2039
|
-
|
|
2040
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2041
|
-
});
|
|
2042
|
-
|
|
2043
|
-
it("should update options in the DOM", () => {
|
|
2044
|
-
compile(
|
|
2045
|
-
'<select ng-model="selected" ng-options="item.id as item.name for item in values"></select>',
|
|
2046
|
-
);
|
|
2047
|
-
|
|
2048
|
-
scope.$apply(() => {
|
|
2049
|
-
scope.values = [
|
|
2050
|
-
{ id: 10, name: "A" },
|
|
2051
|
-
{ id: 20, name: "B" },
|
|
2052
|
-
];
|
|
2053
|
-
scope.selected = scope.values[0].id;
|
|
2054
|
-
});
|
|
2055
|
-
|
|
2056
|
-
scope.$apply(() => {
|
|
2057
|
-
scope.values[0].name = "C";
|
|
2058
|
-
});
|
|
2059
|
-
|
|
2060
|
-
const options = element.querySelectorAll("option");
|
|
2061
|
-
expect(options.length).toEqual(2);
|
|
2062
|
-
expect(options[0]).toEqualOption(10, "C");
|
|
2063
|
-
expect(options[1]).toEqualOption(20, "B");
|
|
2064
|
-
});
|
|
2065
|
-
|
|
2066
|
-
it("should update options in the DOM from object source", () => {
|
|
2067
|
-
compile(
|
|
2068
|
-
'<select ng-model="selected" ng-options="val.id as val.name for (key, val) in values"></select>',
|
|
2069
|
-
);
|
|
2070
|
-
|
|
2071
|
-
scope.$apply(() => {
|
|
2072
|
-
scope.values = { a: { id: 10, name: "A" }, b: { id: 20, name: "B" } };
|
|
2073
|
-
scope.selected = scope.values.a.id;
|
|
2074
|
-
});
|
|
2075
|
-
|
|
2076
|
-
scope.$apply(() => {
|
|
2077
|
-
scope.values.a.name = "C";
|
|
2078
|
-
});
|
|
2079
|
-
|
|
2080
|
-
const options = element.querySelectorAll("option");
|
|
2081
|
-
expect(options.length).toEqual(2);
|
|
2082
|
-
expect(options[0]).toEqualOption(10, "C");
|
|
2083
|
-
expect(options[1]).toEqualOption(20, "B");
|
|
2084
|
-
});
|
|
2085
|
-
|
|
2086
|
-
it("should bind to object key", () => {
|
|
2087
|
-
createSelect({
|
|
2088
|
-
"ng-model": "selected",
|
|
2089
|
-
"ng-options": "key as value for (key, value) in object",
|
|
2090
|
-
});
|
|
2091
|
-
|
|
2092
|
-
scope.$apply(() => {
|
|
2093
|
-
scope.object = { red: "FF0000", green: "00FF00", blue: "0000FF" };
|
|
2094
|
-
scope.selected = "green";
|
|
2095
|
-
});
|
|
2096
|
-
|
|
2097
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2098
|
-
|
|
2099
|
-
scope.$apply(() => {
|
|
2100
|
-
scope.selected = "blue";
|
|
2101
|
-
});
|
|
2102
|
-
|
|
2103
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2104
|
-
});
|
|
2105
|
-
|
|
2106
|
-
it("should bind to object value", () => {
|
|
2107
|
-
createSelect({
|
|
2108
|
-
"ng-model": "selected",
|
|
2109
|
-
"ng-options": "value as key for (key, value) in object",
|
|
2110
|
-
});
|
|
2111
|
-
|
|
2112
|
-
scope.$apply(() => {
|
|
2113
|
-
scope.object = { red: "FF0000", green: "00FF00", blue: "0000FF" };
|
|
2114
|
-
scope.selected = "00FF00";
|
|
2115
|
-
});
|
|
2116
|
-
|
|
2117
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2118
|
-
|
|
2119
|
-
scope.$apply(() => {
|
|
2120
|
-
scope.selected = "0000FF";
|
|
2121
|
-
});
|
|
2122
|
-
|
|
2123
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2124
|
-
});
|
|
2125
|
-
|
|
2126
|
-
it("should bind to object disabled", () => {
|
|
2127
|
-
scope.selected = 30;
|
|
2128
|
-
scope.options = [
|
|
2129
|
-
{ name: "white", value: "#FFFFFF" },
|
|
2130
|
-
{ name: "one", value: 1, unavailable: true },
|
|
2131
|
-
{ name: "notTrue", value: false },
|
|
2132
|
-
{ name: "thirty", value: 30, unavailable: false },
|
|
2133
|
-
];
|
|
2134
|
-
createSelect({
|
|
2135
|
-
"ng-options":
|
|
2136
|
-
"o.value as o.name disable when o.unavailable for o in options",
|
|
2137
|
-
"ng-model": "selected",
|
|
2138
|
-
});
|
|
2139
|
-
|
|
2140
|
-
let options = element.querySelectorAll("option");
|
|
2141
|
-
|
|
2142
|
-
expect(scope.options[1].unavailable).toEqual(true);
|
|
2143
|
-
expect(options[1][0].disabled).toEqual(true);
|
|
2144
|
-
|
|
2145
|
-
scope.$apply(() => {
|
|
2146
|
-
scope.options[1].unavailable = false;
|
|
2147
|
-
});
|
|
2148
|
-
|
|
2149
|
-
options = element.querySelectorAll("option");
|
|
2150
|
-
|
|
2151
|
-
expect(scope.options[1].unavailable).toEqual(false);
|
|
2152
|
-
expect(options[1][0].disabled).toEqual(false);
|
|
2153
|
-
});
|
|
2154
|
-
|
|
2155
|
-
it("should insert the unknown option if bound to null", () => {
|
|
2156
|
-
element.innerHTML =
|
|
2157
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
2158
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2159
|
-
scope = injector.get("$rootScope");
|
|
2160
|
-
|
|
2161
|
-
scope.$apply(() => {
|
|
2162
|
-
scope.values = [{ name: "A" }];
|
|
2163
|
-
scope.selected = null;
|
|
2164
|
-
});
|
|
2165
|
-
|
|
2166
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2167
|
-
expect(element.value).toEqual("?");
|
|
2168
|
-
expect(element.querySelectorAll("option")[0].value).toEqual("?");
|
|
2169
|
-
|
|
2170
|
-
scope.$apply(() => {
|
|
2171
|
-
scope.selected = scope.values[0];
|
|
2172
|
-
});
|
|
2173
|
-
|
|
2174
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2175
|
-
expect(element.querySelectorAll("option").length).toEqual(1);
|
|
2176
|
-
});
|
|
2177
|
-
|
|
2178
|
-
it("should select the provided empty option if bound to null", () => {
|
|
2179
|
-
element.innerHTML =
|
|
2180
|
-
'<select ng-model="selected" ng-options="value.name for value in values"><option value="">blank</option></select>';
|
|
2181
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2182
|
-
scope = injector.get("$rootScope");
|
|
2183
|
-
|
|
2184
|
-
scope.$apply(() => {
|
|
2185
|
-
scope.values = [{ name: "A" }];
|
|
2186
|
-
scope.selected = null;
|
|
2187
|
-
});
|
|
2188
|
-
|
|
2189
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2190
|
-
expect(element.value).toEqual("");
|
|
2191
|
-
expect(element.querySelectorAll("option")[0].value).toEqual("");
|
|
2192
|
-
|
|
2193
|
-
scope.$apply(() => {
|
|
2194
|
-
scope.selected = scope.values[0];
|
|
2195
|
-
});
|
|
2196
|
-
|
|
2197
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2198
|
-
expect(element.querySelectorAll("option")[0].value).toEqual("");
|
|
2199
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2200
|
-
});
|
|
2201
|
-
|
|
2202
|
-
it("should reuse blank option if bound to null", () => {
|
|
2203
|
-
element.innerHTML =
|
|
2204
|
-
'<select ng-model="selected" ng-options="value.name for value in values"><option value="">blank</option></select>';
|
|
2205
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2206
|
-
scope = injector.get("$rootScope");
|
|
2207
|
-
|
|
2208
|
-
scope.$apply(() => {
|
|
2209
|
-
scope.values = [{ name: "A" }];
|
|
2210
|
-
scope.selected = null;
|
|
2211
|
-
});
|
|
2212
|
-
|
|
2213
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2214
|
-
expect(element.value).toEqual("");
|
|
2215
|
-
expect(element.querySelectorAll("option")[0].value).toEqual("");
|
|
2216
|
-
|
|
2217
|
-
scope.$apply(() => {
|
|
2218
|
-
scope.selected = scope.values[0];
|
|
2219
|
-
});
|
|
2220
|
-
|
|
2221
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2222
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2223
|
-
});
|
|
2224
|
-
|
|
2225
|
-
it("should not insert a blank option if one of the options maps to null", () => {
|
|
2226
|
-
createSelect({
|
|
2227
|
-
"ng-model": "myColor",
|
|
2228
|
-
"ng-options": "color.shade as color.name for color in colors",
|
|
2229
|
-
});
|
|
2230
|
-
|
|
2231
|
-
scope.$apply(() => {
|
|
2232
|
-
scope.colors = [
|
|
2233
|
-
{ name: "nothing", shade: null },
|
|
2234
|
-
{ name: "red", shade: "dark" },
|
|
2235
|
-
];
|
|
2236
|
-
scope.myColor = null;
|
|
2237
|
-
});
|
|
2238
|
-
|
|
2239
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2240
|
-
expect(element.querySelectorAll("option")[0]).toEqualOption(null);
|
|
2241
|
-
expect(element.value).not.toEqualUnknownValue(null);
|
|
2242
|
-
expect(element.querySelectorAll("option")[0]).not.toEqualUnknownOption(
|
|
2243
|
-
null,
|
|
2244
|
-
);
|
|
2245
|
-
});
|
|
2246
|
-
|
|
2247
|
-
it("should insert a unknown option if bound to something not in the list", () => {
|
|
2248
|
-
element.innerHTML =
|
|
2249
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
2250
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2251
|
-
scope = injector.get("$rootScope");
|
|
2252
|
-
|
|
2253
|
-
scope.$apply(() => {
|
|
2254
|
-
scope.values = [{ name: "A" }];
|
|
2255
|
-
scope.selected = {};
|
|
2256
|
-
});
|
|
2257
|
-
|
|
2258
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2259
|
-
expect(element.value).toEqualUnknownValue(scope.selected);
|
|
2260
|
-
expect(element.querySelectorAll("option")[0]).toEqualUnknownOption(
|
|
2261
|
-
scope.selected,
|
|
2262
|
-
);
|
|
2263
|
-
|
|
2264
|
-
scope.$apply(() => {
|
|
2265
|
-
scope.selected = scope.values[0];
|
|
2266
|
-
});
|
|
2267
|
-
|
|
2268
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2269
|
-
expect(element.querySelectorAll("option").length).toEqual(1);
|
|
2270
|
-
});
|
|
2271
|
-
|
|
2272
|
-
it(
|
|
2273
|
-
"should insert and select temporary unknown option when no options-model match, empty " +
|
|
2274
|
-
"option is present and model is defined",
|
|
2275
|
-
() => {
|
|
2276
|
-
scope.selected = "C";
|
|
2277
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2278
|
-
element.innerHTML =
|
|
2279
|
-
'<select ng-model="selected" ng-options="value.name for value in values"><option value="">blank</option></select>';
|
|
2280
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2281
|
-
scope = injector.get("$rootScope");
|
|
2282
|
-
|
|
2283
|
-
expect(element.value).toBe("?");
|
|
2284
|
-
expect(element.length).toBe(4);
|
|
2285
|
-
|
|
2286
|
-
scope.$apply("selected = values[1]");
|
|
2287
|
-
|
|
2288
|
-
expect(element.value).not.toBe("");
|
|
2289
|
-
expect(element.length).toBe(3);
|
|
2290
|
-
},
|
|
2291
|
-
);
|
|
2292
|
-
|
|
2293
|
-
it('should select correct input if previously selected option was "?"', () => {
|
|
2294
|
-
element.innerHTML =
|
|
2295
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
2296
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2297
|
-
scope = injector.get("$rootScope");
|
|
2298
|
-
|
|
2299
|
-
scope.$apply(() => {
|
|
2300
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2301
|
-
scope.selected = {};
|
|
2302
|
-
});
|
|
2303
|
-
|
|
2304
|
-
expect(element.querySelectorAll("option").length).toEqual(3);
|
|
2305
|
-
expect(element.value).toEqualUnknownValue();
|
|
2306
|
-
expect(element.querySelectorAll("option")[0]).toEqualUnknownOption();
|
|
2307
|
-
|
|
2308
|
-
setSelectValue(element, 1);
|
|
2309
|
-
|
|
2310
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2311
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2312
|
-
expect(element.querySelectorAll("option")[0][0].selected).toBeTruthy();
|
|
2313
|
-
});
|
|
2314
|
-
|
|
2315
|
-
it("should remove unknown option when empty option exists and model is undefined", () => {
|
|
2316
|
-
scope.selected = "C";
|
|
2317
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2318
|
-
element.innerHTML =
|
|
2319
|
-
'<select ng-model="selected" ng-options="value.name for value in values"><option value="">blank</option></select>';
|
|
2320
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2321
|
-
scope = injector.get("$rootScope");
|
|
2322
|
-
|
|
2323
|
-
expect(element.value).toBe("?");
|
|
2324
|
-
|
|
2325
|
-
scope.selected = undefined;
|
|
2326
|
-
expect(element.value).toBe("");
|
|
2327
|
-
});
|
|
2328
|
-
|
|
2329
|
-
it('should ensure that at least one option element has the "selected" attribute', () => {
|
|
2330
|
-
createSelect({
|
|
2331
|
-
"ng-model": "selected",
|
|
2332
|
-
"ng-options": "item.id as item.name for item in values",
|
|
2333
|
-
});
|
|
2334
|
-
|
|
2335
|
-
scope.$apply(() => {
|
|
2336
|
-
scope.values = [
|
|
2337
|
-
{ id: 10, name: "A" },
|
|
2338
|
-
{ id: 20, name: "B" },
|
|
2339
|
-
];
|
|
2340
|
-
});
|
|
2341
|
-
expect(element.value).toEqualUnknownValue();
|
|
2342
|
-
expect(
|
|
2343
|
-
element.querySelectorAll("option")[0].getAttribute("selected"),
|
|
2344
|
-
).toEqual("selected");
|
|
2345
|
-
|
|
2346
|
-
scope.$apply(() => {
|
|
2347
|
-
scope.selected = 10;
|
|
2348
|
-
});
|
|
2349
|
-
// Here the ? option should disappear and the first real option should have selected attribute
|
|
2350
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2351
|
-
expect(
|
|
2352
|
-
element.querySelectorAll("option")[0].getAttribute("selected"),
|
|
2353
|
-
).toEqual("selected");
|
|
2354
|
-
|
|
2355
|
-
// Here the selected value is changed and we change the selected attribute
|
|
2356
|
-
scope.$apply(() => {
|
|
2357
|
-
scope.selected = 20;
|
|
2358
|
-
});
|
|
2359
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2360
|
-
expect(
|
|
2361
|
-
element.querySelectorAll("option")[1].getAttribute("selected"),
|
|
2362
|
-
).toEqual("selected");
|
|
2363
|
-
|
|
2364
|
-
scope.$apply(() => {
|
|
2365
|
-
scope.values.push({ id: 30, name: "C" });
|
|
2366
|
-
});
|
|
2367
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2368
|
-
expect(
|
|
2369
|
-
element.querySelectorAll("option")[1].getAttribute("selected"),
|
|
2370
|
-
).toEqual("selected");
|
|
2371
|
-
|
|
2372
|
-
// Here the ? option should reappear and have selected attribute
|
|
2373
|
-
scope.$apply(() => {
|
|
2374
|
-
scope.selected = undefined;
|
|
2375
|
-
});
|
|
2376
|
-
expect(element.value).toEqualUnknownValue();
|
|
2377
|
-
expect(
|
|
2378
|
-
element.querySelectorAll("option")[0].getAttribute("selected"),
|
|
2379
|
-
).toEqual("selected");
|
|
2380
|
-
});
|
|
2381
|
-
|
|
2382
|
-
it("should select the correct option for selectAs and falsy values", () => {
|
|
2383
|
-
scope.values = [
|
|
2384
|
-
{ value: 0, label: "zero" },
|
|
2385
|
-
{ value: 1, label: "one" },
|
|
2386
|
-
];
|
|
2387
|
-
scope.selected = "";
|
|
2388
|
-
createSelect({
|
|
2389
|
-
"ng-model": "selected",
|
|
2390
|
-
"ng-options": "option.value as option.label for option in values",
|
|
2391
|
-
});
|
|
2392
|
-
|
|
2393
|
-
const option = element.querySelectorAll("option")[0];
|
|
2394
|
-
expect(option).toEqualUnknownOption();
|
|
2395
|
-
});
|
|
2396
|
-
|
|
2397
|
-
it("should update the model if the selected option is removed", () => {
|
|
2398
|
-
scope.values = [
|
|
2399
|
-
{ value: 0, label: "zero" },
|
|
2400
|
-
{ value: 1, label: "one" },
|
|
2401
|
-
];
|
|
2402
|
-
scope.selected = 1;
|
|
2403
|
-
createSelect({
|
|
2404
|
-
"ng-model": "selected",
|
|
2405
|
-
"ng-options": "option.value as option.label for option in values",
|
|
2406
|
-
});
|
|
2407
|
-
expect(element).toEqualSelectValue(1);
|
|
2408
|
-
|
|
2409
|
-
// Check after initial option update
|
|
2410
|
-
scope.$apply(() => {
|
|
2411
|
-
scope.values.pop();
|
|
2412
|
-
});
|
|
2413
|
-
|
|
2414
|
-
expect(element.value).toEqual("?");
|
|
2415
|
-
expect(scope.selected).toEqual(null);
|
|
2416
|
-
|
|
2417
|
-
// Check after model change
|
|
2418
|
-
scope.$apply(() => {
|
|
2419
|
-
scope.selected = 0;
|
|
2420
|
-
});
|
|
2421
|
-
|
|
2422
|
-
expect(element).toEqualSelectValue(0);
|
|
2423
|
-
|
|
2424
|
-
scope.$apply(() => {
|
|
2425
|
-
scope.values.pop();
|
|
2426
|
-
});
|
|
2427
|
-
|
|
2428
|
-
expect(element.value).toEqual("?");
|
|
2429
|
-
expect(scope.selected).toEqual(null);
|
|
2430
|
-
});
|
|
2431
|
-
|
|
2432
|
-
it("should update the model if all the selected (multiple) options are removed", () => {
|
|
2433
|
-
scope.values = [
|
|
2434
|
-
{ value: 0, label: "zero" },
|
|
2435
|
-
{ value: 1, label: "one" },
|
|
2436
|
-
{ value: 2, label: "two" },
|
|
2437
|
-
];
|
|
2438
|
-
scope.selected = [1, 2];
|
|
2439
|
-
createSelect({
|
|
2440
|
-
"ng-model": "selected",
|
|
2441
|
-
multiple: true,
|
|
2442
|
-
"ng-options": "option.value as option.label for option in values",
|
|
2443
|
-
});
|
|
2444
|
-
|
|
2445
|
-
expect(element).toEqualSelectValue([1, 2], true);
|
|
2446
|
-
|
|
2447
|
-
// Check after initial option update
|
|
2448
|
-
scope.$apply(() => {
|
|
2449
|
-
scope.values.pop();
|
|
2450
|
-
});
|
|
2451
|
-
|
|
2452
|
-
expect(element).toEqualSelectValue([1], true);
|
|
2453
|
-
expect(scope.selected).toEqual([1]);
|
|
2454
|
-
|
|
2455
|
-
scope.$apply(() => {
|
|
2456
|
-
scope.values.pop();
|
|
2457
|
-
});
|
|
2458
|
-
|
|
2459
|
-
expect(element).toEqualSelectValue([], true);
|
|
2460
|
-
expect(scope.selected).toEqual([]);
|
|
2461
|
-
|
|
2462
|
-
// Check after model change
|
|
2463
|
-
scope.$apply(() => {
|
|
2464
|
-
scope.selected = [0];
|
|
2465
|
-
});
|
|
2466
|
-
|
|
2467
|
-
expect(element).toEqualSelectValue([0], true);
|
|
2468
|
-
|
|
2469
|
-
scope.$apply(() => {
|
|
2470
|
-
scope.values.pop();
|
|
2471
|
-
});
|
|
2472
|
-
|
|
2473
|
-
expect(element).toEqualSelectValue([], true);
|
|
2474
|
-
expect(scope.selected).toEqual([]);
|
|
2475
|
-
});
|
|
2476
|
-
});
|
|
2477
|
-
|
|
2478
|
-
describe("empty option", () => {
|
|
2479
|
-
it("should be compiled as template, be watched and updated", () => {
|
|
2480
|
-
let option;
|
|
2481
|
-
createSingleSelect('<option value="">blank is {{blankVal}}</option>');
|
|
2482
|
-
|
|
2483
|
-
scope.$apply(() => {
|
|
2484
|
-
scope.blankVal = "so blank";
|
|
2485
|
-
scope.values = [{ name: "A" }];
|
|
2486
|
-
});
|
|
2487
|
-
|
|
2488
|
-
// check blank option is first and is compiled
|
|
2489
|
-
expect(element.querySelectorAll("option").length).toBe(2);
|
|
2490
|
-
option = element.querySelectorAll("option")[0];
|
|
2491
|
-
expect(option.value).toBe("");
|
|
2492
|
-
expect(option.textContent).toBe("blank is so blank");
|
|
2493
|
-
|
|
2494
|
-
scope.$apply(() => {
|
|
2495
|
-
scope.blankVal = "not so blank";
|
|
2496
|
-
});
|
|
2497
|
-
|
|
2498
|
-
// check blank option is first and is compiled
|
|
2499
|
-
expect(element.querySelectorAll("option").length).toBe(2);
|
|
2500
|
-
option = element.querySelectorAll("option")[0];
|
|
2501
|
-
expect(option.value).toBe("");
|
|
2502
|
-
expect(option.textContent).toBe("blank is not so blank");
|
|
2503
|
-
});
|
|
2504
|
-
|
|
2505
|
-
it("should support binding via ngBindTemplate directive", () => {
|
|
2506
|
-
let option;
|
|
2507
|
-
createSingleSelect(
|
|
2508
|
-
'<option value="" ng-bind-template="blank is {{blankVal}}"></option>',
|
|
2509
|
-
);
|
|
2510
|
-
|
|
2511
|
-
scope.$apply(() => {
|
|
2512
|
-
scope.blankVal = "so blank";
|
|
2513
|
-
scope.values = [{ name: "A" }];
|
|
2514
|
-
});
|
|
2515
|
-
|
|
2516
|
-
// check blank option is first and is compiled
|
|
2517
|
-
expect(element.querySelectorAll("option").length).toBe(2);
|
|
2518
|
-
option = element.querySelectorAll("option")[0];
|
|
2519
|
-
expect(option.value).toBe("");
|
|
2520
|
-
expect(option.textContent).toBe("blank is so blank");
|
|
2521
|
-
});
|
|
2522
|
-
|
|
2523
|
-
it("should support binding via ngBind attribute", () => {
|
|
2524
|
-
let option;
|
|
2525
|
-
createSingleSelect('<option value="" ng-bind="blankVal"></option>');
|
|
2526
|
-
|
|
2527
|
-
scope.$apply(() => {
|
|
2528
|
-
scope.blankVal = "is blank";
|
|
2529
|
-
scope.values = [{ name: "A" }];
|
|
2530
|
-
});
|
|
2531
|
-
|
|
2532
|
-
// check blank option is first and is compiled
|
|
2533
|
-
expect(element.querySelectorAll("option").length).toBe(2);
|
|
2534
|
-
option = element.querySelectorAll("option")[0];
|
|
2535
|
-
expect(option.value).toBe("");
|
|
2536
|
-
expect(option.textContent).toBe("is blank");
|
|
2537
|
-
});
|
|
2538
|
-
|
|
2539
|
-
it("should be ignored when it has no value attribute", () => {
|
|
2540
|
-
// The option value is set to the textContent if there's no value attribute,
|
|
2541
|
-
// so in that case it doesn't count as a blank option
|
|
2542
|
-
createSingleSelect("<option>--select--</option>");
|
|
2543
|
-
scope.$apply(() => {
|
|
2544
|
-
scope.values = [{ name: "A" }, { name: "B" }, { name: "C" }];
|
|
2545
|
-
});
|
|
2546
|
-
|
|
2547
|
-
const options = element.querySelectorAll("option");
|
|
2548
|
-
|
|
2549
|
-
expect(options[0]).toEqualUnknownOption();
|
|
2550
|
-
expect(options[1]).toEqualOption(scope.values[0], "A");
|
|
2551
|
-
expect(options[2]).toEqualOption(scope.values[1], "B");
|
|
2552
|
-
expect(options.eq(3)).toEqualOption(scope.values[2], "C");
|
|
2553
|
-
});
|
|
2554
|
-
|
|
2555
|
-
it("should be rendered with the attributes preserved", () => {
|
|
2556
|
-
let option;
|
|
2557
|
-
createSingleSelect(
|
|
2558
|
-
'<option value="" class="coyote" id="road-runner" ' +
|
|
2559
|
-
'custom-attr="custom-attr">{{blankVal}}</option>',
|
|
2560
|
-
);
|
|
2561
|
-
|
|
2562
|
-
scope.$apply(() => {
|
|
2563
|
-
scope.blankVal = "is blank";
|
|
2564
|
-
});
|
|
2565
|
-
|
|
2566
|
-
// check blank option is first and is compiled
|
|
2567
|
-
option = element.querySelectorAll("option")[0];
|
|
2568
|
-
expect(option[0].classList.contains("coyote")).toBeTruthy();
|
|
2569
|
-
expect(option.getAttribute("id")).toBe("road-runner");
|
|
2570
|
-
expect(option.getAttribute("custom-attr")).toBe("custom-attr");
|
|
2571
|
-
});
|
|
2572
|
-
|
|
2573
|
-
it("should be selected, if it is available and no other option is selected", () => {
|
|
2574
|
-
// selectedIndex is used here because JQLite incorrectly reports element.value
|
|
2575
|
-
scope.$apply(() => {
|
|
2576
|
-
scope.values = [{ name: "A" }];
|
|
2577
|
-
});
|
|
2578
|
-
element.innerHTML =
|
|
2579
|
-
'<select ng-model="selected" ng-options="value.name for value in values"><option value="">blank</option></select>';
|
|
2580
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2581
|
-
scope = injector.get("$rootScope");
|
|
2582
|
-
// ensure the first option (the blank option) is selected
|
|
2583
|
-
expect(element.selectedIndex).toEqual(0);
|
|
2584
|
-
// ensure the option has not changed following the digest
|
|
2585
|
-
expect(element.selectedIndex).toEqual(0);
|
|
2586
|
-
});
|
|
2587
|
-
|
|
2588
|
-
it("should be selectable if select is multiple", () => {
|
|
2589
|
-
createMultiSelect(true);
|
|
2590
|
-
|
|
2591
|
-
// select the empty option
|
|
2592
|
-
setSelectValue(element, 0);
|
|
2593
|
-
|
|
2594
|
-
// ensure selection and correct binding
|
|
2595
|
-
expect(element.selectedIndex).toEqual(0);
|
|
2596
|
-
expect(scope.selected).toEqual([]);
|
|
2597
|
-
});
|
|
2598
|
-
|
|
2599
|
-
it("should be possible to use ngIf in the blank option", () => {
|
|
2600
|
-
let option;
|
|
2601
|
-
createSingleSelect('<option ng-if="isBlank" value="">blank</option>');
|
|
2602
|
-
|
|
2603
|
-
scope.$apply(() => {
|
|
2604
|
-
scope.values = [{ name: "A" }];
|
|
2605
|
-
scope.isBlank = true;
|
|
2606
|
-
});
|
|
2607
|
-
|
|
2608
|
-
expect(element.value).toBe("");
|
|
2609
|
-
|
|
2610
|
-
scope.$apply("isBlank = false");
|
|
2611
|
-
|
|
2612
|
-
expect(element.value).toBe("?");
|
|
2613
|
-
|
|
2614
|
-
scope.$apply("isBlank = true");
|
|
2615
|
-
|
|
2616
|
-
expect(element.value).toBe("");
|
|
2617
|
-
});
|
|
2618
|
-
|
|
2619
|
-
it("should be possible to use ngIf in the blank option when values are available upon linking", () => {
|
|
2620
|
-
let options;
|
|
2621
|
-
|
|
2622
|
-
scope.values = [{ name: "A" }];
|
|
2623
|
-
createSingleSelect('<option ng-if="isBlank" value="">blank</option>');
|
|
2624
|
-
|
|
2625
|
-
scope.$apply("isBlank = true");
|
|
2626
|
-
|
|
2627
|
-
options = element.querySelectorAll("option");
|
|
2628
|
-
expect(options.length).toBe(2);
|
|
2629
|
-
expect(options[0].value).toBe("");
|
|
2630
|
-
expect(options[0].textContent).toBe("blank");
|
|
2631
|
-
|
|
2632
|
-
scope.$apply("isBlank = false");
|
|
2633
|
-
|
|
2634
|
-
expect(element.value).toBe("?");
|
|
2635
|
-
});
|
|
2636
|
-
|
|
2637
|
-
it("should select the correct option after linking when the ngIf expression is initially falsy", () => {
|
|
2638
|
-
scope.values = [{ name: "black" }, { name: "white" }, { name: "red" }];
|
|
2639
|
-
scope.selected = scope.values[2];
|
|
2640
|
-
|
|
2641
|
-
expect(() => {
|
|
2642
|
-
createSingleSelect('<option ng-if="isBlank" value="">blank</option>');
|
|
2643
|
-
scope.$apply();
|
|
2644
|
-
}).not.toThrow();
|
|
2645
|
-
|
|
2646
|
-
expect(element.querySelectorAll("option")[2].selected).toBe(true);
|
|
2647
|
-
expect(linkLog).toEqual(["linkNgOptions"]);
|
|
2648
|
-
});
|
|
2649
|
-
|
|
2650
|
-
it('should add / remove the "selected" attribute on empty option which has an initially falsy ngIf expression', () => {
|
|
2651
|
-
scope.values = [{ name: "black" }, { name: "white" }, { name: "red" }];
|
|
2652
|
-
scope.selected = scope.values[2];
|
|
2653
|
-
|
|
2654
|
-
createSingleSelect('<option ng-if="isBlank" value="">blank</option>');
|
|
2655
|
-
scope.$apply();
|
|
2656
|
-
|
|
2657
|
-
expect(element.querySelectorAll("option")[2].selected).toBe(true);
|
|
2658
|
-
|
|
2659
|
-
scope.$apply("isBlank = true");
|
|
2660
|
-
expect(element.querySelectorAll("option")[0].value).toBe("");
|
|
2661
|
-
expect(element.querySelectorAll("option")[0].selected).toBe(false);
|
|
2662
|
-
|
|
2663
|
-
scope.$apply("selected = null");
|
|
2664
|
-
expect(element.querySelectorAll("option")[0].value).toBe("");
|
|
2665
|
-
expect(element.querySelectorAll("option")[0].selected).toBe(true);
|
|
2666
|
-
|
|
2667
|
-
scope.selected = scope.values[1];
|
|
2668
|
-
scope.$apply();
|
|
2669
|
-
expect(element.querySelectorAll("option")[0].value).toBe("");
|
|
2670
|
-
expect(element.querySelectorAll("option")[0].selected).toBe(false);
|
|
2671
|
-
expect(element.querySelectorAll("option")[2].selected).toBe(true);
|
|
2672
|
-
});
|
|
2673
|
-
|
|
2674
|
-
it('should add / remove the "selected" attribute on empty option which has an initially truthy ngIf expression when no option is selected', () => {
|
|
2675
|
-
scope.values = [{ name: "black" }, { name: "white" }, { name: "red" }];
|
|
2676
|
-
scope.isBlank = true;
|
|
2677
|
-
|
|
2678
|
-
createSingleSelect('<option ng-if="isBlank" value="">blank</option>');
|
|
2679
|
-
scope.$apply();
|
|
2680
|
-
|
|
2681
|
-
expect(element.querySelectorAll("option")[0].value).toBe("");
|
|
2682
|
-
expect(element.querySelectorAll("option")[0].selected).toBe(true);
|
|
2683
|
-
scope.selected = scope.values[2];
|
|
2684
|
-
scope.$apply();
|
|
2685
|
-
expect(element.querySelectorAll("option")[0].selected).toBe(false);
|
|
2686
|
-
expect(element.querySelectorAll("option")[3].selected).toBe(true);
|
|
2687
|
-
});
|
|
2688
|
-
|
|
2689
|
-
it('should add the "selected" attribute on empty option which has an initially falsy ngIf expression when no option is selected', () => {
|
|
2690
|
-
scope.values = [{ name: "black" }, { name: "white" }, { name: "red" }];
|
|
2691
|
-
|
|
2692
|
-
createSingleSelect('<option ng-if="isBlank" value="">blank</option>');
|
|
2693
|
-
scope.$apply();
|
|
2694
|
-
|
|
2695
|
-
expect(element.querySelectorAll("option")[0].selected).toBe(false);
|
|
2696
|
-
|
|
2697
|
-
scope.isBlank = true;
|
|
2698
|
-
scope.$apply();
|
|
2699
|
-
|
|
2700
|
-
expect(element.querySelectorAll("option")[0].value).toBe("");
|
|
2701
|
-
expect(element.querySelectorAll("option")[0].selected).toBe(true);
|
|
2702
|
-
expect(element.querySelectorAll("option")[1].selected).toBe(false);
|
|
2703
|
-
});
|
|
2704
|
-
|
|
2705
|
-
it("should not throw when a directive compiles the blank option before ngOptions is linked", () => {
|
|
2706
|
-
expect(() => {
|
|
2707
|
-
createSelect(
|
|
2708
|
-
{
|
|
2709
|
-
"o-compile-contents": "",
|
|
2710
|
-
name: "select",
|
|
2711
|
-
"ng-model": "value",
|
|
2712
|
-
"ng-options": "item for item in items",
|
|
2713
|
-
},
|
|
2714
|
-
true,
|
|
2715
|
-
);
|
|
2716
|
-
}).not.toThrow();
|
|
2717
|
-
|
|
2718
|
-
expect(linkLog).toEqual(["linkCompileContents", "linkNgOptions"]);
|
|
2719
|
-
});
|
|
2720
|
-
|
|
2721
|
-
it("should not throw with a directive that replaces", () => {
|
|
2722
|
-
let $templateCache = injector.get("$templateCache");
|
|
2723
|
-
$templateCache.set(
|
|
2724
|
-
"select_template.html",
|
|
2725
|
-
'<select ng-options="option as option for option in selectable_options"> <option value="">This is a test</option> </select>',
|
|
2726
|
-
);
|
|
2727
|
-
|
|
2728
|
-
scope.options = ["a", "b", "c", "d"];
|
|
2729
|
-
|
|
2730
|
-
expect(() => {
|
|
2731
|
-
element = $compile(
|
|
2732
|
-
'<custom-select ng-model="value" options="options"></custom-select>',
|
|
2733
|
-
)(scope);
|
|
2734
|
-
}).not.toThrow();
|
|
2735
|
-
|
|
2736
|
-
dealoc(element);
|
|
2737
|
-
});
|
|
2738
|
-
});
|
|
2739
|
-
|
|
2740
|
-
describe("on change", () => {
|
|
2741
|
-
it("should update model on change", () => {
|
|
2742
|
-
element.innerHTML =
|
|
2743
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
2744
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2745
|
-
scope = injector.get("$rootScope");
|
|
2746
|
-
|
|
2747
|
-
scope.$apply(() => {
|
|
2748
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2749
|
-
scope.selected = scope.values[0];
|
|
2750
|
-
});
|
|
2751
|
-
|
|
2752
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2753
|
-
|
|
2754
|
-
setSelectValue(element, 1);
|
|
2755
|
-
expect(scope.selected).toEqual(scope.values[1]);
|
|
2756
|
-
});
|
|
2757
|
-
|
|
2758
|
-
it("should update model on change through expression", () => {
|
|
2759
|
-
createSelect({
|
|
2760
|
-
"ng-model": "selected",
|
|
2761
|
-
"ng-options": "item.id as item.name for item in values",
|
|
2762
|
-
});
|
|
2763
|
-
|
|
2764
|
-
scope.$apply(() => {
|
|
2765
|
-
scope.values = [
|
|
2766
|
-
{ id: 10, name: "A" },
|
|
2767
|
-
{ id: 20, name: "B" },
|
|
2768
|
-
];
|
|
2769
|
-
scope.selected = scope.values[0].id;
|
|
2770
|
-
});
|
|
2771
|
-
|
|
2772
|
-
expect(element).toEqualSelectValue(scope.selected);
|
|
2773
|
-
|
|
2774
|
-
setSelectValue(element, 1);
|
|
2775
|
-
expect(scope.selected).toEqual(scope.values[1].id);
|
|
2776
|
-
});
|
|
2777
|
-
|
|
2778
|
-
it("should update model to null on change", () => {
|
|
2779
|
-
element.innerHTML =
|
|
2780
|
-
'<select ng-model="selected" ng-options="value.name for value in values"><option value="">blank</option></select>';
|
|
2781
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
2782
|
-
scope = injector.get("$rootScope");
|
|
2783
|
-
|
|
2784
|
-
scope.$apply(() => {
|
|
2785
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2786
|
-
scope.selected = scope.values[0];
|
|
2787
|
-
});
|
|
2788
|
-
|
|
2789
|
-
element.value = "";
|
|
2790
|
-
browserTrigger(element, "change");
|
|
2791
|
-
expect(scope.selected).toEqual(null);
|
|
2792
|
-
});
|
|
2793
|
-
|
|
2794
|
-
// Regression https://github.com/angular/angular.js/issues/7855
|
|
2795
|
-
it("should update the model with ng-change", () => {
|
|
2796
|
-
createSelect({
|
|
2797
|
-
"ng-change": "change()",
|
|
2798
|
-
"ng-model": "selected",
|
|
2799
|
-
"ng-options": "value for value in values",
|
|
2800
|
-
});
|
|
2801
|
-
|
|
2802
|
-
scope.$apply(() => {
|
|
2803
|
-
scope.values = ["A", "B"];
|
|
2804
|
-
scope.selected = "A";
|
|
2805
|
-
});
|
|
2806
|
-
|
|
2807
|
-
scope.change = function () {
|
|
2808
|
-
scope.selected = "A";
|
|
2809
|
-
};
|
|
2810
|
-
|
|
2811
|
-
element.querySelectorAll("option")[1].selected = true;
|
|
2812
|
-
|
|
2813
|
-
browserTrigger(element, "change");
|
|
2814
|
-
expect(element.querySelectorAll("option")[0].selected).toBeTruthy();
|
|
2815
|
-
expect(scope.selected).toEqual("A");
|
|
2816
|
-
});
|
|
2817
|
-
});
|
|
2818
|
-
|
|
2819
|
-
describe("disabled blank", () => {
|
|
2820
|
-
it("should select disabled blank by default", () => {
|
|
2821
|
-
const html =
|
|
2822
|
-
'<select ng-model="someModel" ng-options="c for c in choices">' +
|
|
2823
|
-
'<option value="" disabled>Choose One</option>' +
|
|
2824
|
-
"</select>";
|
|
2825
|
-
scope.$apply(() => {
|
|
2826
|
-
scope.choices = ["A", "B", "C"];
|
|
2827
|
-
});
|
|
2828
|
-
|
|
2829
|
-
compile(html);
|
|
2830
|
-
|
|
2831
|
-
const options = element.querySelectorAll("option");
|
|
2832
|
-
const optionToSelect = options[0];
|
|
2833
|
-
expect(optionToSelect.textContent).toBe("Choose One");
|
|
2834
|
-
expect(optionToSelect[0].selected).toBe(true);
|
|
2835
|
-
expect(element.value).toBe("");
|
|
2836
|
-
|
|
2837
|
-
dealoc(element);
|
|
2838
|
-
});
|
|
2839
|
-
|
|
2840
|
-
it("should select disabled blank by default when select is required", () => {
|
|
2841
|
-
const html =
|
|
2842
|
-
'<select ng-model="someModel" ng-options="c for c in choices" required>' +
|
|
2843
|
-
'<option value="" disabled>Choose One</option>' +
|
|
2844
|
-
"</select>";
|
|
2845
|
-
scope.$apply(() => {
|
|
2846
|
-
scope.choices = ["A", "B", "C"];
|
|
2847
|
-
});
|
|
2848
|
-
|
|
2849
|
-
compile(html);
|
|
2850
|
-
|
|
2851
|
-
const options = element.querySelectorAll("option");
|
|
2852
|
-
const optionToSelect = options[0];
|
|
2853
|
-
expect(optionToSelect.textContent).toBe("Choose One");
|
|
2854
|
-
expect(optionToSelect[0].selected).toBe(true);
|
|
2855
|
-
expect(element.value).toBe("");
|
|
2856
|
-
|
|
2857
|
-
dealoc(element);
|
|
2858
|
-
});
|
|
2859
|
-
});
|
|
2860
|
-
|
|
2861
|
-
describe("select-many", () => {
|
|
2862
|
-
it("should read multiple selection", () => {
|
|
2863
|
-
createMultiSelect();
|
|
2864
|
-
|
|
2865
|
-
scope.$apply(() => {
|
|
2866
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2867
|
-
scope.selected = [];
|
|
2868
|
-
});
|
|
2869
|
-
|
|
2870
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2871
|
-
expect(element.querySelectorAll("option")[0].selected).toBeFalsy();
|
|
2872
|
-
expect(element.querySelectorAll("option")[1].selected).toBeFalsy();
|
|
2873
|
-
|
|
2874
|
-
scope.$apply(() => {
|
|
2875
|
-
scope.selected.push(scope.values[1]);
|
|
2876
|
-
});
|
|
2877
|
-
|
|
2878
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2879
|
-
expect(element.querySelectorAll("option")[0].selected).toBeFalsy();
|
|
2880
|
-
expect(element.querySelectorAll("option")[1].selected).toBeTruthy();
|
|
2881
|
-
|
|
2882
|
-
scope.$apply(() => {
|
|
2883
|
-
scope.selected.push(scope.values[0]);
|
|
2884
|
-
});
|
|
2885
|
-
|
|
2886
|
-
expect(element.querySelectorAll("option").length).toEqual(2);
|
|
2887
|
-
expect(element.querySelectorAll("option")[0].selected).toBeTruthy();
|
|
2888
|
-
expect(element.querySelectorAll("option")[1].selected).toBeTruthy();
|
|
2889
|
-
});
|
|
2890
|
-
|
|
2891
|
-
it("should update model on change", () => {
|
|
2892
|
-
createMultiSelect();
|
|
2893
|
-
|
|
2894
|
-
scope.$apply(() => {
|
|
2895
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2896
|
-
scope.selected = [];
|
|
2897
|
-
});
|
|
2898
|
-
|
|
2899
|
-
element.querySelectorAll("option")[0].selected = true;
|
|
2900
|
-
|
|
2901
|
-
browserTrigger(element, "change");
|
|
2902
|
-
expect(scope.selected).toEqual([scope.values[0]]);
|
|
2903
|
-
});
|
|
2904
|
-
|
|
2905
|
-
it("should select from object", () => {
|
|
2906
|
-
createSelect({
|
|
2907
|
-
"ng-model": "selected",
|
|
2908
|
-
multiple: true,
|
|
2909
|
-
"ng-options": "key as value for (key,value) in values",
|
|
2910
|
-
});
|
|
2911
|
-
scope.values = { 0: "A", 1: "B" };
|
|
2912
|
-
|
|
2913
|
-
scope.selected = ["1"];
|
|
2914
|
-
expect(element.querySelectorAll("option")[1].selected).toBe(true);
|
|
2915
|
-
|
|
2916
|
-
element.querySelectorAll("option")[0].selected = true;
|
|
2917
|
-
browserTrigger(element, "change");
|
|
2918
|
-
expect(scope.selected).toEqual(["0", "1"]);
|
|
2919
|
-
|
|
2920
|
-
element.querySelectorAll("option")[1].selected = false;
|
|
2921
|
-
browserTrigger(element, "change");
|
|
2922
|
-
expect(scope.selected).toEqual(["0"]);
|
|
2923
|
-
});
|
|
2924
|
-
|
|
2925
|
-
it("should deselect all options when model is emptied", () => {
|
|
2926
|
-
createMultiSelect();
|
|
2927
|
-
scope.$apply(() => {
|
|
2928
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2929
|
-
scope.selected = [scope.values[0]];
|
|
2930
|
-
});
|
|
2931
|
-
expect(element.querySelectorAll("option")[0].selected).toEqual(true);
|
|
2932
|
-
|
|
2933
|
-
scope.$apply(() => {
|
|
2934
|
-
scope.selected.pop();
|
|
2935
|
-
});
|
|
2936
|
-
|
|
2937
|
-
expect(element.querySelectorAll("option")[0].selected).toEqual(false);
|
|
2938
|
-
});
|
|
2939
|
-
|
|
2940
|
-
// Support: Safari 9+
|
|
2941
|
-
// This test relies defining a getter/setter `selected` property on either `<option>` elements
|
|
2942
|
-
// or their prototype. Some browsers (including Safari 9) are very flakey when the
|
|
2943
|
-
// getter/setter is not defined on the prototype (probably due to some bug). On Safari 9, the
|
|
2944
|
-
// getter/setter that is already defined on the `<option>` element's prototype is not
|
|
2945
|
-
// configurable, so we can't overwrite it with our spy.
|
|
2946
|
-
if (
|
|
2947
|
-
!/\b(9|\d{2})(?:\.\d+)+[\s\S]*safari/i.test(window.navigator.userAgent)
|
|
2948
|
-
) {
|
|
2949
|
-
it("should not re-set the `selected` property if it already has the correct value", () => {
|
|
2950
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
2951
|
-
createMultiSelect();
|
|
2952
|
-
|
|
2953
|
-
const options = element.querySelectorAll("option");
|
|
2954
|
-
const optionsSetSelected = [];
|
|
2955
|
-
const _selected = [];
|
|
2956
|
-
|
|
2957
|
-
// Set up spies
|
|
2958
|
-
const optionProto = Object.getPrototypeOf(options[0]);
|
|
2959
|
-
const originalSelectedDescriptor =
|
|
2960
|
-
isFunction(Object.getOwnPropertyDescriptor) &&
|
|
2961
|
-
Object.getOwnPropertyDescriptor(optionProto, "selected");
|
|
2962
|
-
const addSpiesOnProto =
|
|
2963
|
-
originalSelectedDescriptor && originalSelectedDescriptor.configurable;
|
|
2964
|
-
|
|
2965
|
-
Object.entries(options).forEach(([i, option]) => {
|
|
2966
|
-
const setSelected = function (value) {
|
|
2967
|
-
_selected[i] = value;
|
|
2968
|
-
};
|
|
2969
|
-
optionsSetSelected[i] = jasmine
|
|
2970
|
-
.createSpy(`optionSetSelected${i}`)
|
|
2971
|
-
.and.callFake(setSelected);
|
|
2972
|
-
setSelected(option.selected);
|
|
2973
|
-
});
|
|
2974
|
-
|
|
2975
|
-
if (!addSpiesOnProto) {
|
|
2976
|
-
Object.entries(options).forEach(([i, option]) => {
|
|
2977
|
-
Object.defineProperty(option, "selected", {
|
|
2978
|
-
get() {
|
|
2979
|
-
return _selected[i];
|
|
2980
|
-
},
|
|
2981
|
-
set: optionsSetSelected[i],
|
|
2982
|
-
});
|
|
2983
|
-
});
|
|
2984
|
-
} else {
|
|
2985
|
-
// Support: Firefox 54+
|
|
2986
|
-
// We cannot use the above (simpler) method on all browsers because of Firefox 54+, which
|
|
2987
|
-
// is very flaky when the getter/setter property is defined on the element itself and not
|
|
2988
|
-
// the prototype. (Possibly the result of some (buggy?) optimization.)
|
|
2989
|
-
const getSelected = function (index) {
|
|
2990
|
-
return _selected[index];
|
|
2991
|
-
};
|
|
2992
|
-
const setSelected = function (index, value) {
|
|
2993
|
-
optionsSetSelected[index](value);
|
|
2994
|
-
};
|
|
2995
|
-
const getSelectedOriginal = function (option) {
|
|
2996
|
-
return originalSelectedDescriptor.get.call(option);
|
|
2997
|
-
};
|
|
2998
|
-
const setSelectedOriginal = function (option, value) {
|
|
2999
|
-
originalSelectedDescriptor.set.call(option, value);
|
|
3000
|
-
};
|
|
3001
|
-
const getIndexAndCall = function (
|
|
3002
|
-
option,
|
|
3003
|
-
foundFn,
|
|
3004
|
-
notFoundFn,
|
|
3005
|
-
value,
|
|
3006
|
-
) {
|
|
3007
|
-
for (let i = 0, ii = options.length; i < ii; ++i) {
|
|
3008
|
-
if (options[i] === option) return foundFn(i, value);
|
|
3009
|
-
}
|
|
3010
|
-
return notFoundFn(option, value);
|
|
3011
|
-
};
|
|
3012
|
-
|
|
3013
|
-
Object.defineProperty(optionProto, "selected", {
|
|
3014
|
-
get() {
|
|
3015
|
-
return getIndexAndCall(this, getSelected, getSelectedOriginal);
|
|
3016
|
-
},
|
|
3017
|
-
set(value) {
|
|
3018
|
-
return getIndexAndCall(
|
|
3019
|
-
this,
|
|
3020
|
-
setSelected,
|
|
3021
|
-
setSelectedOriginal,
|
|
3022
|
-
value,
|
|
3023
|
-
);
|
|
3024
|
-
},
|
|
3025
|
-
});
|
|
3026
|
-
}
|
|
3027
|
-
|
|
3028
|
-
// Select `optionA`
|
|
3029
|
-
scope.$apply("selected = [values[0]]");
|
|
3030
|
-
|
|
3031
|
-
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(true);
|
|
3032
|
-
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
|
3033
|
-
expect(options[0].selected).toBe(true);
|
|
3034
|
-
expect(options[1].selected).toBe(false);
|
|
3035
|
-
optionsSetSelected[0].calls.reset();
|
|
3036
|
-
optionsSetSelected[1].calls.reset();
|
|
3037
|
-
|
|
3038
|
-
// Select `optionB` (`optionA` remains selected)
|
|
3039
|
-
scope.$apply("selected.push(values[1])");
|
|
3040
|
-
|
|
3041
|
-
expect(optionsSetSelected[0]).not.toHaveBeenCalled();
|
|
3042
|
-
expect(optionsSetSelected[1]).toHaveBeenCalledOnceWith(true);
|
|
3043
|
-
expect(options[0].selected).toBe(true);
|
|
3044
|
-
expect(options[1].selected).toBe(true);
|
|
3045
|
-
optionsSetSelected[0].calls.reset();
|
|
3046
|
-
optionsSetSelected[1].calls.reset();
|
|
3047
|
-
|
|
3048
|
-
// Unselect `optionA` (`optionB` remains selected)
|
|
3049
|
-
scope.$apply("selected.shift()");
|
|
3050
|
-
|
|
3051
|
-
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(false);
|
|
3052
|
-
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
|
3053
|
-
expect(options[0].selected).toBe(false);
|
|
3054
|
-
expect(options[1].selected).toBe(true);
|
|
3055
|
-
optionsSetSelected[0].calls.reset();
|
|
3056
|
-
optionsSetSelected[1].calls.reset();
|
|
3057
|
-
|
|
3058
|
-
// Reselect `optionA` (`optionB` remains selected)
|
|
3059
|
-
scope.$apply("selected.push(values[0])");
|
|
3060
|
-
|
|
3061
|
-
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(true);
|
|
3062
|
-
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
|
3063
|
-
expect(options[0].selected).toBe(true);
|
|
3064
|
-
expect(options[1].selected).toBe(true);
|
|
3065
|
-
optionsSetSelected[0].calls.reset();
|
|
3066
|
-
optionsSetSelected[1].calls.reset();
|
|
3067
|
-
|
|
3068
|
-
// Unselect `optionB` (`optionA` remains selected)
|
|
3069
|
-
scope.$apply("selected.shift()");
|
|
3070
|
-
|
|
3071
|
-
expect(optionsSetSelected[0]).not.toHaveBeenCalled();
|
|
3072
|
-
expect(optionsSetSelected[1]).toHaveBeenCalledOnceWith(false);
|
|
3073
|
-
expect(options[0].selected).toBe(true);
|
|
3074
|
-
expect(options[1].selected).toBe(false);
|
|
3075
|
-
optionsSetSelected[0].calls.reset();
|
|
3076
|
-
optionsSetSelected[1].calls.reset();
|
|
3077
|
-
|
|
3078
|
-
// Unselect `optionA`
|
|
3079
|
-
scope.$apply("selected.length = 0");
|
|
3080
|
-
|
|
3081
|
-
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(false);
|
|
3082
|
-
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
|
3083
|
-
expect(options[0].selected).toBe(false);
|
|
3084
|
-
expect(options[1].selected).toBe(false);
|
|
3085
|
-
optionsSetSelected[0].calls.reset();
|
|
3086
|
-
optionsSetSelected[1].calls.reset();
|
|
3087
|
-
|
|
3088
|
-
// Support: Firefox 54+
|
|
3089
|
-
// Restore `originalSelectedDescriptor`
|
|
3090
|
-
if (addSpiesOnProto) {
|
|
3091
|
-
Object.defineProperty(
|
|
3092
|
-
optionProto,
|
|
3093
|
-
"selected",
|
|
3094
|
-
originalSelectedDescriptor,
|
|
3095
|
-
);
|
|
3096
|
-
}
|
|
3097
|
-
});
|
|
3098
|
-
}
|
|
3099
|
-
|
|
3100
|
-
if (window.MutationObserver) {
|
|
3101
|
-
// IE9 and IE10 do not support MutationObserver
|
|
3102
|
-
// Since the feature is only needed for a test, it's okay to skip these browsers
|
|
3103
|
-
it("should render the initial options only one time", () => {
|
|
3104
|
-
scope.value = ["black"];
|
|
3105
|
-
scope.values = ["black", "white", "red"];
|
|
3106
|
-
// observe-child-list adds a MutationObserver that we will read out after ngOptions
|
|
3107
|
-
// has been compiled
|
|
3108
|
-
createSelect({
|
|
3109
|
-
"ng-model": "selected",
|
|
3110
|
-
"ng-options": "value.name for value in values",
|
|
3111
|
-
multiple: "true",
|
|
3112
|
-
"observe-child-list": "",
|
|
3113
|
-
});
|
|
3114
|
-
|
|
3115
|
-
const optionEls = element.querySelectorAll("option");
|
|
3116
|
-
const records = childListMutationObserver.takeRecords();
|
|
3117
|
-
|
|
3118
|
-
expect(records.length).toBe(1);
|
|
3119
|
-
expect(records[0].addedNodes).toEqual(optionEls);
|
|
3120
|
-
});
|
|
3121
|
-
}
|
|
3122
|
-
});
|
|
3123
|
-
|
|
3124
|
-
describe("required state", () => {
|
|
3125
|
-
it("should set the error if the empty option is selected", () => {
|
|
3126
|
-
createSelect(
|
|
3127
|
-
{
|
|
3128
|
-
"ng-model": "selection",
|
|
3129
|
-
"ng-options": "item for item in values",
|
|
3130
|
-
required: "",
|
|
3131
|
-
},
|
|
3132
|
-
true,
|
|
3133
|
-
);
|
|
3134
|
-
|
|
3135
|
-
scope.$apply(() => {
|
|
3136
|
-
scope.values = ["a", "b"];
|
|
3137
|
-
scope.selection = scope.values[0];
|
|
3138
|
-
});
|
|
3139
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3140
|
-
expect(ngModelCtrl.$error.required).toBeFalsy();
|
|
3141
|
-
|
|
3142
|
-
const options = element.querySelectorAll("option");
|
|
3143
|
-
|
|
3144
|
-
// // view -> model
|
|
3145
|
-
setSelectValue(element, 0);
|
|
3146
|
-
expect(element.classList.contains("ng-invalid")).toBeTrue();
|
|
3147
|
-
expect(ngModelCtrl.$error.required).toBeTruthy();
|
|
3148
|
-
|
|
3149
|
-
setSelectValue(element, 1);
|
|
3150
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3151
|
-
expect(ngModelCtrl.$error.required).toBeFalsy();
|
|
3152
|
-
|
|
3153
|
-
// // model -> view
|
|
3154
|
-
scope.$apply("selection = null");
|
|
3155
|
-
expect(options[0].selected).toBe(true);
|
|
3156
|
-
expect(element.classList.contains("ng-invalid")).toBeTrue();
|
|
3157
|
-
expect(ngModelCtrl.$error.required).toBeTruthy();
|
|
3158
|
-
});
|
|
3159
|
-
|
|
3160
|
-
it("should validate with empty option and bound ngRequired", () => {
|
|
3161
|
-
createSelect(
|
|
3162
|
-
{
|
|
3163
|
-
"ng-model": "value",
|
|
3164
|
-
"ng-options": "item.name for item in values",
|
|
3165
|
-
"ng-required": "required",
|
|
3166
|
-
},
|
|
3167
|
-
true,
|
|
3168
|
-
);
|
|
3169
|
-
|
|
3170
|
-
scope.$apply(() => {
|
|
3171
|
-
scope.values = [
|
|
3172
|
-
{ name: "A", id: 1 },
|
|
3173
|
-
{ name: "B", id: 2 },
|
|
3174
|
-
];
|
|
3175
|
-
scope.required = false;
|
|
3176
|
-
});
|
|
3177
|
-
|
|
3178
|
-
const options = element.querySelectorAll("option");
|
|
3179
|
-
|
|
3180
|
-
setSelectValue(element, 0);
|
|
3181
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3182
|
-
|
|
3183
|
-
scope.$apply("required = true");
|
|
3184
|
-
expect(element.classList.contains("ng-invalid")).toBeTrue();
|
|
3185
|
-
|
|
3186
|
-
scope.$apply("value = values[0]");
|
|
3187
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3188
|
-
|
|
3189
|
-
setSelectValue(element, 0);
|
|
3190
|
-
expect(element.classList.contains("ng-invalid")).toBeTrue();
|
|
3191
|
-
|
|
3192
|
-
scope.$apply("required = false");
|
|
3193
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3194
|
-
});
|
|
3195
|
-
|
|
3196
|
-
it("should treat an empty array as invalid when `multiple` attribute used", () => {
|
|
3197
|
-
createSelect(
|
|
3198
|
-
{
|
|
3199
|
-
"ng-model": "value",
|
|
3200
|
-
"ng-options": "item.name for item in values",
|
|
3201
|
-
"ng-required": "required",
|
|
3202
|
-
multiple: "",
|
|
3203
|
-
},
|
|
3204
|
-
true,
|
|
3205
|
-
);
|
|
3206
|
-
|
|
3207
|
-
scope.$apply(() => {
|
|
3208
|
-
scope.value = [];
|
|
3209
|
-
scope.values = [
|
|
3210
|
-
{ name: "A", id: 1 },
|
|
3211
|
-
{ name: "B", id: 2 },
|
|
3212
|
-
];
|
|
3213
|
-
scope.required = true;
|
|
3214
|
-
});
|
|
3215
|
-
expect(element.classList.contains("ng-invalid")).toBeTrue();
|
|
3216
|
-
|
|
3217
|
-
scope.$apply(() => {
|
|
3218
|
-
// ngModelWatch does not set objectEquality flag
|
|
3219
|
-
// array must be replaced in order to trigger $formatters
|
|
3220
|
-
scope.value = [scope.values[0]];
|
|
3221
|
-
});
|
|
3222
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3223
|
-
});
|
|
3224
|
-
|
|
3225
|
-
it("should NOT set the error if the empty option is present but required attribute is not", () => {
|
|
3226
|
-
scope.$apply(() => {
|
|
3227
|
-
scope.values = ["a", "b"];
|
|
3228
|
-
});
|
|
3229
|
-
|
|
3230
|
-
element.innerHTML =
|
|
3231
|
-
'<select ng-model="selected" ng-options="value.name for value in values"></select>';
|
|
3232
|
-
injector = window.angular.bootstrap(element, ["myModule"]);
|
|
3233
|
-
scope = injector.get("$rootScope");
|
|
3234
|
-
|
|
3235
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3236
|
-
expect(element.classList.contains("ng-pristine")).toBeTrue();
|
|
3237
|
-
expect(ngModelCtrl.$error.required).toBeFalsy();
|
|
3238
|
-
});
|
|
3239
|
-
|
|
3240
|
-
it("should NOT set the error if the unknown option is selected", () => {
|
|
3241
|
-
createSelect({
|
|
3242
|
-
"ng-model": "selection",
|
|
3243
|
-
"ng-options": "item for item in values",
|
|
3244
|
-
required: "",
|
|
3245
|
-
});
|
|
3246
|
-
|
|
3247
|
-
scope.$apply(() => {
|
|
3248
|
-
scope.values = ["a", "b"];
|
|
3249
|
-
scope.selection = "a";
|
|
3250
|
-
});
|
|
3251
|
-
|
|
3252
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3253
|
-
expect(ngModelCtrl.$error.required).toBeFalsy();
|
|
3254
|
-
|
|
3255
|
-
scope.$apply('selection = "c"');
|
|
3256
|
-
expect(element.value).toBe("?");
|
|
3257
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3258
|
-
expect(ngModelCtrl.$error.required).toBeFalsy();
|
|
3259
|
-
});
|
|
3260
|
-
|
|
3261
|
-
it("should allow falsy values as values", () => {
|
|
3262
|
-
createSelect(
|
|
3263
|
-
{
|
|
3264
|
-
"ng-model": "value",
|
|
3265
|
-
"ng-options": "item.value as item.name for item in values",
|
|
3266
|
-
"ng-required": "required",
|
|
3267
|
-
},
|
|
3268
|
-
true,
|
|
3269
|
-
);
|
|
3270
|
-
|
|
3271
|
-
scope.$apply(() => {
|
|
3272
|
-
scope.values = [
|
|
3273
|
-
{ name: "True", value: true },
|
|
3274
|
-
{ name: "False", value: false },
|
|
3275
|
-
];
|
|
3276
|
-
scope.required = false;
|
|
3277
|
-
});
|
|
3278
|
-
|
|
3279
|
-
setSelectValue(element, 2);
|
|
3280
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3281
|
-
expect(scope.value).toBe(false);
|
|
3282
|
-
|
|
3283
|
-
scope.$apply("required = true");
|
|
3284
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3285
|
-
expect(scope.value).toBe(false);
|
|
3286
|
-
});
|
|
3287
|
-
|
|
3288
|
-
it("should validate after option list was updated", () => {
|
|
3289
|
-
createSelect(
|
|
3290
|
-
{
|
|
3291
|
-
"ng-model": "selection",
|
|
3292
|
-
"ng-options": "item for item in values",
|
|
3293
|
-
required: "",
|
|
3294
|
-
},
|
|
3295
|
-
true,
|
|
3296
|
-
);
|
|
3297
|
-
|
|
3298
|
-
scope.$apply(() => {
|
|
3299
|
-
scope.values = ["A", "B"];
|
|
3300
|
-
scope.selection = scope.values[0];
|
|
3301
|
-
});
|
|
3302
|
-
|
|
3303
|
-
expect(element.value).toBe("string:A");
|
|
3304
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3305
|
-
expect(ngModelCtrl.$error.required).toBeFalsy();
|
|
3306
|
-
|
|
3307
|
-
scope.$apply(() => {
|
|
3308
|
-
scope.values = ["C", "D"];
|
|
3309
|
-
});
|
|
3310
|
-
|
|
3311
|
-
expect(element.value).toBe("");
|
|
3312
|
-
expect(element.classList.contains("ng-invalid")).toBeTrue();
|
|
3313
|
-
expect(ngModelCtrl.$error.required).toBeTruthy();
|
|
3314
|
-
// ngModel sets undefined for invalid values
|
|
3315
|
-
expect(scope.selection).toBeUndefined();
|
|
3316
|
-
});
|
|
3317
|
-
});
|
|
3318
|
-
|
|
3319
|
-
describe("required and empty option", () => {
|
|
3320
|
-
it("should select the empty option after compilation", () => {
|
|
3321
|
-
createSelect(
|
|
3322
|
-
{
|
|
3323
|
-
name: "select",
|
|
3324
|
-
"ng-model": "value",
|
|
3325
|
-
"ng-options": "item for item in ['first', 'second', 'third']",
|
|
3326
|
-
required: "required",
|
|
3327
|
-
},
|
|
3328
|
-
true,
|
|
3329
|
-
);
|
|
3330
|
-
|
|
3331
|
-
expect(element.value).toBe("");
|
|
3332
|
-
const emptyOption = element.querySelectorAll("option")[0];
|
|
3333
|
-
expect(emptyOption[0].selected).toBe(true);
|
|
3334
|
-
expect(emptyOption.value).toBe("");
|
|
3335
|
-
});
|
|
3336
|
-
});
|
|
3337
|
-
|
|
3338
|
-
describe("ngModelCtrl", () => {
|
|
3339
|
-
it('should prefix the model value with the word "the" using $parsers', () => {
|
|
3340
|
-
createSelect({
|
|
3341
|
-
name: "select",
|
|
3342
|
-
"ng-model": "value",
|
|
3343
|
-
"ng-options": "item for item in ['first', 'second', 'third', 'fourth']",
|
|
3344
|
-
});
|
|
3345
|
-
|
|
3346
|
-
scope.form.select.$parsers.push((value) => `the ${value}`);
|
|
3347
|
-
|
|
3348
|
-
setSelectValue(element, 3);
|
|
3349
|
-
expect(scope.value).toBe("the third");
|
|
3350
|
-
expect(element).toEqualSelectValue("third");
|
|
3351
|
-
});
|
|
3352
|
-
|
|
3353
|
-
it('should prefix the view value with the word "the" using $formatters', () => {
|
|
3354
|
-
createSelect({
|
|
3355
|
-
name: "select",
|
|
3356
|
-
"ng-model": "value",
|
|
3357
|
-
"ng-options":
|
|
3358
|
-
"item for item in ['the first', 'the second', 'the third', 'the fourth']",
|
|
3359
|
-
});
|
|
3360
|
-
|
|
3361
|
-
scope.form.select.$formatters.push((value) => `the ${value}`);
|
|
3362
|
-
|
|
3363
|
-
scope.$apply(() => {
|
|
3364
|
-
scope.value = "third";
|
|
3365
|
-
});
|
|
3366
|
-
expect(element).toEqualSelectValue("the third");
|
|
3367
|
-
});
|
|
3368
|
-
|
|
3369
|
-
it("should fail validation when $validators fail", () => {
|
|
3370
|
-
createSelect({
|
|
3371
|
-
name: "select",
|
|
3372
|
-
"ng-model": "value",
|
|
3373
|
-
"ng-options": "item for item in ['first', 'second', 'third', 'fourth']",
|
|
3374
|
-
});
|
|
3375
|
-
|
|
3376
|
-
scope.form.select.$validators.fail = function () {
|
|
3377
|
-
return false;
|
|
3378
|
-
};
|
|
3379
|
-
|
|
3380
|
-
setSelectValue(element, 3);
|
|
3381
|
-
expect(element.classList.contains("ng-invalid")).toBeTrue();
|
|
3382
|
-
expect(scope.value).toBeUndefined();
|
|
3383
|
-
expect(element).toEqualSelectValue("third");
|
|
3384
|
-
});
|
|
3385
|
-
|
|
3386
|
-
it("should pass validation when $validators pass", () => {
|
|
3387
|
-
createSelect({
|
|
3388
|
-
name: "select",
|
|
3389
|
-
"ng-model": "value",
|
|
3390
|
-
"ng-options": "item for item in ['first', 'second', 'third', 'fourth']",
|
|
3391
|
-
});
|
|
3392
|
-
|
|
3393
|
-
scope.form.select.$validators.pass = function () {
|
|
3394
|
-
return true;
|
|
3395
|
-
};
|
|
3396
|
-
|
|
3397
|
-
setSelectValue(element, 3);
|
|
3398
|
-
expect(element.classList.contains("ng-valid")).toBeTrue();
|
|
3399
|
-
expect(scope.value).toBe("third");
|
|
3400
|
-
expect(element).toEqualSelectValue("third");
|
|
3401
|
-
});
|
|
3402
|
-
|
|
3403
|
-
it("should fail validation when $asyncValidators fail", () => {
|
|
3404
|
-
let defer;
|
|
3405
|
-
createSelect({
|
|
3406
|
-
name: "select",
|
|
3407
|
-
"ng-model": "value",
|
|
3408
|
-
"ng-options": "item for item in ['first', 'second', 'third', 'fourth']",
|
|
3409
|
-
});
|
|
3410
|
-
|
|
3411
|
-
scope.form.select.$asyncValidators.async = function () {
|
|
3412
|
-
defer = Promise.withResolvers();
|
|
3413
|
-
return defer.promise;
|
|
3414
|
-
};
|
|
3415
|
-
|
|
3416
|
-
setSelectValue(element, 3);
|
|
3417
|
-
expect(scope.form.select.$pending).toBeDefined();
|
|
3418
|
-
expect(scope.value).toBeUndefined();
|
|
3419
|
-
expect(element).toEqualSelectValue("third");
|
|
3420
|
-
|
|
3421
|
-
defer.reject();
|
|
3422
|
-
expect(scope.form.select.$pending).toBeUndefined();
|
|
3423
|
-
expect(scope.value).toBeUndefined();
|
|
3424
|
-
expect(element).toEqualSelectValue("third");
|
|
3425
|
-
});
|
|
3426
|
-
|
|
3427
|
-
it("should pass validation when $asyncValidators pass", () => {
|
|
3428
|
-
let defer;
|
|
3429
|
-
createSelect({
|
|
3430
|
-
name: "select",
|
|
3431
|
-
"ng-model": "value",
|
|
3432
|
-
"ng-options": "item for item in ['first', 'second', 'third', 'fourth']",
|
|
3433
|
-
});
|
|
3434
|
-
|
|
3435
|
-
scope.form.select.$asyncValidators.async = function () {
|
|
3436
|
-
defer = Promise.withResolvers();
|
|
3437
|
-
return defer.promise;
|
|
3438
|
-
};
|
|
3439
|
-
|
|
3440
|
-
setSelectValue(element, 3);
|
|
3441
|
-
expect(scope.form.select.$pending).toBeDefined();
|
|
3442
|
-
expect(scope.value).toBeUndefined();
|
|
3443
|
-
expect(element).toEqualSelectValue("third");
|
|
3444
|
-
|
|
3445
|
-
defer.resolve();
|
|
3446
|
-
expect(scope.form.select.$pending).toBeUndefined();
|
|
3447
|
-
expect(scope.value).toBe("third");
|
|
3448
|
-
expect(element).toEqualSelectValue("third");
|
|
3449
|
-
});
|
|
3450
|
-
|
|
3451
|
-
it("should not set $dirty with select-multiple after compilation", () => {
|
|
3452
|
-
scope.values = ["a", "b"];
|
|
3453
|
-
scope.selected = ["b"];
|
|
3454
|
-
|
|
3455
|
-
createSelect({
|
|
3456
|
-
"ng-model": "selected",
|
|
3457
|
-
multiple: true,
|
|
3458
|
-
"ng-options": "value for value in values",
|
|
3459
|
-
name: "select",
|
|
3460
|
-
});
|
|
3461
|
-
|
|
3462
|
-
expect(element.querySelectorAll("option")[1].selected).toBe(true);
|
|
3463
|
-
expect(scope.form.select.$pristine).toBe(true);
|
|
3464
|
-
});
|
|
3465
|
-
});
|
|
3466
|
-
|
|
3467
|
-
describe("selectCtrl api", () => {
|
|
3468
|
-
it("should reflect the status of empty and unknown option", () => {
|
|
3469
|
-
createSingleSelect('<option ng-if="isBlank" value="">blank</option>');
|
|
3470
|
-
|
|
3471
|
-
const selectCtrl = element.controller("select");
|
|
3472
|
-
|
|
3473
|
-
scope.$apply(() => {
|
|
3474
|
-
scope.values = [{ name: "A" }, { name: "B" }];
|
|
3475
|
-
scope.isBlank = true;
|
|
3476
|
-
});
|
|
3477
|
-
|
|
3478
|
-
expect(element.value).toBe("");
|
|
3479
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(true);
|
|
3480
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
|
|
3481
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
|
|
3482
|
-
|
|
3483
|
-
// empty -> selection
|
|
3484
|
-
scope.$apply(() => {
|
|
3485
|
-
scope.selected = scope.values[0];
|
|
3486
|
-
});
|
|
3487
|
-
|
|
3488
|
-
expect(element.value).not.toBe("");
|
|
3489
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(true);
|
|
3490
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
|
|
3491
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
|
|
3492
|
-
|
|
3493
|
-
// remove empty
|
|
3494
|
-
scope.$apply("isBlank = false");
|
|
3495
|
-
|
|
3496
|
-
expect(element.value).not.toBe("");
|
|
3497
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(false);
|
|
3498
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
|
|
3499
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
|
|
3500
|
-
|
|
3501
|
-
// selection -> unknown
|
|
3502
|
-
scope.$apply('selected = "unmatched"');
|
|
3503
|
-
|
|
3504
|
-
expect(element.value).toBe("?");
|
|
3505
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(false);
|
|
3506
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
|
|
3507
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
|
|
3508
|
-
|
|
3509
|
-
// add empty
|
|
3510
|
-
scope.$apply("isBlank = true");
|
|
3511
|
-
|
|
3512
|
-
expect(element.value).toBe("?");
|
|
3513
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(true);
|
|
3514
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
|
|
3515
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
|
|
3516
|
-
|
|
3517
|
-
// unknown -> empty
|
|
3518
|
-
scope.$apply(() => {
|
|
3519
|
-
scope.selected = null;
|
|
3520
|
-
});
|
|
3521
|
-
|
|
3522
|
-
expect(element.value).toBe("");
|
|
3523
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(true);
|
|
3524
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
|
|
3525
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
|
|
3526
|
-
|
|
3527
|
-
// empty -> unknown
|
|
3528
|
-
scope.$apply('selected = "unmatched"');
|
|
3529
|
-
|
|
3530
|
-
expect(element.value).toBe("?");
|
|
3531
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(true);
|
|
3532
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
|
|
3533
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(true);
|
|
3534
|
-
|
|
3535
|
-
// unknown -> selection
|
|
3536
|
-
scope.$apply(() => {
|
|
3537
|
-
scope.selected = scope.values[1];
|
|
3538
|
-
});
|
|
3539
|
-
|
|
3540
|
-
expect(element.value).not.toBe("");
|
|
3541
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(true);
|
|
3542
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(false);
|
|
3543
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
|
|
3544
|
-
|
|
3545
|
-
// selection -> empty
|
|
3546
|
-
scope.$apply("selected = null");
|
|
3547
|
-
|
|
3548
|
-
expect(element.value).toBe("");
|
|
3549
|
-
expect(selectCtrl.$hasEmptyOption()).toBe(true);
|
|
3550
|
-
expect(selectCtrl.$isEmptyOptionSelected()).toBe(true);
|
|
3551
|
-
expect(selectCtrl.$isUnknownOptionSelected()).toBe(false);
|
|
3552
|
-
});
|
|
3553
|
-
});
|
|
3554
|
-
});
|