저번에 UI 자동화에 대한 개요(?) 정도로만 시작했으며
이번에는 메일까지 접속해서 확인하도록 하겠습니다.
ID를 가져와서 입력하는 부분 및 PW를 가져오는 부분은 생략 하겠습니다.
전 포스팅에서 다루었기 때문에
id와 pw를 입력해서 로그인 까지 하게되면
const _url = "https://www.naver.com/"; require('chromedriver'); const webdriver = require('selenium-webdriver'); const {By,Util} = webdriver; var driver = new webdriver.Builder() .forBrowser('chrome') .build(); const register_pc = false; (async () => { try { await driver.get(_url); await driver.manage().window().maximize(); let inputId = await driver.findElement(By.css('input#id')); await inputId.sendKeys('myID'); let inputpw = await driver.findElement(By.css('input#pw')); await inputpw.sendKeys('mypassWord'); let loginBtn = await driver.findElement(By.css("input[type='submit']")); await loginBtn.click(); let page_ = await driver.findElements(By.css('fieldset.login_form a')); // 최초 실행 PC일 경우 페이지가 나타남 if(!!page_){ // 등록 page_[0] // 등록 안함 page_[1] !!register_pc ?console.log("등록합니다.") :await page_[1].click(); } } catch(err){ console.log("자동화 도중 에러 ",err + " 에러메시지 끝 "); } finally { await driver.sleep(2000); await driver.quit(); } })();
해당과 같이 코드를 작성후 node test.js 를 실행할시에 로그인 까지는 정상적으로 됩니다.
그후에 내 로그인 프로파일에 메일 이라는 부분을 클릭하여서 이동을 하여야 디는데 iframe 특성상
일반 DOM 과 분리되어있는 독립 document이기 때문에 클릭이 되지않습니다.
-> 정확히는 WebElement를 가져오지 못합니다.
해당 내용을 해결하기 위해서는 selenium-js에 있는 swtichTo 라는 API 를 사용하여야 합니다.
아래의 이미지는 네이버 로그인 프로필은 iframe으로 감싸져있음을 나타냅니다.
Native JavaScript 역시 iframe에 접근할 때는
window.frames["minime"].document.getElementById("mail_count_profile");
이와같이 사용합니다.
[iframe]
결과 코드
const _url = "https://www.naver.com/"; // require 가 Builder보다 위에 있어야 함 공식 홈페이지 require('chromedriver'); const webdriver = require('selenium-webdriver'); const {By,Util} = webdriver; // 드라이버 빌드 var driver = new webdriver.Builder() .forBrowser('chrome') .build(); const register_pc = false; (async () => { try { // 페이지 이동 await driver.get(_url); // 윈도우 최대화 headless 옵션 사용시 는 의미없음 await driver.manage().window().maximize(); // input값 가져옴 let inputId = await driver.findElement(By.css('input#id')); // ID 입력 await inputId.sendKeys('id'); // password 값 가져옴 let inputpw = await driver.findElement(By.css('input#pw')); // password 입력 await inputpw.sendKeys('pw'); // login 버튼 가져와서 클릭 let loginBtn = await driver.findElement(By.css("input[type='submit']")); await loginBtn.click(); // 최초 실행 PC일 경우 해당 페이지가 나타나기 때문에 존재한다면 등록 유무 선택 let page_ = await driver.findElements(By.css('fieldset.login_form a')); if(!!page_){ // 등록 page_[0] 등록 안함 page_[1] !!register_pc ?console.log("등록합니다.") :await page_[1].click(); } // selenium-js 에서는 switchTo.frame을 통해서 프레임을 변경 한다. await driver.switchTo().frame('minime'); // 변경 후 프로필에 메일을 가져오고 클릭 let mail_profile = await driver.findElement(By.id('mail_count_profile')); // 메일 클릭 // 화면 제어가 빠른 경우에 대한 sleep -> 추후 isContentsLoaded 또는 WebElement Condition 으로 변경 await driver.sleep(1500); await mail_profile.click(); // 기존 프레임으로 다시 돌아오는 경우 (page이동이없었을때) // await driver.switchTo().defaultContent(); // 임시 테스트용 Sleep await driver.sleep(2000); console.log(await driver.getTitle()); console.log(await driver.getCurrentUrl()); let newUrl = await driver.getCurrentUrl(); await driver.navigate().to(newUrl); // 가장 최상단 메일 의 Subject를 가져옴 let mailTitle = await driver.findElement(By.css('ol.mailList.sender_context li .subject')); // 셀레니엄 JS에서 getText는 innerText를 가져온다고 되어있습니다. console.log(await mailTitle.getText()); // 페이지 뒤로가기 // await driver.navigate().back(); } catch(err){ // Node Debug시 메시지가 너무길어 한글로 처음과 끝을 지정해서 보여지기 쉽게 처리 console.log("자동화 도중 에러 ",err + " 에러메시지 끝 "); } finally { await driver.sleep(2000); await driver.quit(); } })();
저는 네이버 알림을 켜놔서 새로운 기기 에서 로그인되었다는 창이 계속 나타나네요