b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
121 lines
3.3 KiB
TypeScript
121 lines
3.3 KiB
TypeScript
import { screen } from "@testing-library/react";
|
|
import Focus from "@tiptap/extension-focus";
|
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
import StarterKit from "@tiptap/starter-kit";
|
|
import * as React from "react";
|
|
import { describe, it, expect, vi } from "vitest";
|
|
|
|
import { render } from "./utils/render.js";
|
|
|
|
// Test wrapper to render editor with Focus extension
|
|
function TestEditor({ spotlightMode = false }: { spotlightMode?: boolean }) {
|
|
const editor = useEditor({
|
|
extensions: [
|
|
StarterKit,
|
|
Focus.configure({
|
|
className: "has-focus",
|
|
mode: "all",
|
|
}),
|
|
],
|
|
content: `
|
|
<p>First paragraph</p>
|
|
<p>Second paragraph</p>
|
|
<p>Third paragraph</p>
|
|
`,
|
|
immediatelyRender: true,
|
|
});
|
|
|
|
if (!editor) return <div data-testid="loading">Loading...</div>;
|
|
|
|
return (
|
|
<div className={spotlightMode ? "spotlight-mode" : ""} data-testid="editor-wrapper">
|
|
<style>{`
|
|
.spotlight-mode .ProseMirror > *:not(.has-focus) {
|
|
opacity: 0.3;
|
|
transition: opacity 0.2s ease;
|
|
}
|
|
.spotlight-mode .ProseMirror > .has-focus {
|
|
opacity: 1;
|
|
transition: opacity 0.2s ease;
|
|
}
|
|
`}</style>
|
|
<EditorContent editor={editor} data-testid="editor-content" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
describe("Editor Focus Mode", () => {
|
|
it("Focus extension is configured correctly", async () => {
|
|
void render(<TestEditor />);
|
|
|
|
// Wait for editor to initialize (not just loading state)
|
|
await vi.waitFor(
|
|
() => {
|
|
const wrapper = screen.queryByTestId("editor-wrapper");
|
|
expect(wrapper).toBeTruthy();
|
|
},
|
|
{ timeout: 2000 },
|
|
);
|
|
|
|
const editorContent = screen.getByTestId("editor-content");
|
|
expect(editorContent).toBeDefined();
|
|
|
|
// The editor should be rendered with ProseMirror
|
|
const proseMirror = editorContent.querySelector(".ProseMirror");
|
|
expect(proseMirror).toBeTruthy();
|
|
|
|
// Verify the editor has the correct structure (3 paragraphs)
|
|
const paragraphs = proseMirror?.querySelectorAll("p");
|
|
expect(paragraphs?.length).toBe(3);
|
|
});
|
|
|
|
it("spotlight mode applies CSS class to editor wrapper", async () => {
|
|
void render(<TestEditor spotlightMode={true} />);
|
|
|
|
// Wait for editor to initialize
|
|
await vi.waitFor(
|
|
() => {
|
|
const wrapper = screen.queryByTestId("editor-wrapper");
|
|
expect(wrapper).toBeTruthy();
|
|
},
|
|
{ timeout: 2000 },
|
|
);
|
|
|
|
const wrapper = screen.getByTestId("editor-wrapper");
|
|
expect(wrapper.classList.contains("spotlight-mode")).toBe(true);
|
|
});
|
|
|
|
it("non-spotlight mode does not have spotlight-mode class", async () => {
|
|
void render(<TestEditor spotlightMode={false} />);
|
|
|
|
// Wait for editor to initialize
|
|
await vi.waitFor(
|
|
() => {
|
|
const wrapper = screen.queryByTestId("editor-wrapper");
|
|
expect(wrapper).toBeTruthy();
|
|
},
|
|
{ timeout: 2000 },
|
|
);
|
|
|
|
const wrapper = screen.getByTestId("editor-wrapper");
|
|
expect(wrapper.classList.contains("spotlight-mode")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("Distraction-free mode state", () => {
|
|
it("can toggle between focus modes", () => {
|
|
// Simple state test - verifies the type and state pattern works
|
|
type FocusMode = "normal" | "spotlight";
|
|
|
|
let focusMode: FocusMode = "normal";
|
|
|
|
// Toggle to spotlight
|
|
focusMode = "spotlight";
|
|
expect(focusMode).toBe("spotlight");
|
|
|
|
// Toggle back to normal
|
|
focusMode = "normal";
|
|
expect(focusMode).toBe("normal");
|
|
});
|
|
});
|