Skip to content

Commit 43babe8

Browse files
authored
Mock fakestoreapi.com requests (#4178)
- Creates a mockFakeStoreAPI() function to add to test beforeEach() statements. - Adds mocking statement to blueprints-editorial.spec.ts @samijaber Was this the `blueprints-editorial.spec.ts` file the main file causing errors? Or, should we add this mock statement elsewhere? <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds Playwright helpers to mock fakestoreapi.com and updates the editorial snippet test to use them for stable CI. > > - **Tests**: > - **Helpers**: > - Add `packages/sdks-tests/src/helpers/fakestoreapi-mock.ts` with `mockFakeStoreAPI` and `mockFakeStoreAPIAll` to intercept `fakestoreapi.com` product and image requests, returning mock JSON and a 1x1 PNG. > - **Snippet Test** (`packages/sdks-tests/src/snippet-tests/blueprints-editorial.spec.ts`): > - Import and invoke `mockFakeStoreAPI` in `beforeEach` and navigate to `/products/1`. > - Update suite/test names to remove "with Real Data" and verify product image, details, editorial content, and footer while keeping existing package skip list. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit cd3548d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent f3d3117 commit 43babe8

File tree

2 files changed

+141
-7
lines changed

2 files changed

+141
-7
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import type { Page, Route } from '@playwright/test';
2+
3+
/**
4+
* Mock product data matching the fakestoreapi.com schema
5+
*/
6+
const MOCK_PRODUCTS: Record<string, any> = {
7+
'1': {
8+
id: 1,
9+
title: 'Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops',
10+
price: 109.95,
11+
description:
12+
'Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday',
13+
category: "men's clothing",
14+
image: 'https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg',
15+
rating: {
16+
rate: 3.9,
17+
count: 120,
18+
},
19+
},
20+
'2': {
21+
id: 2,
22+
title: 'Mens Casual Premium Slim Fit T-Shirts',
23+
price: 22.3,
24+
description:
25+
'Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.',
26+
category: "men's clothing",
27+
image: 'https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg',
28+
rating: {
29+
rate: 4.1,
30+
count: 259,
31+
},
32+
},
33+
'3': {
34+
id: 3,
35+
title: 'Mens Cotton Jacket',
36+
price: 55.99,
37+
description:
38+
'great outerwear jackets for Spring/Autumn/Winter, suitable for many occasions, such as working, hiking, camping, mountain/rock climbing, cycling, traveling or other outdoors. Good gift choice for you or your family member. A warm hearted love to Father, husband or son in this thanksgiving or Christmas Day.',
39+
category: "men's clothing",
40+
image: 'https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg',
41+
rating: {
42+
rate: 4.7,
43+
count: 500,
44+
},
45+
},
46+
};
47+
48+
/**
49+
* Sets up Playwright route interception to mock fakestoreapi.com requests
50+
* @param page - Playwright Page object
51+
*/
52+
export async function mockFakeStoreAPI(page: Page) {
53+
// Mock product API requests
54+
await page.route('**/fakestoreapi.com/products/*', async (route: Route) => {
55+
const url = route.request().url();
56+
const productId = url.split('/products/')[1]?.split('?')[0];
57+
58+
// Get mock product data or use product 1 as fallback
59+
const product = MOCK_PRODUCTS[productId] || MOCK_PRODUCTS['1'];
60+
61+
await route.fulfill({
62+
status: 200,
63+
contentType: 'application/json',
64+
body: JSON.stringify(product),
65+
});
66+
});
67+
68+
// Mock image requests from fakestoreapi.com
69+
// This prevents tests from hanging when trying to load images from the blocked domain
70+
await page.route('**/fakestoreapi.com/img/**', async (route: Route) => {
71+
// Return a small transparent 1x1 PNG instead of trying to load from fakestoreapi.com
72+
const transparentPng = Buffer.from(
73+
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
74+
'base64'
75+
);
76+
77+
await route.fulfill({
78+
status: 200,
79+
contentType: 'image/png',
80+
body: transparentPng,
81+
});
82+
});
83+
}
84+
85+
/**
86+
* Sets up Playwright route interception to mock all fakestoreapi.com requests
87+
* This is a more comprehensive version that handles both product and products list endpoints
88+
* @param page - Playwright Page object
89+
*/
90+
export async function mockFakeStoreAPIAll(page: Page) {
91+
// Mock individual product requests
92+
await page.route('**/fakestoreapi.com/products/*', async (route: Route) => {
93+
const url = route.request().url();
94+
95+
// Skip if this is the /products endpoint without an ID
96+
if (url.endsWith('/products') || url.endsWith('/products/')) {
97+
return route.continue();
98+
}
99+
100+
const productId = url.split('/products/')[1]?.split('?')[0];
101+
const product = MOCK_PRODUCTS[productId] || MOCK_PRODUCTS['1'];
102+
103+
await route.fulfill({
104+
status: 200,
105+
contentType: 'application/json',
106+
body: JSON.stringify(product),
107+
});
108+
});
109+
110+
// Mock products list endpoint
111+
await page.route('**/fakestoreapi.com/products', async (route: Route) => {
112+
await route.fulfill({
113+
status: 200,
114+
contentType: 'application/json',
115+
body: JSON.stringify(Object.values(MOCK_PRODUCTS)),
116+
});
117+
});
118+
119+
// Mock image requests from fakestoreapi.com
120+
await page.route('**/fakestoreapi.com/img/**', async (route: Route) => {
121+
const transparentPng = Buffer.from(
122+
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
123+
'base64'
124+
);
125+
126+
await route.fulfill({
127+
status: 200,
128+
contentType: 'image/png',
129+
body: transparentPng,
130+
});
131+
});
132+
}

packages/sdks-tests/src/snippet-tests/blueprints-editorial.spec.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { expect } from '@playwright/test';
22
import { test } from '../helpers/index.js';
3+
import { mockFakeStoreAPI } from '../helpers/fakestoreapi-mock.js';
34

4-
test.describe('Product Editorial Page with Real Data', () => {
5+
test.describe('Product Editorial Page', () => {
56
test.beforeEach(async ({ page, packageName }) => {
6-
// TO-DO: the fakestoreapi.com calls are failing in the CI pipeline
7-
test.skip(true, 'fakestoreapi.com calls are failing in the CI pipeline');
8-
97
test.skip(
108
[
119
'react-native-74',
@@ -22,14 +20,18 @@ test.describe('Product Editorial Page with Real Data', () => {
2220
'gen1-next15-app',
2321
].includes(packageName)
2422
);
23+
24+
// Mock fakestoreapi.com to avoid anti-bot protection issues in CI
25+
await mockFakeStoreAPI(page);
26+
2527
await page.goto('/products/1');
2628
});
2729

2830
test('should render the header component', async ({ page }) => {
2931
await expect(page.locator('h1')).toHaveText('Acme Corp');
3032
});
3133

32-
test('should render the product info with real data', async ({ page }) => {
34+
test('should render the product info', async ({ page }) => {
3335
// Wait for the product image element to appear
3436
const productImage = page.locator('.product-image img');
3537
await expect(productImage).toBeAttached();
@@ -52,8 +54,8 @@ test.describe('Product Editorial Page with Real Data', () => {
5254
await expect(page.locator('p').nth(2)).toBeVisible();
5355
});
5456

55-
test('should render the editorial content with real data', async ({ page }) => {
56-
// verify that the editorial content is visible and has some text (as the real data may vary)
57+
test('should render the editorial content', async ({ page }) => {
58+
// verify that the editorial content is visible and has some text
5759
await expect(page.locator('.builder-blocks')).toBeVisible();
5860
await expect(page.locator('.builder-blocks')).toHaveText(/.+/);
5961
});

0 commit comments

Comments
 (0)