Adds a login handling to restrict the access to the i18n-manager route

parent 436a8951
This diff is collapsed.
......@@ -22,8 +22,7 @@ export class FooterBarComponent implements OnInit, OnDestroy {
return this._footerElements;
}
@Input()
set footerElements(value: Array<IFooterBarElement>) {
@Input() set footerElements(value: Array<IFooterBarElement>) {
this.hasRightScrollElement = value.length > 1;
this._footerElements = value;
}
......@@ -126,7 +125,9 @@ export class FooterBarComponent implements OnInit, OnDestroy {
} else {
const child = navbarFooter.children.item(this.footerElemIndex);
const childWidth = child.clientWidth;
navbarFooter.scrollLeft -= (childWidth);
navbarFooter.scrollLeft -= (
childWidth
);
}
}
......@@ -146,7 +147,9 @@ export class FooterBarComponent implements OnInit, OnDestroy {
if (this.footerElemIndex === 1) {
const childWidth = child.clientWidth;
const leftButtonWidth = document.getElementById('footer-move-left').clientWidth;
navbarFooter.scrollLeft += (childWidth - leftButtonWidth);
navbarFooter.scrollLeft += (
childWidth - leftButtonWidth
);
} else {
navbarFooter.scrollLeft += child.clientWidth;
}
......@@ -158,6 +161,10 @@ export class FooterBarComponent implements OnInit, OnDestroy {
return;
}
if (!this.footerElements.length) {
return true;
}
const navbarFooter = document.getElementById('navbar-footer-container');
if (!navbarFooter) {
return false;
......
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { I18nManagerComponent } from './i18n-manager.component';
import { I18nManagerOverviewComponent } from './i18n-manager-overview.component';
describe('FeTranslationComponent', () => {
let component: I18nManagerComponent;
let fixture: ComponentFixture<I18nManagerComponent>;
describe('I18nManagerOverviewComponent', () => {
let component: I18nManagerOverviewComponent;
let fixture: ComponentFixture<I18nManagerOverviewComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [I18nManagerComponent],
declarations: [I18nManagerOverviewComponent],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(I18nManagerComponent);
fixture = TestBed.createComponent(I18nManagerOverviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
......@@ -23,6 +23,6 @@ describe('FeTranslationComponent', () => {
expect(component).toBeTruthy();
});
it('should contain a TYPE reference', () => {
expect(I18nManagerComponent.TYPE).toEqual('I18nManagerComponent');
expect(I18nManagerOverviewComponent.TYPE).toEqual('I18nManagerOverviewComponent');
});
});
......@@ -3,18 +3,19 @@ import { Observable, of } from 'rxjs/index';
import { FooterBarService } from '../../service/footer-bar/footer-bar.service';
import { HeaderLabelService } from '../../service/header-label/header-label.service';
import { LanguageLoaderService } from '../../service/language-loader/language-loader.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { ModalOrganizerService } from '../../service/modal-organizer/modal-organizer.service';
import { ProjectLoaderService } from '../../service/project-loader/project-loader.service';
import { FILTER, PROJECT } from '../../shared/enums';
@Component({
selector: 'app-fe-translation',
templateUrl: './i18n-manager.component.html',
styleUrls: ['./i18n-manager.component.scss'],
selector: 'app-i18n-manager-overview',
templateUrl: './i18n-manager-overview.component.html',
styleUrls: ['./i18n-manager-overview.component.scss'],
})
export class I18nManagerComponent implements OnInit, OnDestroy {
export class I18nManagerOverviewComponent implements OnInit, OnDestroy {
public static readonly TYPE = 'I18nManagerComponent';
public static readonly TYPE = 'I18nManagerOverviewComponent';
public readonly filters = FILTER;
private _langRef = ['en', 'de', 'fr', 'it', 'es'];
......@@ -93,10 +94,15 @@ export class I18nManagerComponent implements OnInit, OnDestroy {
this._hasAnyMatches = value;
}
constructor(private footerBarService: FooterBarService, private headerLabelService: HeaderLabelService,
public modalOrganizerService: ModalOrganizerService, public projectLoaderService: ProjectLoaderService,
private languageLoaderService: LanguageLoaderService,
constructor(
private footerBarService: FooterBarService,
private headerLabelService: HeaderLabelService,
public modalOrganizerService: ModalOrganizerService,
public projectLoaderService: ProjectLoaderService,
private languageLoaderService: LanguageLoaderService,
private casService: CasLoginService,
) {
this.casService.casLoginRequired = true;
this.headerLabelService.headerLabel = 'I18Nator';
this.footerBarService.replaceFooterElements([]);
}
......
......@@ -2,16 +2,18 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PipesModule } from '../pipes/pipes.module';
import { LanguageLoaderService } from '../service/language-loader/language-loader.service';
import { StaticLoginService } from '../service/login/static-login.service';
import { ModalOrganizerService } from '../service/modal-organizer/modal-organizer.service';
import { ProjectLoaderService } from '../service/project-loader/project-loader.service';
import { SharedModule } from '../shared/shared.module';
import { I18nManagerComponent } from './i18n-manager/i18n-manager.component';
import { I18nManagerOverviewComponent } from './i18n-manager-overview/i18n-manager-overview.component';
import { KeyOutputComponent } from './key-output/key-output.component';
const i18nManagerRoutes: Routes = [
{
path: 'i18n-manager',
component: I18nManagerComponent,
canActivate: [StaticLoginService],
component: I18nManagerOverviewComponent,
},
];
......@@ -19,7 +21,7 @@ const i18nManagerRoutes: Routes = [
imports: [
SharedModule, PipesModule, RouterModule.forChild(i18nManagerRoutes),
],
declarations: [I18nManagerComponent, KeyOutputComponent],
declarations: [I18nManagerOverviewComponent, KeyOutputComponent],
providers: [
LanguageLoaderService, ProjectLoaderService, ModalOrganizerService,
],
......
......@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NgxQRCodeModule } from '@techiediaries/ngx-qrcode';
import { MarkdownModule } from '../../markdown/markdown.module';
import { CasService } from '../../service/cas/cas.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { SharedModule } from '../../shared/shared.module';
import { ThemesModule } from '../../themes/themes.module';
import { ConfidenceRateComponent } from './confidence-rate/confidence-rate.component';
......@@ -20,49 +20,40 @@ export const quizFlowRoutes: Routes = [
path: '',
pathMatch: 'full',
redirectTo: 'lobby',
},
{
}, {
path: 'lobby',
canLoad: [CasService],
canLoad: [CasLoginService],
component: QuizLobbyComponent,
data: {},
},
{
}, {
path: 'results',
component: QuizResultsComponent,
data: {},
},
{
}, {
path: 'results/:questionIndex',
component: QuestionDetailsComponent,
data: {},
},
{
}, {
path: 'theme',
component: QuizThemeComponent,
data: {},
},
{
}, {
path: 'leaderboard',
component: LeaderboardComponent,
data: {},
},
{
}, {
path: 'leaderboard/:questionIndex',
component: LeaderboardComponent,
data: {},
},
{
}, {
path: 'voting',
component: VotingComponent,
data: {},
},
{
}, {
path: 'reading-confirmation',
component: ReadingConfirmationComponent,
data: {},
},
{
}, {
path: 'confidence-rate',
component: ConfidenceRateComponent,
data: {},
......@@ -71,20 +62,10 @@ export const quizFlowRoutes: Routes = [
@NgModule({
imports: [
MarkdownModule,
SharedModule,
ThemesModule,
RouterModule.forChild(quizFlowRoutes),
QuizResultsModule,
NgxQRCodeModule,
MarkdownModule, SharedModule, ThemesModule, RouterModule.forChild(quizFlowRoutes), QuizResultsModule, NgxQRCodeModule,
],
declarations: [
QuizLobbyComponent,
VotingComponent,
LeaderboardComponent,
QuizThemeComponent,
ReadingConfirmationComponent,
ConfidenceRateComponent,
QuizLobbyComponent, VotingComponent, LeaderboardComponent, QuizThemeComponent, ReadingConfirmationComponent, ConfidenceRateComponent,
],
})
export class QuizFlowModule {
......
......@@ -9,12 +9,12 @@ import { of } from 'rxjs/index';
import { createTranslateLoader } from '../../../lib/translation.factory';
import { LobbyApiService } from '../../service/api/lobby/lobby-api.service';
import { QuizApiService } from '../../service/api/quiz/quiz-api.service';
import { CasService } from '../../service/cas/cas.service';
import { ConnectionMockService } from '../../service/connection/connection.mock.service';
import { ConnectionService } from '../../service/connection/connection.service';
import { CurrentQuizMockService } from '../../service/current-quiz/current-quiz.mock.service';
import { CurrentQuizService } from '../../service/current-quiz/current-quiz.service';
import { FooterBarService } from '../../service/footer-bar/footer-bar.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { SettingsService } from '../../service/settings/settings.service';
import { SharedService } from '../../service/shared/shared.service';
import { ThemesMockService } from '../../service/themes/themes.mock.service';
......@@ -27,12 +27,20 @@ import { QuizJoinComponent } from './quiz-join.component';
class MockRouter {
public queryParams = {
subscribe: (next) => (next({ ticket: 'testCasTicket' })),
toPromise: () => (new Promise(resolve => resolve({ ticket: 'testCasTicket' }))),
subscribe: (next) => (
next({ ticket: 'testCasTicket' })
),
toPromise: () => (
new Promise(resolve => resolve({ ticket: 'testCasTicket' }))
),
};
public params = {
subscribe: (next) => (next({ quizName: 'test' })),
toPromise: () => (new Promise(resolve => resolve({ quizName: 'test' }))),
subscribe: (next) => (
next({ quizName: 'test' })
),
toPromise: () => (
new Promise(resolve => resolve({ quizName: 'test' }))
),
};
}
......@@ -43,13 +51,12 @@ describe('QuizJoinComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule,
HttpClientModule,
HttpClientTestingModule,
TranslateModule.forRoot({
RouterTestingModule, HttpClientModule, HttpClientTestingModule, TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
useFactory: (
createTranslateLoader
),
deps: [HttpClient],
},
compiler: {
......@@ -59,17 +66,32 @@ describe('QuizJoinComponent', () => {
}),
],
providers: [
CasService,
CasLoginService,
LobbyApiService,
QuizApiService,
{ provide: CurrentQuizService, useClass: CurrentQuizMockService },
{ provide: ThemesService, useClass: ThemesMockService },
{
provide: CurrentQuizService,
useClass: CurrentQuizMockService,
},
{
provide: ThemesService,
useClass: ThemesMockService,
},
UserService,
FooterBarService,
SettingsService,
{ provide: ConnectionService, useClass: ConnectionMockService },
{ provide: WebsocketService, useClass: WebsocketMockService },
{ provide: ActivatedRoute, useClass: MockRouter },
{
provide: ConnectionService,
useClass: ConnectionMockService,
},
{
provide: WebsocketService,
useClass: WebsocketMockService,
},
{
provide: ActivatedRoute,
useClass: MockRouter,
},
SharedService,
],
declarations: [QuizJoinComponent],
......@@ -90,33 +112,29 @@ describe('QuizJoinComponent', () => {
expect(QuizJoinComponent.TYPE).toEqual('QuizJoinComponent');
}));
it('should redirect the user to / on failure',
async(inject([Router, QuizApiService], (router: Router, quizApiService: QuizApiService) => {
const quizStatusData = {
status: 'STATUS:FAILED',
step: 'QUIZ:UNAVAILABLE',
payload: {
authorizeViaCas: true,
provideNickSelection: false,
},
};
it('should redirect the user to / on failure', async(inject([Router, QuizApiService], (router: Router, quizApiService: QuizApiService) => {
const quizStatusData = {
status: 'STATUS:FAILED',
step: 'QUIZ:UNAVAILABLE',
payload: {
authorizeViaCas: true,
provideNickSelection: false,
},
};
spyOn(quizApiService, 'getQuizStatus').and.returnValue(of(quizStatusData));
spyOn(router, 'navigate').and.callFake(() => {});
spyOn(quizApiService, 'getQuizStatus').and.returnValue(of(quizStatusData));
spyOn(router, 'navigate').and.callFake(() => {});
component.ngOnInit();
expect(router.navigate).toHaveBeenCalledWith(['/']);
}),
),
);
it('should add a cas ticket to the casService if a ticket is supplied', async(inject(
[Router, CurrentQuizService, CasService, QuizApiService, LobbyApiService],
(router: Router,
currentQuizService: CurrentQuizService,
casService: CasService,
quizApiService: QuizApiService,
lobbyApiService: LobbyApiService,
component.ngOnInit();
expect(router.navigate).toHaveBeenCalledWith(['/']);
})));
it('should add a cas casTicket to the casService if a casTicket is supplied',
async(inject([Router, CurrentQuizService, CasLoginService, QuizApiService, LobbyApiService], (router: Router,
currentQuizService: CurrentQuizService,
casService: CasLoginService,
quizApiService: QuizApiService,
lobbyApiService: LobbyApiService,
) => {
const quizStatusData = {
status: 'STATUS:SUCCESSFUL',
......@@ -145,108 +163,96 @@ describe('QuizJoinComponent', () => {
expect(casService.quizName).toEqual('test');
})));
it('should redirect the user to the membergroup selection if there are multiple groups available', async(inject(
[Router, CurrentQuizService, QuizApiService, LobbyApiService],
(router: Router,
currentQuizService: CurrentQuizService,
quizApiService: QuizApiService,
lobbyApiService: LobbyApiService,
) => {
const customQuiz = currentQuizService.quiz;
customQuiz.sessionConfig.nicks.memberGroups = ['Group1', 'Group2'];
const quizStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
authorizeViaCas: true,
provideNickSelection: false,
},
};
const lobbyStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
quiz: {
originalObject: customQuiz.serialize(),
it('should redirect the user to the membergroup selection if there are multiple groups available', async(
inject([Router, CurrentQuizService, QuizApiService, LobbyApiService],
(router: Router, currentQuizService: CurrentQuizService, quizApiService: QuizApiService, lobbyApiService: LobbyApiService) => {
const customQuiz = currentQuizService.quiz;
customQuiz.sessionConfig.nicks.memberGroups = ['Group1', 'Group2'];
const quizStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
authorizeViaCas: true,
provideNickSelection: false,
},
},
};
};
const lobbyStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
quiz: {
originalObject: customQuiz.serialize(),
},
},
};
spyOn(quizApiService, 'getQuizStatus').and.returnValue(of(quizStatusData));
spyOn(lobbyApiService, 'getLobbyStatus').and.returnValue(of(lobbyStatusData));
spyOn(router, 'navigate').and.callFake(() => {});
spyOn(quizApiService, 'getQuizStatus').and.returnValue(of(quizStatusData));
spyOn(lobbyApiService, 'getLobbyStatus').and.returnValue(of(lobbyStatusData));
spyOn(router, 'navigate').and.callFake(() => {});
component.ngOnInit();
expect(router.navigate).toHaveBeenCalledWith(['/nicks', 'memberGroup']);
})));
component.ngOnInit();
expect(router.navigate).toHaveBeenCalledWith(['/nicks', 'memberGroup']);
})));
it('should redirect the user to input the nickname if no predefined nicks are available', async(inject(
[CurrentQuizService, Router, QuizApiService, LobbyApiService],
(currentQuizService: CurrentQuizService,
router: Router,
quizApiService: QuizApiService,
lobbyApiService: LobbyApiService,
) => {
const quizStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
authorizeViaCas: true,
provideNickSelection: false,
},
};
const lobbyStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
quiz: {
originalObject: currentQuizService.quiz.serialize(),
it('should redirect the user to input the nickname if no predefined nicks are available', async(
inject([CurrentQuizService, Router, QuizApiService, LobbyApiService],
(currentQuizService: CurrentQuizService, router: Router, quizApiService: QuizApiService, lobbyApiService: LobbyApiService) => {
const quizStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
authorizeViaCas: true,
provideNickSelection: false,
},
},
};
};
const lobbyStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
quiz: {
originalObject: currentQuizService.quiz.serialize(),
},
},
};
spyOn(quizApiService, 'getQuizStatus').and.returnValue(of(quizStatusData));
spyOn(lobbyApiService, 'getLobbyStatus').and.returnValue(of(lobbyStatusData));
spyOn(router, 'navigate').and.callFake(() => {});
spyOn(quizApiService, 'getQuizStatus').and.returnValue(of(quizStatusData));
spyOn(lobbyApiService, 'getLobbyStatus').and.returnValue(of(lobbyStatusData));
spyOn(router, 'navigate').and.callFake(() => {});
component.ngOnInit();
expect(router.navigate).toHaveBeenCalledWith(['/nicks', 'input']);
})));
component.ngOnInit();
expect(router.navigate).toHaveBeenCalledWith(['/nicks', 'input']);
})));
it('should redirect the user to the nickname selection if predefined nicks are available', async(inject(
[CurrentQuizService, Router, QuizApiService, LobbyApiService],
(currentQuizService: CurrentQuizService,
router: Router,
quizApiService: QuizApiService,
lobbyApiService: LobbyApiService,
) => {
it('should redirect the user to the nickname selection if predefined nicks are available', async(
inject([CurrentQuizService, Router, QuizApiService, LobbyApiService],
(currentQuizService: CurrentQuizService, router: Router, quizApiService: QuizApiService, lobbyApiService: LobbyApiService) => {
const customQuiz = currentQuizService.quiz;
customQuiz.sessionConfig.nicks.addSelectedNick('Predefined1');
customQuiz.sessionConfig.nicks.addSelectedNick('Predefined2');
const quizStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
authorizeViaCas: true,
provideNickSelection: true,
},
};
const lobbyStatusData = {
status: 'STATUS:SUCCESSFUL',
step: 'QUIZ:AVAILABLE',
payload: {
quiz: {
originalObject: customQuiz.serialize(),
const customQuiz = currentQuizService.quiz;
customQuiz.sessionConfig.nicks.addSelectedNick('Predefined1');
customQuiz.sessionConfig.nicks.addSelectedNick('Predefined2');