[ADF-4457] StorageService should be independent of AppConfigService (#4712)

* [ADF-4457] StorageService should be independent of AppConfigService

* [ADF-4457] Fix e2e tests

* [ADF-4457] Fix e2e tests

* [ADF-4457] Improve storage service workflow

* Fix linting

* Fix unit tests

* Fix e2e test

* Add missing class to constructor

* Fix e2e test

* Rebase branch

* Improve unit test

* fix test
This commit is contained in:
davidcanonieto
2019-06-25 16:21:13 +01:00
committed by Eugenio Romano
parent 90c403ae9e
commit 5c07d5b3e6
29 changed files with 432 additions and 369 deletions

View File

@@ -18,7 +18,14 @@
import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { Node } from '@alfresco/js-api'; import { Node } from '@alfresco/js-api';
import { Observable, Subject, of } from 'rxjs'; import { Observable, Subject, of } from 'rxjs';
import { CardViewItem, NodesApiService, LogService, CardViewUpdateService, AlfrescoApiService, TranslationService } from '@alfresco/adf-core'; import {
CardViewItem,
NodesApiService,
LogService,
CardViewUpdateService,
AlfrescoApiService,
TranslationService
} from '@alfresco/adf-core';
import { ContentMetadataService } from '../../services/content-metadata.service'; import { ContentMetadataService } from '../../services/content-metadata.service';
import { CardViewGroup } from '../../interfaces/content-metadata.interfaces'; import { CardViewGroup } from '../../interfaces/content-metadata.interfaces';
import { switchMap, takeUntil, catchError } from 'rxjs/operators'; import { switchMap, takeUntil, catchError } from 'rxjs/operators';
@@ -78,7 +85,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
private logService: LogService, private logService: LogService,
private alfrescoApiService: AlfrescoApiService, private alfrescoApiService: AlfrescoApiService,
private translationService: TranslationService private translationService: TranslationService
) {} ) {
}
ngOnInit() { ngOnInit() {
this.cardViewUpdateService.itemUpdated$ this.cardViewUpdateService.itemUpdated$
@@ -112,7 +120,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
try { try {
statusCode = JSON.parse(error.message).error.statusCode; statusCode = JSON.parse(error.message).error.statusCode;
} catch {} } catch {
}
let message = `METADATA.ERRORS.${statusCode}`; let message = `METADATA.ERRORS.${statusCode}`;
@@ -143,12 +152,12 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
return this.nodesApiService.updateNode(this.node.id, nodeBody); return this.nodesApiService.updateNode(this.node.id, nodeBody);
} }
showGroup(group: CardViewGroup) { showGroup(group: CardViewGroup): boolean {
const properties = group.properties.filter((property) => { const properties = group.properties.filter((property) => {
return !!property.displayValue; return !!property.displayValue;
}); });
return properties.length; return properties.length > 0;
} }
ngOnDestroy() { ngOnDestroy() {

View File

@@ -16,7 +16,7 @@
*/ */
import { AlfrescoApiServiceMock, AppConfigService, ContentService, import { AlfrescoApiServiceMock, AppConfigService, ContentService,
setupTestBed, CoreModule, TranslationMock setupTestBed, CoreModule, TranslationMock, StorageService
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { FileNode, FolderNode } from '../../mock'; import { FileNode, FolderNode } from '../../mock';
import { ContentActionHandler } from '../models/content-action.model'; import { ContentActionHandler } from '../models/content-action.model';
@@ -37,7 +37,7 @@ describe('DocumentActionsService', () => {
beforeEach(() => { beforeEach(() => {
const contentService = new ContentService(null, null, null, null); const contentService = new ContentService(null, null, null, null);
const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); documentListService = new DocumentListService(contentService, alfrescoApiService, null, null);
service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService); service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService);

View File

@@ -16,7 +16,7 @@
*/ */
import { AlfrescoApiServiceMock, AlfrescoApiService, import { AlfrescoApiServiceMock, AlfrescoApiService,
AppConfigService, ContentService, setupTestBed, CoreModule, LogService, AppConfigServiceMock } from '@alfresco/adf-core'; AppConfigService, ContentService, setupTestBed, CoreModule, LogService, AppConfigServiceMock, StorageService } from '@alfresco/adf-core';
import { DocumentListService } from './document-list.service'; import { DocumentListService } from './document-list.service';
import { CustomResourcesService } from './custom-resources.service'; import { CustomResourcesService } from './custom-resources.service';
@@ -70,7 +70,7 @@ describe('DocumentListService', () => {
beforeEach(() => { beforeEach(() => {
const logService = new LogService(new AppConfigServiceMock(null)); const logService = new LogService(new AppConfigServiceMock(null));
const contentService = new ContentService(null, null, null, null); const contentService = new ContentService(null, null, null, null);
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
const customActionService = new CustomResourcesService(alfrescoApiService, logService); const customActionService = new CustomResourcesService(alfrescoApiService, logService);
service = new DocumentListService(contentService, alfrescoApiService, logService, customActionService); service = new DocumentListService(contentService, alfrescoApiService, logService, customActionService);
jasmine.Ajax.install(); jasmine.Ajax.install();

View File

@@ -16,7 +16,8 @@
*/ */
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { AlfrescoApiServiceMock, AppConfigService, ContentService, setupTestBed, CoreModule, TranslationMock } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, AppConfigService, ContentService, setupTestBed,
CoreModule, TranslationMock, StorageService } from '@alfresco/adf-core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { FileNode, FolderNode } from '../../mock'; import { FileNode, FolderNode } from '../../mock';
import { ContentActionHandler } from '../models/content-action.model'; import { ContentActionHandler } from '../models/content-action.model';
@@ -39,7 +40,7 @@ describe('FolderActionsService', () => {
appConfig.config.ecmHost = 'http://localhost:9876/ecm'; appConfig.config.ecmHost = 'http://localhost:9876/ecm';
const contentService = new ContentService(null, null, null, null); const contentService = new ContentService(null, null, null, null);
const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); documentListService = new DocumentListService(contentService, alfrescoApiService, null, null);
service = new FolderActionsService(null, documentListService, contentService, new TranslationMock()); service = new FolderActionsService(null, documentListService, contentService, new TranslationMock());
}); });

View File

@@ -39,6 +39,7 @@ export enum AppConfigValues {
DISABLECSRF = 'disableCSRF', DISABLECSRF = 'disableCSRF',
AUTH_WITH_CREDENTIALS = 'auth.withCredentials', AUTH_WITH_CREDENTIALS = 'auth.withCredentials',
APPLICATION = 'application', APPLICATION = 'application',
STORAGE_PREFIX = 'application.storagePrefix',
NOTIFY_DURATION = 'notificationDefaultDuration' NOTIFY_DURATION = 'notificationDefaultDuration'
} }

View File

@@ -17,26 +17,23 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { StorageService } from '../services/storage.service';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
@Injectable() @Injectable()
export class DebugAppConfigService extends AppConfigService { export class DebugAppConfigService extends AppConfigService {
constructor(http: HttpClient) { constructor(private storage: StorageService, http: HttpClient) {
super(http); super(http);
} }
/** @override */ /** @override */
get<T>(key: string, defaultValue?: T): T { get<T>(key: string, defaultValue?: T): T {
if (key === AppConfigValues.OAUTHCONFIG) { if (key === AppConfigValues.OAUTHCONFIG) {
return <T> (JSON.parse(this.getItem(key)) || super.get<T>(key, defaultValue)); return <T> (JSON.parse(this.storage.getItem(key)) || super.get<T>(key, defaultValue));
} else if (key === AppConfigValues.APPLICATION) { } else if (key === AppConfigValues.APPLICATION) {
return undefined; return undefined;
} else { } else {
return <T> (<any> this.getItem(key) || super.get<T>(key, defaultValue)); return <T> (<any> this.storage.getItem(key) || super.get<T>(key, defaultValue));
} }
} }
getItem(key: string): string | null {
return localStorage.getItem(key);
}
} }

View File

@@ -17,14 +17,14 @@
import { DateCellComponent } from './date-cell.component'; import { DateCellComponent } from './date-cell.component';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { AlfrescoApiServiceMock, AppConfigService } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, AppConfigService, StorageService } from '@alfresco/adf-core';
import { Node } from '@alfresco/js-api'; import { Node } from '@alfresco/js-api';
describe('DataTableCellComponent', () => { describe('DataTableCellComponent', () => {
let alfrescoApiService: AlfrescoApiServiceMock; let alfrescoApiService: AlfrescoApiServiceMock;
beforeEach(() => { beforeEach(() => {
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
}); });
it('should use medium format by default', () => { it('should use medium format by default', () => {

View File

@@ -102,7 +102,7 @@ describe('DownloadZipDialogComponent', () => {
it('should call cancelDownload when CANCEL button is clicked', () => { it('should call cancelDownload when CANCEL button is clicked', () => {
fixture.detectChanges(); fixture.detectChanges();
spyOn(component, 'cancelDownload').and.returnValue(''); spyOn(component, 'cancelDownload');
const cancelButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#cancel-button'); const cancelButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#cancel-button');
cancelButton.click(); cancelButton.click();
@@ -118,7 +118,7 @@ describe('DownloadZipDialogComponent', () => {
it('should close dialog when download is completed', () => { it('should close dialog when download is completed', () => {
component.download('fakeUrl', 'fileName'); component.download('fakeUrl', 'fileName');
spyOn(component, 'cancelDownload').and.returnValue(''); spyOn(component, 'cancelDownload');
fixture.detectChanges(); fixture.detectChanges();
expect(dialogRef.close).toHaveBeenCalled(); expect(dialogRef.close).toHaveBeenCalled();
}); });
@@ -134,7 +134,7 @@ describe('DownloadZipDialogComponent', () => {
it('should interrupt download when cancel button is clicked', () => { it('should interrupt download when cancel button is clicked', () => {
spyOn(component, 'downloadZip'); spyOn(component, 'downloadZip');
spyOn(component, 'download'); spyOn(component, 'download');
spyOn(component, 'cancelDownload').and.returnValue(''); spyOn(component, 'cancelDownload');
fixture.detectChanges(); fixture.detectChanges();

View File

@@ -22,6 +22,7 @@ import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
import { AppConfigService } from '../app-config/app-config.service'; import { AppConfigService } from '../app-config/app-config.service';
import { setupTestBed } from '../testing/setupTestBed'; import { setupTestBed } from '../testing/setupTestBed';
import { CoreTestingModule } from '../testing/core.testing.module'; import { CoreTestingModule } from '../testing/core.testing.module';
import { StorageService } from '../services/storage.service';
describe('NodeFavoriteDirective', () => { describe('NodeFavoriteDirective', () => {
@@ -33,7 +34,7 @@ describe('NodeFavoriteDirective', () => {
}); });
beforeEach(() => { beforeEach(() => {
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
directive = new NodeFavoriteDirective( alfrescoApiService); directive = new NodeFavoriteDirective( alfrescoApiService);
}); });

View File

@@ -18,15 +18,24 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AppConfigService } from '../app-config/app-config.service'; import { AppConfigService } from '../app-config/app-config.service';
import { AlfrescoApiService } from '../services/alfresco-api.service'; import { AlfrescoApiService } from '../services/alfresco-api.service';
import { StorageService } from '../services/storage.service';
/* tslint:disable:adf-file-name */ /* tslint:disable:adf-file-name */
@Injectable() @Injectable()
export class AlfrescoApiServiceMock extends AlfrescoApiService { export class AlfrescoApiServiceMock extends AlfrescoApiService {
constructor(protected appConfig: AppConfigService) { constructor(protected appConfig: AppConfigService,
super(appConfig); protected storageService: StorageService) {
super(appConfig, storageService);
if (!this.alfrescoApi) { if (!this.alfrescoApi) {
this.initAlfrescoApi(); this.initAlfrescoApi();
} }
} }
initialize(): Promise<any> {
return new Promise((resolve) => {
this.alfrescoApiInitializedSubject.next();
resolve();
});
}
} }

View File

@@ -25,8 +25,9 @@ import {
} from '@alfresco/js-api'; } from '@alfresco/js-api';
import { AlfrescoApiCompatibility, AlfrescoApiConfig } from '@alfresco/js-api'; import { AlfrescoApiCompatibility, AlfrescoApiConfig } from '@alfresco/js-api';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
import { Subject } from 'rxjs'; import { Subject, Observable } from 'rxjs';
import { OauthConfigModel } from '../models/oauth-config.model'; import { OauthConfigModel } from '../models/oauth-config.model';
import { StorageService } from './storage.service';
/* tslint:disable:adf-file-name */ /* tslint:disable:adf-file-name */
@@ -39,6 +40,9 @@ export class AlfrescoApiService {
*/ */
nodeUpdated = new Subject<Node>(); nodeUpdated = new Subject<Node>();
protected alfrescoApiInitializedSubject: Subject<any>;
alfrescoApiInitialized: Observable<any>;
protected alfrescoApi: AlfrescoApiCompatibility; protected alfrescoApi: AlfrescoApiCompatibility;
lastConfig: AlfrescoApiConfig; lastConfig: AlfrescoApiConfig;
@@ -95,12 +99,18 @@ export class AlfrescoApiService {
return this.getInstance().core.groupsApi; return this.getInstance().core.groupsApi;
} }
constructor(protected appConfig: AppConfigService) { constructor(
protected appConfig: AppConfigService,
protected storageService: StorageService) {
this.alfrescoApiInitializedSubject = new Subject();
this.alfrescoApiInitialized = this.alfrescoApiInitializedSubject.asObservable();
} }
async load() { async load() {
await this.appConfig.load().then(() => { await this.appConfig.load().then(() => {
this.storageService.prefix = this.appConfig.get<string>(AppConfigValues.STORAGE_PREFIX, '');
this.initAlfrescoApi(); this.initAlfrescoApi();
this.alfrescoApiInitializedSubject.next();
}); });
} }

View File

@@ -40,7 +40,7 @@ describe('Auth Guard SSO role service', () => {
}); });
it('Should canActivate be true if the Role is present int the JWT token', async(() => { it('Should canActivate be true if the Role is present int the JWT token', async(() => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } }); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } });
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
@@ -50,7 +50,7 @@ describe('Auth Guard SSO role service', () => {
})); }));
it('Should canActivate be false if the Role is not present int the JWT token', async(() => { it('Should canActivate be false if the Role is not present int the JWT token', async(() => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role3'] } }); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role3'] } });
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
@@ -60,7 +60,7 @@ describe('Auth Guard SSO role service', () => {
})); }));
it('Should not redirect if canActivate is', async(() => { it('Should not redirect if canActivate is', async(() => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } }); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } });
spyOn(routerService, 'navigate').and.stub(); spyOn(routerService, 'navigate').and.stub();
@@ -72,7 +72,7 @@ describe('Auth Guard SSO role service', () => {
})); }));
it('Should canActivate return false if the data Role to check is empty', async(() => { it('Should canActivate return false if the data Role to check is empty', async(() => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1', 'role3'] } }); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1', 'role3'] } });
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
@@ -81,7 +81,7 @@ describe('Auth Guard SSO role service', () => {
})); }));
it('Should canActivate return false if the realm_access is not present', async(() => { it('Should canActivate return false if the realm_access is not present', async(() => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); spyOn(jwtHelperService, 'decodeToken').and.returnValue({});
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
@@ -90,7 +90,7 @@ describe('Auth Guard SSO role service', () => {
})); }));
it('Should redirect to the redirectURL if canActivate is false and redirectUrl is in data', async(() => { it('Should redirect to the redirectURL if canActivate is false and redirectUrl is in data', async(() => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); spyOn(jwtHelperService, 'decodeToken').and.returnValue({});
spyOn(routerService, 'navigate').and.stub(); spyOn(routerService, 'navigate').and.stub();
@@ -102,7 +102,7 @@ describe('Auth Guard SSO role service', () => {
})); }));
it('Should not redirect if canActivate is false and redirectUrl is not in data', async(() => { it('Should not redirect if canActivate is false and redirectUrl is not in data', async(() => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); spyOn(jwtHelperService, 'decodeToken').and.returnValue({});
spyOn(routerService, 'navigate').and.stub(); spyOn(routerService, 'navigate').and.stub();
@@ -137,7 +137,7 @@ describe('Auth Guard SSO role service', () => {
it('Should canActivate be true if both Real Role and Client Role are present int the JWT token', () => { it('Should canActivate be true if both Real Role and Client Role are present int the JWT token', () => {
const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ spyOn(jwtHelperService, 'decodeToken').and.returnValue({
'realm_access': { roles: ['role1'] }, 'realm_access': { roles: ['role1'] },
@@ -152,7 +152,7 @@ describe('Auth Guard SSO role service', () => {
it('Should canActivate be false if the Client Role is not present int the JWT token with the correct role', () => { it('Should canActivate be false if the Client Role is not present int the JWT token with the correct role', () => {
const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ spyOn(jwtHelperService, 'decodeToken').and.returnValue({
'realm_access': { roles: ['role1'] }, 'realm_access': { roles: ['role1'] },
@@ -168,7 +168,7 @@ describe('Auth Guard SSO role service', () => {
describe('ClientRole ', () => { describe('ClientRole ', () => {
it('Should be true if the resource_access contains the single role', () => { it('Should be true if the resource_access contains the single role', () => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue( spyOn(jwtHelperService, 'decodeToken').and.returnValue(
{ {
@@ -180,7 +180,7 @@ describe('Auth Guard SSO role service', () => {
}); });
it('Should be true if the resource_access contains at least one of the roles', () => { it('Should be true if the resource_access contains at least one of the roles', () => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue( spyOn(jwtHelperService, 'decodeToken').and.returnValue(
{ {
@@ -192,7 +192,7 @@ describe('Auth Guard SSO role service', () => {
}); });
it('Should be false if the resource_access does not contain the role', () => { it('Should be false if the resource_access does not contain the role', () => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue( spyOn(jwtHelperService, 'decodeToken').and.returnValue(
{ {
'resource_access': { fakeapp: { roles: ['role3'] } } 'resource_access': { fakeapp: { roles: ['role3'] } }
@@ -202,7 +202,7 @@ describe('Auth Guard SSO role service', () => {
}); });
it('Should be false if the resource_access does not contain the client role related to the app', () => { it('Should be false if the resource_access does not contain the client role related to the app', () => {
spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue( spyOn(jwtHelperService, 'decodeToken').and.returnValue(
{ {
'resource_access': { anotherfakeapp: { roles: ['role1'] } } 'resource_access': { anotherfakeapp: { roles: ['role1'] } }

View File

@@ -18,7 +18,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { JwtHelperService } from './jwt-helper.service'; import { JwtHelperService } from './jwt-helper.service';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { StorageService } from './storage.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -52,28 +51,22 @@ export class AuthGuardSsoRoleService implements CanActivate {
return hasRole; return hasRole;
} }
constructor(private storageService: StorageService, private jwtHelperService: JwtHelperService, private router: Router) { constructor(private jwtHelperService: JwtHelperService, private router: Router) {
} }
getRealmRoles(): string[] { getRealmRoles(): string[] {
const access = this.jwtHelperService.getValueFromLocalAccessToken<any>('realm_access'); const access = this.jwtHelperService.getValueFromLocalAccessToken<any>('realm_access');
const roles = access ? access['roles'] : []; return access ? access['roles'] : [];
return roles;
} }
getClientRoles(client: string): string[] { getClientRoles(client: string): string[] {
const clientRole = this.jwtHelperService.getValueFromLocalAccessToken<any>('resource_access')[client]; const clientRole = this.jwtHelperService.getValueFromLocalAccessToken<any>('resource_access')[client];
const roles = clientRole ? clientRole['roles'] : []; return clientRole ? clientRole['roles'] : [];
return roles;
}
getAccessToken(): string {
return this.storageService.getItem(JwtHelperService.USER_ACCESS_TOKEN);
} }
hasRealmRole(role: string): boolean { hasRealmRole(role: string): boolean {
let hasRole = false; let hasRole = false;
if (this.getAccessToken()) { if (this.jwtHelperService.getAccessToken()) {
const realmRoles = this.getRealmRoles(); const realmRoles = this.getRealmRoles();
hasRole = realmRoles.some((currentRole) => { hasRole = realmRoles.some((currentRole) => {
return currentRole === role; return currentRole === role;
@@ -96,7 +89,7 @@ export class AuthGuardSsoRoleService implements CanActivate {
hasClientRole(clientRole, role: string): boolean { hasClientRole(clientRole, role: string): boolean {
let hasRole = false; let hasRole = false;
if (this.getAccessToken()) { if (this.jwtHelperService.getAccessToken()) {
const clientRoles = this.getClientRoles(clientRole); const clientRoles = this.getClientRoles(clientRole);
hasRole = clientRoles.some((currentRole) => { hasRole = clientRoles.some((currentRole) => {
return currentRole === role; return currentRole === role;

View File

@@ -79,8 +79,15 @@ export class JwtHelperService {
* @returns Value from the token * @returns Value from the token
*/ */
getValueFromLocalAccessToken<T>(key: string): T { getValueFromLocalAccessToken<T>(key: string): T {
const accessToken = localStorage.getItem(JwtHelperService.USER_ACCESS_TOKEN); return this.getValueFromToken(this.getAccessToken(), key);
return this.getValueFromToken(accessToken, key); }
/**
* Gets access token
* @returns access token
*/
getAccessToken(): string {
return localStorage.getItem(JwtHelperService.USER_ACCESS_TOKEN);
} }
/** /**

View File

@@ -29,11 +29,9 @@ describe('StorageService', () => {
const key = 'test_key'; const key = 'test_key';
const value = 'test_value'; const value = 'test_value';
describe('StorageService', () => {
setupTestBed({ setupTestBed({
imports: [CoreTestingModule], imports: [CoreTestingModule]
providers: [
{ provide: AppConfigService, useClass: AppConfigServiceMock }
]
}); });
beforeEach(() => { beforeEach(() => {
@@ -48,15 +46,7 @@ describe('StorageService', () => {
it('should get the prefix for the storage from app config', (done) => { it('should get the prefix for the storage from app config', (done) => {
appConfig.load().then(() => { appConfig.load().then(() => {
expect(storage.storagePrefix).toBe('ADF_APP_'); expect(storage.prefix).toBe('ADF_APP_');
done();
});
});
it('should set an empty prefix when the it is not defined in the app config', (done) => {
appConfig.config.application.storagePrefix = '';
appConfig.load().then(() => {
expect(storage.storagePrefix).toBe('');
done(); done();
}); });
}); });
@@ -66,20 +56,9 @@ describe('StorageService', () => {
appConfig.load().then(() => { appConfig.load().then(() => {
storage.setItem(key, value); storage.setItem(key, value);
expect(localStorage.hasOwnProperty('ADF_APP_' + key)).not.toBe(null); const storageKey = localStorage.key(0);
expect(localStorage.getItem('ADF_APP_' + key)).toBe(value); expect(storageKey).toBe('ADF_APP_' + key);
done(); expect(localStorage.getItem(storageKey)).toBe(value);
});
});
it('should set a property without a prefix in the local storage', (done) => {
storage.clear();
appConfig.config.application.storagePrefix = '';
appConfig.load().then(() => {
storage.setItem(key, value);
expect(localStorage.hasOwnProperty(key)).not.toBe(null);
expect(localStorage.getItem(key)).toBe(value);
done(); done();
}); });
}); });
@@ -95,3 +74,36 @@ describe('StorageService', () => {
}); });
}); });
}); });
describe('StorageService', () => {
setupTestBed({
imports: [CoreTestingModule]
});
beforeEach(() => {
appConfig = TestBed.get(AppConfigService);
appConfig.config = {
application: {
storagePrefix: ''
}
};
storage = TestBed.get(StorageService);
});
it('should set an empty prefix when the it is not defined in the app config', (done) => {
appConfig.load().then(() => {
expect(storage.prefix).toBe('');
done();
});
});
it('should set a property without a prefix in the local storage', (done) => {
appConfig.load().then(() => {
storage.setItem(key, value);
expect(localStorage.getItem(key)).toBe(value);
done();
});
});
});
});

View File

@@ -16,7 +16,6 @@
*/ */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AppConfigService } from '../app-config/app-config.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -25,11 +24,18 @@ export class StorageService {
private memoryStore: { [key: string]: any } = {}; private memoryStore: { [key: string]: any } = {};
private useLocalStorage: boolean = false; private useLocalStorage: boolean = false;
storagePrefix: string; private _prefix: string = '';
constructor(private appConfigService: AppConfigService) { get prefix() {
return this._prefix;
}
set prefix(prefix: string) {
this._prefix = prefix ? prefix + '_' : '';
}
constructor() {
this.useLocalStorage = this.storageAvailable('localStorage'); this.useLocalStorage = this.storageAvailable('localStorage');
this.appConfigService.onLoad.subscribe(this.getAppPrefix.bind(this));
} }
/** /**
@@ -39,9 +45,9 @@ export class StorageService {
*/ */
getItem(key: string): string | null { getItem(key: string): string | null {
if (this.useLocalStorage) { if (this.useLocalStorage) {
return localStorage.getItem(this.storagePrefix + key); return localStorage.getItem(this.prefix + key);
} else { } else {
return this.memoryStore.hasOwnProperty(this.storagePrefix + key) ? this.memoryStore[this.storagePrefix + key] : null; return this.memoryStore.hasOwnProperty(this.prefix + key) ? this.memoryStore[this.prefix + key] : null;
} }
} }
@@ -52,9 +58,9 @@ export class StorageService {
*/ */
setItem(key: string, data: string) { setItem(key: string, data: string) {
if (this.useLocalStorage) { if (this.useLocalStorage) {
localStorage.setItem(this.storagePrefix + key, data); localStorage.setItem(this.prefix + key, data);
} else { } else {
this.memoryStore[this.storagePrefix + key] = data.toString(); this.memoryStore[this.prefix + key] = data.toString();
} }
} }
@@ -73,9 +79,9 @@ export class StorageService {
*/ */
removeItem(key: string) { removeItem(key: string) {
if (this.useLocalStorage) { if (this.useLocalStorage) {
localStorage.removeItem(this.storagePrefix + key); localStorage.removeItem(this.prefix + key);
} else { } else {
delete this.memoryStore[this.storagePrefix + key]; delete this.memoryStore[this.prefix + key];
} }
} }
@@ -86,7 +92,7 @@ export class StorageService {
*/ */
hasItem(key: string): boolean { hasItem(key: string): boolean {
if (this.useLocalStorage) { if (this.useLocalStorage) {
return localStorage.getItem(this.storagePrefix + key) ? true : false; return localStorage.getItem(this.prefix + key) ? true : false;
} else { } else {
return this.memoryStore.hasOwnProperty(key); return this.memoryStore.hasOwnProperty(key);
} }
@@ -103,19 +109,4 @@ export class StorageService {
return false; return false;
} }
} }
/**
* Sets the prefix that is used for the local storage of the app
* It assigns the string that is defined i the app config,
* empty prefix otherwise.
*/
getAppPrefix() {
const appConfiguration = this.appConfigService.get<any>('application');
if (appConfiguration && appConfiguration.storagePrefix) {
this.storagePrefix = appConfiguration.storagePrefix + '_';
} else {
this.storagePrefix = '';
}
}
} }

View File

@@ -23,6 +23,8 @@ import { UserPreferencesService, UserPreferenceValues } from './user-preferences
import { setupTestBed } from '../testing/setupTestBed'; import { setupTestBed } from '../testing/setupTestBed';
import { CoreTestingModule } from '../testing/core.testing.module'; import { CoreTestingModule } from '../testing/core.testing.module';
import { AppConfigServiceMock } from '../mock/app-config.service.mock'; import { AppConfigServiceMock } from '../mock/app-config.service.mock';
import { AlfrescoApiService } from './alfresco-api.service';
import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
describe('UserPreferencesService', () => { describe('UserPreferencesService', () => {
@@ -30,13 +32,15 @@ describe('UserPreferencesService', () => {
let preferences: UserPreferencesService; let preferences: UserPreferencesService;
let storage: StorageService; let storage: StorageService;
let appConfig: AppConfigServiceMock; let appConfig: AppConfigServiceMock;
let alfrescoApiService: AlfrescoApiServiceMock;
let translate: TranslateService; let translate: TranslateService;
let changeDisposable: any; let changeDisposable: any;
setupTestBed({ setupTestBed({
imports: [CoreTestingModule], imports: [CoreTestingModule],
providers: [ providers: [
{ provide: AppConfigService, useClass: AppConfigServiceMock } { provide: AppConfigService, useClass: AppConfigServiceMock },
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }
] ]
}); });
@@ -51,6 +55,7 @@ describe('UserPreferencesService', () => {
storage = TestBed.get(StorageService); storage = TestBed.get(StorageService);
translate = TestBed.get(TranslateService); translate = TestBed.get(TranslateService);
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
}); });
beforeEach(() => { beforeEach(() => {
@@ -65,8 +70,13 @@ describe('UserPreferencesService', () => {
storage.clear(); storage.clear();
}); });
describe(' with pagination config', () => {
beforeEach(() => {
preferences = new UserPreferencesService(translate, appConfig, storage, alfrescoApiService);
});
it('should get default pagination from app config', (done) => { it('should get default pagination from app config', (done) => {
preferences = new UserPreferencesService(translate, appConfig, storage);
appConfig.config.pagination.size = 0; appConfig.config.pagination.size = 0;
appConfig.load().then(() => { appConfig.load().then(() => {
expect(preferences.paginationSize).toBe(0); expect(preferences.paginationSize).toBe(0);
@@ -75,52 +85,44 @@ describe('UserPreferencesService', () => {
}); });
it('should return supported page sizes defined in the app config', () => { it('should return supported page sizes defined in the app config', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
const supportedPages = preferences.supportedPageSizes; const supportedPages = preferences.supportedPageSizes;
appConfig.load(); appConfig.load();
expect(supportedPages).toEqual(supportedPaginationSize); expect(supportedPages).toEqual(supportedPaginationSize);
}); });
it('should use [GUEST] as default storage prefix', () => { it('should use [GUEST] as default storage prefix', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.setStoragePrefix(null); preferences.setStoragePrefix(null);
expect(preferences.getStoragePrefix()).toBe('GUEST'); expect(preferences.getStoragePrefix()).toBe('GUEST');
}); });
it('should change storage prefix', () => { it('should change storage prefix', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.setStoragePrefix('USER_A'); preferences.setStoragePrefix('USER_A');
expect(preferences.getStoragePrefix()).toBe('USER_A'); expect(preferences.getStoragePrefix()).toBe('USER_A');
}); });
it('should format property key for default prefix', () => { it('should format property key for default prefix', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.setStoragePrefix(null); preferences.setStoragePrefix(null);
expect(preferences.getPropertyKey('propertyA')).toBe('GUEST__propertyA'); expect(preferences.getPropertyKey('propertyA')).toBe('GUEST__propertyA');
}); });
it('should format property key for custom prefix', () => { it('should format property key for custom prefix', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.setStoragePrefix('USER_A'); preferences.setStoragePrefix('USER_A');
expect(preferences.getPropertyKey('propertyA')).toBe('USER_A__propertyA'); expect(preferences.getPropertyKey('propertyA')).toBe('USER_A__propertyA');
}); });
it('should save value with default prefix', () => { it('should save value with default prefix', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.set('propertyA', 'valueA'); preferences.set('propertyA', 'valueA');
const propertyKey = preferences.getPropertyKey('propertyA'); const propertyKey = preferences.getPropertyKey('propertyA');
expect(storage.getItem(propertyKey)).toBe('valueA'); expect(storage.getItem(propertyKey)).toBe('valueA');
}); });
it('should null value return default prefix', () => { it('should null value return default prefix', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
storage.setItem('paginationSize', null); storage.setItem('paginationSize', null);
const paginationSize = preferences.getPropertyKey('paginationSize'); const paginationSize = preferences.getPropertyKey('paginationSize');
expect(preferences.get(paginationSize, 'default')).toBe('default'); expect(preferences.get(paginationSize, 'default')).toBe('default');
}); });
it('should save value with custom prefix', () => { it('should save value with custom prefix', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.setStoragePrefix('USER_A'); preferences.setStoragePrefix('USER_A');
preferences.set('propertyA', 'valueA'); preferences.set('propertyA', 'valueA');
const propertyKey = preferences.getPropertyKey('propertyA'); const propertyKey = preferences.getPropertyKey('propertyA');
@@ -128,32 +130,54 @@ describe('UserPreferencesService', () => {
}); });
it('should return as default locale the app.config locate as first', () => { it('should return as default locale the app.config locate as first', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
appConfig.config.locale = 'fake-locate-config'; appConfig.config.locale = 'fake-locate-config';
spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser'); spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser');
expect(preferences.getDefaultLocale()).toBe('fake-locate-config'); expect(preferences.getDefaultLocale()).toBe('fake-locate-config');
}); });
it('should return as default locale the browser locale as second', () => { it('should return as default locale the browser locale as second', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser'); spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser');
expect(preferences.getDefaultLocale()).toBe('fake-locate-browser'); expect(preferences.getDefaultLocale()).toBe('fake-locate-browser');
}); });
it('should return as default locale the component property as third ', () => { it('should return as default locale the component property as third ', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
spyOn(translate, 'getBrowserCultureLang').and.stub(); spyOn(translate, 'getBrowserCultureLang').and.stub();
expect(preferences.getDefaultLocale()).toBe('en'); expect(preferences.getDefaultLocale()).toBe('en');
}); });
it('should return as locale the store locate', () => { it('should return as locale the store locate', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.locale = 'fake-store-locate'; preferences.locale = 'fake-store-locate';
appConfig.config.locale = 'fake-locate-config'; appConfig.config.locale = 'fake-locate-config';
spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser'); spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser');
expect(preferences.locale).toBe('fake-store-locate'); expect(preferences.locale).toBe('fake-store-locate');
}); });
it('should not store in the storage the locale if the app.config.json does not have a value', () => {
preferences.locale = 'fake-store-locate';
spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser');
expect(preferences.locale).toBe('fake-store-locate');
expect(storage.getItem(UserPreferenceValues.Locale)).toBe(null);
});
it('should stream the page size value when is set', (done) => {
preferences.paginationSize = 5;
changeDisposable = preferences.onChange.subscribe((userPreferenceStatus) => {
expect(userPreferenceStatus[UserPreferenceValues.PaginationSize]).toBe(5);
done();
});
});
it('should stream the user preference status when changed', (done) => {
preferences.set('propertyA', 'valueA');
changeDisposable = preferences.onChange.subscribe((userPreferenceStatus) => {
expect(userPreferenceStatus.propertyA).toBe('valueA');
done();
});
});
});
describe('with language config', () => {
it('should store default textOrientation based on language', async(() => { it('should store default textOrientation based on language', async(() => {
appConfig.config.languages = [ appConfig.config.languages = [
{ {
@@ -161,8 +185,8 @@ describe('UserPreferencesService', () => {
} }
]; ];
appConfig.config.locale = 'fake-locale-config'; appConfig.config.locale = 'fake-locale-config';
preferences = new UserPreferencesService(translate, appConfig, storage); preferences = new UserPreferencesService(translate, appConfig, storage, alfrescoApiService);
appConfig.load(); alfrescoApiService.initialize();
const textOrientation = preferences.getPropertyKey('textOrientation'); const textOrientation = preferences.getPropertyKey('textOrientation');
expect(storage.getItem(textOrientation)).toBe('ltr'); expect(storage.getItem(textOrientation)).toBe('ltr');
})); }));
@@ -175,8 +199,8 @@ describe('UserPreferencesService', () => {
} }
]; ];
appConfig.config.locale = 'fake-locale-config'; appConfig.config.locale = 'fake-locale-config';
preferences = new UserPreferencesService(translate, appConfig, storage); preferences = new UserPreferencesService(translate, appConfig, storage, alfrescoApiService);
appConfig.load(); alfrescoApiService.initialize();
const textOrientation = preferences.getPropertyKey('textOrientation'); const textOrientation = preferences.getPropertyKey('textOrientation');
expect(storage.getItem(textOrientation)).toBe('rtl'); expect(storage.getItem(textOrientation)).toBe('rtl');
})); }));
@@ -187,8 +211,8 @@ describe('UserPreferencesService', () => {
key: 'fake-locale-browser' key: 'fake-locale-browser'
} }
]; ];
preferences = new UserPreferencesService(translate, appConfig, storage); preferences = new UserPreferencesService(translate, appConfig, storage, alfrescoApiService);
appConfig.load(); alfrescoApiService.initialize();
const textOrientation = preferences.getPropertyKey('textOrientation'); const textOrientation = preferences.getPropertyKey('textOrientation');
expect(storage.getItem(textOrientation)).toBe(null); expect(storage.getItem(textOrientation)).toBe(null);
@@ -202,8 +226,8 @@ describe('UserPreferencesService', () => {
} }
]; ];
spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locale-browser'); spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locale-browser');
preferences = new UserPreferencesService(translate, appConfig, storage); preferences = new UserPreferencesService(translate, appConfig, storage, alfrescoApiService);
appConfig.load(); alfrescoApiService.initialize();
changeDisposable = preferences.onChange changeDisposable = preferences.onChange
.subscribe((userPreferenceStatus) => { .subscribe((userPreferenceStatus) => {
@@ -211,30 +235,5 @@ describe('UserPreferencesService', () => {
done(); done();
}); });
}); });
it('should not store in the storage the locale if the app.config.json does not have a value', () => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.locale = 'fake-store-locate';
spyOn(translate, 'getBrowserCultureLang').and.returnValue('fake-locate-browser');
expect(preferences.locale).toBe('fake-store-locate');
expect(storage.getItem(UserPreferenceValues.Locale)).toBe(null);
});
it('should stream the page size value when is set', (done) => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.paginationSize = 5;
changeDisposable = preferences.onChange.subscribe((userPreferenceStatus) => {
expect(userPreferenceStatus[UserPreferenceValues.PaginationSize]).toBe(5);
done();
});
});
it('should stream the user preference status when changed', (done) => {
preferences = new UserPreferencesService(translate, appConfig, storage);
preferences.set('propertyA', 'valueA');
changeDisposable = preferences.onChange.subscribe((userPreferenceStatus) => {
expect(userPreferenceStatus.propertyA).toBe('valueA');
done();
});
}); });
}); });

View File

@@ -22,6 +22,7 @@ import { AppConfigService, AppConfigValues } from '../app-config/app-config.serv
import { LanguageItem } from '../language-menu/language.interface'; import { LanguageItem } from '../language-menu/language.interface';
import { StorageService } from './storage.service'; import { StorageService } from './storage.service';
import { distinctUntilChanged, map } from 'rxjs/operators'; import { distinctUntilChanged, map } from 'rxjs/operators';
import { AlfrescoApiService } from './alfresco-api.service';
export enum UserPreferenceValues { export enum UserPreferenceValues {
PaginationSize = 'paginationSize', PaginationSize = 'paginationSize',
@@ -48,8 +49,9 @@ export class UserPreferencesService {
constructor(public translate: TranslateService, constructor(public translate: TranslateService,
private appConfig: AppConfigService, private appConfig: AppConfigService,
private storage: StorageService) { private storage: StorageService,
this.appConfig.onLoad.subscribe(this.initUserPreferenceStatus.bind(this)); private alfrescoApiService: AlfrescoApiService) {
this.alfrescoApiService.alfrescoApiInitialized.subscribe(this.initUserPreferenceStatus.bind(this));
this.onChangeSubject = new BehaviorSubject(this.userPreferenceStatus); this.onChangeSubject = new BehaviorSubject(this.userPreferenceStatus);
this.onChange = this.onChangeSubject.asObservable(); this.onChange = this.onChangeSubject.asObservable();
} }

View File

@@ -18,7 +18,7 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormCloudService } from './form-cloud.service'; import { FormCloudService } from './form-cloud.service';
import { AlfrescoApiService, CoreModule, setupTestBed, AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core'; import { AlfrescoApiService, CoreModule, setupTestBed, AppConfigService } from '@alfresco/adf-core';
import { of } from 'rxjs'; import { of } from 'rxjs';
declare let jasmine: any; declare let jasmine: any;
@@ -28,11 +28,6 @@ const responseBody = {
{ id: 'id', name: 'name', formKey: 'form-key' } { id: 'id', name: 'name', formKey: 'form-key' }
}; };
const alfrescoApiServiceStub = {
getInstance() { },
load() { }
};
const oauth2Auth = jasmine.createSpyObj('oauth2Auth', ['callCustomApi']); const oauth2Auth = jasmine.createSpyObj('oauth2Auth', ['callCustomApi']);
describe('Form Cloud service', () => { describe('Form Cloud service', () => {
@@ -48,11 +43,7 @@ describe('Form Cloud service', () => {
NoopAnimationsModule, NoopAnimationsModule,
CoreModule.forRoot() CoreModule.forRoot()
], ],
providers: [ providers: [FormCloudService, AlfrescoApiService, AppConfigService]
FormCloudService,
{ provide: AlfrescoApiService, useValue: alfrescoApiServiceStub },
{ provide: AppConfigService, useClass: AppConfigServiceMock }
]
}); });
beforeEach(() => { beforeEach(() => {

View File

@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { async } from '@angular/core/testing'; import { async } from '@angular/core/testing';
import { setupTestBed } from '@alfresco/adf-core'; import { setupTestBed, StorageService } from '@alfresco/adf-core';
import { fakeProcessCloudList } from '../mock/process-list-service.mock'; import { fakeProcessCloudList } from '../mock/process-list-service.mock';
import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core';
import { ProcessListCloudService } from './process-list-cloud.service'; import { ProcessListCloudService } from './process-list-cloud.service';
@@ -62,7 +62,7 @@ describe('Activiti ProcessList Cloud Service', () => {
}); });
beforeEach(async(() => { beforeEach(async(() => {
alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null)); alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
service = new ProcessListCloudService(alfrescoApiMock, service = new ProcessListCloudService(alfrescoApiMock,
new AppConfigService(null), new AppConfigService(null),
new LogService(new AppConfigService(null))); new LogService(new AppConfigService(null)));

View File

@@ -16,7 +16,7 @@
*/ */
import { async, TestBed } from '@angular/core/testing'; import { async, TestBed } from '@angular/core/testing';
import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; import { setupTestBed, IdentityUserService, StorageService } from '@alfresco/adf-core';
import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core';
import { TaskCloudService } from './task-cloud.service'; import { TaskCloudService } from './task-cloud.service';
import { taskCompleteCloudMock } from '../task-header/mocks/fake-complete-task.mock'; import { taskCompleteCloudMock } from '../task-header/mocks/fake-complete-task.mock';
@@ -68,7 +68,7 @@ describe('Task Cloud Service', () => {
}); });
beforeEach(async(() => { beforeEach(async(() => {
alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null)); alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
identityUserService = TestBed.get(IdentityUserService); identityUserService = TestBed.get(IdentityUserService);
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(cloudMockUser); spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(cloudMockUser);
service = new TaskCloudService(alfrescoApiMock, service = new TaskCloudService(alfrescoApiMock,

View File

@@ -16,7 +16,7 @@
*/ */
import { async } from '@angular/core/testing'; import { async } from '@angular/core/testing';
import { setupTestBed } from '@alfresco/adf-core'; import { setupTestBed, StorageService } from '@alfresco/adf-core';
import { fakeTaskCloudList } from '../mock/fakeTaskResponseMock'; import { fakeTaskCloudList } from '../mock/fakeTaskResponseMock';
import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core';
import { TaskListCloudService } from './task-list-cloud.service'; import { TaskListCloudService } from './task-list-cloud.service';
@@ -64,7 +64,7 @@ describe('Activiti TaskList Cloud Service', () => {
}); });
beforeEach(async(() => { beforeEach(async(() => {
alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null)); alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
service = new TaskListCloudService(alfrescoApiMock, service = new TaskListCloudService(alfrescoApiMock,
new AppConfigService(null), new AppConfigService(null),
new LogService(new AppConfigService(null))); new LogService(new AppConfigService(null)));

View File

@@ -19,7 +19,8 @@ import { async } from '@angular/core/testing';
import { mockError, fakeProcessFilters } from '../../mock'; import { mockError, fakeProcessFilters } from '../../mock';
import { FilterProcessRepresentationModel } from '../models/filter-process.model'; import { FilterProcessRepresentationModel } from '../models/filter-process.model';
import { ProcessFilterService } from './process-filter.service'; import { ProcessFilterService } from './process-filter.service';
import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService, setupTestBed, CoreModule } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService,
setupTestBed, CoreModule, StorageService } from '@alfresco/adf-core';
declare let jasmine: any; declare let jasmine: any;
@@ -36,7 +37,7 @@ describe('Process filter', () => {
}); });
beforeEach(() => { beforeEach(() => {
apiService = new AlfrescoApiServiceMock(new AppConfigService(null)); apiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
service = new ProcessFilterService(apiService); service = new ProcessFilterService(apiService);
alfrescoApi = apiService.getInstance(); alfrescoApi = apiService.getInstance();
}); });

View File

@@ -21,7 +21,8 @@ import { mockError, fakeProcessDef, fakeTasksList } from '../../mock';
import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model'; import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model';
import { ProcessInstanceVariable } from '../models/process-instance-variable.model'; import { ProcessInstanceVariable } from '../models/process-instance-variable.model';
import { ProcessService } from './process.service'; import { ProcessService } from './process.service';
import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigService, setupTestBed, CoreModule } from '@alfresco/adf-core'; import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigService,
setupTestBed, CoreModule, StorageService } from '@alfresco/adf-core';
declare let moment: any; declare let moment: any;
@@ -38,7 +39,7 @@ describe('ProcessService', () => {
}); });
beforeEach(() => { beforeEach(() => {
apiService = new AlfrescoApiServiceMock(new AppConfigService(null)); apiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
service = new ProcessService(apiService); service = new ProcessService(apiService);
alfrescoApi = apiService.getInstance(); alfrescoApi = apiService.getInstance();
}); });

View File

@@ -19,7 +19,7 @@ import { async } from '@angular/core/testing';
import { fakeAppFilter, fakeAppPromise, fakeFilters } from '../../mock'; import { fakeAppFilter, fakeAppPromise, fakeFilters } from '../../mock';
import { FilterRepresentationModel } from '../models/filter.model'; import { FilterRepresentationModel } from '../models/filter.model';
import { TaskFilterService } from './task-filter.service'; import { TaskFilterService } from './task-filter.service';
import { AlfrescoApiServiceMock, LogService, AppConfigService, setupTestBed, CoreModule } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, LogService, AppConfigService, setupTestBed, CoreModule, StorageService } from '@alfresco/adf-core';
declare let jasmine: any; declare let jasmine: any;
@@ -34,7 +34,9 @@ describe('Activiti Task filter Service', () => {
}); });
beforeEach(async(() => { beforeEach(async(() => {
service = new TaskFilterService(new AlfrescoApiServiceMock(new AppConfigService(null)), new LogService(new AppConfigService(null))); service = new TaskFilterService(
new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()),
new LogService(new AppConfigService(null)));
jasmine.Ajax.install(); jasmine.Ajax.install();
})); }));

View File

@@ -16,7 +16,7 @@
*/ */
import { async } from '@angular/core/testing'; import { async } from '@angular/core/testing';
import { UserProcessModel, setupTestBed, CoreModule } from '@alfresco/adf-core'; import { UserProcessModel, setupTestBed, CoreModule, StorageService } from '@alfresco/adf-core';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { import {
fakeCompletedTaskList, fakeCompletedTaskList,
@@ -50,7 +50,9 @@ describe('Activiti TaskList Service', () => {
}); });
beforeEach(async(() => { beforeEach(async(() => {
service = new TaskListService(new AlfrescoApiServiceMock(new AppConfigService(null)), new LogService(new AppConfigService(null))); service = new TaskListService(
new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()),
new LogService(new AppConfigService(null)));
jasmine.Ajax.install(); jasmine.Ajax.install();
})); }));

View File

@@ -31,6 +31,12 @@ export class LocalStorageUtil {
); );
} }
static async removeStorageItem(field: string) {
await browser.executeScript(
'window.adf.removeStorageItem(`' + field + '`);'
);
}
static async setUserPreference(field: string, value: any) { static async setUserPreference(field: string, value: any) {
await browser.executeScript( await browser.executeScript(
'window.adf.setUserPreference(`' + field + '`, `' + value + '`);' 'window.adf.setUserPreference(`' + field + '`, `' + value + '`);'

View File

@@ -16,7 +16,7 @@
*/ */
import { AlfrescoApiCompatibility, AlfrescoApiConfig } from '@alfresco/js-api'; import { AlfrescoApiCompatibility, AlfrescoApiConfig } from '@alfresco/js-api';
import { AlfrescoApiService, AppConfigValues, AppConfigService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigValues, AppConfigService, StorageService } from '@alfresco/adf-core';
export class TestingAlfrescoApiService extends AlfrescoApiService { export class TestingAlfrescoApiService extends AlfrescoApiService {
@@ -25,9 +25,10 @@ export class TestingAlfrescoApiService extends AlfrescoApiService {
config = { config = {
}; };
constructor(public appConfig: AppConfigService) { constructor(public appConfig: AppConfigService, public storageService: StorageService) {
super(null); super(null, null);
const oauth = Object.assign({}, this.appConfig.get<any>(AppConfigValues.OAUTHCONFIG, null)); const oauth = Object.assign({}, this.appConfig.get<any>(AppConfigValues.OAUTHCONFIG, null));
this.storageService.prefix = this.appConfig.get<string>(AppConfigValues.STORAGE_PREFIX, '');
this.config = new AlfrescoApiConfig({ this.config = new AlfrescoApiConfig({
provider: this.appConfig.get<string>(AppConfigValues.PROVIDERS), provider: this.appConfig.get<string>(AppConfigValues.PROVIDERS),
hostEcm: this.appConfig.get<string>(AppConfigValues.ECMHOST), hostEcm: this.appConfig.get<string>(AppConfigValues.ECMHOST),
@@ -37,6 +38,7 @@ export class TestingAlfrescoApiService extends AlfrescoApiService {
contextRoot: this.appConfig.get<string>(AppConfigValues.CONTEXTROOTECM), contextRoot: this.appConfig.get<string>(AppConfigValues.CONTEXTROOTECM),
disableCsrf: this.appConfig.get<boolean>(AppConfigValues.DISABLECSRF), disableCsrf: this.appConfig.get<boolean>(AppConfigValues.DISABLECSRF),
withCredentials: this.appConfig.get<boolean>(AppConfigValues.AUTH_WITH_CREDENTIALS, false), withCredentials: this.appConfig.get<boolean>(AppConfigValues.AUTH_WITH_CREDENTIALS, false),
domainPrefix: this.storageService.prefix,
oauth2: oauth oauth2: oauth
}); });
} }

114
package-lock.json generated
View File

@@ -1,69 +1,69 @@
{ {
"name": "alfresco-components", "name": "alfresco-components",
"version": "3.2.1", "version": "3.3.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@alfresco/adf-content-services": { "@alfresco/adf-content-services": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.3.0.tgz",
"integrity": "sha512-dljtJUnvlA2OC1g9u8TyQEnoHqTEVl94AH6S7dcpWiACLCSMiwd5Zkdpe/p/5FWxPY4on53iIR31KJmyYXfoYQ==", "integrity": "sha512-VzEqJC+e2CYtFSwSJDXI8PR7xFCozsV113CpLEW9GT1rcNOyZrwQUe1MZqD3iNJzZdtsw+VI1kfsOwX9v0LNeA==",
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@alfresco/adf-core": { "@alfresco/adf-core": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.3.0.tgz",
"integrity": "sha512-BFaL3ARaErwvYa4OjgAgWbN0Pm1NMfULd9gFZROQCqPhr794KtwhGqIVmr+G6JjaQvIXMZ3hSTppKu63NyBoqA==", "integrity": "sha512-OKjG0FduZWj/Ux4O/hKtvz4opWCLrrRP0bsQfRPMfNymIUlHHhS12ciPVSlKaVlozrJ4poyjq8maGa8gqSDMcA==",
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@alfresco/adf-extensions": { "@alfresco/adf-extensions": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.3.0.tgz",
"integrity": "sha512-ULYZmpRfR7ckLvNe/273DhgWvx7wvoUDzy1lsOIpFS0LfyfjEqEjOcQQ3V2DAcbR1Rl7cJ7+3RXkfVHmp/d6ng==", "integrity": "sha512-Fvet22KpZ8zLGKccgsjlf9uEE2+47h0QMDMSX1S4tMbLlLs34PpHQiYNPOEKZgeV/kWx0+nhM7QhQUfH8NpRUA==",
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@alfresco/adf-insights": { "@alfresco/adf-insights": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.3.0.tgz",
"integrity": "sha512-6ktlzvoHJ2Pf6+Qcp/ua8rZ/RYuakO0Y6QeFNXlilVt3FK/jF1AmJT3Xj21tdnxOEzWAKTH1lb+rd/0itP+DoQ==", "integrity": "sha512-EX04XBLz4tuGzG/pcJpkxUL8gjbUtr/njBa+J1R4V5H4Lk66pBf9okINZvSrNWExNSPKmuz/1YqmS+X5QMwAQQ==",
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@alfresco/adf-process-services": { "@alfresco/adf-process-services": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.3.0.tgz",
"integrity": "sha512-cHNFYxzkUgvf0oqWJt87rnmEl9ujtJ2Jw73jR/Wcayk2QgOrmMuhaIaFlkgqhfudIHeXnpT2RfcgxcF7rWCWaA==", "integrity": "sha512-ib08V7g7h8BCkJ/lkkDTZPBOz8qSqD40aif5uySr8YX6QKSZ5KyEdfqKikYyEchISEOd0yhhN/nxZW1ExHb0iQ==",
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@alfresco/adf-process-services-cloud": { "@alfresco/adf-process-services-cloud": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.3.0.tgz",
"integrity": "sha512-40IirZWLqRqTcJlYMwNRX7AyWUdrRzOHG2OPsAtTO4ozEub3UzYZDte/7uh7a52CoVsSz+Kx/oom8pGK+9MVoQ==", "integrity": "sha512-7PQlXx4zi8uWk/Gp8A8ETicFFfHzEcaR9sI4UK+vUtPyG5MbDobbaPWLyn8iMZQniuCBk1oFwVRY2JrXf5Tciw==",
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@alfresco/adf-testing": { "@alfresco/adf-testing": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.3.0.tgz",
"integrity": "sha512-8RG80G3JMvB3QjtVRI4jsLXDUicvqXyc9TrTgOcH6ilYKKTqt6P+OJi3H45yLPhat41MwSeP1LgCoUW3d1SWHQ==", "integrity": "sha512-xZUgLyuHTWwR22xdT7x5sh11vUrk/94thdfIFsYEuTX6X4W5lJkylF/C9fAuAPIuTkrAu8DWloUgSNVtyTCMVg==",
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@alfresco/js-api": { "@alfresco/js-api": {
"version": "3.2.1", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.3.0.tgz",
"integrity": "sha512-qaXftaHqFonWRKRmYxhB2/bEpUh5fvUj6cN+xuKUXIGgt9XxF76NpWkXnEEQLZ0BWg5upd19Q3N1x4E7DiNGUg==", "integrity": "sha512-A15Q5j4jVNFUI0hdw0zIGonU05Wbjvq8ZJBijrkC3fq904oYuq49giKpPkbXjowk9xBfZZejGvaDMT5jYTXlxg==",
"requires": { "requires": {
"event-emitter": "0.3.4", "event-emitter": "0.3.4",
"superagent": "3.8.2" "superagent": "3.8.2"
@@ -5629,11 +5629,12 @@
}, },
"dependencies": { "dependencies": {
"d": { "d": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"requires": { "requires": {
"es5-ext": "^0.10.9" "es5-ext": "^0.10.50",
"type": "^1.0.1"
} }
} }
} }
@@ -5663,11 +5664,12 @@
}, },
"dependencies": { "dependencies": {
"d": { "d": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"requires": { "requires": {
"es5-ext": "^0.10.9" "es5-ext": "^0.10.50",
"type": "^1.0.1"
} }
} }
} }
@@ -6527,7 +6529,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@@ -6548,12 +6551,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@@ -6568,17 +6573,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@@ -6695,7 +6703,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@@ -6707,6 +6716,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@@ -6721,6 +6731,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@@ -6728,12 +6739,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@@ -6752,6 +6765,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@@ -6832,7 +6846,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@@ -6844,6 +6859,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@@ -6929,7 +6945,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@@ -6965,6 +6982,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@@ -6984,6 +7002,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@@ -7027,12 +7046,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.3", "version": "3.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@@ -17056,6 +17077,11 @@
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"dev": true "dev": true
}, },
"type": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz",
"integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw=="
},
"type-check": { "type-check": {
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",