mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
117 lines
3.7 KiB
JavaScript
117 lines
3.7 KiB
JavaScript
/*
|
|
* Copyright (c) 2026 by Christian Kellner.
|
|
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
|
*/
|
|
|
|
import { readFile } from 'fs/promises';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const FIXTURES_DIR = path.join(__dirname, 'testFixtures');
|
|
|
|
const testProviderConfig = JSON.parse(
|
|
await readFile(new URL('./provider/testProvider.json', import.meta.url), 'utf-8'),
|
|
);
|
|
|
|
// hostname → providerName, built from testProvider.json
|
|
const hostnameToProvider = {};
|
|
// providerName → list page pathname (for distinguishing list vs detail URLs)
|
|
const providerListPath = {};
|
|
|
|
for (const [name, cfg] of Object.entries(testProviderConfig)) {
|
|
if (!cfg.url) continue;
|
|
try {
|
|
const parsed = new URL(cfg.url);
|
|
hostnameToProvider[parsed.hostname] = name;
|
|
providerListPath[name] = parsed.pathname;
|
|
} catch {
|
|
// skip malformed URLs
|
|
}
|
|
}
|
|
|
|
async function tryReadFile(filepath) {
|
|
try {
|
|
return await readFile(filepath, 'utf-8');
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function withRealEstateType(data, realEstateType) {
|
|
if (!realEstateType?.length || !Array.isArray(data?.resultListItems)) {
|
|
return data;
|
|
}
|
|
|
|
const cloned = typeof structuredClone === 'function' ? structuredClone(data) : JSON.parse(JSON.stringify(data));
|
|
for (const item of cloned.resultListItems) {
|
|
if (item?.type === 'EXPOSE_RESULT' && item?.item) {
|
|
item.item.realEstateType = realEstateType;
|
|
}
|
|
}
|
|
return cloned;
|
|
}
|
|
|
|
/**
|
|
* Returns fixture HTML for the given URL by mapping hostname → provider name,
|
|
* then distinguishing list vs detail pages by comparing the URL path against
|
|
* the configured list URL path from testProvider.json.
|
|
*/
|
|
export async function readFixture(url) {
|
|
let hostname, pathname;
|
|
try {
|
|
const parsed = new URL(url);
|
|
hostname = parsed.hostname;
|
|
pathname = parsed.pathname;
|
|
} catch {
|
|
return null;
|
|
}
|
|
|
|
const providerName = hostnameToProvider[hostname];
|
|
if (!providerName) return null;
|
|
|
|
if (providerListPath[providerName] === pathname) {
|
|
return tryReadFile(path.join(FIXTURES_DIR, `${providerName}.html`));
|
|
}
|
|
|
|
// Detail page: prefer dedicated detail fixture, fall back to list fixture
|
|
const detailHtml = await tryReadFile(path.join(FIXTURES_DIR, `${providerName}_detail.html`));
|
|
if (detailHtml) return detailHtml;
|
|
return tryReadFile(path.join(FIXTURES_DIR, `${providerName}.html`));
|
|
}
|
|
|
|
/**
|
|
* Returns a fetch replacement that intercepts immoscout mobile API calls and
|
|
* serves pre-downloaded JSON fixtures. Throws for any other URL to prevent
|
|
* accidental live network traffic in offline mode.
|
|
*/
|
|
export function buildFetchMock() {
|
|
let listData = null;
|
|
let detailData = null;
|
|
|
|
return async (url) => {
|
|
const urlStr = String(url);
|
|
|
|
if (urlStr.includes('api.mobile.immobilienscout24.de/search/list')) {
|
|
if (!listData) {
|
|
const raw = await tryReadFile(path.join(FIXTURES_DIR, 'immoscout_list.json'));
|
|
listData = raw ? JSON.parse(raw) : { resultListItems: [] };
|
|
}
|
|
|
|
const requestedType = new URL(urlStr).searchParams.get('realestatetype');
|
|
const responseData = withRealEstateType(listData, requestedType);
|
|
return { ok: true, status: 200, json: () => Promise.resolve(responseData) };
|
|
}
|
|
|
|
if (urlStr.includes('api.mobile.immobilienscout24.de/expose/')) {
|
|
if (!detailData) {
|
|
const raw = await tryReadFile(path.join(FIXTURES_DIR, 'immoscout_detail.json'));
|
|
detailData = raw ? JSON.parse(raw) : { sections: [], contact: {} };
|
|
}
|
|
return { ok: true, status: 200, json: () => Promise.resolve(detailData) };
|
|
}
|
|
|
|
throw new Error(`Network request blocked in offline mode: ${urlStr}`);
|
|
};
|
|
}
|