diff options
Diffstat (limited to 'mod2/ui/src/app/comp-spec-validation')
4 files changed, 458 insertions, 0 deletions
diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.css b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.css new file mode 100644 index 0000000..d76e0fa --- /dev/null +++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.css @@ -0,0 +1,73 @@ +/* + * # ============LICENSE_START======================================================= + * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * # ================================================================================ + * # Licensed under the Apache License, Version 2.0 (the "License"); + * # you may not use this file except in compliance with the License. + * # You may obtain a copy of the License at + * # + * # http://www.apache.org/licenses/LICENSE-2.0 + * # + * # Unless required by applicable law or agreed to in writing, software + * # distributed under the License is distributed on an "AS IS" BASIS, + * # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * # See the License for the specific language governing permissions and + * # limitations under the License. + * # ============LICENSE_END========================================================= + */ + +.validator-input-card{ + width: 40%; + min-width: 430px; + min-height: 100%; + border: 2px solid slategray; + border-radius: 5px; + background-color: white; + padding: 1%; +} +.validator-output-card{ + width: 58%; + border: 2px solid slategray; + margin-left: 2%; + min-height: 100%; + border-radius: 5px; + background-color: white; + padding: 1%; +} + +.input-section-card{ + font-size: 14px; + border: solid slategray; + border-style: double; + margin-top: 7px +} + +.validateSpec{ + margin-top: 10px; +} +.downloadSchema{ + margin-top: 80px; +} + +.type-selection{ + position: absolute; + background-color: rgba(128, 128, 128, 0.15); + width: 190px; + height: 40px; + display: inline-flex; + align-items: center; + margin-left: 150px; +} + +.greenOutput{ + background-color: rgba(0, 255, 0, 0.205); + height: 40px; + padding: 3px; + border: 2px solid rgba(0, 66, 0, 0.747); +} +.redOutput{ + background-color: rgba(255, 0, 0, 0.267); + height: 87%; + padding: 10px; + border: 2px solid rgba(65, 0, 0, 0.712); +} diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.html b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.html new file mode 100644 index 0000000..9867364 --- /dev/null +++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.html @@ -0,0 +1,108 @@ +<!-- + # ============LICENSE_START======================================================= + # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + # ================================================================================ + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # ============LICENSE_END========================================================= + --> + +<div style="margin-left: 2%; margin-right: 2%;"> + <p style="font-size: 26px;">Component Specification Validation</p> + <div style="display: inline-flex; width: 100%; height: 100%; min-height: 450px;"> + <div class="validator-input-card"> + <div> + <mat-card class="input-section-card"> + <span><b>Action</b></span><span style="color:red">*</span><br> + <div style="display: inline-flex;"> + <div style="padding-right: 10%; width: 200px;"> + <p-radioButton name="spec-validator-actions" value="validateSpec" [(ngModel)]="spec_validator_action" (click)="validateRadioButton()"></p-radioButton> Validate Spec File + </div> + <div> + <p-radioButton name="spec-validator-actions" value="downloadSchema" [(ngModel)]="spec_validator_action" (click)="downloadRadioButton()"></p-radioButton> Download Schema + </div> + </div> + </mat-card> + + <mat-card class="input-section-card"> + <span><b>Release</b></span><span style="color:red">*</span><br> + <div> + <div style="display: inline-flex; align-items: center;"> + <p-radioButton name="spec-validator-release" value="2007" [(ngModel)]="release"></p-radioButton> 2007+ + </div> + </div> + </mat-card> + + <mat-card class="input-section-card"> + <span><b>Type</b></span><span style="color:red">*</span><br> + <div> + <div style="display: inline-flex; align-items: center;"> + <p-radioButton name="spec-validator-type" value="k8s" [(ngModel)]="type"></p-radioButton> K8s + </div> + <br> + <div style="display: inline-flex; align-items: center;"> + <p-radioButton name="spec-validator-type" value="docker" [(ngModel)]="type"></p-radioButton> Docker + </div> + </div> + </mat-card> + + <mat-card *ngIf="spec_validator_action === 'validateSpec'" class="input-section-card"> + <!-- * * * Comp Spec File Select * * * --> + <div> + <b>Component Spec File</b><span style="color:red">*</span><br> + + <div style="display: inline-flex;"> + <input #myFile type="file" style="color:blue; font-style: italic; width: fit-content" + (input)="onCompSpecUpload($event)" name="myfile" accept=".json"> + + <button pButton type="button" (click)="resetFile()" + style="background-color: transparent; border: none; height: 20px;"><i class="pi pi-times" + style="color: black;"></i></button> + </div> + </div> + </mat-card> + + <div> + <div *ngIf="shouldValidate" style="background-color: rgba(128, 128, 128, 0.315); height: 2px; width: 100%; margin-top: 2%;"></div> + <div *ngIf="shouldDownload" style="background-color: rgba(128, 128, 128, 0.315); height: 2px; width: 100%; margin-top: 22%;"></div> + + <div style="float: right; margin-top: 8px"> + <div *ngIf="shouldValidate" matTooltip="Fill In Required Fields" [matTooltipDisabled]="!(release === '' || type === '' || compSpecContent === null)" matTooltipPosition="above"> + <button [disabled]="release === '' || type === '' || compSpecContent === null" pButton label="Validate Spec" type="button" (click)="validateSpec()"></button> + </div> + <div *ngIf="shouldDownload" matTooltip="Fill In Required Fields" [matTooltipDisabled]="!(release === '' || type === '')" matTooltipPosition="above"> + <button [disabled]="release === '' || type === ''" pButton label="Download Schema" type="button" (click)="downloadSchema()"></button> + </div> + </div> + </div> + </div> + </div> + + <div *ngIf="shouldValidate" class="validator-output-card"> + <span><b>Output:</b></span><br><br> + <div *ngIf="specValidated" style="width: 100%; padding: 1%; border-radius: 3px; overflow: hidden;" [ngClass]="{'greenOutput' : validCompSpec === true, 'redOutput' : validCompSpec === false}"> + <div> + <span style="font-weight: 500;">{{specValidationOutputHeader}}</span> + <div *ngIf="specValidationOutputMessage !== ''" style="margin-top: 10px; width: 100%; height: 2px; background-color: rgba(128, 128, 128, 0.315); "></div> + + <div *ngIf="specValidationOutputMessage !== ''" style="margin-top: 10px"> + <p-scrollPanel [style]="{width: '100%', height: '50vh'}"> + <pre style="white-space: pre-wrap;"><b>Summary:</b><br>{{specValidationOutputSummary}}</pre> + <pre style="white-space: pre-wrap;"><b>Message(s):</b><br>{{specValidationOutputMessage}}</pre> + </p-scrollPanel> + </div> + + </div> + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.spec.ts b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.spec.ts new file mode 100644 index 0000000..a9efe28 --- /dev/null +++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.spec.ts @@ -0,0 +1,132 @@ +/* + * # ============LICENSE_START======================================================= + * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * # ================================================================================ + * # Licensed under the Apache License, Version 2.0 (the "License"); + * # you may not use this file except in compliance with the License. + * # You may obtain a copy of the License at + * # + * # http://www.apache.org/licenses/LICENSE-2.0 + * # + * # Unless required by applicable law or agreed to in writing, software + * # distributed under the License is distributed on an "AS IS" BASIS, + * # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * # See the License for the specific language governing permissions and + * # limitations under the License. + * # ============LICENSE_END========================================================= + */ + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { RadioButtonModule } from 'primeng/radiobutton'; + +import { CompSpecValidationComponent } from './comp-spec-validation.component'; +import { FormsModule } from '@angular/forms'; +import { MatCardModule, MatTooltipModule } from '@angular/material'; +import { ScrollPanelModule } from 'primeng/scrollpanel'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { MessageService } from 'primeng/api'; +import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt'; +import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner'; + +describe('CompSpecValidationComponent', () => { + let component: CompSpecValidationComponent; + let fixture: ComponentFixture<CompSpecValidationComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CompSpecValidationComponent ], + imports: [ + RadioButtonModule, + FormsModule, + MatCardModule, + MatTooltipModule, + ScrollPanelModule, + HttpClientTestingModule, + Ng4LoadingSpinnerModule + ], + providers: [ + MessageService, + { provide: JWT_OPTIONS, useValue: JWT_OPTIONS }, + JwtHelperService + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CompSpecValidationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it(`should have as shouldValidate 'false'`, () => { + const fixture = TestBed.createComponent(CompSpecValidationComponent); + const app = fixture.debugElement.componentInstance; + expect(app.shouldValidate).toEqual(false); + }); + + it(`should change shouldValidate to 'true'`, async(() => { + const fixture = TestBed.createComponent(CompSpecValidationComponent); + const app = fixture.debugElement.componentInstance; + app.validateRadioButton() + fixture.detectChanges(); + expect(app.shouldValidate).toEqual(true); + })); + + it(`should have as shouldDownload 'false'`, () => { + const fixture = TestBed.createComponent(CompSpecValidationComponent); + const app = fixture.debugElement.componentInstance; + expect(app.shouldDownload).toEqual(false); + }); + + it(`should change shouldDownload to 'true'`, async(() => { + const fixture = TestBed.createComponent(CompSpecValidationComponent); + const app = fixture.debugElement.componentInstance; + app.downloadRadioButton() + fixture.detectChanges(); + expect(app.shouldDownload).toEqual(true); + })); + + it(`should set validation error message`, async(() => { + const fixture = TestBed.createComponent(CompSpecValidationComponent); + const app = fixture.debugElement.componentInstance; + let mockSuccess = { + status: 200 + } + app.setSpecValidationMessage(mockSuccess) + fixture.detectChanges(); + expect(app.validCompSpec).toEqual(true) + })); + + it(`should set validation error message`, async(() => { + const fixture = TestBed.createComponent(CompSpecValidationComponent); + const app = fixture.debugElement.componentInstance; + + let mockError = { + status: 400, + error: { + summary: 'Test', + errors: [ + 'error1', + 'error2' + ] + } + } + app.setSpecValidationMessage(mockError) + fixture.detectChanges(); + expect(app.validCompSpec).toEqual(false) + })); + + it(`should invalidate JSON structure`, async(() => { + const fixture = TestBed.createComponent(CompSpecValidationComponent); + const app = fixture.debugElement.componentInstance; + let mockErrorJson = "test: 'test}" + app.compSpecContent = mockErrorJson + expect(() => app.validateJsonStructure()).toThrowError('JSON Structure error, quit!') + })); + +}); diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.ts b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.ts new file mode 100644 index 0000000..2ce8fef --- /dev/null +++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.ts @@ -0,0 +1,145 @@ +/* + * # ============LICENSE_START======================================================= + * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * # ================================================================================ + * # Licensed under the Apache License, Version 2.0 (the "License"); + * # you may not use this file except in compliance with the License. + * # You may obtain a copy of the License at + * # + * # http://www.apache.org/licenses/LICENSE-2.0 + * # + * # Unless required by applicable law or agreed to in writing, software + * # distributed under the License is distributed on an "AS IS" BASIS, + * # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * # See the License for the specific language governing permissions and + * # limitations under the License. + * # ============LICENSE_END========================================================= + */ + +import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; +import { SpecValidationService } from '../services/spec-validation.service'; +import { DownloadService } from '../services/download.service'; +import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner'; + +@Component({ + selector: 'app-comp-spec-validation', + templateUrl: './comp-spec-validation.component.html', + styleUrls: ['./comp-spec-validation.component.css'] +}) +export class CompSpecValidationComponent implements OnInit { + + @ViewChild('myFile', {static: false}) + myInputVariable: ElementRef; + + spec_validator_action; + release = ''; + type = ''; + shouldValidate = false; + shouldDownload = false; + validCompSpec = false; + specValidated = false; + specValidationOutputSummary: any; + + constructor(private specValidator: SpecValidationService, private downloadService: DownloadService, private spinnerService: Ng4LoadingSpinnerService ) { } + + ngOnInit() { + + } + + compSpecSelected: any; + onCompSpecUpload(event){ + this.compSpecSelected = event.target.files[0]; + this.readCsFileContent(this.compSpecSelected); + } + + compSpecContent: any = null; + readCsFileContent(file) { + if (file) { + let fileReader = new FileReader(); + fileReader.onload = (e) => { this.compSpecContent = fileReader.result; }; + fileReader.readAsText(file); + } + } + + validateRadioButton(){ + this.shouldValidate = true; + this.shouldDownload = false; + } + + downloadRadioButton(){ + this.shouldValidate = false; + this.shouldDownload = true; + this.compSpecContent = null; + this.specValidated = false + } + + resetFile(){ + this.myInputVariable.nativeElement.value = ""; + this.compSpecContent = null + this.compSpecSelected = null + this.specValidated = false + } + + specValidationOutputHeader = '' + specValidationOutputMessage = ''; + validateSpec(){ + this.specValidationOutputHeader = "" + this.specValidationOutputMessage = "" + this.specValidationOutputSummary = "" + + this.spinnerService.show() + this.validateJsonStructure() + this.specValidator.sendSpecFile(this.compSpecContent, this.type, this.release).subscribe( + res => {}, err => { + this.setSpecValidationMessage(err) + } + ) + } + + setSpecValidationMessage(res){ + if(res.status === 200){ + this.specValidationOutputHeader = "Success: Valid Component Spec" + this.specValidationOutputMessage = "" + this.validCompSpec = true + } else { + this.specValidationOutputHeader = `${res.status} Error: Invalid Component Spec` + this.specValidationOutputSummary = res.error.summary + + for(let item of res.error.errors){ + this.specValidationOutputMessage += `- ${item}\n\n` + } + + this.validCompSpec = false + } + + this.specValidated = true; + this.spinnerService.hide() + } + + validateJsonStructure() { + try { + JSON.parse(this.compSpecContent); + } catch (error) { + this.specValidationOutputHeader = "Error: Invalid Component Spec" + this.specValidationOutputSummary = "JSON Structure Error" + this.specValidationOutputMessage = error + this.validCompSpec = false + this.specValidated = true + this.spinnerService.hide() + throw new Error('JSON Structure error, quit!'); + } + } + + downloadSchema(){ + this.spinnerService.show() + this.specValidator.getSchema(this.type).subscribe( + res => { + this.downloadService.downloadJSON(res, `${this.release}+_${this.type}_Schema`) + this.spinnerService.hide() + }, err => { + console.log(err) + this.spinnerService.hide() + } + ) + } +} |