Please find the below script and find the response as well.
import { browser } from 'k6/browser';
import { check } from 'k6';
import { sleep } from 'k6';
import { group } from 'k6';
export const options = {
scenarios: {
ui: {
executor: 'per-vu-iterations',
vus: 1,
iterations: 2,
maxDuration: '5m', // Add maxDuration as per K6 best practices
options: {
browser: {
type: 'chromium',
},
},
},
},
};
// Global variables to store browser context per VU
let vuPage = null;
let browserContext = null; // Store browser context to maintain session
const TOTAL_ITERATIONS = 2; // Define iterations as a constant
// VU Setup - runs once per VU before iterations start (per K6 standards)
export function setup() {
// This runs once before all VUs start - use for global setup only
console.log('Global setup completed');
return {}; // Return any data needed by VUs
}
// Main VU function - called for each iteration (per K6 standards)
export default async function (data) {
console.log(`=== STARTING ITERATION ${__ITER + 1} of ${TOTAL_ITERATIONS} ===`);
// VU-specific initialization: Launch browser and login only on first iteration (once per VU)
if (__ITER === 0) {
console.log('First iteration - initializing browser and login...');
await initializeAndLogin();
} else {
console.log(`Subsequent iteration ${__ITER + 1} - reusing existing authenticated session...`);
}
// Run the main business actions for each iteration
try {
await performBusinessActions();
} catch (error) {
console.log(`*** ITERATION ${__ITER + 1} ENCOUNTERED ERROR: ${error.message} ***`);
console.log(`Stopping current iteration ${__ITER + 1} and proceeding to next iteration...`);
// Don't re-throw the error - this allows the next iteration to continue
}
// VU-specific cleanup: If this is the last iteration, perform logout (once per VU)
if (__ITER === TOTAL_ITERATIONS - 1) {
console.log('Last iteration - performing logout and cleanup...');
try {
await performLogout();
} catch (error) {
console.log(`*** LOGOUT ERROR: ${error.message} ***`);
console.log('Error during logout, but continuing with VU completion...');
}
} else {
console.log(`Iteration ${__ITER + 1} complete. Moving to next iteration...`);
}
console.log(`=== COMPLETED ITERATION ${__ITER + 1} ===`);
}
// VU Teardown - runs once per VU after all iterations complete (per K6 standards)
export function teardown(data) {
// This runs once after all VUs complete - use for global cleanup only
console.log('Global teardown completed');
}
async function initializeAndLogin() {
console.log('VU Init: Starting browser context and performing login...');
// Create browser context first to maintain session
browserContext = await browser.newContext();
// Create new page within the browser context
vuPage = await browserContext.newPage();
try {
// Navigate to JPetStore homepage
group('01_Homepage_Load', () => {
console.log('Navigating to homepage...');
});
await vuPage.goto('https://jpetstore.aspectran.com/', { waitUntil: 'networkidle' });
sleep(2);
const homeContent = await vuPage.content();
check(homeContent, {
'Homepage loaded': (t) => t.includes('JPetStore') || t.includes('Enter the Store'),
});
console.log('Homepage loaded successfully');
sleep(1);
// Click Sign In
group('02_Navigate_to_SignIn', () => {
console.log('Clicking Sign In...');
});
await vuPage.locator('a[href*="signonForm"]').click();
await vuPage.waitForLoadState('networkidle');
const signinContent = await vuPage.content();
check(signinContent, {
'Sign in page loaded': (t) => t.includes('Username') || t.includes('Password'),
});
console.log('Sign in page loaded');
sleep(1);
// Fill username and password and login
group('03_User_Login', () => {
console.log('Performing user login...');
});
// Fill username
console.log('Filling username...');
await vuPage.locator('input[name="username"]').click();
await vuPage.locator('input[name="username"]').clear();
await vuPage.locator('input[name="username"]').fill('testuser1');
sleep(1);
// Fill password
console.log('Filling password...');
await vuPage.locator('input[name="password"]').click();
await vuPage.locator('input[name="password"]').clear();
await vuPage.locator('input[name="password"]').fill('perftest');
sleep(1);
// Click Login button
console.log('Attempting login...');
await vuPage.locator('#Signon > form > div > div > button').click();
await vuPage.waitForLoadState('networkidle');
sleep(3);
const loginContent = await vuPage.content();
check(loginContent, {
'Login successful': (t) => t.includes('Welcome') || t.includes('testuser1') || t.includes('Sign Out'),
});
console.log('Login completed - Browser context established with authenticated session');
sleep(1);
} catch (error) {
console.log(`Login failed with error: ${error.message}`);
// Close browser context and page if login fails
if (vuPage) {
try {
await vuPage.close();
} catch (e) {
console.log('Error closing page:', e.message);
}
}
if (browserContext) {
try {
await browserContext.close();
} catch (e) {
console.log('Error closing browser context:', e.message);
}
}
throw error;
}
}
async function performBusinessActions() {
console.log(`*** ITERATION ${__ITER + 1}: Running business actions... ***`);
// Simple check - if page doesn't exist, skip this iteration
if (!vuPage || vuPage.isClosed()) {
console.log('Page is not available for business actions. Skipping this iteration.');
return;
}
try {
// Business Action 1: Navigate to Dogs category (runs per iteration)
group('04_Browse_Dogs_Category', () => {
console.log(`Iteration ${__ITER + 1}: Clicking on Dogs category...`);
});
await vuPage.locator('#SidebarContent a[href*="DOGS"], a[href*="viewCategory"][href*="DOGS"]').click();
await vuPage.waitForLoadState('networkidle');
sleep(2);
const dogsContent = await vuPage.content();
check(dogsContent, {
'Dogs category loaded': (t) => t.includes('Dogs') || t.includes('Bulldog'),
});
console.log(`Iteration ${__ITER + 1}: Dogs category loaded successfully`);
sleep(1);
// Business Action 2: Select K9-BD product
group('05_Select_Product', () => {
console.log(`Iteration ${__ITER + 1}: Clicking on K9-BD product...`);
});
await vuPage.locator('a[href*="K9-BD-"], a[href*="productId=K9-BD"]').click();
await vuPage.waitForLoadState('networkidle');
sleep(2);
const productContent = await vuPage.content();
check(productContent, {
'Product page loaded': (t) => t.includes('K9-BD-') || t.includes('Bulldog'),
});
console.log(`Iteration ${__ITER + 1}: Product page loaded successfully`);
sleep(1);
// Business Action 3: Add item to cart
group('06_Add_Item_to_Cart', () => {
console.log(`Iteration ${__ITER + 1}: Adding item to cart...`);
});
await vuPage.locator('#Catalog > table > tbody > tr:nth-child(2) > td:nth-child(5) > a').click();
await vuPage.waitForLoadState('networkidle');
sleep(2);
const cartContent = await vuPage.content();
check(cartContent, {
'Item added to cart': (t) => t.includes('Shopping Cart') || t.includes('Sub Total'),
});
console.log(`Iteration ${__ITER + 1}: Item added to cart successfully`);
sleep(1);
// Business Action 4: Remove item from cart
group('07_Remove_Item_from_Cart', () => {
console.log(`Iteration ${__ITER + 1}: Removing item from cart...`);
});
await vuPage.locator('#Cart > form > table > tbody > tr:nth-child(2) > td:nth-child(8) > a').click();
await vuPage.waitForLoadState('networkidle');
sleep(2);
const removeContent = await vuPage.content();
check(removeContent, {
'Item removed from cart': (t) => t.includes('Shopping Cart'),
});
console.log(`Iteration ${__ITER + 1}: Item removed from cart successfully`);
sleep(1);
console.log(`*** ITERATION ${__ITER + 1} COMPLETED SUCCESSFULLY ***`);
} catch (error) {
console.log(`*** ITERATION ${__ITER + 1} FAILED with error: ${error.message} ***`);
console.log(`Stopping current iteration ${__ITER + 1} and allowing next iteration to proceed...`);
// Don't throw error - this allows the next iteration to continue
return; // Exit current iteration gracefully
}
}
// Logout function - called after all iterations are complete
async function performLogout() {
console.log('All iterations completed. Performing logout...');
if (vuPage && !vuPage.isClosed()) {
group('08_User_Logout', () => {
console.log('Signing out...');
});
try {
await vuPage.locator('#Menu > div:nth-child(1) > a:nth-child(7)').click();
await vuPage.waitForLoadState('networkidle');
sleep(2);
const signoutContent = await vuPage.content();
check(signoutContent, {
'Signed out successfully': (t) => t.includes('Sign In') || !t.includes('testuser1'),
});
console.log('Signed out successfully');
} catch (e) {
console.log('Error during logout:', e.message);
}
}
// Clean up browser resources
try {
if (vuPage && !vuPage.isClosed()) {
await vuPage.close();
console.log('Page closed');
}
if (browserContext) {
await browserContext.close();
console.log('Browser context closed');
}
} catch (e) {
console.log('Error closing browser resources:', e.message);
}
}
Response:
scenarios: (100.00%) 1 scenario, 1 max VUs, 5m30s max duration (incl. graceful stop):
\* ui: 2 iterations for each of 1 VUs (maxDuration: 5m0s, gracefulStop: 30s)
INFO\[0000\] Global setup completed source=console
INFO\[0000\] === STARTING ITERATION 1 of 2 === source=console
INFO\[0000\] First iteration - initializing browser and login... source=console
INFO\[0000\] VU Init: Starting browser context and performing login... source=console
INFO\[0001\] Navigating to homepage... source=console
INFO\[0005\] Homepage loaded successfully source=console
INFO\[0006\] Clicking Sign In... source=console
INFO\[0008\] Sign in page loaded source=console
INFO\[0009\] Performing user login... source=console
INFO\[0009\] Filling username... source=console
INFO\[0010\] Filling password... source=console
INFO\[0012\] Attempting login... source=console
INFO\[0015\] Login completed - Browser context established with authenticated session source=console
INFO\[0016\] \*\*\* ITERATION 1: Running business actions... \*\*\* source=console
INFO\[0016\] Iteration 1: Clicking on Dogs category... source=console
INFO\[0019\] Iteration 1: Dogs category loaded successfully source=console
INFO\[0020\] Iteration 1: Clicking on K9-BD product... source=console
INFO\[0024\] Iteration 1: Product page loaded successfully source=console
INFO\[0025\] Iteration 1: Adding item to cart... source=console
INFO\[0028\] Iteration 1: Item added to cart successfully source=console
INFO\[0029\] Iteration 1: Removing item from cart... source=console
INFO\[0032\] Iteration 1: Item removed from cart successfully source=console
INFO\[0033\] \*\*\* ITERATION 1 COMPLETED SUCCESSFULLY \*\*\* source=console
INFO\[0033\] Iteration 1 complete. Moving to next iteration... source=console
INFO\[0033\] === COMPLETED ITERATION 1 === source=console
INFO\[0034\] === STARTING ITERATION 2 of 2 === source=console
INFO\[0034\] Subsequent iteration 2 - reusing existing authenticated session... source=console
INFO\[0034\] \*\*\* ITERATION 2: Running business actions... \*\*\* source=console
INFO\[0034\] Page is not available for business actions. Skipping this iteration. source=consol
INFO\[0034\] Last iteration - performing logout and cleanup... source=console
INFO\[0034\] All iterations completed. Performing logout... source=console
INFO\[0034\] Browser context closed source=console
INFO\[0034\] === COMPLETED ITERATION 2 === source=console
INFO\[0034\] Global teardown completed source=console