import { describe, expect, it } from "vitest" import { adjustTagsForEdit, detectActiveMention, insertMention, segmentTaggedText } from "./mentions" describe("detectActiveMention", () => { it("finner @-forsøk ved starten av teksten", () => { expect(detectActiveMention("@Fre", 4)).toEqual({ start: 0, query: "Fre" }) }) it("finner @-forsøk midt i teksten, etter mellomrom", () => { const body = "God runde med @Fre" expect(detectActiveMention(body, body.length)).toEqual({ start: 14, query: "Fre" }) }) it("trigges IKKE av en e-post-adresse (@ uten forutgående mellomrom)", () => { const body = "kontakt meg på navn@example" expect(detectActiveMention(body, body.length)).toBeNull() }) it("returnerer null når markøren ikke er i et @-forsøk i det hele tatt", () => { expect(detectActiveMention("bare vanlig tekst", 5)).toBeNull() }) it("returnerer null når @-forsøket ble avbrutt av et mellomrom (fullført/forlatt)", () => { const body = "@Fredrik er kul" expect(detectActiveMention(body, body.length)).toBeNull() }) it("virker med markøren midt i ordet, ikke bare på slutten", () => { const body = "@Fredrik Mathisen" // markør rett etter "Fre" i "Fredrik" expect(detectActiveMention(body, 4)).toEqual({ start: 0, query: "Fre" }) }) }) describe("insertMention", () => { it("erstatter @søketekst med @Fullt Navn og regner riktig ny markørposisjon", () => { const body = "God runde med @Fre i dag" const start = 14 const cursor = 18 // rett etter "Fre" const result = insertMention(body, start, cursor, { user_id: "u1", display_name: "Fredrik Mathisen" }) expect(result.body).toBe("God runde med @Fredrik Mathisen i dag") expect(result.tag).toEqual({ user_id: "u1", display_name: "Fredrik Mathisen", start_index: 14, end_index: 31 }) expect(result.cursor).toBe(31) // Taggens eget utsnitt skal faktisk væra "@Fredrik Mathisen". expect(result.body.slice(result.tag.start_index, result.tag.end_index)).toBe("@Fredrik Mathisen") }) }) describe("adjustTagsForEdit", () => { const tag = { user_id: "u1", display_name: "Fredrik Mathisen", start_index: 14, end_index: 32 } it("beholder taggen uendret når redigeringen skjer ETTER den", () => { const oldBody = "God runde med @Fredrik Mathisen i dag" const newBody = "God runde med @Fredrik Mathisen i dag, supert vær" const result = adjustTagsForEdit(oldBody, newBody, [tag]) expect(result).toEqual([tag]) }) it("forskyver taggen når tekst settes inn FØR den", () => { const oldBody = "med @Fredrik Mathisen i dag" const newBody = "God runde med @Fredrik Mathisen i dag" const shifted = { ...tag, start_index: 0, end_index: 18 } // relativt til oldBody sin tag const oldTag = { ...tag, start_index: 4, end_index: 22 } const result = adjustTagsForEdit(oldBody, newBody, [oldTag]) const delta = newBody.length - oldBody.length expect(result).toEqual([{ ...oldTag, start_index: oldTag.start_index + delta, end_index: oldTag.end_index + delta }]) }) it("dropper taggen stille når redigeringen overlapper dens eget utsnitt", () => { const oldBody = "med @Fredrik Mathisen i dag" const oldTag = { ...tag, start_index: 4, end_index: 22 } // Sletter en bokstav MIDT i det taggede navnet. const newBody = "med @Fredrik athisen i dag" const result = adjustTagsForEdit(oldBody, newBody, [oldTag]) expect(result).toEqual([]) }) it("dropper KUN den berørte taggen, beholder en urørt tag et annet sted", () => { const oldBody = "@Fredrik og @Kari spilte i dag" const fredrikTag = { user_id: "u1", display_name: "Fredrik", start_index: 0, end_index: 8 } const kariTag = { user_id: "u2", display_name: "Kari", start_index: 12, end_index: 17 } // Redigerer midt i "Fredrik". const newBody = "@Fred og @Kari spilte i dag" const result = adjustTagsForEdit(oldBody, newBody, [fredrikTag, kariTag]) const delta = newBody.length - oldBody.length expect(result).toEqual([{ ...kariTag, start_index: kariTag.start_index + delta, end_index: kariTag.end_index + delta }]) }) }) describe("segmentTaggedText", () => { it("deler teksten korrekt rundt én tag", () => { const body = "God runde med @Fredrik Mathisen i dag" const tag = { user_id: "u1", display_name: "Fredrik Mathisen", start_index: 14, end_index: 31 } const segments = segmentTaggedText(body, [tag]) expect(segments).toEqual([ { text: "God runde med ", tag: null }, { text: "@Fredrik Mathisen", tag }, { text: " i dag", tag: null }, ]) }) it("returnerer hele teksten som ett segment når det ikke finnes tags", () => { const segments = segmentTaggedText("bare vanlig tekst", []) expect(segments).toEqual([{ text: "bare vanlig tekst", tag: null }]) }) it("håndterer flere tags i rekkefølge", () => { const body = "@Fredrik og @Kari spilte" const t1 = { user_id: "u1", display_name: "Fredrik", start_index: 0, end_index: 8 } const t2 = { user_id: "u2", display_name: "Kari", start_index: 12, end_index: 17 } const segments = segmentTaggedText(body, [t1, t2]) expect(segments.map((s) => s.text)).toEqual(["@Fredrik", " og ", "@Kari", " spilte"]) }) it("hopper defensivt over en tag med ugyldig/utenfor-grense offset i stedet for å krasje", () => { const body = "kort tekst" const badTag = { user_id: "u1", display_name: "X", start_index: 5, end_index: 999 } expect(() => segmentTaggedText(body, [badTag])).not.toThrow() expect(segmentTaggedText(body, [badTag])).toEqual([{ text: "kort tekst", tag: null }]) }) })