feat: add darkMode and hideSelectors to Node.js and Python SDKs
Some checks failed
Build & Deploy to Staging / Build & Deploy to Staging (push) Has been cancelled
Some checks failed
Build & Deploy to Staging / Build & Deploy to Staging (push) Has been cancelled
This commit is contained in:
parent
96d21aa63b
commit
90c1e7da44
3 changed files with 125 additions and 0 deletions
|
|
@ -33,6 +33,10 @@ export interface ScreenshotOptions {
|
||||||
delay?: number;
|
delay?: number;
|
||||||
/** Page load event to wait for (default: domcontentloaded) */
|
/** Page load event to wait for (default: domcontentloaded) */
|
||||||
waitUntil?: "load" | "domcontentloaded" | "networkidle0" | "networkidle2";
|
waitUntil?: "load" | "domcontentloaded" | "networkidle0" | "networkidle2";
|
||||||
|
/** Emulate dark mode (prefers-color-scheme: dark) */
|
||||||
|
darkMode?: boolean;
|
||||||
|
/** CSS selectors to hide before capture (max 10, each max 200 chars) */
|
||||||
|
hideSelectors?: string | string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SnapAPIConfig {
|
export interface SnapAPIConfig {
|
||||||
|
|
@ -108,6 +112,18 @@ export class SnapAPI {
|
||||||
* format: 'png',
|
* format: 'png',
|
||||||
* deviceScale: 2
|
* deviceScale: 2
|
||||||
* });
|
* });
|
||||||
|
*
|
||||||
|
* // Dark mode with hidden elements
|
||||||
|
* const darkScreenshot = await snap.capture({
|
||||||
|
* url: 'https://example.com',
|
||||||
|
* darkMode: true,
|
||||||
|
* hideSelectors: ['.ads', '.popup', '.cookie-banner']
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // Hide single selector
|
||||||
|
* const clean = await snap.capture('https://example.com', {
|
||||||
|
* hideSelectors: '.advertisement'
|
||||||
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @throws {SnapAPIError} When the API returns an error response
|
* @throws {SnapAPIError} When the API returns an error response
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,98 @@ describe('SnapAPI', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends darkMode parameter correctly', async () => {
|
||||||
|
const mockArrayBuffer = new ArrayBuffer(100);
|
||||||
|
mockFetch.mockResolvedValueOnce({
|
||||||
|
ok: true,
|
||||||
|
arrayBuffer: () => Promise.resolve(mockArrayBuffer),
|
||||||
|
});
|
||||||
|
|
||||||
|
await snap.capture('https://example.com', {
|
||||||
|
darkMode: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalledWith(
|
||||||
|
'https://snapapi.eu/v1/screenshot',
|
||||||
|
expect.objectContaining({
|
||||||
|
body: JSON.stringify({
|
||||||
|
url: 'https://example.com',
|
||||||
|
darkMode: true,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends hideSelectors as string correctly', async () => {
|
||||||
|
const mockArrayBuffer = new ArrayBuffer(100);
|
||||||
|
mockFetch.mockResolvedValueOnce({
|
||||||
|
ok: true,
|
||||||
|
arrayBuffer: () => Promise.resolve(mockArrayBuffer),
|
||||||
|
});
|
||||||
|
|
||||||
|
await snap.capture('https://example.com', {
|
||||||
|
hideSelectors: '.ads',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalledWith(
|
||||||
|
'https://snapapi.eu/v1/screenshot',
|
||||||
|
expect.objectContaining({
|
||||||
|
body: JSON.stringify({
|
||||||
|
url: 'https://example.com',
|
||||||
|
hideSelectors: '.ads',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends hideSelectors as array correctly', async () => {
|
||||||
|
const mockArrayBuffer = new ArrayBuffer(100);
|
||||||
|
mockFetch.mockResolvedValueOnce({
|
||||||
|
ok: true,
|
||||||
|
arrayBuffer: () => Promise.resolve(mockArrayBuffer),
|
||||||
|
});
|
||||||
|
|
||||||
|
await snap.capture('https://example.com', {
|
||||||
|
hideSelectors: ['.ads', '.popup', '.banner'],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalledWith(
|
||||||
|
'https://snapapi.eu/v1/screenshot',
|
||||||
|
expect.objectContaining({
|
||||||
|
body: JSON.stringify({
|
||||||
|
url: 'https://example.com',
|
||||||
|
hideSelectors: ['.ads', '.popup', '.banner'],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends both darkMode and hideSelectors together', async () => {
|
||||||
|
const mockArrayBuffer = new ArrayBuffer(100);
|
||||||
|
mockFetch.mockResolvedValueOnce({
|
||||||
|
ok: true,
|
||||||
|
arrayBuffer: () => Promise.resolve(mockArrayBuffer),
|
||||||
|
});
|
||||||
|
|
||||||
|
await snap.capture('https://example.com', {
|
||||||
|
darkMode: true,
|
||||||
|
hideSelectors: ['.ads', '.tracking'],
|
||||||
|
format: 'png',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalledWith(
|
||||||
|
'https://snapapi.eu/v1/screenshot',
|
||||||
|
expect.objectContaining({
|
||||||
|
body: JSON.stringify({
|
||||||
|
url: 'https://example.com',
|
||||||
|
darkMode: true,
|
||||||
|
hideSelectors: ['.ads', '.tracking'],
|
||||||
|
format: 'png',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('works with ScreenshotOptions object form', async () => {
|
it('works with ScreenshotOptions object form', async () => {
|
||||||
const mockArrayBuffer = new ArrayBuffer(100);
|
const mockArrayBuffer = new ArrayBuffer(100);
|
||||||
mockFetch.mockResolvedValueOnce({
|
mockFetch.mockResolvedValueOnce({
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ class ScreenshotOptions:
|
||||||
device_scale: Optional[float] = None
|
device_scale: Optional[float] = None
|
||||||
delay: Optional[int] = None
|
delay: Optional[int] = None
|
||||||
wait_until: Optional[str] = None
|
wait_until: Optional[str] = None
|
||||||
|
dark_mode: Optional[bool] = None
|
||||||
|
hide_selectors: Optional[list] = None
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
"""Convert to API request body (camelCase keys)."""
|
"""Convert to API request body (camelCase keys)."""
|
||||||
|
|
@ -46,6 +48,8 @@ class ScreenshotOptions:
|
||||||
"device_scale": "deviceScale",
|
"device_scale": "deviceScale",
|
||||||
"delay": "delay",
|
"delay": "delay",
|
||||||
"wait_until": "waitUntil",
|
"wait_until": "waitUntil",
|
||||||
|
"dark_mode": "darkMode",
|
||||||
|
"hide_selectors": "hideSelectors",
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
mapping[k]: v
|
mapping[k]: v
|
||||||
|
|
@ -98,6 +102,8 @@ class SnapAPI:
|
||||||
device_scale: Optional[float] = None,
|
device_scale: Optional[float] = None,
|
||||||
delay: Optional[int] = None,
|
delay: Optional[int] = None,
|
||||||
wait_until: Optional[str] = None,
|
wait_until: Optional[str] = None,
|
||||||
|
dark_mode: Optional[bool] = None,
|
||||||
|
hide_selectors: Optional[list] = None,
|
||||||
options: Optional[ScreenshotOptions] = None,
|
options: Optional[ScreenshotOptions] = None,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
"""Capture a screenshot.
|
"""Capture a screenshot.
|
||||||
|
|
@ -113,6 +119,8 @@ class SnapAPI:
|
||||||
device_scale: Device pixel ratio (1-3).
|
device_scale: Device pixel ratio (1-3).
|
||||||
delay: Extra delay in ms (0-5000).
|
delay: Extra delay in ms (0-5000).
|
||||||
wait_until: Load event (domcontentloaded, load, networkidle0, networkidle2).
|
wait_until: Load event (domcontentloaded, load, networkidle0, networkidle2).
|
||||||
|
dark_mode: Emulate dark mode (prefers-color-scheme: dark).
|
||||||
|
hide_selectors: CSS selectors to hide before capture (max 10, each max 200 chars).
|
||||||
options: ScreenshotOptions object (alternative to keyword args).
|
options: ScreenshotOptions object (alternative to keyword args).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
@ -141,6 +149,13 @@ class SnapAPI:
|
||||||
full_page=True,
|
full_page=True,
|
||||||
device_scale=2,
|
device_scale=2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Dark mode with hidden elements
|
||||||
|
dark_screenshot = snap.capture(
|
||||||
|
"https://example.com",
|
||||||
|
dark_mode=True,
|
||||||
|
hide_selectors=['.ads', '.popup', '.cookie-banner']
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
if options:
|
if options:
|
||||||
body = options.to_dict()
|
body = options.to_dict()
|
||||||
|
|
@ -160,6 +175,8 @@ class SnapAPI:
|
||||||
device_scale=device_scale,
|
device_scale=device_scale,
|
||||||
delay=delay,
|
delay=delay,
|
||||||
wait_until=wait_until,
|
wait_until=wait_until,
|
||||||
|
dark_mode=dark_mode,
|
||||||
|
hide_selectors=hide_selectors,
|
||||||
)
|
)
|
||||||
body = opts.to_dict()
|
body = opts.to_dict()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue