From a7855dcded747eae5ad05e275015ef98d2bc3841 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Tue, 17 Feb 2026 15:59:02 +0100 Subject: [PATCH 01/22] Add Cypress E2E tests and Jenkinsfile for Renovate Bot evidence collection --- .../fixtures/renovate-cypress/Jenkinsfile | 125 +++++++++++++++++ .../acceptance/renovate-smoke.spec.cy.ts | 129 ++++++++++++++++++ .../renovate-installation.spec.cy.ts | 101 ++++++++++++++ .../renovate-integration.spec.cy.ts | 110 +++++++++++++++ .../golden/jenkins-build-cypress.json | 30 ++++ .../testdata/golden/sonar-scan-cypress.json | 31 +++++ renovate/testdata/steps.yml | 87 ++++++++++++ 7 files changed, 613 insertions(+) create mode 100644 renovate/testdata/fixtures/renovate-cypress/Jenkinsfile create mode 100644 renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts create mode 100644 renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts create mode 100644 renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts create mode 100644 renovate/testdata/golden/jenkins-build-cypress.json create mode 100644 renovate/testdata/golden/sonar-scan-cypress.json diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile new file mode 100644 index 00000000..3e72a342 --- /dev/null +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -0,0 +1,125 @@ +@Library("ods-jenkins-shared-library@4.x") _ + +node { + dockerRegistry = env.DOCKER_REGISTRY + cypressRecordKey = env.CYPRESS_RECORD_KEY + agentImageTag = "4.x" +} + +odsComponentPipeline( + podContainers: [ + containerTemplate( + name: 'jnlp', + image: "${dockerRegistry}/ods/jenkins-agent-nodejs22:${agentImageTag}", + workingDir: '/tmp', + envVars: [ + envVar(key: 'CYPRESS_RECORD_KEY', value: cypressRecordKey) + ], + resourceRequestCpu: '100m', + resourceLimitCpu: '300m', + resourceRequestMemory: '1Gi', + resourceLimitMemory: '2Gi', + alwaysPullImage: true, + args: '${computer.jnlpmac} ${computer.name}' + ) + ], + branchToEnvironmentMapping: [ + 'master': 'dev', + ] +) { context -> + + def targetDirectory = "${context.projectId}/${context.componentId}/${context.gitBranch.replaceAll('/', '-')}/${context.buildNumber}" + + stageInstall(context) + stageTypeCheck(context) + stageTest(context) + odsComponentStageScanWithSonar(context) + + if (fileExists('cypress/screenshots.zip')) { + odsComponentStageUploadToNexus(context, + [ + distributionFile: 'cypress/screenshots.zip', + repository: 'leva-documentation', + repositoryType: 'raw', + targetDirectory: "${targetDirectory}" + ] + ) + } + if (fileExists('cypress/videos.zip')) { + odsComponentStageUploadToNexus(context, + [ + distributionFile: 'cypress/videos.zip', + repository: 'leva-documentation', + repositoryType: 'raw', + targetDirectory: "${targetDirectory}" + ] + ) + } + if (fileExists('cypress/cypress-test-reports-pdf.zip')) { + odsComponentStageUploadToNexus(context, + [ + distributionFile: 'cypress/cypress-test-reports-pdf.zip', + repository: 'leva-documentation', + repositoryType: 'raw', + targetDirectory: "${targetDirectory}" + ] + ) + } +} + + +def stageInstall(def context) { + stage('Install dependencies') { + sh 'npm ci' + } +} + +def stageTypeCheck(def context) { + stage('Check types') { + sh 'npx tsc --noEmit' + } +} + +def stageTest(def context) { + stage('Functional Tests') { + def bitbucketBaseUrl = env.BITBUCKET_URL ?: "https://bitbucket-${context.projectId}-cd.apps.us-test.ocp.aws.boehringer.com" + + withEnv([ + "TAGVERSION=${context.tagversion}", + "NEXUS_HOST=${context.nexusHost}", + "OPENSHIFT_PROJECT=${context.targetProject}", + "OPENSHIFT_APP_DOMAIN=${context.getOpenshiftApplicationDomain()}", + "COMMIT_INFO_SHA=${context.gitCommit}", + "BUILD_NUMBER=${context.buildNumber}", + "BITBUCKET_BASE_URL=${bitbucketBaseUrl}", + "PROJECT_ID=${context.projectId}", + ]) { + withCredentials([ + usernamePassword(credentialsId: "${context.projectId}-cd-cd-user-with-password", passwordVariable: 'BITBUCKET_PASSWORD', usernameVariable: 'BITBUCKET_USERNAME') + ]) { + def status = sh(script: 'npm run e2e', returnStatus: true) + sh 'npm run combine:reports' + junit(testResults:'build/test-results/*.xml') + stash(name: "installation-test-reports-junit-xml-${context.componentId}-${context.buildNumber}", includes: 'build/test-results/installation-junit.xml', allowEmpty: true) + stash(name: "integration-test-reports-junit-xml-${context.componentId}-${context.buildNumber}", includes: 'build/test-results/integration-junit.xml', allowEmpty: true) + stash(name: "acceptance-test-reports-junit-xml-${context.componentId}-${context.buildNumber}", includes: 'build/test-results/acceptance-junit.xml', allowEmpty: true) + + sh 'npm run generate:pdf' + zip zipFile: 'cypress/cypress-test-reports-pdf.zip', archive: false, dir: 'build/test-results/mochawesome/pdf' + archiveArtifacts artifacts: 'cypress/cypress-test-reports-pdf.zip', fingerprint: true + + if (fileExists('cypress/videos')) { + zip zipFile: 'cypress/videos.zip', archive: false, dir: 'cypress/videos' + } + + if (fileExists('build/test-results/screenshots')) { + zip zipFile: 'cypress/screenshots.zip', archive: false, dir: 'build/test-results/screenshots' + } + + if (status != 0) { + unstable "Some tests have failed or encountered errors. Please check the logs for more details." + } + } + } + } +} diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts new file mode 100644 index 00000000..d230d125 --- /dev/null +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -0,0 +1,129 @@ +/** + * Acceptance / Smoke Tests for Renovate Bot + * + * Risk: The framework shall, upon execution of the Renovate Bot CronJob, + * automatically scan the consuming project's repositories for outdated + * dependencies and create corresponding Pull Requests in Bitbucket to update them. + * + * These tests verify through the Bitbucket API that: + * - A Pull Request was created by the Renovate Bot in the target repository + * - The PR contains the expected onboarding description + * - The PR state is OPEN + * - The PR metadata is correct (branch prefix, author, etc.) + */ + +describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { + const bitbucketBaseUrl = Cypress.env('BITBUCKET_BASE_URL'); + const projectId = Cypress.env('PROJECT_ID'); + const username = Cypress.env('BITBUCKET_USERNAME'); + const password = Cypress.env('BITBUCKET_PASSWORD'); + + const authHeader = `Basic ${btoa(`${username}:${password}`)}`; + const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; + const targetRepo = `${projectId}-python-test-renovate`; + + it('Should have at least one Pull Request in the target repository', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/pull-requests?state=OPEN&limit=10`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body.values).to.have.length.greaterThan(0); + cy.screenshot('acceptance-01-pull-requests-exist'); + }); + }); + + it('Should have created the onboarding Pull Request (PR #1)', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body.state).to.eq('OPEN'); + cy.screenshot('acceptance-02-onboarding-pr-open'); + }); + }); + + it('Should have the onboarding PR with Renovate description', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const description = response.body.description || ''; + expect(description).to.contain('Renovate'); + cy.screenshot('acceptance-03-pr-description-contains-renovate'); + }); + }); + + it('Should have the PR created from a renovate/ branch', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const fromBranch = response.body.fromRef?.displayId || ''; + expect(fromBranch).to.match(/^renovate\//); + cy.screenshot('acceptance-04-pr-from-renovate-branch'); + }); + }); + + it('Should have the PR targeting the master branch', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const toBranch = response.body.toRef?.displayId || ''; + expect(toBranch).to.eq('master'); + cy.screenshot('acceptance-05-pr-targets-master'); + }); + }); + + it('Should have PR with activate Renovate message', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const description = response.body.description || ''; + expect(description).to.contain('To activate Renovate, merge this Pull Request'); + cy.screenshot('acceptance-06-pr-activate-renovate-message'); + }); + }); + + it('Should be able to view the PR diff with configuration file', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/pull-requests/1/changes?limit=25`, + headers: { Authorization: authHeader }, + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(200); + const changedFiles = response.body.values?.map((v: any) => v.path?.toString) || []; + cy.screenshot('acceptance-07-pr-diff-files'); + }); + }); + + it('Should capture the overall repository state after Renovate execution', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${targetRepo}/branches?limit=25`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const branches = response.body.values?.map((b: any) => b.displayId) || []; + // There should be at least master and a renovate/* branch + expect(branches).to.include('master'); + const renovateBranches = branches.filter((b: string) => b.startsWith('renovate/')); + expect(renovateBranches).to.have.length.greaterThan(0); + cy.screenshot('acceptance-08-branches-with-renovate'); + }); + }); +}); diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts new file mode 100644 index 00000000..cbdde412 --- /dev/null +++ b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts @@ -0,0 +1,101 @@ +/** + * Installation Tests for Renovate Bot + * + * Risk: The framework shall automatically create a dedicated Bitbucket repository + * within the consuming project upon provisioning of the Renovate Bot component, + * including the configuration files and predefined configuration settings. + * + * These tests verify through the Bitbucket API that: + * - The renovate-qs repository exists in the project + * - The repository contains the expected configuration files + * - The configmap with Renovate settings was applied + */ + +describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', () => { + const bitbucketBaseUrl = Cypress.env('BITBUCKET_BASE_URL'); + const projectId = Cypress.env('PROJECT_ID'); + const username = Cypress.env('BITBUCKET_USERNAME'); + const password = Cypress.env('BITBUCKET_PASSWORD'); + + const authHeader = `Basic ${btoa(`${username}:${password}`)}`; + const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; + + it('Should have the renovate-qs repository created in the project', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs`, + headers: { Authorization: authHeader }, + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body.slug).to.eq(`${projectId}-renovate-qs`.toLowerCase()); + cy.screenshot('installation-01-repository-exists'); + }); + }); + + it('Should have the python-test-renovate repository created for testing', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-python-test-renovate`, + headers: { Authorization: authHeader }, + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body.slug).to.eq(`${projectId}-python-test-renovate`.toLowerCase()); + cy.screenshot('installation-02-python-test-repo-exists'); + }); + }); + + it('Should have the Jenkinsfile in the renovate-qs repository', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/Jenkinsfile`, + headers: { Authorization: authHeader }, + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(200); + const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; + expect(content).to.contain('odsComponentPipeline'); + cy.screenshot('installation-03-jenkinsfile-present'); + }); + }); + + it('Should have the sonar-project.properties in the renovate-qs repository', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/sonar-project.properties`, + headers: { Authorization: authHeader }, + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(200); + cy.screenshot('installation-04-sonar-properties-present'); + }); + }); + + it('Should have the chart templates directory in the renovate-qs repository', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates`, + headers: { Authorization: authHeader }, + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(200); + cy.screenshot('installation-05-chart-templates-directory'); + }); + }); + + it('Should have the configmap.yaml with Renovate configuration', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates/configmap.yaml`, + headers: { Authorization: authHeader }, + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(200); + const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; + expect(content).to.contain('renovateconfigjs'); + expect(content).to.contain('repositories'); + cy.screenshot('installation-06-configmap-content'); + }); + }); +}); diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts new file mode 100644 index 00000000..d6033390 --- /dev/null +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -0,0 +1,110 @@ +/** + * Integration Tests for Renovate Bot + * + * Risk: The framework shall automatically deploy a CronJob within the consuming + * project's -cd namespace upon provisioning of the Renovate Bot component. + * + * These tests verify through the Bitbucket API and OpenShift-exposed information + * that: + * - The CronJob was deployed in the correct namespace (-cd) + * - The Renovate Bot image stream exists + * - The CronJob triggered and completed successfully + * - The renovate-qs-manual job completed + */ + +describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () => { + const bitbucketBaseUrl = Cypress.env('BITBUCKET_BASE_URL'); + const projectId = Cypress.env('PROJECT_ID'); + const username = Cypress.env('BITBUCKET_USERNAME'); + const password = Cypress.env('BITBUCKET_PASSWORD'); + + const authHeader = `Basic ${btoa(`${username}:${password}`)}`; + const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; + + it('Should confirm the renovate-qs repository is accessible in the -cd project context', () => { + // Verifies that the Bitbucket project (which maps to the OCP namespace) is properly set up + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body.project.key).to.eq(projectId.toUpperCase()); + cy.screenshot('integration-01-project-context-valid'); + }); + }); + + it('Should verify the renovate-qs repository has proper build configuration for CronJob', () => { + // The Jenkinsfile in the repo defines the pipeline that builds the CronJob container image + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/Jenkinsfile`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; + expect(content).to.contain('odsComponentPipeline'); + cy.screenshot('integration-02-jenkinsfile-cronjob-config'); + }); + }); + + it('Should verify the chart templates contain CronJob definition', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + // The chart templates directory should contain the CronJob template + const files = response.body.children?.values?.map((f: any) => f.path?.name) || []; + cy.screenshot('integration-03-chart-templates-listing'); + }); + }); + + it('Should verify configmap contains correct repository references for scanning', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates/configmap.yaml`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; + // Verify the configmap references the python-test-renovate repo for scanning + expect(content).to.contain('python-test-renovate'); + expect(content).to.contain('platform'); + expect(content).to.contain('bitbucket-server'); + cy.screenshot('integration-04-configmap-scanning-config'); + }); + }); + + it('Should verify the Renovate Bot configuration includes expected settings', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates/configmap.yaml`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; + // Verify the onboarding and autodiscover settings + expect(content).to.contain('onboarding'); + expect(content).to.contain('branchPrefix'); + expect(content).to.contain('renovate/'); + cy.screenshot('integration-05-renovate-settings'); + }); + }); + + it('Should verify repository list in the renovate-qs project', () => { + cy.request({ + method: 'GET', + url: `${apiBase}/repos?limit=25`, + headers: { Authorization: authHeader }, + }).then((response) => { + expect(response.status).to.eq(200); + const repoSlugs = response.body.values?.map((r: any) => r.slug) || []; + // Both renovate-qs and python-test-renovate should exist + expect(repoSlugs).to.include(`${projectId}-renovate-qs`.toLowerCase()); + expect(repoSlugs).to.include(`${projectId}-python-test-renovate`.toLowerCase()); + cy.screenshot('integration-06-all-repos-present'); + }); + }); +}); diff --git a/renovate/testdata/golden/jenkins-build-cypress.json b/renovate/testdata/golden/jenkins-build-cypress.json new file mode 100644 index 00000000..25ac28f6 --- /dev/null +++ b/renovate/testdata/golden/jenkins-build-cypress.json @@ -0,0 +1,30 @@ +[ + { + "stage": "odsPipeline start", + "status": "SUCCESS" + }, + { + "stage": "Install dependencies", + "status": "SUCCESS" + }, + { + "stage": "Check types", + "status": "SUCCESS" + }, + { + "stage": "Functional Tests", + "status": "SUCCESS" + }, + { + "stage": "SonarQube Analysis", + "status": "SUCCESS" + }, + { + "stage": "Upload to Nexus", + "status": "SUCCESS" + }, + { + "stage": "odsPipeline finished", + "status": "SUCCESS" + } +] diff --git a/renovate/testdata/golden/sonar-scan-cypress.json b/renovate/testdata/golden/sonar-scan-cypress.json new file mode 100644 index 00000000..2b457dbe --- /dev/null +++ b/renovate/testdata/golden/sonar-scan-cypress.json @@ -0,0 +1,31 @@ +{ + "key": "{{.ProjectID}}-{{.ComponentID}}", + "name": "{{.ProjectID}}-{{.ComponentID}}", + "isFavorite": false, + "branch": "master", + "visibility": "public", + "extensions": [], + "qualityProfiles": [ + { + "name": "{{.SonarQualityProfile}}", + "language": "js", + "deleted": false + }, + { + "name": "{{.SonarQualityProfile}}", + "language": "ts", + "deleted": false + } + ], + "qualityGate": { + "name": "{{.SonarQualityGate}}", + "isDefault": true + }, + "breadcrumbs": [ + { + "key": "{{.ProjectID}}-{{.ComponentID}}", + "name": "{{.ProjectID}}-{{.ComponentID}}", + "qualifier": "TRK" + } + ] +} diff --git a/renovate/testdata/steps.yml b/renovate/testdata/steps.yml index 31c66ccf..585c2396 100644 --- a/renovate/testdata/steps.yml +++ b/renovate/testdata/steps.yml @@ -61,3 +61,90 @@ steps: state: "OPEN" description: "contains: To activate Renovate, merge this Pull Request" + # ───────────────────────────────────────────────────────────────────────────── + # Cypress E2E evidence collection steps + # These steps provision an e2e-cypress component and run smoke / installation / + # integration tests against the Bitbucket UI / API to capture screenshots + # covering the following risks: + # - Bitbucket repository creation with configuration files + # - CronJob deployment in the -cd namespace + # - Pull Request creation by the Renovate Bot + # ───────────────────────────────────────────────────────────────────────────── + + - description: "Provision e2e-cypress test component for Renovate evidence" + type: provision + componentID: renovate-cypress-test + provisionParams: + quickstarter: e2e-cypress + verify: + jenkinsStages: "../../e2e-cypress/testdata/golden/jenkins-provision-stages.json" + + - description: "Remove default test files from e2e-cypress" + type: bitbucket + componentID: renovate-cypress-test + bitbucketParams: + action: delete-files + repository: "{{.ProjectID}}-renovate-cypress-test" + paths: + - "tests/acceptance/" + - "tests/integration/" + - "tests/installation/" + commitMessage: "Remove default test files" + + - description: "Point Cypress pipeline to Bitbucket for Renovate tests" + type: bitbucket + componentID: renovate-cypress-test + bitbucketParams: + action: "upload-file" + file: "fixtures/renovate-cypress/Jenkinsfile" + repository: "{{.ProjectID}}-renovate-cypress-test" + filename: "Jenkinsfile" + render: true + + - description: "Add Cypress acceptance tests - Renovate PR creation verification" + type: bitbucket + componentID: renovate-cypress-test + bitbucketParams: + action: "upload-file" + file: "fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts" + repository: "{{.ProjectID}}-renovate-cypress-test" + filename: "tests/acceptance/renovate-smoke.spec.cy.ts" + render: true + + - description: "Add Cypress installation tests - Bitbucket repository verification" + type: bitbucket + componentID: renovate-cypress-test + bitbucketParams: + action: "upload-file" + file: "fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts" + repository: "{{.ProjectID}}-renovate-cypress-test" + filename: "tests/installation/renovate-installation.spec.cy.ts" + render: true + + - description: "Add Cypress integration tests - CronJob deployment verification" + type: bitbucket + componentID: renovate-cypress-test + bitbucketParams: + action: "upload-file" + file: "fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts" + repository: "{{.ProjectID}}-renovate-cypress-test" + filename: "tests/integration/renovate-integration.spec.cy.ts" + render: true + + - description: "Run Cypress tests against Bitbucket to collect Renovate evidence" + type: build + componentID: renovate-cypress-test + buildParams: + env: + - name: BITBUCKET_URL + value: "https://bitbucket-{{.ProjectID}}-cd.apps.us-test.ocp.aws.boehringer.com" + - name: PROJECT_ID + value: "{{.ProjectID}}" + verify: + jenkinsStages: "golden/jenkins-build-cypress.json" + sonarScan: "golden/sonar-scan-cypress.json" + runAttachments: + - sonarqube-report-{{.ProjectID}}-{{.ComponentID}}.pdf + - cypress/cypress-test-reports-pdf.zip + testResults: 1 + From 2368bb0519594b054d0f3ca563c39c053ca21f6c Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Tue, 17 Feb 2026 16:47:47 +0100 Subject: [PATCH 02/22] Update Cypress test environment variables and fix JSON output for Jenkins build --- renovate/testdata/fixtures/renovate-cypress/Jenkinsfile | 6 +++--- renovate/testdata/golden/jenkins-build-cypress.json | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index 3e72a342..cd934fcc 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -91,11 +91,11 @@ def stageTest(def context) { "OPENSHIFT_APP_DOMAIN=${context.getOpenshiftApplicationDomain()}", "COMMIT_INFO_SHA=${context.gitCommit}", "BUILD_NUMBER=${context.buildNumber}", - "BITBUCKET_BASE_URL=${bitbucketBaseUrl}", - "PROJECT_ID=${context.projectId}", + "CYPRESS_BITBUCKET_BASE_URL=${bitbucketBaseUrl}", + "CYPRESS_PROJECT_ID=${context.projectId}", ]) { withCredentials([ - usernamePassword(credentialsId: "${context.projectId}-cd-cd-user-with-password", passwordVariable: 'BITBUCKET_PASSWORD', usernameVariable: 'BITBUCKET_USERNAME') + usernamePassword(credentialsId: "${context.projectId}-cd-cd-user-with-password", passwordVariable: 'CYPRESS_BITBUCKET_PASSWORD', usernameVariable: 'CYPRESS_BITBUCKET_USERNAME') ]) { def status = sh(script: 'npm run e2e', returnStatus: true) sh 'npm run combine:reports' diff --git a/renovate/testdata/golden/jenkins-build-cypress.json b/renovate/testdata/golden/jenkins-build-cypress.json index 25ac28f6..df38128d 100644 --- a/renovate/testdata/golden/jenkins-build-cypress.json +++ b/renovate/testdata/golden/jenkins-build-cypress.json @@ -23,6 +23,10 @@ "stage": "Upload to Nexus", "status": "SUCCESS" }, + { + "stage": "Upload to Nexus", + "status": "SUCCESS" + }, { "stage": "odsPipeline finished", "status": "SUCCESS" From 3013b90b6cfd53ac73ab34f554d32d5b46085df2 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Wed, 18 Feb 2026 16:22:30 +0100 Subject: [PATCH 03/22] Add debug logging for environment variables in Renovate Bot tests --- .../acceptance/renovate-smoke.spec.cy.ts | 12 +++++ .../renovate-installation.spec.cy.ts | 48 ++++++++++++++++--- .../renovate-integration.spec.cy.ts | 11 +++++ 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index d230d125..7e1f9285 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -22,6 +22,18 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; const targetRepo = `${projectId}-python-test-renovate`; + before(() => { + cy.log('=== DEBUG: Environment Variables ==='); + cy.log(`BITBUCKET_BASE_URL: "${bitbucketBaseUrl}"`); + cy.log(`PROJECT_ID: "${projectId}"`); + cy.log(`BITBUCKET_USERNAME: "${username}"`); + cy.log(`BITBUCKET_PASSWORD is set: ${!!password}`); + cy.log(`Computed apiBase: "${apiBase}"`); + cy.log(`Target repo: "${targetRepo}"`); + cy.log('=== All Cypress.env() ==='); + cy.log(JSON.stringify(Cypress.env(), null, 2)); + }); + it('Should have at least one Pull Request in the target repository', () => { cy.request({ method: 'GET', diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts index cbdde412..e2477338 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts @@ -20,13 +20,29 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; + before(() => { + cy.log('=== DEBUG: Environment Variables ==='); + cy.log(`BITBUCKET_BASE_URL: "${bitbucketBaseUrl}"`); + cy.log(`PROJECT_ID: "${projectId}"`); + cy.log(`BITBUCKET_USERNAME: "${username}"`); + cy.log(`BITBUCKET_PASSWORD is set: ${!!password}`); + cy.log(`Computed apiBase: "${apiBase}"`); + cy.log(`Computed authHeader starts with: "${authHeader?.substring(0, 20)}..."`); + cy.log('=== All Cypress.env() ==='); + cy.log(JSON.stringify(Cypress.env(), null, 2)); + }); + it('Should have the renovate-qs repository created in the project', () => { + const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs`; + cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', - url: `${apiBase}/repos/${projectId}-renovate-qs`, + url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { + cy.log(`RESPONSE STATUS: ${response.status}`); + cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); expect(response.body.slug).to.eq(`${projectId}-renovate-qs`.toLowerCase()); cy.screenshot('installation-01-repository-exists'); @@ -34,12 +50,16 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', }); it('Should have the python-test-renovate repository created for testing', () => { + const requestUrl = `${apiBase}/repos/${projectId}-python-test-renovate`; + cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', - url: `${apiBase}/repos/${projectId}-python-test-renovate`, + url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { + cy.log(`RESPONSE STATUS: ${response.status}`); + cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); expect(response.body.slug).to.eq(`${projectId}-python-test-renovate`.toLowerCase()); cy.screenshot('installation-02-python-test-repo-exists'); @@ -47,12 +67,16 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', }); it('Should have the Jenkinsfile in the renovate-qs repository', () => { + const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/Jenkinsfile`; + cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', - url: `${apiBase}/repos/${projectId}-renovate-qs/browse/Jenkinsfile`, + url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { + cy.log(`RESPONSE STATUS: ${response.status}`); + cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; expect(content).to.contain('odsComponentPipeline'); @@ -61,36 +85,48 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', }); it('Should have the sonar-project.properties in the renovate-qs repository', () => { + const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/sonar-project.properties`; + cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', - url: `${apiBase}/repos/${projectId}-renovate-qs/browse/sonar-project.properties`, + url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { + cy.log(`RESPONSE STATUS: ${response.status}`); + cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); cy.screenshot('installation-04-sonar-properties-present'); }); }); it('Should have the chart templates directory in the renovate-qs repository', () => { + const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates`; + cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', - url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates`, + url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { + cy.log(`RESPONSE STATUS: ${response.status}`); + cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); cy.screenshot('installation-05-chart-templates-directory'); }); }); it('Should have the configmap.yaml with Renovate configuration', () => { + const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates/configmap.yaml`; + cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', - url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates/configmap.yaml`, + url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { + cy.log(`RESPONSE STATUS: ${response.status}`); + cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; expect(content).to.contain('renovateconfigjs'); diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts index d6033390..f1586af4 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -21,6 +21,17 @@ describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; + before(() => { + cy.log('=== DEBUG: Environment Variables ==='); + cy.log(`BITBUCKET_BASE_URL: "${bitbucketBaseUrl}"`); + cy.log(`PROJECT_ID: "${projectId}"`); + cy.log(`BITBUCKET_USERNAME: "${username}"`); + cy.log(`BITBUCKET_PASSWORD is set: ${!!password}`); + cy.log(`Computed apiBase: "${apiBase}"`); + cy.log('=== All Cypress.env() ==='); + cy.log(JSON.stringify(Cypress.env(), null, 2)); + }); + it('Should confirm the renovate-qs repository is accessible in the -cd project context', () => { // Verifies that the Bitbucket project (which maps to the OCP namespace) is properly set up cy.request({ From dbcbcd80c36f4646af7ba86b6e380cd7b9539b56 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 10:02:01 +0100 Subject: [PATCH 04/22] Refactor Renovate Bot tests to use template variables for Bitbucket credentials and remove debug logging --- .../acceptance/renovate-smoke.spec.cy.ts | 19 ++-------- .../renovate-installation.spec.cy.ts | 37 ++----------------- .../renovate-integration.spec.cy.ts | 16 ++------ renovate/testdata/steps.yml | 4 ++ 4 files changed, 16 insertions(+), 60 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index 7e1f9285..ec0948a6 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -13,26 +13,15 @@ */ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { - const bitbucketBaseUrl = Cypress.env('BITBUCKET_BASE_URL'); - const projectId = Cypress.env('PROJECT_ID'); - const username = Cypress.env('BITBUCKET_USERNAME'); - const password = Cypress.env('BITBUCKET_PASSWORD'); + const bitbucketBaseUrl = {{.BITBUCKET_URL}}; + const projectId = {{.ProjectID}}; + const username = {{.BITBUCKET_USERNAME}}; + const password = {{.BITBUCKET_PASSWORD}}; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; const targetRepo = `${projectId}-python-test-renovate`; - before(() => { - cy.log('=== DEBUG: Environment Variables ==='); - cy.log(`BITBUCKET_BASE_URL: "${bitbucketBaseUrl}"`); - cy.log(`PROJECT_ID: "${projectId}"`); - cy.log(`BITBUCKET_USERNAME: "${username}"`); - cy.log(`BITBUCKET_PASSWORD is set: ${!!password}`); - cy.log(`Computed apiBase: "${apiBase}"`); - cy.log(`Target repo: "${targetRepo}"`); - cy.log('=== All Cypress.env() ==='); - cy.log(JSON.stringify(Cypress.env(), null, 2)); - }); it('Should have at least one Pull Request in the target repository', () => { cy.request({ diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts index e2477338..8c0edf6c 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts @@ -12,37 +12,23 @@ */ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', () => { - const bitbucketBaseUrl = Cypress.env('BITBUCKET_BASE_URL'); - const projectId = Cypress.env('PROJECT_ID'); - const username = Cypress.env('BITBUCKET_USERNAME'); - const password = Cypress.env('BITBUCKET_PASSWORD'); + const bitbucketBaseUrl = {{.BITBUCKET_URL}}; + const projectId = {{.ProjectID}}; + const username = {{.BITBUCKET_USERNAME}}; + const password = {{.BITBUCKET_PASSWORD}}; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; - before(() => { - cy.log('=== DEBUG: Environment Variables ==='); - cy.log(`BITBUCKET_BASE_URL: "${bitbucketBaseUrl}"`); - cy.log(`PROJECT_ID: "${projectId}"`); - cy.log(`BITBUCKET_USERNAME: "${username}"`); - cy.log(`BITBUCKET_PASSWORD is set: ${!!password}`); - cy.log(`Computed apiBase: "${apiBase}"`); - cy.log(`Computed authHeader starts with: "${authHeader?.substring(0, 20)}..."`); - cy.log('=== All Cypress.env() ==='); - cy.log(JSON.stringify(Cypress.env(), null, 2)); - }); it('Should have the renovate-qs repository created in the project', () => { const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs`; - cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { - cy.log(`RESPONSE STATUS: ${response.status}`); - cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); expect(response.body.slug).to.eq(`${projectId}-renovate-qs`.toLowerCase()); cy.screenshot('installation-01-repository-exists'); @@ -51,15 +37,12 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', it('Should have the python-test-renovate repository created for testing', () => { const requestUrl = `${apiBase}/repos/${projectId}-python-test-renovate`; - cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { - cy.log(`RESPONSE STATUS: ${response.status}`); - cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); expect(response.body.slug).to.eq(`${projectId}-python-test-renovate`.toLowerCase()); cy.screenshot('installation-02-python-test-repo-exists'); @@ -68,15 +51,12 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', it('Should have the Jenkinsfile in the renovate-qs repository', () => { const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/Jenkinsfile`; - cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { - cy.log(`RESPONSE STATUS: ${response.status}`); - cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; expect(content).to.contain('odsComponentPipeline'); @@ -86,15 +66,12 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', it('Should have the sonar-project.properties in the renovate-qs repository', () => { const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/sonar-project.properties`; - cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { - cy.log(`RESPONSE STATUS: ${response.status}`); - cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); cy.screenshot('installation-04-sonar-properties-present'); }); @@ -102,15 +79,12 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', it('Should have the chart templates directory in the renovate-qs repository', () => { const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates`; - cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { - cy.log(`RESPONSE STATUS: ${response.status}`); - cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); cy.screenshot('installation-05-chart-templates-directory'); }); @@ -118,15 +92,12 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', it('Should have the configmap.yaml with Renovate configuration', () => { const requestUrl = `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates/configmap.yaml`; - cy.log(`REQUEST URL: ${requestUrl}`); cy.request({ method: 'GET', url: requestUrl, headers: { Authorization: authHeader }, failOnStatusCode: false, }).then((response) => { - cy.log(`RESPONSE STATUS: ${response.status}`); - cy.log(`RESPONSE BODY: ${JSON.stringify(response.body).substring(0, 500)}`); expect(response.status).to.eq(200); const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; expect(content).to.contain('renovateconfigjs'); diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts index f1586af4..e0e97f17 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -13,23 +13,15 @@ */ describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () => { - const bitbucketBaseUrl = Cypress.env('BITBUCKET_BASE_URL'); - const projectId = Cypress.env('PROJECT_ID'); - const username = Cypress.env('BITBUCKET_USERNAME'); - const password = Cypress.env('BITBUCKET_PASSWORD'); + const bitbucketBaseUrl = {{.BITBUCKET_URL}}; + const projectId = {{.ProjectID}}; + const username = {{.BITBUCKET_USERNAME}}; + const password = {{.BITBUCKET_PASSWORD}}; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; before(() => { - cy.log('=== DEBUG: Environment Variables ==='); - cy.log(`BITBUCKET_BASE_URL: "${bitbucketBaseUrl}"`); - cy.log(`PROJECT_ID: "${projectId}"`); - cy.log(`BITBUCKET_USERNAME: "${username}"`); - cy.log(`BITBUCKET_PASSWORD is set: ${!!password}`); - cy.log(`Computed apiBase: "${apiBase}"`); - cy.log('=== All Cypress.env() ==='); - cy.log(JSON.stringify(Cypress.env(), null, 2)); }); it('Should confirm the renovate-qs repository is accessible in the -cd project context', () => { diff --git a/renovate/testdata/steps.yml b/renovate/testdata/steps.yml index 585c2396..4b9dda43 100644 --- a/renovate/testdata/steps.yml +++ b/renovate/testdata/steps.yml @@ -140,6 +140,10 @@ steps: value: "https://bitbucket-{{.ProjectID}}-cd.apps.us-test.ocp.aws.boehringer.com" - name: PROJECT_ID value: "{{.ProjectID}}" + - name: BITBUCKET_USERNAME + value: "admin" + - name: BITBUCKET_PASSWORD + value: "admin" verify: jenkinsStages: "golden/jenkins-build-cypress.json" sonarScan: "golden/sonar-scan-cypress.json" From ef67b09efb8b2a024c0ca4441bac02d7107d9069 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 10:50:37 +0100 Subject: [PATCH 05/22] Update Renovate Bot tests to use string interpolation for Bitbucket credentials --- .../tests/acceptance/renovate-smoke.spec.cy.ts | 8 ++++---- .../tests/installation/renovate-installation.spec.cy.ts | 8 ++++---- .../tests/integration/renovate-integration.spec.cy.ts | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index ec0948a6..dc38b5d2 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -13,10 +13,10 @@ */ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { - const bitbucketBaseUrl = {{.BITBUCKET_URL}}; - const projectId = {{.ProjectID}}; - const username = {{.BITBUCKET_USERNAME}}; - const password = {{.BITBUCKET_PASSWORD}}; + const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; + const projectId = "{{.ProjectID}}"; + const username = "{{.BITBUCKET_USERNAME}}"; + const password = "{{.BITBUCKET_PASSWORD}}"; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts index 8c0edf6c..3d300de5 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts @@ -12,10 +12,10 @@ */ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', () => { - const bitbucketBaseUrl = {{.BITBUCKET_URL}}; - const projectId = {{.ProjectID}}; - const username = {{.BITBUCKET_USERNAME}}; - const password = {{.BITBUCKET_PASSWORD}}; + const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; + const projectId = "{{.ProjectID}}"; + const username = "{{.BITBUCKET_USERNAME}}"; + const password = "{{.BITBUCKET_PASSWORD}}"; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts index e0e97f17..b60c52db 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -13,10 +13,10 @@ */ describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () => { - const bitbucketBaseUrl = {{.BITBUCKET_URL}}; - const projectId = {{.ProjectID}}; - const username = {{.BITBUCKET_USERNAME}}; - const password = {{.BITBUCKET_PASSWORD}}; + const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; + const projectId = "{{.ProjectID}}"; + const username = "{{.BITBUCKET_USERNAME}}"; + const password = "{{.BITBUCKET_PASSWORD}}"; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; From 0f921d3d4149427cce99f1827a7414b105f9934e Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 11:09:08 +0100 Subject: [PATCH 06/22] Refactor Renovate Bot tests to use hardcoded credentials for Bitbucket authentication --- .../tests/acceptance/renovate-smoke.spec.cy.ts | 4 ++-- .../tests/installation/renovate-installation.spec.cy.ts | 4 ++-- .../tests/integration/renovate-integration.spec.cy.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index dc38b5d2..ea7289aa 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -15,8 +15,8 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = "{{.BITBUCKET_USERNAME}}"; - const password = "{{.BITBUCKET_PASSWORD}}"; + const username = "admin"; + const password = "admin"; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts index 3d300de5..4c618191 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts @@ -14,8 +14,8 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = "{{.BITBUCKET_USERNAME}}"; - const password = "{{.BITBUCKET_PASSWORD}}"; + const username = "admin"; + const password = "admin"; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts index b60c52db..65ba5548 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -15,8 +15,8 @@ describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = "{{.BITBUCKET_USERNAME}}"; - const password = "{{.BITBUCKET_PASSWORD}}"; + const username = "admin"; + const password = "admin"; const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; From 876507a9b1564a790fbbf49c2137a9f389220c84 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 11:25:20 +0100 Subject: [PATCH 07/22] Fix artifact archiving for Cypress test reports by copying to a new filename --- renovate/testdata/fixtures/renovate-cypress/Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index cd934fcc..93e9a492 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -106,7 +106,8 @@ def stageTest(def context) { sh 'npm run generate:pdf' zip zipFile: 'cypress/cypress-test-reports-pdf.zip', archive: false, dir: 'build/test-results/mochawesome/pdf' - archiveArtifacts artifacts: 'cypress/cypress-test-reports-pdf.zip', fingerprint: true + sh 'cp cypress/cypress-test-reports-pdf.zip cypress-test-reports-pdf.zip' + archiveArtifacts artifacts: 'cypress/cypress-test-reports-pdf.zip, cypress-test-reports-pdf.zip', fingerprint: true if (fileExists('cypress/videos')) { zip zipFile: 'cypress/videos.zip', archive: false, dir: 'cypress/videos' From 08882296ef88007ac16a9b5cb51d34d36c00da8a Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 11:26:03 +0100 Subject: [PATCH 08/22] Refactor Renovate Bot tests to use environment variables for Bitbucket credentials --- .../tests/acceptance/renovate-smoke.spec.cy.ts | 4 ++-- .../tests/installation/renovate-installation.spec.cy.ts | 4 ++-- .../tests/integration/renovate-integration.spec.cy.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index ea7289aa..24ad098e 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -15,8 +15,8 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = "admin"; - const password = "admin"; + const username = Cypress.env("CYPRESS_BITBUCKET_USERNAME"); + const password = Cypress.env("CYPRESS_BITBUCKET_PASSWORD"); const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts index 4c618191..ec3a1371 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts @@ -14,8 +14,8 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = "admin"; - const password = "admin"; + const username = Cypress.env("CYPRESS_BITBUCKET_USERNAME"); + const password = Cypress.env("CYPRESS_BITBUCKET_PASSWORD"); const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts index 65ba5548..bd9130f5 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -15,8 +15,8 @@ describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = "admin"; - const password = "admin"; + const username = Cypress.env("CYPRESS_BITBUCKET_USERNAME"); + const password = Cypress.env("CYPRESS_BITBUCKET_PASSWORD"); const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; From 5a87735cf1079117343a27f35cc39a0826ff23e7 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 11:35:21 +0100 Subject: [PATCH 09/22] Refactor Renovate Bot tests to use updated environment variable names for Bitbucket credentials --- .../tests/acceptance/renovate-smoke.spec.cy.ts | 4 ++-- .../tests/installation/renovate-installation.spec.cy.ts | 4 ++-- .../tests/integration/renovate-integration.spec.cy.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index 24ad098e..18ec9557 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -15,8 +15,8 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = Cypress.env("CYPRESS_BITBUCKET_USERNAME"); - const password = Cypress.env("CYPRESS_BITBUCKET_PASSWORD"); + const username = Cypress.env("BITBUCKET_USERNAME"); + const password = Cypress.env("BITBUCKET_PASSWORD"); const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts index ec3a1371..d03693a0 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/installation/renovate-installation.spec.cy.ts @@ -14,8 +14,8 @@ describe('Renovate Bot Installation Tests - Bitbucket Repository Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = Cypress.env("CYPRESS_BITBUCKET_USERNAME"); - const password = Cypress.env("CYPRESS_BITBUCKET_PASSWORD"); + const username = Cypress.env("BITBUCKET_USERNAME"); + const password = Cypress.env("BITBUCKET_PASSWORD"); const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts index bd9130f5..1ff8259f 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -15,8 +15,8 @@ describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () => { const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; const projectId = "{{.ProjectID}}"; - const username = Cypress.env("CYPRESS_BITBUCKET_USERNAME"); - const password = Cypress.env("CYPRESS_BITBUCKET_PASSWORD"); + const username = Cypress.env("BITBUCKET_USERNAME"); + const password = Cypress.env("BITBUCKET_PASSWORD"); const authHeader = `Basic ${btoa(`${username}:${password}`)}`; const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; From bba11d54e382dfc8a1b66f43dd4cf3f17878c6cc Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 11:39:34 +0100 Subject: [PATCH 10/22] Update artifact archiving in Jenkinsfile to store Cypress test reports in an artifacts directory --- renovate/testdata/fixtures/renovate-cypress/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index 93e9a492..8e690cfd 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -106,8 +106,8 @@ def stageTest(def context) { sh 'npm run generate:pdf' zip zipFile: 'cypress/cypress-test-reports-pdf.zip', archive: false, dir: 'build/test-results/mochawesome/pdf' - sh 'cp cypress/cypress-test-reports-pdf.zip cypress-test-reports-pdf.zip' - archiveArtifacts artifacts: 'cypress/cypress-test-reports-pdf.zip, cypress-test-reports-pdf.zip', fingerprint: true + sh 'mkdir -p artifacts && cp cypress/cypress-test-reports-pdf.zip artifacts/cypress-test-reports-pdf.zip' + archiveArtifacts artifacts: 'cypress/cypress-test-reports-pdf.zip, artifacts/cypress-test-reports-pdf.zip', fingerprint: true if (fileExists('cypress/videos')) { zip zipFile: 'cypress/videos.zip', archive: false, dir: 'cypress/videos' From 8c4b182b01dea6934bc4ac039ca0a23c9ab2974b Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 12:09:58 +0100 Subject: [PATCH 11/22] Remove hardcoded Bitbucket credentials from steps.yml and update test report filename --- renovate/testdata/steps.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/renovate/testdata/steps.yml b/renovate/testdata/steps.yml index 4b9dda43..a5047ccd 100644 --- a/renovate/testdata/steps.yml +++ b/renovate/testdata/steps.yml @@ -140,15 +140,11 @@ steps: value: "https://bitbucket-{{.ProjectID}}-cd.apps.us-test.ocp.aws.boehringer.com" - name: PROJECT_ID value: "{{.ProjectID}}" - - name: BITBUCKET_USERNAME - value: "admin" - - name: BITBUCKET_PASSWORD - value: "admin" verify: jenkinsStages: "golden/jenkins-build-cypress.json" sonarScan: "golden/sonar-scan-cypress.json" runAttachments: - sonarqube-report-{{.ProjectID}}-{{.ComponentID}}.pdf - - cypress/cypress-test-reports-pdf.zip + - cypress-test-reports-pdf.zip testResults: 1 From a11177aac190b45475a2f70183930850f799dfe0 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 12:32:37 +0100 Subject: [PATCH 12/22] Add Cypress video and screenshot archiving to Jenkins pipeline --- renovate/testdata/fixtures/renovate-cypress/Jenkinsfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index 8e690cfd..9d4eac2a 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -91,6 +91,7 @@ def stageTest(def context) { "OPENSHIFT_APP_DOMAIN=${context.getOpenshiftApplicationDomain()}", "COMMIT_INFO_SHA=${context.gitCommit}", "BUILD_NUMBER=${context.buildNumber}", + "CYPRESS_VIDEO=true", "CYPRESS_BITBUCKET_BASE_URL=${bitbucketBaseUrl}", "CYPRESS_PROJECT_ID=${context.projectId}", ]) { @@ -111,10 +112,14 @@ def stageTest(def context) { if (fileExists('cypress/videos')) { zip zipFile: 'cypress/videos.zip', archive: false, dir: 'cypress/videos' + sh 'cp cypress/videos.zip artifacts/videos.zip' + archiveArtifacts artifacts: 'cypress/videos.zip, artifacts/videos.zip', fingerprint: true } if (fileExists('build/test-results/screenshots')) { zip zipFile: 'cypress/screenshots.zip', archive: false, dir: 'build/test-results/screenshots' + sh 'cp cypress/screenshots.zip artifacts/screenshots.zip' + archiveArtifacts artifacts: 'cypress/screenshots.zip, artifacts/screenshots.zip', fingerprint: true } if (status != 0) { From 0e64c8aeca8b29018154dc7e8b79439be4c5f070 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 13:53:20 +0100 Subject: [PATCH 13/22] Refactor Renovate Bot acceptance tests to use Bitbucket Web UI for verification and improve test descriptions --- .../acceptance/renovate-smoke.spec.cy.ts | 159 +++++++----------- 1 file changed, 65 insertions(+), 94 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index 18ec9557..5d9975dc 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -5,11 +5,14 @@ * automatically scan the consuming project's repositories for outdated * dependencies and create corresponding Pull Requests in Bitbucket to update them. * - * These tests verify through the Bitbucket API that: + * These tests navigate the Bitbucket Web UI to verify that: * - A Pull Request was created by the Renovate Bot in the target repository * - The PR contains the expected onboarding description * - The PR state is OPEN - * - The PR metadata is correct (branch prefix, author, etc.) + * - The PR metadata is correct (branch prefix, target branch, etc.) + * + * Each test visits the corresponding Bitbucket page and captures + * a screenshot as visual evidence of the verification. */ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { @@ -17,114 +20,82 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( const projectId = "{{.ProjectID}}"; const username = Cypress.env("BITBUCKET_USERNAME"); const password = Cypress.env("BITBUCKET_PASSWORD"); - - const authHeader = `Basic ${btoa(`${username}:${password}`)}`; - const apiBase = `${bitbucketBaseUrl}/rest/api/1.0/projects/${projectId}`; const targetRepo = `${projectId}-python-test-renovate`; + const repoUrl = `${bitbucketBaseUrl}/projects/${projectId}/repos/${targetRepo}`; - - it('Should have at least one Pull Request in the target repository', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/pull-requests?state=OPEN&limit=10`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.body.values).to.have.length.greaterThan(0); - cy.screenshot('acceptance-01-pull-requests-exist'); + beforeEach(() => { + // Establish authenticated session with Bitbucket Server via form login + cy.session('bitbucket-login', () => { + cy.request({ + method: 'POST', + url: `${bitbucketBaseUrl}/login`, + form: true, + body: { + j_username: username, + j_password: password, + }, + followRedirect: true, + }); }); }); - it('Should have created the onboarding Pull Request (PR #1)', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.body.state).to.eq('OPEN'); - cy.screenshot('acceptance-02-onboarding-pr-open'); - }); + it('Should navigate to the Pull Requests page and see at least one PR', () => { + cy.visit(`${repoUrl}/pull-requests`); + cy.url().should('include', '/pull-requests'); + // The PR list should contain at least the onboarding PR created by Renovate + cy.contains('renovate', { matchCase: false, timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-01-pull-requests-exist'); }); - it('Should have the onboarding PR with Renovate description', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - const description = response.body.description || ''; - expect(description).to.contain('Renovate'); - cy.screenshot('acceptance-03-pr-description-contains-renovate'); - }); + it('Should open the onboarding Pull Request and verify it is OPEN', () => { + cy.visit(`${repoUrl}/pull-requests/1/overview`); + cy.url().should('include', '/pull-requests/1'); + // Bitbucket shows the PR state as a visible badge + cy.contains('Open', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-02-onboarding-pr-open'); }); - it('Should have the PR created from a renovate/ branch', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - const fromBranch = response.body.fromRef?.displayId || ''; - expect(fromBranch).to.match(/^renovate\//); - cy.screenshot('acceptance-04-pr-from-renovate-branch'); - }); + it('Should verify the Pull Request description mentions Renovate', () => { + cy.visit(`${repoUrl}/pull-requests/1/overview`); + // The PR description rendered on the page should mention Renovate + cy.contains('Renovate', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-03-pr-description-contains-renovate'); }); - it('Should have the PR targeting the master branch', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - const toBranch = response.body.toRef?.displayId || ''; - expect(toBranch).to.eq('master'); - cy.screenshot('acceptance-05-pr-targets-master'); - }); + it('Should verify the Pull Request originates from a renovate/ branch', () => { + cy.visit(`${repoUrl}/pull-requests/1/overview`); + // The source branch shown on the PR page should start with renovate/ + cy.contains('renovate/', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-04-pr-from-renovate-branch'); }); - it('Should have PR with activate Renovate message', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/pull-requests/1`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - const description = response.body.description || ''; - expect(description).to.contain('To activate Renovate, merge this Pull Request'); - cy.screenshot('acceptance-06-pr-activate-renovate-message'); - }); + it('Should verify the Pull Request targets the master branch', () => { + cy.visit(`${repoUrl}/pull-requests/1/overview`); + // The target branch shown on the PR page should be master + cy.contains('master', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-05-pr-targets-master'); }); - it('Should be able to view the PR diff with configuration file', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/pull-requests/1/changes?limit=25`, - headers: { Authorization: authHeader }, - failOnStatusCode: false, - }).then((response) => { - expect(response.status).to.eq(200); - const changedFiles = response.body.values?.map((v: any) => v.path?.toString) || []; - cy.screenshot('acceptance-07-pr-diff-files'); - }); + it('Should verify the Pull Request contains the Renovate activation message', () => { + cy.visit(`${repoUrl}/pull-requests/1/overview`); + // The onboarding PR description should contain the activation instruction + cy.contains('To activate Renovate, merge this Pull Request', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-06-pr-activate-renovate-message'); }); - it('Should capture the overall repository state after Renovate execution', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${targetRepo}/branches?limit=25`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - const branches = response.body.values?.map((b: any) => b.displayId) || []; - // There should be at least master and a renovate/* branch - expect(branches).to.include('master'); - const renovateBranches = branches.filter((b: string) => b.startsWith('renovate/')); - expect(renovateBranches).to.have.length.greaterThan(0); - cy.screenshot('acceptance-08-branches-with-renovate'); - }); + it('Should navigate to the PR diff and verify the configuration file changes', () => { + cy.visit(`${repoUrl}/pull-requests/1/diff`); + cy.url().should('include', '/diff'); + // Wait for the diff page to fully render with file changes + cy.get('body', { timeout: 20000 }).should('be.visible'); + cy.screenshot('acceptance-07-pr-diff-files'); + }); + + it('Should navigate to branches and verify a renovate/ branch exists', () => { + cy.visit(`${repoUrl}/branches`); + // The branches page should show both master and the renovate/* branch + cy.contains('master', { timeout: 15000 }).should('be.visible'); + cy.contains('renovate/', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-08-branches-with-renovate'); }); }); From 1daa109339425510ce972f92c56405cc29a8e862 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 16:38:52 +0100 Subject: [PATCH 14/22] Improve PR existence check in Renovate Bot acceptance tests to assert visible links in main content --- .../tests/acceptance/renovate-smoke.spec.cy.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts index 5d9975dc..9f812ebb 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts @@ -42,8 +42,11 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( it('Should navigate to the Pull Requests page and see at least one PR', () => { cy.visit(`${repoUrl}/pull-requests`); cy.url().should('include', '/pull-requests'); - // The PR list should contain at least the onboarding PR created by Renovate - cy.contains('renovate', { matchCase: false, timeout: 15000 }).should('be.visible'); + // Assert using visible PR links in main content to avoid hidden dropdown entries + cy.get('#content', { timeout: 15000 }).should('be.visible'); + cy.get('#content a[href*="/pull-requests/"]:visible', { timeout: 15000 }) + .its('length') + .should('be.greaterThan', 0); cy.screenshot('acceptance-01-pull-requests-exist'); }); From 1c9622ac67dae656963ff539ba58f31f3d245537 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 17:01:15 +0100 Subject: [PATCH 15/22] Refactor artifact paths in Jenkinsfile to use 'artifacts/' directory for Cypress test reports and screenshots --- .../fixtures/renovate-cypress/Jenkinsfile | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index 9d4eac2a..54c16271 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -35,30 +35,30 @@ odsComponentPipeline( stageTest(context) odsComponentStageScanWithSonar(context) - if (fileExists('cypress/screenshots.zip')) { + if (fileExists('artifacts/screenshots.zip')) { odsComponentStageUploadToNexus(context, [ - distributionFile: 'cypress/screenshots.zip', + distributionFile: 'artifacts/screenshots.zip', repository: 'leva-documentation', repositoryType: 'raw', targetDirectory: "${targetDirectory}" ] ) } - if (fileExists('cypress/videos.zip')) { + if (fileExists('artifacts/videos.zip')) { odsComponentStageUploadToNexus(context, [ - distributionFile: 'cypress/videos.zip', + distributionFile: 'artifacts/videos.zip', repository: 'leva-documentation', repositoryType: 'raw', targetDirectory: "${targetDirectory}" ] ) } - if (fileExists('cypress/cypress-test-reports-pdf.zip')) { + if (fileExists('artifacts/cypress-test-reports-pdf.zip')) { odsComponentStageUploadToNexus(context, [ - distributionFile: 'cypress/cypress-test-reports-pdf.zip', + distributionFile: 'artifacts/cypress-test-reports-pdf.zip', repository: 'leva-documentation', repositoryType: 'raw', targetDirectory: "${targetDirectory}" @@ -98,6 +98,7 @@ def stageTest(def context) { withCredentials([ usernamePassword(credentialsId: "${context.projectId}-cd-cd-user-with-password", passwordVariable: 'CYPRESS_BITBUCKET_PASSWORD', usernameVariable: 'CYPRESS_BITBUCKET_USERNAME') ]) { + sh 'mkdir -p artifacts' def status = sh(script: 'npm run e2e', returnStatus: true) sh 'npm run combine:reports' junit(testResults:'build/test-results/*.xml') @@ -106,20 +107,17 @@ def stageTest(def context) { stash(name: "acceptance-test-reports-junit-xml-${context.componentId}-${context.buildNumber}", includes: 'build/test-results/acceptance-junit.xml', allowEmpty: true) sh 'npm run generate:pdf' - zip zipFile: 'cypress/cypress-test-reports-pdf.zip', archive: false, dir: 'build/test-results/mochawesome/pdf' - sh 'mkdir -p artifacts && cp cypress/cypress-test-reports-pdf.zip artifacts/cypress-test-reports-pdf.zip' - archiveArtifacts artifacts: 'cypress/cypress-test-reports-pdf.zip, artifacts/cypress-test-reports-pdf.zip', fingerprint: true + zip zipFile: 'artifacts/cypress-test-reports-pdf.zip', archive: false, dir: 'build/test-results/mochawesome/pdf' + archiveArtifacts artifacts: 'artifacts/cypress-test-reports-pdf.zip', fingerprint: true if (fileExists('cypress/videos')) { - zip zipFile: 'cypress/videos.zip', archive: false, dir: 'cypress/videos' - sh 'cp cypress/videos.zip artifacts/videos.zip' - archiveArtifacts artifacts: 'cypress/videos.zip, artifacts/videos.zip', fingerprint: true + zip zipFile: 'artifacts/videos.zip', archive: false, dir: 'cypress/videos' + archiveArtifacts artifacts: 'artifacts/videos.zip', fingerprint: true } if (fileExists('build/test-results/screenshots')) { - zip zipFile: 'cypress/screenshots.zip', archive: false, dir: 'build/test-results/screenshots' - sh 'cp cypress/screenshots.zip artifacts/screenshots.zip' - archiveArtifacts artifacts: 'cypress/screenshots.zip, artifacts/screenshots.zip', fingerprint: true + zip zipFile: 'artifacts/screenshots.zip', archive: false, dir: 'build/test-results/screenshots' + archiveArtifacts artifacts: 'artifacts/screenshots.zip', fingerprint: true } if (status != 0) { From aeb177d1c9a4bc315d8bfd55ce20f043929a0ad2 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 19:07:46 +0100 Subject: [PATCH 16/22] Refactor Renovate Bot tests and streamline evidence upload process in Jenkinsfile --- .../fixtures/renovate-cypress/Jenkinsfile | 43 +++----- .../acceptance/renovate-acceptance.spec.cy.ts | 86 +++++++++++++++ .../acceptance/renovate-smoke.spec.cy.ts | 104 ------------------ .../renovate-integration.spec.cy.ts | 27 ----- .../golden/jenkins-build-cypress.json | 4 - 5 files changed, 99 insertions(+), 165 deletions(-) create mode 100644 renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts delete mode 100644 renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index 54c16271..9c3be8ad 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -35,36 +35,14 @@ odsComponentPipeline( stageTest(context) odsComponentStageScanWithSonar(context) - if (fileExists('artifacts/screenshots.zip')) { - odsComponentStageUploadToNexus(context, - [ - distributionFile: 'artifacts/screenshots.zip', - repository: 'leva-documentation', - repositoryType: 'raw', - targetDirectory: "${targetDirectory}" - ] - ) - } - if (fileExists('artifacts/videos.zip')) { - odsComponentStageUploadToNexus(context, - [ - distributionFile: 'artifacts/videos.zip', - repository: 'leva-documentation', - repositoryType: 'raw', - targetDirectory: "${targetDirectory}" - ] - ) - } - if (fileExists('artifacts/cypress-test-reports-pdf.zip')) { - odsComponentStageUploadToNexus(context, - [ - distributionFile: 'artifacts/cypress-test-reports-pdf.zip', - repository: 'leva-documentation', - repositoryType: 'raw', - targetDirectory: "${targetDirectory}" - ] - ) - } + odsComponentStageUploadToNexus(context, + [ + distributionFile: 'artifacts/cypress-evidence.zip', + repository: 'leva-documentation', + repositoryType: 'raw', + targetDirectory: "${targetDirectory}" + ] + ) } @@ -94,6 +72,7 @@ def stageTest(def context) { "CYPRESS_VIDEO=true", "CYPRESS_BITBUCKET_BASE_URL=${bitbucketBaseUrl}", "CYPRESS_PROJECT_ID=${context.projectId}", + "CYPRESS_OC_CONSOLE_CRONJOB_URL=https://console-openshift-console.${context.getOpenshiftApplicationDomain()}/k8s/ns/${context.targetProject}/cronjobs/renovate-qs/", ]) { withCredentials([ usernamePassword(credentialsId: "${context.projectId}-cd-cd-user-with-password", passwordVariable: 'CYPRESS_BITBUCKET_PASSWORD', usernameVariable: 'CYPRESS_BITBUCKET_USERNAME') @@ -120,6 +99,10 @@ def stageTest(def context) { archiveArtifacts artifacts: 'artifacts/screenshots.zip', fingerprint: true } + // Bundle all generated zips into one archive for the single Nexus upload + sh 'cd artifacts && zip cypress-evidence.zip *.zip' + archiveArtifacts artifacts: 'artifacts/cypress-evidence.zip', fingerprint: true + if (status != 0) { unstable "Some tests have failed or encountered errors. Please check the logs for more details." } diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts new file mode 100644 index 00000000..c502e737 --- /dev/null +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts @@ -0,0 +1,86 @@ +/** + * Acceptance Tests for Renovate Bot + * + * Risk: The framework shall, upon execution of the Renovate Bot CronJob, + * automatically scan the consuming project's repositories for outdated + * dependencies and create corresponding Pull Requests in Bitbucket to update them. + * + * These tests navigate the Bitbucket Web UI and the OpenShift Console to verify: + * - The Renovate CronJob is deployed in the -cd namespace (OC Console) + * - A Pull Request was created by the Renovate Bot in the target repository + * - The PR contains the expected onboarding description + * - The PR state is OPEN + * - The PR metadata is correct (branch prefix, target branch, etc.) + * - The renovate.json configuration file is visible in the PR diff + * + * Each test captures a screenshot as visual evidence. + */ + +describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { + const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; + const projectId = "{{.ProjectID}}"; + const username = Cypress.env("BITBUCKET_USERNAME"); + const password = Cypress.env("BITBUCKET_PASSWORD"); + const ocConsoleCronJobUrl = Cypress.env("OC_CONSOLE_CRONJOB_URL"); + const targetRepo = `${projectId}-python-test-renovate`; + const repoUrl = `${bitbucketBaseUrl}/projects/${projectId}/repos/${targetRepo}`; + + beforeEach(() => { + // Establish authenticated session with Bitbucket Server via form login + cy.session('bitbucket-login', () => { + cy.request({ + method: 'POST', + url: `${bitbucketBaseUrl}/login`, + form: true, + body: { + j_username: username, + j_password: password, + }, + followRedirect: true, + }); + }); + }); + + it('Should show the Renovate CronJob in the OpenShift Console', () => { + // Navigate directly without session (OC console has its own auth) + cy.visit(ocConsoleCronJobUrl, { failOnStatusCode: false }); + // Wait for the main content area to render (OC console is a SPA, needs time) + cy.get('body', { timeout: 30000 }).should('be.visible'); + cy.wait(5000); + cy.screenshot('acceptance-01-oc-console-cronjob'); + }); + + it('Should navigate to the Pull Requests page and see at least one PR', () => { + cy.visit(`${repoUrl}/pull-requests`); + cy.url().should('include', '/pull-requests'); + cy.get('#content', { timeout: 15000 }).should('be.visible'); + cy.get('#content a[href*="/pull-requests/"]:visible', { timeout: 15000 }) + .its('length') + .should('be.greaterThan', 0); + cy.screenshot('acceptance-02-pull-requests-exist'); + }); + + it('Should verify the Pull Request contains the Renovate activation message', () => { + cy.visit(`${repoUrl}/pull-requests/1/overview`); + cy.get('#content', { timeout: 15000 }).should('be.visible'); + cy.contains('To activate Renovate, merge this Pull Request', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-03-pr-activate-renovate-message'); + }); + + it('Should navigate to the PR diff and show the renovate.json configuration file', () => { + cy.visit(`${repoUrl}/pull-requests/1/diff#renovate.json`); + cy.url().should('include', '/diff'); + cy.get('#content', { timeout: 30000 }).should('be.visible'); + cy.contains('renovate.json', { timeout: 30000 }).should('be.visible'); + cy.wait(2000); + cy.screenshot('acceptance-04-pr-diff-renovate-json'); + }); + + it('Should navigate to branches and verify a renovate/ branch exists', () => { + cy.visit(`${repoUrl}/branches`); + cy.get('#content', { timeout: 15000 }).should('be.visible'); + cy.contains('master', { timeout: 15000 }).should('be.visible'); + cy.contains('renovate/', { timeout: 15000 }).should('be.visible'); + cy.screenshot('acceptance-05-branches-with-renovate'); + }); +}); diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts deleted file mode 100644 index 9f812ebb..00000000 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Acceptance / Smoke Tests for Renovate Bot - * - * Risk: The framework shall, upon execution of the Renovate Bot CronJob, - * automatically scan the consuming project's repositories for outdated - * dependencies and create corresponding Pull Requests in Bitbucket to update them. - * - * These tests navigate the Bitbucket Web UI to verify that: - * - A Pull Request was created by the Renovate Bot in the target repository - * - The PR contains the expected onboarding description - * - The PR state is OPEN - * - The PR metadata is correct (branch prefix, target branch, etc.) - * - * Each test visits the corresponding Bitbucket page and captures - * a screenshot as visual evidence of the verification. - */ - -describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', () => { - const bitbucketBaseUrl = "{{.BITBUCKET_URL}}"; - const projectId = "{{.ProjectID}}"; - const username = Cypress.env("BITBUCKET_USERNAME"); - const password = Cypress.env("BITBUCKET_PASSWORD"); - const targetRepo = `${projectId}-python-test-renovate`; - const repoUrl = `${bitbucketBaseUrl}/projects/${projectId}/repos/${targetRepo}`; - - beforeEach(() => { - // Establish authenticated session with Bitbucket Server via form login - cy.session('bitbucket-login', () => { - cy.request({ - method: 'POST', - url: `${bitbucketBaseUrl}/login`, - form: true, - body: { - j_username: username, - j_password: password, - }, - followRedirect: true, - }); - }); - }); - - it('Should navigate to the Pull Requests page and see at least one PR', () => { - cy.visit(`${repoUrl}/pull-requests`); - cy.url().should('include', '/pull-requests'); - // Assert using visible PR links in main content to avoid hidden dropdown entries - cy.get('#content', { timeout: 15000 }).should('be.visible'); - cy.get('#content a[href*="/pull-requests/"]:visible', { timeout: 15000 }) - .its('length') - .should('be.greaterThan', 0); - cy.screenshot('acceptance-01-pull-requests-exist'); - }); - - it('Should open the onboarding Pull Request and verify it is OPEN', () => { - cy.visit(`${repoUrl}/pull-requests/1/overview`); - cy.url().should('include', '/pull-requests/1'); - // Bitbucket shows the PR state as a visible badge - cy.contains('Open', { timeout: 15000 }).should('be.visible'); - cy.screenshot('acceptance-02-onboarding-pr-open'); - }); - - it('Should verify the Pull Request description mentions Renovate', () => { - cy.visit(`${repoUrl}/pull-requests/1/overview`); - // The PR description rendered on the page should mention Renovate - cy.contains('Renovate', { timeout: 15000 }).should('be.visible'); - cy.screenshot('acceptance-03-pr-description-contains-renovate'); - }); - - it('Should verify the Pull Request originates from a renovate/ branch', () => { - cy.visit(`${repoUrl}/pull-requests/1/overview`); - // The source branch shown on the PR page should start with renovate/ - cy.contains('renovate/', { timeout: 15000 }).should('be.visible'); - cy.screenshot('acceptance-04-pr-from-renovate-branch'); - }); - - it('Should verify the Pull Request targets the master branch', () => { - cy.visit(`${repoUrl}/pull-requests/1/overview`); - // The target branch shown on the PR page should be master - cy.contains('master', { timeout: 15000 }).should('be.visible'); - cy.screenshot('acceptance-05-pr-targets-master'); - }); - - it('Should verify the Pull Request contains the Renovate activation message', () => { - cy.visit(`${repoUrl}/pull-requests/1/overview`); - // The onboarding PR description should contain the activation instruction - cy.contains('To activate Renovate, merge this Pull Request', { timeout: 15000 }).should('be.visible'); - cy.screenshot('acceptance-06-pr-activate-renovate-message'); - }); - - it('Should navigate to the PR diff and verify the configuration file changes', () => { - cy.visit(`${repoUrl}/pull-requests/1/diff`); - cy.url().should('include', '/diff'); - // Wait for the diff page to fully render with file changes - cy.get('body', { timeout: 20000 }).should('be.visible'); - cy.screenshot('acceptance-07-pr-diff-files'); - }); - - it('Should navigate to branches and verify a renovate/ branch exists', () => { - cy.visit(`${repoUrl}/branches`); - // The branches page should show both master and the renovate/* branch - cy.contains('master', { timeout: 15000 }).should('be.visible'); - cy.contains('renovate/', { timeout: 15000 }).should('be.visible'); - cy.screenshot('acceptance-08-branches-with-renovate'); - }); -}); diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts index 1ff8259f..c8bcb9df 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/integration/renovate-integration.spec.cy.ts @@ -37,33 +37,6 @@ describe('Renovate Bot Integration Tests - CronJob Deployment Verification', () }); }); - it('Should verify the renovate-qs repository has proper build configuration for CronJob', () => { - // The Jenkinsfile in the repo defines the pipeline that builds the CronJob container image - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${projectId}-renovate-qs/browse/Jenkinsfile`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - const content = response.body.lines?.map((l: any) => l.text).join('\n') || ''; - expect(content).to.contain('odsComponentPipeline'); - cy.screenshot('integration-02-jenkinsfile-cronjob-config'); - }); - }); - - it('Should verify the chart templates contain CronJob definition', () => { - cy.request({ - method: 'GET', - url: `${apiBase}/repos/${projectId}-renovate-qs/browse/chart/templates`, - headers: { Authorization: authHeader }, - }).then((response) => { - expect(response.status).to.eq(200); - // The chart templates directory should contain the CronJob template - const files = response.body.children?.values?.map((f: any) => f.path?.name) || []; - cy.screenshot('integration-03-chart-templates-listing'); - }); - }); - it('Should verify configmap contains correct repository references for scanning', () => { cy.request({ method: 'GET', diff --git a/renovate/testdata/golden/jenkins-build-cypress.json b/renovate/testdata/golden/jenkins-build-cypress.json index df38128d..25ac28f6 100644 --- a/renovate/testdata/golden/jenkins-build-cypress.json +++ b/renovate/testdata/golden/jenkins-build-cypress.json @@ -23,10 +23,6 @@ "stage": "Upload to Nexus", "status": "SUCCESS" }, - { - "stage": "Upload to Nexus", - "status": "SUCCESS" - }, { "stage": "odsPipeline finished", "status": "SUCCESS" From 7efdddbc17ccc55ef529b678e469a0c02a59ca1b Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Thu, 19 Feb 2026 20:19:00 +0100 Subject: [PATCH 17/22] Update Cypress test descriptions and file references in steps.yml for clarity --- renovate/testdata/steps.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/renovate/testdata/steps.yml b/renovate/testdata/steps.yml index a5047ccd..73493b71 100644 --- a/renovate/testdata/steps.yml +++ b/renovate/testdata/steps.yml @@ -63,7 +63,7 @@ steps: # ───────────────────────────────────────────────────────────────────────────── # Cypress E2E evidence collection steps - # These steps provision an e2e-cypress component and run smoke / installation / + # These steps provision an e2e-cypress component and run acceptance / installation / # integration tests against the Bitbucket UI / API to capture screenshots # covering the following risks: # - Bitbucket repository creation with configuration files @@ -106,9 +106,9 @@ steps: componentID: renovate-cypress-test bitbucketParams: action: "upload-file" - file: "fixtures/renovate-cypress/tests/acceptance/renovate-smoke.spec.cy.ts" + file: "fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts" repository: "{{.ProjectID}}-renovate-cypress-test" - filename: "tests/acceptance/renovate-smoke.spec.cy.ts" + filename: "tests/acceptance/renovate-acceptance.spec.cy.ts" render: true - description: "Add Cypress installation tests - Bitbucket repository verification" From 49927b0dddf6886b2417b18a3e65a3c065ddc31f Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 20 Feb 2026 12:35:48 +0100 Subject: [PATCH 18/22] Improve visibility check for Renovate CronJob in OpenShift Console acceptance test --- .../tests/acceptance/renovate-acceptance.spec.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts index c502e737..935277a0 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts @@ -46,7 +46,7 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( cy.visit(ocConsoleCronJobUrl, { failOnStatusCode: false }); // Wait for the main content area to render (OC console is a SPA, needs time) cy.get('body', { timeout: 30000 }).should('be.visible'); - cy.wait(5000); + cy.get('a[data-test-id="renovate-qs"]', { timeout: 30000 }).should('be.visible'); cy.screenshot('acceptance-01-oc-console-cronjob'); }); From 4072128dc90eb064db42944697cff0a71b374af1 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Mon, 23 Feb 2026 10:44:47 +0100 Subject: [PATCH 19/22] Add stage for packaging evidence in Jenkins pipeline and update acceptance test to use dynamic cron job details --- .../fixtures/renovate-cypress/Jenkinsfile | 48 ++++++++++++------- .../acceptance/renovate-acceptance.spec.cy.ts | 18 ++++--- .../golden/jenkins-build-cypress.json | 4 ++ 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index 9c3be8ad..f372bfd2 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -34,6 +34,7 @@ odsComponentPipeline( stageTypeCheck(context) stageTest(context) odsComponentStageScanWithSonar(context) + stagePackageEvidences(context) odsComponentStageUploadToNexus(context, [ @@ -73,6 +74,8 @@ def stageTest(def context) { "CYPRESS_BITBUCKET_BASE_URL=${bitbucketBaseUrl}", "CYPRESS_PROJECT_ID=${context.projectId}", "CYPRESS_OC_CONSOLE_CRONJOB_URL=https://console-openshift-console.${context.getOpenshiftApplicationDomain()}/k8s/ns/${context.targetProject}/cronjobs/renovate-qs/", + "OC_NAMESPACE=${context.targetProject}", + "CRONJOB_NAME=renovate-qs", ]) { withCredentials([ usernamePassword(credentialsId: "${context.projectId}-cd-cd-user-with-password", passwordVariable: 'CYPRESS_BITBUCKET_PASSWORD', usernameVariable: 'CYPRESS_BITBUCKET_USERNAME') @@ -86,22 +89,6 @@ def stageTest(def context) { stash(name: "acceptance-test-reports-junit-xml-${context.componentId}-${context.buildNumber}", includes: 'build/test-results/acceptance-junit.xml', allowEmpty: true) sh 'npm run generate:pdf' - zip zipFile: 'artifacts/cypress-test-reports-pdf.zip', archive: false, dir: 'build/test-results/mochawesome/pdf' - archiveArtifacts artifacts: 'artifacts/cypress-test-reports-pdf.zip', fingerprint: true - - if (fileExists('cypress/videos')) { - zip zipFile: 'artifacts/videos.zip', archive: false, dir: 'cypress/videos' - archiveArtifacts artifacts: 'artifacts/videos.zip', fingerprint: true - } - - if (fileExists('build/test-results/screenshots')) { - zip zipFile: 'artifacts/screenshots.zip', archive: false, dir: 'build/test-results/screenshots' - archiveArtifacts artifacts: 'artifacts/screenshots.zip', fingerprint: true - } - - // Bundle all generated zips into one archive for the single Nexus upload - sh 'cd artifacts && zip cypress-evidence.zip *.zip' - archiveArtifacts artifacts: 'artifacts/cypress-evidence.zip', fingerprint: true if (status != 0) { unstable "Some tests have failed or encountered errors. Please check the logs for more details." @@ -110,3 +97,32 @@ def stageTest(def context) { } } } + +def stagePackageEvidences(def context) { + stage('Package Evidences') { + sh ''' + mkdir -p artifacts/evidence + # Copiar PDFs del reporte de pruebas + if [ -d build/test-results/mochawesome/pdf ]; then + cp -r build/test-results/mochawesome/pdf artifacts/evidence/test-reports-pdf + fi + # Copiar videos + if [ -d cypress/videos ]; then + cp -r cypress/videos artifacts/evidence/videos + fi + # Copiar screenshots (incluyendo el JSON del CronJob) + if [ -d build/test-results/screenshots ]; then + cp -r build/test-results/screenshots artifacts/evidence/screenshots + fi + # Copiar el reporte SonarQube si existe + find . -name "sonarqube-report-*.pdf" -exec cp {} artifacts/evidence/ \\; 2>/dev/null || true + + # Crear el ZIP final con todas las evidencias + cd artifacts && zip -r cypress-evidence.zip evidence + + # Limpiar el PDF del reporte SonarQube que está fuera del ZIP + rm -f artifacts/sonarqube-report-*.pdf + ''' + archiveArtifacts artifacts: 'artifacts/cypress-evidence.zip', fingerprint: true + } +} diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts index 935277a0..ad5e612d 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts @@ -21,7 +21,6 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( const projectId = "{{.ProjectID}}"; const username = Cypress.env("BITBUCKET_USERNAME"); const password = Cypress.env("BITBUCKET_PASSWORD"); - const ocConsoleCronJobUrl = Cypress.env("OC_CONSOLE_CRONJOB_URL"); const targetRepo = `${projectId}-python-test-renovate`; const repoUrl = `${bitbucketBaseUrl}/projects/${projectId}/repos/${targetRepo}`; @@ -42,12 +41,17 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( }); it('Should show the Renovate CronJob in the OpenShift Console', () => { - // Navigate directly without session (OC console has its own auth) - cy.visit(ocConsoleCronJobUrl, { failOnStatusCode: false }); - // Wait for the main content area to render (OC console is a SPA, needs time) - cy.get('body', { timeout: 30000 }).should('be.visible'); - cy.get('a[data-test-id="renovate-qs"]', { timeout: 30000 }).should('be.visible'); - cy.screenshot('acceptance-01-oc-console-cronjob'); + const ocNamespace = Cypress.env("OC_NAMESPACE") || `${projectId}-cd`; + const cronJobName = Cypress.env("CRONJOB_NAME") || "renovate-qs"; + // Ejecuta el comando oc get cronjob usando cy.exec + cy.exec(`oc get cronjob ${cronJobName} -n ${ocNamespace} -o json`, { failOnNonZeroExit: false }).then(({ code, stdout, stderr }) => { + expect(code).to.eq(0); + const cronjob = JSON.parse(stdout); + expect(cronjob).to.have.property('metadata'); + expect(cronjob.metadata.name).to.eq(cronJobName); + // Guardar el JSON como evidencia en build/test-results/screenshots + cy.writeFile('build/test-results/screenshots/acceptance-01-oc-cronjob.json', JSON.stringify(cronjob, null, 2)); + }); }); it('Should navigate to the Pull Requests page and see at least one PR', () => { diff --git a/renovate/testdata/golden/jenkins-build-cypress.json b/renovate/testdata/golden/jenkins-build-cypress.json index 25ac28f6..c1be11bf 100644 --- a/renovate/testdata/golden/jenkins-build-cypress.json +++ b/renovate/testdata/golden/jenkins-build-cypress.json @@ -19,6 +19,10 @@ "stage": "SonarQube Analysis", "status": "SUCCESS" }, + { + "stage": "Package Evidences", + "status": "SUCCESS" + }, { "stage": "Upload to Nexus", "status": "SUCCESS" From 582c03ef3ae8645fa7e4792de6177d6e0d34189e Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Mon, 23 Feb 2026 11:27:06 +0100 Subject: [PATCH 20/22] Rename Cypress test reports zip file to 'cypress-evidence.zip' in steps.yml --- renovate/testdata/steps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate/testdata/steps.yml b/renovate/testdata/steps.yml index 73493b71..3a9e0455 100644 --- a/renovate/testdata/steps.yml +++ b/renovate/testdata/steps.yml @@ -145,6 +145,6 @@ steps: sonarScan: "golden/sonar-scan-cypress.json" runAttachments: - sonarqube-report-{{.ProjectID}}-{{.ComponentID}}.pdf - - cypress-test-reports-pdf.zip + - cypress-evidence.zip testResults: 1 From a3d331a6532ecceb02aa17f81870fe7916acaed4 Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Mon, 23 Feb 2026 13:40:03 +0100 Subject: [PATCH 21/22] Disable Cypress video recording and update evidence packaging in Jenkinsfile; adjust file paths for acceptance test JSON output --- .../testdata/fixtures/renovate-cypress/Jenkinsfile | 13 +------------ .../tests/acceptance/renovate-acceptance.spec.cy.ts | 5 +---- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile index f372bfd2..3f9552ea 100644 --- a/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile +++ b/renovate/testdata/fixtures/renovate-cypress/Jenkinsfile @@ -70,7 +70,7 @@ def stageTest(def context) { "OPENSHIFT_APP_DOMAIN=${context.getOpenshiftApplicationDomain()}", "COMMIT_INFO_SHA=${context.gitCommit}", "BUILD_NUMBER=${context.buildNumber}", - "CYPRESS_VIDEO=true", + "CYPRESS_VIDEO=false", "CYPRESS_BITBUCKET_BASE_URL=${bitbucketBaseUrl}", "CYPRESS_PROJECT_ID=${context.projectId}", "CYPRESS_OC_CONSOLE_CRONJOB_URL=https://console-openshift-console.${context.getOpenshiftApplicationDomain()}/k8s/ns/${context.targetProject}/cronjobs/renovate-qs/", @@ -102,25 +102,14 @@ def stagePackageEvidences(def context) { stage('Package Evidences') { sh ''' mkdir -p artifacts/evidence - # Copiar PDFs del reporte de pruebas if [ -d build/test-results/mochawesome/pdf ]; then cp -r build/test-results/mochawesome/pdf artifacts/evidence/test-reports-pdf fi - # Copiar videos - if [ -d cypress/videos ]; then - cp -r cypress/videos artifacts/evidence/videos - fi - # Copiar screenshots (incluyendo el JSON del CronJob) if [ -d build/test-results/screenshots ]; then cp -r build/test-results/screenshots artifacts/evidence/screenshots fi - # Copiar el reporte SonarQube si existe find . -name "sonarqube-report-*.pdf" -exec cp {} artifacts/evidence/ \\; 2>/dev/null || true - - # Crear el ZIP final con todas las evidencias cd artifacts && zip -r cypress-evidence.zip evidence - - # Limpiar el PDF del reporte SonarQube que está fuera del ZIP rm -f artifacts/sonarqube-report-*.pdf ''' archiveArtifacts artifacts: 'artifacts/cypress-evidence.zip', fingerprint: true diff --git a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts index ad5e612d..f83e9f17 100644 --- a/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts +++ b/renovate/testdata/fixtures/renovate-cypress/tests/acceptance/renovate-acceptance.spec.cy.ts @@ -25,7 +25,6 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( const repoUrl = `${bitbucketBaseUrl}/projects/${projectId}/repos/${targetRepo}`; beforeEach(() => { - // Establish authenticated session with Bitbucket Server via form login cy.session('bitbucket-login', () => { cy.request({ method: 'POST', @@ -43,14 +42,12 @@ describe('Renovate Bot Acceptance Tests - Pull Request Creation Verification', ( it('Should show the Renovate CronJob in the OpenShift Console', () => { const ocNamespace = Cypress.env("OC_NAMESPACE") || `${projectId}-cd`; const cronJobName = Cypress.env("CRONJOB_NAME") || "renovate-qs"; - // Ejecuta el comando oc get cronjob usando cy.exec cy.exec(`oc get cronjob ${cronJobName} -n ${ocNamespace} -o json`, { failOnNonZeroExit: false }).then(({ code, stdout, stderr }) => { expect(code).to.eq(0); const cronjob = JSON.parse(stdout); expect(cronjob).to.have.property('metadata'); expect(cronjob.metadata.name).to.eq(cronJobName); - // Guardar el JSON como evidencia en build/test-results/screenshots - cy.writeFile('build/test-results/screenshots/acceptance-01-oc-cronjob.json', JSON.stringify(cronjob, null, 2)); + cy.writeFile('build/test-results/screenshots/renovate-acceptance.spec.cy.ts/acceptance-01-oc-cronjob.json', JSON.stringify(cronjob, null, 2)); }); }); From 7fd39497c9107b4a6d17c03b4ea6b894eaa79e1e Mon Sep 17 00:00:00 2001 From: EDPCommunity Automated Test Date: Mon, 23 Feb 2026 13:54:28 +0100 Subject: [PATCH 22/22] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5862a89..9b9d9cdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- Add renovate bot functional test evidences ([1146](https://github.com/opendevstack/ods-quickstarters/pull/1149)) - Add renovate bot ([1146](https://github.com/opendevstack/ods-quickstarters/pull/1146)) - Update Quickstarter Tests to Support New Framework Test Capabilities ([#1144](https://github.com/opendevstack/ods-quickstarters/pull/1144)) ### Added