Files
Socialflow/shared/reel.test.ts
T
Claude 9b66a6dc5a feat(reels): montage Remotion unifié, aperçu en direct, tests et CI
Montage (étape 3) :
- Nouvelle composition ReelVideo : sous-titres animés mot à mot (3 styles :
  Impact, Surligné, Épuré), logo, effet de fin et fondu, en React
- Le service Python prépare l'image (recadrage, HDR, stabilisation, dernière
  image figée) et la piste son finale (/prepare-reel) ; Remotion compose
- Reels d'images sur les mêmes composants, avec le vrai minutage de la voix
- Police Montserrat embarquée (plus de dépendance à Google Fonts)
- REEL_RENDERER=ffmpeg conserve le rendu FFmpeg, plus rapide, en secours
- Script de pré-bundle réparé (échouait en silence : require en ESM)

Interface (étape 4) :
- Aperçu en direct avec @remotion/player, identique au rendu final ; la voix
  testée cale les sous-titres, sinon minutage estimé
- Choix du style de sous-titres sur les 4 pages Reel
- Vraie progression : étape réelle du rendu, échecs visibles 24 h avec leur
  cause ; fin de la barre simulée et du faux « publié avec succès »

Outillage (étape 5) :
- Tests vitest (minutage identique à Python, validation, sécurité) et
  pytest ; CI GitHub Actions (tsc, tests, build, ruff)
- Captures d'écran, out.mp4 et scripts de test retirés de la racine

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Ze4bs7tpF1KGWUk6ZZSZ4
2026-09-24 14:37:42 +00:00

36 lines
1.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { imagesReelParamsSchema, ttsPreviewSchema, videoReelParamsSchema } from "./reel";
describe("videoReelParamsSchema", () => {
it("exige une vidéo et une page, avec des messages lisibles", () => {
const result = videoReelParamsSchema.safeParse({ pageIds: [] });
expect(result.success).toBe(false);
expect(result.error?.issues.map((i) => i.message)).toContain("Vidéo requise");
});
it("applique les valeurs par défaut", () => {
const params = videoReelParamsSchema.parse({ videoMediaId: "v", pageIds: ["p"] });
expect(params).toMatchObject({ captionStyle: "bold", stabilize: false, drawText: true, musicVolume: 0.25 });
});
it("accepte les anciens paramètres encore stockés dans des jobs", () => {
expect(videoReelParamsSchema.safeParse({ videoMediaId: "v", pageIds: ["p"], wordDuration: 0.6 }).success).toBe(true);
});
it("refuse un moteur de voix inconnu", () => {
expect(videoReelParamsSchema.safeParse({ videoMediaId: "v", pageIds: ["p"], ttsEngine: "autre" }).success).toBe(false);
});
});
describe("imagesReelParamsSchema", () => {
it("limite à 4 images", () => {
expect(imagesReelParamsSchema.safeParse({ imageUrls: ["a", "b", "c", "d", "e"] }).success).toBe(false);
});
});
describe("ttsPreviewSchema", () => {
it("refuse un texte vide", () => {
expect(ttsPreviewSchema.safeParse({ text: " " }).success).toBe(false);
});
});