Skip to content

Commit cb72fb3

Browse files
committed
app component tests
1 parent 9722624 commit cb72fb3

2 files changed

Lines changed: 137 additions & 4 deletions

File tree

src/components/app.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import { AuthService } from '../services/authservice';
1414
template: `
1515
<h2>Github battle <span>an Angular example app by <a href="https://edument.se">Edument</a></span></h2>
1616
<div *ngIf="!loginName">
17-
You have to <button (click)="logIn()">log in</button>, otherwise Github's API limits won't let us have enough fun!
17+
You have to <button class="qa-login-button" (click)="logIn()">log in</button>, otherwise Github's API limits won't let us have enough fun!
1818
</div>
19-
<div *ngIf="error">
19+
<div *ngIf="error" class="qa-error-section">
2020
Something went wrong :(
2121
</div>
22-
<div *ngIf="loginName">
22+
<div *ngIf="loginName" class="qa-loggedin">
2323
Logged in as {{loginName}}.
2424
<hr/>
2525
<battle></battle>
@@ -39,7 +39,6 @@ import { AuthService } from '../services/authservice';
3939
`]
4040
})
4141
export class AppComponent {
42-
plrs = ["FOO",null,null]
4342
error = null;
4443
loginName: string
4544
constructor(private authService: AuthService, private zone: NgZone){

src/specs/component.app.spec.ts

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/******************************************
2+
Unit tests for the App component. We need to test...
3+
4+
* template
5+
* login functionality
6+
* correct usage of the Auth service
7+
8+
/*******************************************/
9+
10+
// --------------- Child component stubs -----------------
11+
12+
import { Component } from '@angular/core';
13+
14+
@Component({
15+
selector: 'battle',
16+
template: ''
17+
})
18+
class FakeBattle {}
19+
20+
// --------------- Service mocks ---------------
21+
22+
import * as sinon from 'sinon';
23+
24+
const fakeAuthService = {
25+
signInWithPopup: sinon.stub(),
26+
listenToAuthChanges: sinon.stub()
27+
};
28+
29+
// --------------- Test config ---------------
30+
31+
import { CommonModule } from '@angular/common';
32+
import { AuthService } from '../services/authservice';
33+
import { AppComponent } from '../components/app';
34+
35+
const testModuleConfig = {
36+
imports: [CommonModule],
37+
declarations: [AppComponent, FakeBattle],
38+
providers: [{provide: AuthService, useValue: fakeAuthService}]
39+
}
40+
41+
// --------------- Test suite ---------------
42+
43+
import { TestBed, getTestBed, ComponentFixture } from '@angular/core/testing';
44+
import { expect } from 'chai';
45+
import { DebugElement } from '@angular/core';
46+
47+
let fixture: ComponentFixture<AppComponent>
48+
let instance: AppComponent
49+
let debugElement: DebugElement
50+
let nativeElement: HTMLElement;
51+
52+
describe('AppComponent', () => {
53+
before(() => TestBed.configureTestingModule(testModuleConfig));
54+
after(() => getTestBed().resetTestingModule());
55+
56+
beforeEach(() => {
57+
fixture = TestBed.createComponent(AppComponent);
58+
debugElement = fixture.debugElement;
59+
instance = debugElement.componentInstance;
60+
nativeElement = debugElement.nativeElement;
61+
fixture.detectChanges();
62+
});
63+
64+
it('should instantiate ok', () => {
65+
expect(instance).to.exist;
66+
});
67+
68+
describe('when not logged in', () => {
69+
it('should not render a battle component yet', () => {
70+
expect(nativeElement.querySelector('battle')).to.not.exist;
71+
});
72+
73+
it('should render a login button', () => {
74+
expect(nativeElement.querySelector('.qa-login-button')).to.exist;
75+
});
76+
77+
it('should be listening to auth changes', () => {
78+
expect(fakeAuthService.listenToAuthChanges.called).to.be.true;
79+
expect(fakeAuthService.listenToAuthChanges.lastCall.args[0]).to.be.a('function');
80+
});
81+
82+
it('should not trigger popup immediately', () => {
83+
expect(fakeAuthService.signInWithPopup.called).to.be.false;
84+
});
85+
86+
it('should trigger popup when button is clicked', () => {
87+
nativeElement.querySelector('.qa-login-button').dispatchEvent(new Event('click'));
88+
expect(fakeAuthService.signInWithPopup.called).to.be.true;
89+
});
90+
});
91+
92+
describe('when login error', () => {
93+
beforeEach(() => {
94+
const authCallback = fakeAuthService.listenToAuthChanges.lastCall.args[0];
95+
authCallback({ user: {}, error: Symbol('some error') });
96+
fixture.detectChanges();
97+
});
98+
99+
it('should render an error section', () => {
100+
expect(nativeElement.querySelector('.qa-error-section')).to.exist;
101+
});
102+
103+
it('should still render a login button', () => {
104+
expect(nativeElement.querySelector('.qa-login-button')).to.exist;
105+
});
106+
});
107+
108+
describe('when logged in', () => {
109+
const fakeAuth = {
110+
token: Math.random().toString(),
111+
user: {
112+
displayName: Math.random().toString()
113+
}
114+
};
115+
116+
beforeEach(() => {
117+
const authCallback = fakeAuthService.listenToAuthChanges.lastCall.args[0];
118+
authCallback(fakeAuth);
119+
fixture.detectChanges();
120+
});
121+
122+
it('should not render login button', () => {
123+
expect(nativeElement.querySelector('.qa-login-button')).to.not.exist;
124+
});
125+
126+
it('should render login section with user name', () => {
127+
expect(nativeElement.querySelector('.qa-loggedin').innerHTML).to.contain(fakeAuth.user.displayName);
128+
});
129+
130+
it('should render a battle component', () => {
131+
expect(nativeElement.querySelector('battle')).to.exist;
132+
});
133+
});
134+
});

0 commit comments

Comments
 (0)