feat: add support for indicating workplaceTypes (#296)

This commit is contained in:
Ryan Foote
2026-03-21 20:43:43 +00:00
committed by GitHub
parent 8274ec4e14
commit 0b22c08d7d
25 changed files with 497 additions and 5 deletions
+3
View File
@@ -63,6 +63,9 @@ export const manifest: ExtractorManifest = {
single:
context.settings.searchCities ?? context.settings.jobspyLocation,
}),
workplaceTypes: context.settings.workplaceTypes
? JSON.parse(context.settings.workplaceTypes)
: undefined,
maxJobsPerTerm,
shouldCancel: context.shouldCancel,
onProgress: (event) => {
+15
View File
@@ -30,6 +30,7 @@ export interface RunStartupJobsOptions {
searchTerms?: string[];
selectedCountry?: string;
locations?: string[];
workplaceTypes?: Array<"remote" | "hybrid" | "onsite">;
maxJobsPerTerm?: number;
onProgress?: (event: StartupJobsProgressEvent) => void;
shouldCancel?: () => boolean;
@@ -41,6 +42,18 @@ export interface StartupJobsResult {
error?: string;
}
type StartupJobsWorkplaceType = "remote" | "hybrid" | "on-site";
function mapWorkplaceTypes(
workplaceTypes: Array<"remote" | "hybrid" | "onsite"> | undefined,
): StartupJobsWorkplaceType[] | undefined {
if (!workplaceTypes || workplaceTypes.length === 0) return undefined;
return workplaceTypes.map((workplaceType) =>
workplaceType === "onsite" ? "on-site" : workplaceType,
);
}
function toPositiveIntOrFallback(
value: number | string | undefined,
fallback: number,
@@ -123,6 +136,7 @@ export async function runStartupJobs(
locations: options.locations,
});
const maxJobsPerTerm = toPositiveIntOrFallback(options.maxJobsPerTerm, 50);
const workplaceType = mapWorkplaceTypes(options.workplaceTypes);
const termTotal = searchTerms.length * runLocations.length;
const jobs: CreateJobInput[] = [];
const seen = new Set<string>();
@@ -149,6 +163,7 @@ export async function runStartupJobs(
requestedCount: maxJobsPerTerm,
enrichDetails: true,
location: location ?? undefined,
workplaceType,
});
let jobsFoundTerm = 0;
@@ -35,4 +35,30 @@ describe("startupjobs manifest", () => {
}),
);
});
it("forwards workplace types to the runner", async () => {
const { manifest } = await import("../src/manifest");
const { runStartupJobs } = await import("../src/run");
const runStartupJobsMock = vi.mocked(runStartupJobs);
runStartupJobsMock.mockResolvedValue({
success: true,
jobs: [],
});
await manifest.run({
source: "startupjobs",
selectedSources: ["startupjobs"],
settings: {
workplaceTypes: '["remote","onsite"]',
},
searchTerms: ["software engineer"],
selectedCountry: "united kingdom",
});
expect(runStartupJobsMock).toHaveBeenCalledWith(
expect.objectContaining({
workplaceTypes: ["remote", "onsite"],
}),
);
});
});
+42
View File
@@ -72,4 +72,46 @@ describe("runStartupJobs", () => {
}),
);
});
it("passes workplaceType to the scraper", async () => {
const { scrapeStartupJobsViaAlgolia } = await import(
"startup-jobs-scraper"
);
const scrapeMock = vi.mocked(scrapeStartupJobsViaAlgolia);
scrapeMock.mockResolvedValueOnce([]);
const { runStartupJobs } = await import("../src/run");
await runStartupJobs({
searchTerms: ["software engineer"],
workplaceTypes: ["remote", "hybrid"],
});
expect(scrapeMock).toHaveBeenCalledWith(
expect.objectContaining({
workplaceType: ["remote", "hybrid"],
}),
);
});
it("maps onsite workplaceType to the scraper's on-site value", async () => {
const { scrapeStartupJobsViaAlgolia } = await import(
"startup-jobs-scraper"
);
const scrapeMock = vi.mocked(scrapeStartupJobsViaAlgolia);
scrapeMock.mockResolvedValueOnce([]);
const { runStartupJobs } = await import("../src/run");
await runStartupJobs({
searchTerms: ["software engineer"],
workplaceTypes: ["onsite"],
});
expect(scrapeMock).toHaveBeenCalledWith(
expect.objectContaining({
workplaceType: ["on-site"],
}),
);
});
});