@@ -76,7 +76,7 @@ public static void main(String[] args) {
7676 loginToLinkedIn ();
7777 randomSleep (SHORT_SLEEP );
7878
79- String jobTitle = "full stack java developer" ;
79+ String jobTitle = "java developer" ;
8080 logger .info ("Search by default for" + jobTitle );
8181 String jobLocation = "United States" ;
8282 getSearchResultsFor (jobTitle );
@@ -85,61 +85,64 @@ public static void main(String[] args) {
8585 setFilters ();
8686 boolean choice = false ;
8787 do {
88- // Scroll thru the job Description
88+
8989 List <WebElement > jobCards = driver
90- .findElements (By .xpath ("/html/body/div[5]/div[3]/div[4]/div/div/main/div/div[1]/div/ul/li" ));
90+ .findElements (By .xpath ("/html/body/div[5]/div[3]/div[4]/div/div/main/div/div[1]/div/ul/li" ));
9191 int i = 1 ;
9292
9393 for (WebElement card : jobCards ) {
94- // /html/body/div[5]/div[3]/div[4]/div/div/main/div/div[1]/div/ul/li[1]
9594 WebElement view = driver .findElement (
96- By .xpath ("/html/body/div[5]/div[3]/div[4]/div/div/main/div/div[1]/div/ul/li[" + i + "]" ));
97-
98- scrollToWebElement (view );
99- // get the aria label in this element as job Title In Card,
100- // if it contains any of the MUST_HAVE, then click on the card
101- //
102- WebElement aTag = view .findElement (By .cssSelector (".disabled.ember-view.job-card-container__link.job-card-list__title" ));
103-
104- // Extract the aria-label content
105- String jobTitleInCard = aTag .getAttribute ("aria-label" );
106- logger .info ("jobTitleInCard: " + jobTitleInCard );
107-
108- // Print the content
95+ By .xpath ("/html/body/div[5]/div[3]/div[4]/div/div/main/div/div[1]/div/ul/li[" + i + "]" ));
10996
110- logger .info ("Clicking job card with xpath: " + "/html/body/div[5]/div[3]/div[4]/div/div/main/div/div[1]/div/ul/li[" + i + "]" );
111- i ++;
97+ scrollToWebElement (view );
11298
113- // process job Title in Card by removing special characters with space and split the job Title into words
114- jobTitleInCard = jobTitleInCard .trim ().replaceAll ("[^a-zA-Z0-9]" , " " ).toLowerCase ();
115- String [] jobTitleInCardWords = jobTitleInCard .split (" " );
99+ WebElement aTag = view .findElement (By .cssSelector (".disabled.ember-view.job-card-container__link.job-card-list__title" ));
116100
117- // check if any of the MUST_HAVE words are in the job Title in Card
101+ // Extract the aria-label content
102+ String jobTitleInCard = aTag .getAttribute ("aria-label" );
103+ logger .info ("jobTitleInCard: " + jobTitleInCard );
104+ i ++;
105+ // process job Title in Card by removing special characters except space with space and split the job Title into words
118106
119- // scan the jobTitle for must not have words
120- if (hasWords (jobTitleInCardWords , MUST_NOT_HAVE ) || !hasWords (jobTitleInCardWords , MUST_HAVE ))
121- {
122- logger .info ("Skipping job: " + jobTitleInCard );
123- continue ;
124- }
125- logger .info ("Processing job: " + jobTitleInCard );
126- card .click ();
107+ jobTitleInCard = jobTitleInCard .trim ().replaceAll ("[^a-zA-Z0-9]" , " " );
108+ String [] jobTitleInCardWords = jobTitleInCard .split (" " );
109+ // for each word in job title, trim it and convert it to lower case using stream API
110+ jobTitleInCardWords = Arrays .stream (jobTitleInCardWords ).map (String ::trim ).map (String ::toLowerCase ).toArray (String []::new );
127111
128- // Skipping already applied Jobs
129- String easyApplyBtnInJobDesc = "/html/body/div[5]/div[3]/div[4]/div/div/main/div/div[2]/div/div[2]/div[1]/div/div[1]/div/div[1]/div[1]/div[4]/div/div/div/button" ;
130- if (!elementExists (easyApplyBtnInJobDesc )) {
131- continue ;
132- }
112+ // check if any of the MUST_HAVE words are in the job Title in Card
133113
134- chooseToApply (scanner );
114+ // scan the jobTitle for must not have words
115+ if (hasWords (jobTitleInCardWords , MUST_NOT_HAVE ) || !hasWords (jobTitleInCardWords , MUST_HAVE )) {
116+ logger .info ("Skipping job: " + jobTitleInCard );
117+ continue ;
135118 }
119+ logger .info ("Processing job: " + jobTitleInCard );
120+ card .click ();
136121
137- choice = offerUserChoices ();
138- } while (choice );
139- // close the browser
122+ randomSleep (SHORT_SLEEP );
123+ if (!isThisJobApplied ()) {
124+ logger .info ("Job was previously applied" );
125+ continue ;
126+ }
127+ logger .info ("Job was not previously applied" );
128+ chooseToApply (scanner );
129+ }
130+ choice = offerUserChoices ();
131+ } while (choice );
140132 closeBrowser ();
141133 }
142134
135+ private static boolean isThisJobApplied () {
136+ boolean containsClass ;
137+ String easyApplyBtnDivXPath = "/html/body/div[5]/div[3]/div[4]/div/div/main/div/div[2]/div/div[2]/div[1]/div/div[1]/div/div[1]/div[1]/div[4]/div/div/div" ;
138+
139+ WebElement easyApplyBtnDiv = driver .findElement (By .xpath (easyApplyBtnDivXPath ));
140+ // Check if the easyApplyBtnDiv has class "jobs-apply-button--top-card"
141+ String className = "jobs-apply-button--top-card" ;
142+ containsClass = (boolean ) js .executeScript ("return arguments[0].classList.contains(arguments[1])" , easyApplyBtnDiv , className );
143+ return containsClass ;
144+ }
145+
143146 private static void closeBrowser () {
144147 scanner .close ();
145148 driver .quit ();
@@ -155,16 +158,15 @@ private static boolean hasWords(String[] jobTitleInCardWords, List<String> WORDS
155158 }
156159 return mustHave ;
157160 }
158-
161+
159162 private static boolean offerUserChoices () {
160163 String jobLocation = "United States" ;
161164 String jobTitle = "java developer" ;
162165 System .out .println ("Choose from Options \n 1. Search new job Title \n 2. Change Job Location \n 3. Click next page & press 3 \n 4. exit \n " );
163- // take input integer from user
164166 int choice = scanner .nextInt ();
165167 switch (choice ) {
166168 case 1 :
167- Scanner sc2 = new Scanner (System .in ); //System.in is a standard input stream
169+ Scanner sc2 = new Scanner (System .in ); //System.in is a standard input stream
168170 System .out .println ("Enter new job title\n " );
169171 jobTitle = sc2 .nextLine (); //reads string
170172 getSearchResultsFor (jobTitle , true );
@@ -177,7 +179,7 @@ private static boolean offerUserChoices() {
177179 System .out .println ("Assuming you clicked on next page" );
178180 break ;
179181
180- default :
182+ default :
181183 // log exiting
182184 logger .info ("Exiting the program" );
183185 return false ;
@@ -194,10 +196,9 @@ private static boolean elementExists(String xpath) {
194196 }
195197
196198 private static void chooseToApply (Scanner scanner ) {
197- System .out .println ("Do you want to apply for the job? (y/n) e to exit\n " );
199+ System .out .println ("Do you want to apply for the job? (y/n) e to exit" );
198200 String input = scanner .nextLine ();
199- if (input .trim ().equalsIgnoreCase ("e" ))
200- {
201+ if (input .trim ().equalsIgnoreCase ("e" )) {
201202 System .out .println ("Exiting the program" );
202203 closeBrowser ();
203204 System .exit (0 );
@@ -207,7 +208,6 @@ private static void chooseToApply(Scanner scanner) {
207208 applyForThisJob ();
208209 }
209210 }
210- //disabled ember-view job-card-container__link job-card-list__title
211211
212212 private static void applyForThisJob () {
213213 WebElement applyButton = driver .findElement (By .xpath (
@@ -216,6 +216,13 @@ private static void applyForThisJob() {
216216
217217 // xpath for next button:
218218 // /html/body/div[3]/div/div/div[2]/div/div[2]/form/footer/div[2]/button
219+
220+ // submit button xpath:
221+ // /html/body/div[3]/div/div/div[2]/div/div[2]/div/footer/div[3]/button[2]
222+ /// html/body/div[3]/div/div/div[2]/div/div[2]/div/footer/div[2]/button[2]
223+ ///html/body/div[3]/div/div/div[2]/div/div[2]/div/footer/div[3]/button[2]
224+ // scroll to the submit button
225+
219226 try {
220227 WebElement formFooter = driver .findElement (By .xpath (
221228 "/html/body/div[3]/div/div/div[2]/div/div[2]/form/footer" ));
@@ -224,55 +231,33 @@ private static void applyForThisJob() {
224231 while (formFooter != null && nextButton != null ) {
225232 scrollToWebElement (nextButton , false );
226233 logger .info ("Found next button" );
227- //get next button aria lable
228- String nextButtonAriaLabel = nextButton .getAttribute ("aria-label" );
229- // log next button aria label
230- logger .info ("Next button aria label: " + nextButtonAriaLabel );
231234 nextButton .click ();
232- //Log Clicked next button
233235 logger .info ("Clicked next button" );
234236 randomSleep (SHORT_SLEEP );
235237 nextButton = formFooter .findElement (By .cssSelector (".artdeco-button--primary.ember-view" ));
236238 }
237239
238- // submit button xpath:
239- // /html/body/div[3]/div/div/div[2]/div/div[2]/div/footer/div[3]/button[2]
240- /// html/body/div[3]/div/div/div[2]/div/div[2]/div/footer/div[2]/button[2]
241- // /html/body/div[3]/div/div/div[2]/div/div[2]/div/footer/div[3]/button[2]
242- // scroll to the submit button
243-
244-
245- }
246- catch (Exception e ) {
240+ } catch (Exception e ) {
247241 logger .info (e .getMessage ());
248242 }
249243 try {
250244 WebElement submitButton = driver .findElement (By .xpath (
251245 "/html/body/div[3]/div/div/div[2]/div/div[2]/div/footer" )).findElement (By .cssSelector (".artdeco-button--primary.ember-view" ));
252246 scrollToWebElement (submitButton , false );
253247 submitButton .click ();
254- randomSleep (LONG_SLEEP );
248+ randomSleep (MEDIUM_SLEEP );
255249 } catch (NoSuchElementException e ) {
256250 WebElement submitButton = driver .findElement (By .xpath (
257- "/html/body/div[3]/div/div/div[2]/div/div/form/footer/ " )).findElement (By .cssSelector (".artdeco-button--primary.ember-view" ));
251+ "/html/body/div[3]/div/div/div[2]/div/div/form/footer" )).findElement (By .cssSelector (".artdeco-button--primary.ember-view" ));
258252 scrollToWebElement (submitButton , false );
259253 submitButton .click ();
260- randomSleep (LONG_SLEEP );
261- }
262- catch (Exception e ) {
254+ randomSleep (MEDIUM_SLEEP );
255+ } catch (Exception e ) {
263256 logger .info (e .getMessage ());
264257 }
265258
266259 WebElement closeButton = driver .findElement (By .xpath ("/html/body/div[3]/div/div/button" ));
267260 closeButton .click ();
268- // Sleep for 5 secondsn
269-
270- // single click submit jobs
271- // <button aria-label="Submit application" id="ember1409" class="artdeco-button artdeco-button--2 artdeco-button--primary ember-view" type="button"><!---->
272- //<span class="artdeco-button__text">
273- // Submit application
274- // </span></button>
275- // xpath: /html/body/div[3]/div/div/div[2]/div/div/form/footer/div[3]/button
276261
277262 }
278263
@@ -328,25 +313,24 @@ private static void scrollToWebElement(WebElement contractExperienceLevel, boole
328313 if (sleep )
329314 randomSleep (SHORT_SLEEP );
330315 }
316+
331317 private static void clickWebElement (WebElement webElement ) {
332318 js .executeScript ("arguments[0].click();" , webElement );
333319 randomSleep (SHORT_SLEEP );
334320 }
335321
336322 private static void getSearchResultsFor (String jobTitle ) {
337- ///html/body/div[4]/header/div/div/div/div[2]/div[2]/div/div[2]/input[1]
323+ ///html/body/div[4]/header/div/div/div/div[2]/div[2]/div/div[2]/input[1]
338324 WebElement searchField = driver .findElement (By .xpath ("/html/body/div[5]/header/div/div/div/div[2]/div[2]/div/div/input[1]" ));
339325 js .executeScript ("arguments[0].scrollIntoView();" , searchField );
340- // scrollToWebElement(searchField);
341326 sendKeysToWebElement (jobTitle , searchField );
342327 sendKeysToWebElement ("\n " , searchField );
343328 }
344329
345- private static void getSearchResultsFor (String jobTitle , boolean newSearch ){
330+ private static void getSearchResultsFor (String jobTitle , boolean newSearch ) {
346331
347332 WebElement searchField = driver .findElement (By .xpath ("/html/body/div[5]/header/div/div/div/div[2]/div[1]/div/div/input[1]" ));
348333 scrollToWebElement (searchField );
349- // Clear the search field
350334 searchField .clear ();
351335 sendKeysToWebElement (jobTitle , searchField );
352336 sendKeysToWebElement ("\n " , searchField );
@@ -360,7 +344,6 @@ private static void sendKeysToWebElement(String jobTitle, WebElement searchField
360344 private static void loginToLinkedIn () {
361345
362346 driver .get (linkedInSite );
363- // Wait for page to load for 5 seconds
364347 enterIntoTextFieldById (emailInputBoxID , loginEmail );
365348 enterIntoTextFieldById (passwordInputBoxID , loginPass );
366349 String loginButtonXPath = "//button[@data-id='sign-in-form__submit-btn']" ;
0 commit comments