2025-06-25 13:37:35 -05:00

174 lines
4.7 KiB
TypeScript

import { describe, test, expect } from '@jest/globals';
import { ResolverPlugin, DependencyStates } from '@src/views/resolvers/custom-resolvers';
import { PropertyTypes } from '@src/core/types';
import { testResolverWithPlugins, createTestDelta } from '@test-helpers/resolver-test-helper';
import Debug from 'debug';
const debug = Debug('rz:test:discount-plugins');
// Mock plugins for testing
class DiscountPlugin extends ResolverPlugin<number, never> {
readonly name = 'discount' as const;
readonly dependencies = [] as const;
initialize() {
return 0;
}
update(
_currentState: number,
newValue: PropertyTypes,
) {
const numValue = typeof newValue === 'number' ? newValue : 0;
const clampedValue = Math.min(100, Math.max(0, numValue)); // Clamp between 0-100
debug(`DiscountPlugin: updated discount to ${clampedValue}`);
return clampedValue;
}
resolve( state: number ): number {
return state;
}
}
class DiscountedPricePlugin extends ResolverPlugin<number | null, 'discount'> {
readonly name = 'price' as const;
readonly dependencies = ['discount'] as const;
initialize() {
return null;
}
update(
_currentState: number | null,
newValue: PropertyTypes,
) {
const numValue = typeof newValue === 'number' ? newValue : 0;
debug(`DiscountedPricePlugin: updated price to ${numValue}`);
return numValue;
}
resolve(
state: number | null,
dependencies: DependencyStates
): number | null {
if (state === null) {
return null;
}
// Ensure discount is a number and default to 0 if undefined
const discount = typeof dependencies.discount === 'number' ? dependencies.discount : 0;
const discountMultiplier = (100 - discount) / 100;
return state * discountMultiplier;
}
}
describe('Discount and DiscountedPrice Plugins', () => {
test('should apply discount to price', async () => {
// Arrange
const entityId = 'product1';
// Act
const result = await testResolverWithPlugins({
entityId,
plugins: {
price: new DiscountedPricePlugin(),
discount: new DiscountPlugin()
},
deltas: [
// Set base price
createTestDelta()
.withTimestamp(1000)
.setProperty(entityId, 'price', 100, 'product')
.buildV1(),
// Set discount (20%)
createTestDelta()
.withTimestamp(2000)
.setProperty(entityId, 'discount', 20, 'product')
.buildV1()
],
});
// Assert
expect(result).toBeDefined();
expect(result?.properties?.price).toBe(80); // 100 * 0.8 = 80
});
test('should handle zero discount', async () => {
// Arrange
const entityId = 'product1';
// Act
const result = await testResolverWithPlugins({
entityId,
plugins: {
price: new DiscountedPricePlugin(),
discount: new DiscountPlugin()
},
deltas: [
// Set base price
createTestDelta()
.withTimestamp(1000)
.setProperty(entityId, 'price', 100, 'products')
.buildV1(),
// Set discount to 0
createTestDelta()
.withTimestamp(2000)
.setProperty(entityId, 'discount', 0, 'products')
.buildV1()
],
});
// Assert
expect(result).toBeDefined();
expect(result?.properties?.price).toBe(100); // 100 * 1.0 = 100
});
test('should handle 100% discount', async () => {
// Arrange
const entityId = 'product1';
// Act
const result = await testResolverWithPlugins({
entityId,
plugins: {
price: new DiscountedPricePlugin(),
discount: new DiscountPlugin()
},
deltas: [
// Set base price
createTestDelta()
.withTimestamp(1000)
.setProperty(entityId, 'price', 100, 'products')
.buildV1(),
// Set discount to 100%
createTestDelta()
.withTimestamp(2000)
.setProperty(entityId, 'discount', 100, 'products')
.buildV1()
],
});
// Assert
expect(result).toBeDefined();
expect(result?.properties.price).toBe(0); // 100 * 0.0 = 0
});
test('should handle missing discount plugin', async () => {
// Arrange
const entityId = 'product1';
// Act
await expect(
testResolverWithPlugins({
entityId,
plugins: {
price: new DiscountedPricePlugin()
// No discount plugin provided
},
deltas: [
// Set base price
createTestDelta()
.withTimestamp(1000)
.setProperty(entityId, 'price', 100, 'products')
.buildV1()
]
})).rejects.toThrowError('Dependency discount not found for plugin price');
});
});