1import { describe, it, expect, vi } from "vitest";
2import { NativeModules } from "react-native";
3import { alertImpl } from "../src/Yoga/React/Native/MacOS/Alert.js";
4import { showMenuImpl } from "../src/Yoga/React/Native/MacOS/Menu.js";
8} from "../src/Yoga/React/Native/MacOS/Pasteboard.js";
9import { shareImpl } from "../src/Yoga/React/Native/MacOS/ShareService.js";
10import { notifyImpl } from "../src/Yoga/React/Native/MacOS/UserNotification.js";
14} from "../src/Yoga/React/Native/MacOS/Sound.js";
17 removeStatusBarItemImpl,
18} from "../src/Yoga/React/Native/MacOS/StatusBarItem.js";
19import { previewImpl } from "../src/Yoga/React/Native/MacOS/QuickLook.js";
24} from "../src/Yoga/React/Native/MacOS/SpeechSynthesizer.js";
28} from "../src/Yoga/React/Native/MacOS/ColorPanel.js";
32} from "../src/Yoga/React/Native/MacOS/FontPanel.js";
33import { recognizeTextImpl } from "../src/Yoga/React/Native/MacOS/OCR.js";
38} from "../src/Yoga/React/Native/MacOS/SpeechRecognition.js";
43} from "../src/Yoga/React/Native/MacOS/NaturalLanguage.js";
45describe("macOS Alert FFI", () => {
46 it("alertImpl calls NativeModules.MacOSAlertModule.show", () => {
47 const spy = vi.spyOn(NativeModules.MacOSAlertModule, "show");
48 alertImpl("warning", "Title", "Message", ["OK", "Cancel"]);
49 expect(spy).toHaveBeenCalledWith("warning", "Title", "Message", [
56 it("alertImpl passes style through", () => {
57 const spy = vi.spyOn(NativeModules.MacOSAlertModule, "show");
58 alertImpl("critical", "Error", "Something broke", ["Retry"]);
59 expect(spy).toHaveBeenCalledWith("critical", "Error", "Something broke", [
65 it("alertImpl does not throw with empty buttons", () => {
66 expect(() => alertImpl("informational", "Info", "Note", [])).not.toThrow();
70describe("macOS Menu FFI", () => {
71 it("showMenuImpl calls NativeModules.MacOSMenuModule.show with items", () => {
72 const spy = vi.spyOn(NativeModules.MacOSMenuModule, "show");
74 { title: "Cut", id: "cut" },
75 { title: "Copy", id: "copy" },
77 const callback = (_id) => () => {};
78 showMenuImpl(items, callback);
79 expect(spy).toHaveBeenCalledWith(items);
83 it("showMenuImpl invokes callback when item selected", async () => {
84 const selectedId = "paste";
85 vi.spyOn(NativeModules.MacOSMenuModule, "show").mockResolvedValueOnce(
89 const callback = (id) => () => {
92 showMenuImpl([{ title: "Paste", id: "paste" }], callback);
93 await new Promise((r) => setTimeout(r, 10));
94 expect(result).toBe("paste");
97 it("showMenuImpl does not invoke callback when no item selected", async () => {
98 vi.spyOn(NativeModules.MacOSMenuModule, "show").mockResolvedValueOnce("");
100 const callback = (_id) => () => {
103 showMenuImpl([{ title: "Save", id: "save" }], callback);
104 await new Promise((r) => setTimeout(r, 10));
105 expect(called).toBe(false);
109describe("macOS Pasteboard FFI", () => {
110 it("copyToClipboardImpl does not throw", () => {
111 expect(() => copyToClipboardImpl("Hello from tests")).not.toThrow();
114 it("readClipboardImpl does not throw", () => {
115 expect(() => readClipboardImpl()).not.toThrow();
119describe("macOS ShareService FFI", () => {
120 it("shareImpl calls NativeModules.MacOSShareModule.share", () => {
121 const spy = vi.spyOn(NativeModules.MacOSShareModule, "share");
122 shareImpl(["Hello", "https://example.com"]);
123 expect(spy).toHaveBeenCalledWith(["Hello", "https://example.com"]);
127 it("shareImpl does not throw with empty array", () => {
128 expect(() => shareImpl([])).not.toThrow();
132describe("macOS UserNotification FFI", () => {
133 it("notifyImpl calls NativeModules.MacOSNotificationModule.notify", () => {
134 const spy = vi.spyOn(NativeModules.MacOSNotificationModule, "notify");
135 notifyImpl("Title", "Body");
136 expect(spy).toHaveBeenCalledWith("Title", "Body");
141describe("macOS Sound FFI", () => {
142 it("playSoundImpl calls NativeModules.MacOSSoundModule.play", () => {
143 const spy = vi.spyOn(NativeModules.MacOSSoundModule, "play");
144 playSoundImpl("Glass");
145 expect(spy).toHaveBeenCalledWith("Glass");
149 it("beepImpl calls NativeModules.MacOSSoundModule.beep", () => {
150 const spy = vi.spyOn(NativeModules.MacOSSoundModule, "beep");
152 expect(spy).toHaveBeenCalled();
157describe("macOS StatusBarItem FFI", () => {
158 it("setStatusBarItemImpl calls NativeModules.MacOSStatusBarModule.set", () => {
159 const spy = vi.spyOn(NativeModules.MacOSStatusBarModule, "set");
163 menuItems: [{ id: "a", title: "Item A" }],
165 setStatusBarItemImpl(config);
166 expect(spy).toHaveBeenCalledWith(config);
170 it("removeStatusBarItemImpl calls NativeModules.MacOSStatusBarModule.remove", () => {
171 const spy = vi.spyOn(NativeModules.MacOSStatusBarModule, "remove");
172 removeStatusBarItemImpl();
173 expect(spy).toHaveBeenCalled();
178describe("macOS QuickLook FFI", () => {
179 it("previewImpl calls NativeModules.MacOSQuickLookModule.preview", () => {
180 const spy = vi.spyOn(NativeModules.MacOSQuickLookModule, "preview");
181 previewImpl("/tmp/test.txt");
182 expect(spy).toHaveBeenCalledWith("/tmp/test.txt");
187describe("macOS SpeechSynthesizer FFI", () => {
188 it("sayImpl calls NativeModules.MacOSSpeechModule.say", () => {
189 const spy = vi.spyOn(NativeModules.MacOSSpeechModule, "say");
191 expect(spy).toHaveBeenCalledWith("Hello");
195 it("sayWithVoiceImpl calls NativeModules.MacOSSpeechModule.sayWithVoice", () => {
196 const spy = vi.spyOn(NativeModules.MacOSSpeechModule, "sayWithVoice");
197 sayWithVoiceImpl("Hello", "com.apple.voice.Alex");
198 expect(spy).toHaveBeenCalledWith("Hello", "com.apple.voice.Alex");
202 it("stopSpeakingImpl calls NativeModules.MacOSSpeechModule.stop", () => {
203 const spy = vi.spyOn(NativeModules.MacOSSpeechModule, "stop");
205 expect(spy).toHaveBeenCalled();
210describe("macOS ColorPanel FFI", () => {
211 it("showColorPanelImpl calls NativeModules.MacOSColorPanelModule.show", () => {
212 const spy = vi.spyOn(NativeModules.MacOSColorPanelModule, "show");
213 showColorPanelImpl();
214 expect(spy).toHaveBeenCalled();
218 it("hideColorPanelImpl calls NativeModules.MacOSColorPanelModule.hide", () => {
219 const spy = vi.spyOn(NativeModules.MacOSColorPanelModule, "hide");
220 hideColorPanelImpl();
221 expect(spy).toHaveBeenCalled();
226describe("macOS FontPanel FFI", () => {
227 it("showFontPanelImpl calls NativeModules.MacOSFontPanelModule.show", () => {
228 const spy = vi.spyOn(NativeModules.MacOSFontPanelModule, "show");
230 expect(spy).toHaveBeenCalled();
234 it("hideFontPanelImpl calls NativeModules.MacOSFontPanelModule.hide", () => {
235 const spy = vi.spyOn(NativeModules.MacOSFontPanelModule, "hide");
237 expect(spy).toHaveBeenCalled();
242describe("macOS OCR FFI", () => {
243 it("recognizeTextImpl returns an Aff that calls NativeModules.MacOSOCRModule.recognize", async () => {
244 const spy = vi.spyOn(NativeModules.MacOSOCRModule, "recognize");
245 const aff = recognizeTextImpl("/tmp/test.png");
253 await new Promise((r) => setTimeout(r, 10));
254 expect(spy).toHaveBeenCalledWith("/tmp/test.png");
255 expect(result).toBe("Recognized text from /tmp/test.png");
260describe("macOS SpeechRecognition FFI", () => {
261 it("startImpl calls NativeModules.MacOSSpeechRecognitionModule.start", () => {
262 const spy = vi.spyOn(NativeModules.MacOSSpeechRecognitionModule, "start");
264 expect(spy).toHaveBeenCalled();
268 it("stopImpl calls stop and invokes callback with transcript", async () => {
269 const spy = vi.spyOn(NativeModules.MacOSSpeechRecognitionModule, "stop");
271 stopImpl((text) => () => {
274 await new Promise((r) => setTimeout(r, 10));
275 expect(spy).toHaveBeenCalled();
276 expect(result).toBe("final transcript");
280 it("pollTranscriptImpl calls getTranscript and invokes callback", async () => {
281 const spy = vi.spyOn(
282 NativeModules.MacOSSpeechRecognitionModule,
286 pollTranscriptImpl((text) => () => {
289 await new Promise((r) => setTimeout(r, 10));
290 expect(spy).toHaveBeenCalled();
291 expect(result).toBe("partial transcript");
296describe("macOS NaturalLanguage FFI", () => {
297 it("detectLanguageImpl returns an Aff that resolves with language code", async () => {
298 const spy = vi.spyOn(NativeModules.MacOSNLModule, "detectLanguage");
299 const aff = detectLanguageImpl("Hello world");
307 await new Promise((r) => setTimeout(r, 10));
308 expect(spy).toHaveBeenCalledWith("Hello world");
309 expect(result).toBe("en");
313 it("analyzeSentimentImpl returns an Aff that resolves with score", async () => {
314 const spy = vi.spyOn(NativeModules.MacOSNLModule, "sentiment");
315 const aff = analyzeSentimentImpl("I love this");
323 await new Promise((r) => setTimeout(r, 10));
324 expect(spy).toHaveBeenCalledWith("I love this");
325 expect(result).toBe(0.5);
329 it("tokenizeImpl returns an Aff that resolves with tokens", async () => {
330 const spy = vi.spyOn(NativeModules.MacOSNLModule, "tokenize");
331 const aff = tokenizeImpl("Hello world");
339 await new Promise((r) => setTimeout(r, 10));
340 expect(spy).toHaveBeenCalledWith("Hello world");
341 expect(result).toEqual(["Hello", "world"]);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list