Skip to content

Commit

Permalink
health-check 리포터 파일 분리
Browse files Browse the repository at this point in the history
  • Loading branch information
disjukr committed Jun 30, 2019
1 parent 78aa4a5 commit b3e2d98
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 102 deletions.
106 changes: 4 additions & 102 deletions src/test/health-check/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import fs from 'fs';
import puppeteer from 'puppeteer';
import showdown from 'showdown'

import {
wait,
Expand All @@ -9,6 +8,7 @@ import {
getImpl,
fromJSON,
} from '../..';
import imageReporter from './reporter/image';


interface Case {
Expand All @@ -26,17 +26,7 @@ interface JobError {
interface JobOk extends UnwrapPromise<ReturnType<typeof doJob>> {
type: 'ok';
}
type JobResult = (JobError | JobOk) & { duration: number };
type CheckElements = 'title' | 'subtitle' | 'content' | 'timestamp.created' | 'timestamp.lastModified' | 'reporters.0.name' | 'reporters.0.mail';
const CheckElementNames: { [key in CheckElements]: string } = {
'title': '제목',
'subtitle': '부제목',
'content': '본문',
'timestamp.created': '작성일',
'timestamp.lastModified': '수정일',
'reporters.0.name': '작성자 이름',
'reporters.0.mail': '작성자 이메일',
}
export type JobResult = (JobError | JobOk) & { duration: number };

// `impl` 기준 사전순으로 정렬할 것
const cases: Case[] = [
Expand Down Expand Up @@ -212,12 +202,7 @@ async function run() {
await page.close();
}
}));

// Create image report
const markdownReport = makeMarkdownReport(jobResults);
const htmlReport = makeHtmlReport(markdownReport);
await screenshotReport(browser, htmlReport);

await imageReporter(jobResults, browser);
await browser.close();
fs.writeFileSync(
'./tmp/health-check.json',
Expand All @@ -229,89 +214,6 @@ run().catch(e => {
process.exit(1);
});

function makeMarkdownReport(jobResults: JobResult[]): string {
let report = '| 사이트 | 상태 |\n|------|-------|';
for (const jobResult of jobResults) {
let message;
if (jobResult.type == 'error') {
message = '• ❓테스트 실패';
} else {
message = '• '
if (jobResult.problems && jobResult.problems.length == 0) {
message += `✅`;
} else {
message += `❌`;
}
const links = [`[url](${jobResult.url})`];
for(const issueNumber of jobResult.related) {
links.push(`[${issueNumber}](https://github.com/disjukr/just-news/issues/${issueNumber})`);
}
message += '(' + links.join(', ') + ')';

const problemMessages = [];
for (const [element, reason] of jobResult.problems) {
switch (reason) {
case 'missing':
problemMessages.push(`\`잘못된 ${CheckElementNames[element]}\``);
break;
case 'invalid':
problemMessages.push(`\`${CheckElementNames[element]} 누락됨\``);
break;
}
}
message += problemMessages.join(', ');

}
report += `\n| ${jobResult.impl} | ${message} |`;
}
return report;
}

function makeHtmlReport(markdownReport: string): string {
const showdownConverter = new showdown.Converter({tables: true});

return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="https://unpkg.com/primer/build/build.css" rel="stylesheet">
<style>
body {
display: inline-block;
}
</style>
</head>
<body class="markdown-body">
${showdownConverter.makeHtml(markdownReport)}
</body>
</html>
`
}

async function screenshotReport(browser: puppeteer.Browser, htmlReport: string) {
const page = await browser.newPage();
await page.setContent(htmlReport);

const rect = await page.evaluate(() => {
const element = document.querySelector('.markdown-body');
if (!element)
throw new Error("Markdown body is not found!")
const {left, top, width, height} = element.getBoundingClientRect();
return {left, top, width, height, id: element.id};
});

await page.screenshot({
path: './tmp/report.png',
clip: {
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height,
}
});
}

async function doJob(job: Case, page: puppeteer.Page) {
const impl = getImpl(job.impl);
const waitForSelector = async (selector: string) => void await Promise.race([
Expand All @@ -325,7 +227,7 @@ async function doJob(job: Case, page: puppeteer.Page) {
]);
const article = fromJSON(await page.evaluate(doJob.browserScript));
type ProblemReason = 'missing' | 'invalid';
type Problem = [CheckElements/* path */, ProblemReason];
type Problem = [string/* path */, ProblemReason];
interface JobOkResult extends Case {
article: typeof article;
problems: Problem[];
Expand Down
30 changes: 30 additions & 0 deletions src/test/health-check/reporter/html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import showdown from 'showdown';

import { Reporter } from '.';
import markdownReporter from './markdown';

const htmlReporter: Reporter<string> = async (jobResults, browser) => {
const markdownReport = await markdownReporter(jobResults, browser);
const showdownConverter = new showdown.Converter({tables: true});
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link
href="https://unpkg.com/primer/build/build.css"
rel="stylesheet">
<style>
body {
display: inline-block;
}
</style>
</head>
<body class="markdown-body">
${showdownConverter.makeHtml(markdownReport)}
</body>
</html>
`;
}

export default htmlReporter;
26 changes: 26 additions & 0 deletions src/test/health-check/reporter/image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Reporter } from '.';
import htmlReporter from './html';

const imageReporter: Reporter<void> = async (jobResults, browser) => {
const htmlReport = await htmlReporter(jobResults, browser);
const page = await browser.newPage();
await page.setContent(htmlReport);
const rect = await page.evaluate(() => {
const element = document.querySelector('.markdown-body');
if (!element)
throw new Error("Markdown body is not found!")
const {left, top, width, height} = element.getBoundingClientRect();
return {left, top, width, height, id: element.id};
});
await page.screenshot({
path: './tmp/health-check.png',
clip: {
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height,
}
});
}

export default imageReporter;
6 changes: 6 additions & 0 deletions src/test/health-check/reporter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import puppeteer from 'puppeteer';

import { JobResult } from '..';

export type Reporter<T extends (Buffer | string | void)> =
(jobResults: JobResult[], browser: puppeteer.Browser) => (Promise<T> | T);
54 changes: 54 additions & 0 deletions src/test/health-check/reporter/markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Reporter } from '.';

const markdownReporter: Reporter<string> = jobResults => {
let report = '| 사이트 | 상태 |\n|------|-------|';
for (const jobResult of jobResults) {
let message;
if (jobResult.type == 'error') {
message = '• ❓테스트 실패';
} else {
message = '• '
if (jobResult.problems && jobResult.problems.length == 0) {
message += `✅`;
} else {
message += `❌`;
}
const links = [`[url](${jobResult.url})`];
for(const issueNumber of jobResult.related) {
links.push(`[${issueNumber}](https://github.com/disjukr/just-news/issues/${issueNumber})`);
}
message += '(' + links.join(', ') + ')';

const problemMessages = [];
for (const [problem, reason] of jobResult.problems) {
switch (reason) {
case 'missing':
problemMessages.push(`\`잘못된 ${sayProblem(problem)}\``);
break;
case 'invalid':
problemMessages.push(`\`${sayProblem(problem)} 누락됨\``);
break;
}
}
message += problemMessages.join(', ');

}
report += `\n| ${jobResult.impl} | ${message} |`;
}
return report;
};

export default markdownReporter;

const sayProblem = (text: string) => {
switch (text) {
case 'title': return '제목';
case 'subtitle': return '부제목';
case 'content': return '본문';
case 'timestamp.created': return '작성일';
case 'timestamp.lastModified': return '수정일';
case 'reporters.0.name': return '작성자 이름';
case 'reporters.0.mail': return '작성자 이메일';
}
return text;
};

0 comments on commit b3e2d98

Please sign in to comment.