Moving tests over to new framework

This commit is contained in:
Matthew Ross 2018-03-21 17:11:02 -04:00
parent d8d385e2a2
commit 80cbbba967
9 changed files with 123 additions and 134 deletions

View File

@ -95,6 +95,8 @@ Developing on TaskBoard is pretty simple too.
2. Run `git checkout dev` to work on the `dev` branch
3. If you don't have it already, install the Angular CLI globally with `npm i -g @angular/cli`
4. Run `npm i` to install dependencies (this also installs the API dependencies)
5. Run `npm run watch` for the build to automatically run after any change.
a. You will need to change permissions on `dist/api/` manually after the first build.
#### Unit Tests

12
package-lock.json generated
View File

@ -6122,9 +6122,9 @@
}
},
"jasmine-core": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz",
"integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=",
"version": "2.99.1",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
"integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
"dev": true
},
"jasmine-spec-reporter": {
@ -6387,9 +6387,9 @@
"dev": true
},
"karma-jasmine-html-reporter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.0.0.tgz",
"integrity": "sha512-SN9R/Pl9cY40yLlc7FkTcfswUr19M6ZZ25eM8X5wtZ0gvp0gneWZbe5lPYcer/Yrbz0D6QUiTSJaEzr3KBPvSg==",
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz",
"integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=",
"dev": true,
"requires": {
"karma-jasmine": "1.1.1"

View File

@ -65,13 +65,13 @@
"bourbon": "5.0.0",
"bourbon-neat": "1.9.0",
"codelyzer": "^4.2.1",
"jasmine-core": "^3.1.0",
"jasmine-core": "^2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.4.2",
"karma-jasmine": "~1.1.1",
"karma-jasmine-html-reporter": "^1.0.0",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-phantomjs-launcher": "^1.0.4",
"protractor": "~5.3.0",
"ts-node": "~5.0.1",

View File

@ -44,11 +44,8 @@ export class ApiInterceptor implements HttpInterceptor {
localStorage.setItem(this.JWT_KEY, response.data[0]);
}
}, (err: any) => {
if (!(err instanceof HttpErrorResponse)) {
return;
}
if ((err.status === 401 || err.status === 400) &&
if ((err instanceof HttpErrorResponse) &&
(err.status === 401 || err.status === 400) &&
(err.url + '').indexOf('login') === -1) {
this.router.navigate(['']);
localStorage.removeItem(this.JWT_KEY);

View File

@ -55,6 +55,8 @@ export class BoardDisplay implements OnInit {
this.userFilter = null;
this.categoryFilter = null;
this.activeBoard = new Board();
this.loading = true;
stringsService.stringsChanged.subscribe(newStrings => {

View File

@ -28,7 +28,7 @@ export class TopNav {
this.version = constants.VERSION;
authService.userChanged
.subscribe(user => this.username = user.username);
.subscribe(user => this.username = user ? user.username : '');
stringsService.stringsChanged.subscribe(newStrings => {
this.strings = newStrings;

View File

@ -1,110 +1,106 @@
import { TestBed, inject } from '@angular/core/testing';
import {
HttpModule,
XHRBackend,
CookieXSRFStrategy,
ResponseOptions,
BrowserXhr,
RequestOptions
} from '@angular/http';
HttpClient,
HttpErrorResponse,
HTTP_INTERCEPTORS
} from '@angular/common/http';
import {
HttpClientTestingModule,
HttpTestingController
} from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import { AuthService } from '../../src/app/shared/auth/auth.service';
import { ApiInterceptor } from '../../src/app/app.api-http';
import { ApiHttp, API_HTTP_PROVIDERS, apiHttpFactory } from '../../src/app/app.api-http';
describe('ApiInterceptor', () => {
const mockAuthService = {
describe('ApiHttp', () => {
let apiHttp;
const routerMock = {
path: 'test',
url: 'test',
navigate(arr) {
this.path = arr[0];
}
};
beforeEach(() => {
const backend = new XHRBackend(new BrowserXhr(),
new ResponseOptions(),
new CookieXSRFStrategy()),
requestOptions = new RequestOptions();
apiHttp = new ApiHttp(backend, requestOptions, <any>routerMock);
});
it('provides API_HTTP_PROVIDERS', () => {
expect(API_HTTP_PROVIDERS).toEqual(jasmine.any(Array));
});
it('provides a factory method', () => {
const actual = apiHttpFactory(null, null, null);
expect(actual).toEqual(jasmine.any(ApiHttp));
});
it('should create', () => {
expect(apiHttp).toBeTruthy();
});
it('has a request method', () => {
expect(apiHttp.request('')).toEqual(jasmine.any(Observable));
});
it('handles the HTTP methods', () => {
expect(apiHttp.get('')).toEqual(jasmine.any(Observable));
expect(apiHttp.post('')).toEqual(jasmine.any(Observable));
expect(apiHttp.put('')).toEqual(jasmine.any(Observable));
expect(apiHttp.delete('')).toEqual(jasmine.any(Observable));
});
it('injects headers', () => {
localStorage.setItem('taskboard.jwt', 'testjwt');
const headers = apiHttp.getRequestOptionArgs().headers;
expect(headers._headers.get('content-type')[0])
.toEqual('application/json');
expect(headers._headers.get('authorization')[0])
.toEqual('testjwt');
});
it('intercepts observable responses', () => {
const response = {
json() {
return {
data: ['testjwt']
};
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule.withRoutes([])
],
providers: [
{
provide: AuthService,
useValue: mockAuthService
},
{
provide: HTTP_INTERCEPTORS,
useClass: ApiInterceptor,
multi: true
}
};
apiHttp.intercept(Observable.of(response))
.map(response => {
expect(localStorage.getItem('taskboard.jwt'))
.toEqual('testjwt');
});
apiHttp.intercept(Observable.throw(null, <any>response))
.catch((err, caught) => {
expect(localStorage.getItem('taskboard.jwt'))
.toEqual('');
]
});
});
it('handles valid responses', () => {
apiHttp.handleResponse({ json: () => ({ data: [ 'jwt' ] }) });
afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => {
httpMock.verify();
}));
expect(localStorage.getItem('taskboard.jwt')).toEqual('jwt');
it('adds Content-Type header',
inject([HttpClient, HttpTestingController],
(http: HttpClient, httpMock: HttpTestingController) => {
http.get('').subscribe(response => {
expect(response).toBeTruthy();
});
it('handles error responses', () => {
var error = {
status: 401,
url: ''
};
const req = httpMock.expectOne(req =>
req.headers.has('Content-Type') && req.headers.get('Content-Type') === 'application/json'
);
expect(req.request.method).toEqual('GET');
apiHttp.handleError(error, null);
req.flush({});
}
)
);
it('adds Authorization header when JWT is present',
inject([HttpClient, HttpTestingController],
(http: HttpClient, httpMock: HttpTestingController) => {
localStorage.setItem('taskboard.jwt', 'fake');
http.post('', {}).subscribe(response => {
expect(response).toBeTruthy();
});
const req = httpMock.expectOne(req =>
req.headers.has('Authorization') && req.headers.get('Authorization') === 'fake'
);
expect(req.request.method).toEqual('POST');
req.flush({ data: ['newToken'] });
expect(localStorage.getItem('taskboard.jwt')).toEqual('newToken');
}
)
)
it('handles errors and clears the JWT',
inject([HttpClient, HttpTestingController],
(http: HttpClient, httpMock: HttpTestingController) => {
localStorage.setItem('taskboard.jwt', 'fake');
http.get('').subscribe(response => {
expect(response).toBeTruthy();
}, error => {
expect(error).toBeTruthy();
});
const req = httpMock.expectOne(req =>
req.headers.has('Content-Type') && req.headers.get('Content-Type') === 'application/json'
);
expect(req.request.method).toEqual('GET');
const error = new HttpErrorResponse({ status: 401 });
req.flush({}, error);
expect(localStorage.getItem('Authorization')).toEqual(null);
}
)
)
expect(localStorage.getItem('taskboard.jwt')).toEqual(null);
});
});

View File

@ -1,25 +1,21 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpModule } from '@angular/http';
import { AppComponent } from '../../src/app/app.component';
import {
Notifications,
NotificationsService,
StringsService
} from '../../src/app/shared/index';
} from '../../src/app/shared/services';
import { SharedModule } from '../../src/app/shared/shared.module';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule,
HttpModule
],
declarations: [
AppComponent,
Notifications
SharedModule
],
declarations: [ AppComponent ],
providers: [
StringsService,
NotificationsService

View File

@ -1,13 +1,10 @@
import { async, TestBed, ComponentFixture } from '@angular/core/testing'
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { BaseRequestOptions, Http } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
@ -17,12 +14,15 @@ import {
Constants,
ContextMenuService,
NotificationsService
} from '../../../src/app/shared/index';
} from '../../../src/app/shared/services';
import { Login } from '../../../src/app/login/login.component';
import { Settings } from '../../../src/app/settings/index';
import { Dashboard } from '../../../src/app/dashboard/index';
import { BoardService, BoardDisplay } from '../../../src/app/board/index';
import { ROUTES } from '../../../src/app/app.routes';
import { SettingsModule } from '../../../src/app/settings/settings.module';
import { SharedModule } from '../../../src/app/shared/shared.module';
import { DashboardModule } from '../../../src/app/dashboard/dashboard.module';
import { BoardDisplay } from '../../../src/app/board/board.component';
import { BoardService } from '../../../src/app/board/board.service';
import { ColumnDisplay } from '../../../src/app/board/column/column.component';
import { TaskDisplay } from '../../../src/app/board/task/task.component';
describe('BoardDisplay', () => {
let component: BoardDisplay,
@ -31,15 +31,19 @@ describe('BoardDisplay', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes(ROUTES),
RouterTestingModule,
HttpClientTestingModule,
FormsModule,
DragulaModule
DragulaModule,
SettingsModule,
SharedModule,
DashboardModule
],
declarations: [
BoardDisplay,
Login,
Settings,
Dashboard
BoardDisplay,
ColumnDisplay,
TaskDisplay
],
providers: [
Title,
@ -49,22 +53,14 @@ describe('BoardDisplay', () => {
StringsService,
ContextMenuService,
NotificationsService,
MockBackend,
BaseRequestOptions,
{
provide: ActivatedRoute,
useValue: {
url: new BehaviorSubject([{ path: 'boards/1' }]),
params: new BehaviorSubject({ id: 1 })
}
},
{
provide: Http,
useFactory: (backend, options) => new Http(backend, options),
deps: [ MockBackend, BaseRequestOptions ]
}
],
schemas: [ NO_ERRORS_SCHEMA ]
]
}).compileComponents();
}));