Files
santifer--career-ops/tests/providers/remoteok.test.mjs
T
wehub-resource-sync d083df1fdb
CodeQL Analysis / Analyze (javascript-typescript) (push) Failing after 2s
Web CI / web typecheck + build (push) Failing after 1s
Release Please / release-please (push) Failing after 1s
CodeQL Analysis / Analyze (go) (push) Failing after 16s
chore: import upstream snapshot with attribution
2026-07-13 12:02:43 +08:00

131 lines
6.5 KiB
JavaScript

// tests/providers/remoteok.test.mjs — direct provider-contract tests (#1499).
// RemoteOK is a board-wide aggregator feed: no detect(), a fixed FEED_URL, and
// an API quirk — index 0 of the returned array is a {last_updated, legal}
// metadata object, not a job. These tests pin the id/fetch contract that
// scan.mjs relies on, with a deterministic mock ctx (no network).
import { pass, fail, ROOT } from '../helpers.mjs';
import { join } from 'path';
import { pathToFileURL } from 'url';
console.log('\nProvider — remoteok');
try {
const remoteokModule = await import(pathToFileURL(join(ROOT, 'providers/remoteok.mjs')).href);
const remoteok = remoteokModule.default;
if (remoteok.id === 'remoteok') pass('remoteok.id is "remoteok"');
else fail(`remoteok.id is ${JSON.stringify(remoteok.id)}`);
// Board-wide feed: no detect() — wired in explicitly via `provider: remoteok`.
if (remoteok.detect === undefined && typeof remoteok.fetch === 'function') {
pass('remoteok exposes fetch() only (no detect — explicit provider: wiring)');
} else {
fail(`remoteok surface: detect=${typeof remoteok.detect}, fetch=${typeof remoteok.fetch}`);
}
// Deterministic sample payload mirroring the real feed shape: metadata object
// at index 0, then job rows keyed by `position` (not `title`).
const sample = [
{ last_updated: 1751500000, legal: 'API terms...' }, // metadata row — must be dropped
{
slug: 'acme-staff-ai-engineer',
position: 'Staff AI Engineer',
company: 'Acme Corp',
location: 'Worldwide',
url: 'https://remoteok.com/remote-jobs/acme-staff-ai-engineer',
date: '2026-07-01T00:00:00+00:00',
},
{
position: ' Platform Engineer ', // whitespace → trimmed
company: ' ', // whitespace-only → falls back to entry.name
location: null, // non-string → ''
url: ' https://remoteok.com/remote-jobs/beta-platform-engineer ',
},
null, // null row — must be skipped
'not-an-object', // non-object row — must be skipped
{ position: '', url: 'https://remoteok.com/remote-jobs/empty' }, // empty position — skip
{ position: 'Relative URL Role', url: '/remote-jobs/relative' }, // non-absolute url — skip
{ position: 'No URL Role' }, // missing url — skip
];
let capturedUrl = null;
let capturedOpts = null;
const fetched = await remoteok.fetch(
{ name: 'RemoteOK Board', provider: 'remoteok' },
{ fetchJson: async (url, opts) => { capturedUrl = url; capturedOpts = opts; return sample; } },
);
if (capturedUrl === 'https://remoteok.com/api')
pass('remoteok.fetch() requests the fixed board-wide feed URL');
else fail(`remoteok.fetch() requested ${JSON.stringify(capturedUrl)}`);
if (capturedOpts && capturedOpts.redirect === 'error')
pass('remoteok.fetch() passes redirect:"error" to fetchJson (SSRF guard)');
else fail(`remoteok.fetch() should pass redirect:"error", got: ${JSON.stringify(capturedOpts)}`);
if (fetched.length === 2)
pass('remoteok.fetch() keeps 2 valid jobs (drops metadata row, null, non-object, empty-position, bad-url rows)');
else fail(`remoteok.fetch() returned ${fetched.length} jobs (expected 2): ${JSON.stringify(fetched)}`);
// Normalized shape: exactly { title, url, company, location }.
if (fetched[0] && Object.keys(fetched[0]).sort().join(',') === 'company,location,title,url')
pass('remoteok.fetch() returns the normalized { title, url, company, location } shape');
else fail(`remoteok.fetch() row 0 keys = ${JSON.stringify(fetched[0] && Object.keys(fetched[0]))}`);
if (fetched[0]?.title === 'Staff AI Engineer'
&& fetched[0]?.url === 'https://remoteok.com/remote-jobs/acme-staff-ai-engineer'
&& fetched[0]?.company === 'Acme Corp'
&& fetched[0]?.location === 'Worldwide')
pass('remoteok.fetch() maps position/url/company/location for a full row');
else fail(`remoteok.fetch() row 0 = ${JSON.stringify(fetched[0])}`);
if (fetched[1]?.title === 'Platform Engineer'
&& fetched[1]?.url === 'https://remoteok.com/remote-jobs/beta-platform-engineer')
pass('remoteok.fetch() trims whitespace from title and url');
else fail(`remoteok.fetch() row 1 title/url = ${JSON.stringify({ title: fetched[1]?.title, url: fetched[1]?.url })}`);
if (fetched[1]?.company === 'RemoteOK Board')
pass('remoteok.fetch() falls back to entry.name when company is whitespace-only');
else fail(`remoteok.fetch() row 1 company = ${JSON.stringify(fetched[1]?.company)}`);
if (fetched[1]?.location === '')
pass('remoteok.fetch() yields empty location for a non-string location value');
else fail(`remoteok.fetch() row 1 location = ${JSON.stringify(fetched[1]?.location)}`);
// company default when both the row's company and entry.name are missing → 'RemoteOK'.
const noName = await remoteok.fetch(
{},
{ fetchJson: async () => [{ position: 'Role', url: 'https://remoteok.com/remote-jobs/x' }] },
);
if (noName[0]?.company === 'RemoteOK')
pass('remoteok.fetch() defaults company to "RemoteOK" when company and entry.name are both missing');
else fail(`remoteok.fetch() default company = ${JSON.stringify(noName[0]?.company)}`);
// Non-array API response → typed error, not a silent empty result.
let badResponseThrew = false;
try {
await remoteok.fetch(
{ name: 'X', provider: 'remoteok' },
{ fetchJson: async () => ({ jobs: [] }) },
);
} catch (e) {
badResponseThrew = /unexpected API response/.test(e.message);
}
if (badResponseThrew) pass('remoteok.fetch() throws on a non-array API response');
else fail('remoteok.fetch() should throw when the response is not an array');
// null response → the error message must say "null", not "object".
let nullResponseMsg = '';
try {
await remoteok.fetch({ name: 'X' }, { fetchJson: async () => null });
} catch (e) {
nullResponseMsg = e.message;
}
if (/unexpected API response/.test(nullResponseMsg) && /got null/.test(nullResponseMsg))
pass('remoteok.fetch() reports "null" (not "object") for a null API response');
else fail(`remoteok.fetch() null-response error = ${JSON.stringify(nullResponseMsg)}`);
} catch (e) {
fail(`remoteok provider tests crashed: ${e.message}`);
}