diff --git a/CHANGELOG.md b/CHANGELOG.md
index c339672921..785d76b229 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,29 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+### [0.7.3](https://github.com/webern-unibas-ch/awg-app/compare/v0.7.2...v0.7.3) (2020-04-09)
+
+### Bug Fixes
+
+- **app:** move editor info from home to edition view ([f0434cc](https://github.com/webern-unibas-ch/awg-app/commit/f0434cce4962f5ff7c06e8bfe1033e4b2c91c69a))
+- **app:** use rel attribute for target links instead of wrong ref attr ([04578ee](https://github.com/webern-unibas-ch/awg-app/commit/04578ee1bfa811613beb72bf0faa2084bbd88a2c))
+- **core:** add sagw logo to footer ([b41d013](https://github.com/webern-unibas-ch/awg-app/commit/b41d013deec3e30fca6ae03e1398676199b48a82))
+- **core:** remove MetaEdition from MetaModel ([010d02f](https://github.com/webern-unibas-ch/awg-app/commit/010d02f07173d93a152ec9fe0f48c81da4baa5fe))
+- **edition:** add dropdown for sample queries in graph view ([c995ada](https://github.com/webern-unibas-ch/awg-app/commit/c995ada1d10101b2e8fb3f0930b798f7b309d220))
+- **edition:** add modal hint on how to use graph ([626d024](https://github.com/webern-unibas-ch/awg-app/commit/626d0240f7e75ba9a6ad1d44ded459217ff8d579))
+- **edition:** add resp statement to work model ([d9eefae](https://github.com/webern-unibas-ch/awg-app/commit/d9eefae9f4f5ae15f55ce687d749cdf481b20941))
+- **edition:** do not remove all svg when redrawing force graph ([e6cfdac](https://github.com/webern-unibas-ch/awg-app/commit/e6cfdac716aadb11211834be0d6be8bb9266910d))
+- **edition:** improve general remarks for graph view ([b1b1c24](https://github.com/webern-unibas-ch/awg-app/commit/b1b1c2499080728b5f0ca144a512331094187a87))
+- **edition:** improve handling of triples dropdown button in force-graph ([c41925b](https://github.com/webern-unibas-ch/awg-app/commit/c41925b796815a1670fbc415bfb96541e89f30cc))
+- **edition:** improve query reset in graph view ([09e309c](https://github.com/webern-unibas-ch/awg-app/commit/09e309ca8dcfa0e6290e32cdbb1535a965d725dc))
+- **edition:** refactor EditionWork to provide all needed info ([0319790](https://github.com/webern-unibas-ch/awg-app/commit/03197908d689c59a0235a1a9616b362edf6eeeff))
+- **edition:** remove unused EditionDetailNotification ([4e1f151](https://github.com/webern-unibas-ch/awg-app/commit/4e1f15100fa6de68346c991d284825edf0318315))
+- **edition:** shorten short forms of some EditionConstants ([61a297d](https://github.com/webern-unibas-ch/awg-app/commit/61a297d8c5af924dc69ef096b67015143970982d))
+- **edition:** use full EditionRoute for EditionWork routes ([2c98f5d](https://github.com/webern-unibas-ch/awg-app/commit/2c98f5d39b28a4cf961cc9812dd8e160eeb054aa))
+- **edition:** use modal for edition detail hint & improve hint message ([0383470](https://github.com/webern-unibas-ch/awg-app/commit/0383470e67715b76898562329f3f90b1b34d1707))
+- **edition:** use queryList in graph data to allow multiple queries ([ca988f2](https://github.com/webern-unibas-ch/awg-app/commit/ca988f208a699045063679245effa200089afd69))
+- **home:** add sketch edition link to Opus 25 header ([aaeaa80](https://github.com/webern-unibas-ch/awg-app/commit/aaeaa801669f4d8a3a32823e0e8872d39f7f14ea))
+
### [0.7.2](https://github.com/webern-unibas-ch/awg-app/compare/v0.7.1...v0.7.2) (2020-03-20)
### Features
diff --git a/package.json b/package.json
index 5be3720275..3c8cba303d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "awg-app",
- "version": "0.7.2",
+ "version": "0.7.3",
"license": "MIT",
"author": {
"name": "Stefan Münnich",
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts
index 4bf75ab143..e7a180a95e 100644
--- a/src/app/app.component.spec.ts
+++ b/src/app/app.component.spec.ts
@@ -7,6 +7,7 @@ import { of as observableOf } from 'rxjs';
import Spy = jasmine.Spy;
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { RouterEventsService } from '@awg-core/services';
@@ -71,6 +72,10 @@ describe('AppComponent (DONE)', () => {
(window as any).ga = undefined;
});
+ afterAll(() => {
+ cleanStylesFromDOM();
+ });
+
it('should create the app', async(() => {
expect(component).toBeTruthy();
}));
diff --git a/src/app/app.globals.ts b/src/app/app.globals.ts
index 1d4b68318a..669035662b 100644
--- a/src/app/app.globals.ts
+++ b/src/app/app.globals.ts
@@ -1,15 +1,15 @@
// THIS IS AN AUTO-GENERATED FILE. DO NOT CHANGE IT MANUALLY!
-// Generated last time on Sat Mar 21 00:35:34 2020
+// Generated last time on Thu Apr 9 12:48:35 2020
/**
* The latest version of the AWG App
*/
-export const appVersion = '0.7.2';
+export const appVersion = '0.7.3';
/**
* The release date of the latest version of the AWG App
*/
-export const appVersionReleaseDate = '21. März 2020';
+export const appVersionReleaseDate = '09. April 2020';
/**
* The URL of the AWG App
diff --git a/src/app/core/core-models/geo-names.model.ts b/src/app/core/core-models/geo-names.model.ts
index a92d930dc0..7e30ed91f4 100644
--- a/src/app/core/core-models/geo-names.model.ts
+++ b/src/app/core/core-models/geo-names.model.ts
@@ -77,7 +77,7 @@ export class GeoNames {
this.gnid +
'" title="' +
this.longLabel +
- '" target="_blank" ref="noopener noreferrer">' +
+ '" target="_blank" rel="noopener noreferrer">' +
geoIcon +
'';
let wikiLink = '';
@@ -88,7 +88,7 @@ export class GeoNames {
this.wiki +
'" title="' +
this.wiki +
- '" target="_blank" ref="noopener noreferrer">' +
+ '" target="_blank" rel="noopener noreferrer">' +
wikiIcon +
'';
}
diff --git a/src/app/core/core-models/index.ts b/src/app/core/core-models/index.ts
index 8dcf01f50d..cb1323674d 100644
--- a/src/app/core/core-models/index.ts
+++ b/src/app/core/core-models/index.ts
@@ -9,6 +9,6 @@
import { GeoNames } from './geo-names.model';
import { Logo, Logos } from './logos.model';
-import { Meta, MetaContact, MetaEdition, MetaPage, MetaStructure, MetaSectionTypes } from './meta.model';
+import { Meta, MetaContact, MetaPage, MetaStructure, MetaSectionTypes } from './meta.model';
-export { GeoNames, Logo, Logos, Meta, MetaContact, MetaEdition, MetaPage, MetaStructure, MetaSectionTypes };
+export { GeoNames, Logo, Logos, Meta, MetaContact, MetaPage, MetaStructure, MetaSectionTypes };
diff --git a/src/app/core/core-models/meta.model.ts b/src/app/core/core-models/meta.model.ts
index 4ad7d807cb..205b313b37 100644
--- a/src/app/core/core-models/meta.model.ts
+++ b/src/app/core/core-models/meta.model.ts
@@ -5,7 +5,6 @@
*/
export enum MetaSectionTypes {
page = 'page',
- edition = 'edition',
structure = 'structure',
contact = 'contact'
}
@@ -17,14 +16,14 @@ export enum MetaSectionTypes {
*/
export class MetaPerson {
/**
- * The name of the person.
+ * The (FOAF) name of the person.
*/
name: string;
/**
- * The contact (webadress) of a person.
+ * The (FOAF) homepage of a person.
*/
- contactUrl: string;
+ homepage: string;
}
/**
@@ -80,24 +79,6 @@ export class MetaPage {
versionReleaseDate: string;
}
-/**
- * The MetaEdition class.
- *
- * It is used in the context of the edition view
- * to store the meta data about the edition.
- */
-export class MetaEdition {
- /**
- * The editors of an edition.
- */
- editors: MetaPerson[];
-
- /**
- * The last modification date of an edition.
- */
- lastModified: string;
-}
-
/**
* The MetaStructure class.
*
@@ -205,11 +186,6 @@ export class Meta {
*/
page: MetaPage;
- /**
- * The meta data for the edition view.
- */
- edition: MetaEdition;
-
/**
* The meta data for the structure view.
*/
diff --git a/src/app/core/footer/footer-copyright/footer-copyright.component.spec.ts b/src/app/core/footer/footer-copyright/footer-copyright.component.spec.ts
index e00cc7a1ac..2561b2db4d 100644
--- a/src/app/core/footer/footer-copyright/footer-copyright.component.spec.ts
+++ b/src/app/core/footer/footer-copyright/footer-copyright.component.spec.ts
@@ -1,9 +1,10 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { getAndExpectDebugElementByCss } from '@testing/expect-helper';
-import { Meta, MetaPage, MetaSectionTypes } from '@awg-core/core-models';
+import { MetaPage, MetaSectionTypes } from '@awg-core/core-models';
import { METADATA } from '@awg-core/mock-data';
import { FooterCopyrightComponent } from './footer-copyright.component';
@@ -32,6 +33,10 @@ describe('FooterCopyrightComponent (DONE)', () => {
expectedPageMetaData = METADATA[MetaSectionTypes.page];
});
+ afterAll(() => {
+ cleanStylesFromDOM();
+ });
+
it('should create', () => {
expect(component).toBeTruthy();
});
diff --git a/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts b/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts
index 32052ce05b..659257b910 100644
--- a/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts
+++ b/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts
@@ -1,6 +1,7 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { click } from '@testing/click-helper';
import { getAndExpectDebugElementByCss, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { RouterLinkStubDirective } from '@testing/router-stubs';
@@ -36,6 +37,10 @@ describe('FooterDeclarationComponent (DONE)', () => {
expectedPageMetaData = METADATA[MetaSectionTypes.page];
});
+ afterAll(() => {
+ cleanStylesFromDOM();
+ });
+
it('should create', () => {
expect(component).toBeTruthy();
});
diff --git a/src/app/core/footer/footer-logo/footer-logo.component.html b/src/app/core/footer/footer-logo/footer-logo.component.html
index b69002cdf0..6bf3d74f1c 100644
--- a/src/app/core/footer/footer-logo/footer-logo.component.html
+++ b/src/app/core/footer/footer-logo/footer-logo.component.html
@@ -1,3 +1,3 @@
-
-
+
+
diff --git a/src/app/core/footer/footer-logo/footer-logo.component.spec.ts b/src/app/core/footer/footer-logo/footer-logo.component.spec.ts
index d8f72aa98e..894b34f197 100644
--- a/src/app/core/footer/footer-logo/footer-logo.component.spec.ts
+++ b/src/app/core/footer/footer-logo/footer-logo.component.spec.ts
@@ -1,9 +1,14 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
-import { getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import Spy = jasmine.Spy;
+
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
+import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
+import { expectSpyCall, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { Logo } from '@awg-core/core-models';
+import { LOGOSDATA } from '@awg-core/mock-data';
import { FooterLogoComponent } from './footer-logo.component';
@@ -13,7 +18,14 @@ describe('FooterLogoComponent (DONE)', () => {
let compDe: DebugElement;
let compEl: any;
+ let getLogoClassSpy: Spy;
+
let expectedLogo: Logo;
+ let expectedNonRightMainFooterLogo: Logo;
+ let expectedNonMainFooterLogo: Logo;
+
+ const cssClassFloatRight = 'float-right';
+ const cssClassMarginY2 = 'my-2';
beforeEach(async(() => {
TestBed.configureTestingModule({
@@ -28,12 +40,18 @@ describe('FooterLogoComponent (DONE)', () => {
compEl = compDe.nativeElement;
// test data
- expectedLogo = {
- id: 'unibaslogo',
- src: 'assets/img/logos/uni.svg',
- alt: 'Logo Uni Basel',
- href: 'https://www.unibas.ch'
- };
+ expectedLogo = LOGOSDATA.unibas;
+ expectedNonRightMainFooterLogo = LOGOSDATA.sagw;
+ expectedNonMainFooterLogo = LOGOSDATA.angular;
+
+ // spies on component functions
+ // `.and.callThrough` will track the spy down the nested describes, see
+ // https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3Eand.callThrough%3C/code%3E
+ getLogoClassSpy = spyOn(component, 'getLogoClass').and.callThrough();
+ });
+
+ afterAll(() => {
+ cleanStylesFromDOM();
});
it('should create', () => {
@@ -42,11 +60,17 @@ describe('FooterLogoComponent (DONE)', () => {
describe('BEFORE initial data binding', () => {
it('should not have logo', () => {
- expect(component.logo).toBeUndefined('should be undefined');
+ expect(component.logo).toBeUndefined(`should be undefined`);
+ });
+
+ describe('#getLogoClass', () => {
+ it('... should not have been called yet', () => {
+ expectSpyCall(getLogoClassSpy, 0);
+ });
});
describe('VIEW', () => {
- it('... should contain one image inside an anchor', () => {
+ it('... should contain one image inside an anchor a', () => {
const imageDes = getAndExpectDebugElementByCss(compDe, 'a > img', 1, 1);
});
@@ -60,16 +84,16 @@ describe('FooterLogoComponent (DONE)', () => {
const imageEl = imageDes[0].nativeElement;
expect(anchorEl.href).toBeDefined();
- expect(anchorEl.href).toBe('', 'should be empty string');
+ expect(anchorEl.href).not.toBeTruthy('should be empty string');
expect(imageEl.id).toBeDefined();
- expect(imageEl.id).toBe('', 'should be empty string');
+ expect(imageEl.id).not.toBeTruthy('should be empty string');
expect(imageEl.src).toBeDefined();
- expect(imageEl.src).toBe('', 'should be empty string');
+ expect(imageEl.src).not.toBeTruthy('should be empty string');
expect(imageEl.alt).toBeDefined();
- expect(imageEl.alt).toBe('', 'should be empty string');
+ expect(imageEl.alt).not.toBeTruthy('should be empty string');
});
});
});
@@ -77,19 +101,123 @@ describe('FooterLogoComponent (DONE)', () => {
describe('AFTER initial data binding', () => {
beforeEach(() => {
// simulate the parent setting the input properties
- component.logo = expectedLogo;
+ component.logo = LOGOSDATA.unibas;
// trigger initial data binding
fixture.detectChanges();
});
it('should have logo', () => {
+ expect(component.logo).toBeDefined(`should be defined`);
+ expect(component.logo).toBe(expectedLogo, `should be ${expectedLogo}`);
+ });
+
+ it('should change logo if input changes', () => {
expect(component.logo).toBeDefined();
expect(component.logo).toBe(expectedLogo);
+
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.sagw;
+ fixture.detectChanges();
+
+ expect(component.logo).toBeDefined(`should be defined`);
+ expect(component.logo).toEqual(
+ expectedNonRightMainFooterLogo,
+ `should equal ${expectedNonRightMainFooterLogo}`
+ );
+
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.angular;
+ fixture.detectChanges();
+
+ expect(component.logo).toBeDefined(`should be defined`);
+ expect(component.logo).toEqual(expectedNonMainFooterLogo, `should equal ${expectedNonMainFooterLogo}`);
+ });
+
+ describe('#getLogoClass', () => {
+ it('... should have been called with logo id', () => {
+ expectSpyCall(getLogoClassSpy, 1, expectedLogo.id);
+ });
+
+ it('... should return class `my-2 float-right` for right main footer logos', () => {
+ expectSpyCall(getLogoClassSpy, 1, expectedLogo.id);
+
+ const classList = component.getLogoClass(component.logo.id);
+
+ expect(classList).toBeTruthy(`should not be empty`);
+ expect(classList).toContain(cssClassFloatRight, `should contain ${cssClassFloatRight}`);
+ expect(classList).toContain(cssClassMarginY2, `should contain ${cssClassMarginY2}`);
+ expect(classList).toBe(
+ cssClassMarginY2 + ' ' + cssClassFloatRight,
+ `should be ${cssClassMarginY2} ${cssClassFloatRight}`
+ );
+ });
+
+ it('... should return class `float-right` only for right main footer logos', () => {
+ expectSpyCall(getLogoClassSpy, 1, expectedLogo.id);
+
+ let classList = component.getLogoClass(component.logo.id);
+
+ expect(classList).toBeTruthy(`should not be empty`);
+ expect(classList).toContain(cssClassFloatRight, `should contain ${cssClassFloatRight}`);
+
+ // main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.sagw;
+ fixture.detectChanges();
+
+ classList = component.getLogoClass(component.logo.id);
+
+ expect(classList).toBeTruthy(`should not be empty`);
+ expect(classList).not.toContain(cssClassFloatRight, `should not contain ${cssClassFloatRight}`);
+
+ // not main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.angular;
+ fixture.detectChanges();
+
+ classList = component.getLogoClass(component.logo.id);
+
+ expect(classList).not.toBeTruthy(`should be empty`);
+ });
+
+ it('... should return class `my-2` only for main footer logos', () => {
+ let classList = component.getLogoClass(component.logo.id);
+
+ expect(classList).toBeTruthy(`should not be empty`);
+ expect(classList).toContain(cssClassMarginY2, `should contain ${cssClassMarginY2}`);
+
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.sagw;
+ fixture.detectChanges();
+
+ classList = component.getLogoClass(component.logo.id);
+
+ expect(classList).toBeTruthy(`should not be empty`);
+ expect(classList).toContain(cssClassMarginY2, `should contain ${cssClassMarginY2}`);
+
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.angular;
+ fixture.detectChanges();
+
+ classList = component.getLogoClass(component.logo.id);
+
+ expect(classList).not.toBeTruthy(`should be empty`);
+ });
});
describe('VIEW', () => {
- it('... should render logo', () => {
+ it('... should have correct logo link in anchor', () => {
+ // find debug elements
+ const anchorDes = getAndExpectDebugElementByCss(compDe, 'a', 1, 1);
+
+ // find native elements
+ const anchorEl = anchorDes[0].nativeElement;
+
+ expect(anchorEl.href).toContain(expectedLogo.href, `should contain ${expectedLogo.href}`);
+ });
+
+ it('... should have correct logo id in img', () => {
// find debug elements
const anchorDes = getAndExpectDebugElementByCss(compDe, 'a', 1, 1);
const imageDes = getAndExpectDebugElementByCss(compDe, 'img', 1, 1);
@@ -98,10 +226,136 @@ describe('FooterLogoComponent (DONE)', () => {
const anchorEl = anchorDes[0].nativeElement;
const imageEl = imageDes[0].nativeElement;
- expect(anchorEl.href).toContain(expectedLogo.href);
- expect(imageEl.id).toContain(expectedLogo.id);
- expect(imageEl.src).toContain(expectedLogo.src);
- expect(imageEl.alt).toContain(expectedLogo.alt);
+ expect(imageEl.id).toBe(expectedLogo.id, `should be ${expectedLogo.id}`);
+ });
+
+ it('... should have correct logo src and alt in img', () => {
+ // find debug elements
+ const anchorDes = getAndExpectDebugElementByCss(compDe, 'a', 1, 1);
+ const imageDes = getAndExpectDebugElementByCss(compDe, 'img', 1, 1);
+
+ // find native elements
+ const anchorEl = anchorDes[0].nativeElement;
+ const imageEl = imageDes[0].nativeElement;
+
+ expect(imageEl.src).toContain(expectedLogo.src, `should contain ${expectedLogo.src}`);
+ expect(imageEl.alt).toBe(expectedLogo.alt, `should be ${expectedLogo.alt}`);
+ });
+
+ it('... should have CSS class `my-2 float-right` applied only to right main footer logos', async () => {
+ // for CSS class karma tests cf. https://stackoverflow.com/a/49157894
+
+ // right main footer logo
+ // find debug elements
+ const imageDes = getAndExpectDebugElementByCss(compDe, 'img', 1, 1);
+
+ // find native elements
+ const imageEl = imageDes[0].nativeElement;
+ const imageClasses = imageDes[0].classes;
+
+ expect(imageEl.classList).toContain(cssClassFloatRight, `should contain ${cssClassFloatRight}`);
+ expect(imageClasses[cssClassFloatRight]).toBeTruthy(`should not be empty`);
+ expect(imageEl.classList).toContain(cssClassMarginY2, `should contain ${cssClassMarginY2}`);
+ expect(imageClasses[cssClassMarginY2]).toBeTruthy(`should not be empty`);
+ });
+
+ it('... should have CSS class `float-right` applied only to right main footer logos', async () => {
+ // for CSS class karma tests cf. https://stackoverflow.com/a/49157894
+
+ // right main footer logo
+ // find debug elements
+ const imageDes = getAndExpectDebugElementByCss(compDe, 'img', 1, 1);
+
+ // find native elements
+ const imageEl = imageDes[0].nativeElement;
+ const imageClasses = imageDes[0].classes;
+
+ expect(imageEl.classList).toContain(cssClassFloatRight, `should contain ${cssClassFloatRight}`);
+ expect(imageClasses[cssClassFloatRight]).toBeTruthy(`should not be empty`);
+
+ // main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.sagw;
+ await detectChangesOnPush(fixture); // fixture.detectChanges with onPush strategy
+
+ expect(imageEl.classList).not.toContain(cssClassFloatRight, `should contain ${cssClassFloatRight}`);
+ expect(imageClasses[cssClassFloatRight]).not.toBeTruthy(`should not be empty`);
+
+ // not main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.angular;
+ await detectChangesOnPush(fixture); // fixture.detectChanges with onPush
+
+ expect(imageEl.classList).not.toContain(cssClassFloatRight, `should contain ${cssClassFloatRight}`);
+ expect(imageClasses[cssClassFloatRight]).not.toBeTruthy(`should be empty`);
+ });
+
+ it('... should have CSS class `my-2` applied only to main footer logos', async () => {
+ // right main footer logo
+ // find debug elements
+ const imageDes = getAndExpectDebugElementByCss(compDe, 'img', 1, 1);
+
+ // find native elements
+ const imageEl = imageDes[0].nativeElement;
+ const imageClasses = imageDes[0].classes;
+
+ expect(imageEl.classList).toContain(cssClassMarginY2, `should contain ${cssClassMarginY2}`);
+ expect(imageClasses[cssClassMarginY2]).toBeTruthy(`should not be empty`);
+
+ // main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.sagw;
+ await detectChangesOnPush(fixture); // fixture.detectChanges with onPush strategy
+
+ expect(imageEl.classList).toContain(cssClassMarginY2, `should contain ${cssClassMarginY2}`);
+ expect(imageClasses[cssClassMarginY2]).toBeTruthy(`should not be empty`);
+
+ // not main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.angular;
+ await detectChangesOnPush(fixture); // fixture.detectChanges with onPush
+
+ expect(imageEl.classList).not.toContain(cssClassMarginY2, `should not contain ${cssClassMarginY2}`);
+ expect(imageClasses[cssClassMarginY2]).not.toBeTruthy(`should be empty`);
+ });
+
+ it('... should have [ngClass] resolve to correct classes', async () => {
+ // right main footer logo
+ // find debug elements
+ const imageDes = getAndExpectDebugElementByCss(compDe, 'img', 1, 1);
+ const imageAttributes = imageDes[0].attributes;
+
+ // find native elements
+ const imageEl = imageDes[0].nativeElement;
+ const imageElAttributes = imageEl.attributes;
+
+ expect(imageAttributes['ng-reflect-ng-class']).toBe(
+ cssClassMarginY2 + ' ' + cssClassFloatRight,
+ `should be ${cssClassMarginY2} ${cssClassFloatRight}`
+ );
+ expect(imageElAttributes['ng-reflect-ng-class'].value).toBe(
+ cssClassMarginY2 + ' ' + cssClassFloatRight,
+ `should be ${cssClassMarginY2} ${cssClassFloatRight}`
+ );
+
+ // main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.sagw;
+ await detectChangesOnPush(fixture); // fixture.detectChanges with onPush strategy
+
+ expect(imageAttributes['ng-reflect-ng-class']).toBe(cssClassMarginY2, `should be ${cssClassMarginY2}`);
+ expect(imageElAttributes['ng-reflect-ng-class'].value).toBe(
+ cssClassMarginY2,
+ `should be ${cssClassMarginY2}`
+ );
+
+ // not main footer logo
+ // trigger changes in data binding
+ component.logo = LOGOSDATA.angular;
+ await detectChangesOnPush(fixture); // fixture.detectChanges with onPush strategy
+
+ expect(imageAttributes['ng-reflect-ng-class']).not.toBeTruthy(`should be empty string`);
+ expect(imageElAttributes['ng-reflect-ng-class'].value).not.toBeTruthy(`should be empty string`);
});
});
});
diff --git a/src/app/core/footer/footer-logo/footer-logo.component.ts b/src/app/core/footer/footer-logo/footer-logo.component.ts
index 2cdc776fb4..23a2d245ec 100644
--- a/src/app/core/footer/footer-logo/footer-logo.component.ts
+++ b/src/app/core/footer/footer-logo/footer-logo.component.ts
@@ -1,6 +1,7 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { Logo } from '@awg-core/core-models';
+import { LOGOSDATA } from '@awg-core/mock-data';
/**
* The FooterLogo component.
@@ -21,4 +22,29 @@ export class FooterLogoComponent {
*/
@Input()
logo: Logo;
+
+ /**
+ * Public variable: getLogoClass.
+ *
+ * It checks a given logo id for the logo
+ * being part of the (right) main footer.
+ *
+ * @param {string} id The given logo id.
+ *
+ * @returns {boolean} The boolean value of the comparison.
+ */
+ getLogoClass(id: string) {
+ const isSnfLogo = id === LOGOSDATA.snf.id;
+ const isUnibasLogo = id === LOGOSDATA.unibas.id;
+ const isSagwLogo = id === LOGOSDATA.sagw.id;
+
+ let classList = '';
+ if (isUnibasLogo || isSnfLogo || isSagwLogo) {
+ classList = 'my-2';
+ }
+ if (isUnibasLogo || isSnfLogo) {
+ classList += ' float-right';
+ }
+ return classList;
+ }
}
diff --git a/src/app/core/footer/footer-poweredby/footer-poweredby.component.spec.ts b/src/app/core/footer/footer-poweredby/footer-poweredby.component.spec.ts
index cfde76dfdd..9bf6097fe1 100644
--- a/src/app/core/footer/footer-poweredby/footer-poweredby.component.spec.ts
+++ b/src/app/core/footer/footer-poweredby/footer-poweredby.component.spec.ts
@@ -1,10 +1,10 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, DebugElement, Input } from '@angular/core';
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { getAndExpectDebugElementByCss, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { Logo, Logos } from '@awg-core/core-models';
-
import { FooterPoweredbyComponent } from './footer-poweredby.component';
@Component({ selector: 'awg-footer-logo', template: '' })
@@ -68,6 +68,10 @@ describe('FooterPoweredbyComponent (DONE)', () => {
};
});
+ afterAll(() => {
+ cleanStylesFromDOM();
+ });
+
it('should create', () => {
expect(component).toBeTruthy();
});
diff --git a/src/app/core/footer/footer.component.html b/src/app/core/footer/footer.component.html
index 39efd46b5b..d8db3cb845 100644
--- a/src/app/core/footer/footer.component.html
+++ b/src/app/core/footer/footer.component.html
@@ -1,14 +1,15 @@