mirror of
https://github.com/ramvignesh-b/pi-ku.git
synced 2026-05-04 08:56:52 +00:00
ci: add sll support and enhance e2e workflow
This commit is contained in:
@@ -34,6 +34,7 @@ export async function registerAndLogin(
|
||||
// 2. Activation via Mailpit
|
||||
logger.info(`[Auth] Polling Mailpit for activation email...`);
|
||||
const activationLink = await MailpitHelper.getActivationLink(email);
|
||||
|
||||
await page.goto(activationLink);
|
||||
|
||||
await expect(page.getByText(/account activated/i)).toBeVisible();
|
||||
|
||||
@@ -7,7 +7,7 @@ export interface MailpitMessage {
|
||||
To: { Address: string }[];
|
||||
}
|
||||
|
||||
const MAILPIT_API_URL = process.env.MAILPIT_API_URL;
|
||||
const MAILPIT_API_URL = `http://${process.env.EMAIL_HOST}:${process.env.EMAIL_API_PORT}/api/v1`;
|
||||
|
||||
export const MailpitHelper = {
|
||||
getActivationLink: async (
|
||||
@@ -18,7 +18,6 @@ export const MailpitHelper = {
|
||||
const requestContext = await request.newContext();
|
||||
|
||||
while (Date.now() - startTime < timeout) {
|
||||
// Search specifically for the recipient to reduce data transfer
|
||||
const response = await requestContext.get(`${MAILPIT_API_URL}/search`, {
|
||||
params: { query: `to:${email}`, limit: 1 },
|
||||
});
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
import process, { env } from "node:process";
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
import dotenv from "dotenv";
|
||||
import { getBaseUrl } from "./utils/url-builder";
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
*/
|
||||
dotenv.config({ path: path.resolve(process.cwd(), "../.env.e2e") });
|
||||
const baseUrl = getBaseUrl(
|
||||
env.SSL_ENABLED === "true",
|
||||
env.FRONTEND_DOMAIN,
|
||||
env.FRONTEND_PORT,
|
||||
);
|
||||
|
||||
console.log(baseUrl);
|
||||
export default defineConfig({
|
||||
timeout: 60000,
|
||||
expect: {
|
||||
@@ -26,7 +34,7 @@ export default defineConfig({
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.FRONTEND_URL,
|
||||
baseURL: baseUrl,
|
||||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
||||
actionTimeout: 20000,
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
@@ -53,8 +61,12 @@ export default defineConfig({
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: {
|
||||
command: "bun run dev",
|
||||
url: process.env.FRONTEND_URL,
|
||||
command: "bun run dev -- --mode e2e",
|
||||
url: getBaseUrl(
|
||||
process.env.SSL_ENABLED === "true",
|
||||
process.env.FRONTEND_DOMAIN,
|
||||
process.env.FRONTEND_PORT,
|
||||
),
|
||||
reuseExistingServer: !process.env.CI,
|
||||
ignoreHTTPSErrors: true,
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@ import { server } from "../../test/mocks/server";
|
||||
import { useAuthStore } from "../store/useAuthStore";
|
||||
import { api } from "./apiClient";
|
||||
|
||||
const API_URL = "http://piku-server";
|
||||
const VITE_API_URL = "http://piku-server";
|
||||
|
||||
beforeEach(() => {
|
||||
useAuthStore.setState({
|
||||
@@ -24,7 +24,7 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
vi.stubEnv("API_URL", API_URL);
|
||||
vi.stubEnv("VITE_API_URL", VITE_API_URL);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@@ -37,7 +37,7 @@ describe("request interceptor", () => {
|
||||
|
||||
let capturedAuthHeader = "";
|
||||
server.use(
|
||||
http.get(`${API_URL}/api/auth/me/`, ({ request }) => {
|
||||
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
|
||||
capturedAuthHeader = request.headers.get("Authorization") ?? "";
|
||||
return HttpResponse.json(mockUser);
|
||||
}),
|
||||
@@ -51,7 +51,7 @@ describe("request interceptor", () => {
|
||||
it("should not send Authorization header when the store has no token", async () => {
|
||||
let capturedAuthHeader: string | null = "";
|
||||
server.use(
|
||||
http.get(`${API_URL}/api/auth/me/`, ({ request }) => {
|
||||
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
|
||||
capturedAuthHeader = request.headers.get("Authorization");
|
||||
return HttpResponse.json({});
|
||||
}),
|
||||
@@ -70,14 +70,14 @@ describe("response interceptor", () => {
|
||||
let _refreshApiCallCount = 0;
|
||||
|
||||
server.use(
|
||||
http.get(`${API_URL}/api/auth/me/`, ({ request }) => {
|
||||
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
|
||||
meApiCallCount++;
|
||||
if (request.headers.get("Authorization") === "Bearer expired-token") {
|
||||
return new HttpResponse(null, { status: 401 });
|
||||
}
|
||||
return HttpResponse.json(mockUser);
|
||||
}),
|
||||
http.post(`${API_URL}/api/auth/refresh/`, () => {
|
||||
http.post(`${VITE_API_URL}/api/auth/refresh/`, () => {
|
||||
_refreshApiCallCount++;
|
||||
return HttpResponse.json({ access: "refreshed-token" });
|
||||
}),
|
||||
@@ -94,13 +94,13 @@ describe("response interceptor", () => {
|
||||
useAuthStore.getState().setAuth("expired-token", mockUser);
|
||||
|
||||
server.use(
|
||||
http.get(`${API_URL}/api/auth/me/`, ({ request }) => {
|
||||
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
|
||||
if (request.headers.get("Authorization") === "Bearer expired-token") {
|
||||
return new HttpResponse(null, { status: 401 });
|
||||
}
|
||||
return HttpResponse.json(mockUser);
|
||||
}),
|
||||
http.post(`${API_URL}/api/auth/refresh/`, () =>
|
||||
http.post(`${VITE_API_URL}/api/auth/refresh/`, () =>
|
||||
HttpResponse.json({ access: "refreshed-token" }),
|
||||
),
|
||||
);
|
||||
@@ -115,14 +115,14 @@ describe("response interceptor", () => {
|
||||
|
||||
server.use(
|
||||
http.get(
|
||||
`${API_URL}/api/auth/me/`,
|
||||
`${VITE_API_URL}/api/auth/me/`,
|
||||
() =>
|
||||
new HttpResponse(JSON.stringify({ detail: "Invalid token" }), {
|
||||
status: 401,
|
||||
}),
|
||||
),
|
||||
http.post(
|
||||
`${API_URL}/api/auth/refresh/`,
|
||||
`${VITE_API_URL}/api/auth/refresh/`,
|
||||
() =>
|
||||
new HttpResponse(JSON.stringify({ detail: "Refresh failed" }), {
|
||||
status: 401,
|
||||
|
||||
@@ -17,7 +17,7 @@ import { useAuth } from "./useAuth";
|
||||
vi.mock("../utils/crypto");
|
||||
vi.mock("../utils/keystore");
|
||||
|
||||
const API_URL = "http://piku-server";
|
||||
const VITE_API_URL = "http://piku-server";
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
@@ -112,7 +112,7 @@ describe("logout", () => {
|
||||
it("should call the logout API endpoint", async () => {
|
||||
let logoutCalled = false;
|
||||
server.use(
|
||||
http.post(`${API_URL}/api/auth/logout/`, () => {
|
||||
http.post(`${VITE_API_URL}/api/auth/logout/`, () => {
|
||||
logoutCalled = true;
|
||||
return HttpResponse.json({});
|
||||
}),
|
||||
@@ -139,7 +139,7 @@ describe("logout", () => {
|
||||
it("should clear the auth store even if the API call fails", async () => {
|
||||
server.use(
|
||||
http.post(
|
||||
`${API_URL}/api/auth/logout/`,
|
||||
`${VITE_API_URL}/api/auth/logout/`,
|
||||
() => new HttpResponse(null, { status: 500 }),
|
||||
),
|
||||
);
|
||||
@@ -163,7 +163,7 @@ describe("initialize", () => {
|
||||
});
|
||||
let refreshCalled = false;
|
||||
server.use(
|
||||
http.post(`${API_URL}/api/auth/refresh/`, () => {
|
||||
http.post(`${VITE_API_URL}/api/auth/refresh/`, () => {
|
||||
refreshCalled = true;
|
||||
return HttpResponse.json({ access: "new-token" });
|
||||
}),
|
||||
@@ -194,7 +194,7 @@ describe("initialize", () => {
|
||||
it("should preserve the master key even if the refresh attempt fails", async () => {
|
||||
server.use(
|
||||
http.post(
|
||||
`${API_URL}/api/auth/refresh/`,
|
||||
`${VITE_API_URL}/api/auth/refresh/`,
|
||||
() => new HttpResponse(null, { status: 401 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export const getBaseUrl = (
|
||||
isSslEnabled: boolean,
|
||||
domain: string | undefined,
|
||||
port: string | undefined,
|
||||
): string => {
|
||||
const uriScheme = isSslEnabled ? "https" : "http";
|
||||
const baseURL = `${uriScheme}://${domain}${port ? `:${port}` : ""}`;
|
||||
return baseURL;
|
||||
};
|
||||
+23
-8
@@ -3,24 +3,39 @@ import path from "node:path";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { defineConfig, loadEnv } from "vite";
|
||||
import { getBaseUrl } from "./utils/url-builder";
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, "../", "");
|
||||
const isSslEnabled = env.SSL_ENABLED === "true";
|
||||
let ssl_certs: { key: Buffer; cert: Buffer };
|
||||
|
||||
if (isSslEnabled) {
|
||||
ssl_certs = {
|
||||
key: fs.readFileSync(
|
||||
path.resolve(__dirname, "../certs/localhost-key.pem"),
|
||||
),
|
||||
cert: fs.readFileSync(path.resolve(__dirname, "../certs/localhost.pem")),
|
||||
};
|
||||
}
|
||||
|
||||
const baseApiUrl = getBaseUrl(
|
||||
isSslEnabled,
|
||||
env.BACKEND_DOMAIN,
|
||||
env.BACKEND_PORT,
|
||||
);
|
||||
console.log(baseApiUrl);
|
||||
return {
|
||||
envDir: "../",
|
||||
plugins: [react(), tailwindcss()],
|
||||
define: {
|
||||
"import.meta.env.VITE_API_URL": JSON.stringify(baseApiUrl),
|
||||
},
|
||||
server: {
|
||||
port: Number(env.FRONTEND_PORT),
|
||||
host: env.FRONTEND_DOMAIN,
|
||||
https: {
|
||||
key: fs.readFileSync(
|
||||
path.resolve(__dirname, "../certs/localhost-key.pem"),
|
||||
),
|
||||
cert: fs.readFileSync(
|
||||
path.resolve(__dirname, "../certs/localhost.pem"),
|
||||
),
|
||||
},
|
||||
https: isSslEnabled ? ssl_certs : undefined,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user