test: add unit tests for frontend top-down auto-reset and backend split logic

This commit is contained in:
DanielS
2026-07-09 21:56:13 +02:00
parent 988625ba42
commit 992e726406
3 changed files with 169 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
import { describe, it, expect } from 'vitest';
import { splitCart, CartItem } from './checkout-split';
describe('Checkout Split Logic', () => {
it('should place purchase items only into purchase group', () => {
const cart: CartItem[] = [
{ billingInterval: 'one_time', selections: {} },
{ billingType: 'purchase', selections: {} }
];
const { purchaseItems, subscriptionItems } = splitCart(cart);
expect(purchaseItems.length).toBe(2);
expect(subscriptionItems.length).toBe(0);
});
it('should place subscription items only into subscription group', () => {
const cart: CartItem[] = [
{ billingInterval: 'monthly', selections: {} },
{ billingType: 'subscription', selections: {} }
];
const { purchaseItems, subscriptionItems } = splitCart(cart);
expect(purchaseItems.length).toBe(0);
expect(subscriptionItems.length).toBe(2);
});
it('should split mixed cart into separate purchase and subscription groups', () => {
const cart: CartItem[] = [
{ billingInterval: 'one_time', selections: {} },
{ billingInterval: 'monthly', selections: {} },
{ billingType: 'purchase', selections: {} },
{ billingType: 'subscription', selections: {} }
];
const { purchaseItems, subscriptionItems } = splitCart(cart);
expect(purchaseItems.length).toBe(2);
expect(subscriptionItems.length).toBe(2);
});
});

View File

@@ -0,0 +1,17 @@
export interface CartItem {
id?: string;
billingInterval?: 'one_time' | 'monthly';
billingType?: 'purchase' | 'subscription';
selections: any;
moduleQuantities?: Record<string, number>;
}
export function splitCart(items: CartItem[]) {
const purchaseItems = items.filter(
item => item.billingInterval === 'one_time' || item.billingType === 'purchase'
);
const subscriptionItems = items.filter(
item => item.billingInterval === 'monthly' || item.billingType === 'subscription'
);
return { purchaseItems, subscriptionItems };
}

View File

@@ -0,0 +1,110 @@
import { describe, it, expect } from 'vitest';
import { handleBaseProductChange, handleModuleToggle } from './wizard-state';
import { Product, ProductModule, Category, WizardSelections } from './types';
describe('Wizard State Management', () => {
const mockCategories: Category[] = [
{
id: 'cat-1',
name: 'Kasse',
sort_order: 1,
is_required: true,
allow_multiselect: false,
free_items_limit: 0,
preselect: false,
resets_others: false,
created_at: '',
},
{
id: 'cat-2',
name: 'Backoffice',
sort_order: 2,
is_required: false,
allow_multiselect: false, // Radio behavior
free_items_limit: 0,
preselect: false,
resets_others: false,
created_at: '',
}
];
const mockModules: ProductModule[] = [
{
id: 'mod-cloud',
product_id: 'prod-gastro',
name: 'POSCloud',
price: 10,
requirements: [],
exclusions: [],
created_at: '',
},
{
id: 'mod-office-1',
product_id: 'prod-gastro',
name: 'Office Pro',
price: 20,
requirements: [],
exclusions: [],
created_at: '',
},
{
id: 'mod-office-2',
product_id: 'prod-gastro',
name: 'Office Light',
price: 5,
requirements: [],
exclusions: [],
created_at: '',
}
];
it('should automatically remove excluded modules when switching base product', () => {
const currentSelections: WizardSelections = {
'cat-2': {
productId: null,
moduleIds: ['mod-cloud'] // User has POSCloud selected
}
};
// Exclusion rule: 'prod-small' excludes 'mod-cloud'
const mockExclusions = [
{
product_id: 'prod-small',
excluded_module_id: 'mod-cloud'
}
];
const result = handleBaseProductChange(
'prod-small',
currentSelections,
mockModules,
[],
mockExclusions
);
// POSCloud should be removed
expect(result['cat-2'].moduleIds).not.toContain('mod-cloud');
});
it('should respect allow_multiselect = false and only allow one selection in that category', () => {
let selections: WizardSelections = {
'cat-2': {
productId: null,
moduleIds: ['mod-office-1']
}
};
// Toggle on 'mod-office-2' in a single-select category
selections = handleModuleToggle(
'mod-office-2',
'cat-2',
selections,
mockCategories,
mockModules
);
// Should only contain 'mod-office-2'
expect(selections['cat-2'].moduleIds).toContain('mod-office-2');
expect(selections['cat-2'].moduleIds).not.toContain('mod-office-1');
});
});