Moving tests over to new framework
This commit is contained in:
parent
d8d385e2a2
commit
80cbbba967
@ -95,6 +95,8 @@ Developing on TaskBoard is pretty simple too.
|
|||||||
2. Run `git checkout dev` to work on the `dev` branch
|
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`
|
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)
|
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
|
#### Unit Tests
|
||||||
|
|
||||||
|
12
package-lock.json
generated
12
package-lock.json
generated
@ -6122,9 +6122,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jasmine-core": {
|
"jasmine-core": {
|
||||||
"version": "3.1.0",
|
"version": "2.99.1",
|
||||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
|
||||||
"integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=",
|
"integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"jasmine-spec-reporter": {
|
"jasmine-spec-reporter": {
|
||||||
@ -6387,9 +6387,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"karma-jasmine-html-reporter": {
|
"karma-jasmine-html-reporter": {
|
||||||
"version": "1.0.0",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz",
|
||||||
"integrity": "sha512-SN9R/Pl9cY40yLlc7FkTcfswUr19M6ZZ25eM8X5wtZ0gvp0gneWZbe5lPYcer/Yrbz0D6QUiTSJaEzr3KBPvSg==",
|
"integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"karma-jasmine": "1.1.1"
|
"karma-jasmine": "1.1.1"
|
||||||
|
@ -65,13 +65,13 @@
|
|||||||
"bourbon": "5.0.0",
|
"bourbon": "5.0.0",
|
||||||
"bourbon-neat": "1.9.0",
|
"bourbon-neat": "1.9.0",
|
||||||
"codelyzer": "^4.2.1",
|
"codelyzer": "^4.2.1",
|
||||||
"jasmine-core": "^3.1.0",
|
"jasmine-core": "^2.8.0",
|
||||||
"jasmine-spec-reporter": "~4.2.1",
|
"jasmine-spec-reporter": "~4.2.1",
|
||||||
"karma": "~2.0.0",
|
"karma": "~2.0.0",
|
||||||
"karma-chrome-launcher": "~2.2.0",
|
"karma-chrome-launcher": "~2.2.0",
|
||||||
"karma-coverage-istanbul-reporter": "^1.4.2",
|
"karma-coverage-istanbul-reporter": "^1.4.2",
|
||||||
"karma-jasmine": "~1.1.1",
|
"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",
|
"karma-phantomjs-launcher": "^1.0.4",
|
||||||
"protractor": "~5.3.0",
|
"protractor": "~5.3.0",
|
||||||
"ts-node": "~5.0.1",
|
"ts-node": "~5.0.1",
|
||||||
|
@ -44,11 +44,8 @@ export class ApiInterceptor implements HttpInterceptor {
|
|||||||
localStorage.setItem(this.JWT_KEY, response.data[0]);
|
localStorage.setItem(this.JWT_KEY, response.data[0]);
|
||||||
}
|
}
|
||||||
}, (err: any) => {
|
}, (err: any) => {
|
||||||
if (!(err instanceof HttpErrorResponse)) {
|
if ((err instanceof HttpErrorResponse) &&
|
||||||
return;
|
(err.status === 401 || err.status === 400) &&
|
||||||
}
|
|
||||||
|
|
||||||
if ((err.status === 401 || err.status === 400) &&
|
|
||||||
(err.url + '').indexOf('login') === -1) {
|
(err.url + '').indexOf('login') === -1) {
|
||||||
this.router.navigate(['']);
|
this.router.navigate(['']);
|
||||||
localStorage.removeItem(this.JWT_KEY);
|
localStorage.removeItem(this.JWT_KEY);
|
||||||
|
@ -55,6 +55,8 @@ export class BoardDisplay implements OnInit {
|
|||||||
this.userFilter = null;
|
this.userFilter = null;
|
||||||
this.categoryFilter = null;
|
this.categoryFilter = null;
|
||||||
|
|
||||||
|
this.activeBoard = new Board();
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
stringsService.stringsChanged.subscribe(newStrings => {
|
stringsService.stringsChanged.subscribe(newStrings => {
|
||||||
|
@ -28,7 +28,7 @@ export class TopNav {
|
|||||||
this.version = constants.VERSION;
|
this.version = constants.VERSION;
|
||||||
|
|
||||||
authService.userChanged
|
authService.userChanged
|
||||||
.subscribe(user => this.username = user.username);
|
.subscribe(user => this.username = user ? user.username : '');
|
||||||
|
|
||||||
stringsService.stringsChanged.subscribe(newStrings => {
|
stringsService.stringsChanged.subscribe(newStrings => {
|
||||||
this.strings = newStrings;
|
this.strings = newStrings;
|
||||||
|
@ -1,110 +1,106 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
import {
|
import {
|
||||||
HttpModule,
|
HttpClient,
|
||||||
XHRBackend,
|
HttpErrorResponse,
|
||||||
CookieXSRFStrategy,
|
HTTP_INTERCEPTORS
|
||||||
ResponseOptions,
|
} from '@angular/common/http';
|
||||||
BrowserXhr,
|
import {
|
||||||
RequestOptions
|
HttpClientTestingModule,
|
||||||
} from '@angular/http';
|
HttpTestingController
|
||||||
|
} from '@angular/common/http/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { AuthService } from '../../src/app/shared/auth/auth.service';
|
||||||
import 'rxjs/add/operator/catch';
|
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(() => {
|
beforeEach(() => {
|
||||||
const backend = new XHRBackend(new BrowserXhr(),
|
TestBed.configureTestingModule({
|
||||||
new ResponseOptions(),
|
imports: [
|
||||||
new CookieXSRFStrategy()),
|
HttpClientTestingModule,
|
||||||
requestOptions = new RequestOptions();
|
RouterTestingModule.withRoutes([])
|
||||||
|
],
|
||||||
apiHttp = new ApiHttp(backend, requestOptions, <any>routerMock);
|
providers: [
|
||||||
|
{
|
||||||
|
provide: AuthService,
|
||||||
|
useValue: mockAuthService
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: ApiInterceptor,
|
||||||
|
multi: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('provides API_HTTP_PROVIDERS', () => {
|
afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => {
|
||||||
expect(API_HTTP_PROVIDERS).toEqual(jasmine.any(Array));
|
httpMock.verify();
|
||||||
});
|
}));
|
||||||
|
|
||||||
it('provides a factory method', () => {
|
it('adds Content-Type header',
|
||||||
const actual = apiHttpFactory(null, null, null);
|
inject([HttpClient, HttpTestingController],
|
||||||
|
(http: HttpClient, httpMock: HttpTestingController) => {
|
||||||
|
http.get('').subscribe(response => {
|
||||||
|
expect(response).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
expect(actual).toEqual(jasmine.any(ApiHttp));
|
const req = httpMock.expectOne(req =>
|
||||||
});
|
req.headers.has('Content-Type') && req.headers.get('Content-Type') === 'application/json'
|
||||||
|
);
|
||||||
|
expect(req.request.method).toEqual('GET');
|
||||||
|
|
||||||
it('should create', () => {
|
req.flush({});
|
||||||
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']
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
)
|
||||||
|
);
|
||||||
|
|
||||||
apiHttp.intercept(Observable.of(response))
|
it('adds Authorization header when JWT is present',
|
||||||
.map(response => {
|
inject([HttpClient, HttpTestingController],
|
||||||
expect(localStorage.getItem('taskboard.jwt'))
|
(http: HttpClient, httpMock: HttpTestingController) => {
|
||||||
.toEqual('testjwt');
|
localStorage.setItem('taskboard.jwt', 'fake');
|
||||||
});
|
|
||||||
|
|
||||||
apiHttp.intercept(Observable.throw(null, <any>response))
|
http.post('', {}).subscribe(response => {
|
||||||
.catch((err, caught) => {
|
expect(response).toBeTruthy();
|
||||||
expect(localStorage.getItem('taskboard.jwt'))
|
});
|
||||||
.toEqual('');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('handles valid responses', () => {
|
const req = httpMock.expectOne(req =>
|
||||||
apiHttp.handleResponse({ json: () => ({ data: [ 'jwt' ] }) });
|
req.headers.has('Authorization') && req.headers.get('Authorization') === 'fake'
|
||||||
|
);
|
||||||
|
expect(req.request.method).toEqual('POST');
|
||||||
|
|
||||||
expect(localStorage.getItem('taskboard.jwt')).toEqual('jwt');
|
req.flush({ data: ['newToken'] });
|
||||||
});
|
expect(localStorage.getItem('taskboard.jwt')).toEqual('newToken');
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
it('handles error responses', () => {
|
it('handles errors and clears the JWT',
|
||||||
var error = {
|
inject([HttpClient, HttpTestingController],
|
||||||
status: 401,
|
(http: HttpClient, httpMock: HttpTestingController) => {
|
||||||
url: ''
|
localStorage.setItem('taskboard.jwt', 'fake');
|
||||||
};
|
|
||||||
|
|
||||||
apiHttp.handleError(error, null);
|
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);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,25 +1,21 @@
|
|||||||
import { TestBed, async } from '@angular/core/testing';
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { HttpModule } from '@angular/http';
|
|
||||||
|
|
||||||
import { AppComponent } from '../../src/app/app.component';
|
import { AppComponent } from '../../src/app/app.component';
|
||||||
import {
|
import {
|
||||||
Notifications,
|
|
||||||
NotificationsService,
|
NotificationsService,
|
||||||
StringsService
|
StringsService
|
||||||
} from '../../src/app/shared/index';
|
} from '../../src/app/shared/services';
|
||||||
|
import { SharedModule } from '../../src/app/shared/shared.module';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterTestingModule,
|
RouterTestingModule,
|
||||||
HttpModule
|
SharedModule
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
Notifications
|
|
||||||
],
|
],
|
||||||
|
declarations: [ AppComponent ],
|
||||||
providers: [
|
providers: [
|
||||||
StringsService,
|
StringsService,
|
||||||
NotificationsService
|
NotificationsService
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
import { async, TestBed, ComponentFixture } from '@angular/core/testing'
|
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 { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Title } from '@angular/platform-browser';
|
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 { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
|
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
|
||||||
|
|
||||||
@ -17,12 +14,15 @@ import {
|
|||||||
Constants,
|
Constants,
|
||||||
ContextMenuService,
|
ContextMenuService,
|
||||||
NotificationsService
|
NotificationsService
|
||||||
} from '../../../src/app/shared/index';
|
} from '../../../src/app/shared/services';
|
||||||
import { Login } from '../../../src/app/login/login.component';
|
import { Login } from '../../../src/app/login/login.component';
|
||||||
import { Settings } from '../../../src/app/settings/index';
|
import { SettingsModule } from '../../../src/app/settings/settings.module';
|
||||||
import { Dashboard } from '../../../src/app/dashboard/index';
|
import { SharedModule } from '../../../src/app/shared/shared.module';
|
||||||
import { BoardService, BoardDisplay } from '../../../src/app/board/index';
|
import { DashboardModule } from '../../../src/app/dashboard/dashboard.module';
|
||||||
import { ROUTES } from '../../../src/app/app.routes';
|
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', () => {
|
describe('BoardDisplay', () => {
|
||||||
let component: BoardDisplay,
|
let component: BoardDisplay,
|
||||||
@ -31,15 +31,19 @@ describe('BoardDisplay', () => {
|
|||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterTestingModule.withRoutes(ROUTES),
|
RouterTestingModule,
|
||||||
|
HttpClientTestingModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
DragulaModule
|
DragulaModule,
|
||||||
|
SettingsModule,
|
||||||
|
SharedModule,
|
||||||
|
DashboardModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
BoardDisplay,
|
|
||||||
Login,
|
Login,
|
||||||
Settings,
|
BoardDisplay,
|
||||||
Dashboard
|
ColumnDisplay,
|
||||||
|
TaskDisplay
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
Title,
|
Title,
|
||||||
@ -49,22 +53,14 @@ describe('BoardDisplay', () => {
|
|||||||
StringsService,
|
StringsService,
|
||||||
ContextMenuService,
|
ContextMenuService,
|
||||||
NotificationsService,
|
NotificationsService,
|
||||||
MockBackend,
|
|
||||||
BaseRequestOptions,
|
|
||||||
{
|
{
|
||||||
provide: ActivatedRoute,
|
provide: ActivatedRoute,
|
||||||
useValue: {
|
useValue: {
|
||||||
url: new BehaviorSubject([{ path: 'boards/1' }]),
|
url: new BehaviorSubject([{ path: 'boards/1' }]),
|
||||||
params: new BehaviorSubject({ id: 1 })
|
params: new BehaviorSubject({ id: 1 })
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: Http,
|
|
||||||
useFactory: (backend, options) => new Http(backend, options),
|
|
||||||
deps: [ MockBackend, BaseRequestOptions ]
|
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
schemas: [ NO_ERRORS_SCHEMA ]
|
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user