-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtest.js
210 lines (193 loc) · 6.74 KB
/
test.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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
const AJV = require('ajv').default
const JSZip = require('jszip')
const blanksValues = require('./blanks')
const commonmark = require('commonform-commonmark')
const docx = require('commonform-docx')
const docxOptions = require('./docx-options')
const fs = require('fs')
const handler = require('./server')
const http = require('http')
const listVars = require('mustache-vars')
const mustache = require('mustache')
const ooxmlSignaturePages = require('ooxml-signature-pages')
const order = require('fs').readFileSync('./order.md', 'utf8')
const path = require('path')
const playwright = require('playwright')
const prepareBlanks = require('commonform-prepare-blanks')
const tape = require('tape')
const examples = require('./examples.json')
const prompts = require('./prompts.json')
const schema = require('./prompts.schema.json')
const signatures = require('./signatures.json')
const terms = require('fs').readFileSync('./terms.md', 'utf8')
tape('prompts conform to schema', test => {
const ajv = new AJV({ allErrors: true })
const validate = ajv.compile(schema)
validate(prompts)
test.same(validate.errors, null)
test.end()
})
tape('templating', test => {
function vars (input) {
return listVars(input).map(e => e.split('\t').reverse()[0])
}
const usedInTerms = vars(terms)
const usedInOrder = vars(order)
const possible = []
prompts.forEach(prompt => {
const promptID = prompt.id
prompt.responses.forEach(response => {
if (response.version > 1) return
const responseID = response.id
possible.push(`${promptID}=${responseID}`)
})
})
/*
possible.forEach(expected => {
if (!usedInTerms.includes(expected)) {
test.fail(`In Prompts, Not in Terms: ${expected}`)
}
})
*/
usedInTerms.forEach(expected => {
if (!possible.includes(expected)) {
test.fail(`In Terms, Not in Prompts: ${expected}`)
}
})
usedInOrder.forEach(expected => {
if (!possible.includes(expected)) {
test.fail(`In Order, Not in Prompts: ${expected}`)
}
})
test.end()
})
tape('prompt requirements', test => {
for (const prompt of prompts) {
if (!prompt.requires) continue
const promptID = prompt.id
for (const requirement of prompt.requires) {
for (const otherPromptID in requirement) {
const otherPrompt = prompts.find(prompt => prompt.id === otherPromptID)
test.assert(otherPrompt, `${promptID}: required prompt "${otherPromptID}" exists`)
const responseID = requirement[otherPromptID]
const response = otherPrompt.responses.find(response => response.id === responseID)
test.assert(response, `${promptID}: required prompt "${otherPromptID}" has response "${responseID}"`)
}
}
}
test.end()
})
for (const name in examples) {
tape(`validate example "${name}"`, test => {
const example = examples[name]
for (const promptID in example) {
const responseID = example[promptID]
const prompt = prompts.find(prompt => prompt.id === promptID)
test.assert(prompt, `promptID "${promptID}"`)
if (!prompt) break
const response = prompt.responses.find(response => response.id === responseID)
test.assert(response, `responseID "${responseID}"`)
}
test.end()
})
}
tape('terms renders', testRenders('terms', terms))
tape('order renders', testRenders('order', order))
function testRenders (kind, template) {
return test => {
for (const name in examples) {
test.test(`render example "${name}"`, test => {
const example = examples[name]
const view = {}
for (const promptID in example) {
const responseID = example[promptID]
view[`${promptID}=${responseID}`] = true
}
let rendered
test.doesNotThrow(() => {
rendered = mustache.render(template, view)
}, `Mustache render ${name}`)
let parsed
test.doesNotThrow(() => {
parsed = commonmark.parse(rendered)
}, 'Common Form render')
test.doesNotThrow(() => {
const options = {
title: `PolyForm Commercial Test Rendering: ${name} ${kind}`,
edition: `Generated ${new Date().toISOString()}`,
after: ooxmlSignaturePages(kind === 'order' ? signatures : [])
}
const blanks = kind === 'order'
? prepareBlanks(blanksValues, parsed.directions)
: []
Object.assign(options, docxOptions)
docx(parsed.form, blanks, options)
.generateAsync({ type: 'nodebuffer' })
.then(result => {
fs.mkdir('examples', { recursive: true }, error => {
test.ifError(error, 'created examples directory')
fs.writeFile(path.join('examples', `${name}-${kind}.docx`), result, error => {
test.ifError(error)
test.end()
})
})
})
})
})
}
}
}
for (const key in examples) {
tape(`integration: ${key}`, test => {
const server = http.createServer(handler)
server.listen(0 /* random high port */, async () => {
const port = server.address().port
test.assert(port, 'port')
let browser
try {
// Launch a browser.
browser = await playwright.chromium.launch({
headless: !process.env.HEADFUL
})
const context = await browser.newContext({
acceptDownloads: true
})
const page = await context.newPage()
await page.goto(`http://localhost:${port}`)
// Check <h1>.
const h1 = await page.$('h1')
const heading = await h1.textContent()
test.equal(heading, 'Commercial License Generator', 'heading')
// Fill out the form.
const showAdvanced = await page.$('text=Show Advanced Options')
if (showAdvanced) await showAdvanced.click()
const example = examples[key]
for (const promptID in example) {
const responseID = example[promptID]
await page.check(`#${promptID}_${responseID}`)
}
// Download the packet.
const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('#submit')
])
test.pass('selected all options')
const path = await download.path()
test.assert(path, 'downloaded')
// Inspect the archive.
const data = fs.readFileSync(path)
const zip = new JSZip()
await zip.loadAsync(data)
const entries = Object.keys(zip.files)
test.assert(entries.includes('order.docx'), 'zip contains order.docx')
test.assert(entries.includes('terms.docx'), 'zip contains terms.docx')
} catch (error) {
test.ifError(error)
} finally {
if (browser) browser.close()
server.close()
test.end()
}
})
})
}