-
Notifications
You must be signed in to change notification settings - Fork 7
/
index.js
executable file
·184 lines (169 loc) · 5.97 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/env node
const program = require('commander')
const puppeteer = require('puppeteer')
const fsPath = require('fs-path')
const fs = require('fs')
const path = require('path')
const RJSON = require('relaxed-json')
const recursiveRead = require('recursive-readdir')
const { promisify } = require('util')
const Bottleneck = require('bottleneck')
const childProcess = require('child_process')
const readFile = promisify(fs.readFile)
const exec = promisify(childProcess.exec)
process.on('unhandledRejection', r => console.log(r))
const limiter = new Bottleneck(2)
const start = new Date()
program
.option('-i, --in [path]', 'Input Folder containing Jest Snapshots')
.option('-o, --out [path]', 'Output Folder that images will be saved to')
.option('-a, --all', 'Run snappydoo for all snapshots, not just modified ones')
.parse(process.argv)
let excludeList = []
let fileCreationCounter = 0
async function getandSaveScreenshot (snapshots, snapshotFileName, browser) {
async function getMessageBuilderImage (page, message) {
await page.goto(`https://api.slack.com/docs/messages/builder?msg=${encodeURIComponent(message)}`)
// not sure why navigation event doesn't fire
// await page.waitForNavigation({ waitUntil: 'load' });
await page.waitForSelector('#message_loading_indicator', { hidden: true, timeout: 30000 })
// https://github.com/GoogleChrome/puppeteer/issues/306#issuecomment-322929342
async function screenshotDOMElement (selector, padding = 0) {
const rect = await page.evaluate((selector) => {
const element = document.querySelector(selector)
const { x, y, width, height } = element.getBoundingClientRect()
return { left: x, top: y, width, height, id: element.id }
}, selector)
return page.screenshot({
clip: {
x: rect.left - padding,
y: rect.top - padding,
width: rect.width + (padding * 2),
height: rect.height + (padding * 2)
}
})
}
return screenshotDOMElement('#msgs_div')
}
const page = await browser.newPage()
page.setViewport({ width: 1000, height: 600, deviceScaleFactor: 2 })
let renderedImage
try {
renderedImage = await getMessageBuilderImage(
page,
JSON.stringify(snapshots[snapshotFileName])
)
} catch (e) {
// retry once
console.log(e)
console.log(`Retrying ${snapshotFileName}`)
renderedImage = await getMessageBuilderImage(
page,
JSON.stringify(snapshots[snapshotFileName])
)
}
try {
await fsPath.writeFile(snapshotFileName, renderedImage, () => {})
fileCreationCounter += 1
console.log(`Created ${snapshotFileName}`)
} catch (e) {
throw new Error(`Failed to create file: ${e}`)
}
await page.close()
}
async function main () {
// load config from package.json
let packageJSON
try {
packageJSON = await readFile(path.join(process.cwd(), 'package.json'))
} catch (e) {
console.error(
'Cannot find package.json. Make sure you run snappydoo from the root of your project',
e
)
}
const snappydooConfig = JSON.parse(packageJSON).snappydoo
let inputPath
let outputPath
if (snappydooConfig) {
if (snappydooConfig.out) {
outputPath = snappydooConfig.out
}
if (snappydooConfig.in) {
inputPath = snappydooConfig.in
}
if (snappydooConfig.exclude) {
excludeList = snappydooConfig.exclude
}
if (snappydooConfig.limit) {
limiter.changeSettings(snappydooConfig.limit)
}
}
// command line args take precedence over package.json
if (program.in) {
inputPath = program.in
}
if (program.out) {
outputPath = program.out
}
if (!outputPath || !inputPath) {
console.error('Error: Please specify both an output and an input path.')
process.exit(1)
}
const { stdout, stderr } = await exec('git ls-files --modified --others --exclude-standard')
if (stderr) {
throw new Error(`Couldn't run 'git ls-files' ${stderr}`)
}
const modifiedFiles = stdout.split('\n')
let snapshotFiles = await recursiveRead(path.join(process.cwd(), inputPath))
snapshotFiles = snapshotFiles.filter(file => {
return (
path.extname(file) === '.snap' &&
program.all ? true : modifiedFiles.indexOf(file.replace(`${process.cwd()}/`, '')) > -1
)
})
snapshotFiles = snapshotFiles.map(file => {
return file.replace(`${process.cwd()}/${inputPath}/`, '')
})
const snapshots = {}
// extraxt individual snapshots from snapshot files
snapshotFiles.forEach(async (file) => {
// eslint-disable-next-line
const match = new RegExp('(.*)\/?__snapshots__\/(.*).test\.(js|ts)\.snap').exec(file)
if (match) {
if (excludeList.indexOf(match[2]) > -1) {
// if snapshot is on black list, don't process any further
return
}
const snapshotsInFile = require(path.join(process.cwd(), inputPath, file))
Object.keys(snapshotsInFile).forEach((snapshotName) => {
const cleaned = snapshotsInFile[snapshotName]
.replace(/Object /g, '')
.replace(/Array /g, '')
.replace(/\n/g, '')
let message = JSON.parse(RJSON.transform(cleaned))
if (!message.attachments) {
message = { attachments: [message] }
}
const folderName = `${outputPath}/${match[1]}/${match[2]}`
snapshots[`${folderName}/${snapshotName}.png`] = message
})
}
})
console.log(`Fetching ${Object.keys(snapshots).length} screenshot${Object.keys(snapshots).length === 1 ? '' : 's'} from message builder`)
const browser = await puppeteer.launch({ headless: true })
// for (const snapshotFileName of Object.keys(snapshots)) {
await Promise.all(
Object.keys(snapshots).map(async (snapshotFileName) => {
await limiter.schedule(
getandSaveScreenshot,
snapshots,
snapshotFileName,
browser
)
})
)
await browser.close()
console.log(`Snappydoo done in ${(new Date() - start) / 1000}s. Created ${fileCreationCounter} file${fileCreationCounter === 1 ? '' : 's'}`)
}
main()