Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
9fc31ef
Add QIT development tools and E2E testing setup
mgascam Sep 16, 2025
84f29c7
Remove QIT development tools and simplify E2E test setup for WooComme…
mgascam Sep 17, 2025
0da9163
Refactor QIT development tools for WooPayments: update comments, enha…
mgascam Sep 16, 2025
002936a
Add E2E test credentials and enhance WooPayments setup scripts
mgascam Sep 17, 2025
d653017
Add GitHub Actions workflow for QIT E2E tests
mgascam Sep 17, 2025
210ca92
Enhance security for token handling in CI workflow
mgascam Sep 17, 2025
c40f524
Use QIT E2E secrets
mgascam Sep 18, 2025
579c5bc
Add changelog
mgascam Sep 18, 2025
2574ae6
Remove wrongly committed files
mgascam Sep 18, 2025
34e406c
Amend comment
mgascam Sep 18, 2025
17e063f
Whitelist subscriptions core package to fix the build error
mgascam Sep 18, 2025
774e9ab
Add a step to install QIT
mgascam Sep 18, 2025
63d2ba3
Refactor QIT CLI installation and update test command syntax in E2E s…
mgascam Sep 18, 2025
5ecc2cd
Fix qit command error
mgascam Sep 18, 2025
8d06343
Refactor QIT E2E test execution and streamline environment variable h…
mgascam Sep 18, 2025
8ad9d73
Update QIT E2E test command to use correct paths and environment vari…
mgascam Sep 18, 2025
903e8b8
Remove upload step
mgascam Sep 18, 2025
2768df8
Restore composer files
mgascam Sep 22, 2025
2ce58fc
Revert changes to composer.*
mgascam Sep 22, 2025
26c7d89
Upgrade qit cli package
mgascam Sep 22, 2025
be27564
Migrate basic.spec.ts
mgascam Sep 29, 2025
248f7a5
Migrate shopper-checkout-purchase with ctp disabled
mgascam Sep 29, 2025
2929833
Migrate shopper-checkout-purchase with card testing protection enabled
mgascam Sep 29, 2025
e5ec5a6
Migrate shopper-wc-blocks-checkout-purchase.spec.ts
mgascam Sep 29, 2025
4fde4e5
Migrate shopper-checkout-failures.spec.ts
mgascam Sep 29, 2025
a5a8f94
Migrate shopper-wc-blocks-checkout-failures
mgascam Sep 29, 2025
50a7be3
Migrate shopper-checkout-save-card-and-purchase spec
mgascam Sep 29, 2025
9b860e1
Add auth fixture and use it in basic spec
mgascam Sep 30, 2025
0366c3b
Use auth fixture in shopper checkout spec
mgascam Sep 30, 2025
0ae59be
Use auth fixture in blocks purchase
mgascam Sep 30, 2025
9c350e1
Use auth fixture in the shopper-checkout-failures.spec
mgascam Sep 30, 2025
ad957c5
Use auth fixture in shopper-wc-blocks-checkout-failures
mgascam Sep 30, 2025
f576384
Use auth fixture in shopper-checkout-save-card-and-purchase spec
mgascam Sep 30, 2025
192e4de
Migrate shopper-wc-blocks-saved-card-checkout-and-usage spec
mgascam Sep 30, 2025
f0e5b6e
Migrate shopper-pay-for-order. spec
mgascam Sep 30, 2025
8fd7a7a
Migrate shopper-checkout-purchase-site-editor spec
mgascam Sep 30, 2025
c4a3993
Migrate shopper-checkout-cart-coupon spec
mgascam Sep 30, 2025
284980f
Migrate shopper-myaccount-payment-methods-add-fail spec
mgascam Sep 30, 2025
a4a00bf
Migrate shopper-checkout-purchase-with-upe-methods spec
mgascam Sep 30, 2025
173e2f3
MIgrate klarna-checkout-purchase spec
mgascam Sep 30, 2025
3696293
Migrate alipay-checkout-purchase spec
mgascam Sep 30, 2025
6875146
Migrate shopper-bnpls-checkout spec
mgascam Sep 30, 2025
8fd367d
Migrate multi-currency-checkout spec
mgascam Sep 30, 2025
d591410
Migrate shopper-multi-currency-widget spec
mgascam Sep 30, 2025
55554ef
Increase timeout for beforeAll in shopper multi-currency widget spec
mgascam Sep 30, 2025
e48c0d5
WIP: Migrate shopper-myaccount-saved-cards.spec.ts
mgascam Sep 30, 2025
dcae2fd
MIgrate shopper-myaccount-saved-cards spec
mgascam Sep 30, 2025
d0c4d99
Support running single spec
mgascam Oct 1, 2025
a7c530b
Add wp-cli-stubs dependency and update psalm-loader for static analysis
mgascam Sep 24, 2025
ec6bf86
Refine plugin row locator to exclude update rows in activation test
mgascam Oct 1, 2025
080a64e
Rename misspelled vars on env file
mgascam Oct 1, 2025
0d0cae7
Refactor E2E runner script to improve path handling and default spec …
mgascam Oct 6, 2025
869dac9
Add shopper tags to E2E tests for improved categorization
mgascam Oct 6, 2025
71a7d8c
Refactor E2E tests to remove conditional describe and use consistent …
mgascam Oct 7, 2025
24a8c67
WIP refactor cli commands
mgascam Oct 7, 2025
cf15684
Refactor QIT Jetpack connection setup and status scripts
mgascam Oct 7, 2025
5e6a71c
Remove wp-cli-stubs dependency from composer.json and psalm-loader.php
mgascam Oct 7, 2025
934a371
Update QIT bootstrap volume path in configuration
mgascam Oct 7, 2025
57b077c
Remove workflow file - will be added in final PR
mgascam Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 140 additions & 23 deletions tests/qit/e2e-runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ if [[ -f "$QIT_ROOT/config/local.env" ]]; then
. "$QIT_ROOT/config/local.env"
fi

# If QIT_BINARY is not set, default to ./vendor/bin/qit
QIT_BINARY=${QIT_BINARY:-./vendor/bin/qit}

echo "Running E2E tests..."

# Change to project root directory to build plugin
Expand Down Expand Up @@ -81,18 +78,13 @@ else
echo "$CURRENT_SIG" > "$BUILD_HASH_FILE"
fi

# Change to QIT directory so qit.yml is automatically found
cd "$QIT_ROOT"

# Convert relative QIT_BINARY path to absolute for directory change compatibility
if [[ "$QIT_BINARY" = ./* ]]; then
QIT_CMD="$WCP_ROOT/$QIT_BINARY"
else
QIT_CMD="$QIT_BINARY"
fi
# QIT CLI is installed via composer as a dev dependency
QIT_CMD="./vendor/bin/qit"

# Pass basic Jetpack environment variables
# Build environment arguments for local development
env_args=()

# Add Jetpack environment variables if available
if [[ -n "${E2E_JP_SITE_ID:-}" ]]; then
env_args+=( --env "E2E_JP_SITE_ID=${E2E_JP_SITE_ID}" )
fi
Expand All @@ -103,15 +95,140 @@ if [[ -n "${E2E_JP_USER_TOKEN:-}" ]]; then
env_args+=( --env "E2E_JP_USER_TOKEN=${E2E_JP_USER_TOKEN}" )
fi

# Run our QIT E2E tests (qit.yml automatically loaded from current directory)
echo "Running QIT E2E tests with Jetpack functionality..."
if [ ${#env_args[@]} -eq 0 ]; then
"$QIT_CMD" run:e2e woocommerce-payments ./e2e \
--source "$WCP_ROOT/woocommerce-payments.zip"
else
"$QIT_CMD" run:e2e woocommerce-payments ./e2e \
--source "$WCP_ROOT/woocommerce-payments.zip" \
"${env_args[@]}"
# Determine the desired spec target. Defaults to the whole suite unless
# overridden via the first positional argument (if it is not an option) or
# the WCP_E2E_SPEC environment variable.
SPEC_TARGET=${WCP_E2E_SPEC:-tests/qit/e2e}
TEST_TAG=""
declare -a FORWARDED_ARGS=()

# Parse arguments to extract spec target and optional --tag
while [[ $# -gt 0 ]]; do
case "$1" in
--tag=*)
TEST_TAG="${1#*=}"
shift
;;
--tag)
TEST_TAG="$2"
shift 2
;;
--*)
FORWARDED_ARGS+=("$1")
shift
;;
*)
# First non-option argument is the spec target
if [[ -z "${SPEC_TARGET_SET:-}" ]]; then
SPEC_TARGET="$1"
SPEC_TARGET_SET=1
fi
shift
;;
esac
done

# Normalize paths to work from project root
# Handle various input formats and convert them to paths QIT can use
normalize_path() {
local input="$1"

# If path exists as-is from project root, use it
if [[ -e "$input" ]]; then
echo "$input"
return 0
fi

# Try prefixing with tests/qit/
if [[ -e "tests/qit/$input" ]]; then
echo "tests/qit/$input"
return 0
fi

# Try prefixing with tests/qit/e2e/
if [[ -e "tests/qit/e2e/$input" ]]; then
echo "tests/qit/e2e/$input"
return 0
fi

# If it looks like it starts with e2e/, try tests/qit/e2e/
if [[ "$input" == e2e/* ]] && [[ -e "tests/qit/$input" ]]; then
echo "tests/qit/$input"
return 0
fi

# If just a filename (no path separators), search for it in e2e directory
if [[ "$input" != */* ]]; then
local found
found=$(find tests/qit/e2e -name "$input" -type f | head -1)
if [[ -n "$found" ]]; then
echo "$found"
return 0
fi
fi

# Path not found
echo "$input"
return 1
}

SPEC_TARGET=$(normalize_path "$SPEC_TARGET") || {
echo "Unable to locate spec target: $SPEC_TARGET" >&2
exit 1
}

# Determine if we're running a specific file or directory
PW_OPTIONS=""
if [[ -f "$SPEC_TARGET" ]]; then
# Running a specific spec file - pass it to Playwright via --pw_options
# QIT needs the e2e directory, Playwright needs the specific file
E2E_ROOT="tests/qit/e2e"

# Ensure spec is within e2e directory
case "$SPEC_TARGET" in
"$E2E_ROOT"/*)
# Extract the path relative to e2e directory
PW_OPTIONS="${SPEC_TARGET#$E2E_ROOT/}"
SPEC_TARGET="$E2E_ROOT"
;;
*)
echo "Specified spec file must reside within tests/qit/e2e" >&2
exit 1
;;
esac
fi

echo "QIT E2E foundation tests completed!"
# Build the final command to execute QIT.
echo "Running QIT E2E tests for local development (target: ${SPEC_TARGET}${TEST_TAG:+ | tag: ${TEST_TAG}}${PW_OPTIONS:+ | pw_options: ${PW_OPTIONS}})..."

QIT_CMD_ARGS=(
"$QIT_CMD" run:e2e woocommerce-payments "$SPEC_TARGET"
--config "$QIT_ROOT/qit.yml"
--source "$WCP_ROOT/woocommerce-payments.zip"
"${env_args[@]}"
)

# Add tag filter if specified
if [[ -n "$TEST_TAG" ]]; then
QIT_CMD_ARGS+=( --pw_test_tag="${TEST_TAG}" )
fi

if [[ -n "$PW_OPTIONS" ]]; then
if (( ${#FORWARDED_ARGS[@]} )); then
for arg in "${FORWARDED_ARGS[@]}"; do
if [[ "$arg" == --pw_options || "$arg" == --pw_options=* ]]; then
echo "Do not combine a spec file with manual --pw_options overrides." >&2
exit 1
fi
done
fi
QIT_CMD_ARGS+=( --pw_options "$PW_OPTIONS" )
fi

if (( ${#FORWARDED_ARGS[@]} )); then
QIT_CMD_ARGS+=( "${FORWARDED_ARGS[@]}" )
fi

"${QIT_CMD_ARGS[@]}"

echo "QIT E2E tests completed!"
28 changes: 11 additions & 17 deletions tests/qit/e2e/basic.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ test( 'Load home page', async ( { page } ) => {
} );

/**
* Test admin authentication and WooPayments plugin access
* Test WooCommerce Payments onboarding flow access
* Since we're running in development mode without Jetpack connection,
* we expect to always land on the onboarding flow.
*/
test( 'Access WooPayments as admin', async ( { page } ) => {
test( 'Access WooCommerce Payments onboarding as admin', async ( { page } ) => {
// Use QIT helper to login as admin
await qit.loginAsAdmin( page );

// Navigate to WooPayments settings
// Navigate to WooCommerce Payments settings
await page.goto(
'/wp-admin/admin.php?page=wc-admin&path=%2Fpayments%2Foverview'
);
Expand All @@ -31,21 +33,13 @@ test( 'Access WooPayments as admin', async ( { page } ) => {
page.locator( 'h1:not(.screen-reader-text)' ).first()
).toContainText( /Settings|Payments|Overview/, { timeout: 15000 } );

// Check that we can successfully load the WooPayments interface
// Either we get the overview (if fully connected) OR the onboarding.
const isOnboarding = page.url().includes( 'onboarding' );
const isOverview = page.url().includes( 'payments' );
// In development mode without Jetpack connection, we should be on onboarding
expect( page.url() ).toContain( 'onboarding' );

// We should be on either the onboarding or overview page (both indicate success)
expect( isOnboarding || isOverview ).toBe( true );

// If we're on onboarding, it should be functional (not errored)
if ( isOnboarding ) {
// The onboarding page should load without errors
await expect( page.locator( 'body' ) ).not.toHaveText(
/500|404|Fatal error/
);
}
// The onboarding page should load without errors
await expect( page.locator( 'body' ) ).not.toHaveText(
/500|404|Fatal error/
);
} );

/**
Expand Down
108 changes: 92 additions & 16 deletions tests/qit/e2e/bootstrap/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,90 @@ echo "Setting up WooPayments for E2E testing..."
# Ensure environment is marked as development so dev-only CLI commands are available
wp config set WP_ENVIRONMENT_TYPE development --quiet 2>/dev/null || true

# Create a test product for payment testing
PRODUCT_ID=$(wp post create \
--post_title="Test Product for Payments" \
--post_content="A simple test product for QIT payment testing" \
--post_status=publish \
--post_type=product \
--porcelain)

# Set product meta data properly
wp post meta update $PRODUCT_ID _price "10.00"
wp post meta update $PRODUCT_ID _regular_price "10.00"
wp post meta update $PRODUCT_ID _virtual "yes"
wp post meta update $PRODUCT_ID _manage_stock "no"

# Ensure WooCommerce checkout page exists and is properly configured
wp option update woocommerce_checkout_page_id $(wp post list --post_type=page --post_name=checkout --field=ID --format=ids)
echo "Installing WordPress importer for sample data..."
if ! wp plugin is-installed wordpress-importer >/dev/null 2>&1; then
wp plugin install wordpress-importer --activate
else
wp plugin activate wordpress-importer
fi

WC_SAMPLE_DATA_PATH=$(wp eval 'echo trailingslashit( WP_CONTENT_DIR ) . "plugins/woocommerce/sample-data/sample_products.xml";' 2>/dev/null)
if [ -z "$WC_SAMPLE_DATA_PATH" ]; then
echo "Unable to resolve WooCommerce sample data path; skipping import."
else
if [ -f "$WC_SAMPLE_DATA_PATH" ]; then
echo "Importing WooCommerce sample products from $WC_SAMPLE_DATA_PATH ..."
wp import "$WC_SAMPLE_DATA_PATH" --authors=skip
else
echo "Sample data file not found at $WC_SAMPLE_DATA_PATH; skipping import."
fi
fi

# Ensure WooCommerce core pages exist and capture IDs
echo "Ensuring WooCommerce core pages exist..."
wp wc --user=admin tool run install_pages >/dev/null 2>&1 || true

CHECKOUT_PAGE_ID=$(wp option get woocommerce_checkout_page_id)
CART_PAGE_ID=$(wp option get woocommerce_cart_page_id)

if [ -z "$CHECKOUT_PAGE_ID" ] || [ "$CHECKOUT_PAGE_ID" = "0" ]; then
CHECKOUT_PAGE_ID=$(wp post list --post_type=page --name=checkout --field=ID --format=ids)
fi

if [ -z "$CART_PAGE_ID" ] || [ "$CART_PAGE_ID" = "0" ]; then
CART_PAGE_ID=$(wp post list --post_type=page --name=cart --field=ID --format=ids)
fi

# Default to shortcode-based templates for classic checkout/cart flows
if [ -n "${CHECKOUT_PAGE_ID}" ] && [ -n "${CART_PAGE_ID}" ]; then
echo "Configuring classic checkout and cart pages..."

CHECKOUT_SHORTCODE="<!-- wp:shortcode -->[woocommerce_checkout]<!-- /wp:shortcode -->"
CART_SHORTCODE="<!-- wp:shortcode -->[woocommerce_cart]<!-- /wp:shortcode -->"

# Provision a dedicated WooCommerce Blocks checkout clone if it does not exist yet
CHECKOUT_WCB_PAGE_ID=$(wp post list --post_type=page --name=checkout-wcb --field=ID --format=ids)
if [ -z "$CHECKOUT_WCB_PAGE_ID" ]; then
echo "Creating WooCommerce Blocks checkout page..."
CHECKOUT_WCB_PAGE_ID=$(wp post create \
--from-post="$CHECKOUT_PAGE_ID" \
--post_type=page \
--post_title="Checkout WCB" \
--post_status=publish \
--post_name="checkout-wcb" \
--porcelain)
else
echo "WooCommerce Blocks checkout page already exists (ID: $CHECKOUT_WCB_PAGE_ID)"
fi

wp post update "$CART_PAGE_ID" --post_content="$CART_SHORTCODE"
wp post update "$CHECKOUT_PAGE_ID" --post_content="$CHECKOUT_SHORTCODE"
wp post meta update "$CHECKOUT_PAGE_ID" _wp_page_template "template-fullwidth.php" >/dev/null 2>&1 || true
if [ -n "$CHECKOUT_WCB_PAGE_ID" ]; then
wp post meta update "$CHECKOUT_WCB_PAGE_ID" _wp_page_template "template-fullwidth.php" >/dev/null 2>&1 || true
fi
fi

# Double check option points to the classic checkout page
if [ -n "$CHECKOUT_PAGE_ID" ]; then
wp option update woocommerce_checkout_page_id "$CHECKOUT_PAGE_ID"
fi

# Configure WooCommerce for testing
wp option update woocommerce_currency "USD"
wp option update woocommerce_enable_guest_checkout "yes"
wp option update woocommerce_force_ssl_checkout "no"
wp option set woocommerce_checkout_company_field "optional" --quiet 2>/dev/null || true
wp option set woocommerce_coming_soon "no" --quiet 2>/dev/null || true
wp option set woocommerce_store_pages_only "no" --quiet 2>/dev/null || true

# Ensure Storefront theme is active for consistent storefront markup
if ! wp theme is-installed storefront > /dev/null 2>&1; then
wp theme install storefront --force
fi
wp theme activate storefront



# Create a test customer
wp user create testcustomer [email protected] \
Expand Down Expand Up @@ -84,4 +147,17 @@ wp option set wcpaydev_proxy 0 --quiet 2>/dev/null || true
# Disable onboarding redirect for E2E testing
wp option set wcpay_should_redirect_to_onboarding 0 --quiet 2>/dev/null || true

echo "Dismissing fraud protection welcome tour in E2E tests"
wp option set wcpay_fraud_protection_welcome_tour_dismissed 1 --quiet 2>/dev/null || true

echo "Resetting coupons and creating standard free coupon"
wp post delete $(wp post list --post_type=shop_coupon --format=ids) --force --quiet 2>/dev/null || true
wp db query "DELETE FROM wp_postmeta WHERE post_id NOT IN (SELECT ID FROM wp_posts)" --skip-column-names 2>/dev/null || true
wp wc --user=admin shop_coupon create \
--code=free \
--amount=100 \
--discount_type=percent \
--individual_use=true \
--free_shipping=true

echo "WooPayments configuration completed"
Loading