refactor(ivy): move di tests for Attribute to acceptance (#29299)

PR Close #29299
This commit is contained in:
cexbrayat 2019-03-13 15:31:57 +01:00 committed by Andrew Kushnir
parent b945bc3a9e
commit 0d66844ad6
2 changed files with 107 additions and 124 deletions

View File

@ -7,7 +7,7 @@
*/ */
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {Attribute, ChangeDetectorRef, Component, Directive, Inject, LOCALE_ID, Optional, Pipe, PipeTransform, SkipSelf, ViewChild} from '@angular/core'; import {Attribute, ChangeDetectorRef, Component, Directive, EventEmitter, Inject, Input, LOCALE_ID, Optional, Output, Pipe, PipeTransform, SkipSelf, ViewChild} from '@angular/core';
import {ViewRef} from '@angular/core/src/render3/view_ref'; import {ViewRef} from '@angular/core/src/render3/view_ref';
import {TestBed} from '@angular/core/testing'; import {TestBed} from '@angular/core/testing';
@ -155,6 +155,78 @@ describe('di', () => {
describe('@Attribute', () => { describe('@Attribute', () => {
it('should inject attributes', () => {
@Directive({selector: '[dir]'})
class MyDir {
constructor(
@Attribute('exist') public exist: string,
@Attribute('nonExist') public nonExist: string) {}
}
@Component({template: '<div dir exist="existValue" other="ignore"></div>'})
class MyComp {
@ViewChild(MyDir) directiveInstance !: MyDir;
}
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();
const directive = fixture.componentInstance.directiveInstance;
expect(directive.exist).toBe('existValue');
expect(directive.nonExist).toBeNull();
});
it('should inject attributes on <ng-template>', () => {
@Directive({selector: '[dir]'})
class MyDir {
constructor(
@Attribute('exist') public exist: string,
@Attribute('dir') public myDirectiveAttrValue: string) {}
}
@Component(
{template: '<ng-template dir="initial" exist="existValue" other="ignore"></ng-template>'})
class MyComp {
@ViewChild(MyDir) directiveInstance !: MyDir;
}
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();
const directive = fixture.componentInstance.directiveInstance;
expect(directive.exist).toBe('existValue');
expect(directive.myDirectiveAttrValue).toBe('initial');
});
it('should inject attributes on <ng-container>', () => {
@Directive({selector: '[dir]'})
class MyDir {
constructor(
@Attribute('exist') public exist: string,
@Attribute('dir') public myDirectiveAttrValue: string) {}
}
@Component({
template: '<ng-container dir="initial" exist="existValue" other="ignore"></ng-container>'
})
class MyComp {
@ViewChild(MyDir) directiveInstance !: MyDir;
}
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();
const directive = fixture.componentInstance.directiveInstance;
expect(directive.exist).toBe('existValue');
expect(directive.myDirectiveAttrValue).toBe('initial');
});
it('should be able to inject different kinds of attributes', () => { it('should be able to inject different kinds of attributes', () => {
@Directive({selector: '[dir]'}) @Directive({selector: '[dir]'})
class MyDir { class MyDir {
@ -181,7 +253,6 @@ describe('di', () => {
expect(directive.otherAttr).toBe('value'); expect(directive.otherAttr).toBe('value');
expect(directive.className).toBe('hello there'); expect(directive.className).toBe('hello there');
expect(directive.inlineStyles).toBe('margin: 1px; color: red;'); expect(directive.inlineStyles).toBe('margin: 1px; color: red;');
}); });
it('should not inject attributes with namespace', () => { it('should not inject attributes with namespace', () => {
@ -210,5 +281,37 @@ describe('di', () => {
expect(directive.namespacedExist).toBeNull(); expect(directive.namespacedExist).toBeNull();
expect(directive.other).toBe('otherValue'); expect(directive.other).toBe('otherValue');
}); });
it('should not inject attributes representing bindings and outputs', () => {
@Directive({selector: '[dir]'})
class MyDir {
@Input() binding !: string;
@Output() output = new EventEmitter();
constructor(
@Attribute('exist') public exist: string,
@Attribute('binding') public bindingAttr: string,
@Attribute('output') public outputAttr: string,
@Attribute('other') public other: string) {}
}
@Component({
template:
'<div dir exist="existValue" [binding]="bindingValue" (output)="outputValue" other="otherValue" ignore="ignoreValue"></div>'
})
class MyComp {
@ViewChild(MyDir) directiveInstance !: MyDir;
}
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();
const directive = fixture.componentInstance.directiveInstance;
expect(directive.exist).toBe('existValue');
expect(directive.bindingAttr).toBeNull();
expect(directive.outputAttr).toBeNull();
expect(directive.other).toBe('otherValue');
});
}); });
}); });

View File

@ -6,14 +6,14 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Attribute, ChangeDetectorRef, ElementRef, Host, INJECTOR, Inject, InjectFlags, Injector, Optional, Renderer2, Self, SkipSelf, TemplateRef, ViewContainerRef, ɵɵdefineInjectable, ɵɵdefineInjector} from '@angular/core'; import {ChangeDetectorRef, ElementRef, Host, INJECTOR, Inject, InjectFlags, Injector, Optional, Renderer2, Self, SkipSelf, TemplateRef, ViewContainerRef, ɵɵdefineInjectable, ɵɵdefineInjector} from '@angular/core';
import {createLView, createNodeAtIndex, createTView} from '@angular/core/src/render3/instructions/shared'; import {createLView, createNodeAtIndex, createTView} from '@angular/core/src/render3/instructions/shared';
import {ComponentType, RenderFlags} from '@angular/core/src/render3/interfaces/definition'; import {ComponentType, RenderFlags} from '@angular/core/src/render3/interfaces/definition';
import {createInjector} from '../../src/di/r3_injector'; import {createInjector} from '../../src/di/r3_injector';
import {ɵɵdefineComponent} from '../../src/render3/definition'; import {ɵɵdefineComponent} from '../../src/render3/definition';
import {bloomAdd, bloomHasToken, bloomHashBitOrFactory as bloomHash, getOrCreateNodeInjectorForNode} from '../../src/render3/di'; import {bloomAdd, bloomHasToken, bloomHashBitOrFactory as bloomHash, getOrCreateNodeInjectorForNode} from '../../src/render3/di';
import {ɵɵProvidersFeature, ɵɵallocHostVars, ɵɵbind, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵdefineDirective, ɵɵdirectiveInject, ɵɵelement, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementProperty, ɵɵelementStart, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵinjectAttribute, ɵɵinterpolation2, ɵɵload, ɵɵprojection, ɵɵprojectionDef, ɵɵreference, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextBinding} from '../../src/render3/index'; import {ɵɵProvidersFeature, ɵɵallocHostVars, ɵɵbind, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵdefineDirective, ɵɵdirectiveInject, ɵɵelement, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementProperty, ɵɵelementStart, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵinterpolation2, ɵɵload, ɵɵprojection, ɵɵprojectionDef, ɵɵreference, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextBinding} from '../../src/render3/index';
import {LContainer, NATIVE} from '../../src/render3/interfaces/container'; import {LContainer, NATIVE} from '../../src/render3/interfaces/container';
import {TNODE} from '../../src/render3/interfaces/injector'; import {TNODE} from '../../src/render3/interfaces/injector';
import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node'; import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node';
@ -2054,126 +2054,6 @@ describe('di', () => {
() => { expect(() => new ComponentFixture(MyComp)).toThrow(); }); () => { expect(() => new ComponentFixture(MyComp)).toThrow(); });
}); });
describe('@Attribute', () => {
let myDirectiveInstance !: MyDirective | null;
class MyDirective {
exists = 'wrong' as string | null;
myDirective = 'wrong' as string | null;
constructor(
@Attribute('exist') existAttrValue: string|null,
@Attribute('myDirective') myDirectiveAttrValue: string|null) {
this.exists = existAttrValue;
this.myDirective = myDirectiveAttrValue;
}
static ngDirectiveDef = ɵɵdefineDirective({
type: MyDirective,
selectors: [['', 'myDirective', '']],
factory: () => myDirectiveInstance =
new MyDirective(ɵɵinjectAttribute('exist'), ɵɵinjectAttribute('myDirective'))
});
}
beforeEach(() => myDirectiveInstance = null);
it('should inject attribute', () => {
let exist = 'wrong' as string | null;
let nonExist = 'wrong' as string | null;
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
ɵɵelementStart(0, 'div', ['exist', 'existValue', 'other', 'ignore']);
exist = ɵɵinjectAttribute('exist');
nonExist = ɵɵinjectAttribute('nonExist');
}
}, 1);
new ComponentFixture(MyApp);
expect(exist).toEqual('existValue');
expect(nonExist).toBeNull();
});
// https://stackblitz.com/edit/angular-scawyi?file=src%2Fapp%2Fapp.component.ts
it('should inject attributes on <ng-template>', () => {
let myDirectiveInstance: MyDirective;
/* <ng-template myDirective="initial" exist="existValue" other="ignore"></ng-template>*/
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
ɵɵtemplate(
0, null, 0, 0, 'ng-template',
['myDirective', 'initial', 'exist', 'existValue', 'other', 'ignore']);
}
if (rf & RenderFlags.Update) {
myDirectiveInstance = getDirectiveOnNode(0);
}
}, 1, 0, [MyDirective]);
new ComponentFixture(MyApp);
expect(myDirectiveInstance !.exists).toEqual('existValue');
expect(myDirectiveInstance !.myDirective).toEqual('initial');
});
// https://stackblitz.com/edit/angular-scawyi?file=src%2Fapp%2Fapp.component.ts
it('should inject attributes on <ng-container>', () => {
let myDirectiveInstance: MyDirective;
/* <ng-container myDirective="initial" exist="existValue" other="ignore"></ng-container>*/
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
ɵɵelementContainerStart(
0, ['myDirective', 'initial', 'exist', 'existValue', 'other', 'ignore']);
ɵɵelementContainerEnd();
}
if (rf & RenderFlags.Update) {
myDirectiveInstance = getDirectiveOnNode(0);
}
}, 1, 0, [MyDirective]);
new ComponentFixture(MyApp);
expect(myDirectiveInstance !.exists).toEqual('existValue');
expect(myDirectiveInstance !.myDirective).toEqual('initial');
});
// https://stackblitz.com/edit/angular-8ytqkp?file=src%2Fapp%2Fapp.component.ts
it('should not inject attributes representing bindings and outputs', () => {
let exist = 'wrong' as string | null;
let nonExist = 'wrong' as string | null;
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
ɵɵelementStart(0, 'div', ['exist', 'existValue', AttributeMarker.Bindings, 'nonExist']);
exist = ɵɵinjectAttribute('exist');
nonExist = ɵɵinjectAttribute('nonExist');
}
}, 1);
new ComponentFixture(MyApp);
expect(exist).toEqual('existValue');
expect(nonExist).toBeNull();
});
it('should not accidentally inject attributes representing bindings and outputs', () => {
let exist = 'wrong' as string | null;
let nonExist = 'wrong' as string | null;
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
ɵɵelementStart(0, 'div', [
'exist', 'existValue', AttributeMarker.Bindings, 'binding1', 'nonExist', 'binding2'
]);
exist = ɵɵinjectAttribute('exist');
nonExist = ɵɵinjectAttribute('nonExist');
}
}, 1);
new ComponentFixture(MyApp);
expect(exist).toEqual('existValue');
expect(nonExist).toBeNull();
});
});
describe('ɵɵinject', () => { describe('ɵɵinject', () => {
describe('bloom filter', () => { describe('bloom filter', () => {
let mockTView: any; let mockTView: any;