-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(e2e-tests): add documentation for test automation (#55)
documentation about TestAutomation E2E Tests was added. why: E2E Tests were implemented to test the behaviour of API in different scenarios. Documentation includes the following topics: TestAutomation Summary, Access Token Retrieval, Test Data File Setup, InterfacePartnerHealthCheck SystemHealthCheck RegistrationScenarios, NotificationInitScenario, ServiceAccountCUDScenario, CreateAppScenario.
- Loading branch information
Showing
11 changed files
with
1,230 additions
and
0 deletions.
There are no files selected for viewing
File renamed without changes.
160 changes: 160 additions & 0 deletions
160
developer/Technical Documentation/TestAutomation/01. Summary.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
# Test Automation Summary | ||
|
||
## How to run | ||
|
||
E2E Tests can be started manually with the help of the "Test Automation E2E Tests" workflow via GitHub Actions. This | ||
workflow has two parameters: environment and test category. Environment value can be for example "dev" or "int". | ||
Test category defines, which group of tests will be executed. For now the following test categories are implemented: | ||
all, interface health check, portal health check, portal, registration. | ||
|
||
## Users for TestAutomation | ||
|
||
For successful run of tests following users should exist in the corresponding environment: | ||
|
||
* Portal test users for portal tests | ||
* Technical users for Interface Partner Health Checks | ||
|
||
## Management of secrets and environment variables | ||
|
||
Sensitive data is stored in a separate from the project tree location and isn't checked into source control. Two types | ||
of data are further distinguished: variables and secrets. Variables include such data as urls and non-sensitive, but | ||
domain specific ids as for example NotificationOfferId. Secrets include user names and passwords as well as specific | ||
tokens such as TempMail API token. | ||
|
||
For now the following variables are in use (can be found in the project in ```tests/TestRessources.cs```): | ||
|
||
| Variable | Value | | ||
|--------------------------|------------------------------------------------------| | ||
| ENVIRONMENT | dev | | ||
| NOTIFICATION_OFFER_ID | UUID_VALUE | | ||
| PORTAL_USER_COMPANY_NAME | PORTAL-COMPANY-FOR-TESTS | | ||
| CLEARING_HOUSE_URL | <https://validation.test.example.org> | | ||
| CLEARING_HOUSE_TOKEN_URL | <https://iam.test.example.org/{endpoint}/token> | | ||
| SD_FACTORY_BASE_URL | <https://sdfactory.{Env}.example.org> | | ||
| WALLET_BASE_URL | <https://managed-identity-wallets.{Env}.example.org> | | ||
| BASE_PORTAL_URL | <https://portal.{Env}.example.org> | | ||
| BASE_CENTRAL_IDP_URL | <https://centralidp.{Env}.example.org> | | ||
| BASE_PORTAL_BACKEND_URL | <https://portal-backend.{Env}.example.org> | | ||
| BPDM_URL | <https://partners-pool.{Env}.example.org> | | ||
|
||
where example.org corresponds to the domain in use. | ||
|
||
Following secrets are in use (can be found in the project in ```tests/Secrets.cs```): | ||
|
||
| Secret | | ||
|-------------------------------------------| | ||
| TEMPMAIL_APIKEY | | ||
| INTERFACE_HEALTH_CHECK_TECH_CLIENT_ID | | ||
| INTERFACE_HEALTH_CHECK_TECH_CLIENT_SECRET | | ||
| CLEARING_HOUSE_CLIENT_ID | | ||
| CLEARING_HOUSE_CLIENT_SECRET | | ||
| PORTAL_USER_NAME | | ||
| PORTAL_USER_PASSWORD | | ||
|
||
where TEMPMAIL_APIKEY is a token to call TempMail API, technical client id and secret for interface health check are | ||
used for BPDM, SdFactory and Wallet health checks, client id and secret for clearing house are used for ClearingHouse | ||
health check and portal user name and password are used for the rest of the tests. | ||
|
||
Secrets and variables can be managed via GitHub Actions to run the workflow or locally for local run. | ||
|
||
* via GitHub Actions | ||
|
||
In order to run workflow "TestAutomation E2E Tests" secrets (user names and passwords) should be added to GitHub Secrets | ||
on environment level. For example, to run on "dev" environment "dev" should be created first and then all necessary | ||
secrets should be added to this environment. Url variables can be added as variables on repository level as they are | ||
parametrized with {Env}. Environment specific variables such as company names and offer ids can be added on environment | ||
level. | ||
|
||
* for local test run | ||
|
||
In order to set environment variables locally, values should be added into ```tests/appsettings.EndToEndTests.json```. | ||
Secrets should be managed with the help of | ||
the [Secret Manager](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-7.0&tabs=windows). | ||
First Secret Manager should be initialized in the project with ```dotnet user-secrets init``` and then all necessary | ||
secrets should be set with the help of the command ```dotnet user-secrets set "USER_SECRET" "12345". | ||
|
||
## Structure | ||
|
||
E2E Tests are divided into two groups: tests for health check and functional tests. Below you can find a short | ||
description of these tests. Detailed information is available in separate files with according names. | ||
|
||
Base url for tests: | ||
|
||
``` | ||
https://portal-backend.{env}.demo.example.org | ||
``` | ||
|
||
where "env" defines environment specifics. | ||
|
||
### Health Check Tests | ||
|
||
Health check is needed to be executed to make sure that the appropriate endpoints are available and return a non-empty | ||
response. It can be run separately or before functional tests. | ||
|
||
#### [PortalHealthCheck](04.%20PortalHealthCheck.md) | ||
|
||
Portal health check is implemented for administration and registration services in order to check the load of static | ||
data and availability of additional endpoints. | ||
|
||
#### [InterfacePartnerHealthCheck](03.%20InterfacePArtnerHealthCheck.md) | ||
|
||
Interface Partner Health Check is now implemented for BPDM, ClearingHouse, SdFactory and Wallet. | ||
|
||
### Functional E2E Tests | ||
|
||
Functional E2E tests are designed to check the behavior of an application under different scenarios. Following scenarios | ||
were implemented: | ||
|
||
#### [Registration scenarios](05.%20RegistrationScenarios.md) | ||
|
||
Registration scenarios suppose to check if registration process runs as expected. The following scenarios were | ||
implemented completely: registration without bpn, update of company detail data after confirmation, in-registration | ||
invitation. Two scenarios (registration without bpn and registration without document upload) were partly implemented as | ||
adjustments in productive code are needed. | ||
Some additional scenarios can be added later. For example, validation of the right company detail data depending on the | ||
selected country. | ||
|
||
#### [Notification initial scenario](NotificationInitSceanrio.md) | ||
|
||
Notification initial scenario checks if a new random portal role can be assigned and unassigned and if appropriate | ||
notification, to the respective right person and with the correct content is created. | ||
|
||
#### [Service Account CUD Scenarios](ServiceAccountCUDScenarios.md) | ||
|
||
Create-Update-Delete Scenarios suppose to check if new service accounts can be correctly created, updated and deleted. | ||
|
||
## Test Parametrization | ||
|
||
Some tests are parameterized, which allow to run test scenarios with different data sets in one launch. The test data | ||
files are json files with the lists of data objects. The structure of these files can be | ||
found [here](08.%20TestDataFileSetup.md). | ||
|
||
Parameterized tests are marked as Theory. Member data annotation shows which function delivers test data sets for the | ||
test and calls appropriate functions from TestDataHelper class to fetch necessary data from test data file. | ||
|
||
Test data file is firstly parsed as a list of dictionary<string, Object> where dictionary key is a string variable that | ||
represents the name of the object. Dictionary value corresponds to the appropriate data type and deserialized to the | ||
object of this type. | ||
|
||
Test data file is first deserialized as a list of Dictionary<string, object>, where string variable defines the type of | ||
object. | ||
|
||
## ReportPortal | ||
|
||
After running the tests, the results can be sent to ReportPortal for better visualization. In order to make it possible | ||
the following secrets should be added to the file ```tests/ReportPortal.config.json```: | ||
|
||
| Secret | | ||
|----------------------------------| | ||
| REPORTPORTAL_URL | | ||
| REPORTPORTAL_PROJECT | | ||
| REPORTPORTAL_AUTHENTICATION_UUID | | ||
|
||
Similar to the process described above these secrets can be defined as secrets on environment level in GitHub Actions. | ||
They will be automatically added to the config file before build of the solution. | ||
|
||
For local run values should be added to the file ```tests/ReportPortal.config.json```, but should not be committed into | ||
source control. | ||
|
||
The values of secrets can be found under the profile tab in deployed ReportPortal. The further specifics for running and | ||
configuring the ReportPortal are highlighted [here](10.%20ReportPortal.md). |
210 changes: 210 additions & 0 deletions
210
developer/Technical Documentation/TestAutomation/02. Access Token Retrieval.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
# Access Token Retrieval | ||
|
||
While a normal user usually has access to access tokens by being signed in, when testing endpoints in an automated | ||
manner as part of a CI/CD pipeline it is needed to get access token for tests. For existing users, the token can be | ||
retrieved via the authentication flow using the company name, username and password. For new users invited during the | ||
registration process, a temporary email address needed to be created first in order to receive an email with a password. | ||
|
||
The implementation of | ||
|
||
* [Authentication Flow](#authentication-flow) | ||
* [Use of disposable email addresses](#use-of-disposable-email-addresses) | ||
* [DeveloperMail API](#developermail-api) | ||
* [TempMail API](#tempmail-api) | ||
|
||
will be explained now and can be found here: | ||
|
||
``` | ||
..\tests\endtoend\AuthFlow | ||
``` | ||
|
||
## Authentication Flow | ||
|
||
In order to fetch a user token, the company name, username and password are required. A series of HTTP requests against | ||
the CentralIdp and SharedIdp have to be made in order to exchange the credentials for an access token via auth code | ||
grant. | ||
Additionally, if a new user was created following an E2E test, the password has to be updated. Thus, the authentication | ||
flow consists of a series of 6 and 8 requests for existing users and new users, respectively: | ||
|
||
### Authenticate existing and new users: Start | ||
|
||
* Start on the CentralIdp Page | ||
|
||
``` | ||
GET: https://centralidp.{env}.example.org/auth/realms/CX-Central/protocol/openid-connect/auth | ||
``` | ||
|
||
This request returns an HTML body from which the list of existing companies can be extracted. The response Header " | ||
Set-Cookie" contains 3 cookies which are required for following requests. | ||
|
||
* Forward to Login SharedIdp Url | ||
|
||
``` | ||
GET: https://centralidp.{env}.example.org/auth/realms/CX-Central/broker/{companyNameInUrl}/login?client_id=Cl2-CX-Portal&tab_id={tabId}&session_code={sessionCode} | ||
``` | ||
|
||
This request returns the header location to a SharedIdp Url. The query parameters are extracted from the chosen company. | ||
The request headers must include the cookies fetched from the previous request. | ||
|
||
* Get Login form | ||
|
||
``` | ||
GET: {sharedIdpUrl from previous request} | ||
``` | ||
|
||
This request returns an HTML body with the login form from which a SharedIdp Url can be extracted. | ||
|
||
* Authenticate User against SharedIdp or forward to update password | ||
|
||
``` | ||
POST: {sharedIdpUrl from previous request} | ||
``` | ||
|
||
This request requires a form body which must include the company name, username and password of the user to be | ||
authenticated. It returns the header location to an Url. | ||
This Url can either be a CentralIdp Url for fetching the auth code for login of an existing user or another SharedIdp | ||
Url for updating the password of a new user. | ||
|
||
### Authenticate new users only: Update Password | ||
|
||
* Forward to Update-Password form SharedIdp Url | ||
|
||
``` | ||
GET: {sharedIdpUrl from previous request} | ||
``` | ||
|
||
This request returns an HTML body with the update-password form from which a SharedIdp Url can be extracted. The request | ||
headers must include the cookies fetched from the first request. | ||
|
||
* Update user password | ||
|
||
``` | ||
POST: {sharedIdpUrl from previous request} | ||
``` | ||
|
||
This request requires a form body which must include the username, old password, new password and the confirmed new | ||
password of the user to be authenticated. It returns the header location to a CentralIdp Url for fetching the auth Url. | ||
From here on, the authentication flow for new users continues to follow the flow for existing users: | ||
|
||
### Authenticate existing and new users: End | ||
|
||
* Authenticate User against CentralIdp | ||
|
||
``` | ||
GET: {centralIdpUrl from previous request} | ||
``` | ||
|
||
This request returns the header location to a CentralIdp Url. The Url includes the auth code. The request headers must | ||
include the cookies fetched from the first request. | ||
|
||
* Exchange Auth code for access token | ||
|
||
``` | ||
POST: https://centralidp.{env}.example.org/auth/realms/CX-Central/protocol/openid-connect/token | ||
``` | ||
|
||
This request requires a form body which must include the code, grant type, client id and redirect uri. It returns a JSON | ||
object including the user access token. | ||
|
||
## Use of disposable email addresses | ||
|
||
The registration process consists of an invitation step in which an administrator sends to a user an invitation to join | ||
the Catena-X Portal. To make it possible temporary email services are used. | ||
Per default [DeveloperMail](https://developermail.com/api/v1/) is used as it is a free API with suitable limit on | ||
requests (only more than 25 requests in one second will result a HTTP 429 Too Many Requests response). In case if this | ||
API is not available [TempMail API](https://apilayer.com/marketplace/temp_mail-api) will be used as it is restricted to | ||
500 requests in month and requires registration to get TempMailApiKey to access functionality. | ||
|
||
### DeveloperMail API | ||
|
||
The base url for requests to DeveloperMail API is: | ||
|
||
``` | ||
https://developermail.com/api/v1 | ||
``` | ||
|
||
In order to get a username and password for a new user the following steps are executed: | ||
|
||
* Generate a random email address | ||
|
||
``` | ||
PUT: /mailbox | ||
``` | ||
|
||
This endpoint returns a response that contains a username and an access token of the type "X-MailboxToken" for all other | ||
requests. | ||
|
||
* Send invitation to user @ developermail.com (s. [RegistrationScenarios](05.%20RegistrationScenarios.md)) | ||
|
||
Important: a delay after sending invitation and before checking mailbox is implemented in order to give time for the | ||
emails to reach the mailbox. | ||
|
||
* Get existing message ids | ||
|
||
``` | ||
GET: /mailbox/{username} | ||
``` | ||
|
||
* Check mailbox with the body consists of the list with the received ids | ||
|
||
``` | ||
POST: /mailbox/{username}/messages | ||
``` | ||
|
||
* Find email with password and fetch it | ||
|
||
The password is searched in the first paragraph that follows after the paragraph with the text 'Below you | ||
can find your password' in the email whose topic contains "Password required". | ||
|
||
* Delete mailbox | ||
|
||
``` | ||
DELETE: /mailbox/{username} | ||
``` | ||
|
||
For security reasons the mailbox is deleted after fetching the password. | ||
|
||
### TempMail API | ||
|
||
Registration is required to use TempMailApi, which can be done [here](https://apilayer.com/marketplace/temp_mail-api) | ||
with any email address you use. TempMailApiKey should be stored secure as GitHub Secret or locally via Secret Manager | ||
and should not be committed to version control. | ||
|
||
The base url for requests to TempMail API is: | ||
|
||
``` | ||
https://api.apilayer.com/temp_mail | ||
``` | ||
|
||
* Get available domains | ||
|
||
``` | ||
GET: /domains | ||
``` | ||
|
||
In contrast to the first option here a random address is not generated, but a list of available domains is requested. | ||
Any username can be chosen, for now "apitestuser" is hardcoded. | ||
|
||
* Send invitation to "apitestuser" @ one of available domains ( | ||
s. [RegistrationScenarios](05.%20RegistrationScenarios.md)) | ||
* Get password message and fetch password | ||
|
||
``` | ||
GET: /mail/id/{hashedEmailAddress} | ||
``` | ||
|
||
where email address is hashed with MD5. | ||
|
||
Similar to the approach described above the password is searched in the first paragraph of the table that follows after | ||
the paragraph with the text 'Below you can find your password' in the email whose topic contains "Password required". | ||
|
||
* Delete password message | ||
|
||
``` | ||
DELETE: /delete/id/{mailId} | ||
``` | ||
|
||
Finally the password message is deleted after fetching the password for security reasons. | ||
|
||
In both cases after getting the username and password, an authentication flow can be processed to get an access token | ||
for the user. |
Oops, something went wrong.