Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 3 additions & 153 deletions src/app/naver/elementParser.test.ts
Original file line number Diff line number Diff line change
@@ -1,157 +1,7 @@
import PaymentElementParser from "./elementParser";

function getWrappedHtml(htmlString: string) {
return `<div>${htmlString}</div>`;
}

describe("Parse payment history", () => {
let paymentElementParser: PaymentElementParser;
beforeEach(() => {
paymentElementParser = new PaymentElementParser(page);
});
it("Should not return 'purchasedAt' but with 'isAdditional' to be truthy if the product is '추가상품' ", async () => {
// given
const status = "결제완료";
const productName = "쿠키 1개";
const priceString = "100원";
const imageURL = "https://example/example.png";
const HTML = `
<div class="PaymentList_item__1f1JH">
<div class="PaymentList_status__2NgXs"><strong class="PaymentList_value__3sr7-">${status}</strong></div>
<div class="PaymentList_product__2EZFY">
<a href="!#" class="PaymentList_area-thumb__2J02B">
<div class="PaymentList_thumb__2-nTA"><img src="${imageURL}" width="76" height="76" alt="${productName}"></div>
</a>
<div class="PaymentList_area-info__pK_nh">
<a href="!#" class="PaymentList_info__1IHDx">
<div class="PaymentList_date__3mtOZ">
<span class="PaymentList_type-supplement__amOcE">
<span class="blind">추가상품</span>
</span>
</div>
<strong class="PaymentList_name__3wYJ_">${productName}</strong>
<div class="PaymentList_sum__Sj3M1">${priceString}</div>
</a>
</div>
</div>
</div>
`;

const wrappedHTML = getWrappedHtml(HTML);
await page.setContent(wrappedHTML);

const element = await page.$("div");

if (element === null) {
throw new Error("element is null");
}

// when
const paymentHistory = await paymentElementParser.parseElement(element);

// then
expect(paymentHistory.name).toEqual(productName);
expect(paymentHistory.price).toEqual(100);
expect(paymentHistory.thumbnailURL).toEqual(imageURL);
expect(paymentHistory.paymentStatus).toEqual(status);
expect(paymentHistory.isAdditional).toBeTruthy();
expect(paymentHistory.purchasedAt).toBeUndefined();
});
describe("Should return PaymentHistory", () => {
it("When the date is current year", async () => {
// given
const status = "구매확정완료";
const productName =
"[병행]로지텍 K380 무선 블루투스 키보드(국내당일출고)";
const priceString = "31,500원";
const imageURL = "https://example/example.png";
const dateString = "12. 17. 결제";
const HTML = `
<div class="PaymentList_item__1f1JH">
<div class="PaymentList_status__2NgXs"><strong class="PaymentList_value__3sr7-">${status}</strong></div>
<div class="PaymentList_product__2EZFY">
<a href="!#" class="PaymentList_area-thumb__2J02B">
<div class="PaymentList_thumb__2-nTA"><img src="${imageURL}" width="76" height="76" alt="${productName}"></div>
</a>
<div class="PaymentList_area-info__pK_nh">
<a href="!#" class="PaymentList_info__1IHDx">
<div class="PaymentList_date__3mtOZ">${dateString}</div>
<strong class="PaymentList_name__3wYJ_">${productName}</strong>
<div class="PaymentList_sum__Sj3M1">${priceString}</div>
</a>
</div>
</div>
</div>
`;
const wrappedHTML = getWrappedHtml(HTML);
await page.setContent(wrappedHTML);
const element = await page.$("div");
if (element === null) {
throw new Error("element is null");
}

// when
const paymentHistory = await paymentElementParser.parseElement(element);

// then
expect(paymentHistory.name).toEqual(productName);
expect(paymentHistory.price).toEqual(31500);
expect(paymentHistory.thumbnailURL).toEqual(imageURL);
expect(paymentHistory.paymentStatus).toEqual(status);
expect(paymentHistory.isAdditional).toBeFalsy();
expect(paymentHistory.purchasedAt).not.toBeUndefined();

const date = paymentHistory.purchasedAt;
expect(date?.getFullYear()).toEqual(new Date().getFullYear());
expect(date?.getMonth()).toEqual(11);
expect(date?.getDate()).toEqual(17);
});
it("When the date is not current year", async () => {
// given
const status = "구매확정완료";
const productName = "바세린 퓨어 스킨젤리 100ml x 3개";
const priceString = "7,900원";
const imageURL = "https://example/example.png";
const dateString = "2020. 11. 27. 결제";
const HTML = `
<div class="PaymentList_item__1f1JH">
<div class="PaymentList_status__2NgXs"><strong class="PaymentList_value__3sr7-">${status}</strong></div>
<div class="PaymentList_product__2EZFY">
<a href="!#" class="PaymentList_area-thumb__2J02B">
<div class="PaymentList_thumb__2-nTA"><img src="${imageURL}" width="76" height="76" alt="${productName}"></div>
</a>
<div class="PaymentList_area-info__pK_nh">
<a href="!#" class="PaymentList_info__1IHDx">
<div class="PaymentList_date__3mtOZ">${dateString}</div>
<strong class="PaymentList_name__3wYJ_">${productName}</strong>
<div class="PaymentList_sum__Sj3M1">${priceString}</div>
</a>
</div>
</div>
</div>
`;
const wrappedHTML = getWrappedHtml(HTML);
await page.setContent(wrappedHTML);
const element = await page.$("div");
if (element === null) {
throw new Error("element is null");
}

// when
const paymentHistory = await paymentElementParser.parseElement(element);

// then
expect(paymentHistory.name).toEqual(productName);
expect(paymentHistory.price).toEqual(7900);
expect(paymentHistory.thumbnailURL).toEqual(imageURL);
expect(paymentHistory.paymentStatus).toEqual(status);
expect(paymentHistory.isAdditional).toBeFalsy();
expect(paymentHistory.purchasedAt).not.toBeUndefined();

const date = paymentHistory.purchasedAt;
expect(date?.getFullYear()).toEqual(2020);
expect(date?.getMonth()).toEqual(10);
expect(date?.getDate()).toEqual(27);
});
describe("ElementParser", () => {
it("should be defined", () => {
expect(PaymentElementParser).toBeDefined();
});
});
109 changes: 0 additions & 109 deletions src/app/naver/elementParser.ts
Original file line number Diff line number Diff line change
@@ -1,119 +1,10 @@
import puppeteer from "puppeteer";
import { PaymentHistory } from "../common";

export default class ElementParser {
private static async parseName(element: puppeteer.ElementHandle) {
const name =
(await element.$eval(
'strong[class^="PaymentList_name__"]',
(el) => el.textContent
)) || "";
return name;
}

constructor(private readonly page: puppeteer.Page) {
this.page = page;
}

private static async parsePrice(element: puppeteer.ElementHandle) {
const priceString =
(await element.$eval(
'div[class^="PaymentList_sum__"]',
(el) => el.textContent
)) || "0";

const price = +priceString.replace(/[^0-9]/g, "");

return price;
}

private static async parseThumbnailUrl(element: puppeteer.ElementHandle) {
const thumbnailURL = await element.$eval(
'div[class^="PaymentList_thumb__"] > img',
(el) => el.getAttribute("src")
);
return thumbnailURL !== null ? thumbnailURL : "";
}

private static async parsePaymentStatus(element: puppeteer.ElementHandle) {
const paymentStatusString =
(await element.$eval(
'div[class^="PaymentList_status__"]',
(el) => el.textContent
)) || "";

return paymentStatusString;
}

private static async parsePurchasedAtString(
element: puppeteer.ElementHandle
) {
const purchasedAtDateString =
(await element.$eval(
"div[class^='PaymentList_date__']",
(el) => el.textContent
)) || "";

return purchasedAtDateString;
}

private static parsePurchasedAt(purchasedAtDateString: string) {
let splittedByDot = purchasedAtDateString.split(".");
if (splittedByDot.length === 1) {
return;
}
splittedByDot = splittedByDot.slice(0, splittedByDot.length - 1);

const isThisYear = splittedByDot.length == 2;

if (isThisYear) {
const year = new Date().getFullYear();
const month = +splittedByDot[0].trim();
const day = +splittedByDot[1].trim();
return new Date(year, month - 1, day);
}

const year = +splittedByDot[0].trim();
const month = +splittedByDot[1].trim();
const day = +splittedByDot[2].trim();
return new Date(year, month - 1, day);
}

private static parseIsAdditional(purchasedAtDateString: string) {
return purchasedAtDateString.trim() === "추가상품";
}

async parsePaymentElements() {
const elements = await this.page.$$(
"div[class^='PaymentList_article__'] > ul > li"
);
return elements;
}

async parseElement(element: puppeteer.ElementHandle) {
const [name, price, thumbnailURL, paymentStatus, purchasedAtDateString] =
await Promise.all([
ElementParser.parseName(element),
ElementParser.parsePrice(element),
ElementParser.parseThumbnailUrl(element),
ElementParser.parsePaymentStatus(element),
ElementParser.parsePurchasedAtString(element),
]);

const purchasedAt = ElementParser.parsePurchasedAt(purchasedAtDateString);
const isAdditional = ElementParser.parseIsAdditional(purchasedAtDateString);

const paymentHistory: PaymentHistory = {
name,
price,
thumbnailURL,
paymentStatus,
purchasedAt,
isAdditional,
};
return paymentHistory;
}

async parseManualOTPInputElement() {
return await this.page.$("#otp");
}
Expand Down
Loading