UNPKG

yoonite-saga

Version:

> Orchestration de workflows transactionnels avec gestion de compensation (pattern Saga)

107 lines 4.51 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); const class_validator_1 = require("class-validator"); const saga_builder_1 = require("./saga-builder"); const saga_processor_1 = require("./saga-processor"); describe("SagaProcessor", () => { class TestDto { } __decorate([ (0, class_validator_1.IsString)(), __metadata("design:type", String) ], TestDto.prototype, "name", void 0); __decorate([ (0, class_validator_1.IsInt)(), (0, class_validator_1.Min)(1), __metadata("design:type", Number) ], TestDto.prototype, "count", void 0); it("should execute a simple workflow and enrich context", async () => { const builder = new saga_builder_1.SagaBuilder(); const workflow = builder .step("init") .invoke(() => ({ name: "foo", count: 2 })) .build(); const processor = new saga_processor_1.SagaProcessor(); processor.add(workflow); const result = await processor.start(); expect(result.state).toBe("success"); expect(result.context).toEqual({ name: "foo", count: 2 }); expect(result.errors).toHaveLength(0); }); it("should validate context and fail if invalid", async () => { const builder = new saga_builder_1.SagaBuilder(); const workflow = builder .step("invalid") .invoke(() => ({ name: 123, count: 0 })) .validate(TestDto) .build(); const processor = new saga_processor_1.SagaProcessor(); processor.add(workflow); const result = await processor.start(); expect(result.state).toBe("failed"); expect(result.errors.length).toBeGreaterThan(0); expect(result.errors[0].message).toContain("Validation failed"); }); it("should skip step if condition is false", async () => { const builder = new saga_builder_1.SagaBuilder(); const workflow = builder .step("step1") .invoke(() => ({ a: 1 })) .step("step2") .condition(() => false) .invoke(() => ({ b: 2 })) .build(); const processor = new saga_processor_1.SagaProcessor(); processor.add(workflow); const result = await processor.start(); expect(result.context).toEqual({ a: 1 }); expect(result.state).toBe("success"); }); it("should execute compensation on error", async () => { let compensated = false; const builder = new saga_builder_1.SagaBuilder(); const workflow = builder .step("step1") .invoke(() => ({ a: 1 })) .withCompensation(() => { compensated = true; }) .step("step2") .invoke(() => { throw new Error("fail"); }) .build(); const processor = new saga_processor_1.SagaProcessor(); processor.add(workflow); const result = await processor.start(); expect(result.state).toBe("failed"); expect(compensated).toBe(true); }); it("should inject services and use them in invokes", async () => { const log = []; const services = { logger: { log: (msg) => log.push(msg) }, }; const builder = new saga_builder_1.SagaBuilder(); const workflow = builder .step("log") .invoke((ctx, { logger }) => { logger.log("hello"); }) .build(); const processor = new saga_processor_1.SagaProcessor(services); processor.add(workflow); await processor.start(); expect(log).toContain("hello"); }); }); //# sourceMappingURL=saga-processor.spec.js.map