Merge pull request #12904 from Budibase/test-helpers-as-js
Test helpers running as javascript
This commit is contained in:
commit
c01518e5d4
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,7 @@
|
||||||
"manifest": "node ./scripts/gen-collection-info.js"
|
"manifest": "node ./scripts/gen-collection-info.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/handlebars-helpers": "^0.13.0",
|
"@budibase/handlebars-helpers": "^0.13.1",
|
||||||
"dayjs": "^1.10.8",
|
"dayjs": "^1.10.8",
|
||||||
"handlebars": "^4.7.6",
|
"handlebars": "^4.7.6",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
|
|
|
@ -10,8 +10,8 @@ const marked = require("marked")
|
||||||
* https://github.com/budibase/handlebars-helpers
|
* https://github.com/budibase/handlebars-helpers
|
||||||
*/
|
*/
|
||||||
const { join } = require("path")
|
const { join } = require("path")
|
||||||
|
const path = require("path")
|
||||||
|
|
||||||
const DIRECTORY = join(__dirname, "..", "..", "..")
|
|
||||||
const COLLECTIONS = [
|
const COLLECTIONS = [
|
||||||
"math",
|
"math",
|
||||||
"array",
|
"array",
|
||||||
|
@ -115,6 +115,8 @@ function getCommentInfo(file, func) {
|
||||||
docs.example = docs.example.replace("product", "multiply")
|
docs.example = docs.example.replace("product", "multiply")
|
||||||
}
|
}
|
||||||
docs.description = blocks[0].trim()
|
docs.description = blocks[0].trim()
|
||||||
|
docs.acceptsBlock = docs.tags.some(el => el.title === "block")
|
||||||
|
docs.acceptsInline = docs.tags.some(el => el.title === "inline")
|
||||||
return docs
|
return docs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +129,7 @@ function run() {
|
||||||
const foundNames = []
|
const foundNames = []
|
||||||
for (let collection of COLLECTIONS) {
|
for (let collection of COLLECTIONS) {
|
||||||
const collectionFile = fs.readFileSync(
|
const collectionFile = fs.readFileSync(
|
||||||
`${DIRECTORY}/node_modules/${HELPER_LIBRARY}/lib/${collection}.js`,
|
`${path.dirname(require.resolve(HELPER_LIBRARY))}/lib/${collection}.js`,
|
||||||
"utf8"
|
"utf8"
|
||||||
)
|
)
|
||||||
const collectionInfo = {}
|
const collectionInfo = {}
|
||||||
|
@ -159,6 +161,7 @@ function run() {
|
||||||
numArgs: args.length,
|
numArgs: args.length,
|
||||||
example: jsDocInfo.example || undefined,
|
example: jsDocInfo.example || undefined,
|
||||||
description: jsDocInfo.description,
|
description: jsDocInfo.description,
|
||||||
|
requiresBlock: jsDocInfo.acceptsBlock && !jsDocInfo.acceptsInline,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
outputJSON[collection] = collectionInfo
|
outputJSON[collection] = collectionInfo
|
||||||
|
|
|
@ -115,7 +115,7 @@ module.exports.duration = (str, pattern, format) => {
|
||||||
setLocale(config.str, config.pattern)
|
setLocale(config.str, config.pattern)
|
||||||
|
|
||||||
const duration = dayjs.duration(config.str, config.pattern)
|
const duration = dayjs.duration(config.str, config.pattern)
|
||||||
if (!isOptions(format)) {
|
if (format && !isOptions(format)) {
|
||||||
return duration.format(format)
|
return duration.format(format)
|
||||||
} else {
|
} else {
|
||||||
return duration.humanize()
|
return duration.humanize()
|
||||||
|
|
|
@ -3,6 +3,8 @@ const helperList = require("@budibase/handlebars-helpers")
|
||||||
|
|
||||||
let helpers = undefined
|
let helpers = undefined
|
||||||
|
|
||||||
|
const helpersToRemove = ["sortBy"]
|
||||||
|
|
||||||
module.exports.getHelperList = () => {
|
module.exports.getHelperList = () => {
|
||||||
if (helpers) {
|
if (helpers) {
|
||||||
return helpers
|
return helpers
|
||||||
|
@ -15,12 +17,17 @@ module.exports.getHelperList = () => {
|
||||||
}
|
}
|
||||||
for (let collection of constructed) {
|
for (let collection of constructed) {
|
||||||
for (let [key, func] of Object.entries(collection)) {
|
for (let [key, func] of Object.entries(collection)) {
|
||||||
helpers[key] = func
|
// Handlebars injects the hbs options to the helpers by default. We are adding an empty {} as a last parameter to simulate it
|
||||||
|
helpers[key] = (...props) => func(...props, {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let key of Object.keys(externalHandlebars.addedHelpers)) {
|
for (let key of Object.keys(externalHandlebars.addedHelpers)) {
|
||||||
helpers[key] = externalHandlebars.addedHelpers[key]
|
helpers[key] = externalHandlebars.addedHelpers[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const toRemove of helpersToRemove) {
|
||||||
|
delete helpers[toRemove]
|
||||||
|
}
|
||||||
Object.freeze(helpers)
|
Object.freeze(helpers)
|
||||||
return helpers
|
return helpers
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,21 +16,55 @@ jest.mock("@budibase/handlebars-helpers/lib/uuid", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const fs = require("fs")
|
const fs = require("fs")
|
||||||
const { processString } = require("../src/index.cjs")
|
const {
|
||||||
|
processString,
|
||||||
|
convertToJS,
|
||||||
|
processStringSync,
|
||||||
|
encodeJSBinding,
|
||||||
|
} = require("../src/index.cjs")
|
||||||
|
|
||||||
const tk = require("timekeeper")
|
const tk = require("timekeeper")
|
||||||
|
const { getHelperList } = require("../src/helpers")
|
||||||
|
|
||||||
tk.freeze("2021-01-21T12:00:00")
|
tk.freeze("2021-01-21T12:00:00")
|
||||||
|
|
||||||
|
const processJS = (js, context) => {
|
||||||
|
return processStringSync(encodeJSBinding(js), context)
|
||||||
|
}
|
||||||
|
|
||||||
const manifest = JSON.parse(
|
const manifest = JSON.parse(
|
||||||
fs.readFileSync(require.resolve("../manifest.json"), "utf8")
|
fs.readFileSync(require.resolve("../manifest.json"), "utf8")
|
||||||
)
|
)
|
||||||
|
|
||||||
const collections = Object.keys(manifest)
|
const collections = Object.keys(manifest)
|
||||||
const examples = collections.reduce((acc, collection) => {
|
const examples = collections.reduce((acc, collection) => {
|
||||||
const functions = Object.keys(manifest[collection]).filter(
|
const functions = Object.entries(manifest[collection])
|
||||||
fnc => manifest[collection][fnc].example
|
.filter(([_, details]) => details.example)
|
||||||
)
|
.map(([name, details]) => {
|
||||||
if (functions.length) {
|
const example = details.example
|
||||||
|
let [hbs, js] = example.split("->").map(x => x.trim())
|
||||||
|
if (!js) {
|
||||||
|
// The function has no return value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim 's
|
||||||
|
js = js.replace(/^\'|\'$/g, "")
|
||||||
|
if ((parsedExpected = tryParseJson(js))) {
|
||||||
|
if (Array.isArray(parsedExpected)) {
|
||||||
|
if (typeof parsedExpected[0] === "object") {
|
||||||
|
js = JSON.stringify(parsedExpected)
|
||||||
|
} else {
|
||||||
|
js = parsedExpected.join(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const requiresHbsBody = details.requiresBlock
|
||||||
|
return [name, { hbs, js, requiresHbsBody }]
|
||||||
|
})
|
||||||
|
.filter(x => !!x)
|
||||||
|
|
||||||
|
if (Object.keys(functions).length) {
|
||||||
acc[collection] = functions
|
acc[collection] = functions
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
|
@ -55,11 +89,7 @@ function tryParseJson(str) {
|
||||||
describe("manifest", () => {
|
describe("manifest", () => {
|
||||||
describe("examples are valid", () => {
|
describe("examples are valid", () => {
|
||||||
describe.each(Object.keys(examples))("%s", collection => {
|
describe.each(Object.keys(examples))("%s", collection => {
|
||||||
it.each(examples[collection])("%s", async func => {
|
it.each(examples[collection])("%s", async (_, { hbs, js }) => {
|
||||||
const example = manifest[collection][func].example
|
|
||||||
|
|
||||||
let [hbs, js] = example.split("->").map(x => x.trim())
|
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
double: i => i * 2,
|
double: i => i * 2,
|
||||||
isString: x => typeof x === "string",
|
isString: x => typeof x === "string",
|
||||||
|
@ -71,23 +101,40 @@ describe("manifest", () => {
|
||||||
context[`array${i}`] = JSON.parse(arrayString.replace(/\'/g, '"'))
|
context[`array${i}`] = JSON.parse(arrayString.replace(/\'/g, '"'))
|
||||||
})
|
})
|
||||||
|
|
||||||
if (js === undefined) {
|
let result = await processString(hbs, context)
|
||||||
// The function has no return value
|
result = result.replace(/ /g, " ")
|
||||||
return
|
expect(result).toEqual(js)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("can be parsed and run as js", () => {
|
||||||
|
const jsHelpers = getHelperList()
|
||||||
|
const jsExamples = Object.keys(examples).reduce((acc, v) => {
|
||||||
|
acc[v] = examples[v].filter(([key]) => jsHelpers[key])
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
|
||||||
|
describe.each(Object.keys(jsExamples))("%s", collection => {
|
||||||
|
it.each(
|
||||||
|
jsExamples[collection].filter(
|
||||||
|
([_, { requiresHbsBody }]) => !requiresHbsBody
|
||||||
|
)
|
||||||
|
)("%s", async (_, { hbs, js }) => {
|
||||||
|
const context = {
|
||||||
|
double: i => i * 2,
|
||||||
|
isString: x => typeof x === "string",
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = await processString(hbs, context)
|
const arrays = hbs.match(/\[[^/\]]+\]/)
|
||||||
// Trim 's
|
arrays?.forEach((arrayString, i) => {
|
||||||
js = js.replace(/^\'|\'$/g, "")
|
hbs = hbs.replace(new RegExp(escapeRegExp(arrayString)), `array${i}`)
|
||||||
if ((parsedExpected = tryParseJson(js))) {
|
context[`array${i}`] = JSON.parse(arrayString.replace(/\'/g, '"'))
|
||||||
if (Array.isArray(parsedExpected)) {
|
})
|
||||||
if (typeof parsedExpected[0] === "object") {
|
|
||||||
js = JSON.stringify(parsedExpected)
|
let convertedJs = convertToJS(hbs)
|
||||||
} else {
|
|
||||||
js = parsedExpected.join(",")
|
let result = processJS(convertedJs, context)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = result.replace(/ /g, " ")
|
result = result.replace(/ /g, " ")
|
||||||
expect(result).toEqual(js)
|
expect(result).toEqual(js)
|
||||||
})
|
})
|
||||||
|
|
|
@ -2031,10 +2031,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/handlebars-helpers@^0.13.0":
|
"@budibase/handlebars-helpers@^0.13.1":
|
||||||
version "0.13.0"
|
version "0.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.0.tgz#224333d14e3900b7dacf48286af1e624a9fd62ea"
|
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.1.tgz#d02e73c0df8305cd675e70dc37f8427eb0842080"
|
||||||
integrity sha512-g8+sFrMNxsIDnK+MmdUICTVGr6ReUFtnPp9hJX0VZwz1pN3Ynolpk/Qbu6rEWAvoU1sEqY1mXr9uo/+kEfeGbQ==
|
integrity sha512-v4RbXhr3igvK3i2pj5cNltu/4NMxdPIzcUt/o0RoInhesNH1VSLRdweSFr6/Y34fsCR5jHZ6vltdcz2RgrTKgw==
|
||||||
dependencies:
|
dependencies:
|
||||||
get-object "^0.2.0"
|
get-object "^0.2.0"
|
||||||
get-value "^3.0.1"
|
get-value "^3.0.1"
|
||||||
|
|
Loading…
Reference in New Issue