feature/state-and-data-fetching #1

Merged
ilia merged 27 commits from feature/state-and-data-fetching into main 2026-03-24 08:02:20 +00:00
7 changed files with 89 additions and 0 deletions
Showing only changes of commit 9302013632 - Show all commits

View File

@@ -0,0 +1 @@
export * from "./login";

View File

@@ -0,0 +1,6 @@
export const LOGIN_API_ROUTE = "auth/login";
// MOCKS
export const MOCK_EMAIL = "test@test.com";
export const MOCK_PASSWORD = "password";
export const MOCK_TOKEN = "mock.access.token";

View File

@@ -0,0 +1,2 @@
export { login } from './login';
export { LOGIN_API_ROUTE } from './constants';

View File

@@ -0,0 +1,27 @@
import { http, HttpResponse } from "msw";
import type { AuthData } from "../../../model/types/service";
import { BASE_URL } from "shared/config";
import {
LOGIN_API_ROUTE,
MOCK_EMAIL,
MOCK_PASSWORD,
MOCK_TOKEN,
} from "./constants";
const LOGIN_URL = `${BASE_URL}/${LOGIN_API_ROUTE}`;
/**
* Msw interceptor. Mocks the login endpoint response.
*/
export const loginMock = http.post(LOGIN_URL, async ({ request }) => {
const { email, password } = (await request.json()) as AuthData;
if (email === MOCK_EMAIL && password === MOCK_PASSWORD) {
return HttpResponse.json({
accessToken: MOCK_TOKEN,
user: { id: "1", email },
});
}
return HttpResponse.json({ message: "Invalid credentials" }, { status: 401 });
});

View File

@@ -0,0 +1,29 @@
import { setupServer } from "msw/node";
import { login } from "./login";
import { loginMock } from "./login.mock";
import { MOCK_EMAIL, MOCK_PASSWORD } from "./constants";
const server = setupServer(loginMock);
describe("login", () => {
beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
describe("happy path", () => {
it("returns access token and user on valid credentials", async () => {
const result = await login({ email: MOCK_EMAIL, password: MOCK_PASSWORD });
expect(result.accessToken).toBe("mock.access.token");
expect(result.user).toEqual({ id: "1", email: MOCK_EMAIL });
});
});
describe("error cases", () => {
it("throws on invalid credentials", async () => {
await expect(
login({ email: "wrong@test.com", password: "wrong" }),
).rejects.toThrow();
});
});
});

View File

@@ -0,0 +1,13 @@
import { api } from "../../../api";
import type { AuthData, AuthResponse } from "../../../model/types/service";
import { LOGIN_API_ROUTE } from "./constants";
/**
* Logs in a user with the given email and password.
*
* @param loginData - The user's login data (email and password).
* @returns A promise that resolves to the authentication response.
*/
export function login(loginData: AuthData) {
return api.post(LOGIN_API_ROUTE, { json: loginData }).json<AuthResponse>();
}

View File

@@ -1,5 +1,16 @@
import type { User } from "entities/User";
export interface AuthData {
/**
* User's email address.
*/
email: string;
/**
* User's password.
*/
password: string;
}
export interface AuthResponse {
/**
* Access token for the authenticated user.