docs: show xQc in the product overview

Replace the generic README fixture with current public xQc profile and VOD data while keeping the screenshot capture isolated from local application data.
This commit is contained in:
Sucukdeluxe
2026-08-10 19:41:36 +02:00
parent b3c2a8b9fd
commit e601c3f3d5
2 changed files with 43 additions and 26 deletions
+43 -26
View File
@@ -9,6 +9,14 @@ const {
cleanupE2eEnvironment
} = require('./e2e-test-environment');
async function fetchImageDataUrl(url) {
const response = await fetch(url);
if (!response.ok) throw new Error(`Image request failed with ${response.status}`);
const contentType = response.headers.get('content-type') || 'image/jpeg';
const bytes = Buffer.from(await response.arrayBuffer());
return `data:${contentType};base64,${bytes.toString('base64')}`;
}
async function run() {
const environment = createE2eEnvironment('readme-screenshot', {
language: 'en',
@@ -19,71 +27,80 @@ async function run() {
let app;
try {
const publicImages = await Promise.all([
'https://static-cdn.jtvnw.net/jtv_user_pictures/xqc-profile_image-9298dca608632101-150x150.jpeg',
'https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/73cded95867be2fe9ed5_xqc_320952179547_1786313143//thumb/thumb0-640x360.jpg',
'https://static-cdn.jtvnw.net/cf_vods/d2vi6trrdongqn/a50a886595e03e3ef6ea_xqc_319796892764_1786132273//thumb/thumb0-640x360.jpg',
'https://static-cdn.jtvnw.net/cf_vods/d2vi6trrdongqn/94030284cfbb93ede7b8_xqc_319780491228_1786042905//thumb/thumb0-640x360.jpg',
'https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/f7d01c3a73dacdb116b3_xqc_320763288922_1785952851//thumb/thumb0-640x360.jpg',
'https://static-cdn.jtvnw.net/cf_vods/d1m7jfoe9zdc1j/d0086ce0b50cded348bb_xqc_320745551322_1785869163//thumb/thumb0-640x360.jpg',
'https://static-cdn.jtvnw.net/cf_vods/d2vi6trrdongqn/94d9a9b26ecc5891d8a0_xqc_319661776222_1785780125//thumb/thumb0-640x360.jpg'
].map(fetchImageDataUrl));
app = await electron.launch(getElectronLaunchOptions(environment));
const win = await app.firstWindow();
await verifyE2eIsolation(app, win, environment);
await installOfflineFixtures(app);
await app.evaluate(({ ipcMain }) => {
await app.evaluate(({ ipcMain }, images) => {
const image = (label, from, to) => {
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="640" height="360"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop stop-color="${from}"/><stop offset="1" stop-color="${to}"/></linearGradient></defs><rect width="640" height="360" fill="url(#g)"/><circle cx="520" cy="80" r="110" fill="rgba(255,255,255,.09)"/><circle cx="100" cy="320" r="170" fill="rgba(0,0,0,.12)"/><text x="34" y="300" fill="white" font-family="Segoe UI,Arial" font-size="34" font-weight="700">${label}</text></svg>`;
return `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}`;
};
const vods = [
['Ranked highlights and community games', '5h13m20s', 155331, '#6441a5', '#1f7ae0'],
['Late night challenge run', '7h39m0s', 241394, '#172554', '#7c3aed'],
['Tournament watch party', '5h59m10s', 183557, '#0f766e', '#2563eb'],
['Creative stream and Q&A', '3h40m3s', 94821, '#7c2d12', '#db2777'],
['Weekend co-op session', '4h50m0s', 127644, '#1e3a8a', '#0891b2'],
['Best moments from the week', '2h54m23s', 119663, '#581c87', '#be123c']
].map(([title, duration, viewCount, from, to], index) => ({
id: `demo-vod-${index + 1}`,
['🍝LIVE🍝DRAMA🍝NEWS🍝VIDEOS🍝GAMES🍝REACTS🍝VIDEOGAMES🍝FUN🍝COOL🍝THINGS🍝IMPORTANT🍝BROADCAST🍝SESSION🍝WICKED🍝', '2026-08-09T22:05:48Z', '9h3m44s', 627553],
['🦴LIVE🦴DRAMA🦴NEWS🦴VIDEOS🦴IMPORTANT🦴COBBLEMON TOURNAMENT🦴WINNER🦴POV🦴WICKED🦴LETS GO YAY🦴IM HERE🦴', '2026-08-07T19:51:18Z', '5h26m23s', 464926],
['🤒LIVE🤒DRAMA🤒NEWS🤒COBBLEMON🤒IS LIVE🤒DAY4 IMPORTANT🤒LOCK IN🤒QUICKLY🤒BIG THINGS TODAY🤒DONT SLEEP IN🤒', '2026-08-06T19:01:50Z', '11h49m41s', 878537],
['👈LIVE👈CLICK👈HERE👈DRAMA👈NEWS👈VIDEOS👈GAMES👈COBBLEMON DAY3👈ALSO👈LONG WALK GAME👈FINISHSING?👈HOPEFULY👈LOCK IN👈', '2026-08-05T18:00:55Z', '12h11m17s', 877336],
['👨‍🎨LIVE👨‍🎨CLICK👨‍🎨DRAMA👨‍🎨NEWS👨‍🎨GAMES👨‍🎨VIDEOS👨‍🎨IM LATE👨‍🎨BUT COBBLEMON IS BACK👨‍🎨LOCK IN👨‍🎨WOOO👨‍🎨PULL UP👨‍🎨', '2026-08-04T18:46:08Z', '12h17m10s', 868187],
['🔮LIVE🔮CLICK🔮DRAMA🔮NEWS🔮VIDEOS🔮CLIPS🔮GAMES🔮VIDEOGAMES🔮THINGS🔮IMPORTANT🔮DAY🔮COBBLEMON SERVER🔮LETS GET IT🔮YIPEE🔮TEAM ROCKET POV', '2026-08-03T18:02:10Z', '10h59m24s', 950330]
].map(([title, createdAt, duration, viewCount], index) => ({
id: ['2841886176', '2839940123', '2839002231', '2838068542', '2837216764', '2836308921'][index],
title,
created_at: `2026-08-${String(9 - index).padStart(2, '0')}T18:00:00Z`,
created_at: createdAt,
duration,
thumbnail_url: image(`DEMO VOD ${index + 1}`, from, to),
url: `https://www.twitch.tv/videos/demo-${index + 1}`,
thumbnail_url: images[index + 1] || image(`xQc VOD ${index + 1}`, '#6441a5', '#1f7ae0'),
url: `https://www.twitch.tv/videos/${['2841886176', '2839940123', '2839002231', '2838068542', '2837216764', '2836308921'][index]}`,
view_count: viewCount,
stream_id: `demo-stream-${index + 1}`
stream_id: ''
}));
ipcMain.removeHandler('get-user-id');
ipcMain.handle('get-user-id', async () => 'demo-user');
ipcMain.handle('get-user-id', async () => '71092938');
ipcMain.removeHandler('get-vods');
ipcMain.handle('get-vods', async () => vods);
ipcMain.removeHandler('get-streamer-profile');
ipcMain.handle('get-streamer-profile', async () => ({
login: 'demo_channel',
displayName: 'DemoChannel',
avatarUrl: image('TVM', '#7c3aed', '#0ea5e9'),
login: 'xqc',
displayName: 'xQc',
avatarUrl: images[0] || image('xQc', '#7c3aed', '#0ea5e9'),
bannerUrl: '',
description: 'Example profile for the public product screenshot',
description: 'THE BEST AT ABSOLUTELY EVERYTHING. THE JUICER. LEADER OF THE JUICERS.',
broadcasterType: 'partner',
followerCount: 1250000,
followerCount: 12534104,
vodCount: vods.length,
lastStreamAt: '2026-08-09T18:00:00Z',
lastStreamAt: '2026-08-09T22:05:48Z',
isLive: false,
currentTitle: null,
currentGame: null,
currentStreamPreviewUrl: '',
currentStreamViewers: null,
twitchUrl: 'https://www.twitch.tv/demo_channel',
twitchUrl: 'https://www.twitch.tv/xqc',
fetchedAt: Date.now()
}));
ipcMain.removeHandler('get-streamer-display-names');
ipcMain.handle('get-streamer-display-names', async () => ({ demo_channel: 'DemoChannel' }));
});
ipcMain.handle('get-streamer-display-names', async () => ({ xqc: 'xQc' }));
}, publicImages);
await win.waitForFunction(() => typeof window.showTab === 'function');
await win.setViewportSize({ width: 1600, height: 900 });
await win.evaluate(async () => {
window.changeLanguage('en');
showTab('vods');
isConnected = true;
config.streamers = ['demo_channel'];
config.streamer_display_names = { demo_channel: 'DemoChannel' };
config.streamers = ['xqc'];
config.streamer_display_names = { xqc: 'xQc' };
config.sidebar_split_view = true;
streamerVodCache.clear();
streamerProfileCache.clear();
await window.hydrateStreamerDisplayNames();
await selectStreamer('demo_channel');
await selectStreamer('xqc');
});
await win.waitForTimeout(700);
fs.mkdirSync(path.dirname(outputPath), { recursive: true });