← Files Biological Sequence & Alignment ViewerARCHIVED FILE

src/sequence/model-context.test.ts

5.03 KB · Sep 30, 2026 · 23:01 UTC

↓ Download file

import { describe, expect, it } from "vitest";

import { createSequenceViewerModelContext } from "./model-context";
import { parseSequenceDocument } from "./parser";
import { parseSequenceTrack } from "./tracks";

describe("sequence evidence model-context privacy", () => {
  it.each([
    {
      name: "forward exons",
      segments: [
        { start: 1, end: 3 },
        { start: 7, end: 9 },
      ],
      sequence: "ACGGTA",
      topology: "linear" as const,
      wraparound: false,
    },
    {
      name: "reverse-ordered exons",
      segments: [
        { start: 7, end: 9 },
        { start: 1, end: 3 },
      ],
      sequence: "GTAACG",
      topology: "linear" as const,
      wraparound: false,
    },
    {
      name: "circular origin-spanning range",
      segments: [
        { start: 10, end: 12 },
        { start: 1, end: 3 },
      ],
      sequence: "CGTACG",
      topology: "circular" as const,
      wraparound: true,
    },
  ])(
    "keeps $name distinct from a continuous interval",
    ({ segments, sequence, topology, wraparound }) => {
      const document = parseSequenceDocument({
        contents: ">QA_SEGMENT_GEOMETRY\nACGTACGTACGT\n",
        fileName: "QA_SEGMENT_GEOMETRY.fasta",
      });
      const source = document.records[0];
      const first = segments[0];
      const last = segments.at(-1);
      if (source == null || first == null || last == null)
        throw new Error("Expected bounded segment fixture.");
      const record = { ...source, topology };
      const update = createSequenceViewerModelContext({
        activeSearchHitIndex: 0,
        document: { ...document, records: [record] },
        hits: [],
        paletteId: "ncbi-nucleic-acid",
        query: "",
        record,
        selection: {
          recordId: record.id,
          start: first.start,
          end: last.end,
          segments,
        },
        showFeatures: true,
        showQuality: false,
        showTranslation: false,
        wrapWidth: 60,
      });

      expect(update.structuredContent).toMatchObject({
        selection: {
          discontinuous: true,
          length: 6,
          segments,
          sequence,
          wraparound,
        },
      });
      expect(update.text).toContain(
        wraparound ? "origin-spanning" : "discontinuous",
      );
      if (!wraparound) expect(update.text).not.toContain("origin-spanning");
    },
  );

  it("keeps 100 VCF sample identifiers, genotypes, and headers out of model context", () => {
    const document = parseSequenceDocument({
      contents: ">1\nACGTACGTACGT\n",
      fileName: "public-chromosome-1.fasta",
    });
    const record = document.records[0];
    if (record == null) throw new Error("Expected a public chromosome record.");

    const sampleNames = Array.from(
      { length: 100 },
      (_, index) => `QA_PRIVATE_SAMPLE_${index + 1}`,
    );
    const sampleValues = sampleNames.map(
      (_, index) => `0/1:${index + 20}:PRIVATE_GENOTYPE_${index + 1}`,
    );
    const track = parseSequenceTrack({
      content: [
        "##fileformat=VCFv4.3",
        "##SAMPLE=<ID=QA_PRIVATE_SAMPLE_1,Description=PRIVATE_HEADER_METADATA>",
        [
          "#CHROM",
          "POS",
          "ID",
          "REF",
          "ALT",
          "QUAL",
          "FILTER",
          "INFO",
          "FORMAT",
          ...sampleNames,
        ].join("\t"),
        [
          "1",
          "5",
          "rs-public",
          "A",
          "G",
          ".",
          ".",
          "AC=1",
          "GT:DP:QA",
          ...sampleValues,
        ].join("\t"),
      ].join("\n"),
      displayName: "official-100-sample-conformance.vcf",
      format: "vcf",
      id: "public-vcf-track",
      requestedReference: "1",
    });

    expect(track.vcfHeader?.sampleNames).toHaveLength(100);
    expect(track.variants?.[0]?.sampleValues).toEqual(sampleValues);

    const update = createSequenceViewerModelContext({
      activeSearchHitIndex: 0,
      document,
      hits: [],
      paletteId: "ncbi-nucleic-acid",
      query: "",
      record,
      showFeatures: true,
      showQuality: false,
      showTranslation: false,
      tracks: [
        Object.assign(track, {
          futurePrivateSamplePayload: "PRIVATE_FUTURE_METADATA",
        }),
      ],
      wrapWidth: 60,
    });
    const context = JSON.stringify(update.structuredContent);

    expect(context).not.toContain("QA_PRIVATE_SAMPLE_");
    expect(context).not.toContain("PRIVATE_GENOTYPE_");
    expect(context).not.toContain("PRIVATE_HEADER_METADATA");
    expect(context).not.toContain("PRIVATE_FUTURE_METADATA");
    expect(context).not.toContain("vcfHeader");
    expect(context).not.toContain("sampleValues");
    expect(update.text).not.toContain("QA_PRIVATE_SAMPLE_");
    expect(update.structuredContent).toMatchObject({
      workbench: {
        trackCount: 1,
        tracks: [
          {
            featureCount: 0,
            format: "vcf",
            id: "public-vcf-track",
            kind: "variants",
            readCount: 0,
            variantCount: 1,
          },
        ],
      },
    });
  });
});

SHA-256: a6048fc1063d19438ee153fcf78af51e6b32a168174af504a36b8c084e2e655e