teecup/frontend/lib/mentions.test.ts

122 lines
5.5 KiB
TypeScript
Raw Permalink Normal View History

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 }])
})
})