diff --git a/packages/builder/src/helpers/planTitle.js b/packages/builder/src/helpers/planTitle.js index dc07e8be2f..098bfb4529 100644 --- a/packages/builder/src/helpers/planTitle.js +++ b/packages/builder/src/helpers/planTitle.js @@ -1,11 +1,27 @@ import { PlanType } from "@budibase/types" export function getFormattedPlanName(userPlanType) { - let planName = "Free" - if (userPlanType === PlanType.PREMIUM_PLUS) { - planName = "Premium" - } else if (userPlanType === PlanType.ENTERPRISE_BASIC) { - planName = "Enterprise" + let planName + switch (userPlanType) { + case PlanType.PRO: + planName = "Pro" + break + case PlanType.TEAM: + planName = "Team" + break + case PlanType.PREMIUM: + case PlanType.PREMIUM_PLUS: + planName = "Premium" + break + case PlanType.BUSINESS: + planName = "Business" + break + case PlanType.ENTERPRISE_BASIC: + case PlanType.ENTERPRISE: + planName = "Enterprise" + break + default: + planName = "Free" // Default to "Free" if the type is not explicitly handled } return `${planName} Plan` } diff --git a/packages/string-templates/manifest.json b/packages/string-templates/manifest.json index 36db081936..9dd8260350 100644 --- a/packages/string-templates/manifest.json +++ b/packages/string-templates/manifest.json @@ -137,7 +137,7 @@ "n" ], "numArgs": 2, - "example": "{{ after [1, 2, 3] 1}} -> [3]", + "example": "{{ after ['a', 'b', 'c', 'd'] 2}} -> ['c', 'd']", "description": "

Returns all of the items in an array after the specified index. Opposite of before.

\n" }, "arrayify": { @@ -154,7 +154,7 @@ "n" ], "numArgs": 2, - "example": "{{ before [1, 2, 3] 2}} -> [1, 2]", + "example": "{{ before ['a', 'b', 'c', 'd'] 3}} -> ['a', 'b']", "description": "

Return all of the items in the collection before the specified count. Opposite of after.

\n" }, "eachIndex": { @@ -182,7 +182,7 @@ "n" ], "numArgs": 2, - "example": "{{first [1, 2, 3, 4] 2}} -> [1, 2]", + "example": "{{first [1, 2, 3, 4] 2}} -> 1,2", "description": "

Returns the first item, or first n items of an array.

\n" }, "forEach": { @@ -200,7 +200,7 @@ "options" ], "numArgs": 3, - "example": "{{#inArray [1, 2, 3] 2}} 2 exists {{else}} 2 does not exist {{/inArray}} -> 2 exists", + "example": "{{#inArray [1, 2, 3] 2}} 2 exists {{else}} 2 does not exist {{/inArray}} -> ' 2 exists '", "description": "

Block helper that renders the block if an array has the given value. Optionally specify an inverse block to render when the array does not have the given value.

\n" }, "isArray": { @@ -226,7 +226,7 @@ "separator" ], "numArgs": 2, - "example": "{{join [1, 2, 3]}} -> '1, 2, 3'", + "example": "{{join [1, 2, 3]}} -> 1, 2, 3", "description": "

Join all elements of array into a string, optionally using a given separator.

\n" }, "equalsLength": { @@ -236,7 +236,7 @@ "options" ], "numArgs": 3, - "example": "{{equalsLength '[1,2,3]' 3}} -> true", + "example": "{{equalsLength [1, 2, 3] 3}} -> true", "description": "

Returns true if the the length of the given value is equal to the given length. Can be used as a block or inline helper.

\n" }, "last": { @@ -253,7 +253,7 @@ "value" ], "numArgs": 1, - "example": "{{length '[1, 2, 3]'}} -> 3", + "example": "{{length [1, 2, 3]}} -> 3", "description": "

Returns the length of the given string or array.

\n" }, "lengthEqual": { @@ -263,7 +263,7 @@ "options" ], "numArgs": 3, - "example": "{{equalsLength '[1,2,3]' 3}} -> true", + "example": "{{equalsLength [1, 2, 3] 3}} -> true", "description": "

Returns true if the the length of the given value is equal to the given length. Can be used as a block or inline helper.

\n" }, "map": { @@ -299,7 +299,7 @@ "provided" ], "numArgs": 3, - "example": "{{#some [1, 'b', 3] isString}} string found {{else}} No string found {{/some}} -> string found", + "example": "{{#some [1, \"b\", 3] isString}} string found {{else}} No string found {{/some}} -> ' string found '", "description": "

Block helper that returns the block if the callback returns true for some value in the given array.

\n" }, "sort": { @@ -317,7 +317,7 @@ "props" ], "numArgs": 2, - "example": "{{ sortBy [{a: 'zzz'}, {a: 'aaa'}] 'a' }} -> [{'a':'aaa'}, {'a':'zzz'}]", + "example": "{{ sortBy [{'a': 'zzz'}, {'a': 'aaa'}] 'a' }} -> [{'a':'aaa'},{'a':'zzz'}]", "description": "

Sort an array. If an array of objects is passed, you may optionally pass a key to sort on as the second argument. You may alternatively pass a sorting function as the second argument.

\n" }, "withAfter": { @@ -347,7 +347,7 @@ "options" ], "numArgs": 3, - "example": "{{ withFirst [1, 2, 3] }} {{this}} {{/withFirst}}", + "example": "{{#withFirst [1, 2, 3] }}{{this}}{{/withFirst}} -> 1", "description": "

Use the first item in a collection inside a handlebars block expression. Opposite of withLast.

\n" }, "withGroup": { @@ -357,7 +357,7 @@ "options" ], "numArgs": 3, - "example": "{{#withGroup [1, 2, 3, 4] 2}} {{#each this}} {{.}} {{each}}
{{/withGroup}} -> 1,2
3,4
", + "example": "{{#withGroup [1, 2, 3, 4] 2}}{{#each this}}{{.}}{{/each}}
{{/withGroup}} -> 12
34
", "description": "

Block helper that groups array elements by given group size.

\n" }, "withLast": { @@ -367,7 +367,7 @@ "options" ], "numArgs": 3, - "example": "{{#withLast [1, 2, 3, 4]}} {{this}} {{/withLast}} -> 4", + "example": "{{#withLast [1, 2, 3, 4]}}{{this}}{{/withLast}} -> 4", "description": "

Use the last item or n items in an array as context inside a block. Opposite of withFirst.

\n" }, "withSort": { @@ -377,7 +377,7 @@ "options" ], "numArgs": 3, - "example": "{{#withSort ['b', 'a', 'c']}} {{this}} {{/withSort}} -> abc", + "example": "{{#withSort ['b', 'a', 'c']}}{{this}}{{/withSort}} -> abc", "description": "

Block helper that sorts a collection and exposes the sorted collection as context inside the block.

\n" }, "unique": { @@ -386,7 +386,7 @@ "options" ], "numArgs": 2, - "example": "{{#each (unique ['a', 'a', 'c', 'b', 'e', 'e']) }} {{.}} {{/each}} -> acbe", + "example": "{{#each (unique ['a', 'a', 'c', 'b', 'e', 'e']) }}{{.}}{{/each}} -> acbe", "description": "

Block helper that return an array with all duplicate values removed. Best used along with a each helper.

\n" } }, @@ -396,7 +396,7 @@ "number" ], "numArgs": 1, - "example": "{{ bytes 1386 }} -> 1.4Kb", + "example": "{{ bytes 1386 1 }} -> 1.4 kB", "description": "

Format a number to it's equivalent in bytes. If a string is passed, it's length will be formatted and returned. Examples: - 'foo' => 3 B - 13661855 => 13.66 MB - 825399 => 825.39 kB - 1396 => 1.4 kB

\n" }, "addCommas": { @@ -430,7 +430,7 @@ "fractionDigits" ], "numArgs": 2, - "example": "{{ toExponential 10123 2 }} -> 101e+4", + "example": "{{ toExponential 10123 2 }} -> 1.01e+4", "description": "

Returns a string representing the given number in exponential notation.

\n" }, "toFixed": { @@ -472,7 +472,7 @@ "str" ], "numArgs": 1, - "example": "{{ encodeURI 'https://myurl?Hello There' }} -> https://myurl?Hello%20There", + "example": "{{ encodeURI 'https://myurl?Hello There' }} -> https%3A%2F%2Fmyurl%3FHello%20There", "description": "

Encodes a Uniform Resource Identifier (URI) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.

\n" }, "escape": { @@ -480,7 +480,7 @@ "str" ], "numArgs": 1, - "example": "{{ escape 'https://myurl?Hello+There' }} -> https://myurl?Hello%20There", + "example": "{{ escape 'https://myurl?Hello+There' }} -> https%3A%2F%2Fmyurl%3FHello%2BThere", "description": "

Escape the given string by replacing characters with escape sequences. Useful for allowing the string to be used in a URL, etc.

\n" }, "decodeURI": { @@ -488,7 +488,7 @@ "str" ], "numArgs": 1, - "example": "{{ decodeURI 'https://myurl?Hello%20There' }} -> https://myurl?=Hello There", + "example": "{{ decodeURI 'https://myurl?Hello%20There' }} -> https://myurl?Hello There", "description": "

Decode a Uniform Resource Identifier (URI) component.

\n" }, "urlResolve": { @@ -513,7 +513,7 @@ "url" ], "numArgs": 1, - "example": "{{ stripQueryString 'https://myurl/api/test?foo=bar' }} -> 'https://myurl/api/test'", + "example": "{{ stripQuerystring 'https://myurl/api/test?foo=bar' }} -> 'https://myurl/api/test'", "description": "

Strip the query string from the given url.

\n" }, "stripProtocol": { @@ -521,7 +521,7 @@ "str" ], "numArgs": 1, - "example": "{{ stripProtocol 'https://myurl/api/test' }} -> 'myurl/api/test'", + "example": "{{ stripProtocol 'https://myurl/api/test' }} -> '//myurl/api/test'", "description": "

Strip protocol from a url. Useful for displaying media that may have an 'http' protocol on secure connections.

\n" } }, @@ -573,7 +573,7 @@ "string" ], "numArgs": 1, - "example": "{{ chop ' ABC '}} -> 'ABC'", + "example": "{{ chop ' ABC '}} -> ABC", "description": "

Like trim, but removes both extraneous whitespace and non-word characters from the beginning and end of a string.

\n" }, "dashcase": { @@ -606,7 +606,7 @@ "length" ], "numArgs": 2, - "example": "{{ellipsis 'foo bar baz', 7}} -> foo bar…", + "example": "{{ellipsis 'foo bar baz' 7}} -> foo bar…", "description": "

Truncates a string to the specified length, and appends it with an elipsis, .

\n" }, "hyphenate": { @@ -675,14 +675,6 @@ "example": "{{prepend 'bar' 'foo-'}} -> foo-bar", "description": "

Prepends the given string with the specified prefix.

\n" }, - "raw": { - "args": [ - "options" - ], - "numArgs": 1, - "example": "{{{{#raw}}}} {{foo}} {{{{/raw}}}} -> {{foo}}", - "description": "

Render a block without processing mustache templates inside the block.

\n" - }, "remove": { "args": [ "str", @@ -698,7 +690,7 @@ "substring" ], "numArgs": 2, - "example": "{{remove 'a b a b a b' 'a'}} -> b a b a b", + "example": "{{removeFirst 'a b a b a b' 'a'}} -> ' b a b a b'", "description": "

Remove the first occurrence of substring from the given str.

\n" }, "replace": { @@ -718,7 +710,7 @@ "b" ], "numArgs": 3, - "example": "{{replace 'a b a b a b' 'a' 'z'}} -> z b a b a b", + "example": "{{replaceFirst 'a b a b a b' 'a' 'z'}} -> z b a b a b", "description": "

Replace the first occurrence of substring a with substring b.

\n" }, "sentence": { @@ -752,7 +744,7 @@ "options" ], "numArgs": 3, - "example": "{{#startsWith 'Goodbye' 'Hello, world!'}} Yep {{else}} Nope {{/startsWith}} -> Nope", + "example": "{{#startsWith 'Goodbye' 'Hello, world!'}}Yep{{else}}Nope{{/startsWith}} -> Nope", "description": "

Tests whether a string begins with the given prefix.

\n" }, "titleize": { @@ -760,7 +752,7 @@ "str" ], "numArgs": 1, - "example": "{{#titleize 'this is title case' }} -> This Is Title Case", + "example": "{{titleize 'this is title case' }} -> This Is Title Case", "description": "

Title case the given string.

\n" }, "trim": { @@ -784,7 +776,7 @@ "string" ], "numArgs": 1, - "example": "{{trimRight ' ABC ' }} -> ' ABC '", + "example": "{{trimRight ' ABC ' }} -> ' ABC'", "description": "

Removes extraneous whitespace from the end of a string.

\n" }, "truncate": { @@ -804,7 +796,7 @@ "suffix" ], "numArgs": 3, - "example": "{{truncateWords 'foo bar baz' 1 }} -> foo", + "example": "{{truncateWords 'foo bar baz' 1 }} -> foo…", "description": "

Truncate a string to have the specified number of words. Also see truncate.

\n" }, "upcase": { @@ -844,7 +836,7 @@ "options" ], "numArgs": 4, - "example": "{{compare 10 '<' 5 }} -> true", + "example": "{{compare 10 '<' 5 }} -> false", "description": "

Render a block when a comparison of the first and third arguments returns true. The second argument is the [arithemetic operator][operators] to use. You may also optionally specify an inverse block to render when falsy.

\n" }, "contains": { @@ -874,7 +866,7 @@ "options" ], "numArgs": 3, - "example": "{{#eq 3 3}} equal{{else}} not equal{{/eq}} -> equal", + "example": "{{#eq 3 3}}equal{{else}}not equal{{/eq}} -> equal", "description": "

Block helper that renders a block if a is equal to b. If an inverse block is specified it will be rendered when falsy. You may optionally use the compare='' hash argument for the second value.

\n" }, "gt": { @@ -884,7 +876,7 @@ "options" ], "numArgs": 3, - "example": "{{#gt 4 3}} greater than{{else}} not greater than{{/gt}} -> greater than", + "example": "{{#gt 4 3}} greater than{{else}} not greater than{{/gt}} -> ' greater than'", "description": "

Block helper that renders a block if a is greater than b. If an inverse block is specified it will be rendered when falsy. You may optionally use the compare='' hash argument for the second value.

\n" }, "gte": { @@ -894,7 +886,7 @@ "options" ], "numArgs": 3, - "example": "{{#gte 4 3}} greater than or equal{{else}} not greater than{{/gte}} -> greater than or equal", + "example": "{{#gte 4 3}} greater than or equal{{else}} not greater than{{/gte}} -> ' greater than or equal'", "description": "

Block helper that renders a block if a is greater than or equal to b. If an inverse block is specified it will be rendered when falsy. You may optionally use the compare='' hash argument for the second value.

\n" }, "has": { @@ -904,7 +896,7 @@ "options" ], "numArgs": 3, - "example": "{{#has 'foobar' 'foo'}} has it{{else}} doesn't{{/has}} -> has it", + "example": "{{#has 'foobar' 'foo'}}has it{{else}}doesn't{{/has}} -> has it", "description": "

Block helper that renders a block if value has pattern. If an inverse block is specified it will be rendered when falsy.

\n" }, "isFalsey": { @@ -931,7 +923,7 @@ "options" ], "numArgs": 2, - "example": "{{#ifEven 2}} even {{else}} odd {{/ifEven}} -> even", + "example": "{{#ifEven 2}} even {{else}} odd {{/ifEven}} -> ' even '", "description": "

Return true if the given value is an even number.

\n" }, "ifNth": { @@ -941,8 +933,8 @@ "options" ], "numArgs": 3, - "example": "{{#ifNth 10 2}} remainder {{else}} no remainder {{/ifNth}} -> remainder", - "description": "

Conditionally renders a block if the remainder is zero when a operand is divided by b. If an inverse block is specified it will be rendered when the remainder is not zero.

\n" + "example": "{{#ifNth 2 10}}remainder{{else}}no remainder{{/ifNth}} -> remainder", + "description": "

Conditionally renders a block if the remainder is zero when b operand is divided by a. If an inverse block is specified it will be rendered when the remainder is not zero.

\n" }, "ifOdd": { "args": [ @@ -950,7 +942,7 @@ "options" ], "numArgs": 2, - "example": "{{#ifOdd 3}} odd {{else}} even {{/ifOdd}} -> odd", + "example": "{{#ifOdd 3}}odd{{else}}even{{/ifOdd}} -> odd", "description": "

Block helper that renders a block if value is an odd number. If an inverse block is specified it will be rendered when falsy.

\n" }, "is": { @@ -960,7 +952,7 @@ "options" ], "numArgs": 3, - "example": "{{#is 3 3}} is {{else}} is not {{/is}} -> is", + "example": "{{#is 3 3}} is {{else}} is not {{/is}} -> ' is '", "description": "

Block helper that renders a block if a is equal to b. If an inverse block is specified it will be rendered when falsy. Similar to eq but does not do strict equality.

\n" }, "isnt": { @@ -970,7 +962,7 @@ "options" ], "numArgs": 3, - "example": "{{#isnt 3 3}} isnt {{else}} is {{/isnt}} -> is", + "example": "{{#isnt 3 3}} isnt {{else}} is {{/isnt}} -> ' is '", "description": "

Block helper that renders a block if a is not equal to b. If an inverse block is specified it will be rendered when falsy. Similar to unlessEq but does not use strict equality for comparisons.

\n" }, "lt": { @@ -979,7 +971,7 @@ "options" ], "numArgs": 2, - "example": "{{#lt 2 3}} less than {{else}} more than or equal {{/lt}} -> less than", + "example": "{{#lt 2 3}} less than {{else}} more than or equal {{/lt}} -> ' less than '", "description": "

Block helper that renders a block if a is less than b. If an inverse block is specified it will be rendered when falsy. You may optionally use the compare='' hash argument for the second value.

\n" }, "lte": { @@ -989,7 +981,7 @@ "options" ], "numArgs": 3, - "example": "{{#lte 2 3}} less than or equal {{else}} more than {{/lte}} -> less than or equal", + "example": "{{#lte 2 3}} less than or equal {{else}} more than {{/lte}} -> ' less than or equal '", "description": "

Block helper that renders a block if a is less than or equal to b. If an inverse block is specified it will be rendered when falsy. You may optionally use the compare='' hash argument for the second value.

\n" }, "neither": { @@ -999,7 +991,7 @@ "options" ], "numArgs": 3, - "example": "{{#neither null null}} both falsey {{else}} both not falsey {{/neither}} -> both falsey", + "example": "{{#neither null null}}both falsey{{else}}both not falsey{{/neither}} -> both falsey", "description": "

Block helper that renders a block if neither of the given values are truthy. If an inverse block is specified it will be rendered when falsy.

\n" }, "not": { @@ -1008,7 +1000,7 @@ "options" ], "numArgs": 2, - "example": "{{#not undefined }} falsey {{else}} not falsey {{/not}} -> falsey", + "example": "{{#not undefined }}falsey{{else}}not falsey{{/not}} -> falsey", "description": "

Returns true if val is falsey. Works as a block or inline helper.

\n" }, "or": { @@ -1017,7 +1009,7 @@ "options" ], "numArgs": 2, - "example": "{{#or 1 2 undefined }} at least one truthy {{else}} all falsey {{/or}} -> at least one truthy", + "example": "{{#or 1 2 undefined }} at least one truthy {{else}} all falsey {{/or}} -> ' at least one truthy '", "description": "

Block helper that renders a block if any of the given values is truthy. If an inverse block is specified it will be rendered when falsy.

\n" }, "unlessEq": { @@ -1027,7 +1019,7 @@ "options" ], "numArgs": 3, - "example": "{{#unlessEq 2 1 }} not equal {{else}} equal {{/unlessEq}} -> not equal", + "example": "{{#unlessEq 2 1 }} not equal {{else}} equal {{/unlessEq}} -> ' not equal '", "description": "

Block helper that always renders the inverse block unless a is equal to b.

\n" }, "unlessGt": { @@ -1037,7 +1029,7 @@ "options" ], "numArgs": 3, - "example": "{{#unlessGt 20 1 }} not greater than {{else}} greater than {{/unlessGt}} -> greater than", + "example": "{{#unlessGt 20 1 }} not greater than {{else}} greater than {{/unlessGt}} -> ' greater than '", "description": "

Block helper that always renders the inverse block unless a is greater than b.

\n" }, "unlessLt": { @@ -1047,7 +1039,7 @@ "options" ], "numArgs": 3, - "example": "{{#unlessLt 20 1 }} greater than or equal {{else}} less than {{/unlessLt}} -> greater than or equal", + "example": "{{#unlessLt 20 1 }}greater than or equal{{else}}less than{{/unlessLt}} -> greater than or equal", "description": "

Block helper that always renders the inverse block unless a is less than b.

\n" }, "unlessGteq": { @@ -1057,7 +1049,7 @@ "options" ], "numArgs": 3, - "example": "{{#unlessGteq 20 1 }} less than {{else}} greater than or equal to {{/unlessGteq}} -> greater than or equal to", + "example": "{{#unlessGteq 20 1 }} less than {{else}}greater than or equal to{{/unlessGteq}} -> greater than or equal to", "description": "

Block helper that always renders the inverse block unless a is greater than or equal to b.

\n" }, "unlessLteq": { @@ -1067,7 +1059,7 @@ "options" ], "numArgs": 3, - "example": "{{#unlessLteq 20 1 }} greater than {{else}} less than or equal to {{/unlessLteq}} -> greater than", + "example": "{{#unlessLteq 20 1 }} greater than {{else}} less than or equal to {{/unlessLteq}} -> ' greater than '", "description": "

Block helper that always renders the inverse block unless a is less than or equal to b.

\n" } }, @@ -1204,7 +1196,7 @@ "durationType" ], "numArgs": 2, - "example": "{{duration timeLeft \"seconds\"}} -> a few seconds", + "example": "{{duration 8 \"seconds\"}} -> a few seconds", "description": "

Produce a humanized duration left/until given an amount of time and the type of time measurement.

\n" } } diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index 1a52adf38c..dfbff1a24b 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -25,7 +25,7 @@ "manifest": "node ./scripts/gen-collection-info.js" }, "dependencies": { - "@budibase/handlebars-helpers": "^0.12.0", + "@budibase/handlebars-helpers": "^0.13.0", "dayjs": "^1.10.8", "handlebars": "^4.7.6", "lodash.clonedeep": "^4.5.0", diff --git a/packages/string-templates/scripts/gen-collection-info.js b/packages/string-templates/scripts/gen-collection-info.js index e42c9ccaf0..b487c4dde4 100644 --- a/packages/string-templates/scripts/gen-collection-info.js +++ b/packages/string-templates/scripts/gen-collection-info.js @@ -36,7 +36,7 @@ const ADDED_HELPERS = { duration: { args: ["time", "durationType"], numArgs: 2, - example: '{{duration timeLeft "seconds"}} -> a few seconds', + example: '{{duration 8 "seconds"}} -> a few seconds', description: "Produce a humanized duration left/until given an amount of time and the type of time measurement.", }, @@ -118,6 +118,8 @@ function getCommentInfo(file, func) { return docs } +const excludeFunctions = { string: ["raw"] } + /** * This script is very specific to purpose, parsing the handlebars-helpers files to attempt to get information about them. */ @@ -136,7 +138,8 @@ function run() { // skip built in functions and ones seen already if ( HelperFunctionBuiltin.indexOf(name) !== -1 || - foundNames.indexOf(name) !== -1 + foundNames.indexOf(name) !== -1 || + excludeFunctions[collection]?.includes(name) ) { continue } diff --git a/packages/string-templates/test/helpers.spec.js b/packages/string-templates/test/helpers.spec.js index 380b0f2833..75de373109 100644 --- a/packages/string-templates/test/helpers.spec.js +++ b/packages/string-templates/test/helpers.spec.js @@ -61,10 +61,10 @@ describe("test the array helpers", () => { }) it("should allow use of the before helper", async () => { - const output = await processString("{{before array 2}}", { + const output = await processString("{{before array 3}}", { array, }) - expect(output).toBe("hi,person,how") + expect(output).toBe("hi,person") }) it("should allow use of the filter helper", async () => { diff --git a/packages/string-templates/test/manifest.spec.js b/packages/string-templates/test/manifest.spec.js new file mode 100644 index 0000000000..506f2eb6f7 --- /dev/null +++ b/packages/string-templates/test/manifest.spec.js @@ -0,0 +1,96 @@ +jest.mock("@budibase/handlebars-helpers/lib/math", () => { + const actual = jest.requireActual("@budibase/handlebars-helpers/lib/math") + + return { + ...actual, + random: () => 10, + } +}) +jest.mock("@budibase/handlebars-helpers/lib/uuid", () => { + const actual = jest.requireActual("@budibase/handlebars-helpers/lib/uuid") + + return { + ...actual, + uuid: () => "f34ebc66-93bd-4f7c-b79b-92b5569138bc", + } +}) + +const fs = require("fs") +const { processString } = require("../src/index.cjs") + +const tk = require("timekeeper") +tk.freeze("2021-01-21T12:00:00") + +const manifest = JSON.parse( + fs.readFileSync(require.resolve("../manifest.json"), "utf8") +) + +const collections = Object.keys(manifest) +const examples = collections.reduce((acc, collection) => { + const functions = Object.keys(manifest[collection]).filter( + fnc => manifest[collection][fnc].example + ) + if (functions.length) { + acc[collection] = functions + } + return acc +}, {}) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") // $& means the whole matched string +} + +function tryParseJson(str) { + if (typeof str !== "string") { + return + } + + try { + return JSON.parse(str.replace(/\'/g, '"')) + } catch (e) { + return + } +} + +describe("manifest", () => { + describe("examples are valid", () => { + describe.each(Object.keys(examples))("%s", collection => { + it.each(examples[collection])("%s", async func => { + const example = manifest[collection][func].example + + let [hbs, js] = example.split("->").map(x => x.trim()) + + const context = { + double: i => i * 2, + isString: x => typeof x === "string", + } + + const arrays = hbs.match(/\[[^/\]]+\]/) + arrays?.forEach((arrayString, i) => { + hbs = hbs.replace(new RegExp(escapeRegExp(arrayString)), `array${i}`) + context[`array${i}`] = JSON.parse(arrayString.replace(/\'/g, '"')) + }) + + if (js === undefined) { + // The function has no return value + return + } + + let result = await processString(hbs, context) + // 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(",") + } + } + } + result = result.replace(/ /g, " ") + expect(result).toEqual(js) + }) + }) + }) +}) diff --git a/yarn.lock b/yarn.lock index fa746b9d72..a390d67aa2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2024,10 +2024,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/handlebars-helpers@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.12.0.tgz#dcc4ba8d796a611474e3495b1142c56b470ca67d" - integrity sha512-JjGboau7KMdrVSO8gGJzgo1ACSeD4BxN46vidIx9hvdrEXy+v1x2bfQZMaq/c7Dv+V1vyq7c006XwxR1bpfARg== +"@budibase/handlebars-helpers@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.0.tgz#224333d14e3900b7dacf48286af1e624a9fd62ea" + integrity sha512-g8+sFrMNxsIDnK+MmdUICTVGr6ReUFtnPp9hJX0VZwz1pN3Ynolpk/Qbu6rEWAvoU1sEqY1mXr9uo/+kEfeGbQ== dependencies: get-object "^0.2.0" get-value "^3.0.1"