Files
event-manager/e2e/helpers/frappe.ts
T
xadm 786cbc724f
CI / Server (push) Has been cancelled
Linters / Frappe Linter (push) Has been cancelled
Linters / Vulnerable Dependency Check (push) Has been cancelled
UI Tests / Playwright E2E Tests (push) Has been cancelled
Initialize fork and rebrand app to event_manager
2026-05-11 09:56:57 +02:00

224 lines
5.1 KiB
TypeScript

import { APIRequestContext } from "@playwright/test";
import * as fs from "fs";
/**
* Frappe API response wrapper.
*/
export interface FrappeResponse<T = unknown> {
message?: T;
exc?: string;
exc_type?: string;
_server_messages?: string;
}
// Path to CSRF token file saved by auth.setup.ts
const CSRF_FILE = "e2e/.auth/csrf.json";
// Cache for CSRF token (read from file once)
let csrfTokenCache: string | null = null;
/**
* Get CSRF token from the file saved during auth setup.
* The token is extracted from window.frappe.csrf_token after login.
*/
function getCsrfToken(): string {
// Return cached token if available
if (csrfTokenCache !== null) {
return csrfTokenCache;
}
// Read token from file
try {
if (fs.existsSync(CSRF_FILE)) {
const data = JSON.parse(fs.readFileSync(CSRF_FILE, "utf-8"));
csrfTokenCache = data.csrf_token || "";
return csrfTokenCache;
}
} catch (error) {
console.warn("Failed to read CSRF token file:", error);
}
csrfTokenCache = "";
return "";
}
/**
* Create a new document via Frappe REST API.
*/
export async function createDoc<T = Record<string, unknown>>(
request: APIRequestContext,
doctype: string,
doc: Record<string, unknown>,
): Promise<T> {
const csrfToken = getCsrfToken();
const response = await request.post(`/api/resource/${doctype}`, {
data: doc,
headers: {
"Content-Type": "application/json",
...(csrfToken ? { "X-Frappe-CSRF-Token": csrfToken } : {}),
},
});
if (!response.ok()) {
const error = await response.text();
throw new Error(`Failed to create ${doctype}: ${error}`);
}
const result = await response.json();
return result.data as T;
}
/**
* Get a document by name via Frappe REST API.
*/
export async function getDoc<T = Record<string, unknown>>(
request: APIRequestContext,
doctype: string,
name: string,
): Promise<T> {
const response = await request.get(
`/api/resource/${doctype}/${encodeURIComponent(name)}`,
);
if (!response.ok()) {
const error = await response.text();
throw new Error(`Failed to get ${doctype}/${name}: ${error}`);
}
const result = await response.json();
return result.data as T;
}
/**
* Update a document via Frappe REST API.
*/
export async function updateDoc<T = Record<string, unknown>>(
request: APIRequestContext,
doctype: string,
name: string,
updates: Record<string, unknown>,
): Promise<T> {
const csrfToken = getCsrfToken();
const response = await request.put(`/api/resource/${doctype}/${encodeURIComponent(name)}`, {
data: updates,
headers: {
"Content-Type": "application/json",
...(csrfToken ? { "X-Frappe-CSRF-Token": csrfToken } : {}),
},
});
if (!response.ok()) {
const error = await response.text();
throw new Error(`Failed to update ${doctype}/${name}: ${error}`);
}
const result = await response.json();
return result.data as T;
}
/**
* Delete a document via Frappe REST API.
*/
export async function deleteDoc(
request: APIRequestContext,
doctype: string,
name: string,
): Promise<void> {
const csrfToken = getCsrfToken();
const response = await request.delete(`/api/resource/${doctype}/${encodeURIComponent(name)}`, {
headers: {
...(csrfToken ? { "X-Frappe-CSRF-Token": csrfToken } : {}),
},
});
if (!response.ok()) {
const error = await response.text();
throw new Error(`Failed to delete ${doctype}/${name}: ${error}`);
}
}
/**
* Call a Frappe whitelisted method.
*/
export async function callMethod<T = unknown>(
request: APIRequestContext,
method: string,
args: Record<string, unknown> = {},
): Promise<T> {
const csrfToken = getCsrfToken();
const response = await request.post(`/api/method/${method}`, {
data: args,
headers: {
"Content-Type": "application/json",
...(csrfToken ? { "X-Frappe-CSRF-Token": csrfToken } : {}),
},
});
if (!response.ok()) {
const error = await response.text();
throw new Error(`Failed to call ${method}: ${error}`);
}
const result: FrappeResponse<T> = await response.json();
return result.message as T;
}
/**
* Get a list of documents via Frappe REST API.
*/
export async function getList<T = Record<string, unknown>>(
request: APIRequestContext,
doctype: string,
options: {
fields?: string[];
filters?: Record<string, unknown>;
limit?: number;
orderBy?: string;
} = {},
): Promise<T[]> {
const params = new URLSearchParams();
if (options.fields) {
params.set("fields", JSON.stringify(options.fields));
}
if (options.filters) {
params.set("filters", JSON.stringify(options.filters));
}
if (options.limit) {
params.set("limit_page_length", options.limit.toString());
}
if (options.orderBy) {
params.set("order_by", options.orderBy);
}
const response = await request.get(`/api/resource/${doctype}?${params.toString()}`);
if (!response.ok()) {
const error = await response.text();
throw new Error(`Failed to get list of ${doctype}: ${error}`);
}
const result = await response.json();
return result.data as T[];
}
/**
* Check if a document exists.
*/
export async function docExists(
request: APIRequestContext,
doctype: string,
name: string,
): Promise<boolean> {
try {
await getDoc(request, doctype, name);
return true;
} catch {
return false;
}
}