Skip to content

Commit 3a8e0ef

Browse files
committed
Global setup create products
1 parent d266a94 commit 3a8e0ef

File tree

5 files changed

+436
-20
lines changed

5 files changed

+436
-20
lines changed

playwright.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ dotenv.config({ path: path.resolve(__dirname, '.env') });
1212
* See https://playwright.dev/docs/test-configuration.
1313
*/
1414
export default defineConfig({
15+
globalSetup: require.resolve('./tests/setup/global-setup'),
1516
testDir: './tests',
1617
fullyParallel: true,
1718
forbidOnly: !!process.env.CI,
@@ -24,8 +25,13 @@ export default defineConfig({
2425
},
2526

2627
projects: [
28+
{
29+
name: 'setup',
30+
testMatch: /global\.setup\.ts/,
31+
},
2732
{
2833
name: 'transaction-tests',
34+
dependencies: ['setup'],
2935
use: { ...devices['Desktop Chrome'] },
3036
testMatch: '**/payment-gateway-matrix.spec.ts',
3137
},

tests/fixtures/product-types.ts

Lines changed: 100 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
1-
/**
2-
* Represents the configuration for a product type
3-
*/
1+
// tests/fixtures/product-types.ts
42
export interface ProductType {
53
id: string;
4+
sku: string;
65
name: string;
76
isSubscription: boolean;
87
subscriptionPlugin?: string; // 'woocommerce' or 'yith'
98
sampleProductId?: number; // ID of a sample product of this type for testing
109
sampleProductSlug?: string; // Slug of a sample product
11-
price?: number; // Price to expect
10+
price: number; // Price to expect
11+
// Add WooCommerce-specific fields
12+
woocommerce?: {
13+
type: 'simple' | 'variable' | 'subscription' | 'grouped' | 'external';
14+
status?: 'draft' | 'pending' | 'private' | 'publish';
15+
catalog_visibility?: 'visible' | 'catalog' | 'search' | 'hidden';
16+
description?: string;
17+
short_description?: string;
18+
categories?: Array<{ id: number; name: string; }>;
19+
images?: Array<{ src: string; alt: string; }>;
20+
attributes?: any[];
21+
variations?: any[];
22+
meta_data?: Array<{ key: string; value: any; }>;
23+
};
1224
}
1325

1426
/**
@@ -18,42 +30,110 @@ export const PRODUCT_TYPES: Record<string, ProductType> = {
1830
// Simple product
1931
SIMPLE: {
2032
id: 'simple',
33+
sku: 'TEST-SIMPLE-01',
2134
name: 'Simple Product',
2235
isSubscription: false,
2336
sampleProductId: 63,
2437
sampleProductSlug: 'simple',
25-
price: 19.99
38+
price: 19.99,
39+
woocommerce: {
40+
type: 'simple',
41+
status: 'publish',
42+
catalog_visibility: 'visible',
43+
description: 'A simple test product for automated testing',
44+
short_description: 'Simple test product'
45+
}
2646
},
2747

2848
// Variable product
2949
VARIABLE: {
3050
id: 'variable',
51+
sku: 'TEST-VARIABLE-01',
3152
name: 'Variable Product',
3253
isSubscription: false,
33-
sampleProductId: 456,
34-
sampleProductSlug: 'sample-variable-product',
35-
price: 29.99
54+
sampleProductId: 64,
55+
sampleProductSlug: 'variable',
56+
price: 29.99,
57+
woocommerce: {
58+
type: 'variable',
59+
status: 'publish',
60+
catalog_visibility: 'visible',
61+
description: 'A variable test product for automated testing',
62+
short_description: 'Variable test product',
63+
attributes: [
64+
{
65+
id: 1,
66+
name: 'Size',
67+
options: ['Small', 'Medium', 'Large'],
68+
visible: true,
69+
variation: true
70+
}
71+
]
72+
}
3673
},
3774

3875
// WooCommerce Subscription
39-
WC_SUBSCRIPTION: {
40-
id: 'subscription',
41-
name: 'WooCommerce Subscription',
76+
/*WOO_SUBSCRIPTION: {
77+
id: 'woo-subscription',
78+
sku: 'TEST-SUBSCRIPTION-WOO-01',
79+
name: 'WooCommerce Subscription Product',
4280
isSubscription: true,
4381
subscriptionPlugin: 'woocommerce',
44-
sampleProductId: 789,
45-
sampleProductSlug: 'sample-wc-subscription',
46-
price: 9.99
82+
sampleProductId: 65,
83+
sampleProductSlug: 'woo-subscription',
84+
price: 9.99,
85+
woocommerce: {
86+
type: 'subscription',//check this cause it fails
87+
status: 'publish',
88+
catalog_visibility: 'visible',
89+
description: 'A WooCommerce subscription test product',
90+
short_description: 'WooCommerce subscription test product',
91+
meta_data: [
92+
{ key: '_subscription_price', value: '9.99' },
93+
{ key: '_subscription_period', value: 'month' },
94+
{ key: '_subscription_period_interval', value: '1' }
95+
]
96+
}
4797
},
4898
4999
// YITH Subscription
50100
YITH_SUBSCRIPTION: {
51-
id: 'yith_subscription',
52-
name: 'YITH Subscription',
101+
id: 'yith-subscription',
102+
sku: 'TEST-SUBSCRIPTION-YITH-01',
103+
name: 'YITH Subscription Product',
53104
isSubscription: true,
54105
subscriptionPlugin: 'yith',
55-
sampleProductId: 1011,
56-
sampleProductSlug: 'sample-yith-subscription',
57-
price: 14.99
58-
}
106+
sampleProductId: 66,
107+
sampleProductSlug: 'yith-subscription',
108+
price: 14.99,
109+
woocommerce: {
110+
type: 'simple',
111+
status: 'publish',
112+
catalog_visibility: 'visible',
113+
description: 'A YITH subscription test product',
114+
short_description: 'YITH subscription test product',
115+
meta_data: [
116+
{ key: '_ywsbs_subscription', value: 'yes' },
117+
{ key: '_ywsbs_price_is_per', value: 'month' },
118+
{ key: '_ywsbs_price_time', value: '1' }
119+
]
120+
}
121+
}*/
122+
};
123+
124+
// Helper to get specific product types
125+
export const getProductsByType = (type: 'simple' | 'variable' | 'subscription') => {
126+
return Object.values(PRODUCT_TYPES).filter(product => {
127+
if (type === 'subscription') return product.isSubscription;
128+
if (type === 'variable') return product.woocommerce?.type === 'variable';
129+
if (type === 'simple') return product.woocommerce?.type === 'simple' && !product.isSubscription;
130+
return false;
131+
});
132+
};
133+
134+
// Helper to get products by subscription plugin
135+
export const getSubscriptionProducts = (plugin?: 'woocommerce' | 'yith') => {
136+
return Object.values(PRODUCT_TYPES).filter(product =>
137+
product.isSubscription && (!plugin || product.subscriptionPlugin === plugin)
138+
);
59139
};

tests/setup/global-setup.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// tests/setup/global-setup.ts
2+
import { chromium, FullConfig } from '@playwright/test';
3+
import { WordPressApiClient } from './wordpress-api-client';
4+
import { TestDataManager } from './test-data-manager';
5+
6+
async function globalSetup(config: FullConfig) {
7+
const browser = await chromium.launch();
8+
const context = await browser.newContext();
9+
const page = await context.newPage();
10+
11+
const apiClient = new WordPressApiClient();
12+
const testDataManager = new TestDataManager(apiClient);
13+
const baseUrl = process.env.TESTSITE_URL || 'https://staging-site.ddev.site';
14+
15+
// Authenticate as admin - use full URL
16+
await page.goto(`${baseUrl}/wp-admin`);
17+
await page.fill('#user_login', process.env.WP_ADMIN_USER || 'admin');
18+
await page.fill('#user_pass', process.env.WP_ADMIN_PASS || 'admin');
19+
await page.click('#wp-submit');
20+
21+
// Save authentication state
22+
await context.storageState({ path: 'tests/auth/admin-state.json' });
23+
24+
// test api client
25+
await apiClient.healthCheck();
26+
27+
28+
29+
// Setup test data
30+
await testDataManager.setupTestProducts();
31+
32+
// await testDataManager.setupTestProducts(['SIMPLE', 'VARIABLE']);
33+
// await testDataManager.setupProductsByType('simple');
34+
// await testDataManager.setupSubscriptionProducts('woocommerce');
35+
await testDataManager.setupTestPages();
36+
await testDataManager.setupMoneiPaymentMethods();
37+
38+
await browser.close();
39+
}
40+
41+
export default globalSetup;

tests/setup/test-data-manager.ts

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { PRODUCT_TYPES, ProductType } from '../fixtures/product-types';
2+
import { WordPressApiClient } from './wordpress-api-client';
3+
4+
export class TestDataManager {
5+
constructor(private apiClient: WordPressApiClient) {}
6+
7+
async setupTestProducts(productKeys?: string[]) {
8+
// Use all products if no specific keys provided
9+
const keysToSetup = productKeys || Object.keys(PRODUCT_TYPES);
10+
11+
console.log(`Setting up ${keysToSetup.length} test products...`);
12+
13+
for (const key of keysToSetup) {
14+
const productType = PRODUCT_TYPES[key];
15+
if (!productType) {
16+
console.warn(`Product type ${key} not found in PRODUCT_TYPES`);
17+
continue;
18+
}
19+
20+
await this.ensureProductExists(productType);
21+
}
22+
}
23+
24+
async ensureProductExists(productType: ProductType) {
25+
const existingProduct = await this.apiClient.getProductBySku(productType.sku);
26+
27+
if (!existingProduct) {
28+
console.log(`Creating product: ${productType.name} (${productType.sku})`);
29+
const productData = this.convertToWooCommerceProduct(productType);
30+
console.log('Product data:', productData);
31+
await this.apiClient.createProduct(productData);
32+
} else {
33+
console.log(`Product exists: ${productType.name} (${productType.sku})`);
34+
// Optionally update if needed
35+
const productData = this.convertToWooCommerceProduct(productType);
36+
//await this.apiClient.updateProduct(existingProduct.id, productData);
37+
}
38+
}
39+
private convertToWooCommerceProduct(productType: ProductType) {
40+
const baseProduct = {
41+
name: productType.name,
42+
sku: productType.sku,
43+
regular_price: productType.price.toString(),
44+
type: productType.woocommerce?.type || 'simple',
45+
status: productType.woocommerce?.status || 'publish',
46+
catalog_visibility: productType.woocommerce?.catalog_visibility || 'visible',
47+
description: productType.woocommerce?.description || `Test product: ${productType.name}`,
48+
short_description: productType.woocommerce?.short_description || `Test product for automated testing`,
49+
};
50+
51+
// Add subscription-specific data
52+
if (productType.isSubscription && productType.woocommerce?.meta_data) {
53+
return {
54+
...baseProduct,
55+
meta_data: productType.woocommerce.meta_data
56+
};
57+
}
58+
59+
// Add variable product data
60+
if (productType.woocommerce?.type === 'variable' && productType.woocommerce.attributes) {
61+
return {
62+
...baseProduct,
63+
attributes: productType.woocommerce.attributes
64+
};
65+
}
66+
67+
return baseProduct;
68+
}
69+
async setupProductsByType(type: 'simple' | 'variable' | 'subscription') {
70+
const productKeys = Object.keys(PRODUCT_TYPES).filter(key => {
71+
const product = PRODUCT_TYPES[key];
72+
if (type === 'subscription') return product.isSubscription;
73+
if (type === 'variable') return product.woocommerce?.type === 'variable';
74+
if (type === 'simple') return product.woocommerce?.type === 'simple' && !product.isSubscription;
75+
return false;
76+
});
77+
78+
await this.setupTestProducts(productKeys);
79+
}
80+
81+
// Method to setup subscription products for specific plugin
82+
async setupSubscriptionProducts(plugin?: 'woocommerce' | 'yith') {
83+
const productKeys = Object.keys(PRODUCT_TYPES).filter(key => {
84+
const product = PRODUCT_TYPES[key];
85+
return product.isSubscription && (!plugin || product.subscriptionPlugin === plugin);
86+
});
87+
88+
await this.setupTestProducts(productKeys);
89+
}
90+
91+
async setupTestPages() {
92+
const requiredPages = [
93+
{
94+
slug: 'checkout-classic',
95+
title: 'Classic Checkout',
96+
content: '[woocommerce_checkout]',
97+
template: 'page'
98+
},
99+
{
100+
slug: 'checkout-block',
101+
title: 'Block Checkout',
102+
content: '<!-- wp:woocommerce/checkout --><div class="wp-block-woocommerce-checkout"></div><!-- /wp:woocommerce/checkout -->',
103+
template: 'page'
104+
}
105+
];
106+
107+
for (const pageData of requiredPages) {
108+
await this.ensurePageExists(pageData);
109+
}
110+
}
111+
112+
async ensurePageExists(pageData: any) {
113+
const existingPage = await this.apiClient.getPageBySlug(pageData.slug);
114+
115+
if (!existingPage) {
116+
console.log(`Creating page: ${pageData.title}`);
117+
await this.apiClient.createPage(pageData);
118+
} else {
119+
console.log(`Page exists: ${pageData.title}`);
120+
}
121+
}
122+
123+
async setupMoneiPaymentMethods() {
124+
// Ensure MONEI settings are configured
125+
await this.apiClient.updateOption('woocommerce_monei_settings', {
126+
enabled: 'yes',
127+
apikey: process.env.MONEI_TEST_API_KEY,
128+
accountid: process.env.MONEI_TEST_ACCOUNT_ID,
129+
testmode: 'yes'
130+
});
131+
132+
// Enable specific payment methods
133+
const paymentMethods = ['monei_bizum', 'monei_paypal', 'monei_multibanco'];
134+
for (const method of paymentMethods) {
135+
await this.apiClient.updateOption(`woocommerce_${method}_settings`, {
136+
enabled: 'yes'
137+
});
138+
}
139+
}
140+
}

0 commit comments

Comments
 (0)