Sitemap

Kickstart UI & API Testing in 60s with Super Pancake Automation

9 min readJul 22, 2025

Super Pancake Automation is a modern, lightning-fast framework that uses the Chrome DevTools Protocol to test web UIs and APIs — with zero boilerplate, beautiful HTML reports, and instant setup.

Press enter or click to view image in full size

In this article, I’ll show you how to set up your first project in under a minute using super-pancake-automation.

npm link: https://www.npmjs.com/package/super-pancake-automation

github link: https://github.com/pradapjackie/super-pancake

Initialize Your Project

Open your terminal and run:

npx super-pancake-automation@latest init test-pancake

This command scaffolds a fully working project with sample tests and everything preconfigured.

You’ll be guided through an interactive setup:

-MacBook-Pro WebstormProjects % npx super-pancake-automation@latest init super-pancake
Need to install the following packages:
super-pancake-automation@2.7.2
Ok to proceed? (y) y

🚀 Creating Super Pancake automation project: super-pancake-automation

📝 Let's configure your project preferences:

1. Browser Mode:
○ 1. Headless (faster, no GUI)
● 2. Headed (visible browser window)

Enter your choice (1-2) [2]: 1
2. Screenshot Capture:
● 1. Enabled (capture on failure and success)
○ 2. Only on failure
○ 3. Disabled

Enter your choice (1-3) [1]: 1
3. Sample Tests: Will generate proven working examples (sample.test.js + ui-website.test.js)
4. Test Runner UI:
● 1. Interactive UI enabled
○ 2. Command line only

Enter your choice (1-2) [1]: 1
5. Test Reports:
● 1. HTML reports with screenshots
○ 2. JSON reports
○ 3. Console output only

Enter your choice (1-3) [1]: 1

✨ Creating project with your preferences...

✅ Successfully created super-pancake-automation!

📦 Installing dependencies...
Running npm install...
...
✅ Dependencies installed successfully!

🚀 Next steps:
cd super-pancake-automation
npm test

🎯 Key Features Enabled:
✅ Sequential test execution (prevents Chrome port conflicts)
🚀 Custom Super Pancake test runner
🔧 Environment variable support (HEADED=true, DEBUG=true)
📸 Screenshots will be saved to ./screenshots/
📊 HTML test reports will be generated as ./test-report.html
🎯 Run "npm run test:ui" for interactive testing with Vitest UI
⚡ Tests configured for sequential execution (headless by default)
👀 Use "npm run test:headed" or "HEADED=true npm test" for visible browser
📝 Generated proven working sample tests (sample.test.js + ui-website.test.js + api.test.js)

🛠️ Available Commands:
npm test # Run all tests
npm run test:ui # Vitest UI interface

Happy testing! 🥞

Project Structure

After initialization, your project will look like this:

josestepha@Joses-MacBook-Pro test-pancake % tree
.
├── automationTestReport.html
├── package-lock.json
├── package.json
├── screenshots
├── scripts
│ └── super-pancake-test.js
├── super-pancake.config.js
├── tests
│ ├── sample.test.js
│ └── ui-website.test.js
└── utils
└── test-setup.js

✍️ Writing a Simple Test

Here’s a basic UI test using the built-in CDP functions:


import { describe, it, beforeAll, afterAll } from 'vitest';
import {
// Simplified test setup
createTestEnvironment,
cleanupTestEnvironment,

// DOM operations
enableDOM,
navigateTo,
getText,
waitForSelector,
takeElementScreenshot,

// Assertions
assertEqual,
assertContainsText,

// Reporting
writeReport,

// Port utilities
findAvailablePort
} from 'super-pancake-automation';

let testEnv;

describe('Super Pancake NPM Website Tests', () => {
beforeAll(async () => {
console.log('🌐 Setting up Super Pancake NPM Website test...');

// Find available port dynamically to avoid conflicts
const port = await findAvailablePort(9223, 10);
console.log(`🔍 Using dynamic port: ${port}`);

testEnv = await createTestEnvironment({
headed: process.env.SUPER_PANCAKE_HEADLESS === 'false', // Respect UI setting: false=headless, true=headed
port: port, // Use dynamically allocated port
testName: 'Super Pancake NPM Website Tests'
});
await enableDOM(testEnv.session);
}, 30000);

afterAll(async () => {
// Keep browser open for 5 seconds to see results
console.log('⏳ Keeping browser open for 5 seconds...');
await new Promise(resolve => setTimeout(resolve, 5000));

await cleanupTestEnvironment(testEnv, 'Super Pancake NPM Website Tests');
writeReport();
console.log('📄 UI test report generated');
});

it('should navigate to Super Pancake NPM page', async () => {
console.log('🌐 Testing NPM package page navigation...');

// Navigate to the npm package page
await navigateTo(testEnv.session, 'https://www.npmjs.com/package/super-pancake-automation');

// Wait for page title to load
const h1Element = await waitForSelector(testEnv.session, 'h1', 15000);

// Take screenshot of the NPM page
await takeElementScreenshot(testEnv.session, 'body', './npm-page-screenshot.png');
console.log('📸 NPM page screenshot saved');

console.log('✅ Successfully navigated to NPM package page');
});

it('should verify package information', async () => {
console.log('🔍 Verifying package information...');

try {
// Get package name
const h1Element = await waitForSelector(testEnv.session, 'h1', 5000);
const title = await getText(testEnv.session, h1Element);
console.log('📦 Package title:', title);

// Verify it contains our package name
assertContainsText(title, 'super-pancake-automation', 'Page should show correct package name');

// Look for version information
const versionElement = await waitForSelector(testEnv.session, '[data-testid="version-number"]', 5000);
if (versionElement) {
const version = await getText(testEnv.session, versionElement);
console.log('📋 Current version:', version);
}

console.log('✅ Package information verified');
} catch (error) {
console.log('⚠️ Some package info checks failed (this is normal for new packages):', error.message);
}
});

it('should check package statistics', async () => {
console.log('📊 Checking package statistics...');

// Simple screenshot-based check for package page content
await takeElementScreenshot(testEnv.session, 'body', './package-stats-screenshot.png');
console.log('📸 Package statistics screenshot saved');
console.log('✅ Package statistics check completed');
}, 10000);

it('should verify README content', async () => {
console.log('📖 Checking README content...');

// Simple screenshot-based check for README section
await takeElementScreenshot(testEnv.session, 'body', './readme-screenshot.png');
console.log('📸 README section screenshot saved');
console.log('✅ README verification completed');
}, 10000);

it('should test install command visibility', async () => {
console.log('💻 Checking install command...');

// Take screenshot of install section
await takeElementScreenshot(testEnv.session, 'body', './npm-install-section.png');

console.log('📸 Install section screenshot saved');
console.log('✅ Install command section verified');
});

it('should navigate to GitHub repository', async () => {
console.log('🔗 Testing GitHub repository link...');

// Take screenshot showing the full page with any GitHub links
await takeElementScreenshot(testEnv.session, 'body', './github-links-screenshot.png');
console.log('📸 GitHub links screenshot saved');
console.log('✅ GitHub repository link test completed');
});

});

Here is the configuration for super

export default {
// Browser configuration
browser: {
headless: process.env.HEADED !== 'true',
devtools: process.env.DEBUG === 'true',
slowMo: 0
},

// Sequential test execution settings
execution: {
// Run tests sequentially to avoid Chrome port conflicts
sequential: true,

// Vitest-specific settings for sequential execution
vitest: {
pool: 'forks',
poolOptions: {
forks: {
singleFork: true,
},
},
fileParallelism: false,
sequence: {
concurrent: false,
shuffle: false,
},
bail: 1, // Stop on first failure
retry: 1, // Retry failed tests once
}
},

// Test configuration
test: {
timeout: 30000,
retries: 1
},

// Screenshot configuration
screenshot: {
enabled: true,
path: './screenshots',
onFailure: true,
onSuccess: true,
quality: 90,
fullPage: true
},

// Report configuration
report: {
enabled: true,
format: 'html',
path: './test-report.html',
autoOpen: false
},

// UI configuration
ui: {
enabled: true,
port: 3000
},

// Logging configuration
logging: {
console: true,
network: false,
level: 'info'
},

// Timeouts
timeouts: {
testTimeout: 30000,
pageTimeout: 30000,
elementTimeout: 10000
}
};

API Test Samples

import { describe, it, beforeAll, afterAll } from 'vitest';
import {
// API testing functions
sendGet,
sendPost,
setAuthToken,
withBaseUrl,
timedRequest,

// Assertions for API responses
assertStatus,
assertHeader,
assertBodyContains,
assertResponseTime,
validateSchema,
assertJsonPath,

// Utilities
buildUrlWithParams,
logResponse
} from 'super-pancake-automation';

describe('Super Pancake API Tests', () => {
beforeAll(async () => {
console.log('🚀 Setting up API tests...');
// Optional: Set base URL or auth token
// setAuthToken('your-api-token');
});

afterAll(async () => {
console.log('🧹 API tests completed');
});

it('should perform a GET request to JSONPlaceholder API', async () => {
console.log('🌐 Testing GET request...');

// Make a GET request to a public API
const response = await sendGet('https://jsonplaceholder.typicode.com/posts/1');

// Assert response status
assertStatus(response, 200);

// Assert response contains expected data
assertBodyContains(response, 'userId', 1);
assertBodyContains(response, 'id', 1);

// Verify response structure
const expectedSchema = {
type: 'object',
properties: {
userId: { type: 'number' },
id: { type: 'number' },
title: { type: 'string' },
body: { type: 'string' }
},
required: ['userId', 'id', 'title', 'body']
};

validateSchema(response.data, expectedSchema);

console.log('✅ GET request test passed');
});

it('should test POST request with data', async () => {
console.log('📤 Testing POST request...');

const postData = {
title: 'Super Pancake Test Post',
body: 'This is a test post created by Super Pancake automation',
userId: 1
};

// Make a POST request
const response = await sendPost('https://jsonplaceholder.typicode.com/posts', postData);

// Assert response status for creation
assertStatus(response, 201);

// Assert the posted data is in response
assertBodyContains(response, 'title', 'Super Pancake Test Post');
assertBodyContains(response, 'userId', 1);

// Check that an ID was assigned
const responseId = response.data.id;
if (typeof responseId !== 'number' || responseId <= 0) {
throw new Error(`Expected positive number ID, got: ${responseId}`);
}

console.log('✅ POST request test passed');
});

it('should test response time performance', async () => {
console.log('⏱️ Testing API response time...');

// Use timed request to measure performance
const timedResponse = await timedRequest(() =>
sendGet('https://jsonplaceholder.typicode.com/posts')
);

// Assert response time is reasonable (under 3 seconds)
assertResponseTime(timedResponse, 3000);

// Assert we got multiple posts
const posts = timedResponse.data;
if (!Array.isArray(posts) || posts.length === 0) {
throw new Error('Expected array of posts');
}

console.log(`📊 Response time: ${timedResponse.duration}ms`);
console.log(`📋 Received ${posts.length} posts`);
console.log('✅ Performance test passed');
});

it('should test URL building with parameters', async () => {
console.log('🔗 Testing URL parameter building...');

const baseUrl = 'https://jsonplaceholder.typicode.com/posts';
const params = { userId: 1, _limit: 5 };

// Build URL with parameters
const urlWithParams = buildUrlWithParams(baseUrl, params);
console.log('🌐 Built URL:', urlWithParams);

// Make request with parameters
const response = await sendGet(urlWithParams);

assertStatus(response, 200);

// Should get posts from user 1, limited to 5
const posts = response.data;
if (posts.length > 5) {
throw new Error(`Expected max 5 posts, got ${posts.length}`);
}

// All posts should be from userId 1
for (const post of posts) {
if (post.userId !== 1) {
throw new Error(`Expected userId 1, got ${post.userId}`);
}
}

console.log(`✅ URL parameters test passed - got ${posts.length} posts`);
});

it('should test error handling for invalid endpoints', async () => {
console.log('❌ Testing error handling...');

try {
// Try to access a non-existent endpoint
await sendGet('https://jsonplaceholder.typicode.com/nonexistent');
throw new Error('Expected request to fail');
} catch (error) {
// This should happen - the endpoint doesn't exist
console.log('✅ Correctly handled 404 error:', error.message);
}
});

it('should log and inspect API response', async () => {
console.log('🔍 Testing response logging...');

const response = await sendGet('https://jsonplaceholder.typicode.com/users/1');

// Log the full response for inspection
logResponse(response);

// Assert basic structure
assertStatus(response, 200);
assertBodyContains(response, 'name', 'Leanne Graham');
assertBodyContains(response, 'email', 'Sincere@april.biz');

// Test nested object access
assertJsonPath(response.data, 'address.city', 'Gwenborough');
assertJsonPath(response.data, 'company.name', 'Romaguera-Crona');

console.log('✅ Response logging test passed');
});

});

Run Your First Test

Navigate to your new folder:

cd test-pancake

Then run:

npm test

You’ll see output like:

Test Files  2 failed | 1 passed (3)
Tests 1 failed | 7 passed | 6 skipped (14)
Start at 19:19:59
Duration 15.50s (transform 41ms, setup 0ms, collect 415ms, tests 25.63s, environment 0ms, prepare 149ms)

Interactive Runner

Want a visual test runner?

npx super-pancake-ui

This opens an interactive test dashboard where you can see live results, inspect test cases, and view logs.

Press enter or click to view image in full size
Press enter or click to view image in full size

The report will look like this.

Press enter or click to view image in full size

⚙️ CI-Ready with HTML Reports

Super Pancake is great for CI/CD too. It generates HTML reports and screenshot logs automatically, so debugging failures is fast and visual.

You can integrate it with GitHub Actions, GitLab CI, or Jenkins using:

Conclusion

If you’re tired of over-complicated test setups and flaky drivers, Super Pancake is worth checking out. With just one command, you get everything — CDP-powered browser control, built-in assertions, HTML reports, and headless test execution.

Try it once, and you might just pancake-flip your testing workflow. 🥞

If you enjoyed this, follow me for more on testing, APIs, CI/CD, and dev automation!

I have created a project on GitHub and added the code here.

Feel free to hit clap if you like the content. Happy Automation Testing :) Cheers. 👏

If you’d like to support my work, please leave a good rating for my Chrome plugin here and my Firefox plugin here.

If you found this helpful, leave a ⭐ on GitHub or try contributing a test case!

--

--

Pradap Pandiyan
Pradap Pandiyan

Written by Pradap Pandiyan

I’m a passionate QA Engineer. I’m a motovlogger, content creator, off-roader and freelancer. Buy me a coffee here https://www.buymeacoffee.com/pradappandiyan

No responses yet