diff --git a/packages/core/test/view/BUILD.bazel b/packages/core/test/view/BUILD.bazel new file mode 100644 index 0000000000..31f50eb1cf --- /dev/null +++ b/packages/core/test/view/BUILD.bazel @@ -0,0 +1,52 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "jasmine_node_test", "ts_library", "ts_web_test_suite") + +ts_library( + name = "view_lib", + testonly = True, + srcs = glob( + ["**/*.ts"], + ), + deps = [ + "//packages/core", + "//packages/core/testing", + "//packages/platform-browser", + "//packages/private/testing", + ], +) + +ts_library( + name = "view_node_only_lib", + testonly = True, + srcs = glob(["**/*_node_only_spec.ts"]), + deps = [ + ":view_lib", + "//packages/core", + "//packages/core/testing", + "//packages/private/testing", + ], +) + +jasmine_node_test( + name = "view", + bootstrap = ["angular/tools/testing/init_node_spec.js"], + tags = [ + "no-ivy-aot", + ], + deps = [ + ":view_lib", + ":view_node_only_lib", + "//tools/testing:node", + ], +) + +ts_web_test_suite( + name = "view_web", + tags = [ + "no-ivy-aot", + ], + deps = [ + ":view_lib", + ], +) diff --git a/packages/core/test/view/component_view_spec.ts b/packages/core/test/view/component_view_spec.ts index c8d97015e0..2c5aa1a0e1 100644 --- a/packages/core/test/view/component_view_spec.ts +++ b/packages/core/test/view/component_view_spec.ts @@ -9,7 +9,6 @@ import {SecurityContext} from '@angular/core'; import {ArgumentType, BindingFlags, NodeCheckFn, NodeFlags, Services, ViewData, ViewFlags, ViewState, asElementData, directiveDef, elementDef, rootRenderNodes} from '@angular/core/src/view/index'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; -import {fixmeIvy} from '@angular/private/testing'; import {callMostRecentEventListenerHandler, compViewDef, createAndGetRootNodes, createRootView, isBrowser, recordNodeToRemove} from './helper'; @@ -200,64 +199,62 @@ const addEventListener = '__zone_symbol__addEventListener' as 'addEventListener' }); if (isBrowser()) { - fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') - .it('should support OnPush components', () => { - let compInputValue: any; - class AComp { - a: any; - } + it('should support OnPush components', () => { + let compInputValue: any; + class AComp { + a: any; + } - const update = jasmine.createSpy('updater'); + const update = jasmine.createSpy('updater'); - const addListenerSpy = - spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); + const addListenerSpy = spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); - const {view} = createAndGetRootNodes(compViewDef( - [ - elementDef( - 0, NodeFlags.None, null, null, 1, 'div', null, null, null, null, - () => { - return compViewDef( - [ - elementDef( - 0, NodeFlags.None, null, null, 0, 'span', null, null, - [[null !, 'click']]), - ], - update, null, ViewFlags.OnPush); - }), - directiveDef(1, NodeFlags.Component, null, 0, AComp, [], {a: [0, 'a']}), - ], - (check, view) => { check(view, 1, ArgumentType.Inline, compInputValue); })); + const {view} = createAndGetRootNodes(compViewDef( + [ + elementDef( + 0, NodeFlags.None, null, null, 1, 'div', null, null, null, null, + () => { + return compViewDef( + [ + elementDef( + 0, NodeFlags.None, null, null, 0, 'span', null, null, + [[null !, 'click']]), + ], + update, null, ViewFlags.OnPush); + }), + directiveDef(1, NodeFlags.Component, null, 0, AComp, [], {a: [0, 'a']}), + ], + (check, view) => { check(view, 1, ArgumentType.Inline, compInputValue); })); - Services.checkAndUpdateView(view); + Services.checkAndUpdateView(view); - // auto detach - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).not.toHaveBeenCalled(); + // auto detach + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).not.toHaveBeenCalled(); - // auto attach on input changes - update.calls.reset(); - compInputValue = 'v1'; - Services.checkAndUpdateView(view); - expect(update).toHaveBeenCalled(); + // auto attach on input changes + update.calls.reset(); + compInputValue = 'v1'; + Services.checkAndUpdateView(view); + expect(update).toHaveBeenCalled(); - // auto detach - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).not.toHaveBeenCalled(); + // auto detach + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).not.toHaveBeenCalled(); - // auto attach on events - callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).toHaveBeenCalled(); + // auto attach on events + callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).toHaveBeenCalled(); - // auto detach - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).not.toHaveBeenCalled(); - }); + // auto detach + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).not.toHaveBeenCalled(); + }); } it('should not stop dirty checking views that threw errors in change detection', () => { diff --git a/packages/core/test/view/element_spec.ts b/packages/core/test/view/element_spec.ts index 868675c97e..5e9fe24afd 100644 --- a/packages/core/test/view/element_spec.ts +++ b/packages/core/test/view/element_spec.ts @@ -11,7 +11,6 @@ import {getDebugContext} from '@angular/core/src/errors'; import {BindingFlags, NodeFlags, Services, ViewData, ViewDefinition, asElementData, elementDef} from '@angular/core/src/view/index'; import {TestBed} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; -import {fixmeIvy} from '@angular/private/testing'; import {ARG_TYPE_VALUES, callMostRecentEventListenerHandler, checkNodeInlineOrDynamic, compViewDef, createAndGetRootNodes, isBrowser, recordNodeToRemove} from './helper'; @@ -185,27 +184,26 @@ const removeEventListener = '__zone_symbol__removeEventListener' as 'removeEvent return result; } - fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') - .it('should listen to DOM events', () => { - const handleEventSpy = jasmine.createSpy('handleEvent'); - const removeListenerSpy = - spyOn(HTMLElement.prototype, removeEventListener).and.callThrough(); - const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( - 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], - handleEventSpy)])); + it('should listen to DOM events', () => { + const handleEventSpy = jasmine.createSpy('handleEvent'); + const removeListenerSpy = + spyOn(HTMLElement.prototype, removeEventListener).and.callThrough(); + const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( + 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], + handleEventSpy)])); - rootNodes[0].click(); + rootNodes[0].click(); - expect(handleEventSpy).toHaveBeenCalled(); - let handleEventArgs = handleEventSpy.calls.mostRecent().args; - expect(handleEventArgs[0]).toBe(view); - expect(handleEventArgs[1]).toBe('click'); - expect(handleEventArgs[2]).toBeTruthy(); + expect(handleEventSpy).toHaveBeenCalled(); + let handleEventArgs = handleEventSpy.calls.mostRecent().args; + expect(handleEventArgs[0]).toBe(view); + expect(handleEventArgs[1]).toBe('click'); + expect(handleEventArgs[2]).toBeTruthy(); - Services.destroyView(view); + Services.destroyView(view); - expect(removeListenerSpy).toHaveBeenCalled(); - }); + expect(removeListenerSpy).toHaveBeenCalled(); + }); it('should listen to window events', () => { const handleEventSpy = jasmine.createSpy('handleEvent'); @@ -253,52 +251,49 @@ const removeEventListener = '__zone_symbol__removeEventListener' as 'removeEvent expect(removeListenerSpy).toHaveBeenCalled(); }); - fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') - .it('should preventDefault only if the handler returns false', () => { - let eventHandlerResult: any; - let preventDefaultSpy: jasmine.Spy = undefined !; + it('should preventDefault only if the handler returns false', () => { + let eventHandlerResult: any; + let preventDefaultSpy: jasmine.Spy = undefined !; - const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( - 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], - (view, eventName, event) => { - preventDefaultSpy = spyOn(event, 'preventDefault').and.callThrough(); - return eventHandlerResult; - })])); + const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( + 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], + (view, eventName, event) => { + preventDefaultSpy = spyOn(event, 'preventDefault').and.callThrough(); + return eventHandlerResult; + })])); - eventHandlerResult = undefined; - rootNodes[0].click(); - expect(preventDefaultSpy).not.toHaveBeenCalled(); + eventHandlerResult = undefined; + rootNodes[0].click(); + expect(preventDefaultSpy).not.toHaveBeenCalled(); - eventHandlerResult = true; - rootNodes[0].click(); - expect(preventDefaultSpy).not.toHaveBeenCalled(); + eventHandlerResult = true; + rootNodes[0].click(); + expect(preventDefaultSpy).not.toHaveBeenCalled(); - eventHandlerResult = 'someString'; - rootNodes[0].click(); - expect(preventDefaultSpy).not.toHaveBeenCalled(); + eventHandlerResult = 'someString'; + rootNodes[0].click(); + expect(preventDefaultSpy).not.toHaveBeenCalled(); - eventHandlerResult = false; - rootNodes[0].click(); - expect(preventDefaultSpy).toHaveBeenCalled(); - }); + eventHandlerResult = false; + rootNodes[0].click(); + expect(preventDefaultSpy).toHaveBeenCalled(); + }); - fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') - .it('should report debug info on event errors', () => { - const handleErrorSpy = spyOn(TestBed.get(ErrorHandler), 'handleError'); - const addListenerSpy = - spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); - const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( - 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], - () => { throw new Error('Test'); })])); + it('should report debug info on event errors', () => { + const handleErrorSpy = spyOn(TestBed.get(ErrorHandler), 'handleError'); + const addListenerSpy = spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); + const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( + 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], + () => { throw new Error('Test'); })])); - callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); - const err = handleErrorSpy.calls.mostRecent().args[0]; - expect(err).toBeTruthy(); - expect(err.message).toBe('Test'); - const debugCtx = getDebugContext(err); - expect(debugCtx.view).toBe(view); - expect(debugCtx.nodeIndex).toBe(0); - }); + callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); + const err = handleErrorSpy.calls.mostRecent().args[0]; + expect(err).toBeTruthy(); + expect(err.message).toBe('Test'); + const debugCtx = getDebugContext(err); + expect(debugCtx.view).toBe(view); + expect(debugCtx.nodeIndex).toBe(0); + }); }); } }); diff --git a/packages/core/test/view/provider_spec.ts b/packages/core/test/view/provider_spec.ts index 52d044a946..3d3bcd88c7 100644 --- a/packages/core/test/view/provider_spec.ts +++ b/packages/core/test/view/provider_spec.ts @@ -13,7 +13,6 @@ import {TestBed, withModule} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, createRootView, createAndGetRootNodes, compViewDef, compViewDefFactory} from './helper'; -import {fixmeIvy} from '@angular/private/testing'; { describe(`View Providers`, () => { @@ -138,36 +137,34 @@ import {fixmeIvy} from '@angular/private/testing'; expect(instance.dep instanceof Dep).toBeTruthy(); }); - fixmeIvy( - 'FW-807: NgModule injector doesn\'t report full search path if a token is not found') - .it('should not inject deps from sibling root elements', () => { - const rootElNodes = [ - elementDef(0, NodeFlags.None, null, null, 1, 'span'), - directiveDef(1, NodeFlags.None, null, 0, Dep, []), - elementDef(2, NodeFlags.None, null, null, 1, 'span'), - directiveDef(3, NodeFlags.None, null, 0, SomeService, [Dep]), - ]; + it('should not inject deps from sibling root elements', () => { + const rootElNodes = [ + elementDef(0, NodeFlags.None, null, null, 1, 'span'), + directiveDef(1, NodeFlags.None, null, 0, Dep, []), + elementDef(2, NodeFlags.None, null, null, 1, 'span'), + directiveDef(3, NodeFlags.None, null, 0, SomeService, [Dep]), + ]; - expect(() => createAndGetRootNodes(compViewDef(rootElNodes))) - .toThrowError( - 'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' + - ' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' + - ' NullInjectorError: No provider for Dep!'); + expect(() => createAndGetRootNodes(compViewDef(rootElNodes))) + .toThrowError( + 'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' + + ' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' + + ' NullInjectorError: No provider for Dep!'); - const nonRootElNodes = [ - elementDef(0, NodeFlags.None, null, null, 4, 'span'), - elementDef(1, NodeFlags.None, null, null, 1, 'span'), - directiveDef(2, NodeFlags.None, null, 0, Dep, []), - elementDef(3, NodeFlags.None, null, null, 1, 'span'), - directiveDef(4, NodeFlags.None, null, 0, SomeService, [Dep]), - ]; + const nonRootElNodes = [ + elementDef(0, NodeFlags.None, null, null, 4, 'span'), + elementDef(1, NodeFlags.None, null, null, 1, 'span'), + directiveDef(2, NodeFlags.None, null, 0, Dep, []), + elementDef(3, NodeFlags.None, null, null, 1, 'span'), + directiveDef(4, NodeFlags.None, null, 0, SomeService, [Dep]), + ]; - expect(() => createAndGetRootNodes(compViewDef(nonRootElNodes))) - .toThrowError( - 'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' + - ' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' + - ' NullInjectorError: No provider for Dep!'); - }); + expect(() => createAndGetRootNodes(compViewDef(nonRootElNodes))) + .toThrowError( + 'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' + + ' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' + + ' NullInjectorError: No provider for Dep!'); + }); it('should inject from a parent element in a parent view', () => { createAndGetRootNodes(compViewDef([ @@ -183,17 +180,16 @@ import {fixmeIvy} from '@angular/private/testing'; expect(instance.dep instanceof Dep).toBeTruthy(); }); - fixmeIvy('FW-807: NgModule injector don\'t report full search path if a token is not found') - .it('should throw for missing dependencies', () => { - expect(() => createAndGetRootNodes(compViewDef([ - elementDef(0, NodeFlags.None, null, null, 1, 'span'), - directiveDef(1, NodeFlags.None, null, 0, SomeService, ['nonExistingDep']) - ]))) - .toThrowError( - 'StaticInjectorError(DynamicTestModule)[nonExistingDep]: \n' + - ' StaticInjectorError(Platform: core)[nonExistingDep]: \n' + - ' NullInjectorError: No provider for nonExistingDep!'); - }); + it('should throw for missing dependencies', () => { + expect(() => createAndGetRootNodes(compViewDef([ + elementDef(0, NodeFlags.None, null, null, 1, 'span'), + directiveDef(1, NodeFlags.None, null, 0, SomeService, ['nonExistingDep']) + ]))) + .toThrowError( + 'StaticInjectorError(DynamicTestModule)[nonExistingDep]: \n' + + ' StaticInjectorError(Platform: core)[nonExistingDep]: \n' + + ' NullInjectorError: No provider for nonExistingDep!'); + }); it('should use null for optional missing dependencies', () => { createAndGetRootNodes(compViewDef([