/**
* Integration / wiring tests — verify that each tool works end-to-end through
* its in-memory fallback path when Shopify API keys are NOT configured.
*
* No MSW or external mocks are needed: the tests exercise the real code paths
* that activate when env vars like SHOPIFY_ACCESS_TOKEN are empty strings.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { loadConfig } from '../../src/types.js';
import { manageCart } from '../../src/tools/manage-cart.js';
import { scoutInventory } from '../../src/tools/scout-inventory.js';
import { trackOrder } from '../../src/tools/track-order.js';
import { negotiateTerms, resetAdminAPICache } from '../../src/tools/negotiate-terms.js';
import { getDeps, resetDeps } from '../../src/dynamo/factory.js';
// ─── manage_cart fallback ───
describe('manage_cart fallback (no Shopify keys)', () => {
it('creates a cart with a UUID id via the in-memory path', async () => {
const result = await manageCart({ action: 'create' });
// UUID v4 pattern: 8-4-4-4-12 hex chars
expect(result.cart_id).toMatch(
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
);
expect(result.line_items).toHaveLength(0);
expect(result.item_count).toBe(0);
});
it('supports a full add + get cycle with correct item_count and line_items', async () => {
// 1. Create cart
const cart = await manageCart({ action: 'create' });
// 2. Add an item
await manageCart({
action: 'add',
cart_id: cart.cart_id,
variant_id: 'wiring-var-1',
quantity: 3,
});
// 3. Get the cart and verify
const fetched = await manageCart({
action: 'get',
cart_id: cart.cart_id,
});
expect(fetched.item_count).toBe(3);
expect(fetched.line_items).toHaveLength(1);
expect(fetched.line_items[0]!.variant_id).toBe('wiring-var-1');
expect(fetched.line_items[0]!.quantity).toBe(3);
});
});
// ─── scout_inventory fallback ───
describe('scout_inventory fallback (no Shopify keys)', () => {
it('returns empty products gracefully when no store domain is configured', async () => {
const result = await scoutInventory({ query: 'test' });
expect(result).toEqual({
products: [],
total_count: 0,
has_more: false,
});
});
});
// ─── track_order fallback ───
describe('track_order fallback (no Shopify keys)', () => {
it('returns mock data with found: true when no access token is configured', async () => {
const result = await trackOrder({ order_id: 'test-123' });
expect(result.found).toBe(true);
expect(result.order).toBeDefined();
expect(result.order!.id).toBe('test-123');
expect(result.tracking).toBeDefined();
expect(result.tracking!.tracking_number).toBeDefined();
expect(result.estimated_delivery).toBeDefined();
});
});
// ─── negotiate_terms fallback ───
describe('negotiate_terms fallback (no Shopify keys)', () => {
beforeEach(() => {
resetAdminAPICache();
});
it('returns a result with negotiation and checkout_session defined', async () => {
const config = loadConfig();
const result = await negotiateTerms(
{
cart_id: 'test',
agent_profile_url: 'https://example.com/profile',
},
config,
);
expect(result.negotiation).toBeDefined();
expect(result.negotiation.active_capabilities).toBeDefined();
expect(result.negotiation.available_discounts).toBeDefined();
expect(result.negotiation.shipping_options).toBeDefined();
expect(result.negotiation.payment_handlers).toBeDefined();
expect(result.checkout_session).toBeDefined();
expect(result.checkout_session!.id).toBeDefined();
expect(result.checkout_session!.status).toBeDefined();
});
});
// ─── factory createStores ───
describe('factory getDeps', () => {
beforeEach(() => {
resetDeps();
});
it('returns sessionManager, mandateStore, feeCollector, verifier, and guardrail', () => {
const deps = getDeps();
expect(deps.sessionManager).toBeDefined();
expect(deps.mandateStore).toBeDefined();
expect(deps.feeCollector).toBeDefined();
expect(deps.verifier).toBeDefined();
expect(deps.guardrail).toBeDefined();
expect(deps.config).toBeDefined();
});
it('creates fresh instances after resetDeps()', () => {
const first = getDeps();
resetDeps();
const second = getDeps();
// After reset, getDeps should return new instances (not the cached ones)
expect(second.sessionManager).not.toBe(first.sessionManager);
expect(second.mandateStore).not.toBe(first.mandateStore);
expect(second.feeCollector).not.toBe(first.feeCollector);
});
});