feat(f8): isAuthorable + widened selectionRejection (file|untitled)
Spec §6.4: replace the scheme!=file / !isUnderRoot rejections with a single !isAuthorable branch. isUnderRoot retained as a routing input. Per-condition messaging (#24) kept for no-editor / empty-selection / non-{file,untitled}. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+26
-21
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { isUnderRoot, selectionRejection } from "../src/workspacePath";
|
||||
import { isAuthorable, isUnderRoot, selectionRejection } from "../src/workspacePath";
|
||||
|
||||
describe("isUnderRoot", () => {
|
||||
const root = "/a/vscode-cowriting-plugin/sandbox";
|
||||
@@ -24,32 +24,37 @@ describe("isUnderRoot", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("selectionRejection", () => {
|
||||
const root = "/ws";
|
||||
const ok = { hasEditor: true, selectionEmpty: false, scheme: "file", fsPath: "/ws/a.md", root };
|
||||
|
||||
it("returns null when everything is valid", () => {
|
||||
expect(selectionRejection(ok)).toBeNull();
|
||||
describe("isAuthorable", () => {
|
||||
it("accepts file: and untitled: schemes", () => {
|
||||
expect(isAuthorable("file")).toBe(true);
|
||||
expect(isAuthorable("untitled")).toBe(true);
|
||||
});
|
||||
it("rejects read-only / virtual schemes", () => {
|
||||
expect(isAuthorable("git")).toBe(false);
|
||||
expect(isAuthorable("output")).toBe(false);
|
||||
expect(isAuthorable("cowriting-baseline")).toBe(false);
|
||||
expect(isAuthorable("")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("selectionRejection — F8 widened (accepts out-of-folder + untitled)", () => {
|
||||
const ok = { hasEditor: true, selectionEmpty: false, scheme: "file" };
|
||||
|
||||
it("accepts an in-folder / out-of-folder file (file: scheme)", () => {
|
||||
expect(selectionRejection({ ...ok, scheme: "file" })).toBeNull();
|
||||
});
|
||||
it("accepts an untitled buffer (no longer rejected)", () => {
|
||||
expect(selectionRejection({ ...ok, scheme: "untitled" })).toBeNull();
|
||||
});
|
||||
it("names the missing editor", () => {
|
||||
const msg = selectionRejection({ ...ok, hasEditor: false });
|
||||
expect(msg).toMatch(/focus a text editor/i);
|
||||
expect(selectionRejection({ ...ok, hasEditor: false })).toMatch(/focus a text editor/i);
|
||||
});
|
||||
|
||||
it("names the empty selection (only when there IS an editor)", () => {
|
||||
const msg = selectionRejection({ ...ok, selectionEmpty: true });
|
||||
expect(msg).toMatch(/select some text/i);
|
||||
expect(selectionRejection({ ...ok, selectionEmpty: true })).toMatch(/select some text/i);
|
||||
});
|
||||
|
||||
it("names an unsaved/non-file document", () => {
|
||||
const msg = selectionRejection({ ...ok, scheme: "untitled" });
|
||||
expect(msg).toMatch(/save this document/i);
|
||||
});
|
||||
|
||||
it("names an out-of-workspace file (the reported bug — NOT a selection problem)", () => {
|
||||
const msg = selectionRejection({ ...ok, fsPath: "/elsewhere/a.md" });
|
||||
expect(msg).toMatch(/outside your workspace folder/i);
|
||||
it("rejects a non-{file,untitled} scheme with its own message (not 'select some text')", () => {
|
||||
const msg = selectionRejection({ ...ok, scheme: "git" });
|
||||
expect(msg).toMatch(/can.?t be edited|read-only|not a file/i);
|
||||
expect(msg).not.toMatch(/select some text/i);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user