1- import { test } from "@playwright/test" ;
1+ import { test , expect } from "@playwright/test" ;
22import { UIhelper } from "../../../utils/ui-helper" ;
33import { Common } from "../../../utils/common" ;
44import { Orchestrator } from "../../../support/pages/orchestrator" ;
55import { skipIfJobName } from "../../../utils/helper" ;
66import { JOB_NAME_PATTERNS } from "../../../utils/constants" ;
7+ import { LogUtils } from "../../audit-log/log-utils" ;
78
89test . describe ( "Orchestrator failswitch workflow tests" , ( ) => {
910 test . skip ( ( ) => skipIfJobName ( JOB_NAME_PATTERNS . OSD_GCP ) ) ; // skipping orchestrator tests on OSD-GCP due to infra not being installed
@@ -24,18 +25,183 @@ test.describe("Orchestrator failswitch workflow tests", () => {
2425 await uiHelper . openSidebar ( "Orchestrator" ) ;
2526 await orchestrator . selectFailSwitchWorkflowItem ( ) ;
2627 await orchestrator . runFailSwitchWorkflow ( "OK" ) ;
28+ await orchestrator . validateCurrentWorkflowStatus ( "Completed" ) ;
2729 await orchestrator . reRunFailSwitchWorkflow ( "Wait" ) ;
2830 await orchestrator . abortWorkflow ( ) ;
2931 await orchestrator . reRunFailSwitchWorkflow ( "KO" ) ;
30- await orchestrator . validateWorkflowStatus ( "Failed" ) ;
32+ await orchestrator . validateCurrentWorkflowStatus ( "Failed" ) ;
33+ await uiHelper . openSidebar ( "Orchestrator" ) ;
34+ await orchestrator . selectFailSwitchWorkflowItem ( ) ;
35+ await orchestrator . runFailSwitchWorkflow ( "Wait" ) ;
36+ await orchestrator . validateCurrentWorkflowStatus ( "Running" ) ;
3137 await uiHelper . openSidebar ( "Orchestrator" ) ;
3238 await orchestrator . validateWorkflowAllRuns ( ) ;
39+ await orchestrator . validateWorkflowAllRunsStatusIcons ( ) ;
3340 } ) ;
3441
35- test ( "Failswitch workflow execution and test abort workflow" , async ( ) => {
42+ test ( "Test abort workflow" , async ( ) => {
3643 await uiHelper . openSidebar ( "Orchestrator" ) ;
3744 await orchestrator . selectFailSwitchWorkflowItem ( ) ;
3845 await orchestrator . runFailSwitchWorkflow ( "Wait" ) ;
3946 await orchestrator . abortWorkflow ( ) ;
4047 } ) ;
48+
49+ test ( "Test Running status validations" , async ( ) => {
50+ await uiHelper . openSidebar ( "Orchestrator" ) ;
51+ await orchestrator . selectFailSwitchWorkflowItem ( ) ;
52+ await orchestrator . runFailSwitchWorkflow ( "Wait" ) ;
53+ await orchestrator . validateWorkflowStatusDetails ( "Running" ) ;
54+ } ) ;
55+
56+ test ( "Test Failed status validations" , async ( ) => {
57+ await uiHelper . openSidebar ( "Orchestrator" ) ;
58+ await orchestrator . selectFailSwitchWorkflowItem ( ) ;
59+ await orchestrator . runFailSwitchWorkflow ( "KO" ) ;
60+ await orchestrator . validateWorkflowStatusDetails ( "Failed" ) ;
61+ } ) ;
62+
63+ test ( "Test Completed status validations" , async ( ) => {
64+ await uiHelper . openSidebar ( "Orchestrator" ) ;
65+ await orchestrator . selectFailSwitchWorkflowItem ( ) ;
66+ await orchestrator . runFailSwitchWorkflow ( "OK" ) ;
67+ await orchestrator . validateWorkflowStatusDetails ( "Completed" ) ;
68+ } ) ;
69+
70+ test ( "Test rerunning from failure point using failswitch workflow" , async ( { } , testInfo ) => {
71+ test . setTimeout ( 240000 ) ; // 4 minutes: pod restarts + 60s sleep + failure/recovery time
72+ const ns = testInfo . project . name ;
73+
74+ test . skip ( ! ns , "NAME_SPACE not set" ) ;
75+
76+ const originalHttpbin = "https://httpbin.org/" ;
77+ try {
78+ await patchHttpbin ( ns ! , "https://foobar.org/" ) ;
79+ await restartAndWait ( ns ! ) ;
80+
81+ await uiHelper . openSidebar ( "Orchestrator" ) ;
82+ await orchestrator . selectFailSwitchWorkflowItem ( ) ;
83+ await orchestrator . runFailSwitchWorkflow ( "Wait" ) ;
84+ await orchestrator . validateCurrentWorkflowStatus ( "Failed" ) ; // 2 minutes: 60s sleep + time to fail
85+
86+ await patchHttpbin ( ns ! , originalHttpbin ) ;
87+ await restartAndWait ( ns ! ) ;
88+
89+ await orchestrator . reRunOnFailure ( "From failure point" ) ;
90+ await orchestrator . validateCurrentWorkflowStatus ( "Completed" ) ;
91+ } catch ( e ) {
92+ test . info ( ) . annotations . push ( {
93+ type : "test-error" ,
94+ description : String ( e ) ,
95+ } ) ;
96+ throw e ;
97+ } finally {
98+ try {
99+ await cleanupAfterTest ( ns ! , originalHttpbin ) ;
100+ } catch ( cleanupErr ) {
101+ test . info ( ) . annotations . push ( {
102+ type : "cleanup-error" ,
103+ description : String ( cleanupErr ) ,
104+ } ) ;
105+ }
106+ }
107+ } ) ;
108+
109+ test ( "Failswitch links to another workflow and link works" , async ( {
110+ page,
111+ } ) => {
112+ await uiHelper . openSidebar ( "Orchestrator" ) ;
113+ await orchestrator . selectFailSwitchWorkflowItem ( ) ;
114+ await orchestrator . runFailSwitchWorkflow ( "OK" ) ;
115+
116+ // Verify suggested next workflow section and navigate via the greeting link
117+ await expect (
118+ page . getByRole ( "heading" , { name : / s u g g e s t e d n e x t w o r k f l o w / i } ) ,
119+ ) . toBeVisible ( ) ;
120+ const greetingLink = page . getByRole ( "link" , { name : / g r e e t i n g / i } ) ;
121+ await expect ( greetingLink ) . toBeVisible ( ) ;
122+ await greetingLink . click ( ) ;
123+
124+ // Popup should appear for Greeting workflow
125+ await expect (
126+ page . getByRole ( "dialog" , { name : / g r e e t i n g w o r k f l o w / i } ) ,
127+ ) . toBeVisible ( ) ;
128+ await expect (
129+ page . getByRole ( "button" , { name : / r u n w o r k f l o w / i } ) ,
130+ ) . toBeVisible ( ) ;
131+ await page . getByRole ( "button" , { name : / r u n w o r k f l o w / i } ) . click ( ) ;
132+
133+ // Verify Greeting workflow execute view shows correct header and "Next" button
134+ await expect (
135+ page . getByRole ( "heading" , { name : "Greeting workflow" } ) ,
136+ ) . toBeVisible ( ) ;
137+ await expect ( page . getByRole ( "button" , { name : "Next" } ) ) . toBeVisible ( ) ;
138+ } ) ;
41139} ) ;
140+
141+ async function getHttpbinValue ( ns : string ) : Promise < string | undefined > {
142+ const args = [
143+ "-n" ,
144+ ns ,
145+ "get" ,
146+ "sonataflow" ,
147+ "failswitch" ,
148+ "-o" ,
149+ `jsonpath={.spec.podTemplate.container.env[?(@.name=='HTTPBIN')].value}` ,
150+ ] ;
151+ const out = await LogUtils . executeCommand ( "oc" , args ) ;
152+ return out || undefined ;
153+ }
154+
155+ async function patchHttpbin ( ns : string , value : string ) : Promise < void > {
156+ const patch = `{"spec":{"podTemplate":{"container":{"env":[{"name":"HTTPBIN","value":"${ value } "}]}}}}` ;
157+ console . log ( "patching HTTPBIN in sontaflow resource to " , value ) ;
158+ const args = [
159+ "-n" ,
160+ ns ,
161+ "patch" ,
162+ "sonataflow" ,
163+ "failswitch" ,
164+ "--type" ,
165+ "merge" ,
166+ "-p" ,
167+ patch ,
168+ ] ;
169+ await LogUtils . executeCommand ( "oc" , args ) ;
170+ }
171+
172+ async function restartAndWait ( ns : string ) : Promise < void > {
173+ console . log ( "restarting deployment failswitch" ) ;
174+ const restartArgs = [
175+ "-n" ,
176+ ns ,
177+ "rollout" ,
178+ "restart" ,
179+ "deployment" ,
180+ "failswitch" ,
181+ ] ;
182+ await LogUtils . executeCommand ( "oc" , restartArgs ) ;
183+
184+ console . log ( "waiting for pods to be ready" ) ;
185+ const waitArgs = [
186+ "-n" ,
187+ ns ,
188+ "wait" ,
189+ "--for=condition=ready" ,
190+ "pod" ,
191+ "-l" ,
192+ "app.kubernetes.io/name=failswitch" ,
193+ "--timeout=5s" ,
194+ ] ;
195+ await LogUtils . executeCommandWithRetries ( "oc" , waitArgs , 5 ) ;
196+ }
197+
198+ async function cleanupAfterTest (
199+ ns : string ,
200+ originalHttpbin : string ,
201+ ) : Promise < void > {
202+ const currentHttpbin = await getHttpbinValue ( ns ! ) ;
203+ if ( currentHttpbin !== originalHttpbin ) {
204+ await patchHttpbin ( ns ! , originalHttpbin ) ;
205+ await restartAndWait ( ns ! ) ;
206+ }
207+ }
0 commit comments