forked from feder-cr/Jobs_Applier_AI_Agent_AIHawk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_aihawk_job_manager.py
168 lines (128 loc) · 6.76 KB
/
test_aihawk_job_manager.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
from src.job import Job
from unittest import mock
from pathlib import Path
import os
import pytest
from ai_hawk.job_manager import AIHawkJobManager
from selenium.common.exceptions import NoSuchElementException
from src.logging import logger
@pytest.fixture
def job_manager(mocker):
"""Fixture to create a AIHawkJobManager instance with mocked driver."""
mock_driver = mocker.Mock()
return AIHawkJobManager(mock_driver)
def test_initialization(job_manager):
"""Test AIHawkJobManager initialization."""
assert job_manager.driver is not None
assert job_manager.set_old_answers == set()
assert job_manager.easy_applier_component is None
def test_set_parameters(mocker, job_manager):
"""Test setting parameters for the AIHawkJobManager."""
# Mocking os.path.exists to return True for the resume path
mocker.patch('pathlib.Path.exists', return_value=True)
params = {
'company_blacklist': ['Company A', 'Company B'],
'title_blacklist': ['Intern', 'Junior'],
'positions': ['Software Engineer', 'Data Scientist'],
'locations': ['New York', 'San Francisco'],
'apply_once_at_company': True,
'uploads': {'resume': '/path/to/resume'}, # Resume path provided here
'outputFileDirectory': '/path/to/output',
'job_applicants_threshold': {
'min_applicants': 5,
'max_applicants': 50
},
'remote': False,
'distance': 50,
'date': {'all_time': True}
}
job_manager.set_parameters(params)
# Normalize paths to handle platform differences (e.g., Windows vs Unix-like systems)
assert str(job_manager.resume_path) == os.path.normpath('/path/to/resume')
assert str(job_manager.output_file_directory) == os.path.normpath(
'/path/to/output')
def next_job_page(self, position, location, job_page):
logger.debug(f"Navigating to next job page: {position} in {location}, page {job_page}")
self.driver.get(
f"https://www.linkedin.com/jobs/search/{self.base_search_url}&keywords={position}&location={location}&start={job_page * 25}")
def test_get_jobs_from_page_no_jobs(mocker, job_manager):
"""Test get_jobs_from_page when no jobs are found."""
mocker.patch.object(job_manager.driver, 'find_element',
side_effect=NoSuchElementException)
jobs = job_manager.get_jobs_from_page()
assert jobs == []
def test_get_jobs_from_page_with_jobs(mocker, job_manager):
"""Test get_jobs_from_page when job elements are found."""
# Mock the no_jobs_element to behave correctly
mock_no_jobs_element = mocker.Mock()
mock_no_jobs_element.text = "No matching jobs found"
# Mocking the find_element to return the mock no_jobs_element
mocker.patch.object(job_manager.driver, 'find_element',
return_value=mock_no_jobs_element)
# Mock the page_source
mocker.patch.object(job_manager.driver, 'page_source',
return_value="some page content")
# Ensure jobs are returned as empty list due to "No matching jobs found"
jobs = job_manager.get_jobs_from_page()
assert jobs == [] # No jobs expected due to "No matching jobs found"
def test_apply_jobs_with_no_jobs(mocker, job_manager):
"""Test apply_jobs when no jobs are found."""
# Mocking find_element to return a mock element that simulates no jobs
mock_element = mocker.Mock()
mock_element.text = "No matching jobs found"
# Mock the driver to simulate the page source
mocker.patch.object(job_manager.driver, 'page_source', return_value="")
# Mock the driver to return the mock element when find_element is called
mocker.patch.object(job_manager.driver, 'find_element',
return_value=mock_element)
# Call apply_jobs and ensure no exceptions are raised
job_manager.apply_jobs()
# Ensure it attempted to find the job results list
assert job_manager.driver.find_element.call_count == 1
def test_apply_jobs_with_jobs(mocker, job_manager):
"""Test apply_jobs when jobs are present."""
# Mock no_jobs_element to simulate the absence of "No matching jobs found" banner
no_jobs_element = mocker.Mock()
no_jobs_element.text = "" # Empty text means "No matching jobs found" is not present
mocker.patch.object(job_manager.driver, 'find_element',
return_value=no_jobs_element)
# Mock the page_source to simulate what the page looks like when jobs are present
mocker.patch.object(job_manager.driver, 'page_source',
return_value="some job content")
# Mock the outer find_elements (scaffold-layout__list-container)
container_mock = mocker.Mock()
# Mock the inner find_elements to return job list items
job_element_mock = mocker.Mock()
# Simulating two job items
job_elements_list = [job_element_mock, job_element_mock]
# Return the container mock, which itself returns the job elements list
container_mock.find_elements.return_value = job_elements_list
mocker.patch.object(job_manager.driver, 'find_elements',
return_value=[container_mock])
# Mock the extract_job_information_from_tile method to return sample job info
mocker.patch.object(job_manager, 'extract_job_information_from_tile', return_value=(
"Title", "Company", "Location", "Apply", "Link"))
# Mock other methods like is_blacklisted, is_already_applied_to_job, and is_already_applied_to_company
mocker.patch.object(job_manager, 'is_blacklisted', return_value=False)
mocker.patch.object(
job_manager, 'is_already_applied_to_job', return_value=False)
mocker.patch.object(
job_manager, 'is_already_applied_to_company', return_value=False)
# Mock the AIHawkEasyApplier component
job_manager.easy_applier_component = mocker.Mock()
# Mock the output_file_directory as a valid Path object
job_manager.output_file_directory = Path("/mocked/path/to/output")
# Mock Path.exists() to always return True (so no actual file system interaction is needed)
mocker.patch.object(Path, 'exists', return_value=True)
# Mock the open function to prevent actual file writing
mock_open = mocker.mock_open()
mocker.patch('builtins.open', mock_open)
# Run the apply_jobs method
job_manager.apply_jobs()
# Assertions
assert job_manager.driver.find_elements.call_count == 1
# Called for each job element
assert job_manager.extract_job_information_from_tile.call_count == 2
# Called for each job element
assert job_manager.easy_applier_component.job_apply.call_count == 2
mock_open.assert_called() # Ensure that the open function was called