@@ -10,6 +10,8 @@ export class PayForOrderPage {
1010 orderTotalSelector : string ;
1111 paymentMethodsSelector : string ;
1212 placeOrderButtonSelector : string ;
13+ savedPaymentMethodsSelector : string ;
14+ errorMessageSelector : string ;
1315
1416 // Credit Card specific locators
1517 cardholderNameInputSelector : string ;
@@ -27,90 +29,115 @@ export class PayForOrderPage {
2729 this . orderTotalSelector = '.wc-block-components-totals-footer-item .wc-block-components-totals-item__value' ;
2830 this . paymentMethodsSelector = '.wc-block-components-radio-control__input' ;
2931 this . placeOrderButtonSelector = '.wc-block-components-checkout-place-order-button' ;
32+ this . savedPaymentMethodsSelector = '.wc-block-saved-payment-method-options' ;
33+ this . errorMessageSelector = '.wc-block-components-notice-banner--error' ;
3034 } else {
3135 this . orderTotalSelector = '.order-total .amount' ;
3236 this . paymentMethodsSelector = '.wc_payment_method input[name="payment_method"]' ;
3337 this . placeOrderButtonSelector = '#place_order' ;
38+ this . savedPaymentMethodsSelector = '.wc-saved-payment-methods' ;
39+ this . errorMessageSelector = '.woocommerce-error' ;
3440 }
3541
3642 this . cardholderNameInputSelector = '#monei-card-holder-name' ;
3743 this . cardInputContainerSelector = '#monei-card-element' ;
3844 this . cardErrorContainerSelector = '#monei-card-errors' ;
3945 }
4046
41- async navigateToPayForOrderPage ( orderId : string ) {
42- await this . page . goto ( `/checkout/order-pay/${ orderId } /?pay_for_order=true&key=wc_order_XXXXXXXXXXXXX` ) ;
43- await this . waitForPageLoad ( ) ;
44- }
45-
46- async waitForPageLoad ( ) {
47- if ( this . checkoutType . isBlockCheckout ) {
48- await this . page . waitForSelector ( '.wc-block-checkout__main' ) ;
49- } else {
50- await this . page . waitForSelector ( '#order_review' ) ;
51- }
47+ async navigateToPayForOrderPage ( orderId : string , orderKey : string ) {
48+ const url = `/checkout/order-pay/${ orderId } /?pay_for_order=true&key=${ orderKey } ` ;
49+ await this . page . goto ( url ) ;
50+ await this . page . waitForLoadState ( 'networkidle' ) ;
5251 }
5352
5453 async getOrderTotal ( ) : Promise < string > {
55- const totalElement = await this . page . locator ( this . orderTotalSelector ) ;
56- return totalElement . innerText ( ) ;
54+ await this . page . waitForSelector ( this . orderTotalSelector ) ;
55+ const totalElement = await this . page . locator ( this . orderTotalSelector ) . first ( ) ;
56+ return await totalElement . innerText ( ) ;
5757 }
5858
5959 async selectPaymentMethod ( paymentMethod : PaymentMethod ) {
60- await this . page . click ( `${ this . paymentMethodsSelector } [value="${ paymentMethod . id } "]` ) ;
61- await this . page . waitForSelector ( `#payment_method_${ paymentMethod . id } ` ) ;
60+ const selector = paymentMethod . selector . classic ;
61+
62+ await this . page . waitForSelector ( selector ) ;
63+ await this . page . click ( selector ) ;
64+
65+ // Wait for payment method UI to update
66+ await this . page . waitForTimeout ( 500 ) ;
67+ }
68+
69+ async getAvailablePaymentMethods ( ) : Promise < string [ ] > {
70+ await this . page . waitForSelector ( this . paymentMethodsSelector ) ;
71+
72+ const methods : string [ ] = [ ] ;
73+ const inputs = await this . page . $$ ( this . paymentMethodsSelector ) ;
74+
75+ for ( const input of inputs ) {
76+ const value = await input . getAttribute ( 'value' ) ;
77+ if ( value ) {
78+ methods . push ( value ) ;
79+ }
80+ }
81+
82+ return methods ;
6283 }
6384
64- async fillCreditCardDetails ( cardDetails : {
65- cardNumber : string ;
66- expiryDate : string ;
67- cvc : string ;
68- cardholderName : string ;
69- } ) {
70- await this . page . fill ( this . cardholderNameInputSelector , cardDetails . cardholderName ) ;
71-
72- // Assuming the card details are entered into an iframe
73- const frameHandle = await this . page . waitForSelector ( `${ this . cardInputContainerSelector } iframe` ) ;
74- const frame = await frameHandle . contentFrame ( ) ;
75-
76- await frame ?. fill ( '[name="cardnumber"]' , cardDetails . cardNumber ) ;
77- await frame ?. fill ( '[name="exp-date"]' , cardDetails . expiryDate ) ;
78- await frame ?. fill ( '[name="cvc"]' , cardDetails . cvc ) ;
85+ async fillCardholderName ( name : string ) {
86+ await this . page . waitForSelector ( this . cardholderNameInputSelector ) ;
87+ await this . page . fill ( this . cardholderNameInputSelector , name ) ;
7988 }
8089
81- async placeOrder ( ) {
90+ async clickPlaceOrder ( ) {
91+ await this . page . waitForSelector ( this . placeOrderButtonSelector ) ;
92+
93+ // Ensure button is enabled
94+ await this . page . waitForFunction (
95+ selector => {
96+ const button = document . querySelector ( selector ) ;
97+ return button && ! ( button as HTMLButtonElement ) . disabled ;
98+ } ,
99+ this . placeOrderButtonSelector ,
100+ { timeout : 10000 }
101+ ) ;
102+
82103 await this . page . click ( this . placeOrderButtonSelector ) ;
83- await this . page . waitForNavigation ( { waitUntil : 'networkidle' } ) ;
84104 }
85105
86- async verifyOrderDetails ( expectedTotal : string ) {
87- const actualTotal = await this . getOrderTotal ( ) ;
88- expect ( actualTotal ) . toBe ( expectedTotal ) ;
106+ async hasSavedPaymentMethods ( ) : Promise < boolean > {
107+ try {
108+ await this . page . waitForSelector ( this . savedPaymentMethodsSelector , { timeout : 5000 } ) ;
109+ return true ;
110+ } catch {
111+ return false ;
112+ }
89113 }
90114
91- async verifyPaymentMethodVisibility ( paymentMethod : PaymentMethod , shouldBeVisible : boolean ) {
92- const selector = this . checkoutType . isBlockCheckout
93- ? `.wc-block-components-radio-control__input[value=" ${ paymentMethod . id } "]`
94- : ` input[name="payment_method"][value=" ${ paymentMethod . id } "] `;
115+ async selectSavedPaymentMethod ( index : number = 0 ) {
116+ const savedMethodSelector = this . checkoutType . isBlockCheckout ?
117+ `.wc-block-saved-payment-method-options__option:nth-child( ${ index + 1 } ) input` :
118+ `.wc-saved-payment-methods input[type="radio"]:nth-child( ${ index + 1 } ) `;
95119
96- if ( shouldBeVisible ) {
97- await expect ( this . page . locator ( selector ) ) . toBeVisible ( ) ;
98- } else {
99- await expect ( this . page . locator ( selector ) ) . toBeHidden ( ) ;
100- }
120+ await this . page . click ( savedMethodSelector ) ;
101121 }
102122
103- async getErrorMessage ( ) : Promise < string | null > {
104- const errorSelector = this . checkoutType . isBlockCheckout
105- ? '.wc-block-components-notice-banner__content'
106- : '.woocommerce-error' ;
123+ async waitForPaymentProcessing ( ) {
124+ // Wait for either success redirect or error message
125+ await Promise . race ( [
126+ this . page . waitForSelector ( '.woocommerce-order-received' , { timeout : 30000 } ) ,
127+ this . page . waitForSelector ( this . errorMessageSelector , { timeout : 30000 } )
128+ ] ) ;
129+ }
107130
108- const errorElement = await this . page . locator ( errorSelector ) ;
109- return errorElement . isVisible ( ) ? errorElement . innerText ( ) : null ;
131+ async getErrorMessage ( ) : Promise < string | null > {
132+ const errorElement = await this . page . locator ( this . errorMessageSelector ) ;
133+ if ( await errorElement . isVisible ( ) ) {
134+ return await errorElement . innerText ( ) ;
135+ }
136+ return null ;
110137 }
111138
112- async waitForSuccessfulPayment ( ) {
113- // Wait for the success message or redirection to the order received page
114- await this . page . waitForSelector ( '.woocommerce-order-received' , { timeout : 30000 } ) ;
139+ async isOrderDetailsVisible ( ) : Promise < boolean > {
140+ return await this . page . isVisible ( '.woocommerce- order-pay' ) ||
141+ await this . page . isVisible ( '.wc-block-checkout__order-pay' ) ;
115142 }
116- }
143+ }
0 commit comments