mocks.cjs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. 'use strict';
  2. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  3. // SPDX-License-Identifier: Apache-2.0
  4. // SPDX-License-Identifier: MIT
  5. /**
  6. * Intercepts all IPC requests with the given mock handler.
  7. *
  8. * This function can be used when testing tauri frontend applications or when running the frontend in a Node.js context during static site generation.
  9. *
  10. * # Examples
  11. *
  12. * Testing setup using vitest:
  13. * ```js
  14. * import { mockIPC, clearMocks } from "@tauri-apps/api/mocks"
  15. * import { invoke } from "@tauri-apps/api/tauri"
  16. *
  17. * afterEach(() => {
  18. * clearMocks()
  19. * })
  20. *
  21. * test("mocked command", () => {
  22. * mockIPC((cmd, args) => {
  23. * switch (cmd) {
  24. * case "add":
  25. * return (args.a as number) + (args.b as number);
  26. * default:
  27. * break;
  28. * }
  29. * });
  30. *
  31. * expect(invoke('add', { a: 12, b: 15 })).resolves.toBe(27);
  32. * })
  33. * ```
  34. *
  35. * The callback function can also return a Promise:
  36. * ```js
  37. * import { mockIPC, clearMocks } from "@tauri-apps/api/mocks"
  38. * import { invoke } from "@tauri-apps/api/tauri"
  39. *
  40. * afterEach(() => {
  41. * clearMocks()
  42. * })
  43. *
  44. * test("mocked command", () => {
  45. * mockIPC((cmd, args) => {
  46. * if(cmd === "get_data") {
  47. * return fetch("https://example.com/data.json")
  48. * .then((response) => response.json())
  49. * }
  50. * });
  51. *
  52. * expect(invoke('get_data')).resolves.toBe({ foo: 'bar' });
  53. * })
  54. * ```
  55. *
  56. * @since 1.0.0
  57. */
  58. function mockIPC(cb) {
  59. // eslint-disable-next-line @typescript-eslint/no-misused-promises
  60. window.__TAURI_IPC__ = async ({ cmd, callback, error, ...args }) => {
  61. try {
  62. // @ts-expect-error The function key is dynamic and therefore not typed
  63. // eslint-disable-next-line @typescript-eslint/no-unsafe-call
  64. window[`_${callback}`](await cb(cmd, args));
  65. }
  66. catch (err) {
  67. // @ts-expect-error The function key is dynamic and therefore not typed
  68. // eslint-disable-next-line @typescript-eslint/no-unsafe-call
  69. window[`_${error}`](err);
  70. }
  71. };
  72. }
  73. /**
  74. * Mocks one or many window labels.
  75. * In non-tauri context it is required to call this function *before* using the `@tauri-apps/api/window` module.
  76. *
  77. * This function only mocks the *presence* of windows,
  78. * window properties (e.g. width and height) can be mocked like regular IPC calls using the `mockIPC` function.
  79. *
  80. * # Examples
  81. *
  82. * ```js
  83. * import { mockWindows } from "@tauri-apps/api/mocks";
  84. * import { getCurrent } from "@tauri-apps/api/window";
  85. *
  86. * mockWindows("main", "second", "third");
  87. *
  88. * const win = getCurrent();
  89. *
  90. * win.label // "main"
  91. * ```
  92. *
  93. * ```js
  94. * import { mockWindows } from "@tauri-apps/api/mocks";
  95. *
  96. * mockWindows("main", "second", "third");
  97. *
  98. * mockIPC((cmd, args) => {
  99. * if (cmd === "tauri") {
  100. * if (
  101. * args?.__tauriModule === "Window" &&
  102. * args?.message?.cmd === "manage" &&
  103. * args?.message?.data?.cmd?.type === "close"
  104. * ) {
  105. * console.log('closing window!');
  106. * }
  107. * }
  108. * });
  109. *
  110. * const { getCurrent } = await import("@tauri-apps/api/window");
  111. *
  112. * const win = getCurrent();
  113. * await win.close(); // this will cause the mocked IPC handler to log to the console.
  114. * ```
  115. *
  116. * @param current Label of window this JavaScript context is running in.
  117. * @param additionalWindows Label of additional windows the app has.
  118. *
  119. * @since 1.0.0
  120. */
  121. function mockWindows(current, ...additionalWindows) {
  122. window.__TAURI_METADATA__ = {
  123. __windows: [current, ...additionalWindows].map((label) => ({ label })),
  124. __currentWindow: { label: current }
  125. };
  126. }
  127. /**
  128. * Mock `convertFileSrc` function
  129. *
  130. *
  131. * @example
  132. * ```js
  133. * import { mockConvertFileSrc } from "@tauri-apps/api/mocks";
  134. * import { convertFileSrc } from "@tauri-apps/api/tauri";
  135. *
  136. * mockConvertFileSrc("windows")
  137. *
  138. * const url = convertFileSrc("C:\\Users\\user\\file.txt")
  139. * ```
  140. *
  141. * @param osName The operating system to mock, can be one of linux, macos, or windows
  142. * @param windowsProtocolScheme The scheme to use on Windows, can be either `http` or `https` and defaults to `https`
  143. *
  144. * @since 1.6.0
  145. */
  146. function mockConvertFileSrc(osName, windowsProtocolScheme = 'https') {
  147. var _a;
  148. window.__TAURI__ = (_a = window.__TAURI__) !== null && _a !== void 0 ? _a : {};
  149. window.__TAURI__.convertFileSrc = function (filePath, protocol = 'asset') {
  150. const path = encodeURIComponent(filePath);
  151. return osName === 'windows'
  152. ? `${windowsProtocolScheme}://${protocol}.localhost/${path}`
  153. : `${protocol}://localhost/${path}`;
  154. };
  155. }
  156. /**
  157. * Clears mocked functions/data injected by the other functions in this module.
  158. * When using a test runner that doesn't provide a fresh window object for each test, calling this function will reset tauri specific properties.
  159. *
  160. * # Example
  161. *
  162. * ```js
  163. * import { mockWindows, clearMocks } from "@tauri-apps/api/mocks"
  164. *
  165. * afterEach(() => {
  166. * clearMocks()
  167. * })
  168. *
  169. * test("mocked windows", () => {
  170. * mockWindows("main", "second", "third");
  171. *
  172. * expect(window).toHaveProperty("__TAURI_METADATA__")
  173. * })
  174. *
  175. * test("no mocked windows", () => {
  176. * expect(window).not.toHaveProperty("__TAURI_METADATA__")
  177. * })
  178. * ```
  179. *
  180. * @since 1.0.0
  181. */
  182. function clearMocks() {
  183. var _a;
  184. // @ts-expect-error "The operand of a 'delete' operator must be optional' does not matter in this case
  185. if ((_a = window.__TAURI__) === null || _a === void 0 ? void 0 : _a.convertFileSrc)
  186. delete window.__TAURI__.convertFileSrc;
  187. // @ts-expect-error "The operand of a 'delete' operator must be optional' does not matter in this case
  188. if (window.__TAURI_IPC__)
  189. delete window.__TAURI_IPC__;
  190. // @ts-expect-error "The operand of a 'delete' operator must be optional' does not matter in this case
  191. if (window.__TAURI_METADATA__)
  192. delete window.__TAURI_METADATA__;
  193. }
  194. exports.clearMocks = clearMocks;
  195. exports.mockConvertFileSrc = mockConvertFileSrc;
  196. exports.mockIPC = mockIPC;
  197. exports.mockWindows = mockWindows;