diff --git a/lib/core/feature-flags/src/lib/services/debug-features.service.spec.ts b/lib/core/feature-flags/src/lib/services/debug-features.service.spec.ts index 550adff8d8..f6b0f9dc09 100644 --- a/lib/core/feature-flags/src/lib/services/debug-features.service.spec.ts +++ b/lib/core/feature-flags/src/lib/services/debug-features.service.spec.ts @@ -17,37 +17,37 @@ import { TestBed } from '@angular/core/testing'; import { DebugFeaturesService } from './debug-features.service'; -import { StorageService } from '../../../../src/lib/common/services/storage.service'; -import { OverridableFeaturesServiceToken, WritableFeaturesServiceToken } from '../interfaces/features.interface'; +import { OverridableFeaturesServiceToken, WritableFeaturesServiceConfigToken, WritableFeaturesServiceToken } from '../interfaces/features.interface'; import { DummyFeaturesService } from './dummy-features.service'; import { StorageFeaturesService } from './storage-features.service'; import { take } from 'rxjs/operators'; describe('DebugFeaturesService', () => { let service: DebugFeaturesService; - const mockStorage = { - getItem: () => - JSON.stringify({ - feature1: { - current: true - }, - feature2: { - current: false, - fictive: true - } - }), - setItem: () => {} - }; + let mockStorageKey: string; + let mockStorage; beforeEach(() => { + mockStorageKey = 'storage-key-test'; + mockStorage = { [mockStorageKey]: true }; + TestBed.configureTestingModule({ providers: [ DebugFeaturesService, - { provide: StorageService, useValue: mockStorage }, + { + provide: WritableFeaturesServiceConfigToken, + useValue: { storageKey: mockStorageKey } + }, { provide: WritableFeaturesServiceToken, useClass: StorageFeaturesService }, { provide: OverridableFeaturesServiceToken, useClass: DummyFeaturesService } ] }); + + spyOn(sessionStorage, 'getItem').and.callFake((key) => JSON.stringify(mockStorage[key])); + spyOn(sessionStorage, 'setItem').and.callFake((key, value) => { + mockStorage[key] = value; + }); + service = TestBed.inject(DebugFeaturesService); }); diff --git a/lib/core/feature-flags/src/lib/services/debug-features.service.ts b/lib/core/feature-flags/src/lib/services/debug-features.service.ts index bacf205a48..0a6434b5b8 100644 --- a/lib/core/feature-flags/src/lib/services/debug-features.service.ts +++ b/lib/core/feature-flags/src/lib/services/debug-features.service.ts @@ -16,8 +16,8 @@ */ import { Inject, Injectable, Optional } from '@angular/core'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { skip, switchMap } from 'rxjs/operators'; +import { BehaviorSubject, Observable, combineLatest } from 'rxjs'; +import { filter, switchMap } from 'rxjs/operators'; import { IDebugFeaturesService, IFeaturesService, @@ -29,12 +29,12 @@ import { FlagSet, IWritableFeaturesService } from '../interfaces/features.interface'; -import { StorageService } from '@alfresco/adf-core'; @Injectable() export class DebugFeaturesService implements IDebugFeaturesService { - private isInDebugMode: BehaviorSubject; - private isInDebugMode$: Observable; + private readonly isInDebugModeSubject = new BehaviorSubject(false); + private readonly isInDebugMode$ = this.isInDebugModeSubject.asObservable(); + private readonly initSubject = new BehaviorSubject(false); get storageKey(): string { return `${this.config?.storageKey || 'feature-flags'}-override`; @@ -43,14 +43,15 @@ export class DebugFeaturesService implements IDebugFeaturesService { constructor( @Inject(OverridableFeaturesServiceToken) private overriddenFeaturesService: IFeaturesService, @Inject(WritableFeaturesServiceToken) private writableFeaturesService: IFeaturesService & IWritableFeaturesService, - private storageService: StorageService, @Optional() @Inject(WritableFeaturesServiceConfigToken) private config?: WritableFeaturesServiceConfig ) { - this.isInDebugMode = new BehaviorSubject(JSON.parse(this.storageService.getItem(this.storageKey) || 'false')); - this.isInDebugMode$ = this.isInDebugMode.asObservable(); + this.init(); - this.isInDebugMode.pipe(skip(1)).subscribe((debugMode) => { - this.storageService.setItem(this.storageKey, JSON.stringify(debugMode)); + combineLatest({ + debugMode: this.isInDebugModeSubject, + init: this.waitForInitializationToFinish() + }).subscribe(({ debugMode }) => { + sessionStorage.setItem(this.storageKey, JSON.stringify(debugMode)); }); } @@ -87,10 +88,20 @@ export class DebugFeaturesService implements IDebugFeaturesService { } enable(on: boolean): void { - this.isInDebugMode.next(on); + this.isInDebugModeSubject.next(on); } isEnabled$(): Observable { return this.isInDebugMode$; } + + private init() { + const storedOverride = JSON.parse(sessionStorage.getItem(this.storageKey) || 'false'); + this.isInDebugModeSubject.next(storedOverride); + this.initSubject.next(true); + } + + private waitForInitializationToFinish(): Observable { + return this.initSubject.pipe(filter((initialized) => !!initialized)); + } } diff --git a/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts b/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts index 10451e3459..054f49edf8 100644 --- a/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts +++ b/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts @@ -17,17 +17,20 @@ import { TestBed } from '@angular/core/testing'; import { StorageFeaturesService } from './storage-features.service'; -import { StorageService } from '../../../../src/public-api'; import { FlagSet, WritableFeaturesServiceConfigToken } from '../interfaces/features.interface'; import { skip, take } from 'rxjs/operators'; describe('StorageFeaturesService', () => { let storageFeaturesService: StorageFeaturesService; - describe('if flags are present in LocalStorage', () => { - const mockStorage = { - getItem: () => - JSON.stringify({ + describe('if flags are present in sessionStorage', () => { + let mockStorageKey: string; + let mockStorage; + + beforeEach(() => { + mockStorageKey = 'storage-key-test'; + mockStorage = { + [mockStorageKey]: { feature1: { current: true }, @@ -35,23 +38,23 @@ describe('StorageFeaturesService', () => { current: false, fictive: true } - }), - setItem: () => {} - }; + } + }; - beforeEach(() => { TestBed.configureTestingModule({ providers: [ - { provide: StorageService, useValue: mockStorage }, { provide: WritableFeaturesServiceConfigToken, - useValue: { - storageKey: 'storage-key-test' - } + useValue: { storageKey: mockStorageKey } } ] }); + spyOn(sessionStorage, 'getItem').and.callFake((key) => JSON.stringify(mockStorage[key])); + spyOn(sessionStorage, 'setItem').and.callFake((key, value) => { + mockStorage[key] = value; + }); + storageFeaturesService = TestBed.inject(StorageFeaturesService); storageFeaturesService.init(); }); diff --git a/lib/core/feature-flags/src/lib/services/storage-features.service.ts b/lib/core/feature-flags/src/lib/services/storage-features.service.ts index 56c2b414de..6dc9b07afe 100644 --- a/lib/core/feature-flags/src/lib/services/storage-features.service.ts +++ b/lib/core/feature-flags/src/lib/services/storage-features.service.ts @@ -16,8 +16,8 @@ */ import { Inject, Injectable, Optional } from '@angular/core'; -import { BehaviorSubject, Observable, of } from 'rxjs'; -import { map, skip } from 'rxjs/operators'; +import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { FlagChangeset, IFeaturesService, @@ -28,21 +28,21 @@ import { WritableFeaturesServiceConfig } from '../interfaces/features.interface'; import { FlagSetParser } from './flagset.parser'; -import { StorageService } from '@alfresco/adf-core'; @Injectable({ providedIn: 'root' }) export class StorageFeaturesService implements IFeaturesService, IWritableFeaturesService { private currentFlagState: WritableFlagChangeset = {}; - private flags = new BehaviorSubject({}); - private flags$ = this.flags.asObservable(); + private readonly flags = new BehaviorSubject({}); + private readonly flags$ = this.flags.asObservable(); + private readonly initSubject = new BehaviorSubject(false); - constructor( - private storageService: StorageService, - @Optional() @Inject(WritableFeaturesServiceConfigToken) private config?: WritableFeaturesServiceConfig - ) { - this.flags.pipe(skip(1)).subscribe((flags) => { + constructor(@Optional() @Inject(WritableFeaturesServiceConfigToken) private config?: WritableFeaturesServiceConfig) { + combineLatest({ + flags: this.flags, + init: this.waitForInitializationToFinish() + }).subscribe(({ flags }) => { this.currentFlagState = flags; - this.storageService.setItem(this.storageKey, JSON.stringify(FlagSetParser.serialize(flags))); + sessionStorage.setItem(this.storageKey, JSON.stringify(FlagSetParser.serialize(flags))); }); } @@ -51,9 +51,10 @@ export class StorageFeaturesService implements IFeaturesService, IWritableFeatur } init(): Observable { - const storedFlags = JSON.parse(this.storageService.getItem(this.storageKey) || '{}'); + const storedFlags = JSON.parse(sessionStorage.getItem(this.storageKey) || '{}'); const initialFlagChangeSet = FlagSetParser.deserialize(storedFlags); this.flags.next(initialFlagChangeSet); + this.initSubject.next(true); return of(initialFlagChangeSet); } @@ -133,4 +134,8 @@ export class StorageFeaturesService implements IFeaturesService, IWritableFeatur this.flags.next(mergedFlags); } + + private waitForInitializationToFinish(): Observable { + return this.initSubject.pipe(filter((initialized) => !!initialized)); + } }