Mocking OTP Send and Verify APIs in WebdriverIO


Mocking APIs in end-to-end (E2E) tests is crucial to simulate real-world scenarios while keeping your tests fast, reliable, and independent of external services. In this blog, we’ll explore how to mock OTP send and OTP verify APIs using WebdriverIO.
By the end of this tutorial, you’ll be able to:
Mock OTP send success and failure.
Mock OTP verify success and failure.
Let’s dive in!
Why Mock API Calls in E2E Tests?
Reduce Dependency: Avoid relying on third-party services or backend endpoints.
Speed Up Tests: Skip waiting for real API responses.
Simulate Edge Cases: Test success and failure scenarios reliably.
WebdriverIO makes this easy with its mocking capabilities, provided by the @wdio/devtools-service
.
Setup: Add DevTools Service
To use WebdriverIO’s mocking features, ensure you have the @wdio/devtools-service
installed.
Install the Service
npm install @wdio/devtools-service
Update wdio.conf.js
Add the devtools
service to your WebdriverIO configuration:
services: ['devtools'],
This enables network interception and mocking during your tests.
Step 1: Mock OTP Send
Let’s start by mocking the OTP send API, which is typically triggered when a user enters their phone number and requests an OTP.
Scenario 1: OTP Send Success
Here’s how to simulate a successful OTP send response:
it('should mock OTP send success', async () => {
// Mock the OTP send API
const sendOtpMock = await browser.mock('/api/send-otp', { method: 'POST' });
// Respond with a success message
sendOtpMock.respond({
success: true,
message: 'OTP sent successfully',
}, {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
});
// Simulate user interaction
await browser.url('/login');
await $('#phone-input').setValue('9876543210');
await $('#send-otp-button').click();
// Validate success message
const otpSendMessage = await $('#otp-send-message').getText();
expect(otpSendMessage).toBe('OTP sent successfully');
});
Scenario 2: OTP Send Failure
For failure scenarios, return an error response like this:
it('should mock OTP send failure', async () => {
// Mock the OTP send API
const sendOtpMock = await browser.mock('/api/send-otp', { method: 'POST' });
// Respond with an error message
sendOtpMock.respond({
success: false,
message: 'Failed to send OTP. Please try again.',
}, {
statusCode: 400,
headers: { 'Content-Type': 'application/json' },
});
// Simulate user interaction
await $('#phone-input').setValue('1234567890');
await $('#send-otp-button').click();
// Validate error message
const otpSendError = await $('#otp-send-error').getText();
expect(otpSendError).toBe('Failed to send OTP. Please try again.');
});
Step 2: Mock OTP Verify
After sending the OTP, users typically input it to verify their identity. Let’s mock the OTP verification API.
Scenario 1: OTP Verify Success
Here’s how to simulate a successful OTP verification:
it('should mock OTP verify success', async () => {
// Mock the OTP verify API
const verifyOtpMock = await browser.mock('/api/verify-otp', { method: 'POST' });
// Respond with success
verifyOtpMock.respond({
success: true,
message: 'OTP verified successfully',
}, {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
});
// Simulate user interaction
await $('#otp-input').setValue('123456');
await $('#verify-otp-button').click();
// Validate success message
const successMessage = await $('#login-success-message').getText();
expect(successMessage).toBe('Login successful!');
});
Scenario 2: OTP Verify Failure
For failure scenarios, mock an invalid OTP response:
it('should mock OTP verify failure', async () => {
// Mock the OTP verify API
const verifyOtpMock = await browser.mock('/api/verify-otp', { method: 'POST' });
// Respond with an error message
verifyOtpMock.respond({
success: false,
message: 'Invalid OTP. Please try again.',
}, {
statusCode: 401,
headers: { 'Content-Type': 'application/json' },
});
// Simulate user interaction
await $('#otp-input').setValue('000000');
await $('#verify-otp-button').click();
// Validate error message
const errorMessage = await $('#otp-verify-error').getText();
expect(errorMessage).toBe('Invalid OTP. Please try again.');
});
Bonus: Dynamic OTP Verification
To validate different OTP values dynamically, you can use a callback in the respond
method:
const verifyOtpMock = await browser.mock('/api/verify-otp', { method: 'POST' });
verifyOtpMock.respond((request) => {
const { otp } = JSON.parse(request.postData);
return otp === '123456'
? { success: true, message: 'OTP verified successfully' }
: { success: false, message: 'Invalid OTP' };
}, { statusCode: 200 });
This allows you to simulate different responses based on the OTP entered.
Conclusion
By mocking API calls in WebdriverIO, you can simulate success and failure scenarios for OTP send and verify flows without relying on real APIs. This makes your tests faster, more reliable, and flexible for edge case testing.
Key Takeaways
Use
browser.mock
to intercept network requests.Use
respond
to return custom responses (success or failure).Simulate user interactions and validate results with assertions.
Mocking is a powerful way to ensure your login flows are thoroughly tested. Try these examples in your project, and let me know how it works for you!
Happy Testing!
Subscribe to my newsletter
Read articles from Pawan Gangwani directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Pawan Gangwani
Pawan Gangwani
I’m Pawan Gangwani, a passionate Full Stack Developer with over 12 years of experience in web development. Currently serving as a Lead Software Engineer at Lowes India, I specialize in modern web applications, particularly in React and performance optimization. I’m dedicated to best practices in coding, testing, and Agile methodologies. Outside of work, I enjoy table tennis, exploring new cuisines, and spending quality time with my family.