git.iko.soy/rowtype-yoga/purescript-yoga-react-native
on v0.1.0 help sign in
344 lines 11 kB history raw
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";
5import {
6 copyToClipboardImpl,
7 readClipboardImpl,
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";
11import {
12 playSoundImpl,
13 beepImpl,
14} from "../src/Yoga/React/Native/MacOS/Sound.js";
15import {
16 setStatusBarItemImpl,
17 removeStatusBarItemImpl,
18} from "../src/Yoga/React/Native/MacOS/StatusBarItem.js";
19import { previewImpl } from "../src/Yoga/React/Native/MacOS/QuickLook.js";
20import {
21 sayImpl,
22 sayWithVoiceImpl,
23 stopSpeakingImpl,
24} from "../src/Yoga/React/Native/MacOS/SpeechSynthesizer.js";
25import {
26 showColorPanelImpl,
27 hideColorPanelImpl,
28} from "../src/Yoga/React/Native/MacOS/ColorPanel.js";
29import {
30 showFontPanelImpl,
31 hideFontPanelImpl,
32} from "../src/Yoga/React/Native/MacOS/FontPanel.js";
33import { recognizeTextImpl } from "../src/Yoga/React/Native/MacOS/OCR.js";
34import {
35 startImpl,
36 stopImpl,
37 pollTranscriptImpl,
38} from "../src/Yoga/React/Native/MacOS/SpeechRecognition.js";
39import {
40 detectLanguageImpl,
41 analyzeSentimentImpl,
42 tokenizeImpl,
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", [
50 "OK",
51 "Cancel",
52 ]);
53 spy.mockRestore();
54 });
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", [
60 "Retry",
61 ]);
62 spy.mockRestore();
63 });
65 it("alertImpl does not throw with empty buttons", () => {
66 expect(() => alertImpl("informational", "Info", "Note", [])).not.toThrow();
67 });
68});
70describe("macOS Menu FFI", () => {
71 it("showMenuImpl calls NativeModules.MacOSMenuModule.show with items", () => {
72 const spy = vi.spyOn(NativeModules.MacOSMenuModule, "show");
73 const items = [
74 { title: "Cut", id: "cut" },
75 { title: "Copy", id: "copy" },
76 ];
77 const callback = (_id) => () => {};
78 showMenuImpl(items, callback);
79 expect(spy).toHaveBeenCalledWith(items);
80 spy.mockRestore();
81 });
83 it("showMenuImpl invokes callback when item selected", async () => {
84 const selectedId = "paste";
85 vi.spyOn(NativeModules.MacOSMenuModule, "show").mockResolvedValueOnce(
86 selectedId,
87 );
88 let result = "";
89 const callback = (id) => () => {
90 result = id;
91 };
92 showMenuImpl([{ title: "Paste", id: "paste" }], callback);
93 await new Promise((r) => setTimeout(r, 10));
94 expect(result).toBe("paste");
95 });
97 it("showMenuImpl does not invoke callback when no item selected", async () => {
98 vi.spyOn(NativeModules.MacOSMenuModule, "show").mockResolvedValueOnce("");
99 let called = false;
100 const callback = (_id) => () => {
101 called = true;
102 };
103 showMenuImpl([{ title: "Save", id: "save" }], callback);
104 await new Promise((r) => setTimeout(r, 10));
105 expect(called).toBe(false);
106 });
107});
109describe("macOS Pasteboard FFI", () => {
110 it("copyToClipboardImpl does not throw", () => {
111 expect(() => copyToClipboardImpl("Hello from tests")).not.toThrow();
112 });
114 it("readClipboardImpl does not throw", () => {
115 expect(() => readClipboardImpl()).not.toThrow();
116 });
117});
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"]);
124 spy.mockRestore();
125 });
127 it("shareImpl does not throw with empty array", () => {
128 expect(() => shareImpl([])).not.toThrow();
129 });
130});
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");
137 spy.mockRestore();
138 });
139});
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");
146 spy.mockRestore();
147 });
149 it("beepImpl calls NativeModules.MacOSSoundModule.beep", () => {
150 const spy = vi.spyOn(NativeModules.MacOSSoundModule, "beep");
151 beepImpl();
152 expect(spy).toHaveBeenCalled();
153 spy.mockRestore();
154 });
155});
157describe("macOS StatusBarItem FFI", () => {
158 it("setStatusBarItemImpl calls NativeModules.MacOSStatusBarModule.set", () => {
159 const spy = vi.spyOn(NativeModules.MacOSStatusBarModule, "set");
160 const config = {
161 title: "Test",
162 sfSymbol: "star",
163 menuItems: [{ id: "a", title: "Item A" }],
164 };
165 setStatusBarItemImpl(config);
166 expect(spy).toHaveBeenCalledWith(config);
167 spy.mockRestore();
168 });
170 it("removeStatusBarItemImpl calls NativeModules.MacOSStatusBarModule.remove", () => {
171 const spy = vi.spyOn(NativeModules.MacOSStatusBarModule, "remove");
172 removeStatusBarItemImpl();
173 expect(spy).toHaveBeenCalled();
174 spy.mockRestore();
175 });
176});
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");
183 spy.mockRestore();
184 });
185});
187describe("macOS SpeechSynthesizer FFI", () => {
188 it("sayImpl calls NativeModules.MacOSSpeechModule.say", () => {
189 const spy = vi.spyOn(NativeModules.MacOSSpeechModule, "say");
190 sayImpl("Hello");
191 expect(spy).toHaveBeenCalledWith("Hello");
192 spy.mockRestore();
193 });
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");
199 spy.mockRestore();
200 });
202 it("stopSpeakingImpl calls NativeModules.MacOSSpeechModule.stop", () => {
203 const spy = vi.spyOn(NativeModules.MacOSSpeechModule, "stop");
204 stopSpeakingImpl();
205 expect(spy).toHaveBeenCalled();
206 spy.mockRestore();
207 });
208});
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();
215 spy.mockRestore();
216 });
218 it("hideColorPanelImpl calls NativeModules.MacOSColorPanelModule.hide", () => {
219 const spy = vi.spyOn(NativeModules.MacOSColorPanelModule, "hide");
220 hideColorPanelImpl();
221 expect(spy).toHaveBeenCalled();
222 spy.mockRestore();
223 });
224});
226describe("macOS FontPanel FFI", () => {
227 it("showFontPanelImpl calls NativeModules.MacOSFontPanelModule.show", () => {
228 const spy = vi.spyOn(NativeModules.MacOSFontPanelModule, "show");
229 showFontPanelImpl();
230 expect(spy).toHaveBeenCalled();
231 spy.mockRestore();
232 });
234 it("hideFontPanelImpl calls NativeModules.MacOSFontPanelModule.hide", () => {
235 const spy = vi.spyOn(NativeModules.MacOSFontPanelModule, "hide");
236 hideFontPanelImpl();
237 expect(spy).toHaveBeenCalled();
238 spy.mockRestore();
239 });
240});
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");
246 let result = "";
247 aff(
248 (err) => {},
249 (val) => {
250 result = val;
251 },
252 );
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");
256 spy.mockRestore();
257 });
258});
260describe("macOS SpeechRecognition FFI", () => {
261 it("startImpl calls NativeModules.MacOSSpeechRecognitionModule.start", () => {
262 const spy = vi.spyOn(NativeModules.MacOSSpeechRecognitionModule, "start");
263 startImpl();
264 expect(spy).toHaveBeenCalled();
265 spy.mockRestore();
266 });
268 it("stopImpl calls stop and invokes callback with transcript", async () => {
269 const spy = vi.spyOn(NativeModules.MacOSSpeechRecognitionModule, "stop");
270 let result = "";
271 stopImpl((text) => () => {
272 result = text;
273 });
274 await new Promise((r) => setTimeout(r, 10));
275 expect(spy).toHaveBeenCalled();
276 expect(result).toBe("final transcript");
277 spy.mockRestore();
278 });
280 it("pollTranscriptImpl calls getTranscript and invokes callback", async () => {
281 const spy = vi.spyOn(
282 NativeModules.MacOSSpeechRecognitionModule,
283 "getTranscript",
284 );
285 let result = "";
286 pollTranscriptImpl((text) => () => {
287 result = text;
288 });
289 await new Promise((r) => setTimeout(r, 10));
290 expect(spy).toHaveBeenCalled();
291 expect(result).toBe("partial transcript");
292 spy.mockRestore();
293 });
294});
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");
300 let result = "";
301 aff(
302 (err) => {},
303 (val) => {
304 result = val;
305 },
306 );
307 await new Promise((r) => setTimeout(r, 10));
308 expect(spy).toHaveBeenCalledWith("Hello world");
309 expect(result).toBe("en");
310 spy.mockRestore();
311 });
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");
316 let result = -1;
317 aff(
318 (err) => {},
319 (val) => {
320 result = val;
321 },
322 );
323 await new Promise((r) => setTimeout(r, 10));
324 expect(spy).toHaveBeenCalledWith("I love this");
325 expect(result).toBe(0.5);
326 spy.mockRestore();
327 });
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");
332 let result = [];
333 aff(
334 (err) => {},
335 (val) => {
336 result = val;
337 },
338 );
339 await new Promise((r) => setTimeout(r, 10));
340 expect(spy).toHaveBeenCalledWith("Hello world");
341 expect(result).toEqual(["Hello", "world"]);
342 spy.mockRestore();
343 });
344});