
ãã¡ã€ã«ç·šæ
æå§ãã«ãangular-cliã«ãã£ãŠåœ¢æããããããžã§ã¯ãã®æ§é ã äžèŠãªããããã¡ã€ã«ã®äžéšããã£ã«ã¿ãªã³ã°ãããŸããã

Angularã®åäœãã¹ãã¯ãAngularããã³Karmaèªäœã®ãŠãŒãã£ãªãã£ã§ããJasmineã«åºã¥ããŠããŸãã ãããã®ããã±ãŒãžã®èª¬æã¯å ¬åŒãŠã§ããµã€ãã§æäŸãããŠããã®ã§ãç§ã¯ãããè€è£œããŸããã èŠããã«ãJasmineã¯åºæ¬çãªãã¹ãã«å¿ èŠãªæ©èœãæäŸãããã¬ãŒã ã¯ãŒã¯ã§ããAngularãŠãŒãã£ãªãã£ã䜿çšãããšãã¹ãç°å¢ã䜿çšã§ããKarmaã¯ãã¹ããå®è¡ã§ããŸãã

ãã¹ããã¡ã€ã«èªäœã«ã¯ãæ¡åŒµåã®åã«specãè¿œå ããŠååãä»ããããŸãã ãã®ãã¿ãŒã³ã«ãããšïŒ* .spec.ts Karmaã¯ããããèŠã€ããŸãã ãã¹ãã®å Žæã«é¢ããã³ã³ã»ã³ãµã¹ã¯ãããŸããã ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ãã¹ãçšã«ããã¹ããªããžã§ã¯ããšå¥ã®ãã£ã¬ã¯ããªã«ãè¿ããå Žæãèš±å¯ããŸããã AngularããŒã ã«ã¯ããªããžã§ã¯ãã®é£ã«ãã¹ããé 眮ãããšããå©ç¹ããããŸãã
- ãã®ãããªãã¹ãã¯èŠã€ããããã§ãã
- ã¢ããªã±ãŒã·ã§ã³ã®äžéšã«ãã¹ãããªãããšãããã«ããããŸãã
- ãšã³ãã£ãã£ã®ãœãŒã¹ã³ãŒãã移åãããšãã¯ããã¹ãã移åããããšãå¿ããªãã§ãã ããã
- ãšã³ãã£ãã£ã®ãœãŒã¹ã³ãŒãã®ååãå€æŽãããšãããã¹ãã®ååãå¿ããªãã§ãã ããã
angle-cliã§ææ¡ããããªãã·ã§ã³ãéžæããŸãã-ãã¹ãã¯ãªããžã§ã¯ãã®é£ã«ãããŸãã
ã«ã«ãã®ã»ããã¢ãã
Angularã¢ããªã±ãŒã·ã§ã³ããã¹ãããããã®ãšã³ããªãã€ã³ãã¯ãsrc / test.tsãã¡ã€ã«ã§ãããã®ãã¡ã€ã«ã¯ãå¿ èŠãªãã¹ãŠã®ããã±ãŒãžãã€ã³ããŒããã* .spec.tsãã³ãã¬ãŒãã䜿çšããŠãã¹ããã¡ã€ã«ãåéãããã¹ãå®è¡ã·ã¹ãã ïŒãã®å Žåã¯KarmaïŒãéå§ããŸãã ãããžã§ã¯ãäœæåŸã®ãã¡ã€ã«èªäœã¯æ¬¡ã®ããã«ãªããŸãã
// This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/dist/long-stack-trace-zone'; import 'zone.js/dist/proxy.js'; import 'zone.js/dist/sync-test'; import 'zone.js/dist/jasmine-patch'; import 'zone.js/dist/async-test'; import 'zone.js/dist/fake-async-test'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. declare const __karma__: any; declare const require: any; // Prevent Karma from running prematurely. __karma__.loaded = function () {}; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting() ); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // And load the modules. context.keys().map(context); // Finally, start Karma to run the tests. __karma__.start();
ããã§ãç§ãééããåé¡ã«æ³šæãæããããšæããŸãã ã€ã³ããŒãã®é åºã¯éèŠã§ãããå€æŽãã䟡å€ã¯ãããŸãããããããªããšãã«ãŒããéåžžã«æé»çã§ãããšã©ãŒã«å¯Ÿå¿ããããšãã§ããŸãã ãããã£ãŠãã€ã³ããŒããªã¹ãã®æåŸã«ãµãŒãããŒãã£ã®ããã±ãŒãžãè¿œå ãããã¡ã€ã«ã®å é ã«/ * tslintïŒdisable * /ãã©ã°ãè¿œå ããŠãªã³ã¿ãŒãç¡å¹ã«ãããããã®ãã¡ã€ã«ããã®æ§æããé€å€ããããšããå§ãããŸãã
ãã¹ããèšè¿°ããåã«ãããããå®è¡ããKarmaãæ§æããå¿ èŠããããŸãã åææ§æã¯æ¬¡ã®ãšããã§ãã
// Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular/cli'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular/cli/plugins/karma'), require('karma-mocha-reporter'), ], client:{ clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { reports: [ 'html', 'lcovonly' ], fixWebpackSourcePaths: true }, angularCli: { environment: 'dev' }, reporters: ['mocha'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }); };
å¯èœãªãã¹ãŠã®Karmaèšå®ã®èª¬æã¯ãè°è«ã®ããã®å¥åã®ãããã¯ã§ããããã䜿çšãããã®ã®ã¿ã«çŠç¹ãåœãŠãŸãã
- browsers ïŒå®è¡ãããã©ãŠã¶ãŒã®ãªã¹ãã å®å šãªChromeã䜿çšãããŠãããããã¡ã¢ãªæ¶è²»éã®å°ãªãChromeHeadlessã䜿çšããããšã奜ã¿ãŸãã ãã ãã䜿çšããã«ã¯Chrome> = 59ãå¿ èŠã§ããããšã«æ³šæããŠãã ããã
- logLevel ïŒãã詳现ãªãã°ãååŸããããã«ããã¹ã¯ãªãããšã©ãŒããªã©ã®ãšã©ãŒãçºçããå Žåã«LOG_ERRORãšLOG_DEBUGã䜿çšããŸãã èš±å¯ãããå€ã¯5ã§ãã
- config.LOG_DISABLE
- config.LOG_ERROR
- config.LOG_WARN
- config.LOG_INFO
- config.LOG_DEBUG
- ã¬ããŒã¿ãŒ ïŒã¡ãã»ãŒãžãšçµæã®è¡šç€ºãæ
åœããé
åã npmjsã®ãªãŒãã³ã¹ããŒã¹ã§ã¯ãã»ãŒãã¹ãŠã®åºåãã¶ã€ã³ãèŠã€ããããšãã§ããŸããç§ã«ãšã£ãŠã¯ãã³ã³ãœãŒã«çšã®karma-mocha-reporterããã©ãŠã¶ã§ã®åºåçšã®istanbul-thresholdã決å®ããŸããã mochaãæäŸãããã°ã¯ã³ã³ãœãŒã«ã«ãšã£ãŠéåžžã«æçã§ãããIstanbulã¯ãã©ãŠã¶ãžã®åºåãæäŸããŠãããŸããïŒlogLevelïŒconfig.LOG_DEBUGãšãšãã«ãã©ãŠã¶ã®å®å
šèµ·åã䜿çšããŸãã
- ãã©ã°ã€ã³ ååã瀺ãããã«ãããã¯ã«ã«ãã䜿çšãããã©ã°ã€ã³ã®é
åã§ãã ããã§ã¯ãã³ãŒãã«ãã¬ããžã衚瀺ããã³èšç®ããããã®ã¬ããŒã¿ãŒããã©ãŠã¶ãŒããã©ã°ã€ã³ãèŠã€ããããšãã§ããŸãã å©çšå¯èœãªãã©ã°ã€ã³ã®ãªã¹ãã¯ãã¡ãïŒhttps://www.npmjs.com/browse/keyword/karma-pluginïŒã«ãããŸãã
- æšæºæ§æã§ã¯ã filesãã©ã¡ãŒã¿ãŒã¯ãããŸããããã®ãã©ã¡ãŒã¿ãŒã®å€ã®ãªã¹ãã¯ããã¹ãäžã«Karmaã«ãã£ãŠããŠã³ããŒããããŸãã ãã®ãªã¹ãã䜿çšããŠãæšæºã®ããŒããããªã¢ã«ãè¿œå ãããã®ããŒãã«é¢ããèŠåãåé€ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã¯æ¬¡ã®ãšããã§ãã
files: [{ pattern: './node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, watched: true }],
å«ãŸããŠãããã©ã¡ãŒã¿ãŒã«ã¯ãç£èŠãããŠããã¢ã»ã³ããªå ã®ãã¡ã€ã«ãå«ãŸããŸã-ãã¡ã€ã«å ã®å€æŽã远跡ããŸãã
- ãŸãã ããªããã»ããµãã©ã¡ãŒã¿ã䜿çšããŠãAPIã³ãŒãã«ãã¬ããžãã§ãã¯ããªãã«ããŸãã
preprocessors: { '!(./src/api)': ['coverage'] },
ããã§ãæºåãã§ãŒãºãå®äºãããã¹ããå®è¡ã§ããŸãã angle-cliã䜿çšããŠåœ¢æããããããžã§ã¯ãã®å Žåãng testã³ãã³ãã䜿çšãããŸãã ããã«ã¯ããã€ãã®ãªãã·ã§ã³ããããŸãã ããã®ãã¡--sourcemapã«ã€ããŠèšåããããšæããŸãã ååã«åºã¥ããŠããã®ãã©ã¡ãŒã¿ãŒã«ã¯ãã¹ãã®ãœãŒã¹ããããå«ãŸããŸãã ããããããã¯ãXMLHttpRequestïŒfailed to loadããšãããšã©ãŒãåå ã§ãã ãã®ãã©ã¡ãŒã¿ãŒã«falseãèšå®ãããšããã®åé¡ã解決ããŸãã
ã³ã³ããŒãã³ããã¹ã
Angularã³ã³ããŒãã³ãã®æåã§æãéèŠãªãã¹ãããŒã«ã¯TestBedã§ãã 圌女ã®ã¢ã€ãã¢ã¯ãã³ã³ããŒãã³ãã¢ãžã¥ãŒã«ãšåãã§ããããã¹ãç°å¢ã§äœæãããã¢ããªã±ãŒã·ã§ã³ããåé¢ãããå¥åã®ã¢ãžã¥ãŒã«ãäœæããããšã§ãã
TestBedãäœæããã«ã¯ã configureTestingModuleã¡ãœãããåŒã³åºãããã¡ã¿ããŒã¿ãªããžã§ã¯ããæž¡ãããŸãã ãã®ã¡ãœããã¯ãã³ã³ããŒãã³ããå ã®ç¶æ ã«ãªãããã«ãåãã¹ãã®åã«éåæã§åŒã³åºãå¿ èŠããããŸãã beforeEachïŒasyncïŒïŒ=> {}ïŒ;ãšããã¡ãœããããããŸãã
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ AppComponent ], }).compileComponents(); }));
äŸãããããããã«ããã¹ãçšã®ã³ã³ããŒãã³ãã®é åã宣èšããŸãïŒãã®å Žåã¯1ã€ã®ã¿ïŒã å°æ¥çã«ã¯ãäœæ¥ã«å¿ èŠãªã³ã³ããŒãã³ãã®è¿œå ãã¢ãžã¥ãŒã«ããã£ã¬ã¯ãã£ããããã³ãã€ãã®ã€ã³ããŒããå¯èœã«ãªããŸãã configureTestingModuleã¡ãœããã¯TestBedã¯ã©ã¹ãè¿ããŸããããã«ãããcompileComponentsãªã©ã®éçã¡ãœãããåŒã³åºãããšãã§ããŸãã ãã®ã¡ãœããã¯ãã¢ãžã¥ãŒã«ã®ãã¹ãŠã®ã³ã³ããŒãã³ããéåæçã«ã³ã³ãã€ã«ãããã³ãã¬ãŒããšã¹ã¿ã€ã«ããã€ã³ã©ã€ã³ãã«å€æããŸãã ãã®åŸãTestBed.createComponentïŒïŒã¡ãœããã䜿çšããŠãã³ã³ããŒãã³ãã€ã³ã¹ã¿ã³ã¹ãåæçã«åä¿¡ã§ããŸãã ãã®ã¡ãœããã¯ComponentFixtureã®ã€ã³ã¹ã¿ã³ã¹ãè¿ããŸããããã«ãããDebugElementãä»ããŠã³ã³ããŒãã³ããšãã®DOMã«çŽæ¥ã¢ã¯ã»ã¹ã§ããŸãã
æãåçŽãªã³ã³ããŒãã³ããã¹ãã®çµæãã¡ã€ã«
import { TestBed, async } from '@angular/core/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ AppComponent ], }).compileComponents(); })); it('should create the app', async(() => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; expect(app).toBeTruthy(); })); it(`should have as title 'app'`, async(() => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; expect(app.title).toEqual('app'); })); it('should render title in a h1 tag', async(() => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); })); });
ã³ã³ããŒãã³ãã³ãŒã
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; }
ã³ã³ããŒãã³ããã³ãã¬ãŒã
<div style="text-align:center"> <h1> Welcome to {{title}}! </h1> </div>
äŸåé¢ä¿ã®ããã³ã³ããŒãã³ãã®ãã¹ã
éçºè ã¯ãå®éã®ãµãŒãã¹ã䜿çšããŠã¯ãªããããã¹ãã«ãã¹ã¿ãããè¿œå ããå¿ èŠããããšããäºå®ã«çŠç¹ãåœãŠãŠããŸãã
ã³ã³ããŒãã³ãã³ãŒã
import {Component} from '@angular/core'; import {SomeServiceService} from "./some-service.service"; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; name: string; constructor(private someService: SomeServiceService) { this.name = this.someService.getName(); } }
ãã¹ãã³ãŒãïŒ
import { TestBed, async } from '@angular/core/testing'; import { AppComponent } from './app.component'; import { SomeServiceService } from "./some-service.service"; const SomeServiceStub = { getName: () => 'some name' }; describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ AppComponent ], providers: [ // { provide: SomeServiceService, useValue: SomeServiceStub } ] }).compileComponents(); })); it('token should test component with dependency', () => { // root-injector // , beforeEach const someService = TestBed.get(SomeServiceService); expect(someService.getName()).toEqual('some name'); }); // , inject, , root-injector. // , it('token should test component with dependency', inject(([SomeServiceService], (someService: SomeServiceService)) => { const someService = TestBed.get(SomeServiceService); expect(someService.getName()).toEqual('some name'); })); });
ãã®å ŽåãSomeServiceã®åäœãç¹°ãè¿ããªããžã§ã¯ããã€ãŸãgetNameã¡ãœãããå«ããªããžã§ã¯ãã䜿çšããŸãã å®éã®ãµãŒãã¹ã®ä»£ããã«ããã䜿çšããã«ã¯ããstubãã®å€ãå€ãšããŠserviceããã³useValueãæå®ããproviderããããã£ãæã€ãªããžã§ã¯ãããããã€ããŒé åã«è¿œå ããå¿ èŠããããŸãã
SwaggerããŒã¹ã®APIã䜿çšããŠããããããµãŒããŒãšéä¿¡ããããã®ãµãŒãã¹ãèšè¿°ããå¿ èŠã¯ãããŸããã æ®ã£ãŠããã®ã¯ãã¡ãœãããåŒã³åºããŠçµæãåŠçããããšã ãã§ãã ãããŠããã§ãã¡ãœããã®å®è£ ãæŸæ£ããã€ã³ãžã§ã¯ã¿ãŒãä»ããŠãµãŒãã¹ãååŸããäœè£ããããŸãã
ããã¯ãMockBackendã䜿çšããŠè¡ãããŸãã ã€ãŸãããµãŒãã¹ã§ã¯ãªããããã¯ãšã³ãèªäœã眮ãæããŠããŸãã
ã³ã³ããŒãã³ãã³ãŒã
@Component({ selector: 'app-login', templateUrl: 'login.component.html', styleUrls: ['login.component.less'] }) export class LoginComponent implements OnInit { loading: boolean; loginForm: FormGroup; error: any; constructor(private router: Router, private authService: UserService, private fb: FormBuilder, private ref: ChangeDetectorRef) { } ngOnInit() { this.loading = false; this.loginForm = this.fb.group({ login: [''], password: [''] }); } get login() { return this.loginForm.get('login'); } get password() { return this.loginForm.get('password'); } submit() { this.loading = true; this.submitted = true; // const data = { 'login': this.loginForm.controls['login'].value, 'password': this.loginForm.controls['password'].value }; // // - /home/main // 400 401 - this.authService.signIn(data).subscribe( resp => this.router.navigateByUrl('/home/main'), error => { this.loading = false; error.status === 401 || error.status === 400 ? this.error = {errorText: error.title} : ''; this.ref.detectChanges(); } ); } }
ãã¹ãã³ãŒã
class MockError extends Response implements Error { name: any; message: any; } describe('LoginComponent', () => { let component: LoginComponent; let fixture: ComponentFixture<LoginComponent>; let mockBackend: MockBackend; const authUrl = 'login_url'; const testUser = { login: 'test', password: 'test' }; const successResponse = new Response( new ResponseOptions({ status: 200, body: '' }) ); const errorResponse = new MockError( new ResponseOptions({ type: ResponseType.Error, status: 401, body: JSON.stringify({ status: 401, title: 'Unauthorized', } ) }) ); beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [LoginComponent], imports: [ FormsModule, HttpModule, RouterTestingModule.withRoutes([]), ], providers: [ AuthService, {provide: XHRBackend, useClass: MockBackend} ], }).compileComponents(); mockBackend = TestBed.get(XHRBackend); mockBackend.connections.subscribe((connection: MockConnection) => { if (connection.request.method === RequestMethod.Post) { expect(connection.request.url).toEqual(authUrl); (connection.request.getBody() === JSON.stringify(testUser)) ? connection.mockRespond(successResponse) : connection.mockError(errorResponse); } else { connection.mockError(errorResponse); } }); })); beforeEach(() => { fixture = TestBed.createComponent(LoginComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should login correctly', inject([Router], (router: Router) => { const spy = spyOn(router, 'navigateByUrl'); const login = component.loginForm.controls['login']; const password = component.loginForm.controls['password']; login.setValue('test'); password.setValue('test'); fixture.detectChanges(); component.submit(); fixture.detectChanges(); const navArgs = spy.calls.first().args[0]; expect(navArgs).toEqual('/home/main'); })); it('should fail login', () => { const login = component.loginForm.controls['login']; const password = component.loginForm.controls['password']; const errorResponse = { errorText: 'Unauthorized' }; login.setValue('testad'); password.setValue('testad'); fixture.detectChanges(); component.submit(); fixture.detectChanges(); expect(component.error).toEqual(errorResponse); }); });
ãã°ã€ã³ããã©ãŒã ããã®ãã¹ã¯ãŒããååŸããç¹å®ã®URLã«éä¿¡ãããªã³ã¯ãhome / mainããã¯ãªãã¯ãããããšã©ãŒãåŠçããŠè¡šç€ºããã³ã³ããŒãã³ãããããŸãã
ãµãŒãã¹ã®ã¹ã¿ãã䜿çšããããã®ã¡ãœãããå®è£ ããªãããã«ãMockBackendã䜿çšããŸããMockBackendã¯ãèŠæ±ãåŠçããäºåå®çŸ©ãããå¿çãè¿ããŸãã ãããè¡ãã«ã¯ããŸãMockBackendã宣èšããäºæ³ãããURLãæå®ããŠããªã¯ãšã¹ãã«å«ããå¿ èŠãããããŒã¿ã決å®ããŸãã
let mockBackend: MockBackend; const authUrl = 'login_url'; const testUser = { login: 'test', password: 'test' };
次ã«ãçããã©ã®ããã«èŠãããã決å®ããŸãã èŠæ±ãæåãããšç©ºã®å¿çãè¿ããã誀ã£ãå¿çã¯ã¹ããŒã¿ã¹401ãšãšã©ãŒåã®å¿çãè¿ããšããŸãã
const successResponse = new Response( new ResponseOptions({ status: 200, body: '' }) ); const errorResponse = new MockError( new ResponseOptions({ type: ResponseType.Error, status: 401, body: JSON.stringify({ status: 401, title: 'Unauthorized', } ) }) );
ããã«ããã¹ãã¢ãžã¥ãŒã«ãæ§æããåŸãMockBackendãååŸããŠæ¥ç¶ããµãã¹ã¯ã©ã€ãããŸãã POSTã¡ãœãããæ³å®ãããªã¯ãšã¹ãã®URLãäžèšã§ç€ºãããã®ã«äžèŽãããŸãã ãŸããèŠæ±æ¬æãæåŸ ã©ããã§ããããšã確èªããŠãã ããã
mockBackend = TestBed.get(XHRBackend); mockBackend.connections.subscribe((connection: MockConnection) => { if (connection.request.method === RequestMethod.Post) { expect(connection.request.url).toEqual(authUrl); (connection.request.getBody() === JSON.stringify(testUser)) ? connection.mockRespond(successResponse) : connection.mockError(errorResponse); } else { connection.mockError(errorResponse); } });
ãã¹ãã§è¡ããªããã°ãªããªãããšã¯ãã«ãŒã¿ãŒãååŸããããšã§ãïŒãªã¯ãšã¹ããæåãããšç§»è¡ãè¡ãããããïŒããã°ã€ã³æ å ±ãå ¥åãã移è¡ãå®äºããããšã確èªããŸãã
it('should login correctly', inject([Router], (router: Router) => { const spy = spyOn(router, 'navigateByUrl'); const login = component.loginForm.controls['login']; const password = component.loginForm.controls['password']; login.setValue('test'); password.setValue('test'); fixture.detectChanges(); component.submit(); fixture.detectChanges(); const navArgs = spy.calls.first().args[0]; expect(navArgs).toEqual('/home/main'); }));
å ¥åããŒã¿ãšåºåããŒã¿ã䜿çšããŠã³ã³ããŒãã³ãããã¹ããã
ãåãã®ããã«ãã³ã³ããŒãã³ãã¯@Inputããã³@Outputãã³ã¬ãŒã¿ãŒãšããããã£ãä»ããŠããŒã¿ã亀æã§ããŸãã ããšãã°ã次ã®ããã«ïŒ
芪ã³ã³ããŒãã³ãïŒ
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: '<child-comp [userName]="name" [userSurname]="surname"></child-comp>' }) export class ParentComponent { name = 'Some name'; surname = 'Some surname'; }
ChildComponentïŒ
import { Input, Component} from '@angular/core'; @Component({ selector: 'child-comp', template: `<p> : {{userName}}</p> <p> : {{userSurname}}</p>` }) export class ChildComponent{ @Input() userName: string; @Input() userSurname:string; }
芪ã³ã³ããŒãã³ãã®ãã¹ããæ£ããå®è¡ããã«ã¯ã宣èšé åã§åã³ã³ããŒãã³ãã宣èšããå¿ èŠããããŸãã
parent.component.spec.ts
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ParentComponent} from './parent.component'; import {ChildComponent} from '../child/child.component'; describe('ParentComponent', () => { let component: ParentComponent; let fixture: ComponentFixture<ParentComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ParentComponent, ChildComponent] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(ParentComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); });
ãŸããåã³ã³ããŒãã³ãã®å Žåã¯ãå ¥åãã©ã¡ãŒã¿ãŒãæž¡ãå¿ èŠããããŸãã æãç°¡åãªæ¹æ³ã¯ãã³ã³ããŒãã³ãã®äœæåŸã«ãããã®å€ãæåã§æå®ããããšã§ãã
child.component.spec.ts
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChildComponent } from './child.component'; describe('ChildComponent', () => { let component: ChildComponent; let fixture: ComponentFixture<ChildComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ ChildComponent ] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(ChildComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); component.userName = 'some name'; expect(component.userName).toEqual('some name'); }); });