Skip to content

Instantly share code, notes, and snippets.

@orenaksakal
Last active July 19, 2025 20:42
Show Gist options
  • Save orenaksakal/72381b8c195ebf7e5f2b965cd6195b53 to your computer and use it in GitHub Desktop.
Save orenaksakal/72381b8c195ebf7e5f2b965cd6195b53 to your computer and use it in GitHub Desktop.
http.route({
path: "/api/posts",
method: "POST",
handler: httpAction(async (ctx, request) => {
const { title, content } = await request.json();
if (!title || !content) {
return new Response("Title and content are required", {
status: 400,
});
}
const post = await ctx.runMutation(internal.posts.create, {
title,
content,
});
return new Response(JSON.stringify({ post }), {
status: 200,
});
}),
});
http.route({
path: "/api/posts",
method: "PATCH",
handler: httpAction(async (ctx, request) => {
const { id, content } = await request.json();
if (!id) {
return new Response("Post ID is required", {
status: 400,
});
}
await ctx.runMutation(internal.posts.update, {
id,
content,
});
return new Response(JSON.stringify({ post: id }), {
status: 200,
});
}),
});
http.route({
path: "/api/posts",
method: "GET",
handler: httpAction(async (ctx, request) => {
const id = new URL(request.url).searchParams.get("id");
console.log("Retrieving post with ID:", { id, url: request.url });
if (!id) {
return new Response("Post ID is required", {
status: 400,
});
}
const post = await ctx.runMutation(internal.posts.get, { id });
const returnpost = post[0];
return new Response(JSON.stringify({ postId: returnpost._id }), {
status: 200,
});
}),
});
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
// --- TEST CONFIGURATION ---
// Tweak these values to increase or decrease the load.
export const options = {
// vus: Number of virtual users to simulate.
// duration: The total duration of the test.
vus: 5000, // Simulate 10 concurrent users
duration: '60s', // Run the test for 30 seconds
// Thresholds are pass/fail criteria for the test.
thresholds: {
'http_req_duration': ['p(95)<500'], // 95% of requests must complete below 500ms
'http_req_failed': ['rate<0.01'], // Request failure rate must be less than 1%
'checks': ['rate>0.99'], // Success rate of our checks must be > 99%
},
};
// --- TEST CONSTANTS ---
// Make sure to change these to match your PocketBase instance.
const PB_URL = ''; // Your PocketBase URL
const USER_EMAIL = ''; // A valid user email
const USER_PASSWORD = ''; // The password for that user
// The 'setup' function runs once before the test starts.
// We'll use it to authenticate and get a token that all virtual users can share.
export function setup() {
// console.log('Authenticating user...');
// const authRes = http.post(
// `${PB_URL}/api/collections/users/auth-with-password`,
// JSON.stringify({
// identity: USER_EMAIL,
// password: USER_PASSWORD,
// }),
// { headers: { 'Content-Type': 'application/json' } }
// );
// check(authRes, { 'authentication successful': (res) => res.status === 200 });
// const authData = authRes.json();
// const authToken = authData.token;
// const userId = authData.record.id;
// console.log('Authentication successful. Starting test...');
// return { authToken, userId }; // Pass the token and user ID to the main test function
console.log('Setup complete. Starting test...');
}
// --- MAIN TEST FUNCTION ---
// This is the code that each virtual user will execute in a loop.
// The 'data' parameter receives the return value from the setup function.
export default function (data) {
// const { authToken, userId } = data;
// // Set the authorization header for all subsequent requests
// const params = {
// headers: {
// 'Authorization': `Bearer ${authToken}`,
// 'Content-Type': 'application/json',
// },
// };
// 1. CREATE a new post
const createPayload = JSON.stringify({
title: `My Test Post - VU ${__VU} ITER ${__ITER}`, // Use k6 vars for unique data
content: 'This is the content of the post.',
});
const createRes = http.post(`${PB_URL}/api/posts`, createPayload);
check(createRes, { 'post created successfully': (res) => res.status === 200 }); // PocketBase returns 200 on create via SDK-like calls
// We need the ID of the new post for the next steps
const postId = createRes.json().post;
// Think time: simulate a user pausing for a second after creating a post
sleep(1);
// 2. READ the created post
const readRes = http.get(`${PB_URL}/api/posts?id=${postId}`);
check(readRes, { 'post read successfully': (res) => res.status === 200 });
sleep(1);
// 3. UPDATE the post
const updatePayload = JSON.stringify({
id: postId,
content: 'This is the updated content.',
});
const updateRes = http.patch(`${PB_URL}/api/posts`, updatePayload);
check(updateRes, { 'post updated successfully': (res) => res.status === 200 });
// sleep(1);
// // 4. DELETE the post (cleanup)
// const deleteRes = http.del(`${PB_URL}/api/posts/${postId}`, null);
// check(deleteRes, { 'post deleted successfully': (res) => res.status === 204 });
}
app.post("/api/posts", async (context) => {
const { title, content } = await context.req.json();
const post = await db.insert(posts).values({
title: title || "Default Title",
content: content || "Default Content",
}).returning();
console.log("Created post:", post);
return context.json(post);
});
app.get("/api/posts/:id", async (context) => {
const id = context.req.param("id");
const post = await db.query.posts.findFirst({
where: eq(posts.id, id),
});
console.log("Updated post:", post);
return context.json(post || { error: "Post not found" });
});
app.patch("/api/posts/:id", async (context) => {
const id = context.req.param("id");
const { content } = await context.req.json();
console.log("Updating post with ID:", id, "Content:", content);
try {
await db.update(posts).set({ content }).where(eq(posts.id, id));
} catch (error) {
console.error("Error updating post:", error);
return context.json({ error: "Failed to update post" }, 500);
}
console.log("Updated post:");
return context.json({ message: "Post updated successfully" });
});
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
// --- TEST CONFIGURATION ---
// Tweak these values to increase or decrease the load.
export const options = {
// vus: Number of virtual users to simulate.
// duration: The total duration of the test.
vus: 5000, // Simulate 10 concurrent users
duration: '60s', // Run the test for 30 seconds
// Thresholds are pass/fail criteria for the test.
thresholds: {
'http_req_duration': ['p(95)<500'], // 95% of requests must complete below 500ms
'http_req_failed': ['rate<0.01'], // Request failure rate must be less than 1%
'checks': ['rate>0.99'], // Success rate of our checks must be > 99%
},
};
// --- TEST CONSTANTS ---
// Make sure to change these to match your PocketBase instance.
const PB_URL = ''; // Your PocketBase URL
const USER_EMAIL = ''; // A valid user email
const USER_PASSWORD = ''; // The password for that user
// The 'setup' function runs once before the test starts.
// We'll use it to authenticate and get a token that all virtual users can share.
export function setup() {
// console.log('Authenticating user...');
// const authRes = http.post(
// `${PB_URL}/api/collections/users/auth-with-password`,
// JSON.stringify({
// identity: USER_EMAIL,
// password: USER_PASSWORD,
// }),
// { headers: { 'Content-Type': 'application/json' } }
// );
// check(authRes, { 'authentication successful': (res) => res.status === 200 });
// const authData = authRes.json();
// const authToken = authData.token;
// const userId = authData.record.id;
// console.log('Authentication successful. Starting test...');
// return { authToken, userId }; // Pass the token and user ID to the main test function
console.log('Setup complete. Starting test...');
}
// --- MAIN TEST FUNCTION ---
// This is the code that each virtual user will execute in a loop.
// The 'data' parameter receives the return value from the setup function.
export default function (data) {
// const { authToken, userId } = data;
// // Set the authorization header for all subsequent requests
// const params = {
// headers: {
// 'Authorization': `Bearer ${authToken}`,
// 'Content-Type': 'application/json',
// },
// };
// 1. CREATE a new post
const createPayload = JSON.stringify({
title: `My Test Post - VU ${__VU} ITER ${__ITER}`, // Use k6 vars for unique data
content: 'This is the content of the post.',
});
const createRes = http.post(`${PB_URL}/api/posts`, createPayload);
check(createRes, { 'post created successfully': (res) => res.status === 200 }); // PocketBase returns 200 on create via SDK-like calls
// We need the ID of the new post for the next steps
const postId = createRes.json()[0].id;
// Think time: simulate a user pausing for a second after creating a post
sleep(1);
// 2. READ the created post
const readRes = http.get(`${PB_URL}/api/posts/${postId}`);
check(readRes, { 'post read successfully': (res) => res.status === 200 });
sleep(1);
// 3. UPDATE the post
const updatePayload = JSON.stringify({
content: 'This is the updated content.',
});
const updateRes = http.patch(`${PB_URL}/api/posts/${postId}`, updatePayload);
check(updateRes, { 'post updated successfully': (res) => res.status === 200 });
// sleep(1);
// // 4. DELETE the post (cleanup)
// const deleteRes = http.del(`${PB_URL}/api/posts/${postId}`, null);
// check(deleteRes, { 'post deleted successfully': (res) => res.status === 204 });
}
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
// --- TEST CONFIGURATION ---
// Tweak these values to increase or decrease the load.
export const options = {
// vus: Number of virtual users to simulate.
// duration: The total duration of the test.
vus: 5000, // Simulate 10 concurrent users
duration: '60s', // Run the test for 30 seconds
// Thresholds are pass/fail criteria for the test.
thresholds: {
'http_req_duration': ['p(95)<500'], // 95% of requests must complete below 500ms
'http_req_failed': ['rate<0.01'], // Request failure rate must be less than 1%
'checks': ['rate>0.99'], // Success rate of our checks must be > 99%
},
};
// --- TEST CONSTANTS ---
// Make sure to change these to match your PocketBase instance.
const PB_URL = ''; // Your PocketBase URL
const USER_EMAIL = ''; // A valid user email
const USER_PASSWORD = ''; // The password for that user
// The 'setup' function runs once before the test starts.
// We'll use it to authenticate and get a token that all virtual users can share.
export function setup() {
console.log('Authenticating user...');
const authRes = http.post(
`${PB_URL}/api/collections/users/auth-with-password`,
JSON.stringify({
identity: USER_EMAIL,
password: USER_PASSWORD,
}),
{ headers: { 'Content-Type': 'application/json' } }
);
check(authRes, { 'authentication successful': (res) => res.status === 200 });
const authData = authRes.json();
const authToken = authData.token;
const userId = authData.record.id;
console.log('Authentication successful. Starting test...');
return { authToken, userId }; // Pass the token and user ID to the main test function
}
// --- MAIN TEST FUNCTION ---
// This is the code that each virtual user will execute in a loop.
// The 'data' parameter receives the return value from the setup function.
export default function (data) {
const { authToken, userId } = data;
// Set the authorization header for all subsequent requests
const params = {
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
};
// 1. CREATE a new post
const createPayload = JSON.stringify({
title: `My Test Post - VU ${__VU} ITER ${__ITER}`, // Use k6 vars for unique data
content: 'This is the content of the post.',
author: userId, // Associate the post with the authenticated user
});
const createRes = http.post(`${PB_URL}/api/collections/posts/records`, createPayload, params);
check(createRes, { 'post created successfully': (res) => res.status === 200 }); // PocketBase returns 200 on create via SDK-like calls
// We need the ID of the new post for the next steps
const postId = createRes.json('id');
// Think time: simulate a user pausing for a second after creating a post
sleep(1);
// 2. READ the created post
const readRes = http.get(`${PB_URL}/api/collections/posts/records/${postId}`, params);
check(readRes, { 'post read successfully': (res) => res.status === 200 });
sleep(1);
// 3. UPDATE the post
const updatePayload = JSON.stringify({
content: 'This is the updated content.',
});
const updateRes = http.patch(`${PB_URL}/api/collections/posts/records/${postId}`, updatePayload, params);
check(updateRes, { 'post updated successfully': (res) => res.status === 200 });
sleep(1);
// // 4. DELETE the post (cleanup)
// const deleteRes = http.del(`${PB_URL}/api/collections/posts/records/${postId}`, null, params);
// check(deleteRes, { 'post deleted successfully': (res) => res.status === 204 });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment