From b6d173c531c3b03bad8b7c235daaae4da7102ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20M=C3=BCller?= Date: Sun, 16 Apr 2023 20:40:36 +0200 Subject: [PATCH] feat(fonts): host fonts locally (#631) --- frontend/package-lock.json | 12 +++++ frontend/package.json | 2 + frontend/src/app/auth/auth.service.spec.ts | 62 ++++++++++++++++++++++ frontend/src/app/auth/auth.service.ts | 18 +++---- frontend/src/index.html | 16 +++--- frontend/src/styles.scss | 6 +++ 6 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 frontend/src/app/auth/auth.service.spec.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 53ff832e..75e7534a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -23,7 +23,9 @@ "@ngrx/store": "^15.4.0", "@ngrx/store-devtools": "^15.4.0", "chart.js": "^2.9.4", + "material-icons": "^1.13.4", "ng2-charts": "^2.4.3", + "roboto-fontface": "^0.10.0", "rxjs": "^6.6.7", "tslib": "^2.3.1", "zone.js": "~0.11.4" @@ -11225,6 +11227,11 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/material-icons": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/material-icons/-/material-icons-1.13.4.tgz", + "integrity": "sha512-sGljRSo7fG6iK6QXM+LG7ZdMFZnRKaqdVCBO3l7nmweOUKQBkc3y3h2jU0HX+49kGET7/xIo8Ujq+4BG+7u7bw==" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -13422,6 +13429,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/roboto-fontface": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz", + "integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g==" + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index ddf618e1..dc146eca 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -29,7 +29,9 @@ "@ngrx/store": "^15.4.0", "@ngrx/store-devtools": "^15.4.0", "chart.js": "^2.9.4", + "material-icons": "^1.13.4", "ng2-charts": "^2.4.3", + "roboto-fontface": "^0.10.0", "rxjs": "^6.6.7", "tslib": "^2.3.1", "zone.js": "~0.11.4" diff --git a/frontend/src/app/auth/auth.service.spec.ts b/frontend/src/app/auth/auth.service.spec.ts new file mode 100644 index 00000000..436eb013 --- /dev/null +++ b/frontend/src/app/auth/auth.service.spec.ts @@ -0,0 +1,62 @@ +import { fakeAsync, TestBed, tick } from '@angular/core/testing' +import { AuthService } from './auth.service' +import { MockStore, provideMockStore } from '@ngrx/store/testing' +import * as AuthActions from './store/auth.actions' + +describe('AuthService', () => { + let systemUnderTest: AuthService + let store: MockStore + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [AuthService, provideMockStore({ initialState: {} })], + }) + + systemUnderTest = TestBed.inject(AuthService) + store = TestBed.inject(MockStore) + }) + + it('should be created', () => { + expect(systemUnderTest).toBeTruthy() + }) + + describe('setLogoutTimer', () => { + it('should dispatch Logout action after the expiration duration', fakeAsync(() => { + const expirationDuration = 5000 + spyOn(store, 'dispatch').and.callThrough() + + systemUnderTest.setLogoutTimer(expirationDuration) + + expect(systemUnderTest['tokenExpirationTimer']).toBeDefined() + expect(store.dispatch).not.toHaveBeenCalledWith(new AuthActions.Logout()) + + tick(5000) + + expect(store.dispatch).toHaveBeenCalledWith(new AuthActions.Logout()) + })) + }) + + describe('clearLogoutTimer', () => { + it('should clear the timer', fakeAsync(() => { + const expirationDuration = 5000 + spyOn(window, 'clearTimeout').and.callThrough() + + systemUnderTest.setLogoutTimer(expirationDuration) + + systemUnderTest.clearLogoutTimer() + + expect(window.clearTimeout).toHaveBeenCalled() + expect(systemUnderTest['tokenExpirationTimer']).toBeNull() + })) + + it('should not clear the timer if it has already expired', fakeAsync(() => { + const expirationDuration = 0 + spyOn(window, 'clearTimeout').and.callThrough() + + systemUnderTest.clearLogoutTimer() + + expect(window.clearTimeout).not.toHaveBeenCalled() + expect(systemUnderTest['tokenExpirationTimer']).toBeUndefined() + })) + }) +}) diff --git a/frontend/src/app/auth/auth.service.ts b/frontend/src/app/auth/auth.service.ts index b5bcd1e0..d405d5e4 100644 --- a/frontend/src/app/auth/auth.service.ts +++ b/frontend/src/app/auth/auth.service.ts @@ -1,25 +1,25 @@ -import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; +import { Injectable } from '@angular/core' +import { Store } from '@ngrx/store' -import * as fromApp from '../store/app.reducer'; -import * as AuthActions from './store/auth.actions'; +import * as fromApp from '../store/app.reducer' +import * as AuthActions from './store/auth.actions' @Injectable({ providedIn: 'root' }) export class AuthService { - private tokenExpirationTimer: number; + private tokenExpirationTimer constructor(private store: Store) {} setLogoutTimer(expirationDuration: number): void { this.tokenExpirationTimer = setTimeout(() => { - this.store.dispatch(new AuthActions.Logout()); - }, expirationDuration); + this.store.dispatch(new AuthActions.Logout()) + }, expirationDuration) } clearLogoutTimer(): void { if (this.tokenExpirationTimer) { - clearTimeout(this.tokenExpirationTimer); - this.tokenExpirationTimer = null; + clearTimeout(this.tokenExpirationTimer) + this.tokenExpirationTimer = null } } } diff --git a/frontend/src/index.html b/frontend/src/index.html index befdadee..987860ad 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -1,15 +1,13 @@ - + - + CashboxFrontend - - - - - - - + + + + + diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index 7f2f78dc..45a71824 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -1,5 +1,11 @@ /* You can add global styles to this file, and also import other style files */ +$roboto-font-path: "~roboto-fontface/fonts" !default; +@import "roboto-fontface/css/roboto/sass/roboto-fontface"; + +$material-icons-font-path: '~material-icons/iconfont/'; +@import 'material-icons/iconfont/material-icons.scss'; + html, body { height: 100%; }