Twitch-VOD-Manager/scripts/smoke-test-settings-autosave.js
2026-03-06 02:05:23 +01:00

197 lines
5.2 KiB
JavaScript

const { _electron: electron } = require('playwright');
const path = require('path');
const fs = require('fs');
const APPDATA_DIR = path.join(process.env.PROGRAMDATA || 'C:\\ProgramData', 'Twitch_VOD_Manager');
const CONFIG_FILE = path.join(APPDATA_DIR, 'config.json');
const DEFAULT_CONFIG = {
client_id: '',
client_secret: '',
download_path: path.join(process.env.USERPROFILE || 'C:\\Users\\ploet', 'Desktop', 'Twitch_VODs'),
streamers: [],
theme: 'twitch',
download_mode: 'full',
part_minutes: 120,
language: 'en',
filename_template_vod: '{title}.mp4',
filename_template_parts: '{date}_Part{part_padded}.mp4',
filename_template_clip: '{date}_{part}.mp4',
smart_queue_scheduler: true,
performance_mode: 'balanced',
prevent_duplicate_downloads: true,
metadata_cache_minutes: 10
};
function backupFile(filePath) {
if (!fs.existsSync(filePath)) return null;
return fs.readFileSync(filePath);
}
function restoreFile(filePath, backup) {
if (backup === null) {
if (fs.existsSync(filePath)) {
fs.rmSync(filePath, { force: true });
}
return;
}
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, backup);
}
function writeConfig(config) {
fs.mkdirSync(path.dirname(CONFIG_FILE), { recursive: true });
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
}
function readConfig() {
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
}
async function launchApp() {
const electronPath = require('electron');
return electron.launch({
executablePath: electronPath,
args: ['.'],
cwd: process.cwd()
});
}
async function setSettingsAndBlur(win, mode, partMinutes) {
await win.evaluate(async ({ mode, partMinutes }) => {
window.showTab('settings');
const modeField = document.getElementById('downloadMode');
const partField = document.getElementById('partMinutes');
modeField.value = mode;
modeField.dispatchEvent(new Event('change', { bubbles: true }));
partField.focus();
partField.value = String(partMinutes);
partField.dispatchEvent(new Event('input', { bubbles: true }));
partField.blur();
await new Promise((resolve) => setTimeout(resolve, 250));
}, { mode, partMinutes });
}
async function setSettingsAndCloseImmediately(win, mode, partMinutes) {
await win.evaluate(({ mode, partMinutes }) => {
window.showTab('settings');
const modeField = document.getElementById('downloadMode');
const partField = document.getElementById('partMinutes');
modeField.value = mode;
modeField.dispatchEvent(new Event('change', { bubbles: true }));
partField.focus();
partField.value = String(partMinutes);
partField.dispatchEvent(new Event('input', { bubbles: true }));
}, { mode, partMinutes });
}
async function readSettingsFromUi(win) {
return win.evaluate(() => {
window.showTab('settings');
return {
downloadMode: document.getElementById('downloadMode')?.value || '',
partMinutes: document.getElementById('partMinutes')?.value || ''
};
});
}
async function run() {
const configBackup = backupFile(CONFIG_FILE);
const baseConfig = configBackup ? { ...DEFAULT_CONFIG, ...JSON.parse(String(configBackup)) } : { ...DEFAULT_CONFIG };
let app = null;
try {
writeConfig({
...baseConfig,
client_id: '',
client_secret: '',
download_mode: 'full',
part_minutes: 120
});
app = await launchApp();
let win = await app.firstWindow();
await win.waitForTimeout(2200);
await setSettingsAndBlur(win, 'parts', 60);
await app.close();
app = null;
const afterBlurClose = readConfig();
app = await launchApp();
win = await app.firstWindow();
await win.waitForTimeout(2200);
const reopenedAfterBlur = await readSettingsFromUi(win);
await app.close();
app = null;
writeConfig({
...baseConfig,
client_id: '',
client_secret: '',
download_mode: 'full',
part_minutes: 120
});
app = await launchApp();
win = await app.firstWindow();
await win.waitForTimeout(2200);
await setSettingsAndCloseImmediately(win, 'parts', 75);
await app.close();
app = null;
const afterDirectClose = readConfig();
const result = {
afterBlurClose: {
config: {
download_mode: afterBlurClose.download_mode,
part_minutes: afterBlurClose.part_minutes
},
ui: reopenedAfterBlur
},
afterDirectClose: {
config: {
download_mode: afterDirectClose.download_mode,
part_minutes: afterDirectClose.part_minutes
}
}
};
console.log(JSON.stringify(result, null, 2));
const blurCaseOk =
afterBlurClose.download_mode === 'parts' &&
afterBlurClose.part_minutes === 60 &&
reopenedAfterBlur.downloadMode === 'parts' &&
reopenedAfterBlur.partMinutes === '60';
const directCloseOk =
afterDirectClose.download_mode === 'parts' &&
afterDirectClose.part_minutes === 75;
process.exit(blurCaseOk && directCloseOk ? 0 : 1);
} finally {
if (app) {
try {
await app.close();
} catch {
// ignore
}
}
restoreFile(CONFIG_FILE, configBackup);
}
}
run().catch((err) => {
console.error(err);
process.exit(1);
});