Skip to content

Commit a955cb4

Browse files
committed
Add cc vaulting tests
1 parent 6626d08 commit a955cb4

File tree

5 files changed

+297
-16
lines changed

5 files changed

+297
-16
lines changed

playwright.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ export default defineConfig({
4848
use: { ...devices['Desktop Chrome'] },
4949
testMatch: '**/pay-order-gateway-tests.spec.ts',
5050
},
51+
{
52+
name: 'cc-vaulting-tests',
53+
dependencies: ['setup'],
54+
use: { ...devices['Desktop Chrome'] },
55+
testMatch: '**/cc-vaulting-transaction.spec.ts',
56+
},
5157
],
5258

5359
/* Run your local dev server before starting the tests */

tests/helpers/admin-test-helpers.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,26 @@ export class AdminTestHelpers {
3939
console.log('✅ Successfully logged in as admin');
4040
}
4141

42+
async loginAsCustomer(username: string, password: string) {
43+
const adminUser = username;
44+
const adminPassword = password;
45+
46+
await this.page.goto('/wp-admin');
47+
48+
if (await this.page.locator('#wpadminbar').isVisible()) {
49+
console.log('Already logged in as admin');
50+
return;
51+
}
52+
53+
await this.page.fill('#user_login', adminUser);
54+
await this.page.fill('#user_pass', adminPassword);
55+
await this.page.click('#wp-submit');
56+
57+
await this.page.waitForURL('/wp-admin/', { timeout: 10000 });
58+
await expect(this.page.locator('#wpadminbar')).toBeVisible();
59+
console.log('✅ Successfully logged in as customer');
60+
}
61+
4262
/**
4363
* Feature: WordPress admin logout
4464
* Scenario: Admin logs out from WordPress dashboard

tests/helpers/payment-processors/credit-card-processor.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,28 @@ export class CreditCardProcessor extends BasePaymentProcessor {
2626
if(isHostedPayment) {
2727
await this.clickWooSubmitButton()
2828
await this.page.waitForLoadState('networkidle');
29-
30-
const frameLocator = this.page.frameLocator('iframe[name^="__zoid__monei_card_input__"]');
31-
32-
await this.page.getByTestId(this.cardholderNameInput).fill(cardDetails.cardholderName);
33-
34-
await frameLocator.getByTestId(this.cardNumberInput).fill(cardDetails.cardNumber);
35-
await frameLocator.getByTestId(this.cardExpiryInput).fill(cardDetails.expiry);
36-
await frameLocator.getByTestId(this.cardCvcInput).fill(cardDetails.cvc);
37-
29+
await this.fillCardDetails(cardDetails);
3830
await this.page.getByTestId(this.submitButton).click();
3931
if (preset === 'threeDSecure' || preset === 'fail') {
4032
await this.complete3DSecure(preset);
4133
}
4234
} else {
43-
const frameLocator = this.page.frameLocator('iframe[name^="__zoid__monei_card_input__"]');
44-
45-
await this.page.getByTestId(this.cardholderNameInput).fill(cardDetails.cardholderName);
46-
47-
await frameLocator.getByTestId(this.cardNumberInput).fill(cardDetails.cardNumber);
48-
await frameLocator.getByTestId(this.cardExpiryInput).fill(cardDetails.expiry);
49-
await frameLocator.getByTestId(this.cardCvcInput).fill(cardDetails.cvc);
35+
await this.fillCardDetails(cardDetails);
5036
await this.clickWooSubmitButton()
5137
if (preset === 'threeDSecure') {
5238
await this.complete3DSecure(preset);
5339
}
5440
}
5541
}
5642

43+
async fillCardDetails(cardDetails = PAYMENT_TEST_DATA.creditCard['success']) {
44+
const frameLocator = this.page.frameLocator('iframe[name^="__zoid__monei_card_input__"]');
45+
await this.page.getByTestId(this.cardholderNameInput).fill(cardDetails.cardholderName);
46+
await frameLocator.getByTestId(this.cardNumberInput).fill(cardDetails.cardNumber);
47+
await frameLocator.getByTestId(this.cardExpiryInput).fill(cardDetails.expiry);
48+
await frameLocator.getByTestId(this.cardCvcInput).fill(cardDetails.cvc);
49+
}
50+
5751
async validateCardErrors(invalidCard: {
5852
cardNumber: string;
5953
expiry: string;

tests/setup/wordpress-api-client.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,15 @@ export class WordPressApiClient {
293293
}
294294
}
295295

296+
async updateGatewaySettings(gatewayId, settings) {
297+
try {
298+
const response = await this.wooCommerce.put(`payment_gateways/${gatewayId}`, settings);
299+
return response.data;
300+
} catch (error) {
301+
this.handleWooCommerceError(error, 'Error updating gateway');
302+
}
303+
}
304+
296305
// Additional WooCommerce helper methods
297306
async getTaxRates(): Promise<any[]> {
298307
this.logApiCall('GET', '/wp-json/wc/v3/taxes', 'All tax rates');
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
import { test, expect } from '@playwright/test';
2+
import { MoneiSettingsPage } from '../pages/admin/monei-settings-page';
3+
import { CheckoutPage } from '../pages/checkout-page';
4+
import { CartPage } from '../pages/cart-page';
5+
import { AdminTestHelpers, TestEnvironmentHelper } from '../helpers/admin-test-helpers';
6+
import { CreditCardProcessor } from '../helpers/payment-processors/credit-card-processor';
7+
import { OrderVerification } from '../verification/order-verification';
8+
import { WordPressApiClient } from '../setup/wordpress-api-client';
9+
import { CHECKOUT_TYPES } from '../fixtures/checkout-types';
10+
import { PRODUCT_TYPES } from '../fixtures/product-types';
11+
import { USER_TYPES } from '../fixtures/user-types';
12+
import { TEST_USERS } from '../setup/user-setup'
13+
import { UserAuthenticationManager } from '../setup/user-setup'
14+
15+
/**
16+
* MONEI Vaulting/Tokenization Complete Integration Test Suite
17+
*
18+
* This test suite validates:
19+
* 1. Enabling tokenization setting programmatically via existing WooCommerce API client
20+
* 2. Saving credit card from user account payments page
21+
* 3. Removing saved payment methods
22+
* 4. Saving payment method during checkout flow using existing CreditCardProcessor
23+
* 5. Using saved payment method for subsequent transactions
24+
*/
25+
test.describe('MONEI Vaulting/Tokenization Integration Test', () => {
26+
let moneiSettingsPage: MoneiSettingsPage;
27+
let adminHelpers: AdminTestHelpers;
28+
let cartPage: CartPage;
29+
let checkoutPage: CheckoutPage;
30+
let apiClient: WordPressApiClient;
31+
let creditCardProcessor: CreditCardProcessor;
32+
let orderVerification: OrderVerification;
33+
const testConfig = TestEnvironmentHelper.getTestConfig();
34+
let customerEmail: string;
35+
let customerPassword: string;
36+
37+
38+
test.beforeAll(async () => {
39+
TestEnvironmentHelper.validateEnvironment();
40+
console.log('🔧 Test environment validated successfully');
41+
customerEmail = TEST_USERS.ES_CUSTOMER.email;
42+
customerPassword = TEST_USERS.ES_CUSTOMER.password;
43+
});
44+
45+
test.beforeEach(async ({ page }) => {
46+
moneiSettingsPage = new MoneiSettingsPage(page);
47+
adminHelpers = new AdminTestHelpers(page);
48+
cartPage = new CartPage(page);
49+
checkoutPage = new CheckoutPage(page, CHECKOUT_TYPES.CLASSIC);
50+
apiClient = new WordPressApiClient();
51+
creditCardProcessor = new CreditCardProcessor(page, false); // Direct mode for tokenization
52+
orderVerification = new OrderVerification(page);
53+
54+
await adminHelpers.loginAsAdmin(testConfig.adminUser, testConfig.adminPassword);
55+
console.log('🔐 Authenticated as WordPress admin');
56+
});
57+
58+
test.afterEach(async ({ page }) => {
59+
await adminHelpers.cleanupTestData();
60+
});
61+
62+
/**
63+
* Test 1: Setup MONEI with tokenization enabled using existing API infrastructure
64+
*/
65+
test('Setup MONEI configuration and enable tokenization', async ({ page }) => {
66+
console.log('📋 Step 1: Configuring MONEI with test API keys');
67+
68+
// Configure MONEI basic settings using existing method
69+
await adminHelpers.navigateToMoneiSettings();
70+
const isValidConfig = await adminHelpers.validateApiKeys(testConfig.accountId, testConfig.apiKey);
71+
expect(isValidConfig).toBeTruthy();
72+
console.log('✅ MONEI test API keys configured and validated');
73+
74+
// Enable MONEI Credit Card gateway with tokenization using existing API client
75+
console.log('📋 Step 2: Enabling MONEI Credit Card gateway with tokenization via API');
76+
77+
try {
78+
// Enable the main credit card gateway with tokenization
79+
await apiClient.updateGatewaySettings('monei', {
80+
enabled: true,
81+
settings: {
82+
tokenization: 'yes',
83+
}
84+
});
85+
86+
console.log('✅ MONEI Credit Card gateway enabled with tokenization via API');
87+
88+
// Verify tokenization is enabled in admin panel
89+
await page.goto('/wp-admin/admin.php?page=wc-settings&tab=checkout&section=monei');
90+
await page.waitForLoadState('networkidle');
91+
92+
const tokenizationEnabled = await page.isChecked('#woocommerce_monei_tokenization');
93+
expect(tokenizationEnabled).toBe(true);
94+
console.log('✅ Tokenization setting verified in admin panel');
95+
96+
} catch (error) {
97+
console.error('❌ Failed to enable tokenization via API:', error);
98+
throw error;
99+
}
100+
});
101+
102+
/**
103+
* Test 2: Create test customer and save payment method from account page
104+
*/
105+
test('Save credit card method from user account payments page', async ({ page }) => {
106+
console.log('📋 Step 3: Login test customer and saving payment method');
107+
108+
// Login as customer and navigate to payment methods page
109+
await adminHelpers.loginAsCustomer(customerEmail, customerPassword);
110+
await page.goto('/my-account/payment-methods/');
111+
await page.waitForLoadState('networkidle');
112+
113+
// Check if "Add payment method" button exists
114+
const addMethodButton = page.getByRole('link', { name: 'Add payment method' });
115+
await expect(addMethodButton).toBeVisible();
116+
await addMethodButton.click();
117+
await page.waitForLoadState('networkidle');
118+
119+
// Use existing CreditCardProcessor with save option
120+
await fillCreditCardFormWithSave(page);
121+
122+
// Submit the form
123+
await page.click('#place_order, .wc-block-components-checkout-place-order-button');
124+
await page.waitForLoadState('networkidle');
125+
creditCardProcessor.fillCardDetails()
126+
await page.getByTestId('pay-button').click();
127+
128+
// Verify payment method was saved
129+
await page.waitForLoadState('networkidle');
130+
await page.goto('/my-account/payment-methods/');
131+
await page.waitForLoadState('networkidle');
132+
133+
const savedMethods = page.locator('.woocommerce-PaymentMethod[data-title="Method"]');
134+
const methodText = await savedMethods.textContent();
135+
expect(methodText).toContain('Visa ending in 4422');
136+
console.log('✅ Payment method saved successfully from account page');
137+
});
138+
139+
/**
140+
* Test 3: Save payment method during checkout
141+
*/
142+
test('Save payment method during checkout and complete transaction', async ({ page }) => {
143+
//TODO remove any saved payment method
144+
console.log('📋 Step 5: Testing save payment method during checkout');
145+
146+
// Add product to cart using existing CartPage
147+
await cartPage.addProductToCart(PRODUCT_TYPES.SIMPLE);
148+
console.log('✅ Product added to cart');
149+
150+
// Login as customer and proceed to checkout
151+
await adminHelpers.loginAsCustomer(customerEmail, customerPassword);
152+
await checkoutPage.goToCheckout(CHECKOUT_TYPES.CLASSIC); // Classic checkout
153+
await page.waitForLoadState('networkidle');
154+
155+
// Fill billing details using existing method
156+
await checkoutPage.fillBillingDetails(USER_TYPES.ES_USER);
157+
158+
// Select MONEI payment method
159+
const paymentMethodSelector = 'input[value="monei"]';
160+
await page.click(paymentMethodSelector);
161+
await page.waitForTimeout(1000); // Wait for payment form to load
162+
163+
// Use existing CreditCardProcessor with save option
164+
await processCreditCardPaymentWithSave(page);
165+
166+
// Complete the transaction
167+
await orderVerification.verifySuccessfulOrder();
168+
console.log('✅ Transaction completed successfully');
169+
170+
// Verify payment method was saved
171+
await page.goto('/my-account/payment-methods/');
172+
await page.waitForLoadState('networkidle');
173+
174+
const savedMethods = page.locator('.woocommerce-PaymentMethod[data-title="Method"]');
175+
const methodText = await savedMethods.textContent();
176+
expect(methodText).toContain('Visa ending in 4422');
177+
console.log('✅ Payment method saved during checkout');
178+
});
179+
180+
/**
181+
* Test 5: Use saved payment method for subsequent transaction
182+
*/
183+
test('Use saved payment method for subsequent transaction', async ({ page }) => {
184+
console.log('📋 Step 6: Testing transaction with saved payment method');
185+
186+
// Add another product to cart
187+
await cartPage.addProductToCart(PRODUCT_TYPES.SIMPLE);
188+
console.log('✅ Product added to cart for second transaction');
189+
190+
// Login as customer and proceed to checkout
191+
await adminHelpers.loginAsCustomer(customerEmail, customerPassword);
192+
await checkoutPage.goToCheckout(CHECKOUT_TYPES.CLASSIC); // Classic checkout
193+
await page.waitForLoadState('networkidle');
194+
195+
// Fill billing details
196+
await checkoutPage.fillBillingDetails(USER_TYPES.ES_USER);
197+
198+
// Select MONEI payment method
199+
await page.click('input[value="monei"]');
200+
await page.waitForTimeout(1000);
201+
202+
// Check if saved payment methods are available
203+
const savedMethodsDropdown = page.locator('select[name="wc-monei-payment-token"]');
204+
if (await savedMethodsDropdown.isVisible()) {
205+
// Select the saved payment method (skip "Use a new payment method" option)
206+
const options = await savedMethodsDropdown.locator('option').all();
207+
if (options.length > 1) {
208+
await savedMethodsDropdown.selectOption({ index: 1 }); // First saved method
209+
console.log('✅ Saved payment method selected');
210+
} else {
211+
throw new Error('No saved payment methods found in dropdown');
212+
}
213+
} else {
214+
// For block checkout or different UI, look for radio buttons
215+
const savedMethodRadio = page.locator('input[name="wc-monei-payment-token"]:not([value=""])').first();
216+
if (await savedMethodRadio.isVisible()) {
217+
await savedMethodRadio.check();
218+
console.log('✅ Saved payment method selected (radio button)');
219+
} else {
220+
throw new Error('No saved payment methods found');
221+
}
222+
}
223+
224+
// Complete the transaction
225+
await page.click('#place_order');
226+
await orderVerification.verifySuccessfulOrder();
227+
console.log('✅ Second transaction completed successfully using saved payment method');
228+
});
229+
230+
async function fillCreditCardFormWithSave(page: any) {
231+
creditCardProcessor.fillCardDetails()
232+
// Check save payment method checkbox
233+
const saveCheckbox = page.locator('#wc-monei-new-payment-method, input[name="wc-monei-new-payment-method"]');
234+
if (await saveCheckbox.isVisible()) {
235+
await saveCheckbox.check();
236+
console.log('✅ Save payment method checkbox checked');
237+
}
238+
}
239+
240+
async function processCreditCardPaymentWithSave(page: any) {
241+
// Check save payment method option
242+
const saveCheckbox = page.locator('#wc-monei-new-payment-method, input[name="wc-monei-new-payment-method"]');
243+
if (await saveCheckbox.isVisible()) {
244+
await saveCheckbox.check();
245+
}
246+
247+
await creditCardProcessor.clickWooSubmitButton();
248+
await page.waitForLoadState('networkidle');
249+
await creditCardProcessor.fillCardDetails();
250+
await page.getByTestId('pay-button').click();
251+
}
252+
});

0 commit comments

Comments
 (0)