// DripOffers paid-per-click syndication, driven against the REAL bridge on dripoffers.com. // // Creates a paused test campaign, reads its delivery back, pauses/resumes it, proves a retry // cannot double-book, then deletes it. Nothing is left behind and nothing is ever activated, // so no publisher is ever paid for a test click. // // DRIPOFFERS_BRIDGE_URL=... DRIPOFFERS_BRIDGE_KEY=... node qa/dripoffers-bridge.mjs import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); const drip = require('../dripoffers.js'); const ok = [], bad = []; const t = (n, c, extra) => { (c ? ok : bad).push(n + (c || !extra ? '' : ' -> ' + extra)); }; // ---- pure logic first: these run with or without a configured bridge ------ const tiers = { t1: new Set(['US', 'CA', 'GB']), t2: new Set(['BR', 'PL']) }; t('no targeting means worldwide', drip.countriesFor('', tiers) === '*', drip.countriesFor('', tiers)); t('all three tiers collapse to worldwide', drip.countriesFor('1,2,3', tiers) === '*', drip.countriesFor('1,2,3', tiers)); t('tier 1 becomes a country list', drip.countriesFor('1', tiers) === 'US,CA,GB', drip.countriesFor('1', tiers)); t('tier 1+2 merges both lists', drip.countriesFor('1,2', tiers) === 'US,CA,GB,BR,PL', drip.countriesFor('1,2', tiers)); // tier 3 is "everywhere the others are not" — an inclusion list cannot say that, and sending it // worldwide would deliver the Tier 1 traffic its owner deliberately excluded t('tier 3 alone is skipped, not silently widened', drip.countriesFor('3', tiers) === null, String(drip.countriesFor('3', tiers))); t('credits convert to clicks one for one', drip.clicksFor(2000) === 2000, String(drip.clicksFor(2000))); t('one campaign cannot swallow the platform', drip.clicksFor(500000) === drip.MAX_CLICKS, String(drip.clicksFor(500000))); // the offerwall title a stranger actually reads (the platform's floor is 5 characters) const T = (c, u) => drip.titleFor(c, u || 'https://www.mailer.gold/x'); t('the ad headline wins over the internal label', T({ title: 'Get paid instantly', name: 'MG' }) === 'Get paid instantly', String(T({ title: 'Get paid instantly', name: 'MG' }))); t('a usable label is used as-is', T({ name: 'Branded Voice' }) === 'Branded Voice', String(T({ name: 'Branded Voice' }))); t('a two-letter label is qualified, not dropped', T({ name: 'MG' }) === 'MG (mailer.gold)', String(T({ name: 'MG' }))); t('no label at all falls back to the destination', T({}) === 'mailer.gold', String(T({}))); t('nothing usable returns null rather than a made-up title', T({}, 'not a url') === null, String(T({}, 'not a url'))); t('a click format is accepted', drip.kindOk('banner') && drip.kindOk('visits') && drip.kindOk('text')); t('video and solo are not click formats', !drip.kindOk('video') && !drip.kindOk('solo') && !drip.kindOk('featured')); if (!drip.enabled()) { console.log('PASS ' + ok.length + ' (pure logic only)'); for (const b of bad) console.log('FAIL ' + b); console.log('SKIP: DRIPOFFERS_BRIDGE_URL / _KEY not set — live bridge checks not run'); process.exit(bad.length ? 1 : 0); } // ---- live bridge --------------------------------------------------------- const ID = 999000 + Math.floor(Math.random() * 900); const camp = { id: ID, name: 'QA bridge campaign', title: 'A test offer that is never activated', targetUrl: 'https://instantadpay.com/', budget: 12000, spent: 0, accrued: 0, type: 'banner' }; // a campaign below the credit floor is skipped quietly rather than taking a listing const small = await drip.push({ ...camp, id: ID + 1, budget: 200 }, { paused: true, tiers }); t('a campaign under the credit floor is not syndicated', small === null, JSON.stringify(small)); // a format that is not a click offer never goes out const wrongKind = await drip.push({ ...camp, id: ID + 2, type: 'video' }, { paused: true, tiers }); t('a video campaign is not syndicated as a click offer', wrongKind === null, JSON.stringify(wrongKind)); // the real push const r = await drip.push(camp, { paused: true, tiers }); t('campaign syndicated', !!(r && r.campaign_id), JSON.stringify(r)); t('clicks are capped at the per-campaign ceiling', r && r.clicks_booked === drip.MAX_CLICKS, r && String(r.clicks_booked)); t('untargeted campaign goes worldwide', r && r.countries === '*', r && String(r.countries)); t('created paused, so no publisher is paid by the test', r && r.status === 0, r && String(r.status)); t('the funding account was actually debited', r && r.charged === true, r && String(r.charged)); // idempotency: the guard that stops a retry double-booking const again = await drip.push(camp, { paused: true, tiers }); t('a retry returns the SAME campaign, never a second', again && again.campaign_id === r.campaign_id && again.duplicate === true, JSON.stringify(again)); // delivery is counted from the click ledger, never derived from remaining_visits const st = await drip.readServed(ID); t('delivery reads back from the platform', !!(st && st.ok), JSON.stringify(st).slice(0, 140)); t('ordered clicks match what was booked', st && st.ordered_clicks === drip.MAX_CLICKS, st && String(st.ordered_clicks)); t('delivered starts at zero and is a counted figure', st && st.delivered_clicks === 0, st && String(st.delivered_clicks)); // pause / resume mirror — and the reason this matters: a pause must NOT read back as delivered await drip.resume(ID); let s2 = await drip.readServed(ID); t('resume activates it', s2 && s2.status === 1, s2 && String(s2.status)); await drip.pause(ID); s2 = await drip.readServed(ID); t('pause deactivates it', s2 && s2.status === 0, s2 && String(s2.status)); t('pausing does not fake delivery', s2 && s2.delivered_clicks === 0 && s2.remaining_visits === drip.MAX_CLICKS, s2 && (s2.delivered_clicks + '/' + s2.remaining_visits)); // cleanup must actually work, or tests litter a production platform const del = await drip.remove(ID); t('the test campaign is deleted', !!(del && del.ok), JSON.stringify(del)); const gone = await drip.readServed(ID); t('and it is really gone', gone === null, JSON.stringify(gone)); // an unknown campaign reads as null rather than throwing const none = await drip.readServed(ID + 12345); t('an unknown campaign reads as null', none === null, JSON.stringify(none)); console.log('PASS ' + ok.length); for (const b of bad) console.log('FAIL ' + b); process.exit(bad.length ? 1 : 0);