bixi
Version:
企业级中后台前端解决方案
256 lines (232 loc) • 8.47 kB
text/typescript
import { DOCUMENT } from '@angular/common';
import { HTTP_INTERCEPTORS, HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController, TestRequest } from '@angular/common/http/testing';
import { Type } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { BixiAuthModule } from '../auth.module';
import { BIXI_AUTH_CONFIG, BixiAuthConfig } from '../config.type';
import { AuthReferrer, BIXI_SERVICE_TOKEN, ITokenModel, ITokenService } from './interface';
import { SimpleInterceptor } from './simple/simple.interceptor';
import { SimpleTokenModel } from './simple/simple.model';
function genModel<T extends ITokenModel>(modelType: new () => T, token: string | null = `123`) {
const model: any = new modelType();
model.token = token;
model.uid = 1;
return model;
}
class MockTokenService implements ITokenService {
// tslint:disable-next-line:no-any
[key: string]: any;
// tslint:disable-next-line:no-any
_data: any;
// tslint:disable-next-line:no-any
options: any;
referrer: AuthReferrer = {};
set(data: ITokenModel): boolean {
this._data = data;
return true;
}
get(): ITokenModel {
return this._data;
}
// tslint:disable-next-line:no-any
change(): any {
return null;
}
clear() {
this._data = null;
}
get login_url() {
return '/login';
}
}
let otherRes = new HttpResponse();
class OtherInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req.clone()).pipe(
catchError(() => {
return throwError(otherRes);
})
);
}
}
describe('auth: base.interceptor', () => {
let http: HttpClient;
let httpBed: HttpTestingController;
let router: Router;
const MockDoc = {
location: {
href: ''
}
};
// tslint:disable-next-line:no-any
function genModule(options: BixiAuthConfig, tokenData?: ITokenModel, provider: any[] = []) {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule, RouterTestingModule.withRoutes([]), BixiAuthModule],
providers: [
{ provide: DOCUMENT, useValue: MockDoc },
{ provide: BIXI_AUTH_CONFIG, useValue: { ...options } },
{
provide: HTTP_INTERCEPTORS,
useClass: SimpleInterceptor,
multi: true
},
{ provide: BIXI_SERVICE_TOKEN, useClass: MockTokenService }
].concat(provider)
});
if (tokenData) TestBed.inject(BIXI_SERVICE_TOKEN).set(tokenData);
router = TestBed.inject<Router>(Router);
spyOn(router, 'navigate');
http = TestBed.inject<HttpClient>(HttpClient);
httpBed = TestBed.inject(HttpTestingController as Type<HttpTestingController>);
}
describe('[ignores]', () => {
describe('#with config', () => {
const basicModel = genModel(SimpleTokenModel);
it(`should be ignore /login`, (done: () => void) => {
genModule({ ignores: [/assets\//, /\/login/] }, basicModel);
http.get('/login', { responseType: 'text' }).subscribe(done);
const req = httpBed.expectOne('/login') as TestRequest;
expect(req.request.headers.get('token')).toBeNull();
req.flush('ok!');
});
it('should be non-ignore', (done: () => void) => {
genModule({ ignores: [] }, basicModel);
http.get('/login', { responseType: 'text' }).subscribe(done);
const req = httpBed.expectOne('/login') as TestRequest;
expect(req.request.headers.get('token')).toBe('123');
req.flush('ok!');
});
});
describe('#with allow_anonymous_key', () => {
it(`in params`, (done: () => void) => {
genModule({}, genModel(SimpleTokenModel, null));
http.get('/user', { responseType: 'text', params: { _allow_anonymous: '' } }).subscribe(done);
const ret = httpBed.expectOne(() => true);
expect(ret.request.headers.get('Authorization')).toBeNull();
ret.flush('ok!');
});
it(`in params (full url)`, (done: () => void) => {
genModule({}, genModel(SimpleTokenModel, null));
http
.get('https://bixi.datagrand.com/api/user', {
responseType: 'text',
params: { _allow_anonymous: '' }
})
.subscribe(done);
const ret = httpBed.expectOne(() => true);
expect(ret.request.headers.get('Authorization')).toBeNull();
ret.flush('ok!');
});
it(`in url`, (done: () => void) => {
genModule({}, genModel(SimpleTokenModel, null));
http.get('/user?_allow_anonymous=1', { responseType: 'text' }).subscribe(done);
const ret = httpBed.expectOne(() => true);
expect(ret.request.headers.get('Authorization')).toBeNull();
ret.flush('ok!');
});
it(`in url (full url)`, (done: () => void) => {
genModule({}, genModel(SimpleTokenModel, null));
http.get('https://bixi.datagrand.com/api/user?_allow_anonymous=1', { responseType: 'text' }).subscribe(done);
const ret = httpBed.expectOne(() => true);
expect(ret.request.headers.get('Authorization')).toBeNull();
ret.flush('ok!');
});
});
});
describe('[invalid token]', () => {
describe('should be navigate to login', () => {
it('with navigate', (done: () => void) => {
genModule({}, genModel(SimpleTokenModel, null));
http.get('/test', { responseType: 'text' }).subscribe(
() => {
expect(false).toBe(true);
done();
},
// tslint:disable-next-line:no-any
(err: any) => {
expect(err.status).toBe(401);
setTimeout(() => {
expect(TestBed.inject<Router>(Router).navigate).toHaveBeenCalled();
done();
}, 20);
}
);
});
it('with location', (done: () => void) => {
const login_url = 'https://bixi.datagrand.com/login';
genModule({ login_url }, genModel(SimpleTokenModel, null));
http.get('/test', { responseType: 'text' }).subscribe(
() => {
expect(false).toBe(true);
done();
},
// tslint:disable-next-line:no-any
(err: any) => {
expect(err.status).toBe(401);
setTimeout(() => {
expect(TestBed.inject(DOCUMENT).location.href).toBe(login_url);
done();
}, 20);
}
);
});
});
it('should be not navigate to login when token_invalid_redirect: false', (done: () => void) => {
genModule({ token_invalid_redirect: false }, genModel(SimpleTokenModel, null));
http.get('/test', { responseType: 'text' }).subscribe(
() => {
expect(false).toBe(true);
done();
},
// tslint:disable-next-line:no-any
(err: any) => {
expect(err.status).toBe(401);
done();
}
);
});
});
describe('[referrer]', () => {
it('should be always router url', (done: () => void) => {
genModule({ executeOtherInterceptors: false }, genModel(SimpleTokenModel, null));
http.get('/to-test', { responseType: 'text' }).subscribe(
() => {
expect(false).toBe(true);
done();
},
() => {
const tokenSrv = TestBed.inject(BIXI_SERVICE_TOKEN) as MockTokenService;
expect(tokenSrv.referrer).not.toBeNull();
expect(tokenSrv.referrer.url).toBe('/');
done();
}
);
});
});
describe('[executeOtherInterceptors]', () => {
beforeEach(() => {
genModule({ executeOtherInterceptors: true }, genModel(SimpleTokenModel, null), [
{ provide: HTTP_INTERCEPTORS, useClass: OtherInterceptor, multi: true }
]);
});
it('shoul working', done => {
otherRes = new HttpResponse({ body: { a: 1 } });
const url = '/to-test';
http.get(url, { responseType: 'text' }).subscribe(
() => {
expect(false).toBe(true);
done();
},
err => {
expect(err.body.a).toBe(1);
done();
}
);
});
});
});