diff --git a/alfa-client/apps/alfa-e2e/Jenkinsfile b/alfa-client/Jenkinsfile.e2e similarity index 69% rename from alfa-client/apps/alfa-e2e/Jenkinsfile rename to alfa-client/Jenkinsfile.e2e index 4d9192728334431b0219afb7c8ac6372cf9bdaab..9b55f66a5146de14b99bdb88d22821c906c2d13e 100644 --- a/alfa-client/apps/alfa-e2e/Jenkinsfile +++ b/alfa-client/Jenkinsfile.e2e @@ -23,7 +23,10 @@ pipeline { FAILED_PARALLEL_STAGE = " " EA_BEZEICHNER = generateBezeichner("e2e-ea") MAIN_BEZEICHNER = generateBezeichner("e2e-main") + ADMIN_BEZEICHNER = generateBezeichner("e2e-admin") SH_SUCCESS_STATUS_CODE = 0 + KEYCLOAK_CLIENT_ADMIN_APP = "admin" + KEYCLOAK_CLIENT_ALFA_APP = "alfa" } options { @@ -98,6 +101,7 @@ pipeline { script { FAILED_STAGE = env.STAGE_NAME + initEnvAdminDefaultVersions() initEnvAlfaDefaultVersions() initEnvVorgangManagerDefaultVersions() initEnvUserManagerDefaultVersions() @@ -122,6 +126,12 @@ pipeline { string(name: "AlfaImageTag", defaultValue: env.ALFA_IMAGE_TAG, trim: true), string(name: "AlfaHelmChartVersion", defaultValue: env.ALFA_HELM_CHART_VERSION, trim: true), string(name: "AlfaHelmRepoUrl", defaultValue: env.ALFA_HELM_REPO_URL, trim: true), + string(name: "AdministrationImageTag", defaultValue: env.ADMINISTRATION_IMAGE_TAG, trim: true), + string(name: "AdministrationHelmChartVersion", defaultValue: env.ADMINISTRATION_HELM_CHART_VERSION, trim: true), + string(name: "AdministrationHelmRepoUrl", defaultValue: env.ADMINISTRATION_HELM_REPO_URL, trim: true), + string(name: "AdminClientImageTag", defaultValue: env.ADMIN_CLIENT_IMAGE_TAG, trim: true), + string(name: "AdminClientHelmChartVersion", defaultValue: env.ADMIN_CLIENT_HELM_CHART_VERSION, trim: true), + string(name: "AdminClientHelmRepoUrl", defaultValue: env.ADMIN_CLIENT_HELM_REPO_URL, trim: true), string(name: "VorgangManagerImageTag", defaultValue: env.VORGANG_MANAGER_IMAGE_TAG, trim: true), string(name: "VorgangManagerHelmChartVersion", defaultValue: env.VORGANG_MANAGER_HELM_CHART_VERSION, trim: true), string(name: "VorgangManagerHelmRepoUrl", defaultValue: env.VORGANG_MANAGER_HELM_REPO_URL, trim: true), @@ -165,10 +175,9 @@ pipeline { checkoutGitopsE2eBranch() - deleteOzgCloudStack([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER]) + deleteNamespaces([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER, env.ADMIN_BEZEICHNER]) - generateMainNamespaceYaml() - generateEaNamespaceYaml() + generateNamespaces() pushGitopsRepo() } @@ -176,7 +185,7 @@ pipeline { post { failure { script { - deleteOzgCloudStack([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER]) + deleteNamespaces([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER, env.ADMIN_BEZEICHNER]) } } } @@ -211,13 +220,14 @@ pipeline { script { FAILED_STAGE = env.STAGE_NAME - waitForOzgCloudStackRollout([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER]) + waitForAdminRollout(env.ADMIN_BEZEICHNER) + waitForAlfaRollout([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER]) } } post { failure { script { - deleteOzgCloudStack([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER]) + deleteNamespaces([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER, env.ADMIN_BEZEICHNER]) } } } @@ -236,14 +246,14 @@ pipeline { } } -// stage('Run E2E-Tests') { -// when { -// expression { !SKIP_RUN } -// } -// failFast false + stage('Run E2E-Tests') { + when { + expression { !SKIP_RUN } + } + failFast false -// parallel { - stage('E2E-EA') { + parallel { + stage('E2E-Alfa-EA') { when { expression { !SKIP_RUN } } @@ -254,7 +264,7 @@ pipeline { Integer mongoDbPort = forwardMongoDbPort(generateNamespace(bezeichner)) - runTests(bezeichner, 'einheitlicher-ansprechpartner', mongoDbPort, env.STAGE_NAME) + runTests(bezeichner, 'alfa-e2e', 'einheitlicher-ansprechpartner', env.KEYCLOAK_CLIENT_ALFA_APP, mongoDbPort, env.STAGE_NAME) stopForwardMongoDbPort(generateNamespace(bezeichner)) } @@ -268,13 +278,13 @@ pipeline { } always { script { - publishE2ETestResult("einheitlicher-ansprechpartner", "Alfa E2E-Tests EA") + publishAlfaE2ETestResult("einheitlicher-ansprechpartner", "Alfa E2E-Tests EA") } } } } - stage('E2E-Main') { + stage('E2E-Alfa-Main') { when { expression { !SKIP_RUN } } @@ -285,7 +295,7 @@ pipeline { Integer mongoDbPort = forwardMongoDbPort(generateNamespace(bezeichner)) - runTests(bezeichner, 'main-tests', mongoDbPort, env.STAGE_NAME) + runTests(bezeichner, 'alfa-e2e', 'main-tests', env.KEYCLOAK_CLIENT_ALFA_APP, mongoDbPort, env.STAGE_NAME) stopForwardMongoDbPort(generateNamespace(bezeichner)) } @@ -299,13 +309,43 @@ pipeline { } always { script { - publishE2ETestResult("main-tests", "Alfa E2E-Tests main") + publishAlfaE2ETestResult("main-tests", "Alfa E2E-Tests main") } } } } -// } -// } + stage('E2E-Admin-Main') { + when { + expression { !SKIP_RUN } + } + steps { + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + script { + String bezeichner = env.ADMIN_BEZEICHNER + + Integer mongoDbPort = forwardMongoDbPort(generateNamespace(bezeichner)) + + runTests(bezeichner, 'admin-e2e', 'main-tests', env.KEYCLOAK_CLIENT_ADMIN_APP, mongoDbPort, env.STAGE_NAME) + + stopForwardMongoDbPort(generateNamespace(bezeichner)) + } + } + } + post { + failure { + script { + FAILED_PARALLEL_STAGE += "${env.STAGE_NAME} " + } + } + always { + script { + publishAdminE2ETestResult() + } + } + } + } + } + } stage('Delete E2E Namespaces') { when { @@ -315,7 +355,7 @@ pipeline { script { FAILED_STAGE = env.STAGE_NAME - deleteOzgCloudStack([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER]) + deleteNamespaces([env.EA_BEZEICHNER, env.MAIN_BEZEICHNER, env.ADMIN_BEZEICHNER]) } } } @@ -376,21 +416,6 @@ String getHelmChartVersion(Map applicationValues) { return applicationValues.helm.version } -Void initEnvAlfaDefaultVersions() { - if (isMasterBranch() || isReleaseBranch()) { - values = getApplicationValues('alfa') - - env.ALFA_IMAGE_TAG = getImageTag(values) - env.ALFA_HELM_CHART_VERSION = getHelmChartVersion(values) - } - else { - env.ALFA_IMAGE_TAG = getFeatureBranchImageTag() - env.ALFA_HELM_CHART_VERSION = getFeatureBranchHelmChartVersion() - } - - env.ALFA_HELM_REPO_URL = getHelmRepoUrl() -} - Boolean isMasterBranch() { return env.BRANCH_NAME == 'master' } @@ -417,6 +442,33 @@ String getRootPomVersion() { return rootPom.version } +Void initEnvAdminDefaultVersions() { + def values = getApplicationValues('administration') + env.ADMINISTRATION_IMAGE_TAG = getImageTag(values) + env.ADMINISTRATION_HELM_CHART_VERSION = getHelmChartVersion(values) + env.ADMINISTRATION_HELM_REPO_URL = getHelmRepoUrl() + + values = getApplicationValues('admin-client') + env.ADMIN_CLIENT_IMAGE_TAG = getImageTag(values) + env.ADMIN_CLIENT_HELM_CHART_VERSION = getHelmChartVersion(values) + env.ADMIN_CLIENT_HELM_REPO_URL = getHelmRepoUrl() +} + +Void initEnvAlfaDefaultVersions() { + if (isMasterBranch() || isReleaseBranch()) { + values = getApplicationValues('alfa') + + env.ALFA_IMAGE_TAG = getImageTag(values) + env.ALFA_HELM_CHART_VERSION = getHelmChartVersion(values) + } + else { + env.ALFA_IMAGE_TAG = getFeatureBranchImageTag() + env.ALFA_HELM_CHART_VERSION = getFeatureBranchHelmChartVersion() + } + + env.ALFA_HELM_REPO_URL = getHelmRepoUrl() +} + Void initEnvVorgangManagerDefaultVersions() { def values = getApplicationValues('vorgang-manager') @@ -437,6 +489,12 @@ Void initEnvUserVersions(userVersions) { env.ALFA_IMAGE_TAG = userVersions.AlfaImageTag env.ALFA_HELM_CHART_VERSION = userVersions.AlfaHelmChartVersion env.ALFA_HELM_REPO_URL = userVersions.AlfaHelmRepoUrl + env.ADMINISTRATION_IMAGE_TAG = userVersions.AdministrationImageTag + env.ADMINISTRATION_HELM_CHART_VERSION = userVersions.AdministrationHelmChartVersion + env.ADMINISTRATION_HELM_REPO_URL = userVersions.AdministrationHelmRepoUrl + env.ADMIN_CLIENT_IMAGE_TAG = userVersions.AdminClientImageTag + env.ADMIN_CLIENT_HELM_CHART_VERSION = userVersions.AdminClientHelmChartVersion + env.ADMIN_CLIENT_HELM_REPO_URL = userVersions.AdminClientHelmRepoUrl env.VORGANG_MANAGER_IMAGE_TAG = userVersions.VorgangManagerImageTag env.VORGANG_MANAGER_HELM_CHART_VERSION = userVersions.VorgangManagerHelmChartVersion env.VORGANG_MANAGER_HELM_REPO_URL = userVersions.VorgangManagerHelmRepoUrl @@ -468,15 +526,43 @@ Void checkoutGitopsE2eBranch() { } } -Void generateEaNamespaceYaml() { - generateNamespaceYaml(env.EA_BEZEICHNER, "by-ea-dev.yaml"); +Void generateNamespaces() { + def y1 = generateAdminNamespaceYaml() + def y2 = generateEaNamespaceYaml() + def y3 = generateMainNamespaceYaml() + + dir("gitops") { + sh "git add ${y1} ${y2} ${y3}" + sh "git commit -m 'add e2e namespaces for testrun'" + } + +} + +Void generateAdminNamespaceYaml() { + def bezeichner = env.ADMIN_BEZEICHNER + def envValues + dir("alfa-client/apps/admin-e2e/") { + envValues = readYaml file: "src/fixtures/argocd/by-admin-dev.yaml"; + + envValues.ozgcloud.bezeichner = bezeichner + envValues.administration.put("image", ['tag': env.ADMINISTRATION_IMAGE_TAG]) + envValues.administration.put("helm", ['version': env.ADMINISTRATION_HELM_CHART_VERSION, 'repoUrl': env.ADMINISTRATION_HELM_REPO_URL]) + + envValues.admin_client.put("image", ['tag': env.ADMIN_CLIENT_IMAGE_TAG]) + envValues.admin_client.put("helm", ['version': env.ADMIN_CLIENT_HELM_CHART_VERSION, 'repoUrl': env.ADMIN_CLIENT_HELM_REPO_URL]) + } + return writeYamlToGitOps(bezeichner, envValues); +} + +String generateEaNamespaceYaml() { + return generateNamespaceYaml(env.EA_BEZEICHNER, "by-ea-dev.yaml"); } -Void generateMainNamespaceYaml() { - generateNamespaceYaml(env.MAIN_BEZEICHNER, "by-main-dev.yaml"); +String generateMainNamespaceYaml() { + return generateNamespaceYaml(env.MAIN_BEZEICHNER, "by-main-dev.yaml"); } -Void generateNamespaceYaml(String bezeichner, String valuesPathSuffix) { +String generateNamespaceYaml(String bezeichner, String valuesPathSuffix) { def envValues dir('alfa-client/apps/alfa-e2e/') { envValues = readYaml file: "src/fixtures/argocd/" + valuesPathSuffix; @@ -491,18 +577,20 @@ Void generateNamespaceYaml(String bezeichner, String valuesPathSuffix) { envValues.user_manager.put("image", ['tag': env.USER_MANAGER_IMAGE_TAG]) envValues.user_manager.put("helm", ['version': env.USER_MANAGER_HELM_CHART_VERSION, 'repoUrl': env.USER_MANAGER_HELM_REPO_URL]) } + return writeYamlToGitOps(bezeichner, envValues); +} - writeYaml file: "gitops/dev/namespace/namespaces/by-${bezeichner}-dev.yaml", data: envValues, overwrite: true +String writeYamlToGitOps(String bezeichner, Object envValues){ + def bezeichnerYaml = "dev/namespace/namespaces/by-${bezeichner}-dev.yaml" - sh "cat gitops/dev/namespace/namespaces/by-${bezeichner}-dev.yaml" + writeYaml file: "gitops/${bezeichnerYaml}", data: envValues, overwrite: true - dir("gitops") { - sh "git add dev/namespace/namespaces/by-${bezeichner}-dev.yaml" - sh "git commit -m 'add e2e by-${bezeichner}-dev'" - } + sh "cat gitops/${bezeichnerYaml}" + + return bezeichnerYaml; } -Void deleteOzgCloudStack(ozgCloudBezeichner) { +Void deleteNamespaces(ozgCloudBezeichner) { for(bezeichner in ozgCloudBezeichner) { if (hasNamespaceFile(bezeichner)) { removeNamespaceFile(bezeichner) @@ -536,13 +624,19 @@ Void waitForDeletion(String bezeichner) { } } -Void waitForOzgCloudStackRollout(ozgCloudBezeichner) { +Void waitForAlfaRollout(ozgCloudBezeichner) { for(bezeichner in ozgCloudBezeichner) { - waitForRollout(bezeichner) + waitForAlfaRollout(bezeichner) } } -Void waitForRollout(String bezeichner) { +Void waitForAdminRollout(String bezeichner) { + waitForAlfaRollout([bezeichner]) + waitForHealthyApplication(bezeichner, 'administration') + waitForHealthyApplication(bezeichner, 'admin-client') +} + +Void waitForAlfaRollout(String bezeichner) { waitForHealthyApplication(bezeichner, 'application') waitForHealthyApplication(bezeichner, 'vorgang-manager') waitForHealthyApplication(bezeichner, 'user-manager') @@ -580,32 +674,41 @@ Void waitForHealthyStatus(String bezeichner, String application) { sh "kubectl wait --for=jsonpath='{.status.health.status}'=Healthy applications/by-${bezeichner}-dev-${application} -n argocd --timeout=900s" } -Void publishE2ETestResult(String reportFolder, String reportName) { - publishHTML ( - target: [ - allowMissing: false, - alwaysLinkToLastBuild: false, - keepAll: true, - reportDir: "alfa-client/apps/alfa-e2e/reports/${reportFolder}", - reportFiles: 'report.html', - reportName: reportName - ] - ) +Void publishAlfaE2ETestResult(String appVariant, String reportName) { + publishE2ETestResult("alfa-e2e", appVariant, reportName); } -String runTests(String bezeichner, String reportFolder, Integer dbPort, String stageName) { - def config = generateCypressConfig(bezeichner, reportFolder, dbPort) +Void publishAdminE2ETestResult() { + publishE2ETestResult("admin-e2e", "main-tests", "Admin E2E-Tests main"); +} - try { - dir('alfa-client'){ - sh "npm run cypress:version" - sh "apps/alfa-e2e/run-tests.sh ${reportFolder} ${config}" - } - } catch (Exception e) { - printNpmDebugLog() +Void publishE2ETestResult(String appName, String appVariant, String reportName) { + def reportDir = "alfa-client/apps/"+appName+"/reports/"+appVariant; - error("Fehler in Stage ${stageName}") + publishHTML ( + target: [ + allowMissing: false, + alwaysLinkToLastBuild: false, + keepAll: true, + reportDir: reportDir, + reportFiles: 'report.html', + reportName: reportName + ] + ) +} + +String runTests(String bezeichner, String appName, String appVariant, String keycloakClientName, Integer dbPort, String stageName) { + def config = generateCypressConfig(bezeichner, appName, appVariant, keycloakClientName, dbPort) + try { + dir('alfa-client'){ + sh "npm run cypress:version" + sh "apps/run-tests.sh ${appName} ${appVariant} ${config}" } + } catch (Exception e) { + printNpmDebugLog() + + error("Fehler in Stage ${stageName}") + } } Void printNpmDebugLog() { @@ -636,39 +739,49 @@ String cutBranchNameForKeycloakRealm(String branchName, String stageName) { return branchName.take(cutBranchNamePosition) } -String generateCypressConfig(String bezeichner, String testFolder, Integer dbPort) { - def namespace = generateNamespace(bezeichner) - def configName = "cypress-ci-"+testFolder+".json" +String generateCypressConfig(String bezeichner, String appName, String appVariant, String keycloakClientName, Integer dbPort) { + def namespace = generateNamespace(bezeichner) + def configName = "cypress-ci-"+appVariant+".json" - dir('alfa-client/apps/alfa-e2e/'){ - def config = readJSON file: 'cypress-ci.json' + dir("alfa-client/apps/${appName}/"){ + def config = readJSON file: 'cypress-ci.json' - def vorgangManagerDatabaseSecret = getVorgangManagerDatabaseSecret(namespace); - def decodedPassword = decodeString(vorgangManagerDatabaseSecret.password); - def parsablePassword = makePasswordUrlConform(decodedPassword); + def vorgangManagerDatabaseSecret = getVorgangManagerDatabaseSecret(namespace); + def decodedPassword = decodeString(vorgangManagerDatabaseSecret.password); + def parsablePassword = makePasswordUrlConform(decodedPassword); - config.baseUrl = "https://${bezeichner}.${env.CLUSTER_BASE_URL}" as String - config.env.dbUrl = "mongodb://${decodeString(vorgangManagerDatabaseSecret.username)}:${parsablePassword}@localhost:${dbPort}/admin?ssl=false&directConnection=true&socketTimeoutMS=30000&heartbeatFrequencyMS=10000" as String - config.env.keycloakUrl = "https://${env.SSO_URL}/" as String - config.env.keycloakRealm = namespace as String - config.videosFolder = "./reports/${testFolder}/videos" as String - config.screenshotsFolder = "./reports/${testFolder}/screenshots" as String - config.reporterOptions.reportDir = "./reports/${testFolder}/mochawesome-report" as String + config.baseUrl = "https://${generateUrlBezeichner(bezeichner, appName)}.${env.CLUSTER_BASE_URL}" as String + config.env.dbUrl = "mongodb://${decodeString(vorgangManagerDatabaseSecret.username)}:${parsablePassword}@localhost:${dbPort}/admin?ssl=false&directConnection=true&socketTimeoutMS=30000&heartbeatFrequencyMS=10000" as String + config.env.keycloakUrl = "https://${env.SSO_URL}/" as String + config.env.keycloakRealm = namespace as String + config.env.keycloakClient = keycloakClientName as String + config.videosFolder = "./reports/${appVariant}/videos" as String + config.screenshotsFolder = "./reports/${appVariant}/screenshots" as String + config.reporterOptions.reportDir = "./reports/${appVariant}/mochawesome-report" as String - config.specPattern = "src/e2e/${testFolder}/**/*.cy.{js,jsx,ts,tsx}" as String + config.specPattern = "src/e2e/${appVariant}/**/*.cy.{js,jsx,ts,tsx}" as String - config.env.put("search", getElasticsearchEnv(namespace)) - config.env.put("userManager", getUserManagerEnv(namespace, dbPort)) - config.env.put("smocker", getSmockerEnv(namespace)) + config.env.put("search", getElasticsearchEnv(namespace)) + config.env.put("userManager", getUserManagerEnv(namespace, dbPort)) + config.env.put("smocker", getSmockerEnv(namespace)) - writeJSON file: configName, json: config + writeJSON file: configName, json: config - sh "cat ${configName}" - } + sh "cat ${configName}" + } - return "cypress-ci-"+testFolder+".config.ts" + return "cypress-ci-"+appVariant+".config.ts" } +String generateUrlBezeichner(String bezeichner, String appName){ + if(appName == 'admin-e2e'){ + return "${bezeichner}-admin"; + } + return bezeichner; +} + + + String makePasswordUrlConform(String password) { return sh (script: "printf %s ${password} | jq -sRr @uri", returnStdout: true); } @@ -793,7 +906,7 @@ String generateNamespace(String bezeichner) { } String decodeString(String encoded) { - return sh (script: "echo -n ${encoded} | base64 --decode", returnStdout: true) + return sh (script: "echo -n ${encoded} | base64 --decode", returnStdout: true) } Map getElasticsearchSecret(String namespace) { diff --git a/alfa-client/apps/alfa-e2e/Jenkinsfile-static b/alfa-client/Jenkinsfile.e2e.static similarity index 99% rename from alfa-client/apps/alfa-e2e/Jenkinsfile-static rename to alfa-client/Jenkinsfile.e2e.static index 49a92dd823cb02a53f072fa3a55f21facc3c6527..2e499f9abbaf8c2918628b462f2f79a056df66d6 100644 --- a/alfa-client/apps/alfa-e2e/Jenkinsfile-static +++ b/alfa-client/Jenkinsfile.e2e.static @@ -16,7 +16,7 @@ pipeline { environment { BLUE_OCEAN_URL = "https://jenkins.ozg-sh.de/job/E2E%20Tests/job/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/" BUNDESLAND = 'by' - ENVIRONMENT = 'dev' + ENVIRONMENT = 'dev' SSO_URL = 'sso.dev.by.ozg-cloud.de' CLUSTER_BASE_URL = 'dev.by.ozg-cloud.de' FAILED_STAGE = '' @@ -552,7 +552,7 @@ String generateNamespace(String bezeichner) { } String decodeString(String encoded) { - return sh(script: "echo -n ${encoded} | base64 --decode", returnStdout: true) + return sh(script: "echo -n ${encoded} | base64 --decode", returnStdout: true) } Map getElasticsearchSecret(String namespace) { diff --git a/alfa-client/apps/admin-e2e/README.md b/alfa-client/apps/admin-e2e/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cc1f1c46a2e2c7c034d661d9595990bbd606b370 --- /dev/null +++ b/alfa-client/apps/admin-e2e/README.md @@ -0,0 +1,9 @@ +## Allgemein + +Dieses Teilprojekt enthält die End-2-End Tests für die Admin-Anwendung. + +Der Aufbau ist analog der [E2E-Tests für Alfa](../alfa-e2e/README.md). + +Bei Ausführung mit Jenkins im Cluster wird das [Jenkinsfile.e2e](../../Jenkinsfile.e2e) verwendet. + +Bei lokaler Ausführung die hier abgelegte [docker-compose.yml](docker-compose.yml) verwenden. diff --git a/alfa-client/apps/admin-e2e/cypress-ci-main-tests.config.ts b/alfa-client/apps/admin-e2e/cypress-ci-main-tests.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..debc5e3e19864e0afbd6b3376b24aec1be23d3c4 --- /dev/null +++ b/alfa-client/apps/admin-e2e/cypress-ci-main-tests.config.ts @@ -0,0 +1,25 @@ +import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; +import { defineConfig } from 'cypress'; + +//Cypress config is generated by JenkinsFile +const cypressConfig = require('./cypress-ci-main-tests.json'); +const cypressEvents = require('./src/support/cypress-tasks.ts'); + +export default defineConfig({ + e2e: { + ...nxE2EPreset(__dirname), + ...cypressConfig, + setupNodeEvents(on, config) { + return cypressEvents(on, config); + }, + }, + retries: { + experimentalStrategy: 'detect-flake-and-pass-on-threshold', + experimentalOptions: { + maxRetries: 2, + passesRequired: 1, + }, + openMode: true, + runMode: true, + }, +}); diff --git a/alfa-client/apps/admin-e2e/cypress-ci.json b/alfa-client/apps/admin-e2e/cypress-ci.json new file mode 100644 index 0000000000000000000000000000000000000000..ca9f95c11d0896e1559b198fe1521e9f5c95b423 --- /dev/null +++ b/alfa-client/apps/admin-e2e/cypress-ci.json @@ -0,0 +1,22 @@ +{ + "env": { + "database": "vorgang-manager-database", + "keycloakClient": "admin" + }, + "fileServerFolder": ".", + "fixturesFolder": "./src/fixtures", + "modifyObstructiveCode": false, + "video": true, + "chromeWebSecurity": false, + "reporter": "../../node_modules/cypress-mochawesome-reporter", + "defaultCommandTimeout": 10000, + "supportFile": "./src/support/e2e.ts", + "testIsolation": false, + "reporterOptions": { + "html": false, + "json": true, + "quite": true, + "reportFilename": "report", + "overwrite": false + } +} diff --git a/alfa-client/apps/admin-e2e/cypress.config.json b/alfa-client/apps/admin-e2e/cypress.config.json index 136d40d4f8a967df5e477627ba6c81b37d58080d..7bab4470a97551fc92eee55d557dfd983d382fe3 100644 --- a/alfa-client/apps/admin-e2e/cypress.config.json +++ b/alfa-client/apps/admin-e2e/cypress.config.json @@ -19,7 +19,7 @@ "reporterOptions": { "html": false, "json": true, - "reportDir": "./reports/mochawesome-report", + "reportDir": "./reports/main-tests/mochawesome-report", "reportFilename": "report", "overwrite": true } diff --git a/alfa-client/apps/admin-e2e/src/e2e/app/0-login-logout.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/app/0-login-logout.cy.ts similarity index 68% rename from alfa-client/apps/admin-e2e/src/e2e/app/0-login-logout.cy.ts rename to alfa-client/apps/admin-e2e/src/e2e/main-tests/app/0-login-logout.cy.ts index fc19b08d96e0a250e5fa64f323c0e44095458ab1..cbee0dcfa84f4ca39bc865b67cebb499194b7920 100644 --- a/alfa-client/apps/admin-e2e/src/e2e/app/0-login-logout.cy.ts +++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/app/0-login-logout.cy.ts @@ -1,8 +1,8 @@ -import { HeaderE2EComponent } from '../../page-objects/header.po'; -import { MainPage } from '../../page-objects/main.po'; -import { reload } from '../../support/cypress-helper'; -import { exist } from '../../support/cypress.util'; -import { loginByUi } from '../../support/user-util'; +import { HeaderE2EComponent } from '../../../page-objects/header.po'; +import { MainPage } from '../../../page-objects/main.po'; +import { reload } from '../../../support/cypress-helper'; +import { exist } from '../../../support/cypress.util'; +import { loginByUi } from '../../../support/user-util'; describe('Login and Logout', () => { const mainPage: MainPage = new MainPage(); diff --git a/alfa-client/apps/admin-e2e/src/e2e/app/buildinfo.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/app/buildinfo.cy.ts similarity index 57% rename from alfa-client/apps/admin-e2e/src/e2e/app/buildinfo.cy.ts rename to alfa-client/apps/admin-e2e/src/e2e/main-tests/app/buildinfo.cy.ts index 18e94c6e8ac38641fb5555c55e5ae4f17b0e33a7..aa93008afd7b2a61765af4cfc88fc712fe691dec 100644 --- a/alfa-client/apps/admin-e2e/src/e2e/app/buildinfo.cy.ts +++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/app/buildinfo.cy.ts @@ -1,8 +1,8 @@ -import { BuildInfoE2EComponent } from '../../components/buildinfo/buildinfo.e2e.component'; -import { HeaderE2EComponent } from '../../page-objects/header.po'; -import { MainPage } from '../../page-objects/main.po'; -import { exist } from '../../support/cypress.util'; -import { loginAsAriane } from '../../support/user-util'; +import { BuildInfoE2EComponent } from '../../../components/buildinfo/buildinfo.e2e.component'; +import { HeaderE2EComponent } from '../../../page-objects/header.po'; +import { MainPage } from '../../../page-objects/main.po'; +import { exist } from '../../../support/cypress.util'; +import { loginAsAriane } from '../../../support/user-util'; describe('Buildinfo', () => { const mainPage: MainPage = new MainPage(); diff --git a/alfa-client/apps/admin-e2e/src/e2e/benutzer_rollen/benutzer_rollen.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts similarity index 82% rename from alfa-client/apps/admin-e2e/src/e2e/benutzer_rollen/benutzer_rollen.cy.ts rename to alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts index 45b22031b07206ebfc1b7a5ce62c288c99f62e95..d1c52395edf3286ee593f72c2f5cc5c752a7de4b 100644 --- a/alfa-client/apps/admin-e2e/src/e2e/benutzer_rollen/benutzer_rollen.cy.ts +++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts @@ -1,7 +1,7 @@ -import { BenutzerE2EComponent } from '../../components/benutzer/benutzer.e2e.component'; -import { MainPage } from '../../page-objects/main.po'; -import { exist } from '../../support/cypress.util'; -import { loginAsAriane } from '../../support/user-util'; +import { MainPage } from 'apps/admin-e2e/src/page-objects/main.po'; +import { exist } from 'apps/admin-e2e/src/support/cypress.util'; +import { loginAsAriane } from 'apps/admin-e2e/src/support/user-util'; +import { BenutzerE2EComponent } from 'apps/admin-e2e/src/components/benutzer/benutzer.e2e.component'; const mainPage: MainPage = new MainPage(); const benutzerPage: BenutzerE2EComponent = new BenutzerE2EComponent(); diff --git a/alfa-client/apps/admin-e2e/src/e2e/postfach/signatur.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/postfach/signatur.cy.ts similarity index 67% rename from alfa-client/apps/admin-e2e/src/e2e/postfach/signatur.cy.ts rename to alfa-client/apps/admin-e2e/src/e2e/main-tests/postfach/signatur.cy.ts index 1a9d07d9cd02a699d33ad6f24e3df8fb94d24d89..884093ac7af1a52e3485bd8133a431515fa3f095 100644 --- a/alfa-client/apps/admin-e2e/src/e2e/postfach/signatur.cy.ts +++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/postfach/signatur.cy.ts @@ -1,8 +1,8 @@ -import { PostfachE2EComponent } from '../../components/postfach/postfach.e2e.component'; -import { HeaderE2EComponent } from '../../page-objects/header.po'; -import { MainPage, waitForSpinnerToDisappear } from '../../page-objects/main.po'; -import { exist } from '../../support/cypress.util'; -import { loginAsAriane } from '../../support/user-util'; +import { PostfachE2EComponent } from '../../../components/postfach/postfach.e2e.component'; +import { HeaderE2EComponent } from '../../../page-objects/header.po'; +import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; +import { exist } from '../../../support/cypress.util'; +import { loginAsAriane } from '../../../support/user-util'; describe('Signatur', () => { const mainPage: MainPage = new MainPage(); diff --git a/alfa-client/apps/admin-e2e/src/fixtures/argocd/by-admin-dev.yaml b/alfa-client/apps/admin-e2e/src/fixtures/argocd/by-admin-dev.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f307b1c0c8ff3aaf6d33b000ec7500a4e55ae065 --- /dev/null +++ b/alfa-client/apps/admin-e2e/src/fixtures/argocd/by-admin-dev.yaml @@ -0,0 +1,37 @@ +ozgcloud: + bezeichner: admine2emain + environment: dev +e2eTest: true +project: + destinations: + - namespace: "*" + server: https://kubernetes.default.svc + +administration: + enabled: true + +admin_client: + enabled: true + ingress: + use_staging_cert: true + +alfa: + env: + overrideSpringProfiles: "oc,e2e,dev" + ingress: + use_staging_cert: true + +vorgang_manager: + env: + overrideSpringProfiles: "oc,e2e,dev" + +user_manager: + ozgcloud: + usersync: + onstart: false + period: disabled + ingress: + use_staging_cert: true + +smocker: + enabled: false \ No newline at end of file diff --git a/alfa-client/apps/alfa-e2e/README.md b/alfa-client/apps/alfa-e2e/README.md index e54e685002d7a1d2eddf7ddbcf68214f741a5f0f..e8fd2fba20457053b9a043e3cdbadfa696692c5e 100644 --- a/alfa-client/apps/alfa-e2e/README.md +++ b/alfa-client/apps/alfa-e2e/README.md @@ -1,14 +1,39 @@ -# E2E - ## Allgemein -Die E2E Tests werden in parallen Jenkins Stages in seperaten Namespaces durchgeführt. -`einheitlicher-ansprechpartener` -> 'EA'-Umgebung -`main-tests` -> 'Dev'-Umgebung --> es dürfen nur die der Umgebung entsprechenden User für die Tests genutzt werden. -(siehe dokumentation/Anwender/Standardbenutzer.md) +Dieses Teilprojekt bündelt: +* Die End-2-End Tests für die Alfa-Anwendung +* Das Setup für verschiedene Konfigurationsvarianten + +Die Konfigurationsvarianten sind: +* Ausführungsart und Umgebung + * lokal + * Im Cluster (dynamisch deployed) + * Im Cluster (statisch) +* Fachlich unterschiedliche Testgruppen + * `einheitlicher-ansprechpartner` -> 'EA'-Umgebung + * `main-tests` -> 'Dev'-Umgebung + +Dabei benötigen die Testgruppen (sogenannte "App-Varianten", siehe Verzeichnis [src/e2e](src/e2e)) jeweils eine eigene Umgebung in der gewählten Ausführungsart. + +## Lokale Ausführung +Siehe [Entwicklungsdokumentation](https://git.ozg-sh.de/ozgcloud-doc/dokumentation/src/branch/master/Entwicklungsumgebung#e2e-tests). + +## Jenkins/Cluster Ausführung +Die E2E Tests werden in parallelen Jenkins Stages in separaten Namespaces durchgeführt. -## Gegen ein bestehenden Namespace testen +Es dürfen nur die der Umgebung entsprechenden User für die Tests genutzt werden (siehe [Standardbenutzer](https://git.ozg-sh.de/ozgcloud-doc/dokumentation/src/branch/master/Anwender/Standardbenutzer.md)). + +Es gibt 2 Jenkinsfiles: +* E2E ("main") - Das derzeit benutzte Hauptprofil. Namespaces werden hier neu aufgebaut. +* Static - Profil, wenn eine bestehender Namespace (ggf. in ganz bestimmter Konfiguration) getestet werden soll. + +### Dynamisch deployed +* siehe: [Jenkinsfile.e2e](../../Jenkinsfile.e2e) +* Im Verzeichnis 'src/fixtures/argocd' liegen die Kubernetes Templates (ArgoCD-Namespace-Helm-Charts) +* Neue Umgebungen werden im Repo [gitops im Branch "e2e"](https://git.ozg-sh.de/ozgcloud-devops/gitops/src/branch/e2e) eingetragen. + +### Gegen ein bestehenden Namespace testen +Siehe: [Jenkinsfile.e2e](../../Jenkinsfile.e2e.static) Beispiel Namespace: sh-mastere2emain-dev @@ -20,10 +45,11 @@ Beispiel Namespace: sh-mastere2emain-dev 4. Cypress mit entsprechender config starten: `npm run cypress:open -- --config-file cypress-master-main.json` -## docker-compose +## Dev Hinweise ### -march Architektur In die `.env` Datei eintragen: - - USER_MANAGER_DOCKER_IMAGE=march-snapshot-latest \ No newline at end of file +``` +USER_MANAGER_DOCKER_IMAGE=march-snapshot-latest +``` \ No newline at end of file diff --git a/alfa-client/apps/alfa-e2e/cypress.config.json b/alfa-client/apps/alfa-e2e/cypress.config.json index 3a604c010deb694376105420fb38252bc1029efe..10160a6f1a1a224da71dcdc3671381d635fed8b9 100644 --- a/alfa-client/apps/alfa-e2e/cypress.config.json +++ b/alfa-client/apps/alfa-e2e/cypress.config.json @@ -34,7 +34,7 @@ "reporterOptions": { "html": false, "json": true, - "reportDir": "./reports/mochawesome-report", + "reportDir": "./reports/main-tests/mochawesome-report", "reportFilename": "report", "overwrite": true } diff --git a/alfa-client/apps/alfa-e2e/run-tests.sh b/alfa-client/apps/alfa-e2e/run-tests.sh deleted file mode 100755 index 6b7f5098a285a5417326b611f500c686fcd1f08f..0000000000000000000000000000000000000000 --- a/alfa-client/apps/alfa-e2e/run-tests.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -export NO_COLOR=1 - -REPORT_FOLDER=$1 -CONFIG_FILE="${2:-cypress.config.ts}" - -echo "Run E2E for $REPORT_FOLDER with configuration apps/alfa-e2e/$CONFIG_FILE..." - -rm -rf apps/alfa-e2e/reports/${REPORT_FOLDER} - -npx cypress run --project apps/alfa-e2e --spec apps/alfa-e2e/src/e2e/${REPORT_FOLDER} --config-file $CONFIG_FILE - -TEST_RESULT=$? - -if [ -d "apps/alfa-e2e/reports/${REPORT_FOLDER}/mochawesome-report/.jsons" ]; then - mv apps/alfa-e2e/reports/${REPORT_FOLDER}/mochawesome-report/.jsons apps/alfa-e2e/reports/${REPORT_FOLDER}/mochawesome-report/jsons - npx mochawesome-merge apps/alfa-e2e/reports/${REPORT_FOLDER}/mochawesome-report/**/*.json > apps/alfa-e2e/reports/${REPORT_FOLDER}/report.json - # Workaround: mochawesome's "screenshotsFolder" value is not added in the generated HTML file. Add "screenshots" to image paths. - sed --in-place --regexp-extended 's/"([^"]*\.png)/"screenshots\1/' apps/alfa-e2e/reports/${REPORT_FOLDER}/report.json - npx marge apps/alfa-e2e/reports/${REPORT_FOLDER}/report.json -f report -o apps/alfa-e2e/reports/${REPORT_FOLDER} -else - echo "ERROR: Reports do not exist at apps/alfa-e2e/reports/${REPORT_FOLDER}/mochawesome-report/.jsons" -fi - -exit $TEST_RESULT \ No newline at end of file diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml index 58e0660e0f37cba42cc6ab8ed1b0c824d5e3902d..d045ee9c6f58b1df37fc04f1260c0b75178a4bb1 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml +++ b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml @@ -7,6 +7,14 @@ project: - namespace: '*' server: https://kubernetes.default.svc +administration: + enabled: true + +admin_client: + enabled: true + ingress: + use_staging_cert: true + alfa: env: overrideSpringProfiles: 'oc,ea,e2e,dev' diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml index ed32236cd2d0a9b3c211c4c54b7a726e212cf500..1bcb0012c4aa771b977d6834c8d9825b20cb4f11 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml +++ b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml @@ -6,11 +6,10 @@ project: destinations: - namespace: "*" server: https://kubernetes.default.svc + alfa: env: overrideSpringProfiles: "oc,e2e,dev" - customList: - ozgcloud_feature_bescheid-wizard: "true" ingress: use_staging_cert: true ozgcloud: diff --git a/alfa-client/apps/run-tests.sh b/alfa-client/apps/run-tests.sh new file mode 100755 index 0000000000000000000000000000000000000000..eadee4428cd9620ad5c66da8d44a0459f1e42c58 --- /dev/null +++ b/alfa-client/apps/run-tests.sh @@ -0,0 +1,44 @@ +#!/bin/bash +export NO_COLOR=1 + +if [ $# -eq 0 ]; then + >&2 echo "This script is for Jenkins Execution of E2E-Tests" + >&2 echo "Example: ./run-tests.sh admin-e2e main-tests cypress.config.ts" + exit 1 +fi +APP_NAME="${1:-alfa-e2e}" +APP_VARIATION="${2:-main-tests}" +CONFIG_FILE="${3:-cypress.config.ts}" + +if [ -z $APP_NAME ]; then echo "App Folder not set" && exit 1; fi +if [ -z $APP_VARIATION ]; then echo "Variation Name not set" && exit 1; fi +if [ -z $CONFIG_FILE ]; then echo "Config File not set" && exit 1; fi + +SCRIPT_DIR="$(dirname "$0")" +BASE_PATH=${SCRIPT_DIR}/${APP_NAME} +SPEC_GROUP=${BASE_PATH}/src/e2e/${APP_VARIATION} +COMMAND="npx cypress run --project ${BASE_PATH} --spec ${SPEC_GROUP} --config-file ${CONFIG_FILE}" +REPORT_PATH=${BASE_PATH}/reports/${APP_VARIATION} + +echo "Run E2E for ${APP_NAME} with command: '$COMMAND'" + +rm -rf ${REPORT_PATH} + +eval $COMMAND +TEST_RESULT=$? + +if [ -d "${REPORT_PATH}" ]; then + MOCHA_REPORT_PATH=${REPORT_PATH}/mochawesome-report/ + MOCHA_REPORT_JSONS=${MOCHA_REPORT_PATH}.jsons + MOCHA_REPORT_FILE=${MOCHA_REPORT_PATH}report.json + + mv ${MOCHA_REPORT_JSONS} ${MOCHA_REPORT_PATH}/jsons + npx mochawesome-merge ${MOCHA_REPORT_PATH}**/*.json > ${MOCHA_REPORT_FILE} + # Workaround: mochawesome's "screenshotsFolder" value is not added in the generated HTML file. Add "screenshots" to image paths. + sed --in-place --regexp-extended 's/"([^"]*\.png)/"screenshots\1/' ${MOCHA_REPORT_FILE} + npx marge ${MOCHA_REPORT_FILE} -f report -o ${REPORT_PATH} +else + echo "ERROR: Reports do not exist at ${REPORT_PATH}" +fi + +exit $TEST_RESULT \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/forwarding/ForwardingLandesnetzInfoServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/forwarding/ForwardingLandesnetzInfoServiceTest.java index f314dbef0bf2c48ccfb35d1f974ce9e6edaa91cc..19bea4224f26612e6447965cc090ab8eb52efbec 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/forwarding/ForwardingLandesnetzInfoServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/forwarding/ForwardingLandesnetzInfoServiceTest.java @@ -33,9 +33,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.Spy; -import org.springframework.core.io.ResourceLoader; import org.springframework.test.util.ReflectionTestUtils; class ForwardingLandesnetzInfoServiceTest { @@ -43,8 +41,6 @@ class ForwardingLandesnetzInfoServiceTest { @Spy @InjectMocks private ForwardingLandesnetzInfoService service; - @Mock - private ResourceLoader resourceLoader; @DisplayName("Is email in landesnetz") @Nested