pahvalentines/testing_example/successLoadTest.js
2026-02-03 18:43:06 +05:30

177 lines
No EOL
5.4 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { faker } from "https://cdn.jsdelivr.net/npm/@faker-js/faker@9.4.0/+esm";
import http from "k6/http";
import { check, sleep } from "k6";
import { Trend } from "k6/metrics";
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.0.1/index.js';
import { SharedArray } from 'k6/data';
import encoding from 'k6/encoding';
const petCategory = [
"Dog",
"Cat",
"Fish",
"Bird",
"Hamster",
"Gerbil",
"Guinea Pig",
"Rabbit",
"Bearded Dragon",
"Leopard Gecko",
"Corn Snake",
];
const musicGenre = [
"Boy Band",
"Soul",
"Country & Western",
"Hip-Hop",
"K-Pop",
"New Romantic",
];
const BASE_URL = "https://valentinesong.oliver.digital/back";
const randomItem = (arr) => arr[Math.floor(Math.random() * arr.length)];
// Custom metrics for tracking journey stages
const submissionTime = new Trend("submission_duration");
const pollingWaitTime = new Trend("polling_wait_duration");
const resultFetchTime = new Trend("result_fetch_duration");
const totalJourneyTime = new Trend("total_journey_duration");
const pollAttempts = new Trend("poll_attempts_count");
// Load the image file and convert to base64
// Use SharedArray to load file only once and share across VUs
const imageBase64 = new SharedArray('dogImage', function() {
const binFile = open('./dog-test.jpeg', 'b');
return [encoding.b64encode(binFile)];
});
// Define the load test configuration
export const options = {
vus: 2, // number of virtual users running simultaneously
iterations: 2, // number of journey/iteration to complete across all VUS
maxDuration: "10m", // Allow up to 10 mins for the journey to finish
};
export default function () {
const journeyStartTime = Date.now();
const payload = JSON.stringify({
pet_name: faker.person.firstName(),
pet_type: randomItem(petCategory),
music_vibe: randomItem(musicGenre),
owner_name: faker.person.firstName(),
cookie_id: `cookie_test_${faker.string.alphanumeric(10)}`,
// photo: "data:image/gif;base64,R0lGODlhAQABAAAAACw=",
photo: `data:image/jpeg;base64,${imageBase64[0]}`
});
const params = {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
};
// Perform the POST request
const submissionStart = Date.now();
const res = http.post(`${BASE_URL}/api/submissions`, payload, params);
const submissionDuration = Date.now() - submissionStart;
submissionTime.add(submissionDuration);
// Validate the response
const submissionCheck = check(res, {
"status is 200": (r) => r.status === 201 || r.status === 200,
"response time < 2s": (r) => r.timings.duration < 2000,
valid_session_id: (r) => r.json().session_id.length > 10,
});
if (!submissionCheck) {
console.error(`❌ Submission failed for session`);
return; // Exit if submission fails
}
const session_id = res.json().session_id;
console.log(`✅ Submission successful. Session ID: ${session_id}`);
// 2. Poll for Results
let isReady = false;
const pollingInterval = 20; // seconds
const timeoutInSeconds = 10 * 60; // 10 minutes total wait time
const pollingStartTime = Date.now();
let pollCount = 0;
while (!isReady) {
// 1. Check if we have timed out
if ((Date.now() - pollingStartTime) / 1000 > timeoutInSeconds) {
console.error(`⏱️ Polling timed out for session: ${session_id}`);
break;
}
// Wait before next polling
sleep(pollingInterval);
pollCount++;
const pollRes = http.get(
`${BASE_URL}/api/submissions/${session_id}/status`,
);
check(pollRes, {
"polling response received (status = 200)": (r) => r.status === 200,
});
if (pollRes.status === 200 && pollRes.json().status === "success") {
isReady = true;
console.log(
`🎉 Result ready after ${pollCount} poll attempts (${((Date.now() - pollingStartTime) / 1000).toFixed(1)}s)`,
);
}
}
const pollingDuration = Date.now() - pollingStartTime;
pollingWaitTime.add(pollingDuration);
pollAttempts.add(pollCount);
// 3. Final Result
if (isReady) {
const resultFetchStart = Date.now();
const resultRes = http.get(`${BASE_URL}/api/results/${session_id}`);
const resultFetchDuration = Date.now() - resultFetchStart;
resultFetchTime.add(resultFetchDuration);
const resultCheck = check(resultRes, {
"result fetched": (r) => r.status === 200,
"status msg has success": (r) => r.json().status === "success",
"has lyrics": (r) => r.json().lyrics.length > 10,
"has video_url": (r) => r.json().video_url.length > 10,
});
if (resultCheck) {
const totalDuration = Date.now() - journeyStartTime;
totalJourneyTime.add(totalDuration);
console.log(
`✅ Complete journey successful! Total time: ${(totalDuration / 1000).toFixed(1)}s`,
);
} else {
console.error(`❌ Result validation failed for session: ${session_id}`);
}
// User stays on result page for a bit
sleep(20);
} else {
console.error(
`❌ Journey incomplete - result never became ready for session: ${session_id}`,
);
}
// Wait 1 second between requests per user
sleep(1);
}
export function handleSummary(data) {
console.log('\n' + '='.repeat(80));
console.log('📊 CUSTOM METRICS SUMMARY');
console.log(' All durations are in milliseconds (ms). 1 second = 1,000ms | 1 minute = 60,000ms');
console.log('='.repeat(80) + '\n');
return {
'stdout': textSummary(data, { indent: ' ', enableColors: true }),
};
}