#59 added unit tests for the new trigger

This commit is contained in:
Fabio Formosa
2022-08-31 23:46:53 +02:00
parent f1c9fba68e
commit b4bb16130c
9 changed files with 274 additions and 47 deletions

View File

@@ -3,16 +3,7 @@
<mat-card-subtitle><b>TRIGGER DETAILS</b></mat-card-subtitle>
</mat-card-header>
<!-- ADD BUTTON -->
<mat-card-content *ngIf="!existsATriggerInProgress() && !enabledTriggerForm">
<button mat-fab color="primary">
<mat-icon (click)="enableTriggerForm()">add</mat-icon>
</button>
</mat-card-content>
<!-- TRIGGER DETAILS -->
<mat-card-content *ngIf="existsATriggerInProgress() || enabledTriggerForm">
<mat-card-content *ngIf="shouldShowTheTriggerCardContent()">
<div fxLayout="column">
<form name="configForm" fxFlex="1 1 100%" #configForm="ngForm">
@@ -82,7 +73,7 @@
<button mat-raised-button
type="button"
*ngIf="enabledTriggerForm"
*ngIf="enabledTriggerForm && !_newTriggerRequired"
(click)="cancelConfigForm()">
Cancel
</button>

View File

@@ -0,0 +1,80 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {MatCardModule} from '@angular/material/card';
import {SimpleTriggerConfigComponent} from './simple-trigger-config.component';
import {ApiService, ConfigService, SchedulerService} from '../../services';
import {HttpClient} from '@angular/common/http';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {DebugElement, NO_ERRORS_SCHEMA} from '@angular/core';
import {By} from '@angular/platform-browser';
import {RouterTestingModule} from '@angular/router/testing';
import {MatIconModule} from '@angular/material/icon';
import {FormsModule} from '@angular/forms';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatNativeDateModule} from '@angular/material/core';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatInputModule} from '@angular/material/input';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {TriggerKey} from '../../model/triggerKey.model';
import {Trigger} from '../../model/trigger.model';
import {NgxMatDatetimePickerModule} from '@angular-material-components/datetime-picker';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
describe('SimpleTriggerConfig', () => {
let component: SimpleTriggerConfigComponent;
let fixture: ComponentFixture<SimpleTriggerConfigComponent>;
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
beforeEach(async( () => {
TestBed.configureTestingModule({
imports: [FormsModule, MatFormFieldModule, MatFormFieldModule, MatInputModule, BrowserAnimationsModule,
MatNativeDateModule,
MatCardModule, MatIconModule, HttpClientTestingModule, RouterTestingModule],
declarations: [SimpleTriggerConfigComponent],
providers: [SchedulerService, ApiService, ConfigService],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
httpClient = TestBed.inject(HttpClient);
httpTestingController = TestBed.inject(HttpTestingController);
}));
beforeEach(() => {
fixture = TestBed.createComponent(SimpleTriggerConfigComponent);
component = fixture.componentInstance;
});
it('should fetch no triggers at the init', () => {
expect(component).toBeTruthy();
httpTestingController.expectNone('/quartz-manager/simple-triggers/my-simple-trigger');
});
it('should fetch and display the trigger when the triggerKey is passed as input', () => {
const mockTriggerKey = new TriggerKey('my-simple-trigger', null);
component.triggerKey = mockTriggerKey;
fixture.detectChanges();
const mockTrigger = new Trigger();
mockTrigger.triggerKeyDTO = mockTriggerKey;
const getSimpleTriggerReq = httpTestingController.expectOne('/quartz-manager/simple-triggers/my-simple-trigger');
getSimpleTriggerReq.flush(mockTrigger);
const componentDe: DebugElement = fixture.debugElement;
const submitButton = componentDe.query(By.css('form > button'));
expect(submitButton.nativeElement.textContent.trim()).toEqual('Reschedule');
});
it('should get display the form if the openTriggerForm method is called', () => {
component.openTriggerForm();
fixture.detectChanges();
const componentDe: DebugElement = fixture.debugElement;
const submitButton = componentDe.query(By.css('form > button[color="primary"]'));
expect(submitButton.nativeElement.textContent.trim()).toEqual('Submit');
});
});

View File

@@ -1,10 +1,11 @@
import {Component, OnInit} from '@angular/core';
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {SchedulerService} from '../../services';
import {Scheduler} from '../../model/scheduler.model';
import {SimpleTriggerCommand} from '../../model/simple-trigger.command';
import {SimpleTrigger} from '../../model/simple-trigger.model';
import {SimpleTriggerForm} from '../../model/simple-trigger.form';
import * as moment from 'moment';
import {TriggerKey} from '../../model/triggerKey.model';
@Component({
selector: 'qrzmng-simple-trigger-config',
@@ -20,31 +21,53 @@ export class SimpleTriggerConfigComponent implements OnInit {
scheduler: Scheduler;
triggerLoading = true;
enabledTriggerForm = false;
private fetchedTriggers = false;
private triggerInProgress = false;
private selectedTriggerKey: TriggerKey;
enabledTriggerForm = false;
@Output()
onNewTrigger = new EventEmitter<SimpleTrigger>();
constructor(
private schedulerService: SchedulerService
) { }
ngOnInit() {
this.triggerLoading = true;
this.retrieveConfiguredTriggerIfExists();
}
retrieveConfiguredTriggerIfExists = () => {
this.schedulerService.getSimpleTriggerConfig()
openTriggerForm() {
this.enabledTriggerForm = true;
}
private closeTriggerForm() {
this.enabledTriggerForm = false;
}
@Input()
set triggerKey(triggerKey: TriggerKey){
this.selectedTriggerKey = {...triggerKey} as TriggerKey;
this.fetchSelectedTrigger();
}
fetchSelectedTrigger = () => {
this.triggerLoading = true;
this.schedulerService.getSimpleTriggerConfig(this.selectedTriggerKey.name)
.subscribe((retTrigger: SimpleTrigger) => {
this.trigger = retTrigger;
this.formBackup = this.simpleTriggerForm;
this.simpleTriggerForm = this._fromTriggerToForm(retTrigger);
this.triggerLoading = false;
this.triggerInProgress = this.trigger.mayFireAgain;
})
}
shouldShowTheTriggerCardContent = (): boolean => this.trigger !== null || this.enabledTriggerForm;
existsATriggerInProgress = (): boolean => this.trigger && this.triggerInProgress;
cancelConfigForm = () => this.enabledTriggerForm = false;
@@ -59,25 +82,16 @@ export class SimpleTriggerConfigComponent implements OnInit {
this.trigger = retTrigger;
this.formBackup = this.simpleTriggerForm;
this.simpleTriggerForm = this._fromTriggerToForm(retTrigger);
this.enabledTriggerForm = false;
this.fetchedTriggers = true;
this.triggerInProgress = this.trigger.mayFireAgain;
this.onNewTrigger.emit(retTrigger);
this.closeTriggerForm();
}, error => {
this.simpleTriggerForm = this.formBackup;
});
};
enableTriggerForm = () => this.enabledTriggerForm = true;
private _fromTriggerToCommand = (simpleTrigger: SimpleTrigger) => {
const command = new SimpleTriggerCommand();
command.repeatCount = simpleTrigger.repeatCount;
command.repeatInterval = simpleTrigger.repeatInterval;
command.startDate = simpleTrigger.startTime;
command.endDate = simpleTrigger.endTime;
return command;
}
private _fromTriggerToForm = (simpleTrigger: SimpleTrigger): SimpleTriggerForm => {
const command = new SimpleTriggerForm();
command.repeatCount = simpleTrigger.repeatCount;

View File

@@ -1,14 +1,14 @@
<mat-card fxFlex="1 1 auto" style="padding-left: 0; padding-right: 0">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between none" style="padding-right: 1em;" >
<mat-card-subtitle><b>TRIGGERS</b></mat-card-subtitle>
<button mat-raised-button style="top: -0.5em" color="primary" (click)="openNewTriggerForm()">
<button *ngIf="!triggerFormIsOpen" mat-raised-button style="top: -0.5em" color="primary" (click)="onNewTriggerBtnClicked()">
new
</button>
</mat-card-header>
<mat-divider></mat-divider>
<mat-card-content style="position: relative; height: 100%">
<mat-nav-list style="overflow-y: auto; position: absolute; left: 0; right: 0; top: 0; bottom: 0; overflow: auto; height: calc(100% - 3em)">
<mat-list-item *ngFor="let triggerKey of triggerKeys">
<mat-list-item *ngFor="let triggerKey of getTriggerKeyList()" class="triggerItemList">
<a matLine href="...">{{ triggerKey.name }}</a>
<!-- <button mat-icon-button (click)="showInfo(link)">-->
<!-- <mat-icon>info</mat-icon>-->

View File

@@ -0,0 +1,84 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {ApiService, ConfigService, TriggerService} from '../../services';
import {HttpClient} from '@angular/common/http';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {RouterTestingModule} from '@angular/router/testing';
import {DebugElement} from '@angular/core';
import {By} from '@angular/platform-browser';
import {MatCardModule} from '@angular/material/card';
import {MatIconModule} from '@angular/material/icon';
import {MatDividerModule} from '@angular/material/divider';
import {TriggerListComponent} from './trigger-list.component';
import {MatListModule} from '@angular/material/list';
import {TriggerKey} from '../../model/triggerKey.model';
describe('TriggerListComponent', () => {
let component: TriggerListComponent;
let fixture: ComponentFixture<TriggerListComponent>;
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MatCardModule, MatDividerModule, MatIconModule, MatListModule, HttpClientTestingModule, RouterTestingModule],
declarations: [TriggerListComponent],
providers: [TriggerService, ApiService, ConfigService]
}).compileComponents();
httpClient = TestBed.inject(HttpClient);
httpTestingController = TestBed.inject(HttpTestingController);
}));
beforeEach(() => {
fixture = TestBed.createComponent(TriggerListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should select the first trigger of the list', () => {
expect(component).toBeDefined();
let actualSelectedTrigger: TriggerKey;
component.onSelectedTrigger.subscribe(selectedTrigger => actualSelectedTrigger = selectedTrigger);
const getTriggerListReq = httpTestingController.expectOne('quartz-manager/triggers');
const mockExistingTriggers = new Array<TriggerKey>();
const firstTriggerKey = new TriggerKey('trigger1', 'group1');
mockExistingTriggers.push(firstTriggerKey);
const secondTriggerKey = new TriggerKey('trigger2', 'group2');
mockExistingTriggers.push(secondTriggerKey);
getTriggerListReq.flush(mockExistingTriggers);
fixture.detectChanges();
const triggerListComponentDe: DebugElement = fixture.debugElement;
const triggerItemList = triggerListComponentDe.queryAll(By.css('.triggerItemList'));
expect(triggerItemList.length).toEqual(2);
expect(actualSelectedTrigger).toEqual(firstTriggerKey);
});
it('should open the trigger form if the trigger list is empty', () => {
expect(component).toBeDefined();
let actualSelectedTrigger: TriggerKey;
component.onSelectedTrigger.subscribe(selectedTrigger => actualSelectedTrigger = selectedTrigger);
let expectedOpenedNewTriggerFormEvent: boolean;
component.onNewTriggerClicked.subscribe(() => expectedOpenedNewTriggerFormEvent = true);
const getTriggerListReq = httpTestingController.expectOne('quartz-manager/triggers');
getTriggerListReq.flush(new Array<TriggerKey>());
fixture.detectChanges();
const triggerListComponentDe: DebugElement = fixture.debugElement;
const triggerItemList = triggerListComponentDe.queryAll(By.css('.triggerItemList'));
expect(triggerItemList.length).toEqual(0);
expect(expectedOpenedNewTriggerFormEvent).toBeTruthy();
expect(actualSelectedTrigger).toBeUndefined();
});
});

View File

@@ -1,6 +1,7 @@
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {TriggerService} from '../../services/trigger.service';
import {TriggerKey} from '../../model/triggerKey.model';
import {SimpleTrigger} from '../../model/simple-trigger.model';
@Component({
selector: 'qrzmng-trigger-list',
@@ -9,10 +10,18 @@ import {TriggerKey} from '../../model/triggerKey.model';
})
export class TriggerListComponent implements OnInit {
loading = true;
triggerKeys: Array<TriggerKey> = [];
@Input()
newTriggers: Array<SimpleTrigger> = new Array<SimpleTrigger>();
@Output() openedNewTriggerFormEvent = new EventEmitter<boolean>();
loading = true;
triggerKeys: Array<TriggerKey> = new Array<TriggerKey>();
@Output() onNewTriggerClicked = new EventEmitter<void>();
triggerFormIsOpen = false;
selectedTrigger: TriggerKey;
@Output() onSelectedTrigger = new EventEmitter<TriggerKey>();
constructor(
private triggerService: TriggerService
@@ -23,14 +32,35 @@ export class TriggerListComponent implements OnInit {
this.fetchTriggers();
}
@Input()
set openedNewTriggerForm(triggerFormIsOpen: boolean){
this.triggerFormIsOpen = triggerFormIsOpen;
}
getTriggerKeyList = () => {
const newTriggerKeys = this.newTriggers.map(simpleTrigger => simpleTrigger.triggerKeyDTO);
return newTriggerKeys.concat(this.triggerKeys);
}
private fetchTriggers() {
this.triggerService.fetchTriggers()
.subscribe((triggerKeys: Array<TriggerKey>) => {
this.triggerKeys = triggerKeys;
if (!triggerKeys || triggerKeys.length === 0) {
this.onNewTriggerBtnClicked();
}
else {
this.selectTrigger(this.triggerKeys[0]);
}
})
}
openNewTriggerForm() {
this.openedNewTriggerFormEvent.emit(true);
selectTrigger(triggerKey: TriggerKey) {
this.selectedTrigger = triggerKey;
this.onSelectedTrigger.emit(triggerKey);
}
onNewTriggerBtnClicked() {
this.onNewTriggerClicked.emit();
}
}

View File

@@ -43,8 +43,8 @@ export class SchedulerService {
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler/config')
}
getSimpleTriggerConfig = (): Observable<Trigger> => {
return this.apiService.get(getBaseUrl() + '/quartz-manager/simple-triggers/my-simple-trigger');
getSimpleTriggerConfig = (triggerName: string): Observable<Trigger> => {
return this.apiService.get(getBaseUrl() + `/quartz-manager/simple-triggers/${triggerName}`);
}
// deprecated

View File

@@ -1,6 +1,6 @@
<div id="managerViewContainer" class="contenttt" fxLayout="column" fxLayoutAlign="left stretch" fxLayoutGap="10px" fxFill>
<div id="managerViewContainer" fxLayout="column" fxLayoutAlign="left stretch" fxLayoutGap="10px" fxFill>
<div id="schedulerBarContainer" class="contentttt" fxLayout="column" fxLayoutAlign="left stretch">
<div id="schedulerBarContainer" fxLayout="column" fxLayoutAlign="left stretch">
<qrzmng-scheduler-control></qrzmng-scheduler-control>
</div>
@@ -8,13 +8,21 @@
<div fxFlex="0 0 300px">
<div fxLayout="row" fxLayoutAlign="stretch" fxFill>
<qrzmng-trigger-list (openedNewTriggerFormEvent)="setnewTriggerFormOpened($event)" fxFill></qrzmng-trigger-list>
<qrzmng-trigger-list
[newTriggers]="newTriggers"
(onNewTriggerClicked)="onNewTriggerRequested()"
[openedNewTriggerForm]="newTriggerFormOpened"
(onSelectedTrigger)="setSelectedTrigger($event)"
fxFill></qrzmng-trigger-list>
</div>
</div>
<div fxFlex="1 1 500px" >
<div fxLayout="column">
<qrzmng-simple-trigger-config></qrzmng-simple-trigger-config>
<qrzmng-simple-trigger-config
[triggerKey]="selectedTriggerKey"
(onNewTrigger)="onNewTrigger($event)">
</qrzmng-simple-trigger-config>
</div>
</div>

View File

@@ -1,8 +1,11 @@
import { Component, OnInit } from '@angular/core';
import {Component, OnInit, ViewChild} from '@angular/core';
import {
ConfigService,
UserService
} from '../../services';
import {SimpleTrigger} from '../../model/simple-trigger.model';
import {TriggerKey} from '../../model/triggerKey.model';
import {SimpleTriggerConfigComponent} from '../../components/simple-trigger-config';
@Component({
selector: 'manager',
@@ -11,8 +14,14 @@ import {
})
export class ManagerComponent implements OnInit {
@ViewChild(SimpleTriggerConfigComponent)
private triggerConfigComponent!: SimpleTriggerConfigComponent;
newTriggerFormOpened = false;
newTriggers = new Array<SimpleTrigger>();
selectedTriggerKey: TriggerKey;
constructor(
private config: ConfigService,
private userService: UserService
@@ -21,8 +30,19 @@ export class ManagerComponent implements OnInit {
ngOnInit() {
}
setnewTriggerFormOpened(opened: boolean){
this.newTriggerFormOpened = opened;
onNewTriggerRequested() {
this.triggerConfigComponent.openTriggerForm();
}
onNewTrigger(newTrigger: SimpleTrigger) {
this.newTriggers.push(newTrigger);
}
setSelectedTrigger(triggerKey: TriggerKey) {
this.selectedTriggerKey = triggerKey;
}
onTriggerFormToggled(formOpened: boolean) {
this.newTriggerFormOpened = formOpened;
}
}