Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Melodic
melodic-frontend
Commits
57c0af12
Commit
57c0af12
authored
Jul 08, 2020
by
Maria C
Committed by
Alicja Reniewicz
Jul 08, 2020
Browse files
Add Serverless Testing view
parent
77c3c5df
Changes
18
Hide whitespace changes
Inline
Side-by-side
src/app/app-routing.module.ts
View file @
57c0af12
...
...
@@ -35,6 +35,11 @@ const routes: Routes = [
canActivate
:
[
CommonUserAdminRoleGuard
]
},
{
path
:
'
serverless-testing
'
,
loadChildren
:
'
./serverless-testing/serverless-testing.module#ServerlessTestingModule
'
,
canActivate
:
[
CommonUserAdminRoleGuard
]
},
{
path
:
'
**
'
,
loadChildren
:
'
./user/user.module#UserModule
'
},
];
...
...
src/app/common-template/menu/menu.component.html
View file @
57c0af12
...
...
@@ -29,6 +29,7 @@
<a
mat-list-item
routerLink=
"/process/details/offer"
><i
class=
"material-icons"
>
local_offer
</i>
Offers
</a>
<a
mat-list-item
routerLink=
"/simulation"
><i
class=
"material-icons"
>
toys
</i>
Simulation
</a>
<a
mat-list-item
routerLink=
"/serverless-testing"
><i
class=
"material-icons"
>
cloud_done
</i>
Serverless Testing
</a>
<a
*ngIf=
"isAdmin()"
mat-list-item
routerLink=
"/user"
><i
class=
"material-icons"
>
supervisor_account
</i>
Manage Users
</a>
<a
mat-list-item
routerLink=
"/user/password"
><i
class=
"material-icons"
>
visibility
</i>
Change Password
</a>
<a
mat-list-item
(click)=
"onLogOutClick(); snav.close()"
><i
class=
"material-icons"
>
eject
</i>
Log Out
</a>
...
...
src/app/serverless-testing/model/TestResultTree.ts
0 → 100644
View file @
57c0af12
class
TestCaseResult
{
event
:
string
;
expectedOutput
:
string
;
actualOutput
:
string
;
message
:
string
;
result
:
string
;
duration
:
number
;
}
class
FunctionTestResult
{
functionName
:
string
;
duration
:
number
;
passed
:
number
;
failed
:
number
;
ignored
:
number
;
testCaseResults
:
Array
<
TestCaseResult
>
;
overallResult
:
string
;
failedAtStage
:
string
;
message
:
string
;
}
export
class
TestResultTree
{
testsRunResult
:
string
;
failedAtStage
:
string
;
message
:
string
;
duration
:
number
;
functionTestResults
:
Array
<
FunctionTestResult
>
;
}
src/app/serverless-testing/model/UploadYmlResponse.ts
0 → 100644
View file @
57c0af12
export
class
UploadYmlResponse
{
testConfigfilePath
:
string
;
}
src/app/serverless-testing/route/serverless-testing-routing.module.ts
0 → 100644
View file @
57c0af12
import
{
NgModule
}
from
'
@angular/core
'
;
import
{
RouterModule
,
Routes
}
from
'
@angular/router
'
;
import
{
ServerlessTestingMainComponent
}
from
'
../serverless-testing-main/serverless-testing-main.component
'
;
const
routes
:
Routes
=
[
{
path
:
''
,
component
:
ServerlessTestingMainComponent
},
];
@
NgModule
({
imports
:
[
RouterModule
.
forChild
(
routes
)],
exports
:
[
RouterModule
]
})
export
class
ServerlessTestingRoutingModule
{
}
src/app/serverless-testing/serverless-testing-main/serverless-testing-main.component.html
0 → 100644
View file @
57c0af12
<mat-card>
<mat-card-header>
<mat-card-title>
Test Serverless Functions
</mat-card-title>
<mat-card-subtitle>
Here you can test your serverless functions which have been deployed to the cloud.
Upload a test configuration file and then run the tests.
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<app-uploader-yml></app-uploader-yml>
<app-test-runner
[testsRunning]=
"testsRunning"
(runTestsEvent)=
"runTests()"
></app-test-runner>
<app-test-results
[results]=
"testResultTree"
></app-test-results>
</mat-card-content>
</mat-card>
src/app/serverless-testing/serverless-testing-main/serverless-testing-main.component.ts
0 → 100644
View file @
57c0af12
import
{
AfterViewInit
,
Component
,
OnDestroy
,
OnInit
,
ViewChild
}
from
'
@angular/core
'
;
import
{
UploaderYmlComponent
}
from
'
../uploader-yml/uploader-yml.component
'
;
import
{
MatSnackBar
}
from
'
@angular/material
'
;
import
{
ServerlessTestingService
}
from
'
../service/serverless-testing.service
'
;
import
{
TestRunnerComponent
}
from
'
../test-runner/test-runner.component
'
;
import
{
TestResultsComponent
}
from
'
../test-results/test-results.component
'
;
import
{
TestResultTree
}
from
'
../model/TestResultTree
'
;
@
Component
({
selector
:
'
app-serverless-testing
'
,
templateUrl
:
'
./serverless-testing-main.component.html
'
,
styleUrls
:
[
'
../../app.component.css
'
]
})
export
class
ServerlessTestingMainComponent
implements
OnInit
,
AfterViewInit
,
OnDestroy
{
@
ViewChild
(
UploaderYmlComponent
)
uploaderYmlComponent
:
UploaderYmlComponent
;
@
ViewChild
(
TestRunnerComponent
)
testRunnerComponent
:
TestRunnerComponent
;
@
ViewChild
(
TestResultsComponent
)
testResultsComponent
:
TestResultsComponent
;
testsRunning
=
false
;
testResultTree
:
TestResultTree
=
null
;
constructor
(
private
snackBar
:
MatSnackBar
,
private
testingServerlessService
:
ServerlessTestingService
,
)
{
}
ngOnInit
()
{
localStorage
.
setItem
(
'
viewTitle
'
,
'
Serverless Testing
'
);
console
.
log
(
'
Component Serverless-testing-main initiated
'
);
}
ngAfterViewInit
():
void
{
}
ngOnDestroy
():
void
{
console
.
log
(
'
Component Serverless-testing-main destroyed
'
);
}
runTests
()
{
this
.
testsRunning
=
true
;
this
.
testingServerlessService
.
runTests
().
subscribe
(
response
=>
{
this
.
snackBar
.
open
(
'
Tests run ended.
'
,
'
Close
'
,
{
duration
:
10000
});
this
.
testResultTree
=
response
;
this
.
testsRunning
=
false
;
},
error
=>
{
this
.
testsRunning
=
false
;
console
.
log
(
error
);
this
.
snackBar
.
open
(
`
${
error
.
error
.
message
}
`
,
'
Close
'
,
{
duration
:
10000
});
},
);
}
}
src/app/serverless-testing/serverless-testing.module.ts
0 → 100644
View file @
57c0af12
import
{
NgModule
}
from
'
@angular/core
'
;
import
{
CommonModule
}
from
'
@angular/common
'
;
import
{
ServerlessTestingMainComponent
}
from
'
./serverless-testing-main/serverless-testing-main.component
'
;
import
{
AngularMaterialModule
}
from
'
../angular-material/angular-material.module
'
;
import
{
ServerlessTestingRoutingModule
}
from
'
./route/serverless-testing-routing.module
'
;
import
{
UploaderYmlComponent
}
from
'
./uploader-yml/uploader-yml.component
'
;
import
{
TestRunnerComponent
}
from
'
./test-runner/test-runner.component
'
;
import
{
TestResultsComponent
}
from
'
./test-results/test-results.component
'
;
@
NgModule
({
declarations
:
[
ServerlessTestingMainComponent
,
UploaderYmlComponent
,
TestRunnerComponent
,
TestResultsComponent
,
],
imports
:
[
CommonModule
,
ServerlessTestingRoutingModule
,
AngularMaterialModule
],
exports
:
[
],
entryComponents
:
[
]
})
export
class
ServerlessTestingModule
{
}
src/app/serverless-testing/service/serverless-testing.service.ts
0 → 100644
View file @
57c0af12
import
{
Injectable
}
from
'
@angular/core
'
;
import
{
HttpClient
,
HttpHeaders
}
from
'
@angular/common/http
'
;
import
{
tap
}
from
'
rxjs/operators
'
;
import
{
Observable
}
from
'
rxjs
'
;
import
{
AppConfigService
}
from
'
../../app-config/service/app-config.service
'
;
import
{
UploadYmlResponse
}
from
'
../model/UploadYmlResponse
'
;
import
{
TestResultTree
}
from
'
../model/TestResultTree
'
;
@
Injectable
({
providedIn
:
'
root
'
})
export
class
ServerlessTestingService
{
apiUrl
=
`
${
AppConfigService
.
settings
.
apiUrl
}
/auth/test`
;
constructor
(
private
http
:
HttpClient
)
{
}
uploadTestConfiguration
(
formData
:
FormData
):
Observable
<
UploadYmlResponse
>
{
const
uploadUrl
=
this
.
apiUrl
+
'
/upload
'
;
return
this
.
http
.
post
(
uploadUrl
,
formData
,
{
responseType
:
'
json
'
}).
pipe
(
tap
(
(
response
:
UploadYmlResponse
)
=>
{
console
.
log
(
'
Response:
'
,
response
);
},
error
=>
{
console
.
log
(
'
Error while uploading test configuration file:
'
,
error
);
}
));
}
runTests
():
Observable
<
TestResultTree
>
{
const
requestUrl
=
this
.
apiUrl
+
'
/run
'
;
return
this
.
http
.
post
(
requestUrl
,
null
,
{
responseType
:
'
json
'
}).
pipe
(
tap
(
(
response
:
TestResultTree
)
=>
{
console
.
log
(
'
Response:
'
,
response
);
},
error
=>
{
console
.
log
(
'
Error while running tests:
'
,
error
);
}
));
}
}
src/app/serverless-testing/test-results/test-results.component.css
0 → 100644
View file @
57c0af12
div
{
padding-bottom
:
10px
;
}
pre
{
white-space
:
pre-wrap
;
}
src/app/serverless-testing/test-results/test-results.component.html
0 → 100644
View file @
57c0af12
<div
id=
"test-results-id"
>
<mat-card>
<mat-card-header>
<mat-card-title>
Test Results
</mat-card-title>
</mat-card-header>
<mat-card-content>
<div
*ngIf=
"results == null; else resultsBlock"
>
There are currently no results.
</div>
<ng-template
#resultsBlock
>
<div
*ngIf=
"results.testsRunResult === 'FAILURE'; else resultTree"
>
<p>
An error occurred while running the tests at stage {{ results.failedAtStage }}.
</p>
<span>
Message
<pre>
{{ results.message }}
</pre></span>
</div>
<ng-template
#resultTree
>
<div>
Overall duration: {{ results.duration }} seconds
</div>
<mat-accordion>
<mat-expansion-panel
*ngFor=
"let functionTestResult of results.functionTestResults"
(opened)=
"panelOpenState = true"
(closed)=
"panelOpenState = false"
>
<mat-expansion-panel-header>
<mat-panel-title>
<span>
{{ functionTestResult.functionName }} ({{ functionTestResult.overallResult }})
</span>
</mat-panel-title>
</mat-expansion-panel-header>
<span>
Function name
<pre>
{{ functionTestResult.functionName }}
</pre></span>
<span>
Tests duration (seconds)
<pre>
{{ functionTestResult.duration }}
</pre></span>
<span>
Summary
<pre>
{{ functionTestResult.overallResult }}
</pre></span>
<span>
Number of passed tests
<pre>
{{ functionTestResult.passed }}
</pre></span>
<span>
Number of failed tests
<pre>
{{ functionTestResult.failed }}
</pre></span>
<span>
Number of ignored tests
<pre>
{{ functionTestResult.ignored }}
</pre></span>
<span
*ngIf=
"functionTestResult.failedAtStage"
>
Failed to run tests due to failure at stage
<pre>
{{ functionTestResult.failedAtStage }}
</pre>
</span>
<span
*ngIf=
"functionTestResult.message"
>
Message
<pre>
{{ functionTestResult.message }}
</pre></span>
<mat-accordion>
<div>
Test cases
</div>
<mat-expansion-panel
*ngFor=
"let testCaseResult of functionTestResult.testCaseResults; let i = index"
(opened)=
"panelOpenState = true"
(closed)=
"panelOpenState = false"
>
<mat-expansion-panel-header>
<mat-panel-title>
<span>
#{{ i+1 }} ({{ testCaseResult.result }})
</span>
</mat-panel-title>
</mat-expansion-panel-header>
<span>
Result
<pre>
{{ testCaseResult.result }}
</pre></span>
<span>
Duration
<pre>
{{ testCaseResult.duration }}
</pre></span>
<span>
Input
<pre>
{{ testCaseResult.event }}
</pre></span>
<span>
Expected output
<pre>
{{ testCaseResult.expectedOutput }}
</pre></span>
<span
*ngIf=
"testCaseResult.actualOutput"
>
Actual output
<pre>
{{ testCaseResult.actualOutput }}
</pre></span>
<span
*ngIf=
"testCaseResult.message"
>
Message
<pre>
{{ testCaseResult.message }}
</pre></span>
</mat-expansion-panel>
</mat-accordion>
</mat-expansion-panel>
</mat-accordion>
</ng-template>
</ng-template>
</mat-card-content>
</mat-card>
</div>
src/app/serverless-testing/test-results/test-results.component.ts
0 → 100644
View file @
57c0af12
import
{
Component
,
Input
,
OnInit
}
from
'
@angular/core
'
;
import
{
TestResultTree
}
from
'
../model/TestResultTree
'
;
@
Component
({
selector
:
'
app-test-results
'
,
templateUrl
:
'
./test-results.component.html
'
,
styleUrls
:
[
'
./test-results.component.css
'
],
})
export
class
TestResultsComponent
implements
OnInit
{
@
Input
()
results
:
TestResultTree
;
panelOpenState
=
false
;
ngOnInit
():
void
{
}
}
src/app/serverless-testing/test-runner/test-runner.component.css
0 → 100644
View file @
57c0af12
div
{
margin-bottom
:
10px
;
margin-top
:
10px
;
}
button
{
margin-left
:
var
(
--double-margin
);
}
src/app/serverless-testing/test-runner/test-runner.component.html
0 → 100644
View file @
57c0af12
<div
id=
"test-runner-id"
>
<mat-card>
<mat-card-header>
<mat-card-title>
Run tests
</mat-card-title>
</mat-card-header>
<mat-card-content>
<div>
Click here to run the tests.
</div>
<button
mat-fab
(click)=
"runTests()"
>
<mat-icon>
play_arrow
</mat-icon>
</button>
<div
*ngIf=
"testsRunning"
>
<div>
Please wait. It may take a while...
</div>
<mat-progress-bar
color=
"primary"
mode=
"indeterminate"
></mat-progress-bar>
</div>
</mat-card-content>
</mat-card>
</div>
src/app/serverless-testing/test-runner/test-runner.component.ts
0 → 100644
View file @
57c0af12
import
{
Component
,
EventEmitter
,
Input
,
OnInit
,
Output
}
from
'
@angular/core
'
;
@
Component
({
selector
:
'
app-test-runner
'
,
templateUrl
:
'
./test-runner.component.html
'
,
styleUrls
:
[
'
./test-runner.component.css
'
],
})
export
class
TestRunnerComponent
implements
OnInit
{
@
Input
()
testsRunning
:
boolean
;
@
Output
()
runTestsEvent
=
new
EventEmitter
();
ngOnInit
():
void
{
}
runTests
()
{
this
.
runTestsEvent
.
emit
();
}
}
src/app/serverless-testing/uploader-yml/uploader-yml.component.css
0 → 100644
View file @
57c0af12
.file
{
display
:
flex
;
flex-wrap
:
wrap
;
align-items
:
center
;
}
.action-buttons
{
display
:
flex
;
flex-wrap
:
wrap
;
}
src/app/serverless-testing/uploader-yml/uploader-yml.component.html
0 → 100644
View file @
57c0af12
<div
id=
"yml-uploader-div"
>
<mat-card>
<mat-card-header>
<mat-card-title>
YAML file Upload
</mat-card-title>
<mat-card-subtitle>
Upload the test configuration file here. Only .yml and .yaml files are accepted.
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div>
<input
type=
"file"
#ymlFile
id=
"fileUploadDialog"
(change)=
"onFileSelectionEvent($event)"
accept=
".yml,.yaml"
>
</div>
<div
class=
"file"
*ngIf=
"fileToUpload != null"
>
{{fileToUpload.name}} ({{convertBytesToSize(fileToUpload.size)}})
<div
class=
"action-buttons"
>
<button
mat-button
color=
"primary"
[disabled]=
"fileUploadDisabled"
(click)=
"onFileUploadEvent()"
title=
"Upload file"
>
<mat-icon>
file_upload
</mat-icon>
</button>
<button
mat-button
color=
"warn"
[disabled]=
"fileUploadDisabled"
(click)=
"removeSelectedFile()"
title=
"Remove selected file"
>
<mat-icon>
cancel
</mat-icon>
</button>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
src/app/serverless-testing/uploader-yml/uploader-yml.component.ts
0 → 100644
View file @
57c0af12
import
{
Component
,
ElementRef
,
Input
,
OnInit
,
ViewChild
}
from
'
@angular/core
'
;
import
{
ServerlessTestingService
}
from
'
../service/serverless-testing.service
'
;
import
{
MatSnackBar
}
from
'
@angular/material
'
;
@
Component
({
selector
:
'
app-uploader-yml
'
,
templateUrl
:
'
./uploader-yml.component.html
'
,
styleUrls
:
[
'
./uploader-yml.component.css
'
],
})
export
class
UploaderYmlComponent
implements
OnInit
{
uploadInProgress
=
false
;
fileToUpload
:
File
=
null
;
total
:
number
=
null
;
@
ViewChild
(
'
ymlFile
'
)
ymlFile
:
ElementRef
;
constructor
(
private
snackBar
:
MatSnackBar
,
private
testingServerlessService
:
ServerlessTestingService
,
)
{
}
ngOnInit
():
void
{
}
@
Input
()
set
file
(
file
:
any
)
{
this
.
fileToUpload
=
file
;
this
.
total
=
this
.
fileToUpload
.
size
;
}
get
file
():
any
{
return
this
.
fileToUpload
;
}
convertBytesToSize
(
bytes
):
string
{
const
sizes
=
[
'
Bytes
'
,
'
KB
'
,
'
MB
'
,
'
GB
'
,
'
TB
'
];
if
(
bytes
===
0
)
{
return
'
0 Byte
'
;
}
const
i
=
Math
.
floor
(
Math
.
log
(
bytes
)
/
Math
.
log
(
1024
));
return
Math
.
round
(
bytes
/
Math
.
pow
(
1024
,
i
))
+
'
'
+
sizes
[
i
];
}
get
fileUploadDisabled
()
{
return
this
.
uploadInProgress
||
this
.
fileToUpload
==
null
;
}
onFileSelectionEvent
(
event
:
Event
)
{
this
.
fileToUpload
=
(
<
HTMLInputElement
>
event
.
target
).
files
[
0
];
console
.
log
(
'
Received event:
'
,
event
);
}
onFileUploadEvent
()
{
this
.
uploadInProgress
=
true
;
const
formData
:
FormData
=
new
FormData
();
formData
.
set
(
'
file
'
,
this
.
fileToUpload
,
this
.
fileToUpload
.
name
);
this
.
testingServerlessService
.
uploadTestConfiguration
(
formData
).
subscribe
(
response
=>
{
this
.
uploadInProgress
=
false
;
this
.
snackBar
.
open
(
`Successfully uploaded test config file:
${
this
.
fileToUpload
.
name
}
`
,
'
Close
'
,
{
duration
:
10000
},
);
this
.
removeSelectedFile
();
},
error
=>
{
this
.
uploadInProgress
=
false
;
console
.
log
(
error
);
this
.
snackBar
.
open
(
`Error while uploading:
${
error
.
error
.
message
}
`
,
'
Close
'
,
{
duration
:
10000
});
}
);
}
removeSelectedFile
()
{
this
.
fileToUpload
=
null
;
this
.
ymlFile
.
nativeElement
.
value
=
null
;
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment