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;
|
||||
/** Page load event to wait for (default: domcontentloaded) */
|
||||
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 {
|
||||
|
|
@ -108,6 +112,18 @@ export class SnapAPI {
|
|||
* format: 'png',
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -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 () => {
|
||||
const mockArrayBuffer = new ArrayBuffer(100);
|
||||
mockFetch.mockResolvedValueOnce({
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class ScreenshotOptions:
|
|||
device_scale: Optional[float] = None
|
||||
delay: Optional[int] = None
|
||||
wait_until: Optional[str] = None
|
||||
dark_mode: Optional[bool] = None
|
||||
hide_selectors: Optional[list] = None
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Convert to API request body (camelCase keys)."""
|
||||
|
|
@ -46,6 +48,8 @@ class ScreenshotOptions:
|
|||
"device_scale": "deviceScale",
|
||||
"delay": "delay",
|
||||
"wait_until": "waitUntil",
|
||||
"dark_mode": "darkMode",
|
||||
"hide_selectors": "hideSelectors",
|
||||
}
|
||||
return {
|
||||
mapping[k]: v
|
||||
|
|
@ -98,6 +102,8 @@ class SnapAPI:
|
|||
device_scale: Optional[float] = None,
|
||||
delay: Optional[int] = None,
|
||||
wait_until: Optional[str] = None,
|
||||
dark_mode: Optional[bool] = None,
|
||||
hide_selectors: Optional[list] = None,
|
||||
options: Optional[ScreenshotOptions] = None,
|
||||
) -> bytes:
|
||||
"""Capture a screenshot.
|
||||
|
|
@ -113,6 +119,8 @@ class SnapAPI:
|
|||
device_scale: Device pixel ratio (1-3).
|
||||
delay: Extra delay in ms (0-5000).
|
||||
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).
|
||||
|
||||
Returns:
|
||||
|
|
@ -141,6 +149,13 @@ class SnapAPI:
|
|||
full_page=True,
|
||||
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:
|
||||
body = options.to_dict()
|
||||
|
|
@ -160,6 +175,8 @@ class SnapAPI:
|
|||
device_scale=device_scale,
|
||||
delay=delay,
|
||||
wait_until=wait_until,
|
||||
dark_mode=dark_mode,
|
||||
hide_selectors=hide_selectors,
|
||||
)
|
||||
body = opts.to_dict()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue