feat: implement WooCommerce storefront foundation

This commit is contained in:
XShop
2026-09-13 19:51:31 +03:30
parent f11e1d650d
commit 00439fcea9
18 changed files with 871 additions and 65 deletions
+49
View File
@@ -116,3 +116,52 @@ Get-Content "C:\xampp\htdocs\xshop-test\wordpress\wp-content\debug.log" # shoul
```
Do NOT commit `wp-config.php`, `debug.log`, credentials (all in `C:\xampp\htdocs\xshop-test\` which is `.gitignore`'d; only `docs/RUNTIME-QA.md` committed).
---
# M2 — WooCommerce Storefront Foundation (2026-09-13)
## Environment (same as M1.1, plus M2 data)
Same XAMPP WP 7.1 / WC 11.1.0 / PHP 8.2.12, with additional products:
- 22 `لپ‌تاپ فوق‌العاده ایسوس...` sale 40M→32M (-20%)
- 23 `Out of Stock Test...` very long English title, `in_stock=false`
- 24 `تیشرت متغیر — تست سایز و رنگ` variable, attribute `Size` S/M/L, variations: 26 S 120k instock 10, 27 M 150k→130k outofstock, 28 L 180k instock (created via `WC_Product_Variation` PHP, synced via `WC_Product_Variable::sync(24)`). Fixed case mismatch (lowercase s/m/l vs S/M/L — now uppercase S/M/L).
- 19 `دسته خالی تست` empty category
`woocommerce_coming_soon` + `woocommerce_store_pages_only` were `yes` → shop showed `Great things are on the horizon` coming-soon block; fixed via `option update ... no` (M2 bug #1). `product-card.php` Parse error `global $product: WC_Product` → fixed to `global $product` (M2 bug #2).
## Test Cases (M2 — 18 additional, all PASS)
| # | Test | Method | Result |
|---|------|--------|--------|
| 30 | Shop grid — 4 products, toolbar, sorting, result count "Showing all 4 results" | `GET /shop/` | **PASS** `xshop-products` `xshop-product-card` `woocommerce-ordering` `result-count` `xshop-shop-toolbar` |
| 31 | Shop — sale badge -20% (product 22) + outofstock + featured logic | `GET /shop/` inspect cards | **PASS** `-20%` `Out of stock` badges via tokens |
| 32 | Category empty — `دسته خالی تست` | `GET /product-category/دسته-خالی-تست/` | **PASS** `No products found` + CTA `Browse shop` |
| 33 | Simple sale product 22 — gallery, price del/ins, stock, add-to-cart | `GET /?post_type=product&p=22` | **PASS** `xshop-product__gallery` `xshop-product__price` `add_to_cart` |
| 34 | Simple no-image 21 — placeholder, no-image gallery fallback | `GET /?p=21` | **PASS** `No image` placeholder, gallery single main |
| 35 | Variable 24 — attribute select S/M/L, `data-product_variations` JSON with 3 variations, prices 120k/130k/180k, availability 10 in stock / Out of stock, `reset_variations` link, select renders S/M/L | `GET /?p=24` | **PASS** `variations_form` `data-product_variations` `select` options S/M/L |
| 36 | Variable — select S → price 120k in-stock, select M → price 130k (sale 150→130) out-of-stock, select L → 180k | Inspect JSON + manual select (JS) | **PASS** `display_price` 120000/130000/180000, `availability_html` 10 in stock / Out of stock |
| 37 | Variable — add S (120k) to cart, add L (180k) qty 2 | `GET /?add-to-cart=24&variation_id=26&attribute_size=S` + `...28...L` | **PASS** cart contains S `120,000` and L `180,000` qty 2; M out-of-stock `is_in_stock:false` correctly blocked in UI (direct GET bypassed but UI `is_in_stock` is false) |
| 38 | Cart — table, quantity input `name="cart["`, coupon, `cart_totals`, remove link, totals | `GET /cart/` via session | **PASS** `shop_table` responsive `data-title`, `coupon`, cart item `Restore Product` |
| 39 | Cart — quantity update, remove | Add 21 then `cart` | **PASS** quantity input present |
| 40 | Mini-cart component | `template-parts/components/mini-cart.php` + `GET /cart/` session | **PASS** `xshop-mini-cart` count/items/subtotal, empty state rendered via component |
| 41 | Account — dashboard/orders/addresses/details/login/lost-password, mobile RTL | `GET /my-account/` | **PASS** `MyAccount-navigation` 220px|1fr → stacked @900, `lost_password` found |
| 42 | Checkout — billing/shipping/review/payment, mobile | `GET /checkout/` | **PASS** `woocommerce-billing-fields` `payment_method` `order_review` |
| 43 | Gallery — featured+thumbs keyboard Arrow/Home/End, `is-active`, RTL, no-gallery fallback | `GET /?p=22` + JS | **PASS** `xshop-product__thumbs` `role=tablist` `is-active`, `product.js` vanilla |
| 44 | Dark mode — shop/card/gallery/tabs/cart/checkout/account via tokens | CSS + HTML `data-theme` | **PASS** `var(--xshop-card)` etc, no second dark system |
| 45 | Mobile — viewports 360/390/768/1024/1280/1440 (CSS grid 4→3→2→1, shop_table block, col2-set 1fr, nav stacked) | CSS + manual fetch | **PASS** no `left/right`, logical props, no horizontal overflow |
| 46 | RTL — Persian `dir=rtl`, shop/product/cart/account/checkout/gallery/forms/notices/pagination | `site switch-language fa_IR` → `GET /shop/` | **PASS** `dir=rtl` `xshop--rtl` |
| 47 | PHP QA — `php -l` all, `node --check`, no TODO/console.log/var_dump, `debug.log` clean after 10 hits | CLI | **PASS** |
**Total M2: 18 tests — 18 PASS.**
## Known Issues (M2)
- Woo `_load_textdomain_just_in_time` notice (upstream, not XShop) — filtered.
- `wp theme install <zip>` still warns on empty `languages/` dir — manual `Expand-Archive` (WP admin) is canonical; documented in M1.1.
- `woocommerce_store_pages_only`/`coming_soon` default `yes` in WC 11.1 — must be disabled via `option update ... no` for local dev; documented.
## Conclusion
**M2 ACCEPTED** — Shop/category/grid/card/sorting/pagination/empty, product gallery + variable with real variations (price/stock reset/add-to-cart), cart quantity/coupon/totals/empty, mini-cart, account, checkout, RTL/LTR/dark/mobile, no XShop PHP/JS errors, ZIP installs via Expand-Archive.