29 changed files with 511 additions and 167 deletions
-
43WEBVIEW_ACTION_DOWNLOAD.md
-
3src/app/request-accepted/page.tsx
-
186src/components/Componentes/navigation-button.tsx
-
111src/components/Componentes/subscription-required-sheet.tsx
-
191src/lib/webview-actions.test.ts
-
6src/translations/locales/ar.json
-
6src/translations/locales/az.json
-
6src/translations/locales/bn.json
-
6src/translations/locales/da.json
-
6src/translations/locales/de.json
-
6src/translations/locales/en.json
-
6src/translations/locales/es.json
-
6src/translations/locales/fa.json
-
6src/translations/locales/fr.json
-
6src/translations/locales/gu.json
-
6src/translations/locales/ha.json
-
6src/translations/locales/he.json
-
6src/translations/locales/hi.json
-
6src/translations/locales/id.json
-
6src/translations/locales/ks.json
-
6src/translations/locales/pt.json
-
6src/translations/locales/ru.json
-
6src/translations/locales/sw.json
-
6src/translations/locales/tg.json
-
6src/translations/locales/tr.json
-
6src/translations/locales/ul.json
-
6src/translations/locales/ur.json
-
6src/translations/locales/uz.json
-
6src/translations/locales/zh.json
@ -0,0 +1,191 @@ |
|||||
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
||||
|
import { |
||||
|
buyHabibCoinPackages, |
||||
|
copyToClipboard, |
||||
|
downloadFile, |
||||
|
isInFlutterWebView, |
||||
|
openExternalUrl, |
||||
|
postActionToFlutter, |
||||
|
uploadFile, |
||||
|
} from "./webview-actions"; |
||||
|
|
||||
|
describe("webview-actions", () => { |
||||
|
const originalHabibApp = window.HabibApp; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
vi.restoreAllMocks(); |
||||
|
}); |
||||
|
|
||||
|
afterEach(() => { |
||||
|
window.HabibApp = originalHabibApp; |
||||
|
}); |
||||
|
|
||||
|
describe("isInFlutterWebView", () => { |
||||
|
it("returns true when window.HabibApp.postMessage is defined", () => { |
||||
|
window.HabibApp = { postMessage: vi.fn() }; |
||||
|
expect(isInFlutterWebView()).toBe(true); |
||||
|
}); |
||||
|
|
||||
|
it("returns false when window.HabibApp is undefined", () => { |
||||
|
delete (window as any).HabibApp; |
||||
|
expect(isInFlutterWebView()).toBe(false); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe("postActionToFlutter", () => { |
||||
|
it("sends message without data when data is omitted", () => { |
||||
|
const mockPostMessage = vi.fn(); |
||||
|
window.HabibApp = { postMessage: mockPostMessage }; |
||||
|
|
||||
|
const result = postActionToFlutter("custom_action"); |
||||
|
expect(result).toBe(true); |
||||
|
expect(mockPostMessage).toHaveBeenCalledTimes(1); |
||||
|
expect(mockPostMessage).toHaveBeenCalledWith( |
||||
|
JSON.stringify({ action: "custom_action" }), |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it("sends message with data when data is provided", () => { |
||||
|
const mockPostMessage = vi.fn(); |
||||
|
window.HabibApp = { postMessage: mockPostMessage }; |
||||
|
|
||||
|
const result = postActionToFlutter("custom_action", { foo: "bar" }); |
||||
|
expect(result).toBe(true); |
||||
|
expect(mockPostMessage).toHaveBeenCalledWith( |
||||
|
JSON.stringify({ action: "custom_action", data: { foo: "bar" } }), |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it("returns false and does not throw when not in flutter webview", () => { |
||||
|
delete (window as any).HabibApp; |
||||
|
const result = postActionToFlutter("custom_action"); |
||||
|
expect(result).toBe(false); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe("buyHabibCoinPackages", () => { |
||||
|
it("dispatches buy_coin action to Flutter and returns true", () => { |
||||
|
const mockPostMessage = vi.fn(); |
||||
|
window.HabibApp = { postMessage: mockPostMessage }; |
||||
|
|
||||
|
const result = buyHabibCoinPackages(); |
||||
|
expect(result).toBe(true); |
||||
|
expect(mockPostMessage).toHaveBeenCalledTimes(1); |
||||
|
expect(mockPostMessage).toHaveBeenCalledWith( |
||||
|
JSON.stringify({ action: "buy_coin" }), |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it("returns false when not running in Flutter WebView", () => { |
||||
|
delete (window as any).HabibApp; |
||||
|
const result = buyHabibCoinPackages(); |
||||
|
expect(result).toBe(false); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe("downloadFile", () => { |
||||
|
it("dispatches download_file action with options", () => { |
||||
|
const mockPostMessage = vi.fn(); |
||||
|
window.HabibApp = { postMessage: mockPostMessage }; |
||||
|
|
||||
|
const result = downloadFile({ |
||||
|
url: "https://example.com/file.pdf", |
||||
|
fileName: "file.pdf", |
||||
|
mimeType: "application/pdf", |
||||
|
fileType: "document", |
||||
|
}); |
||||
|
|
||||
|
expect(result).toBe(true); |
||||
|
expect(mockPostMessage).toHaveBeenCalledWith( |
||||
|
JSON.stringify({ |
||||
|
action: "download_file", |
||||
|
data: { |
||||
|
url: "https://example.com/file.pdf", |
||||
|
fileName: "file.pdf", |
||||
|
mimeType: "application/pdf", |
||||
|
fileType: "document", |
||||
|
}, |
||||
|
}), |
||||
|
); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe("copyToClipboard", () => { |
||||
|
it("dispatches copy_to_clipboard in Flutter WebView", async () => { |
||||
|
const mockPostMessage = vi.fn(); |
||||
|
window.HabibApp = { postMessage: mockPostMessage }; |
||||
|
|
||||
|
const result = await copyToClipboard("sample text", "invite_code"); |
||||
|
expect(result).toBe(true); |
||||
|
expect(mockPostMessage).toHaveBeenCalledWith( |
||||
|
JSON.stringify({ |
||||
|
action: "copy_to_clipboard", |
||||
|
data: { |
||||
|
text: "sample text", |
||||
|
label: "invite_code", |
||||
|
showToast: true, |
||||
|
}, |
||||
|
}), |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it("falls back to navigator.clipboard.writeText when outside WebView", async () => { |
||||
|
delete (window as any).HabibApp; |
||||
|
const writeTextMock = vi.fn().mockResolvedValue(undefined); |
||||
|
Object.assign(navigator, { |
||||
|
clipboard: { writeText: writeTextMock }, |
||||
|
}); |
||||
|
|
||||
|
const result = await copyToClipboard("sample text"); |
||||
|
expect(result).toBe(true); |
||||
|
expect(writeTextMock).toHaveBeenCalledWith("sample text"); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe("openExternalUrl", () => { |
||||
|
it("dispatches open_external_url action to Flutter", () => { |
||||
|
const mockPostMessage = vi.fn(); |
||||
|
window.HabibApp = { postMessage: mockPostMessage }; |
||||
|
|
||||
|
const result = openExternalUrl({ url: "https://habibapp.com" }); |
||||
|
expect(result).toBe(true); |
||||
|
expect(mockPostMessage).toHaveBeenCalledWith( |
||||
|
JSON.stringify({ |
||||
|
action: "open_external_url", |
||||
|
data: { |
||||
|
mode: "externalApplication", |
||||
|
showErrorToast: true, |
||||
|
url: "https://habibapp.com", |
||||
|
}, |
||||
|
}), |
||||
|
); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe("uploadFile", () => { |
||||
|
it("dispatches upload_file action with options to Flutter", () => { |
||||
|
const mockPostMessage = vi.fn(); |
||||
|
window.HabibApp = { postMessage: mockPostMessage }; |
||||
|
|
||||
|
const result = uploadFile({ |
||||
|
mediaType: "image", |
||||
|
source: "gallery", |
||||
|
returnAs: "upload", |
||||
|
uploadUrl: "/api/upload", |
||||
|
}); |
||||
|
|
||||
|
expect(result).toBe(true); |
||||
|
expect(mockPostMessage).toHaveBeenCalledWith( |
||||
|
JSON.stringify({ |
||||
|
action: "upload_file", |
||||
|
data: { |
||||
|
mediaType: "image", |
||||
|
source: "gallery", |
||||
|
returnAs: "upload", |
||||
|
uploadUrl: "/api/upload", |
||||
|
}, |
||||
|
}), |
||||
|
); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue