// tests/providers/workable.test.mjs — moved verbatim from test-all.mjs (#1440). import { pass, fail, ROOT } from '../helpers.mjs'; import { join } from 'path'; import { pathToFileURL } from 'url'; console.log('\nProvider — workable'); try { const workableModule = await import(pathToFileURL(join(ROOT, 'providers/workable.mjs')).href); const workable = workableModule.default; const { parseWorkableMarkdown } = workableModule; // detect() — auto-detection from careers_url if (workable.id === 'workable') pass('workable.id is "workable"'); else fail(`workable.id is ${JSON.stringify(workable.id)}`); const hit = workable.detect({ name: 'TestCo', careers_url: 'https://apply.workable.com/optimile' }); if (hit && hit.url === 'https://apply.workable.com/optimile/jobs.md') { pass('workable.detect() resolves apply.workable.com/ → /jobs.md feed'); } else { fail(`workable.detect() returned ${JSON.stringify(hit)}`); } const miss = workable.detect({ name: 'TestCo', careers_url: 'https://example.com/careers' }); if (miss === null) pass('workable.detect() returns null for non-workable URLs'); else fail(`workable.detect() should return null, got ${JSON.stringify(miss)}`); // parse() — markdown table const sampleMd = [ '# Optimile — All Open Positions', '', '| Title | Department | Location | Type | Salary | Posted | Details |', '|---|---|---|---|---|---|---|', '| Senior AI PM | Product | Ghent, Belgium | Full-time | — | 2026-04-01 | [View](https://apply.workable.com/optimile/jobs/view/ABC123.md) |', '| Tech Lead | Engineering | Remote | Full-time | — | 2026-03-25 | [View](https://apply.workable.com/optimile/jobs/view/DEF456.md) |', ].join('\n'); const jobs = parseWorkableMarkdown(sampleMd, 'Optimile'); if (jobs.length === 2) pass('parseWorkableMarkdown extracts 2 jobs from 2-row table'); else fail(`parseWorkableMarkdown returned ${jobs.length} jobs, expected 2`); if (jobs[0]?.title === 'Senior AI PM' && jobs[0]?.location === 'Ghent, Belgium' && jobs[0]?.company === 'Optimile') { pass('parseWorkableMarkdown extracts title, location, company correctly'); } else { fail(`parseWorkableMarkdown row 0 = ${JSON.stringify(jobs[0])}`); } if (jobs[0]?.url === 'https://apply.workable.com/optimile/jobs/view/ABC123') { pass('parseWorkableMarkdown strips .md suffix from job URL'); } else { fail(`parseWorkableMarkdown should strip .md; got url=${JSON.stringify(jobs[0]?.url)}`); } // Robustness if (parseWorkableMarkdown('', 'X').length === 0) pass('empty input → empty result'); else fail('empty input should yield empty result'); if (parseWorkableMarkdown(null, 'X').length === 0) pass('null input → empty result (no crash)'); else fail('null input should yield empty result without crashing'); // fetch() reaches the http context on the happy path (allowed hostname). await workable.fetch( { name: 'Smoke', careers_url: 'https://apply.workable.com/optimile' }, { transport: 'http', fetchText: async (url) => { if (!url.startsWith('https://apply.workable.com/')) { throw new Error('fetchText called with unexpected URL'); } return '| Title | Department | Location | Type | Salary | Posted | Details |\n|---|---|---|---|---|---|---|\n'; }, fetchJson: async () => { throw new Error('fetchJson should not be called'); }, }, ); pass('workable.fetch() reaches fetchText on the happy path (allowed hostname)'); // fetch() rejects an unresolvable careers_url (no apply.workable.com match in URL). let rejected = false; try { await workable.fetch( { name: 'BadUrl', careers_url: 'https://evil.com/totally-not-workable' }, { transport: 'http', fetchText: async () => { throw new Error('SSRF! should not reach here'); }, fetchJson: async () => { throw new Error('SSRF! should not reach here'); }, }, ); } catch (e) { if (e.message.includes('cannot derive feed URL')) { rejected = true; } else { fail(`workable.fetch() rejected with wrong error: ${e.message}`); } } if (rejected) pass('workable.fetch() rejects unresolvable careers_url before fetch'); else fail('workable.fetch() should throw cannot-derive-feed-URL for non-Workable URLs'); // SSRF: malicious URL with apply.workable.com in the PATH (not hostname) must not be detected as Workable. // With strict URL parsing, the hostname `evil.example` fails the check and detect() returns null. if (workable.detect({ name: 'Spoof', careers_url: 'https://evil.example/apply.workable.com/slug' }) === null) { pass('workable.detect() rejects path-spoofed URLs (apply.workable.com in path, not hostname)'); } else { fail('workable.detect() must NOT misdetect URLs that contain apply.workable.com in the path'); } // careers_url with non-string value (e.g. YAML mistake passing a number) → detect() returns null without crashing if (workable.detect({ name: 'X', careers_url: 42 }) === null) { pass('workable.detect() returns null for non-string careers_url (42)'); } else { fail('workable.detect() should treat non-string careers_url as missing'); } // Workable parser tolerates a title with a stray pipe — URL is extracted from the line, not cols[7] const strayPipeMd = [ '| Title | Department | Location | Type | Salary | Posted | Details |', '|---|---|---|---|---|---|---|', '| Senior PM (full | part-time) | Product | Remote | Full-time | — | 2026-04-01 | [View](https://apply.workable.com/x/jobs/view/PIPE.md) |', ].join('\n'); const strayJobs = parseWorkableMarkdown(strayPipeMd, 'X'); if (strayJobs.length === 1 && strayJobs[0].url === 'https://apply.workable.com/x/jobs/view/PIPE') { pass('parseWorkableMarkdown extracts URL from line-level regex (survives stray pipes in title)'); } else { fail(`stray-pipe row not handled correctly: ${JSON.stringify(strayJobs)}`); } // Off-domain [View] link is dropped (URL validation) const offDomainMd = [ '| Title | Department | Location | Type | Salary | Posted | Details |', '|---|---|---|---|---|---|---|', '| Good Role | Product | Remote | Full-time | — | 2026-04-01 | [View](https://apply.workable.com/x/jobs/view/ABC.md) |', '| Evil Role | Product | Remote | Full-time | — | 2026-04-01 | [View](https://evil.example/jobs/view/X) |', '| Insecure Role | Product | Remote | Full-time | — | 2026-04-01 | [View](http://apply.workable.com/x/jobs/view/Y.md) |', ].join('\n'); const filteredJobs = parseWorkableMarkdown(offDomainMd, 'X'); if (filteredJobs.length === 1 && filteredJobs[0].title === 'Good Role') { pass('parseWorkableMarkdown drops off-domain and non-https [View] links'); } else { fail(`expected only "Good Role" through, got ${JSON.stringify(filteredJobs.map(j => j.title))}`); } } catch (e) { fail(`workable provider tests crashed: ${e.message}`); }