// // IndeedHTMLJobParserTests.swift // indeed_ai_job_searchTests // import XCTest @testable import indeed_ai_job_search final class IndeedHTMLJobParserTests: XCTestCase { func testDetectsCaptchaPage() { let html = """ Security Check - Indeed.com """ XCTAssertTrue(IndeedHTMLJobParser.isBlockedOrCaptcha(html)) XCTAssertThrowsError( try IndeedHTMLJobParser.parse( html: html, pageURL: URL(string: "https://www.indeed.com/jobs")! ) ) { error in guard case IndeedDataError.forbidden = error else { return XCTFail("Expected forbidden, got \(error)") } } } func testParsesEmbeddedJobKeyJSON() throws { let html = """
""" let pageURL = URL(string: "https://www.indeed.com/jobs?q=iOS")! let dtos = try IndeedHTMLJobParser.parse(html: html, pageURL: pageURL) XCTAssertGreaterThanOrEqual(dtos.count, 2) let tuyo = try XCTUnwrap(dtos.first { $0.jobKey == "5185d0dd8c286093" }) XCTAssertEqual(tuyo.title, "iOS Engineer") XCTAssertEqual(tuyo.company, "Tuyo") XCTAssertTrue(tuyo.url.contains("5185d0dd8c286093")) XCTAssertTrue(IndeedBrowseURLBuilder.isLikelyRealJobKey(tuyo.jobKey ?? "")) let mapped = try IndeedListingMapper.map(tuyo) XCTAssertEqual(mapped.company, "Tuyo") XCTAssertTrue(mapped.indeedURL.absoluteString.contains("viewjob")) XCTAssertFalse(IndeedBrowseURLBuilder.openableURL(for: mapped).usedBrowseFallback) } func testParsesDataJKHTMLCards() throws { let html = """

SwiftUI Developer

Nexlify Studio
Lahore, Pakistan
Rs 1,800,000 - Rs 2,800,000 a year
""" let dtos = try IndeedHTMLJobParser.parse( html: html, pageURL: URL(string: "https://pk.indeed.com/jobs")! ) let job = try XCTUnwrap(dtos.first) XCTAssertEqual(job.jobKey, "abcdef0123456789") XCTAssertEqual(job.title, "SwiftUI Developer") XCTAssertEqual(job.company, "Nexlify Studio") XCTAssertEqual(job.salaryCurrency, "PKR") } } final class IndeedSearchURLBuilderTests: XCTestCase { func testBuildsPakistanHostFromCountry() { var criteria = SearchCriteria() criteria.jobTitle = "iOS Developer" criteria.country = "Pakistan" criteria.city = "Lahore" let url = IndeedSearchURLBuilder.searchURL(criteria: criteria, query: "iOS developer") XCTAssertEqual(url.host, "pk.indeed.com") XCTAssertTrue(url.path.contains("/jobs")) let q = URLComponents(url: url, resolvingAgainstBaseURL: false)? .queryItems?.first { $0.name == "q" }?.value XCTAssertEqual(q, "iOS Developer") } func testRemoteOnlySetsLocationRemote() { var criteria = SearchCriteria() criteria.jobTitle = "iOS" criteria.remoteTypes = [.remote] let url = IndeedSearchURLBuilder.searchURL(criteria: criteria, query: "iOS") let loc = URLComponents(url: url, resolvingAgainstBaseURL: false)? .queryItems?.first { $0.name == "l" }?.value XCTAssertEqual(loc, "Remote") } } final class JobListingFilterUnknownFieldTests: XCTestCase { func testKeepsListingWhenEmploymentUnknownButFilterSet() { var listing = JobListing( indeedJobKey: "5185d0dd8c286093", title: "iOS Developer", company: "Acme", location: "Remote", remoteType: .remote, employmentType: nil, postedAt: Date(), snippet: "Swift", indeedURL: URL(string: "https://www.indeed.com/viewjob?jk=5185d0dd8c286093")! ) var criteria = SearchCriteria() criteria.jobTitle = "iOS" criteria.employmentTypes = [.fullTime] let filtered = JobListingFilter.filter([listing], criteria: criteria, query: "iOS") XCTAssertEqual(filtered.count, 1) listing.employmentType = .partTime let dropped = JobListingFilter.filter([listing], criteria: criteria, query: "iOS") XCTAssertTrue(dropped.isEmpty) } }