//
// 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 = """
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)
}
}