Path: blob/main/tests/unit/percent-format.test.ts
6449 views
/*1* percent-format.test.ts2*3* Tests for the Jupyter percent format script parsing4*5* Copyright (C) 2020-2024 Posit Software, PBC6*/7import { assertEquals, assert } from "testing/asserts";8import { unitTest } from "../test.ts";9import { docs } from "../utils.ts";10import {11isJupyterPercentScript,12markdownFromJupyterPercentScript,13kJupyterPercentScriptExtensions,14kLanguageExtensions,15} from "../../src/core/jupyter/percent.ts";1617// Test that the language extensions mapping is correct18unitTest("percent-format - kLanguageExtensions mapping", async () => {19assertEquals(kLanguageExtensions[".py"], "python");20assertEquals(kLanguageExtensions[".jl"], "julia");21assertEquals(kLanguageExtensions[".r"], "r");22assertEquals(kLanguageExtensions[".q"], "q");23});2425// Test that all extensions in kJupyterPercentScriptExtensions have a language mapping26unitTest("percent-format - all extensions have language mappings", async () => {27for (const ext of kJupyterPercentScriptExtensions) {28assert(29kLanguageExtensions[ext] !== undefined,30`Extension ${ext} has no language mapping`,31);32}33});3435// Test isJupyterPercentScript for Python36unitTest("percent-format - isJupyterPercentScript detects Python percent script", async () => {37const result = isJupyterPercentScript(docs("percent-format/test-python.py"));38assertEquals(result, true, "Should detect Python percent script");39});4041// Test isJupyterPercentScript for q/kdb42unitTest("percent-format - isJupyterPercentScript detects q percent script", async () => {43const result = isJupyterPercentScript(docs("percent-format/test-q.q"));44assertEquals(result, true, "Should detect q percent script");45});4647// Test isJupyterPercentScript for Julia48unitTest("percent-format - isJupyterPercentScript detects Julia percent script", async () => {49const result = isJupyterPercentScript(docs("percent-format/test-julia.jl"));50assertEquals(result, true, "Should detect Julia percent script");51});5253// Test isJupyterPercentScript for R54unitTest("percent-format - isJupyterPercentScript detects R percent script", async () => {55const result = isJupyterPercentScript(docs("percent-format/test-r.r"));56assertEquals(result, true, "Should detect R percent script");57});5859// Test that non-percent scripts are not detected60unitTest("percent-format - isJupyterPercentScript rejects non-percent Python", async () => {61const result = isJupyterPercentScript(docs("percent-format/not-percent.py"));62assertEquals(result, false, "Should not detect non-percent Python file");63});6465unitTest("percent-format - isJupyterPercentScript rejects non-percent q", async () => {66const result = isJupyterPercentScript(docs("percent-format/not-percent.q"));67assertEquals(result, false, "Should not detect non-percent q file");68});6970// Test isJupyterPercentScript rejects unsupported extensions71unitTest("percent-format - isJupyterPercentScript rejects unsupported extensions", async () => {72// Create a temp file with unsupported extension - use a non-existent path73// The function checks extension first, so it won't try to read the file74const result = isJupyterPercentScript("/fake/path/file.txt");75assertEquals(result, false, "Should reject unsupported extension");76});7778// Test markdownFromJupyterPercentScript for Python79unitTest("percent-format - markdownFromJupyterPercentScript converts Python", async () => {80const markdown = markdownFromJupyterPercentScript(81docs("percent-format/test-python.py"),82);8384// Check that it contains python code blocks85assert(markdown.includes("```{python}"), "Should contain python code block");86assert(markdown.includes("```"), "Should contain closing code fence");8788// Check that markdown content is extracted89assert(90markdown.includes("This is a markdown cell"),91"Should contain markdown content",92);9394// Check that code content is present95assert(96markdown.includes('print("Hello from Python")'),97"Should contain Python code",98);99});100101// Test markdownFromJupyterPercentScript for q/kdb102unitTest("percent-format - markdownFromJupyterPercentScript converts q", async () => {103const markdown = markdownFromJupyterPercentScript(104docs("percent-format/test-q.q"),105);106107// Check that it contains q code blocks108assert(markdown.includes("```{q}"), "Should contain q code block");109assert(markdown.includes("```"), "Should contain closing code fence");110111// Check that markdown content is extracted (without the / prefix)112assert(113markdown.includes("This is a markdown cell"),114"Should contain markdown content",115);116117// Check that code content is present118assert(markdown.includes("1+1"), "Should contain q code");119assert(markdown.includes("x: 42"), "Should contain q code");120});121122// Test markdownFromJupyterPercentScript for Julia123unitTest("percent-format - markdownFromJupyterPercentScript converts Julia", async () => {124const markdown = markdownFromJupyterPercentScript(125docs("percent-format/test-julia.jl"),126);127128// Check that it contains julia code blocks129assert(markdown.includes("```{julia}"), "Should contain julia code block");130131// Check that markdown content is extracted132assert(133markdown.includes("This is a markdown cell"),134"Should contain markdown content",135);136137// Check that code content is present138assert(139markdown.includes('println("Hello from Julia")'),140"Should contain Julia code",141);142});143144// Test markdownFromJupyterPercentScript for R145unitTest("percent-format - markdownFromJupyterPercentScript converts R", async () => {146const markdown = markdownFromJupyterPercentScript(147docs("percent-format/test-r.r"),148);149150// Check that it contains r code blocks151assert(markdown.includes("```{r}"), "Should contain r code block");152153// Check that markdown content is extracted154assert(155markdown.includes("This is a markdown cell"),156"Should contain markdown content",157);158159// Check that code content is present160assert(161markdown.includes('print("Hello from R")'),162"Should contain R code",163);164});165166// =============================================================================167// Regression tests for regex bug fix168// The original regex had incorrect alternation: \[markdown|raw\] which matches169// "[markdown" OR "raw]" instead of "[markdown]" OR "[raw]"170// =============================================================================171172// Test that [raw] cells are detected (tests correct alternation grouping)173unitTest("percent-format - isJupyterPercentScript detects [raw] cells", async () => {174const result = isJupyterPercentScript(docs("percent-format/test-raw-cell.py"));175assertEquals(result, true, "Should detect percent script with [raw] cell");176});177178// Test that markdown cells not at start of file are detected (tests multiline matching)179unitTest("percent-format - isJupyterPercentScript detects markdown cell not at file start", async () => {180const result = isJupyterPercentScript(docs("percent-format/test-markdown-not-first.py"));181assertEquals(result, true, "Should detect percent script with markdown cell not at start");182});183184// Test that files containing "raw]" text are not falsely detected185// This was a bug where the regex would match "raw]" anywhere in the file186unitTest("percent-format - isJupyterPercentScript rejects file with raw] text", async () => {187const result = isJupyterPercentScript(docs("percent-format/false-positive-raw.py"));188assertEquals(result, false, "Should not detect file that merely contains 'raw]' text");189});190191192