import { describe, expect, test } from "vitest"; import { appBannerSchema, appPopupSchema, appSplashScreenSchema, exploreTabSchema, h5LinkUpdateSchema, } from "@/features/app-config/schema"; import { FormValidationError, parseForm } from "@/shared/forms/validation"; const validBannerForm = { bannerType: "h5", countryCode: "", coverUrl: "https://media.haiyihy.com/banner/home.png", description: "", displayScope: "home", displayScopes: ["home"], endsAtMs: "1800000000000", param: "https://h5.example.com/activity", platform: "android", regionId: "", roomSmallImageUrl: "", sortOrder: "0", startsAtMs: "1700000000000", status: "active", }; const validSplashScreenForm = { countryCode: "", coverUrl: "https://media.haiyihy.com/splash/launch.png", description: "", displayDurationMs: "4500", endsAtMs: "1800000000000", param: "https://h5.example.com/splash", platform: "ios", regionId: "", sortOrder: "0", splashType: "h5", startsAtMs: "1700000000000", status: "active", }; const validPopupForm = { code: "new-user-popup", displayPeriodDays: "2", endsAtMs: "1800000000000", imageUrl: "", jumpType: "h5", jumpUrl: "https://h5.example.com/popup", name: "新人活动", sortOrder: "0", startsAtMs: "1700000000000", status: "active", }; describe("app config form schema", () => { test("validates dynamic h5 config item", () => { const payload = parseForm(h5LinkUpdateSchema, { key: "host-center.v2", label: "Host Center", url: "https://h5.example.com/host", }); expect(payload.key).toBe("host-center.v2"); expect(payload.label).toBe("Host Center"); }); test("rejects dynamic h5 config key with spaces", () => { expect(() => parseForm(h5LinkUpdateSchema, { key: "host center", label: "Host Center", url: "https://h5.example.com/host", }), ).toThrow(FormValidationError); }); test("keeps banner display scope and delivery time fields", () => { const payload = parseForm(appBannerSchema, validBannerForm); expect(payload.displayScopes).toEqual(["home"]); expect(payload.startsAtMs).toBe(1700000000000); expect(payload.endsAtMs).toBe(1800000000000); }); test("accepts public app jump json for banner", () => { const payload = parseForm(appBannerSchema, { ...validBannerForm, bannerType: "app", param: '{"type":"room_random_game","game_id":"dice"}', }); expect(payload.bannerType).toBe("app"); expect(payload.param).toBe('{"type":"room_random_game","game_id":"dice"}'); }); test("rejects incomplete public app jump json for banner", () => { expect(() => parseForm(appBannerSchema, { ...validBannerForm, bannerType: "app", param: '{"type":"room_game","room_id":"room_1"}', }), ).toThrow(FormValidationError); }); test("accepts multiple banner display scopes", () => { const payload = parseForm(appBannerSchema, { ...validBannerForm, displayScopes: ["home", "room", "recharge"], roomSmallImageUrl: "https://media.haiyihy.com/banner/room-small.png", }); expect(payload.displayScopes).toEqual(["home", "room", "recharge"]); }); test("requires room small image for room banner", () => { expect(() => parseForm(appBannerSchema, { ...validBannerForm, displayScopes: ["home", "room"], roomSmallImageUrl: "", }), ).toThrow(FormValidationError); }); test("rejects inverted banner delivery time range", () => { expect(() => parseForm(appBannerSchema, { ...validBannerForm, endsAtMs: "1700000000000", startsAtMs: "1800000000000", }), ).toThrow(FormValidationError); }); test("keeps splash screen delivery and placement fields without display scope", () => { const payload = parseForm(appSplashScreenSchema, validSplashScreenForm); expect(payload.splashType).toBe("h5"); expect(payload.displayDurationMs).toBe(4500); expect(payload.startsAtMs).toBe(1700000000000); expect(payload.endsAtMs).toBe(1800000000000); expect("displayScopes" in payload).toBe(false); }); test("accepts public app jump json for splash screen", () => { const payload = parseForm(appSplashScreenSchema, { ...validSplashScreenForm, param: '{"type":"wallet"}', splashType: "app", }); expect(payload.splashType).toBe("app"); expect(payload.param).toBe('{"type":"wallet"}'); }); test("requires h5 link for splash screen h5 type", () => { expect(() => parseForm(appSplashScreenSchema, { ...validSplashScreenForm, param: "", }), ).toThrow(FormValidationError); }); test("rejects negative splash screen display duration", () => { expect(() => parseForm(appSplashScreenSchema, { ...validSplashScreenForm, displayDurationMs: "-1", }), ).toThrow(FormValidationError); }); test("rejects inverted splash screen delivery time range", () => { expect(() => parseForm(appSplashScreenSchema, { ...validSplashScreenForm, endsAtMs: "1700000000000", startsAtMs: "1800000000000", }), ).toThrow(FormValidationError); }); test("keeps popup optional image and display period", () => { const payload = parseForm(appPopupSchema, validPopupForm); expect(payload.code).toBe("new-user-popup"); expect(payload.imageUrl).toBe(""); expect(payload.displayPeriodDays).toBe(2); expect(payload.startsAtMs).toBe(1700000000000); expect(payload.endsAtMs).toBe(1800000000000); }); test("accepts public app jump json for popup", () => { const payload = parseForm(appPopupSchema, { ...validPopupForm, jumpType: "app", jumpUrl: '{"type":"room_window","room_id":"room_1","window":"gift_panel","gift_id":"gift_1"}', }); expect(payload.jumpType).toBe("app"); expect(payload.jumpUrl).toBe( '{"type":"room_window","room_id":"room_1","window":"gift_panel","gift_id":"gift_1"}', ); }); test("rejects popup code with spaces", () => { expect(() => parseForm(appPopupSchema, { ...validPopupForm, code: "new user popup", }), ).toThrow(FormValidationError); }); test("requires popup jump address", () => { expect(() => parseForm(appPopupSchema, { ...validPopupForm, jumpUrl: "", }), ).toThrow(FormValidationError); }); test("rejects inverted popup effective time range", () => { expect(() => parseForm(appPopupSchema, { ...validPopupForm, endsAtMs: "1700000000000", startsAtMs: "1800000000000", }), ).toThrow(FormValidationError); }); test("validates explore tab h5 url and sort order", () => { const payload = parseForm(exploreTabSchema, { enabled: true, h5Url: "https://h5.example.com/explore/live", sortOrder: "3", tab: "Live", }); expect(payload.sortOrder).toBe(3); expect(payload.h5Url).toBe("https://h5.example.com/explore/live"); }); test("rejects explore tab url with whitespace", () => { expect(() => parseForm(exploreTabSchema, { enabled: true, h5Url: "https://h5.example.com/explore live", sortOrder: "0", tab: "Live", }), ).toThrow(FormValidationError); }); });