12/08/2018, 17:15

Build extension to check timesheet on WSM (P1)

Hôm nọ mình quên k check timesheet trên wsm nên bị dính mấy phát IL & LE nên nhân dịp đang nghịch thằng puppeteer này mình build luôn 1 cái extension để check wsm luôn OK. Chủ đề đã có. GIờ vạch ra những issue nào Những thứ hay ho mình sẽ áp dụng trong phần này (toàn những thứ mình đã viết ...

Hôm nọ mình quên k check timesheet trên wsm nên bị dính mấy phát IL & LE nên nhân dịp đang nghịch thằng puppeteer này mình build luôn 1 cái extension để check wsm luôn OK. Chủ đề đã có. GIờ vạch ra những issue nào Những thứ hay ho mình sẽ áp dụng trong phần này (toàn những thứ mình đã viết trước đây - giờ chỉ là kết hợp lại vs nhau thôi)

  1. Server Do timesheet thay đổi liên tục nên mình sẽ không dùng DB để lưu Ta sẽ dùng Nodejs & Puppeteer để build 2 API check timesheet & submit request. Mọi người có thể tham khảo bài viết về puppeteer

  2. Client Mình thích xài Angular 2 nên sẽ dùng thằng này cho phần client. Để cho tiện mình sẽ dùng ng-cli

  3. Còn về cách build extension thì mọi người có thể tham khảo tại đây

API check timesheet

@Input sẽ có dạng như sau

{
  "email": "test@framgia.com",
  "password": "wsm-puppeteer"
}

@Output

{
    "day_IL": ['2018-02-26 07:47', '2018-02-21 08:50', '2018-02-23 08:50'],
    "day_LE": ['2018-03-06 15:40', '2018-02-08 14:40'],
}

Login

Đầu tiên ta cần phải login vào hệ thống WSM. Thử xem form login của wsm có những element gì nào Thật may là họ dùng id cho những input, như vậy ta sẽ không sợ bị trùng element. Vậy là ta có

    const puppeteer = require('puppeteer');
    const DOMAIN = 'https://wsm.framgia.vn';

    const URL_TIMESHEET = DOMAIN + '/vi/dashboard/user_timesheets';
    async functon loginWSM(email, password) {
        browser = await puppeteer.launch({headless: true});
        const page = await browser.newPage();
        page.setViewport({awidth: 1280, height: 720});
        await page.goto(URL_TIMESHEET);

        // START LOGIN ===============
        await page.click('.btn-login');

        await page.type('#user_email', email);
        await page.waitFor(500);
        await page.type('#user_password', password);
        await page.waitFor(500);

        await page.click('#devise-login-form .login-success');
    }

Sau khi login thì ta sẽ được chuyển đến màn hình timesheet. Nếu ở ngay chỗ này ta dùng hàm evaluate để lấy dữ liệu thì sẽ bị lỗi. Vì content ở bảng này được load bằng AJAX. Khi code trong evaluate thực hiện thì chưa chắc AJAX đã chạy xong => ta sẽ không lấy được thông tin gì hết

Vậy ta sẽ phải xem trước & sau khi AJAX done thì element nào sẽ được thay đổi

Thử F12 & chỉnh tốc độ mạng về yếu nhất (Tab Network -> Ô select "No Throttling" -> chọn GPRS) để ta có thể quan sát được rõ nhất việc AJAX hoạt động. Các bạn có thể tham khảo ảnh bên dưới Bạn để í thấy <tbody> đang bị trống => ta sẽ phải chờ cho đến khi content trong thẻ <tbody> được load xong. Rất may là puppeteer có support việc này bằng waitForSelector

await page.click('#devise-login-form .login-success');
// check authentication
// Để cho chắc ăn thì mình lấy thêm element thằng cha của nó nữa
await page.waitForSelector('.curr tbody tr', {timeout: 10000}).catch(async function (e) {
    throw new Error("Login fail");
});

Phân tích & lấy timesheet IL LE

OK. Vậy là ta đã login được thành công rồi. Nhưng mục tiêu chính của API này là lấy time IL LE. Vậy phải làm sao... Mình đâu có mò được vào DB để xem Như ta đã biết thì khi IL LE hay timesheet ngày nào đó của bạn có "vấn đề" thì nó sẽ được bôi 1 màu nào đó. Nhưng IL/LE thì được bôi màu nào. Mình đã phải chuột bạch vài buổi để có thể check được việc này. Nhưng sau đó mình phát hiện ra việc đó quá thừa thãi vì...

Hệ thống đã chú thích sẵn cho ta rồi             </div>
            
            <div class=

0