Advertisement
Guest User

Untitled

a guest
Feb 13th, 2017
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.85 KB | None | 0 0
  1. import { DebugElement, NgModule } from '@angular/core';
  2. import { ComponentFixture, TestBed, async } from '@angular/core/testing';
  3. import { FormsModule } from '@angular/forms';
  4. import { By } from '@angular/platform-browser';
  5. import { Router, RouterModule } from '@angular/router';
  6. import { Http } from '@angular/http';
  7.  
  8. import { DashboardComponent } from './dashboard.component';
  9. import { PatientListComponent } from '../patient-list/patient-list.component';
  10. import { PatientListItemComponent } from '../patient-list-item/patient-list-item.component';
  11. import { AuthenticationService } from '../authentication.service';
  12. import { Authentication } from '../authentication';
  13. import { PatientSummaryService } from '../patient-summary/patient-summary.service';
  14. import { PatientSummary } from '../patient-summary/patient-summary';
  15. import { StaffFilterPipe } from '../staff-filter.pipe';
  16.  
  17. import { testData } from '../patient-list/patient-list.test-data';
  18.  
  19. import { MockAuthService, MockPatientSummaryService, RouterStub, HttpMock } from './dashboard.mocks';
  20.  
  21. /*
  22. * DebugElement and By are currently not used. I have left them in the import statements above,
  23. * because any test suite WILL use them when it is fully developed.
  24. */
  25. describe( "DashboardComponent", ()=>{
  26. var component : DashboardComponent;
  27. var fixture : ComponentFixture<DashboardComponent>;
  28. beforeEach(
  29. async(
  30. ()=>{
  31. TestBed.configureTestingModule(
  32. {
  33. imports: [ RouterModule, FormsModule ],
  34. declarations: [ DashboardComponent, PatientListComponent, PatientListItemComponent, StaffFilterPipe ],
  35. providers: [
  36. { provide: AuthenticationService, useClass: MockAuthService },
  37. { provide: PatientSummaryService, useClass: MockPatientSummaryService },
  38. { provide: Router, useClass: RouterStub },
  39. { provide: Http, useClass: HttpMock }
  40. ]
  41. }
  42. ).compileComponents();
  43. console.log( "Compile components is called" );
  44. } ));
  45. beforeEach(()=>{
  46. fixture = TestBed.createComponent( DashboardComponent );
  47. var authService:MockAuthService = fixture.debugElement.injector.get(AuthenticationService);
  48. authService.fakeAnAuth("drbanks");
  49. var patientService: MockPatientSummaryService = fixture.debugElement.injector.get(PatientSummaryService);
  50. patientService.fakeAListChange( testData );
  51. fixture.detectChanges();
  52. component = fixture.componentInstance;
  53. console.log( "Fixture is defined" );
  54. });
  55. describe("component setup verifications", ()=>{
  56. it( "component has an authentication", async(
  57. ()=>{
  58. expect(component.credentials instanceof Authentication).toBe( true );
  59. expect(component.credentials.username).toBe("drbanks");
  60. }
  61. ) );
  62. it( "component has a patient list", async(
  63. ()=>{
  64. expect( Array.isArray( component.patientSummary ) ).toBe(true, "The patientSummary attribute is an array.");
  65. expect( component.patientSummary.length ).toBeGreaterThan( 0, "The patientSummary array has more than zero elements." );
  66. for( var patient of component.patientSummary ){
  67. expect( patient instanceof PatientSummary ).toBe( true, "Each patientSummary element is a PatientSummary object." );
  68. }
  69. }
  70. ) );
  71. });
  72. } );
  73.  
  74. import { Injectable } from '@angular/core';
  75.  
  76. import { testData } from '../patient-list/patient-list.test-data';
  77.  
  78. import { PatientSummaryService } from '../patient-summary/patient-summary.service';
  79. import { PatientSummary } from '../patient-summary/patient-summary';
  80.  
  81. import { Authentication } from '../authentication';
  82. import { AuthenticationService } from '../authentication.service';
  83. import { Staff } from '../staff';
  84.  
  85. @Injectable()
  86. export class RouterStub {
  87. navigate( parts : string[] ){
  88. return parts;
  89. }
  90. }
  91.  
  92. @Injectable()
  93. export class MockAuthService extends AuthenticationService {
  94. sendAuthRequest( restUrl: string, postData : any ){
  95. //override do nothing
  96. }
  97. fakeAnAuth( userid : string ){
  98. var banks : Staff = new Staff();
  99. var owens : Staff = new Staff();
  100. banks.userid = "drbanks";
  101. banks.groupid = ["doctors","super_user"];
  102. owens.userid = "owens";
  103. owens.groupid = ["doctors"];
  104. var options : any = {
  105. drbanks: new Authentication( "drbanks", "test_token_1324", banks ),
  106. drowens: new Authentication( "drowens", "test_token_5123", owens )
  107. };
  108. if( typeof options[ userid ] != "undefined" ){
  109. //emit the selected credential
  110. this.verifySuccess( options[ userid ] );
  111. }else{
  112. //clear credentials and emit an invalidate signal
  113. this.clearCreds();
  114. }
  115.  
  116. }
  117. }
  118.  
  119. @Injectable()
  120. export class MockPatientSummaryService extends PatientSummaryService {
  121. responded : boolean = false;
  122. constructor() {
  123. super( null );
  124. }
  125. getActive(){
  126. if (this.responded ) return;
  127. this.updatedList.emit( testData );
  128. this.responded = true;
  129. }
  130. fakeAListChange( list : PatientSummary[] ){
  131. this.updatedList.emit( list );
  132. }
  133. }
  134.  
  135. @Injectable()
  136. export class HttpMock {}
  137.  
  138. import { Component, Input } from '@angular/core';
  139. import { Router } from '@angular/router';
  140.  
  141. import { Authentication } from '../authentication';
  142. import { AuthenticationService } from '../authentication.service';
  143. import { PatientSummaryService } from '../patient-summary/patient-summary.service';
  144. import { PatientSummary } from '../patient-summary/patient-summary';
  145.  
  146. @Component(
  147. {
  148. moduleId: module.id,
  149. selector: 'dashboard',
  150. template: `
  151. <div class="container" *ngIf="credentials.valid">
  152. <div class="col-xs-12 filterOptions">
  153. <span class="col-xs-12">
  154. <button class="btn btn-small btn-default pull-right" (click)="toggleFilterView()">Toggle Filters</button>
  155. <h4>Filter Options</h4>
  156. </span>
  157. <span *ngIf="viewFilters">
  158. <label>
  159. <input type='checkbox' [(ngModel)]="filterList" />
  160. Filter the list for <strong>only</strong> patients linked to your account.
  161. </label>
  162. <div class="form-group">
  163. <label>Filter By Patient Name</label>
  164. <input class="form-control" [(ngModel)]="nameFilter" placeholder="Patient name in full or in part." />
  165. </div>
  166. </span>
  167. </div>
  168. <h1>Priority Patients</h1>
  169. <patient-list id="priority_patients" [sourceData]="todaysPatientList | staffFilter : acceptableStaff" (clickPatient)="selectPatient($event)"></patient-list>
  170. <h1>Patients Records <small>(Not Yet Complete)</small></h1>
  171. <patient-list id="patient_records_backlog" [sourceData]="nonActivePatientList | staffFilter : acceptableStaff" (clickPatient)="selectPatient($event)"></patient-list>
  172. </div>`,
  173. styles: [
  174. `.filterOptions {
  175. background-color: hsla( 187, 55%, 90%, 0.5 );
  176. padding: 1em;
  177. border: solid 3px black;
  178. border-radius: 1em;
  179. margin-bottom: 1em;
  180. }`
  181. ]
  182. }
  183. )
  184. export class DashboardComponent {
  185. credentials : Authentication = new Authentication(null,null,null);
  186. viewFilters: boolean = false;
  187. nameFilter: string = "";
  188. filterList: boolean = true;
  189. patientSummary: PatientSummary[];
  190.  
  191. constructor( private patientSummaryService : PatientSummaryService,
  192. private authService : AuthenticationService,
  193. private router : Router ){}
  194. ngOnInit(){
  195. var app = this;
  196. this.patientSummaryService.updatedList.subscribe(
  197. (list : PatientSummary[] ) => {app.setPatientSummaryList(list);}
  198. );
  199. this.authService.newCreds.subscribe(
  200. (creds : Authentication) => this.credentials = creds
  201. );
  202. this.authService.invalidate.subscribe(
  203. (obj : any) => this.credentials = new Authentication(null,null,null)
  204. );
  205. }
  206. setPatientSummaryList(list: PatientSummary[]) {
  207. var app = this;
  208. list.sort((a: PatientSummary, b: PatientSummary) => {
  209. var dateA = app.extractDate(a);
  210. var dateB = app.extractDate(b);
  211. if (dateA > dateB) return 1;
  212. if (dateA < dateB) return -1;
  213. return 0;
  214. });
  215. this.patientSummary = list;
  216. }
  217. extractDate(item: PatientSummary) {
  218. var date = item.arrivalTime;
  219. if (date === null || date < item.visit.date) {
  220. date = item.visit.date;
  221. }
  222. return date;
  223. }
  224. nameFilterFunction(item: PatientSummary) {
  225. if (this.nameFilter == "") return true;
  226. if (typeof item == "object" && typeof item.name != "undefined") {
  227. var index = item.name.indexOf(this.nameFilter);
  228. return (index !== -1);
  229. }
  230. return false;
  231. }
  232. toggleFilterView() {
  233. this.viewFilters = !this.viewFilters;
  234. }
  235.  
  236.  
  237. /**
  238. * Returns a list of patients in ascending order (oldest first) of items
  239. * that are today and are assigned to a room.
  240. */
  241. get todaysPatientList() {
  242. var app = this;
  243. if (!Array.isArray(this.patientSummary)) return [];
  244. var list = this.patientSummary.filter(
  245. (item: PatientSummary) => {
  246. var date = app.extractDate(item);
  247. var now = new Date();
  248. var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  249. var tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
  250. return date >= today && date <= tomorrow;
  251. }).filter((item: PatientSummary) => {
  252. if (typeof item == "object" && typeof item.location == "object" && typeof item.location.room !== null) {
  253. return item.location.room != "No Room Assignment";
  254. } else {
  255. return true;
  256. }
  257. });
  258. return list.filter((item) => {return app.nameFilterFunction(item);});
  259. }
  260. /**
  261. * Returns a list of patients in descending order (most recent first) of items
  262. * that do not appear in the todaysPatientList attribute;
  263. */
  264. get nonActivePatientList() {
  265. if (!Array.isArray(this.patientSummary)) return [];
  266. var app = this;
  267. var list = this.todaysPatientList;
  268. var nonActiveList = this.patientSummary.filter((obj: PatientSummary) => {
  269. var index = list.indexOf(obj);
  270. return (index == -1);
  271. });
  272. nonActiveList.reverse();
  273. return nonActiveList.filter((item) => {return app.nameFilterFunction(item);});;
  274. }
  275. get acceptableStaff() {
  276. if (!this.filterList) {
  277. return "any";
  278. } else {
  279. var user = "any";
  280. if (this.credentials instanceof Authentication) {
  281. user = this.credentials.username;
  282. }
  283. if (user === null) user = "any";
  284. return user;
  285. }
  286. };
  287. selectPatient( patient : PatientSummary ){
  288. var id = patient.medfaceId;
  289. this.router.navigate(['/detail',id]);
  290. }
  291. }
  292.  
  293. import {Injectable, Output, EventEmitter} from '@angular/core';
  294. import {Http, Response} from '@angular/http';
  295. import {Authentication} from '../authentication';
  296. import {PatientSummary} from './patient-summary';
  297. import {Observable} from 'rxjs/Observable';
  298. import '../rxjs-operators';
  299.  
  300. @Injectable()
  301. export class PatientSummaryService {
  302. updateFrequency: number = 60000; /* every 1 minutes */
  303. lastUpdateTime: Date = new Date();
  304. lastList: PatientSummary[] = [];
  305. timeoutId: any = null;
  306. auth: Authentication = new Authentication(null, null, null);
  307. @Output() updatedList: EventEmitter<PatientSummary[]> = new EventEmitter<PatientSummary[]>();
  308. constructor(private http: Http) {};
  309. useCredentials(creds: Authentication) {
  310. this.auth = creds;
  311. if (creds.valid == false) {
  312. this.stopHttpRequests();
  313. }
  314. else if (this.timeoutId == null) {
  315. this.startHttpRequests();
  316. }
  317. };
  318. /**
  319. * If the timer is still set, cancel the timer and clear all lists by
  320. * emitting an emty list set.
  321. */
  322. stopHttpRequests() {
  323. if (this.timeoutId) {
  324. clearTimeout(this.timeoutId);
  325. this.timeoutId = null;
  326. this.lastUpdateTime = new Date();
  327. this.lastList = [];
  328. this.updatedList.emit( this.lastList );
  329. }
  330. }
  331.  
  332. /**
  333. * Start collecting lists again.
  334. */
  335. startHttpRequests() {
  336. this.getActive();
  337. }
  338. getActive() : void {
  339. var auth = this.auth;
  340. if (!auth.valid) {
  341. this.stopHttpRequests();
  342. return null;
  343. }
  344. const restUrl = "../rest.php";
  345. let postData = {
  346. username: auth.username,
  347. token: auth.token,
  348. command: "getActiveSummaries",
  349. use_cache: true,
  350. version: "2.0"
  351. };
  352. var service = this;
  353. var observable = this.http.post(restUrl, JSON.stringify(postData))
  354. .map((data) => {return service.extractData(data);})
  355. .catch( (err : any ) => { service.handleError( err ); return null; } );
  356. observable.subscribe(
  357. (dataPacket : {
  358. lastUpdated: Date,
  359. activeList : any
  360.  
  361. } ) => {
  362. if (service.lastUpdateTime.toTimeString() != dataPacket.lastUpdated.toTimeString()) {
  363. service.lastUpdateTime = dataPacket.lastUpdated;
  364. service.lastList = dataPacket.activeList;
  365. service.updatedList.emit(service.lastList);
  366. }
  367. service.setNewTimer();
  368. },
  369. (error) => {
  370. service.handleError(error);
  371. service.setNewTimer();
  372. }
  373. );
  374. };
  375. setNewTimer() {
  376. var service = this;
  377. this.timeoutId = setTimeout(() => {service.getActive();}, service.updateFrequency);
  378. };
  379. convertDateObjects(obj: any) {
  380. if (obj === null) return obj;
  381. var soughtFields = ['year', 'month', 'day', 'hour', 'minute'];
  382. var objFound : any = null;
  383. if (typeof obj == "object") {
  384. objFound = true;
  385. for (var key of soughtFields) {
  386. if (typeof obj[key] == "undefined") {
  387. objFound = false;
  388. break;
  389. }
  390. }
  391. if (objFound) {
  392. if (obj.year !== 1920) {
  393. return new Date(obj.year, obj.month, obj.day, obj.hour, obj.minute);
  394. } else {
  395. return null;
  396. }
  397. } else {
  398. for (var i in obj) {
  399. if (obj.hasOwnProperty(i)) {
  400. var item = this.convertDateObjects(obj[i]);
  401. obj[i] = item;
  402. }
  403. }
  404. }
  405. }
  406. return obj;
  407. };
  408. extractData(response: Response) {
  409. var body = response.json();
  410. body = this.convertDateObjects(body);
  411. console.log(body);
  412. if (typeof body.error !== "undefined") {
  413. throw body.error;
  414. }
  415. var dataPacket = body.data;
  416. return dataPacket;
  417. };
  418. handleError(error : any) {
  419. console.error("Error received in PatientSummaryService.", error);
  420. };
  421. }
  422.  
  423. import { Injectable, Output, EventEmitter } from '@angular/core';
  424. import { Http } from '@angular/http';
  425.  
  426. import './rxjs-operators';
  427.  
  428. import { Authentication } from './authentication';
  429.  
  430. @Injectable()
  431. export class AuthenticationService
  432. {
  433. auth : Authentication = new Authentication( null, null, null );
  434. username: string;
  435. token: string;
  436. cookie_load_complete : boolean = false;
  437. @Output() invalidate : EventEmitter<any> = new EventEmitter();
  438. @Output() newCreds : EventEmitter<any> = new EventEmitter();
  439. constructor( private http : Http ){}
  440. loadCredsFromCookie(){
  441. if( !this.cookie_load_complete ){
  442. var cookieString = document.cookie;
  443. //using ECMA 2015 for cookie management;
  444. let userMatch = cookieString.match( /username=([^;]+)/ );
  445. let tokenMatch = cookieString.match(/token=([^;]+)/);
  446. if( userMatch !== null && tokenMatch!== null ){
  447. let user = userMatch[1];
  448. let token = tokenMatch[1];
  449. this.testToken(user, token);
  450. }
  451. }
  452. this.cookie_load_complete = true;
  453. }
  454. saveCredsInCookie( username : string , token : string ){
  455. //using ECMA 2015 for cookie management
  456. let date = new Date();
  457. let year = date.getFullYear();
  458. let month = date.getMonth();
  459. let day = date.getDate();
  460. let hours = date.getHours();
  461. let minutes = date.getMinutes();
  462. let tomorrow = new Date( year, month, day + 1, hours, minutes );
  463. let _24hours = tomorrow.toUTCString();
  464. document.cookie = `username=${username}; expires=${_24hours}`;
  465. document.cookie = `token=${token}; expires=${_24hours}`;
  466. }
  467. setUserName( name :string ){ this.username = name; }
  468. setToken( token: string ){
  469. let username = this.username;
  470. this.token = token;
  471. this.saveCredsInCookie( username, token );
  472. }
  473. clearCreds(){
  474. this.username = null;
  475. this.token = null;
  476. this.saveCredsInCookie(null,null);
  477. this.invalidate.emit( null );
  478. }
  479. testToken( username : string, token : string ){
  480. this.setUserName( username );
  481. const restUrl = "../rest.php";
  482. let postData = { command: "authenticate", username, token };
  483. this.sendAuthRequest( restUrl, postData );
  484. };
  485.  
  486. testCredentials( userName:string, password:string ) {
  487. this.setUserName( userName );
  488. const restUrl = "../rest.php";
  489. let postData = { command: "authenticate", username: userName, password };
  490. this.sendAuthRequest( restUrl, postData );
  491. };
  492. sendAuthRequest( restUrl: string, postData : any ){
  493. postData.version = "2.0";
  494. var service = this;
  495. var observable = this.http
  496. .post(restUrl, JSON.stringify(postData) )
  497. .map(
  498. this.extractData
  499. )
  500. .catch( service.handleError );
  501. observable.subscribe(
  502. (success : any ) => this.verifySuccess(success),
  503. ( err : any ) => service.handleError( err, {} )
  504. );
  505. };
  506. verifySuccess( data : Authentication ){
  507. if( data.valid == true ){
  508. //successful login
  509. if( this.token !== data.token ){
  510. var auth : Authentication = new Authentication( data.username, data.token, data.staff );
  511. this.auth = auth;
  512. this.setToken( data.token );
  513. this.newCreds.emit( auth );
  514. }
  515. } else {
  516. this.clearCreds();
  517. this.handleError( "Provided credentials are not valid.", {} );
  518. }
  519. }
  520. extractData( response : any ){
  521. var body = response._body;
  522. var jBody = JSON.parse( body );
  523. return jBody.data;
  524. }
  525. handleError( error : any, observable : any ) : any{
  526. console.error( `Error received. ${error}` );
  527. this.setUserName("");
  528. this.setToken( "" );
  529. this.invalidate.emit( { errorMsg: error } );
  530. }
  531. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement