import {describe,it,expect} from "vitest";
import {calculate,settingsFrom,validShortcut,relayTarget,htmlGame,accentInk,viewItems} from "../public/hub-model.js";
describe("Launcher preferences",()=>{
it("preserves explicitly disabled intro and motion settings",()=>{expect(settingsFrom({intro:false,motion:false}).intro).toBe(false);expect(settingsFrom({intro:false,motion:false}).motion).toBe(false);});
it("rejects malformed settings without breaking the page",()=>{expect(settingsFrom(null).theme).toBe("dark");expect(settingsFrom({theme:"bad",focusMinutes:-1}).focusMinutes).toBe(25);});
it("ignores unknown setting properties",()=>{expect(settingsFrom({theme:"light",unknown:"value"})).not.toHaveProperty("unknown");});
});
describe("Custom shortcut validation",()=>{
it("accepts HTTPS shortcuts and normalizes their URL",()=>{expect(validShortcut({name:"Example",url:"https://example.com",category:"apps"}).url).toBe("https://example.com/");});
it.each(["javascript:alert(1)","data:text/html,test","http://example.com","https://user:password@example.com"])("rejects unsafe address %s",url=>{expect(()=>validShortcut({name:"Test",url,category:"apps"})).toThrow();});
it("refuses unsupported categories and oversized titles",()=>{expect(()=>validShortcut({name:"Test",url:"https://example.com",category:"other"})).toThrow();expect(()=>validShortcut({name:"x".repeat(49),url:"https://example.com",category:"apps"})).toThrow();});
});
describe("Calculator",()=>{
it.each([["2*(3+4)","14"],["-3*2.5","-7.5"],["0.1+0.2","0.3"],["12÷3+2×4","12"],["10%3","1"],["-(2+3)*4","-20"]])("evaluates %s",(expression,result)=>{expect(calculate(expression)).toBe(result);});
it.each(["1/0","2**4","alert(1)","(1+2","1+","",".constructor"])("rejects %s",expression=>{expect(()=>calculate(expression)).toThrow();});
});
describe("New hub data",()=>{
it("accepts arbitrary hex accents and both icon sheets",()=>{expect(settingsFrom({accentHex:"#12aB9f",iconSet:"2"})).toMatchObject({accentHex:"#12aB9f",iconSet:"2"});});
it("rejects CSS payloads and unknown icon sets",()=>{expect(settingsFrom({accentHex:"red;display:none",iconSet:"remote"})).toMatchObject({accentHex:"",iconSet:"1"});});
});
describe("HTML imports and relay links",()=>{
it("normalizes an HTTPS relay target",()=>expect(relayTarget("https://example.com")).toBe("https://example.com/"));
it.each(["javascript:alert(1)","https://user:password@example.com/","https://example.com:8443/","file:///test"])("rejects unsafe relay targets %s",url=>expect(()=>relayTarget(url)).toThrow());
it("preserves HTML as data and generates its own game identifier",()=>{const game=htmlGame({name:"Demo",html:""});expect(game.id).toMatch(/^html-/);expect(game.kind).toBe("html");expect(game.html).toContain("