From a3f7b77cff350302d5f734d3cfbee80d0ab6e67e Mon Sep 17 00:00:00 2001 From: Dmytro Nochevnov Date: Thu, 20 Aug 2026 21:36:05 +0300 Subject: [PATCH 1/3] Fix AnsibleDevfileApiTest failure after empty code from execInContainerCommand() Signed-off-by: Dmytro Nochevnov --- tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts b/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts index 6a716d59689..174661cc43e 100644 --- a/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts +++ b/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts @@ -176,7 +176,7 @@ export class KubernetesCommandLineToolsExecutor implements IKubernetesCommandLin Logger.debug(`${this.kubernetesCommandLineTool}`); return this.shellExecutor.executeCommand( - `${this.kubernetesCommandLineTool} exec -i -t ${KubernetesCommandLineToolsExecutor.pod} -n ${this.namespace} -c ${container} -- sh -c '${commandToExecute}'` + `${this.kubernetesCommandLineTool} exec -i ${KubernetesCommandLineToolsExecutor.pod} -n ${this.namespace} -c ${container} -- sh -c '${commandToExecute}'` ); } From be1cdfe20cbc3fb766314ff278e8dbf1310c7503 Mon Sep 17 00:00:00 2001 From: Dmytro Nochevnov Date: Thu, 20 Aug 2026 21:59:09 +0300 Subject: [PATCH 2/3] Second try Signed-off-by: Dmytro Nochevnov --- tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts b/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts index 65df87d9f34..cfd8f453de9 100644 --- a/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts +++ b/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts @@ -91,14 +91,16 @@ suite('Ansible devfile API test', function (): void { const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); expect(output.code).eqls(0); - const recapBlocks: string[] = output.stdout.split(/PLAY RECAP/g).slice(1); + // molecule may write its rich formatted output (box-drawing, ANSI codes) to stderr rather than stdout (CRW-12595) + const combinedOutput: string = (output.stdout + output.stderr).trim(); + + const recapBlocks: string[] = combinedOutput.split(/PLAY RECAP/g).slice(1); recapBlocks.forEach((block): void => { expect(block).match(/failed\s*=\s*0/); }); - const outputText: string = output.stdout.trim(); - expect(outputText).to.include('was installed successfully'); - expect(outputText).to.not.match(/failed\s*=\s*[1-9]\d*/); + expect(combinedOutput).to.include('was installed successfully'); + expect(combinedOutput).to.not.match(/failed\s*=\s*[1-9]\d*/); }); test('Check "molecule-list" command', function (): void { From e7eeced7197aca2737a3f9842bc6f452ef7774e7 Mon Sep 17 00:00:00 2001 From: Dmytro Nochevnov Date: Thu, 20 Aug 2026 22:08:49 +0300 Subject: [PATCH 3/3] Apply solution to all Ansible commands Signed-off-by: Dmytro Nochevnov --- tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts b/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts index cfd8f453de9..44800bb7a52 100644 --- a/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts +++ b/tests/e2e/specs/api/AnsibleDevFileAPI.spec.ts @@ -125,7 +125,8 @@ suite('Ansible devfile API test', function (): void { const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); expect(output.code).eqls(0); - const outputText: string = output.stdout.trim(); + // molecule may write its rich formatted output (box-drawing, ANSI codes) to stderr rather than stdout + const outputText: string = (output.stdout + output.stderr).trim(); expect(outputText).to.include('molecule'); expect(outputText).to.include('ansible'); expect(outputText).to.include('default'); @@ -154,14 +155,16 @@ suite('Ansible devfile API test', function (): void { const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); expect(output.code).eqls(0); - const recapBlocks: string[] = output.stdout.split(/PLAY RECAP/g).slice(1); + // molecule may write its rich formatted output (box-drawing, ANSI codes) to stderr rather than stdout + const combinedOutput: string = (output.stdout + output.stderr).trim(); + + const recapBlocks: string[] = combinedOutput.split(/PLAY RECAP/g).slice(1); recapBlocks.forEach((block): void => { expect(block).match(/failed\s*=\s*0/); }); - const outputText: string = output.stdout.trim(); - expect(outputText).to.include('PLAY [Converge]'); - expect(outputText).to.not.match(/failed\s*=\s*[1-9]\d*/); + expect(combinedOutput).to.include('PLAY [Converge]'); + expect(combinedOutput).to.not.match(/failed\s*=\s*[1-9]\d*/); }); test('Check "molecule-verify" command', function (): void { @@ -186,14 +189,16 @@ suite('Ansible devfile API test', function (): void { const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); expect(output.code).eqls(0); - const recapBlocks: string[] = output.stdout.split(/PLAY RECAP/g).slice(1); + // molecule may write its rich formatted output (box-drawing, ANSI codes) to stderr rather than stdout + const combinedOutput: string = (output.stdout + output.stderr).trim(); + + const recapBlocks: string[] = combinedOutput.split(/PLAY RECAP/g).slice(1); recapBlocks.forEach((block): void => { expect(block).match(/failed\s*=\s*0/); }); - const outputText: string = output.stdout.trim(); - expect(outputText).to.include('PLAY [Verify]'); - expect(outputText).to.not.match(/failed\s*=\s*[1-9]\d*/); + expect(combinedOutput).to.include('PLAY [Verify]'); + expect(combinedOutput).to.not.match(/failed\s*=\s*[1-9]\d*/); }); test('Check "molecule-destroy" command', function (): void { @@ -218,14 +223,16 @@ suite('Ansible devfile API test', function (): void { const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); expect(output.code).eqls(0); - const recapBlocks: string[] = output.stdout.split(/PLAY RECAP/g).slice(1); + // molecule may write its rich formatted output (box-drawing, ANSI codes) to stderr rather than stdout + const combinedOutput: string = (output.stdout + output.stderr).trim(); + + const recapBlocks: string[] = combinedOutput.split(/PLAY RECAP/g).slice(1); recapBlocks.forEach((block): void => { expect(block).match(/failed\s*=\s*0/); }); - const outputText: string = output.stdout.trim(); - expect(outputText).to.include('PLAY [Destroy]'); - expect(outputText).to.not.match(/failed\s*=\s*[1-9]\d*/); + expect(combinedOutput).to.include('PLAY [Destroy]'); + expect(combinedOutput).to.not.match(/failed\s*=\s*[1-9]\d*/); }); test('Check "molecule-test" command', function (): void { @@ -250,16 +257,18 @@ suite('Ansible devfile API test', function (): void { const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); expect(output.code).eqls(0); - const recapBlocks: string[] = output.stdout.split(/PLAY RECAP/g).slice(1); + // molecule may write its rich formatted output (box-drawing, ANSI codes) to stderr rather than stdout + const combinedOutput: string = (output.stdout + output.stderr).trim(); + + const recapBlocks: string[] = combinedOutput.split(/PLAY RECAP/g).slice(1); recapBlocks.forEach((block): void => { expect(block).match(/failed\s*=\s*0/); }); - const outputText: string = output.stdout.trim(); - expect(outputText).to.include('PLAY [Create]'); - expect(outputText).to.include('PLAY [Converge]'); - expect(outputText).to.include('PLAY [Verify]'); - expect(outputText).to.not.match(/failed\s*=\s*[1-9]\d*/); + expect(combinedOutput).to.include('PLAY [Create]'); + expect(combinedOutput).to.include('PLAY [Converge]'); + expect(combinedOutput).to.include('PLAY [Verify]'); + expect(combinedOutput).to.not.match(/failed\s*=\s*[1-9]\d*/); }); test('Check "ansible-navigator" command', function (): void { @@ -300,7 +309,8 @@ suite('Ansible devfile API test', function (): void { const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); expect(output.code).eqls(0); - const outputText: string = output.stdout.trim(); + // ansible-navigator may write output to stderr depending on terminal detection + const outputText: string = (output.stdout + output.stderr).trim(); expect(outputText).to.include('ansible-navigator'); expect(outputText).to.include('collections'); expect(outputText).to.include('config');