diff --git a/apps/vscode/src/test/examples/hello.qmd b/apps/vscode/src/test/examples/hello.qmd index c4cdf60a..77ffd194 100644 --- a/apps/vscode/src/test/examples/hello.qmd +++ b/apps/vscode/src/test/examples/hello.qmd @@ -10,3 +10,5 @@ format: html ``` *YO!* + +note the lack of newline at the end of this file. \ No newline at end of file diff --git a/apps/vscode/src/test/examples/roundtrip-failures.qmd b/apps/vscode/src/test/examples/roundtrip-failures.qmd new file mode 100644 index 00000000..c8438342 --- /dev/null +++ b/apps/vscode/src/test/examples/roundtrip-failures.qmd @@ -0,0 +1,22 @@ +``````{=markdown} +```{=markdown} +hi +``` +`````` + +kBlockCapsuleSentinel uuid sentinel leak during SE→VE +``````{{python}} +``` +dog +``` +`````` + +````` +```{python} +a = 3 +```` +````` + +_YO!_ + +be careful of newline at end of file, roundtripping removes it: diff --git a/apps/vscode/src/test/quartoDoc.test.ts b/apps/vscode/src/test/quartoDoc.test.ts index 87c7f5e5..e6f9fddf 100644 --- a/apps/vscode/src/test/quartoDoc.test.ts +++ b/apps/vscode/src/test/quartoDoc.test.ts @@ -1,62 +1,65 @@ import * as vscode from "vscode"; import * as assert from "assert"; -import { exampleWorkspacePath, exampleWorkspaceOutPath, copyFile, wait } from "./test-utils"; +import { WORKSPACE_PATH, examplesOutUri, wait } from "./test-utils"; import { isQuartoDoc } from "../core/doc"; import { extension } from "./extension"; const APPROX_TIME_TO_OPEN_VISUAL_EDITOR = 1700; suite("Quarto basics", function () { - // Before we run any tests, we should copy any files that get edited in the tests to file under `exampleWorkspaceOutPath` + // Before running tests, copy `./examples` to a new folder `./examples-out`. + // We copy to examples-out because the tests modify the files. suiteSetup(async function () { - const didCopyFile = await copyFile(exampleWorkspacePath('hello.qmd'), exampleWorkspaceOutPath('hello.qmd')); - assert.ok(didCopyFile); + await vscode.workspace.fs.delete(examplesOutUri(), { recursive: true }); + await vscode.workspace.fs.copy(vscode.Uri.file(WORKSPACE_PATH), examplesOutUri()); }); test("Can open a Quarto document", async function () { - const doc = await vscode.workspace.openTextDocument(exampleWorkspaceOutPath("hello.qmd")); + const doc = await vscode.workspace.openTextDocument(examplesOutUri("hello.qmd")); const editor = await vscode.window.showTextDocument(doc); assert.strictEqual(editor?.document.languageId, "quarto"); assert.strictEqual(isQuartoDoc(editor?.document), true); }); - // Note: the following tests may be flaky. They rely on waiting estimated amounts of time for commands to complete. - test("Can edit in visual mode", async function () { - const doc = await vscode.workspace.openTextDocument(exampleWorkspaceOutPath("hello.qmd")); - const editor = await vscode.window.showTextDocument(doc); - - await extension().activate(); - - // manually confirm visual mode so dialogue pop-up doesn't show because dialogues cause test errors - // and switch to visual editor - await vscode.commands.executeCommand("quarto.test_setkVisualModeConfirmedTrue"); - await wait(300); // It seems necessary to wait around 300ms for this command to be done. - await vscode.commands.executeCommand("quarto.editInVisualMode"); - await wait(APPROX_TIME_TO_OPEN_VISUAL_EDITOR); - - assert.ok(await vscode.commands.executeCommand("quarto.test_isInVisualEditor")); - }); - // Note: this test runs after the previous test, so `hello.qmd` has already been touched by the previous + // Note: this test runs after the previous test, so `hello.qmd` can already be touched by the previous // test. That's okay for this test, but could cause issues if you expect a qmd to look how it // does in `/examples`. test("Roundtrip doesn't change hello.qmd", async function () { - const doc = await vscode.workspace.openTextDocument(exampleWorkspaceOutPath("hello.qmd")); + const doc = await vscode.workspace.openTextDocument(examplesOutUri("hello.qmd")); const editor = await vscode.window.showTextDocument(doc); - await extension().activate(); + const { before, after } = await roundtrip(doc); - const docTextBefore = doc.getText(); + assert.equal(before, after); + }); - // switch to visual editor and back - await vscode.commands.executeCommand("quarto.test_setkVisualModeConfirmedTrue"); - await wait(300); - await vscode.commands.executeCommand("quarto.editInVisualMode"); - await wait(APPROX_TIME_TO_OPEN_VISUAL_EDITOR); - await vscode.commands.executeCommand("quarto.editInSourceMode"); - await wait(300); + test("Roundtrip does change roundtrip-failures.qmd", async function () { + // We want this test to fail locally so that we can reference the + // before/affter diff that Mocha logs, but we dont wan't CI to fail. + if (process.env['CI']) this.skip(); - const docTextAfter = doc.getText(); - assert.ok(docTextBefore === docTextAfter, docTextAfter); + const doc = await vscode.workspace.openTextDocument(examplesOutUri("roundtrip-failures.qmd")); + const editor = await vscode.window.showTextDocument(doc); + + const { before, after } = await roundtrip(doc); + + assert.equal(before, after); }); }); + +async function roundtrip(doc: vscode.TextDocument) { + const before = doc.getText(); + + // switch to visual editor and back + await vscode.commands.executeCommand("quarto.test_setkVisualModeConfirmedTrue"); + await wait(300); + await vscode.commands.executeCommand("quarto.editInVisualMode"); + await wait(APPROX_TIME_TO_OPEN_VISUAL_EDITOR); + await vscode.commands.executeCommand("quarto.editInSourceMode"); + await wait(300); + + const after = doc.getText(); + + return { before, after }; +} diff --git a/apps/vscode/src/test/test-utils.ts b/apps/vscode/src/test/test-utils.ts index f395c704..0f878c82 100644 --- a/apps/vscode/src/test/test-utils.ts +++ b/apps/vscode/src/test/test-utils.ts @@ -13,36 +13,12 @@ export const EXTENSION_ROOT_DIR = export const TEST_PATH = path.join(EXTENSION_ROOT_DIR, "src", "test"); export const WORKSPACE_PATH = path.join(TEST_PATH, "examples"); +export const WORKSPACE_OUT_PATH = path.join(TEST_PATH, "examples-out"); -export function exampleWorkspacePath(file: string): string { - return path.join(WORKSPACE_PATH, file); -} -export function exampleWorkspaceOutPath(file: string): string { - return path.join(WORKSPACE_PATH, 'examples-out', file); +export function examplesOutUri(fileName: string = ''): vscode.Uri { + return vscode.Uri.file(path.join(WORKSPACE_OUT_PATH, fileName)); } export function wait(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } - -export async function copyFile( - sourcePath: string, - destPath: string, -): Promise { - try { - const wsedit = new vscode.WorkspaceEdit(); - const data = await vscode.workspace.fs.readFile( - vscode.Uri.file(sourcePath) - ); - const destFileUri = vscode.Uri.file(destPath); - wsedit.createFile(destFileUri, { ignoreIfExists: true }); - - await vscode.workspace.fs.writeFile(destFileUri, data); - - let isDone = await vscode.workspace.applyEdit(wsedit); - if (isDone) return true; - else return false; - } catch (err) { - return false; - } -}