mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
additional theme support tests
This commit is contained in:

committed by
Art Lowel

parent
5a6e4b1278
commit
91ca5af1d4
@@ -1,7 +1,7 @@
|
|||||||
import { Store, StoreModule } from '@ngrx/store';
|
import { Store, StoreModule } from '@ngrx/store';
|
||||||
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule, DOCUMENT } from '@angular/common';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||||
@@ -32,7 +32,9 @@ import { storeModuleConfig } from './app.reducer';
|
|||||||
import { LocaleService } from './core/locale/locale.service';
|
import { LocaleService } from './core/locale/locale.service';
|
||||||
import { authReducer } from './core/auth/auth.reducer';
|
import { authReducer } from './core/auth/auth.reducer';
|
||||||
import { provideMockStore } from '@ngrx/store/testing';
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import {GoogleAnalyticsService} from './statistics/google-analytics.service';
|
import { GoogleAnalyticsService } from './statistics/google-analytics.service';
|
||||||
|
import { ThemeService } from './shared/theme-support/theme.service';
|
||||||
|
import { getMockThemeService } from './shared/mocks/theme-service.mock';
|
||||||
|
|
||||||
let comp: AppComponent;
|
let comp: AppComponent;
|
||||||
let fixture: ComponentFixture<AppComponent>;
|
let fixture: ComponentFixture<AppComponent>;
|
||||||
@@ -73,6 +75,7 @@ describe('App component', () => {
|
|||||||
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
|
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
||||||
{ provide: LocaleService, useValue: getMockLocaleService() },
|
{ provide: LocaleService, useValue: getMockLocaleService() },
|
||||||
|
{ provide: ThemeService, useValue: getMockThemeService() },
|
||||||
provideMockStore({ initialState }),
|
provideMockStore({ initialState }),
|
||||||
AppComponent,
|
AppComponent,
|
||||||
RouteService
|
RouteService
|
||||||
@@ -143,4 +146,32 @@ describe('App component', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when ThemeService returns a custom theme', () => {
|
||||||
|
let document;
|
||||||
|
let headSpy;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// NOTE: Cannot override providers once components have been compiled, so TestBed needs to be reset
|
||||||
|
TestBed.resetTestingModule();
|
||||||
|
TestBed.configureTestingModule(defaultTestBedConf);
|
||||||
|
TestBed.overrideProvider(ThemeService, {useValue: getMockThemeService('custom')});
|
||||||
|
document = TestBed.inject(DOCUMENT);
|
||||||
|
headSpy = jasmine.createSpyObj('head', ['appendChild']);
|
||||||
|
spyOn(document, 'getElementsByTagName').and.returnValue([headSpy]);
|
||||||
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append a link element with the correct attributes to the head element', () => {
|
||||||
|
const link = document.createElement('link');
|
||||||
|
link.setAttribute('rel', 'stylesheet');
|
||||||
|
link.setAttribute('type', 'text/css');
|
||||||
|
link.setAttribute('class', 'theme-css');
|
||||||
|
link.setAttribute('href', '/custom-theme.css');
|
||||||
|
|
||||||
|
expect(headSpy.appendChild).toHaveBeenCalledWith(link);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
import { ThemeService } from '../theme-support/theme.service';
|
import { ThemeService } from '../theme-support/theme.service';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
|
||||||
export function getMockThemeService(): ThemeService {
|
export function getMockThemeService(themeName = 'base'): ThemeService {
|
||||||
return jasmine.createSpyObj('themeService', {
|
return jasmine.createSpyObj('themeService', {
|
||||||
getThemeName: 'base'
|
getThemeName: themeName,
|
||||||
|
getThemeName$: observableOf(themeName)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
// noinspection AngularMissingOrInvalidDeclarationInModule
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-test-component',
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
export class TestComponent {
|
||||||
|
type = 'themed';
|
||||||
|
testInput = 'unset';
|
||||||
|
}
|
11
src/app/shared/theme-support/test/test.component.spec.ts
Normal file
11
src/app/shared/theme-support/test/test.component.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
// noinspection AngularMissingOrInvalidDeclarationInModule
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-test-component',
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
export class TestComponent {
|
||||||
|
type = 'default';
|
||||||
|
testInput = 'unset';
|
||||||
|
}
|
@@ -1,9 +1,8 @@
|
|||||||
import { ThemeEffects } from './theme.effects';
|
import { ThemeEffects } from './theme.effects';
|
||||||
import { Observable } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { provideMockActions } from '@ngrx/effects/testing';
|
import { provideMockActions } from '@ngrx/effects/testing';
|
||||||
import { LinkService } from '../../core/cache/builders/link.service';
|
import { LinkService } from '../../core/cache/builders/link.service';
|
||||||
import { getMockLinkService } from '../mocks/link-service.mock';
|
|
||||||
import { cold, hot } from 'jasmine-marbles';
|
import { cold, hot } from 'jasmine-marbles';
|
||||||
import { ROOT_EFFECTS_INIT } from '@ngrx/effects';
|
import { ROOT_EFFECTS_INIT } from '@ngrx/effects';
|
||||||
import { SetThemeAction } from './theme.actions';
|
import { SetThemeAction } from './theme.actions';
|
||||||
@@ -19,43 +18,91 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
|||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
import { Collection } from '../../core/shared/collection.model';
|
import { Collection } from '../../core/shared/collection.model';
|
||||||
import { COLLECTION } from '../../core/shared/collection.resource-type';
|
import { COLLECTION } from '../../core/shared/collection.resource-type';
|
||||||
|
import {
|
||||||
|
createNoContentRemoteDataObject$,
|
||||||
|
createSuccessfulRemoteDataObject$
|
||||||
|
} from '../remote-data.utils';
|
||||||
import { BASE_THEME_NAME } from './theme.constants';
|
import { BASE_THEME_NAME } from './theme.constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LinkService able to mock recursively resolving DSO parent links
|
||||||
|
* Every time resolveLinkWithoutAttaching is called, it returns the next object in the array of ancestorDSOs until
|
||||||
|
* none are left, after which it returns a no-content remote-date
|
||||||
|
*/
|
||||||
|
class MockLinkService {
|
||||||
|
index = -1;
|
||||||
|
|
||||||
|
constructor(private ancestorDSOs: DSpaceObject[]) {
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveLinkWithoutAttaching() {
|
||||||
|
if (this.index >= this.ancestorDSOs.length - 1) {
|
||||||
|
return createNoContentRemoteDataObject$();
|
||||||
|
} else {
|
||||||
|
this.index++;
|
||||||
|
return createSuccessfulRemoteDataObject$(this.ancestorDSOs[this.index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('ThemeEffects', () => {
|
describe('ThemeEffects', () => {
|
||||||
let themeEffects: ThemeEffects;
|
let themeEffects: ThemeEffects;
|
||||||
let linkService: LinkService;
|
let linkService: LinkService;
|
||||||
let initialState;
|
let initialState;
|
||||||
let actions: Observable<any>;
|
|
||||||
|
let ancestorDSOs: DSpaceObject[];
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
linkService = getMockLinkService();
|
ancestorDSOs = [
|
||||||
|
Object.assign(new Collection(), {
|
||||||
|
type: COLLECTION.value,
|
||||||
|
uuid: 'collection-uuid',
|
||||||
|
_links: { owningCommunity: { href: 'owning-community-link' } }
|
||||||
|
}),
|
||||||
|
Object.assign(new Community(), {
|
||||||
|
type: COMMUNITY.value,
|
||||||
|
uuid: 'sub-community-uuid',
|
||||||
|
_links: { parentCommunity: { href: 'parent-community-link' } }
|
||||||
|
}),
|
||||||
|
Object.assign(new Community(), {
|
||||||
|
type: COMMUNITY.value,
|
||||||
|
uuid: 'top-community-uuid',
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
linkService = new MockLinkService(ancestorDSOs) as any;
|
||||||
initialState = {
|
initialState = {
|
||||||
currentTheme: 'custom',
|
theme: {
|
||||||
|
currentTheme: 'custom',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
function setupEffectsWithActions(mockActions) {
|
||||||
init();
|
init();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
ThemeEffects,
|
ThemeEffects,
|
||||||
{ provide: LinkService, useValue: linkService },
|
{ provide: LinkService, useValue: linkService },
|
||||||
provideMockStore({ initialState }),
|
provideMockStore({ initialState }),
|
||||||
provideMockActions(() => actions)
|
provideMockActions(() => mockActions)
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
themeEffects = TestBed.inject(ThemeEffects);
|
themeEffects = TestBed.inject(ThemeEffects);
|
||||||
});
|
}
|
||||||
|
|
||||||
describe('initTheme$', () => {
|
describe('initTheme$', () => {
|
||||||
it('should set the default theme', () => {
|
beforeEach(() => {
|
||||||
actions = hot('--a-', {
|
setupEffectsWithActions(
|
||||||
a: {
|
hot('--a-', {
|
||||||
type: ROOT_EFFECTS_INIT
|
a: {
|
||||||
}
|
type: ROOT_EFFECTS_INIT
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the default theme', () => {
|
||||||
const expected = cold('--b-', {
|
const expected = cold('--b-', {
|
||||||
b: new SetThemeAction(BASE_THEME_NAME)
|
b: new SetThemeAction(BASE_THEME_NAME)
|
||||||
});
|
});
|
||||||
@@ -64,109 +111,203 @@ describe('ThemeEffects', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Fix test
|
describe('updateThemeOnRouteChange$', () => {
|
||||||
xdescribe('updateThemeOnRouteChange$', () => {
|
const url = '/test/route';
|
||||||
it('test', () => {
|
const dso = Object.assign(new Community(), {
|
||||||
const url = '/test/route';
|
type: COMMUNITY.value,
|
||||||
const dso = Object.assign(new Community(), {
|
uuid: '0958c910-2037-42a9-81c7-dca80e3892b4',
|
||||||
type: COMMUNITY.value,
|
});
|
||||||
uuid: '0958c910-2037-42a9-81c7-dca80e3892b4',
|
|
||||||
});
|
function spyOnPrivateMethods() {
|
||||||
actions = hot('--ab-', {
|
spyOn((themeEffects as any), 'getAncestorDSOs').and.returnValue(() => observableOf([dso]));
|
||||||
a: {
|
spyOn((themeEffects as any), 'matchThemeToDSOs').and.returnValue(new Theme({ name: 'custom' }));
|
||||||
type: ROUTER_NAVIGATED,
|
spyOn((themeEffects as any), 'getActionForMatch').and.returnValue(new SetThemeAction('custom'));
|
||||||
payload: { routerState: { url } },
|
}
|
||||||
},
|
|
||||||
b: {
|
describe('when a resolved action is present', () => {
|
||||||
type: ResolverActionTypes.RESOLVED,
|
beforeEach(() => {
|
||||||
payload: { url, dso },
|
setupEffectsWithActions(
|
||||||
}
|
hot('--ab-', {
|
||||||
|
a: {
|
||||||
|
type: ROUTER_NAVIGATED,
|
||||||
|
payload: { routerState: { url } },
|
||||||
|
},
|
||||||
|
b: {
|
||||||
|
type: ResolverActionTypes.RESOLVED,
|
||||||
|
payload: { url, dso },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
spyOnPrivateMethods();
|
||||||
});
|
});
|
||||||
|
|
||||||
const expected = cold('--b-', {
|
it('should set the theme it receives from the DSO', () => {
|
||||||
b: new SetThemeAction('Publications community (uuid)')
|
const expected = cold('--b-', {
|
||||||
|
b: new SetThemeAction('custom')
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(themeEffects.updateThemeOnRouteChange$).toBeObservable(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when no resolved action is present', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setupEffectsWithActions(
|
||||||
|
hot('--a-', {
|
||||||
|
a: {
|
||||||
|
type: ROUTER_NAVIGATED,
|
||||||
|
payload: { routerState: { url } },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
spyOnPrivateMethods();
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(themeEffects.initTheme$).toBeObservable(expected);
|
it('should set the theme it receives from the route url', () => {
|
||||||
|
const expected = cold('--b-', {
|
||||||
|
b: new SetThemeAction('custom')
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(themeEffects.updateThemeOnRouteChange$).toBeObservable(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when no themes are present', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setupEffectsWithActions(
|
||||||
|
hot('--a-', {
|
||||||
|
a: {
|
||||||
|
type: ROUTER_NAVIGATED,
|
||||||
|
payload: { routerState: { url } },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
(themeEffects as any).themes = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty action', () => {
|
||||||
|
const expected = cold('--b-', {
|
||||||
|
b: new NoOpAction()
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(themeEffects.updateThemeOnRouteChange$).toBeObservable(expected);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getActionForMatch', () => {
|
describe('private functions', () => {
|
||||||
it('should return a SET action if the name doesn\'t match', () => {
|
|
||||||
const theme = new Theme({ name: 'new-theme' });
|
|
||||||
expect((themeEffects as any).getActionForMatch(theme, 'not-matching')).toEqual(new SetThemeAction('new-theme'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty action if the name matches', () => {
|
|
||||||
const theme = new Theme({ name: 'new-theme' });
|
|
||||||
expect((themeEffects as any).getActionForMatch(theme, 'new-theme')).toEqual(new NoOpAction());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('matchThemeToDSOs', () => {
|
|
||||||
let themes: Theme[];
|
|
||||||
let nonMatchingTheme: Theme;
|
|
||||||
let itemMatchingTheme: Theme;
|
|
||||||
let communityMatchingTheme: Theme;
|
|
||||||
let dsos: DSpaceObject[];
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
nonMatchingTheme = Object.assign(new Theme({ name: 'non-matching-theme' }), {
|
setupEffectsWithActions(hot('-', {}));
|
||||||
matches: () => false
|
});
|
||||||
|
|
||||||
|
describe('getActionForMatch', () => {
|
||||||
|
it('should return a SET action if the new theme differs from the current theme', () => {
|
||||||
|
const theme = new Theme({ name: 'new-theme' });
|
||||||
|
expect((themeEffects as any).getActionForMatch(theme, 'old-theme')).toEqual(new SetThemeAction('new-theme'));
|
||||||
});
|
});
|
||||||
itemMatchingTheme = Object.assign(new Theme({ name: 'item-matching-theme' }), {
|
|
||||||
matches: (url, dso) => (dso as any).type === ITEM.value
|
it('should return an empty action if the new theme equals the current theme', () => {
|
||||||
|
const theme = new Theme({ name: 'old-theme' });
|
||||||
|
expect((themeEffects as any).getActionForMatch(theme, 'old-theme')).toEqual(new NoOpAction());
|
||||||
});
|
});
|
||||||
communityMatchingTheme = Object.assign(new Theme({ name: 'community-matching-theme' }), {
|
});
|
||||||
matches: (url, dso) => (dso as any).type === COMMUNITY.value
|
|
||||||
|
describe('matchThemeToDSOs', () => {
|
||||||
|
let themes: Theme[];
|
||||||
|
let nonMatchingTheme: Theme;
|
||||||
|
let itemMatchingTheme: Theme;
|
||||||
|
let communityMatchingTheme: Theme;
|
||||||
|
let dsos: DSpaceObject[];
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nonMatchingTheme = Object.assign(new Theme({ name: 'non-matching-theme' }), {
|
||||||
|
matches: () => false
|
||||||
|
});
|
||||||
|
itemMatchingTheme = Object.assign(new Theme({ name: 'item-matching-theme' }), {
|
||||||
|
matches: (url, dso) => (dso as any).type === ITEM.value
|
||||||
|
});
|
||||||
|
communityMatchingTheme = Object.assign(new Theme({ name: 'community-matching-theme' }), {
|
||||||
|
matches: (url, dso) => (dso as any).type === COMMUNITY.value
|
||||||
|
});
|
||||||
|
dsos = [
|
||||||
|
Object.assign(new Item(), {
|
||||||
|
type: ITEM.value,
|
||||||
|
uuid: 'item-uuid',
|
||||||
|
}),
|
||||||
|
Object.assign(new Collection(), {
|
||||||
|
type: COLLECTION.value,
|
||||||
|
uuid: 'collection-uuid',
|
||||||
|
}),
|
||||||
|
Object.assign(new Community(), {
|
||||||
|
type: COMMUNITY.value,
|
||||||
|
uuid: 'community-uuid',
|
||||||
|
}),
|
||||||
|
];
|
||||||
});
|
});
|
||||||
dsos = [
|
|
||||||
Object.assign(new Item(), {
|
describe('when no themes match any of the DSOs', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
themes = [ nonMatchingTheme ];
|
||||||
|
themeEffects.themes = themes;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return undefined', () => {
|
||||||
|
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when one of the themes match a DSOs', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
themes = [ nonMatchingTheme, itemMatchingTheme ];
|
||||||
|
themeEffects.themes = themes;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the matching theme', () => {
|
||||||
|
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toEqual(itemMatchingTheme);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when multiple themes match some of the DSOs', () => {
|
||||||
|
it('should return the first matching theme', () => {
|
||||||
|
themes = [ nonMatchingTheme, itemMatchingTheme, communityMatchingTheme ];
|
||||||
|
themeEffects.themes = themes;
|
||||||
|
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toEqual(itemMatchingTheme);
|
||||||
|
|
||||||
|
themes = [ nonMatchingTheme, communityMatchingTheme, itemMatchingTheme ];
|
||||||
|
themeEffects.themes = themes;
|
||||||
|
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toEqual(communityMatchingTheme);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getAncestorDSOs', () => {
|
||||||
|
it('should return an array of the provided DSO and its ancestors', (done) => {
|
||||||
|
const dso = Object.assign(new Item(), {
|
||||||
type: ITEM.value,
|
type: ITEM.value,
|
||||||
uuid: 'item-uuid',
|
uuid: 'item-uuid',
|
||||||
}),
|
_links: { owningCollection: { href: 'owning-collection-link' } },
|
||||||
Object.assign(new Collection(), {
|
});
|
||||||
type: COLLECTION.value,
|
|
||||||
uuid: 'collection-uuid',
|
|
||||||
}),
|
|
||||||
Object.assign(new Community(), {
|
|
||||||
type: COMMUNITY.value,
|
|
||||||
uuid: 'community-uuid',
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when no themes match any of the DSOs', () => {
|
observableOf(dso).pipe(
|
||||||
beforeEach(() => {
|
(themeEffects as any).getAncestorDSOs()
|
||||||
themes = [ nonMatchingTheme ];
|
).subscribe((result) => {
|
||||||
themeEffects.themes = themes;
|
expect(result).toEqual([dso, ...ancestorDSOs]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return undefined', () => {
|
it('should return an array of just the provided DSO if it doesn\'t have any parents', (done) => {
|
||||||
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toBeUndefined();
|
const dso = {
|
||||||
});
|
type: ITEM.value,
|
||||||
});
|
uuid: 'item-uuid',
|
||||||
|
};
|
||||||
|
|
||||||
describe('when one of the themes match a DSOs', () => {
|
observableOf(dso).pipe(
|
||||||
beforeEach(() => {
|
(themeEffects as any).getAncestorDSOs()
|
||||||
themes = [ nonMatchingTheme, itemMatchingTheme ];
|
).subscribe((result) => {
|
||||||
themeEffects.themes = themes;
|
expect(result).toEqual([dso]);
|
||||||
});
|
done();
|
||||||
|
});
|
||||||
it('should return the matching theme', () => {
|
|
||||||
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toEqual(itemMatchingTheme);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when multiple themes match some of the DSOs', () => {
|
|
||||||
it('should return the first matching theme', () => {
|
|
||||||
themes = [ nonMatchingTheme, itemMatchingTheme, communityMatchingTheme ];
|
|
||||||
themeEffects.themes = themes;
|
|
||||||
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toEqual(itemMatchingTheme);
|
|
||||||
|
|
||||||
themes = [ nonMatchingTheme, communityMatchingTheme, itemMatchingTheme ];
|
|
||||||
themeEffects.themes = themes;
|
|
||||||
expect((themeEffects as any).matchThemeToDSOs(dsos, '')).toEqual(communityMatchingTheme);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
97
src/app/shared/theme-support/themed.component.spec.ts
Normal file
97
src/app/shared/theme-support/themed.component.spec.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { ThemedComponent } from './themed.component';
|
||||||
|
import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
import { VarDirective } from '../utils/var.directive';
|
||||||
|
import { ThemeService } from './theme.service';
|
||||||
|
import { getMockThemeService } from '../mocks/theme-service.mock';
|
||||||
|
import { TestComponent } from './test/test.component.spec';
|
||||||
|
|
||||||
|
/* tslint:disable:max-classes-per-file */
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-test-themed-component',
|
||||||
|
templateUrl: './themed.component.html'
|
||||||
|
})
|
||||||
|
class TestThemedComponent extends ThemedComponent<TestComponent> {
|
||||||
|
protected inAndOutputNames: (keyof TestComponent & keyof this)[] = ['testInput'];
|
||||||
|
|
||||||
|
testInput = 'unset';
|
||||||
|
|
||||||
|
protected getComponentName(): string {
|
||||||
|
return 'TestComponent';
|
||||||
|
}
|
||||||
|
protected importThemedComponent(themeName: string): Promise<any> {
|
||||||
|
return import(`./test/${themeName}/themed-test.component.spec`);
|
||||||
|
}
|
||||||
|
protected importUnthemedComponent(): Promise<any> {
|
||||||
|
return import('./test/test.component.spec');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ThemedComponent', () => {
|
||||||
|
let component: TestThemedComponent;
|
||||||
|
let fixture: ComponentFixture<TestThemedComponent>;
|
||||||
|
let themeService: ThemeService;
|
||||||
|
|
||||||
|
function setupTestingModuleForTheme(theme: string) {
|
||||||
|
themeService = getMockThemeService(theme);
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [],
|
||||||
|
declarations: [TestThemedComponent, VarDirective],
|
||||||
|
providers: [
|
||||||
|
{ provide: ThemeService, useValue: themeService },
|
||||||
|
],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('when the current theme matches a themed component', () => {
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
setupTestingModuleForTheme('custom');
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TestThemedComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
component.testInput = 'changed';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set compRef to the themed component', waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect((component as any).compRef.instance.type).toEqual('themed');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should sync up this component\'s input with the themed component', waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the current theme doesn\'t match a themed component', () => {
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
setupTestingModuleForTheme('non-existing-theme');
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TestThemedComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
component.testInput = 'changed';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set compRef to the default component', waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect((component as any).compRef.instance.type).toEqual('default');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should sync up this component\'s input with the default component', waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
/* tslint:enable:max-classes-per-file */
|
@@ -194,34 +194,27 @@ export const environment: Partial<GlobalConfig> = {
|
|||||||
},
|
},
|
||||||
themes: [
|
themes: [
|
||||||
{
|
{
|
||||||
// name: 'default',
|
|
||||||
name: 'full-item-page-theme',
|
name: 'full-item-page-theme',
|
||||||
regex: 'items/aa6c6c83-3a83-4953-95d1-2bc2e67854d2/full'
|
regex: 'items/aa6c6c83-3a83-4953-95d1-2bc2e67854d2/full'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// name: 'default',
|
|
||||||
name: 'error-theme',
|
name: 'error-theme',
|
||||||
regex: 'collections/aaaa.*'
|
regex: 'collections/aaaa.*'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// name: 'default',
|
|
||||||
name: 'Item (handle)',
|
name: 'Item (handle)',
|
||||||
handle: '10673/1233' // Item inside publications community
|
handle: '10673/1233'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// name: 'mantis',
|
|
||||||
name: 'blue',
|
name: 'blue',
|
||||||
regex: 'collections\/e8043bc2.*' // Publications/Thesis collections
|
regex: 'collections\/e8043bc2.*'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// name: 'mantis',
|
|
||||||
name: 'Publications community (uuid)',
|
name: 'Publications community (uuid)',
|
||||||
uuid: '0958c910-2037-42a9-81c7-dca80e3892b4' // Publications community
|
uuid: '0958c910-2037-42a9-81c7-dca80e3892b4'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// name: 'default',
|
|
||||||
name: 'base',
|
name: 'base',
|
||||||
// name: 'blue',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user