diff --git a/src/chrome/src/agent/adapters.js b/src/chrome/src/agent/adapters.js index 37709fb37..59f74c74c 100644 --- a/src/chrome/src/agent/adapters.js +++ b/src/chrome/src/agent/adapters.js @@ -16437,6 +16437,20 @@ const ADAPTERS = [ - Use the on-page search ("Search for restaurants, cuisines, and dishes") and the left-rail sort/filters (Relevance / Fastest delivery / Distance / Top rated, "Ratings 4+") rather than guessing URL params.`, }, + // ─── Regional — Takealot (South Africa) ────────────────────────────── + { + name: 'takealot', + category: 'general', + matches: (url) => /^https?:\/\/(www\.)?takealot\.com\//.test(url), + notes: ` +- As of 2026-08, Takealot is a South African retailer and MARKETPLACE. Read the product page's "Sold by" value: third-party seller products use the same ordering flow, but seller identity, stock, and product details still belong to the selected offer. +- Delivery is South Africa-only. At checkout choose "Delivery" to an address or "Collect" from a Takealot Pickup Point; item mix, destination, and payment affect timing, and any delivery fee appears there. Treat the checkout date and fee as authoritative, not the product-page estimate. +- Pre-order products must be ordered individually: do not combine one with normal products or another pre-order variety. The release date can change, so report it as an estimate and re-check before payment. +- Digital products such as airtime, data, courses, gaming vouchers, and downloads are delivered immediately by email and cannot be cancelled. Obtain the user's explicit confirmation before completing payment for one. +- Checkout may show an optional R5 charity donation. Leave it unselected unless the user requested it, then review the Order Summary after any voucher or coupon and before completing payment. +- An added cart item is not a completed order. Success is the confirmation page with an order number and estimated delivery or collection date (also emailed); verify those before reporting that the order was placed.`, + }, + // ─── Regional — Digitec Galaxus (CH + EU: one in-house platform) ────── // galaxus.* (CH/DE/AT/FR/IT/BE/NL) and digitec.ch share product IDs, slugs, and // UI, so one adapter covers both. digitec.ch = the CH tech-only storefront. diff --git a/src/firefox/src/agent/adapters.js b/src/firefox/src/agent/adapters.js index 1027791f3..e1d31cb7e 100644 --- a/src/firefox/src/agent/adapters.js +++ b/src/firefox/src/agent/adapters.js @@ -16435,6 +16435,20 @@ const ADAPTERS = [ - Use the on-page search ("Search for restaurants, cuisines, and dishes") and the left-rail sort/filters (Relevance / Fastest delivery / Distance / Top rated, "Ratings 4+") rather than guessing URL params.`, }, + // ─── Regional — Takealot (South Africa) ────────────────────────────── + { + name: 'takealot', + category: 'general', + matches: (url) => /^https?:\/\/(www\.)?takealot\.com\//.test(url), + notes: ` +- As of 2026-08, Takealot is a South African retailer and MARKETPLACE. Read the product page's "Sold by" value: third-party seller products use the same ordering flow, but seller identity, stock, and product details still belong to the selected offer. +- Delivery is South Africa-only. At checkout choose "Delivery" to an address or "Collect" from a Takealot Pickup Point; item mix, destination, and payment affect timing, and any delivery fee appears there. Treat the checkout date and fee as authoritative, not the product-page estimate. +- Pre-order products must be ordered individually: do not combine one with normal products or another pre-order variety. The release date can change, so report it as an estimate and re-check before payment. +- Digital products such as airtime, data, courses, gaming vouchers, and downloads are delivered immediately by email and cannot be cancelled. Obtain the user's explicit confirmation before completing payment for one. +- Checkout may show an optional R5 charity donation. Leave it unselected unless the user requested it, then review the Order Summary after any voucher or coupon and before completing payment. +- An added cart item is not a completed order. Success is the confirmation page with an order number and estimated delivery or collection date (also emailed); verify those before reporting that the order was placed.`, + }, + // ─── Regional — Digitec Galaxus (CH + EU: one in-house platform) ────── // galaxus.* (CH/DE/AT/FR/IT/BE/NL) and digitec.ch share product IDs, slugs, and // UI, so one adapter covers both. digitec.ch = the CH tech-only storefront. diff --git a/test/run.js b/test/run.js index e4c741d72..ef9560cb8 100644 --- a/test/run.js +++ b/test/run.js @@ -2691,6 +2691,42 @@ test('matches foodpanda.pk and includes food-delivery guidance', () => { assert.notEqual(getActiveAdapterFx('https://www.foodpanda.com.bd/')?.name, 'foodpanda'); }); +test('matches Takealot shopping surfaces and includes South African checkout guidance', () => { + const trustedUrls = [ + 'https://takealot.com/', + 'https://www.takealot.com/all?qsearch=laptop', + 'https://www.takealot.com/example-product/PLID12345678', + 'https://www.takealot.com/cart', + ]; + for (const url of trustedUrls) { + assert.equal(getActiveAdapter(url)?.name, 'takealot'); + assert.equal(getActiveAdapterFx(url)?.name, 'takealot'); + } + + const rejectedUrls = [ + 'https://takealot.co.za/', + 'https://takealot.com.phishing.example/PLID12345678', + 'https://example.com/?next=https://www.takealot.com/PLID12345678', + ]; + for (const url of rejectedUrls) { + assert.notEqual(getActiveAdapter(url)?.name, 'takealot'); + assert.notEqual(getActiveAdapterFx(url)?.name, 'takealot'); + } + + const adapter = getActiveAdapter('https://www.takealot.com/example-product/PLID12345678'); + const firefoxAdapter = getActiveAdapterFx('https://www.takealot.com/cart'); + assert.match(adapter?.notes || '', /2026-08/); + assert.match(adapter?.notes || '', /MARKETPLACE/); + assert.match(adapter?.notes || '', /Sold by/); + assert.match(adapter?.notes || '', /Pickup Point/); + assert.match(adapter?.notes || '', /checkout/i); + assert.match(adapter?.notes || '', /pre-order/i); + assert.match(adapter?.notes || '', /digital/i); + assert.match(adapter?.notes || '', /R5/); + assert.match(adapter?.notes || '', /order number/i); + assert.equal(firefoxAdapter?.notes, adapter?.notes); +}); + test('matches galaxus + digitec and includes anti-bot fetch guidance', () => { assert.equal(getActiveAdapter('https://www.galaxus.ch/de/s1/product/x-123')?.name, 'galaxus'); assert.equal(getActiveAdapter('https://www.digitec.ch/de/s1/product/x-123')?.name, 'galaxus');