Skip to content
GitLab
Menu
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
f3cf1611
Commit
f3cf1611
authored
Apr 07, 2021
by
Alicja Reniewicz
Browse files
Merge branch 'rc3.1' into 'master'
Rc3.1 See merge request
!8
parents
6df11092
e20ef2d0
Pipeline
#12214
canceled with stage
Changes
20
Pipelines
3
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
f3cf1611
...
...
@@ -10,13 +10,17 @@ build-angular-ui:
-
dist/melodic-frontend
before_script
:
-
npm install -g --save-dev @angular/cli@latest
-
npm install --save-dev --unsafe-perm node-sass
-
npm install --save-dev --unsafe-perm node-sass
@4.14.1
-
npm install
script
:
-
ng build --prod
build-ui-docker
:
stage
:
build-ui-docker
only
:
-
master
-
rc3.0
-
rc3.1
image
:
docker:19.03.1
services
:
-
docker:19.03.1-dind
...
...
src/app/app-routing.module.ts
View file @
f3cf1611
...
...
@@ -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 @
f3cf1611
...
...
@@ -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/file-uploader/sensitive-variables-dialog/sensitive-variables-dialog.component.html
View file @
f3cf1611
...
...
@@ -40,7 +40,7 @@
<mat-header-cell
*matHeaderCellDef
>
Value
</mat-header-cell>
<mat-cell
*matCellDef=
"let element;"
[formGroup]=
"element"
>
<mat-form-field>
<input
matInput
placeholder=
"value"
formControlName=
"value"
>
<input
matInput
placeholder=
"value"
formControlName=
"value"
type=
"password"
>
</mat-form-field>
</mat-cell>
</ng-container>
...
...
src/app/serverless-testing/model/TestConfigurationResponse.ts
0 → 100644
View file @
f3cf1611
export
class
TestConfigurationResponse
{
path
:
string
;
configuration
:
TestConfiguration
;
}
class
TestConfiguration
{
tests
:
Array
<
FunctionTestConfiguration
>
;
}
class
FunctionTestConfiguration
{
functionName
:
string
;
triggerPath
:
string
;
testCases
:
Array
<
TestCaseConfiguration
>
;
}
class
TestCaseConfiguration
{
event
:
string
;
condition
:
string
;
expectedValue
:
string
;
}
src/app/serverless-testing/model/TestResultTree.ts
0 → 100644
View file @
f3cf1611
class
TestCaseResult
{
event
:
string
;
condition
:
string
;
expectedValue
:
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/route/serverless-testing-routing.module.ts
0 → 100644
View file @
f3cf1611
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 @
f3cf1611
<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 @
f3cf1611
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 @
f3cf1611
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 @
f3cf1611
import
{
Injectable
}
from
'
@angular/core
'
;
import
{
HttpClient
}
from
'
@angular/common/http
'
;
import
{
tap
}
from
'
rxjs/operators
'
;
import
{
Observable
}
from
'
rxjs
'
;
import
{
AppConfigService
}
from
'
../../app-config/service/app-config.service
'
;
import
{
TestResultTree
}
from
'
../model/TestResultTree
'
;
import
{
TestConfigurationResponse
}
from
'
../model/TestConfigurationResponse
'
;
@
Injectable
({
providedIn
:
'
root
'
})
export
class
ServerlessTestingService
{
apiUrl
=
`
${
AppConfigService
.
settings
.
apiUrl
}
/auth/test`
;
testConfigUrl
=
this
.
apiUrl
+
'
/config
'
;
constructor
(
private
http
:
HttpClient
)
{
}
uploadTestConfiguration
(
formData
:
FormData
):
Observable
<
TestConfigurationResponse
>
{
return
this
.
http
.
post
(
this
.
testConfigUrl
,
formData
,
{
responseType
:
'
json
'
}).
pipe
(
tap
(
(
response
:
TestConfigurationResponse
)
=>
{
console
.
log
(
'
Response:
'
,
response
);
},
error
=>
{
console
.
log
(
'
Error while uploading test configuration file:
'
,
error
);
}
));
}
getTestConfiguration
():
Observable
<
TestConfigurationResponse
>
{
return
this
.
http
.
get
(
this
.
testConfigUrl
,
{
responseType
:
'
json
'
}).
pipe
(
tap
(
(
response
:
TestConfigurationResponse
)
=>
{
console
.
log
(
'
Response:
'
,
response
);
},
error
=>
{
console
.
log
(
'
Error while getting test configuration file:
'
,
error
);
}
));
}
deleteTestConfiguration
():
Observable
<
any
>
{
return
this
.
http
.
delete
(
this
.
testConfigUrl
,
{
responseType
:
'
json
'
}).
pipe
(
tap
(
()
=>
{
console
.
log
(
'
Deleted test config file successfully.
'
);
},
error
=>
{
console
.
log
(
'
Error while deleting 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 @
f3cf1611
samp
{
white-space
:
pre-wrap
;
}
td
{
padding
:
5px
30px
5px
0
;
vertical-align
:
top
;
}
mat-card
{
margin
:
10px
0
;
}
.mat-card-content
{
margin-left
:
16px
;
}
.test-case-key
{
font-weight
:
bold
;
}
.mat-expansion-panel-header-title
{
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
src/app/serverless-testing/test-results/test-results.component.html
0 → 100644
View file @
f3cf1611
<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
>
<p>
Overall duration: {{ results.duration }} seconds
</p>
<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><samp>
{{ functionTestResult.functionName }}
</samp>
(
<samp>
{{ functionTestResult.overallResult }}
</samp>
)
</span>
</mat-panel-title>
</mat-expansion-panel-header>
<table>
<tr><td
class=
"test-case-key"
>
Function name
</td><td><samp>
{{ functionTestResult.functionName }}
</samp></td></tr>
<tr><td
class=
"test-case-key"
>
Tests duration
</td><td>
{{ functionTestResult.duration }} seconds
</td></tr>
<tr><td
class=
"test-case-key"
>
Number of passed tests
</td><td>
{{ functionTestResult.passed }}
</td></tr>
<tr><td
class=
"test-case-key"
>
Number of failed tests
</td><td>
{{ functionTestResult.failed }}
</td></tr>
<tr><td
class=
"test-case-key"
>
Number of passed ignored
</td><td>
{{ functionTestResult.ignored }}
</td></tr>
<tr
*ngIf=
"functionTestResult.failedAtStage"
>
<td
class=
"test-case-key"
>
Failed to run tests due to failure at stage
</td>
<td><samp>
{{ functionTestResult.failedAtStage }}
</samp></td>
</tr>
<tr
*ngIf=
"functionTestResult.message"
>
<td
class=
"test-case-key"
>
Message
</td>
<td><samp>
{{ functionTestResult.message }}
</samp></td>
</tr>
</table>
<mat-accordion>
<h4>
Test cases
</h4>
<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>
<table>
<tr><td
class=
"test-case-key"
>
Result
</td><td><samp>
{{ testCaseResult.result }}
</samp></td></tr>
<tr><td
class=
"test-case-key"
>
Duration
</td><td>
{{ testCaseResult.duration }} seconds
</td></tr>
<tr><td
class=
"test-case-key"
>
Input event
</td><td><samp>
{{ testCaseResult.event }}
</samp></td></tr>
<tr><td
class=
"test-case-key"
>
Condition for the output
</td><td><samp>
{{ testCaseResult.condition }}
</samp></td></tr>
<tr><td
class=
"test-case-key"
>
Expected value
</td><td><samp>
{{ testCaseResult.expectedValue }}
</samp></td></tr>
<tr
*ngIf=
"testCaseResult.actualOutput"
>
<td
class=
"test-case-key"
>
Actual output
</td><td><samp>
{{ testCaseResult.actualOutput }}
</samp></td>
</tr>
<tr
*ngIf=
"testCaseResult.message"
>
<td
class=
"test-case-key"
>
Message
</td><td><samp>
{{ testCaseResult.message }}
</samp></td>
</tr>
</table>
</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 @
f3cf1611
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 @
f3cf1611
button
{
padding
:
0
5px
;
}
mat-card
{
margin
:
10px
0
;
}
.mat-card-content
{
margin-left
:
16px
;
}
.mat-card-actions
{
margin-left
:
16px
;
}
.mat-card-actions
span
{
padding-right
:
8px
;
}
src/app/serverless-testing/test-runner/test-runner.component.html
0 → 100644
View file @
f3cf1611
<div
id=
"test-runner-id"
>
<mat-card>
<mat-card-header>
<mat-card-title>
Run tests
</mat-card-title>
<mat-card-subtitle>
Click on the button to execute the tests.
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<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-actions>
<button
mat-raised-button
color=
"primary"
[disabled]=
"testsRunning"
(click)=
"runTests()"
title=
"Run tests"
>
<mat-icon>
play_arrow
</mat-icon>
<span>
Run tests
</span>
</button>
</mat-card-actions>
</mat-card>
</div>
src/app/serverless-testing/test-runner/test-runner.component.ts
0 → 100644
View file @
f3cf1611
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 @
f3cf1611
td
{
padding
:
5px
30px
5px
0
;
vertical-align
:
top
;
}
button
{
padding
:
0
5px
;
}
mat-card
{
margin
:
10px
0
;
}
.mat-button
{
margin-left
:
16px
;
}
.file
{
margin-top
:
20px
;
}
.mat-accordion
.mat-expansion-panel
:first-of-type
{
margin-top
:
10px
;
}
.mat-expansion-panel-header-title
{
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
.test-case-key
{
font-weight
:
bold
;
}
.delete-button
{
color
:
var
(
--color-warn
);
}
.mat-card-content
{
margin-left
:
16px
;
}
.mat-card-actions
{
margin-left
:
16px
;
}
.mat-card-actions
span
{
padding-right
:
8px
;
}
src/app/serverless-testing/uploader-yml/uploader-yml.component.html
0 → 100644
View file @
f3cf1611
<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>
</mat-card-content>
<mat-card-actions>
<button
mat-button
color=
"primary"
[disabled]=
"fileUploadDisabled"
(click)=
"onFileUploadEvent()"
title=
"Upload file"
>
<mat-icon>
file_upload
</mat-icon>
<span>
Upload
</span>
</button>
<button
mat-button
color=
"warn"
[disabled]=
"fileUploadDisabled"
(click)=
"removeSelectedFile()"
title=
"Cancel"
>
<mat-icon>
cancel
</mat-icon>
<span>
Cancel
</span>
</button>
</mat-card-actions>