Merge pull request #4873 from GabrielInTheWorld/uiFixes
Fixes some UI issues
This commit is contained in:
commit
13e8bbb168
@ -1,4 +1,4 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { PwaService } from './pwa.service';
|
import { PwaService } from './pwa.service';
|
||||||
import { E2EImportsModule } from 'e2e-imports.module';
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
@ -6,12 +6,12 @@ import { E2EImportsModule } from 'e2e-imports.module';
|
|||||||
describe('PwaService', () => {
|
describe('PwaService', () => {
|
||||||
beforeEach(() =>
|
beforeEach(() =>
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [E2EImportsModule]
|
imports: [E2EImportsModule],
|
||||||
|
providers: [PwaService]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', inject([PwaService], (service: PwaService) => {
|
||||||
const service: PwaService = TestBed.get(PwaService);
|
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { TestBed, inject } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('StorageService', () => {
|
describe('StorageService', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule],
|
||||||
providers: [StorageService]
|
providers: [StorageService]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { DurationService } from './duration.service';
|
import { DurationService } from './duration.service';
|
||||||
import { E2EImportsModule } from 'e2e-imports.module';
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
@ -6,12 +6,12 @@ import { E2EImportsModule } from 'e2e-imports.module';
|
|||||||
describe('DurationService', () => {
|
describe('DurationService', () => {
|
||||||
beforeEach(() =>
|
beforeEach(() =>
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [E2EImportsModule]
|
imports: [E2EImportsModule],
|
||||||
|
providers: [DurationService]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', inject([DurationService], (service: DurationService) => {
|
||||||
const service: DurationService = TestBed.get(DurationService);
|
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { HtmlToPdfService } from './html-to-pdf.service';
|
import { HtmlToPdfService } from './html-to-pdf.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('HtmlToPdfService', () => {
|
describe('HtmlToPdfService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
it('should be created', () => {
|
imports: [E2EImportsModule],
|
||||||
const service: HtmlToPdfService = TestBed.get(HtmlToPdfService);
|
providers: [HtmlToPdfService]
|
||||||
expect(service).toBeTruthy();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([HtmlToPdfService], (service: HtmlToPdfService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { LoadFontService } from './load-font.service';
|
import { LoadFontService } from './load-font.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('LoadFontService', () => {
|
describe('LoadFontService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
it('should be created', () => {
|
imports: [E2EImportsModule],
|
||||||
const service: LoadFontService = TestBed.get(LoadFontService);
|
providers: [LoadFontService]
|
||||||
expect(service).toBeTruthy();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([LoadFontService], (service: LoadFontService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { TestBed, inject } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { LoginDataService } from './login-data.service';
|
import { LoginDataService } from './login-data.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('LoginDataService', () => {
|
describe('LoginDataService', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule],
|
||||||
providers: [LoginDataService]
|
providers: [LoginDataService]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,22 +1,35 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
import { ConfigService } from './config.service';
|
import { ConfigService } from './config.service';
|
||||||
import { StorageService } from '../core-services/storage.service';
|
import { StorageService } from '../core-services/storage.service';
|
||||||
import { OpenSlidesStatusService } from '../core-services/openslides-status.service';
|
import { OpenSlidesStatusService } from '../core-services/openslides-status.service';
|
||||||
|
import { HttpService } from '../core-services/http.service';
|
||||||
|
import { environment } from 'environments/environment.prod';
|
||||||
|
import { auditTime } from 'rxjs/operators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The login data send by the server.
|
* The login data send by the server.
|
||||||
*/
|
*/
|
||||||
export interface LoginData {
|
export interface LoginData {
|
||||||
privacy_policy: string;
|
privacy_policy?: string;
|
||||||
legal_notice: string;
|
legal_notice?: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
logo_web_header: {
|
logo_web_header: {
|
||||||
path: string;
|
path: string;
|
||||||
display_name: string;
|
display_name: string;
|
||||||
};
|
};
|
||||||
|
login_info_text?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if the given object holds valid LoginData.
|
||||||
|
*
|
||||||
|
* @param obj The object to check
|
||||||
|
*/
|
||||||
|
function isLoginData(obj: any): obj is LoginData {
|
||||||
|
return !!obj && obj.theme && obj.logo_web_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOGIN_DATA_STORAGE_KEY = 'LoginData';
|
const LOGIN_DATA_STORAGE_KEY = 'LoginData';
|
||||||
@ -29,28 +42,40 @@ const LOGIN_DATA_STORAGE_KEY = 'LoginData';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class LoginDataService {
|
export class LoginDataService {
|
||||||
|
/**
|
||||||
|
* Holds the installation notice.
|
||||||
|
*/
|
||||||
|
private readonly _loginInfoText = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the installation notice as observable.
|
||||||
|
*/
|
||||||
|
public get loginInfoText(): Observable<string> {
|
||||||
|
return this._loginInfoText.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the privacy policy
|
* Holds the privacy policy
|
||||||
*/
|
*/
|
||||||
private readonly _privacy_policy = new BehaviorSubject<string>('');
|
private readonly _privacyPolicy = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable for the privacy policy
|
* Returns an observable for the privacy policy
|
||||||
*/
|
*/
|
||||||
public get privacy_policy(): Observable<string> {
|
public get privacyPolicy(): Observable<string> {
|
||||||
return this._privacy_policy.asObservable();
|
return this._privacyPolicy.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the legal notice
|
* Holds the legal notice
|
||||||
*/
|
*/
|
||||||
private readonly _legal_notice = new BehaviorSubject<string>('');
|
private readonly _legalNotice = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable for the legal notice
|
* Returns an observable for the legal notice
|
||||||
*/
|
*/
|
||||||
public get legal_notice(): Observable<string> {
|
public get legalNotice(): Observable<string> {
|
||||||
return this._legal_notice.asObservable();
|
return this._legalNotice.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,7 +93,7 @@ export class LoginDataService {
|
|||||||
/**
|
/**
|
||||||
* Holds the custom web header
|
* Holds the custom web header
|
||||||
*/
|
*/
|
||||||
private readonly _logo_web_header = new BehaviorSubject<{ path: string; display_name: string }>({
|
private readonly _logoWebHeader = new BehaviorSubject<{ path: string; display_name: string }>({
|
||||||
path: '',
|
path: '',
|
||||||
display_name: ''
|
display_name: ''
|
||||||
});
|
});
|
||||||
@ -76,10 +101,27 @@ export class LoginDataService {
|
|||||||
/**
|
/**
|
||||||
* Returns an observable for the web header
|
* Returns an observable for the web header
|
||||||
*/
|
*/
|
||||||
public get logo_web_header(): Observable<{ path: string; display_name: string }> {
|
public get logoWebHeader(): Observable<{ path: string; display_name: string }> {
|
||||||
return this._logo_web_header.asObservable();
|
return this._logoWebHeader.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit this event, if the current login data should be stored. This
|
||||||
|
* is debounced to minimize requests to the storage service.
|
||||||
|
*/
|
||||||
|
private storeLoginDataRequests = new EventEmitter<void>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds, if `_refresh` can be called. This will be true fter the setup.
|
||||||
|
*/
|
||||||
|
private canRefresh = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks, if during the etup (with `canRefresh=false`) a refresh was requested.
|
||||||
|
* After the setup, this variabel will be checked and a refresh triggered, if it is true.
|
||||||
|
*/
|
||||||
|
private markRefresh = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs this service. The config service is needed to update the privacy
|
* Constructs this service. The config service is needed to update the privacy
|
||||||
* policy and legal notice, when their config values change.
|
* policy and legal notice, when their config values change.
|
||||||
@ -88,67 +130,112 @@ export class LoginDataService {
|
|||||||
public constructor(
|
public constructor(
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private OSStatus: OpenSlidesStatusService
|
private OSStatus: OpenSlidesStatusService,
|
||||||
|
private httpService: HttpService
|
||||||
) {
|
) {
|
||||||
|
this.storeLoginDataRequests.pipe(auditTime(100)).subscribe(() => this.storeLoginData());
|
||||||
|
this.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the login data and *after* that the configs are subscribed. If a request for a refresh
|
||||||
|
* was issued while the setup, the refresh will be executed afterwards.
|
||||||
|
*/
|
||||||
|
private async setup(): Promise<void> {
|
||||||
|
await this.loadLoginData();
|
||||||
this.configService.get<string>('general_event_privacy_policy').subscribe(value => {
|
this.configService.get<string>('general_event_privacy_policy').subscribe(value => {
|
||||||
this._privacy_policy.next(value);
|
if (value !== undefined) {
|
||||||
this.storeLoginData();
|
this._privacyPolicy.next(value);
|
||||||
|
this.storeLoginDataRequests.next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.configService.get<string>('general_event_legal_notice').subscribe(value => {
|
this.configService.get<string>('general_event_legal_notice').subscribe(value => {
|
||||||
this._legal_notice.next(value);
|
if (value !== undefined) {
|
||||||
this.storeLoginData();
|
this._legalNotice.next(value);
|
||||||
|
this.storeLoginDataRequests.next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
configService.get<string>('openslides_theme').subscribe(value => {
|
this.configService.get<string>('openslides_theme').subscribe(value => {
|
||||||
this._theme.next(value);
|
if (value) {
|
||||||
this.storeLoginData();
|
this._theme.next(value);
|
||||||
|
this.storeLoginDataRequests.next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
configService.get<{ path: string; display_name: string }>('logo_web_header').subscribe(value => {
|
this.configService.get<{ path: string; display_name: string }>('logo_web_header').subscribe(value => {
|
||||||
this._logo_web_header.next(value);
|
if (value) {
|
||||||
this.storeLoginData();
|
this._logoWebHeader.next(value);
|
||||||
|
this.storeLoginDataRequests.next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
this.canRefresh = true;
|
||||||
|
if (this.markRefresh) {
|
||||||
|
this._refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.loadLoginData();
|
/**
|
||||||
|
* Explicit refresh the ata from the server.
|
||||||
|
*/
|
||||||
|
public refresh(): void {
|
||||||
|
if (this.canRefresh && !this.markRefresh) {
|
||||||
|
this._refresh();
|
||||||
|
} else if (!this.canRefresh) {
|
||||||
|
this.markRefresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual refresh implementation.
|
||||||
|
*/
|
||||||
|
private async _refresh(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const loginData = await this.httpService.get<LoginData>(environment.urlPrefix + '/users/login/');
|
||||||
|
this.setLoginData(loginData);
|
||||||
|
this.storeLoginDataRequests.next();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Could not refresh login data', e);
|
||||||
|
}
|
||||||
|
this.markRefresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the login data from the storage. If it there, set it.
|
* Load the login data from the storage. If it there, set it.
|
||||||
*/
|
*/
|
||||||
private async loadLoginData(): Promise<void> {
|
private async loadLoginData(): Promise<void> {
|
||||||
const loginData = await this.storageService.get<LoginData | null>(LOGIN_DATA_STORAGE_KEY);
|
const loginData = await this.storageService.get<any>(LOGIN_DATA_STORAGE_KEY);
|
||||||
if (loginData) {
|
if (isLoginData(loginData)) {
|
||||||
this.setLoginData(loginData);
|
this.setLoginData(loginData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for the login data
|
* Triggers all subjects with the given data.
|
||||||
*
|
*
|
||||||
* @param loginData the login data
|
* @param loginData The data
|
||||||
*/
|
*/
|
||||||
public setLoginData(loginData: LoginData): void {
|
private setLoginData(loginData: LoginData): void {
|
||||||
this._privacy_policy.next(loginData.privacy_policy);
|
this._privacyPolicy.next(loginData.privacy_policy);
|
||||||
this._legal_notice.next(loginData.legal_notice);
|
this._legalNotice.next(loginData.legal_notice);
|
||||||
this._theme.next(loginData.theme);
|
this._theme.next(loginData.theme);
|
||||||
this.storeLoginData(loginData);
|
this._logoWebHeader.next(loginData.logo_web_header);
|
||||||
|
this._loginInfoText.next(loginData.login_info_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the login data in the storage.
|
* Saves the login data to the storeage. Do not call this method and
|
||||||
*
|
* use `storeLoginDataRequests` instead. The data to store will be
|
||||||
* @param loginData If given, this data is used. If it's null, the current values
|
* taken form all subjects.
|
||||||
* from the behaviour subject are taken.
|
|
||||||
*/
|
*/
|
||||||
private storeLoginData(loginData?: LoginData): void {
|
private storeLoginData(): void {
|
||||||
if (!loginData) {
|
if (this.OSStatus.isInHistoryMode) {
|
||||||
loginData = {
|
return;
|
||||||
privacy_policy: this._privacy_policy.getValue(),
|
|
||||||
legal_notice: this._legal_notice.getValue(),
|
|
||||||
theme: this._theme.getValue(),
|
|
||||||
logo_web_header: this._logo_web_header.getValue()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (!this.OSStatus.isInHistoryMode) {
|
|
||||||
this.storageService.set(LOGIN_DATA_STORAGE_KEY, loginData);
|
|
||||||
}
|
}
|
||||||
|
const loginData = {
|
||||||
|
privacy_policy: this._privacyPolicy.getValue(),
|
||||||
|
legal_notice: this._legalNotice.getValue(),
|
||||||
|
theme: this._theme.getValue(),
|
||||||
|
logo_web_header: this._logoWebHeader.getValue()
|
||||||
|
};
|
||||||
|
this.storageService.set(LOGIN_DATA_STORAGE_KEY, loginData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { MediaManageService } from './media-manage.service';
|
import { MediaManageService } from './media-manage.service';
|
||||||
import { E2EImportsModule } from 'e2e-imports.module';
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('MediaManageService', () => {
|
describe('MediaManageService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({ imports: [E2EImportsModule] }));
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
it('should be created', () => {
|
imports: [E2EImportsModule],
|
||||||
const service: MediaManageService = TestBed.get(MediaManageService);
|
providers: [MediaManageService]
|
||||||
expect(service).toBeTruthy();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([MediaManageService], (service: MediaManageService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { PdfDocumentService } from '../ui-services/pdf-document.service';
|
import { PdfDocumentService } from '../ui-services/pdf-document.service';
|
||||||
import { E2EImportsModule } from 'e2e-imports.module';
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('PdfDocumentService', () => {
|
describe('PdfDocumentService', () => {
|
||||||
beforeEach(() =>
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [E2EImportsModule]
|
imports: [E2EImportsModule],
|
||||||
})
|
providers: [PdfDocumentService]
|
||||||
);
|
});
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
const service: PdfDocumentService = TestBed.get(PdfDocumentService);
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([PdfDocumentService], (service: PdfDocumentService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { PollService } from './poll.service';
|
import { PollService } from './poll.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('PollService', () => {
|
describe('PollService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
it('should be created', () => {
|
imports: [E2EImportsModule],
|
||||||
const service: PollService = TestBed.get(PollService);
|
providers: [PollService]
|
||||||
expect(service).toBeTruthy();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([PollService], (service: PollService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { RoutingStateService } from './routing-state.service';
|
import { RoutingStateService } from './routing-state.service';
|
||||||
import { E2EImportsModule } from 'e2e-imports.module';
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('RoutingStateService', () => {
|
describe('RoutingStateService', () => {
|
||||||
beforeEach(() =>
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [E2EImportsModule]
|
imports: [E2EImportsModule],
|
||||||
})
|
providers: [RoutingStateService]
|
||||||
);
|
});
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
const service: RoutingStateService = TestBed.get(RoutingStateService);
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([RoutingStateService], (service: RoutingStateService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { SpinnerService } from './spinner.service';
|
import { SpinnerService } from './spinner.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('SpinnerService', () => {
|
describe('SpinnerService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
it('should be created', () => {
|
imports: [E2EImportsModule],
|
||||||
const service: SpinnerService = TestBed.get(SpinnerService);
|
providers: [SpinnerService]
|
||||||
expect(service).toBeTruthy();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([SpinnerService], (service: SpinnerService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { ThemeService } from './theme.service';
|
import { ThemeService } from './theme.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('ThemeService', () => {
|
describe('ThemeService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
it('should be created', () => {
|
imports: [E2EImportsModule],
|
||||||
const service: ThemeService = TestBed.get(ThemeService);
|
providers: [ThemeService]
|
||||||
expect(service).toBeTruthy();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([ThemeService], (service: ThemeService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -77,17 +77,4 @@ export class ThemeService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to ensure, that there is at least one theme set to define
|
|
||||||
* the colors of the components.
|
|
||||||
*
|
|
||||||
* If a theme is already set, nothing happens, otherwise the
|
|
||||||
* `DEFAULT_THEME` will be set.
|
|
||||||
*/
|
|
||||||
public checkTheme(): void {
|
|
||||||
if (!this.currentTheme || this.currentTheme === '') {
|
|
||||||
this.changeTheme(ThemeService.DEFAULT_THEME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { UpdateService } from './update.service';
|
import { UpdateService } from './update.service';
|
||||||
import { E2EImportsModule } from 'e2e-imports.module';
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
@ -11,8 +11,7 @@ describe('UpdateService', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', inject([UpdateService], (service: UpdateService) => {
|
||||||
const service: UpdateService = TestBed.get(UpdateService);
|
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { TestBed, inject } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { ViewportService } from './viewport.service';
|
import { ViewportService } from './viewport.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('ViewportService', () => {
|
describe('ViewportService', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule],
|
||||||
providers: [ViewportService]
|
providers: [ViewportService]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
import { XlsxExportServiceService } from './xlsx-export-service.service';
|
import { XlsxExportServiceService } from './xlsx-export-service.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
describe('XlsxExportServiceService', () => {
|
describe('XlsxExportServiceService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
it('should be created', () => {
|
imports: [E2EImportsModule],
|
||||||
const service: XlsxExportServiceService = TestBed.get(XlsxExportServiceService);
|
providers: [XlsxExportServiceService]
|
||||||
expect(service).toBeTruthy();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([XlsxExportServiceService], (service: XlsxExportServiceService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
.toolbar-left {
|
.toolbar-left {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
max-width: calc(100% - 100px);
|
||||||
button {
|
button {
|
||||||
margin: 12px 0;
|
margin: 12px 0;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
<mat-card class="os-card">
|
<mat-card class="os-card">
|
||||||
<div>
|
<div>
|
||||||
<div class="legal-notice-text" [innerHtml]="legalNotice"></div>
|
<div *ngIf="legalNotice" class="legal-notice-text" [innerHtml]="legalNotice"></div>
|
||||||
|
<div *ngIf="!legalNotice" translate>
|
||||||
|
The event manager hasn't set up a legal notice yet.
|
||||||
|
</div>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<div *ngIf="versionInfo" class="version-text">
|
<div *ngIf="versionInfo" class="version-text">
|
||||||
<a [attr.href]="versionInfo.openslides_url" target="_blank">
|
<a [attr.href]="versionInfo.openslides_url" target="_blank">
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
|
|
||||||
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
@ -82,20 +80,14 @@ export class LegalNoticeContentComponent implements OnInit {
|
|||||||
* @param translate
|
* @param translate
|
||||||
* @param http
|
* @param http
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(private loginDataService: LoginDataService, private http: HttpService) {}
|
||||||
private loginDataService: LoginDataService,
|
|
||||||
private translate: TranslateService,
|
|
||||||
private http: HttpService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribes for the legal notice text.
|
* Subscribes for the legal notice text.
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
this.loginDataService.legal_notice.subscribe(legalNotice => {
|
this.loginDataService.legalNotice.subscribe(legalNotice => {
|
||||||
if (legalNotice) {
|
this.legalNotice = legalNotice;
|
||||||
this.legalNotice = this.translate.instant(legalNotice);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Query the version info.
|
// Query the version info.
|
||||||
|
@ -42,7 +42,7 @@ export class LogoComponent implements OnInit, OnDestroy {
|
|||||||
* On init method
|
* On init method
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
this.logoSubscription = this.loginDataService.logo_web_header.subscribe(nextLogo => {
|
this.logoSubscription = this.loginDataService.logoWebHeader.subscribe(nextLogo => {
|
||||||
if (nextLogo) {
|
if (nextLogo) {
|
||||||
this.logoPath = nextLogo.path;
|
this.logoPath = nextLogo.path;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
|
|
||||||
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,16 +22,14 @@ export class PrivacyPolicyContentComponent implements OnInit {
|
|||||||
* @param loginDataService Login Data
|
* @param loginDataService Login Data
|
||||||
* @param translate for the translation
|
* @param translate for the translation
|
||||||
*/
|
*/
|
||||||
public constructor(private loginDataService: LoginDataService, private translate: TranslateService) {}
|
public constructor(private loginDataService: LoginDataService) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribes for the privacy policy text
|
* Subscribes for the privacy policy text
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
this.loginDataService.privacy_policy.subscribe(privacyPolicy => {
|
this.loginDataService.privacyPolicy.subscribe(privacyPolicy => {
|
||||||
if (privacyPolicy) {
|
this.privacyPolicy = privacyPolicy;
|
||||||
this.privacyPolicy = this.translate.instant(privacyPolicy);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,18 +6,13 @@ import { Title } from '@angular/platform-browser';
|
|||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseComponent } from 'app/base.component';
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
import { AuthService } from 'app/core/core-services/auth.service';
|
import { AuthService } from 'app/core/core-services/auth.service';
|
||||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
import { environment } from 'environments/environment';
|
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
||||||
import { LoginDataService, LoginData } from 'app/core/ui-services/login-data.service';
|
|
||||||
import { ParentErrorStateMatcher } from 'app/shared/parent-error-state-matcher';
|
import { ParentErrorStateMatcher } from 'app/shared/parent-error-state-matcher';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
|
||||||
import { SpinnerService } from 'app/core/ui-services/spinner.service';
|
import { SpinnerService } from 'app/core/ui-services/spinner.service';
|
||||||
|
import { MatSnackBar } from '@angular/material';
|
||||||
interface LoginDataWithInfoText extends LoginData {
|
|
||||||
info_text?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login mask component.
|
* Login mask component.
|
||||||
@ -29,7 +24,7 @@ interface LoginDataWithInfoText extends LoginData {
|
|||||||
templateUrl: './login-mask.component.html',
|
templateUrl: './login-mask.component.html',
|
||||||
styleUrls: ['./login-mask.component.scss']
|
styleUrls: ['./login-mask.component.scss']
|
||||||
})
|
})
|
||||||
export class LoginMaskComponent extends BaseComponent implements OnInit, OnDestroy {
|
export class LoginMaskComponent extends BaseViewComponent implements OnInit, OnDestroy {
|
||||||
/**
|
/**
|
||||||
* Show or hide password and change the indicator accordingly
|
* Show or hide password and change the indicator accordingly
|
||||||
*/
|
*/
|
||||||
@ -72,16 +67,16 @@ export class LoginMaskComponent extends BaseComponent implements OnInit, OnDestr
|
|||||||
public constructor(
|
public constructor(
|
||||||
title: Title,
|
title: Title,
|
||||||
translate: TranslateService,
|
translate: TranslateService,
|
||||||
|
matSnackBar: MatSnackBar,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private operator: OperatorService,
|
private operator: OperatorService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private httpService: HttpService,
|
|
||||||
private loginDataService: LoginDataService,
|
private loginDataService: LoginDataService,
|
||||||
private spinnerService: SpinnerService
|
private spinnerService: SpinnerService
|
||||||
) {
|
) {
|
||||||
super(title, translate);
|
super(title, translate, matSnackBar);
|
||||||
// Hide the spinner if the user is at `login-mask`
|
// Hide the spinner if the user is at `login-mask`
|
||||||
spinnerService.setVisibility(false);
|
spinnerService.setVisibility(false);
|
||||||
this.createForm();
|
this.createForm();
|
||||||
@ -94,17 +89,8 @@ export class LoginMaskComponent extends BaseComponent implements OnInit, OnDestr
|
|||||||
* Observes the operator, if a user was already logged in, recreate to user and skip the login
|
* Observes the operator, if a user was already logged in, recreate to user and skip the login
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
// Get the login data. Save information to the login data service. If there is an
|
this.subscriptions.push(
|
||||||
// error, ignore it.
|
this.loginDataService.loginInfoText.subscribe(notice => (this.installationNotice = notice))
|
||||||
// TODO: This has to be caught by the offline service
|
|
||||||
this.httpService.get<LoginDataWithInfoText>(environment.urlPrefix + '/users/login/').then(
|
|
||||||
response => {
|
|
||||||
if (response.info_text) {
|
|
||||||
this.installationNotice = response.info_text;
|
|
||||||
}
|
|
||||||
this.loginDataService.setLoginData(response);
|
|
||||||
},
|
|
||||||
() => {}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Maybe the operator changes and the user is logged in. If so, redirect him and boot OpenSlides.
|
// Maybe the operator changes and the user is logged in. If so, redirect him and boot OpenSlides.
|
||||||
|
@ -4,6 +4,7 @@ import { Title } from '@angular/platform-browser';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseComponent } from '../../../../base.component';
|
import { BaseComponent } from '../../../../base.component';
|
||||||
|
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login component.
|
* Login component.
|
||||||
@ -22,7 +23,11 @@ export class LoginWrapperComponent extends BaseComponent implements OnInit {
|
|||||||
* @param titleService to set the title
|
* @param titleService to set the title
|
||||||
* @param translate just needed because super.setTitle depends in the `translator.instant` function
|
* @param translate just needed because super.setTitle depends in the `translator.instant` function
|
||||||
*/
|
*/
|
||||||
public constructor(protected titleService: Title, protected translate: TranslateService) {
|
public constructor(
|
||||||
|
protected titleService: Title,
|
||||||
|
protected translate: TranslateService,
|
||||||
|
private loginDataService: LoginDataService
|
||||||
|
) {
|
||||||
super(titleService, translate);
|
super(titleService, translate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,5 +36,6 @@ export class LoginWrapperComponent extends BaseComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Login');
|
super.setTitle('Login');
|
||||||
|
this.loginDataService.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,12 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
class="submit-button"
|
class="submit-button"
|
||||||
[disabled]="newPasswordForm.invalid"
|
[disabled]="newPasswordForm.invalid"
|
||||||
translate
|
|
||||||
>
|
>
|
||||||
Reset password
|
{{ 'Reset password' | translate }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" mat-button routerLink="/login">
|
||||||
|
{{ 'Back to login' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="back-button" routerLink="/login" translate>Back to login</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,14 @@
|
|||||||
<form [formGroup]="resetPasswordForm" (ngSubmit)="resetPassword()" autocomplete="off">
|
<form [formGroup]="resetPasswordForm" (ngSubmit)="resetPassword()" autocomplete="off">
|
||||||
<h3 translate>Enter your email to send the password reset link</h3>
|
<h3 translate>Enter your email to send the password reset link</h3>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input matInput required placeholder="{{ 'Email' | translate }}" formControlName="email" type="email" autocomplete="off" />
|
<input
|
||||||
|
matInput
|
||||||
|
required
|
||||||
|
placeholder="{{ 'Email' | translate }}"
|
||||||
|
formControlName="email"
|
||||||
|
type="email"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
<mat-error *ngIf="resetPasswordForm.get('email').invalid" translate>
|
<mat-error *ngIf="resetPasswordForm.get('email').invalid" translate>
|
||||||
Please enter a valid email address!
|
Please enter a valid email address!
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
@ -8,7 +8,6 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
|
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
import { ThemeService } from 'app/core/ui-services/theme.service';
|
|
||||||
import { BaseViewComponent } from 'app/site/base/base-view';
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,8 +34,7 @@ export class ResetPasswordComponent extends BaseViewComponent implements OnInit
|
|||||||
matSnackBar: MatSnackBar,
|
matSnackBar: MatSnackBar,
|
||||||
private http: HttpService,
|
private http: HttpService,
|
||||||
formBuilder: FormBuilder,
|
formBuilder: FormBuilder,
|
||||||
private router: Router,
|
private router: Router
|
||||||
private themeService: ThemeService
|
|
||||||
) {
|
) {
|
||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
this.resetPasswordForm = formBuilder.group({
|
this.resetPasswordForm = formBuilder.group({
|
||||||
@ -49,7 +47,6 @@ export class ResetPasswordComponent extends BaseViewComponent implements OnInit
|
|||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Reset password');
|
super.setTitle('Reset password');
|
||||||
this.themeService.checkTheme();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,6 +86,7 @@ mat-sidenav-container {
|
|||||||
height: $size;
|
height: $size;
|
||||||
width: $size;
|
width: $size;
|
||||||
font-size: $size;
|
font-size: $size;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -732,20 +732,17 @@ class UserLoginView(WhoAmIDataView):
|
|||||||
"""
|
"""
|
||||||
if self.request.method == "GET":
|
if self.request.method == "GET":
|
||||||
if config["general_login_info_text"]:
|
if config["general_login_info_text"]:
|
||||||
context["info_text"] = config["general_login_info_text"]
|
context["login_info_text"] = config["general_login_info_text"]
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
user = User.objects.get(username="admin")
|
user = User.objects.get(username="admin")
|
||||||
except User.DoesNotExist:
|
|
||||||
context["info_text"] = ""
|
|
||||||
else:
|
|
||||||
if user.check_password("admin"):
|
if user.check_password("admin"):
|
||||||
context["info_text"] = (
|
context["login_info_text"] = (
|
||||||
f"Use <strong>admin</strong> and <strong>admin</strong> for your first login.<br>"
|
f"Use <strong>admin</strong> and <strong>admin</strong> for your first login.<br>"
|
||||||
"Please change your password to hide this message!"
|
"Please change your password to hide this message!"
|
||||||
)
|
)
|
||||||
else:
|
except User.DoesNotExist:
|
||||||
context["info_text"] = ""
|
pass
|
||||||
# Add the privacy policy and legal notice, so the client can display it
|
# Add the privacy policy and legal notice, so the client can display it
|
||||||
# even, it is not logged in.
|
# even, it is not logged in.
|
||||||
context["privacy_policy"] = config["general_event_privacy_policy"]
|
context["privacy_policy"] = config["general_event_privacy_policy"]
|
||||||
|
@ -72,7 +72,7 @@ class TestUserLoginView(TestCase):
|
|||||||
response = self.client.get(self.url)
|
response = self.client.get(self.url)
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue(json.loads(response.content.decode()).get("info_text"))
|
self.assertTrue(json.loads(response.content.decode()).get("login_info_text"))
|
||||||
|
|
||||||
def test_post_no_data(self):
|
def test_post_no_data(self):
|
||||||
response = self.client.post(self.url)
|
response = self.client.post(self.url)
|
||||||
|
Loading…
Reference in New Issue
Block a user