Enhance documentation, implement Twilio OTP delivery, and update payment gateway methods. Updated AGENTS.md and README.md for clarity on ExecPlans and architecture. Added Twilio as a dependency and implemented capture/refund methods in MoyasarGateway. Improved frontend routing with react-router-dom and added authentication context. Updated styles and localization files for better user experience.

This commit is contained in:
2026-02-28 15:33:50 +03:00
parent 86fd07c778
commit a1da918f95
37 changed files with 1645 additions and 277 deletions
+60
View File
@@ -0,0 +1,60 @@
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { vi } from "vitest";
import { BrowserRouter } from "react-router-dom";
import LoginPage from "./LoginPage";
import { AuthProvider } from "../contexts/AuthContext";
import i18n from "../i18n";
vi.mock("../api/client", async (importOriginal) => {
const actual = await importOriginal();
return { ...actual, apiPost: vi.fn() };
});
const { apiPost } = await import("../api/client");
function renderLogin() {
return render(
<AuthProvider>
<BrowserRouter>
<LoginPage />
</BrowserRouter>
</AuthProvider>
);
}
describe("LoginPage", () => {
beforeEach(async () => {
vi.clearAllMocks();
await i18n.changeLanguage("en");
});
it("renders phone input and send code button", () => {
renderLogin();
expect(screen.getByLabelText(/phone number/i)).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Send code" })).toBeInTheDocument();
});
it("shows verify step after successful OTP request", async () => {
apiPost.mockResolvedValueOnce({ request_id: "abc-123", expires_at: "2025-01-01T12:00:00Z" });
renderLogin();
fireEvent.change(screen.getByLabelText(/phone number/i), { target: { value: "+966512345678" } });
fireEvent.click(screen.getByRole("button", { name: "Send code" }));
await waitFor(() => {
expect(screen.getByLabelText(/verification code/i)).toBeInTheDocument();
});
});
it("shows error when OTP request fails", async () => {
apiPost.mockRejectedValueOnce(new Error("Rate limited"));
renderLogin();
fireEvent.change(screen.getByLabelText(/phone number/i), { target: { value: "+966512345678" } });
fireEvent.click(screen.getByRole("button", { name: "Send code" }));
await waitFor(() => {
expect(screen.getByText("Rate limited")).toBeInTheDocument();
});
});
});