config.shop (SHOP_ENABLED, SHOP_PILOT_EMAILS, SHOP_UPLOAD_DIR, STRIPE_CONNECT_WEBHOOK_SECRET), config.shopSetup (299 € einmalig), Collection-IDs shopConfig/shopProducts/shopOrders/shopWiderrufe, services/shop/schalter.js, Katalogschluessel shopSetup in stripeBilling und stripe-products.mjs, services/shop/schema.js, scripts/shop-setup.mjs (--check), schemaKeys fuer die Test-Mocks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
164 lines
5.7 KiB
JavaScript
164 lines
5.7 KiB
JavaScript
import { test, beforeEach, afterEach } from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import path from 'node:path'
|
||
import { config } from '../server/config.js'
|
||
import { shopFuerKunde, shopModus } from '../server/services/shop/schalter.js'
|
||
|
||
const SHOP_ENV = [
|
||
'SHOP_ENABLED',
|
||
'SHOP_PILOT_EMAILS',
|
||
'SHOP_UPLOAD_DIR',
|
||
'STRIPE_CONNECT_WEBHOOK_SECRET',
|
||
'APPWRITE_COLLECTION_SHOP_CONFIG',
|
||
'APPWRITE_COLLECTION_SHOP_PRODUCTS',
|
||
'APPWRITE_COLLECTION_SHOP_ORDERS',
|
||
'APPWRITE_COLLECTION_SHOP_WIDERRUFE',
|
||
]
|
||
|
||
let original
|
||
beforeEach(() => {
|
||
original = { ...config.shop }
|
||
})
|
||
afterEach(() => {
|
||
Object.assign(config.shop, original)
|
||
})
|
||
|
||
/** Frische config.js-Instanz mit genau diesen Shop-Umgebungsvariablen (alle anderen entfernt). */
|
||
let freshCounter = 0
|
||
async function freshConfig(env = {}) {
|
||
const saved = Object.fromEntries(SHOP_ENV.map((key) => [key, process.env[key]]))
|
||
for (const key of SHOP_ENV) delete process.env[key]
|
||
Object.assign(process.env, env)
|
||
try {
|
||
freshCounter += 1
|
||
return (await import(`../server/config.js?shop-test=${freshCounter}`)).config
|
||
} finally {
|
||
for (const key of SHOP_ENV) {
|
||
if (saved[key] === undefined) delete process.env[key]
|
||
else process.env[key] = saved[key]
|
||
}
|
||
}
|
||
}
|
||
|
||
test('Konfiguration: Vorgaben ohne Umgebungsvariablen', async () => {
|
||
const fresh = await freshConfig()
|
||
assert.deepEqual(fresh.shop, {
|
||
mode: 'off',
|
||
pilotEmails: [],
|
||
fassung: '2026-10-05',
|
||
uploadDir: path.join(process.cwd(), 'upload-data', 'shop'),
|
||
connectWebhookSecret: '',
|
||
bestellAblaufMinuten: 30,
|
||
maxArtikel: 500,
|
||
maxBilder: 4,
|
||
maxVarianten: 30,
|
||
anonymisierenJahre: 3,
|
||
loeschTageNachAbschalten: 90,
|
||
unbezahltLoeschTage: 30,
|
||
})
|
||
assert.equal(fresh.collections.shopConfig, 'shopConfig')
|
||
assert.equal(fresh.collections.shopProducts, 'shopProducts')
|
||
assert.equal(fresh.collections.shopOrders, 'shopOrders')
|
||
assert.equal(fresh.collections.shopWiderrufe, 'shopWiderrufe')
|
||
})
|
||
|
||
test('Konfiguration: Umgebungsvariablen werden gelesen und bereinigt', async () => {
|
||
const fresh = await freshConfig({
|
||
SHOP_ENABLED: ' Pilot ',
|
||
SHOP_PILOT_EMAILS: ' Kenso.Gri@Gmail.com, ,justin@webklar.com ',
|
||
SHOP_UPLOAD_DIR: '/tmp/shop-bilder',
|
||
STRIPE_CONNECT_WEBHOOK_SECRET: 'whsec_connect',
|
||
APPWRITE_COLLECTION_SHOP_CONFIG: 'sConfig',
|
||
APPWRITE_COLLECTION_SHOP_PRODUCTS: 'sProducts',
|
||
APPWRITE_COLLECTION_SHOP_ORDERS: 'sOrders',
|
||
APPWRITE_COLLECTION_SHOP_WIDERRUFE: 'sWiderrufe',
|
||
})
|
||
assert.equal(fresh.shop.mode, 'pilot')
|
||
assert.deepEqual(fresh.shop.pilotEmails, ['kenso.gri@gmail.com', 'justin@webklar.com'])
|
||
assert.equal(fresh.shop.uploadDir, '/tmp/shop-bilder')
|
||
assert.equal(fresh.shop.connectWebhookSecret, 'whsec_connect')
|
||
assert.deepEqual(
|
||
[fresh.collections.shopConfig, fresh.collections.shopProducts, fresh.collections.shopOrders, fresh.collections.shopWiderrufe],
|
||
['sConfig', 'sProducts', 'sOrders', 'sWiderrufe'],
|
||
)
|
||
})
|
||
|
||
test('Konfiguration: leerer oder unbekannter Schalter ist off', async () => {
|
||
for (const value of ['', ' ', 'banane', 'true', '1', 'ON ']) {
|
||
const fresh = await freshConfig({ SHOP_ENABLED: value })
|
||
assert.equal(fresh.shop.mode, value.trim().toLowerCase() === 'on' ? 'on' : 'off', `SHOP_ENABLED=${JSON.stringify(value)}`)
|
||
}
|
||
})
|
||
|
||
test('Konfiguration: Katalogeintrag shopSetup', () => {
|
||
assert.deepEqual(config.shopSetup, {
|
||
key: 'shopSetup',
|
||
name: 'Webshop – Einrichtung',
|
||
amountCents: 29900,
|
||
lookupKey: 'webklar_shop_einrichtung_29900',
|
||
oneTime: true,
|
||
priceNickname: 'Webshop-Einrichtung 299 €',
|
||
})
|
||
})
|
||
|
||
test('shopModus: leer und unbekannt sind off, pilot und on bleiben', () => {
|
||
for (const value of [undefined, null, '', 'banane', 'PILOT', 'true']) {
|
||
config.shop.mode = value
|
||
assert.equal(shopModus(), 'off', `mode=${JSON.stringify(value)}`)
|
||
}
|
||
config.shop.mode = 'pilot'
|
||
assert.equal(shopModus(), 'pilot')
|
||
config.shop.mode = 'on'
|
||
assert.equal(shopModus(), 'on')
|
||
})
|
||
|
||
test('shopModus: Aenderung von config.shop.mode wirkt sofort', () => {
|
||
config.shop.mode = 'off'
|
||
assert.equal(shopModus(), 'off')
|
||
config.shop.mode = 'on'
|
||
assert.equal(shopModus(), 'on')
|
||
config.shop.mode = 'off'
|
||
assert.equal(shopModus(), 'off')
|
||
})
|
||
|
||
test('shopFuerKunde: off sperrt alle, auch mit Stern in der Liste', () => {
|
||
config.shop.mode = 'off'
|
||
config.shop.pilotEmails = ['*', 'kenso.gri@gmail.com']
|
||
assert.equal(shopFuerKunde('kenso.gri@gmail.com'), false)
|
||
assert.equal(shopFuerKunde('jemand@example.com'), false)
|
||
})
|
||
|
||
test('shopFuerKunde: pilot erlaubt nur Adressen der Liste, Schreibweise egal', () => {
|
||
config.shop.mode = 'pilot'
|
||
config.shop.pilotEmails = ['kenso.gri@gmail.com']
|
||
assert.equal(shopFuerKunde('kenso.gri@gmail.com'), true)
|
||
assert.equal(shopFuerKunde(' Kenso.Gri@Gmail.com '), true)
|
||
assert.equal(shopFuerKunde('jemand@example.com'), false)
|
||
assert.equal(shopFuerKunde(''), false)
|
||
assert.equal(shopFuerKunde(undefined), false)
|
||
assert.equal(shopFuerKunde(null), false)
|
||
})
|
||
|
||
test('shopFuerKunde: pilot mit leerer Liste laesst niemanden durch, Stern alle (auch ohne Adresse)', () => {
|
||
config.shop.mode = 'pilot'
|
||
config.shop.pilotEmails = []
|
||
assert.equal(shopFuerKunde('kenso.gri@gmail.com'), false)
|
||
assert.equal(shopFuerKunde(''), false)
|
||
config.shop.pilotEmails = ['*']
|
||
assert.equal(shopFuerKunde('jemand@example.com'), true)
|
||
assert.equal(shopFuerKunde(''), true)
|
||
})
|
||
|
||
test('shopFuerKunde: on erlaubt alle Kunden, die Liste spielt keine Rolle', () => {
|
||
config.shop.mode = 'on'
|
||
config.shop.pilotEmails = []
|
||
assert.equal(shopFuerKunde('jemand@example.com'), true)
|
||
assert.equal(shopFuerKunde(''), true)
|
||
})
|
||
|
||
test('shopFuerKunde: Unbekannter Modus gilt als off', () => {
|
||
config.shop.mode = 'banane'
|
||
config.shop.pilotEmails = ['*']
|
||
assert.equal(shopFuerKunde('kenso.gri@gmail.com'), false)
|
||
})
|