|
| 1 | +package com.essheva; |
| 2 | + |
| 3 | +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; |
| 4 | +import org.openqa.selenium.*; |
| 5 | +import org.openqa.selenium.chrome.ChromeDriver; |
| 6 | +import org.openqa.selenium.interactions.Actions; |
| 7 | +import org.openqa.selenium.support.ui.WebDriverWait; |
| 8 | + |
| 9 | +import java.io.IOException; |
| 10 | +import java.time.format.DateTimeFormatter; |
| 11 | +import java.util.List; |
| 12 | + |
| 13 | + |
| 14 | +public class GustoTracker { |
| 15 | + |
| 16 | + GustoTracker() throws IOException, InvalidFormatException { |
| 17 | + Configuration config = new Configuration(); |
| 18 | + TimeTrackerExcelReader reader = new TimeTrackerExcelReader(config.getStatusFilePath()); |
| 19 | + List<DayRecord> records = reader.getRecords(); |
| 20 | + |
| 21 | + System.setProperty("webdriver.chrome.driver", config.getDriverPath().toAbsolutePath().toString()); |
| 22 | + WebDriver driver = new ChromeDriver(); |
| 23 | + |
| 24 | + driver.get("http://gusto.com/login"); |
| 25 | + |
| 26 | + driver.findElement(By.id("user_email")).sendKeys(config.getUserEmail()); |
| 27 | + driver.findElement(By.id("user_password")).sendKeys(config.getUserPassword()); |
| 28 | + driver.findElement(By.id("btn-login")).submit(); |
| 29 | + |
| 30 | + driver.get("https://app.gusto.com/time_tracking"); |
| 31 | + |
| 32 | + logTime(records, driver); |
| 33 | + } |
| 34 | + |
| 35 | + private void logTime(List<DayRecord> records, WebDriver driver) { |
| 36 | + JavascriptExecutor js = (JavascriptExecutor) driver; |
| 37 | + int offSet = 0; |
| 38 | + for (DayRecord record : records) { |
| 39 | + |
| 40 | + System.out.println("Processing record: " + record); |
| 41 | + |
| 42 | + int day = record.getDate().getDayOfMonth(); |
| 43 | + String month = DateTimeFormatter.ofPattern("MMM").format(record.getDate()); |
| 44 | + |
| 45 | + WebElement tr = null; |
| 46 | + while (tr == null) { |
| 47 | + js.executeScript("window.scrollBy(0,100)"); |
| 48 | + tr = new WebDriverWait(driver, 5).until( |
| 49 | + driver1 -> driver1.findElement( |
| 50 | + By.xpath("//tr[td//span/text()='" + day + "' and td//span/text()='" + month + "']"))); |
| 51 | + } |
| 52 | + |
| 53 | + |
| 54 | + try { |
| 55 | + tr.findElement(By.xpath(".//td[@data-title='Breakdown']//span[@class='breakdown__hours']")); |
| 56 | + offSet += 600; |
| 57 | + continue; |
| 58 | + } catch (NoSuchElementException ignore) {} |
| 59 | + |
| 60 | + js.executeScript("window.scrollTo(0, arguments[0])", offSet); |
| 61 | + |
| 62 | + Actions actions = new Actions(driver); |
| 63 | + WebElement expand = tr.findElement(By.xpath(".//td[@data-title='Hours']")); |
| 64 | + actions.moveToElement(expand).perform(); |
| 65 | + |
| 66 | + WebElement expandButton = tr.findElement(By.xpath(".//div[@class='time-log__result']//i")); |
| 67 | + while (!expandButton.isDisplayed()) { |
| 68 | + js.executeScript("window.scrollBy(0,300)"); |
| 69 | + } |
| 70 | + actions.moveToElement(expandButton).click().perform(); |
| 71 | + |
| 72 | + logData(js, record, tr); |
| 73 | + |
| 74 | + js.executeScript("window.scrollBy(0, 750)"); |
| 75 | + |
| 76 | + WebElement submitButton = tr.findElement(By.xpath(".//div[@class='flex']//button")); |
| 77 | + submitButton.submit(); |
| 78 | + |
| 79 | + js.executeScript("window.scrollBy(0, -800)"); |
| 80 | + offSet += 600; |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + private void logData(JavascriptExecutor js, DayRecord record, WebElement tr) { |
| 85 | + DateTimeFormatter gustoTimeFormatter = DateTimeFormatter.ofPattern("hh:mma"); |
| 86 | + |
| 87 | + String startTime = gustoTimeFormatter.format(record.getStart()); |
| 88 | + String endTime = gustoTimeFormatter.format(record.getEnd()); |
| 89 | + String breakTime = gustoTimeFormatter.format(record.getBreakStarted()); |
| 90 | + |
| 91 | + WebElement start = tr.findElement(By.xpath("(.//div[@class='time-log__shift']//input[@type='time'])[1]")); |
| 92 | + WebElement end = tr.findElement(By.xpath("(.//div[@class='time-log__shift']//input[@type='time'])[2]")); |
| 93 | + |
| 94 | + start.sendKeys(startTime); |
| 95 | + putData(endTime, end); |
| 96 | + WebElement breakRadioYes = tr.findElement(By.xpath( |
| 97 | + "(.//div[@class='break-input']//input[@type='radio'])[1]")); |
| 98 | + WebElement breakRadioNo = tr.findElement(By.xpath( |
| 99 | + "(.//div[@class='break-input']//input[@type='radio'])[2]")); |
| 100 | + js.executeScript("arguments[0].click();", breakRadioYes); |
| 101 | + |
| 102 | + WebElement breakStarted = tr.findElement( |
| 103 | + By.xpath(".//div[@class='break-input-secondary-group']//input[@name='break_start']")); |
| 104 | + breakStarted.sendKeys(breakTime); |
| 105 | + WebElement breakDuration = tr.findElement( |
| 106 | + By.xpath(".//div[@class='break-input-secondary-group']//input[@name='break_duration']")); |
| 107 | + breakDuration.clear(); |
| 108 | + breakDuration.sendKeys(String.valueOf(record.getBreakDuration())); |
| 109 | + WebElement notes = tr.findElement(By.tagName("textarea")); |
| 110 | + notes.sendKeys(record.getDescription()); |
| 111 | + } |
| 112 | + |
| 113 | + private void putData(String endTime, WebElement end) { |
| 114 | + end.sendKeys(endTime); |
| 115 | + } |
| 116 | + |
| 117 | + public static void main(String[] args) throws Exception { |
| 118 | + new GustoTracker(); |
| 119 | + } |
| 120 | +} |
| 121 | + |
0 commit comments