1
0
Fork 0
mirror of synced 2024-07-13 18:26:06 +12:00

Merge branch 'master' into budi-7680/data-section-add-search-to-data-sources

This commit is contained in:
Adria Navarro 2023-11-20 17:05:41 +01:00 committed by GitHub
commit dbcc768d42
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
88 changed files with 963 additions and 751 deletions

View file

@ -1,13 +1,11 @@
node_modules
dist
*.spec.js
packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte
packages/server/builder
packages/server/coverage
packages/worker/coverage
packages/backend-core/coverage
packages/server/client
packages/server/src/definitions/openapi.ts
packages/worker/coverage
packages/backend-core/coverage
packages/builder/.routify
packages/sdk/sdk
packages/pro/coverage

View file

@ -5,7 +5,6 @@ const { getDB } = require("../db")
describe("db", () => {
describe("getDB", () => {
it("returns a db", async () => {
const dbName = structures.db.id()
const db = getDB(dbName)
expect(db).toBeDefined()

View file

@ -75,10 +75,12 @@ export function getRedisConnectionDetails() {
}
const [host, port] = url.split(":")
const portNumber = parseInt(port)
return {
host,
password,
port: parseInt(port),
// assume default port for redis if invalid found
port: isNaN(portNumber) ? 6379 : portNumber,
}
}

View file

@ -1,5 +1,5 @@
const _ = require('lodash/fp')
const {structures} = require("../../../tests")
const _ = require("lodash/fp")
const { structures } = require("../../../tests")
jest.mock("../../../src/context")
jest.mock("../../../src/db")
@ -7,10 +7,9 @@ jest.mock("../../../src/db")
const context = require("../../../src/context")
const db = require("../../../src/db")
const {getCreatorCount} = require('../../../src/users/users')
const { getCreatorCount } = require("../../../src/users/users")
describe("Users", () => {
let getGlobalDBMock
let getGlobalUserParamsMock
let paginationMock
@ -26,26 +25,26 @@ describe("Users", () => {
it("Retrieves the number of creators", async () => {
const getUsers = (offset, limit, creators = false) => {
const range = _.range(offset, limit)
const opts = creators ? {builder: {global: true}} : undefined
const opts = creators ? { builder: { global: true } } : undefined
return range.map(() => structures.users.user(opts))
}
const page1Data = getUsers(0, 8)
const page2Data = getUsers(8, 12, true)
getGlobalDBMock.mockImplementation(() => ({
name : "fake-db",
name: "fake-db",
allDocs: () => ({
rows: [...page1Data, ...page2Data]
})
rows: [...page1Data, ...page2Data],
}),
}))
paginationMock.mockImplementationOnce(() => ({
data: page1Data,
hasNextPage: true,
nextPage: "1"
nextPage: "1",
}))
paginationMock.mockImplementation(() => ({
data: page2Data,
hasNextPage: false,
nextPage: undefined
nextPage: undefined,
}))
const creatorsCount = await getCreatorCount()
expect(creatorsCount).toBe(4)

View file

@ -10,6 +10,7 @@
export let disabled = false
export let error = null
export let size = "M"
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -18,6 +19,6 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<Checkbox {error} {disabled} {text} {value} {size} on:change={onChange} />
</Field>

View file

@ -11,6 +11,7 @@
export let error = null
export let placeholder = "Choose an option or type"
export let options = []
export let helpText = null
export let getOptionLabel = option => extractProperty(option, "label")
export let getOptionValue = option => extractProperty(option, "value")
@ -27,7 +28,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<Combobox
{error}
{disabled}

View file

@ -4,7 +4,6 @@
import { createEventDispatcher } from "svelte"
export let value = false
export let error = null
export let id = null
export let text = null
export let disabled = false
@ -22,7 +21,6 @@
<label
class="spectrum-Checkbox spectrum-Checkbox--emphasized {sizeClass}"
class:is-invalid={!!error}
class:checked={value}
class:is-indeterminate={indeterminate}
class:readonly

View file

@ -6,7 +6,6 @@
export let direction = "vertical"
export let value = []
export let options = []
export let error = null
export let disabled = false
export let readonly = false
export let getOptionLabel = option => option
@ -34,7 +33,6 @@
<div
title={getOptionLabel(option)}
class="spectrum-Checkbox spectrum-FieldGroup-item"
class:is-invalid={!!error}
class:readonly
>
<label

View file

@ -10,7 +10,6 @@
export let placeholder = "Choose an option or type"
export let disabled = false
export let readonly = false
export let error = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
@ -39,12 +38,10 @@
<div
class="spectrum-InputGroup"
class:is-focused={open || focus}
class:is-invalid={!!error}
class:is-disabled={disabled}
>
<div
class="spectrum-Textfield spectrum-InputGroup-textfield"
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={open || focus}
>

View file

@ -10,7 +10,6 @@
export let id = null
export let disabled = false
export let readonly = false
export let error = null
export let enableTime = true
export let value = null
export let placeholder = null
@ -188,7 +187,6 @@
<div
id={flatpickrId}
class:is-disabled={disabled || readonly}
class:is-invalid={!!error}
class="flatpickr spectrum-InputGroup spectrum-Datepicker"
class:is-focused={open}
aria-readonly="false"
@ -199,17 +197,7 @@
on:click={flatpickr?.open}
class="spectrum-Textfield spectrum-InputGroup-textfield"
class:is-disabled={disabled}
class:is-invalid={!!error}
>
{#if !!error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<input
{disabled}
{readonly}
@ -227,7 +215,6 @@
class="spectrum-Picker spectrum-Picker--sizeM spectrum-InputGroup-button"
tabindex="-1"
class:is-disabled={disabled}
class:is-invalid={!!error}
on:click={flatpickr?.open}
>
<svg

View file

@ -22,7 +22,6 @@
export let handleFileTooLarge = null
export let handleTooManyFiles = null
export let gallery = true
export let error = null
export let fileTags = []
export let maximum = null
export let extensions = "*"
@ -222,7 +221,6 @@
{#if showDropzone}
<div
class="spectrum-Dropzone"
class:is-invalid={!!error}
class:disabled
role="region"
tabindex="0"
@ -351,9 +349,6 @@
.spectrum-Dropzone {
user-select: none;
}
.spectrum-Dropzone.is-invalid {
border-color: var(--spectrum-global-color-red-400);
}
input[type="file"] {
display: none;
}

View file

@ -14,7 +14,6 @@
export let disabled = false
export let readonly = false
export let updateOnChange = true
export let error = null
export let options = []
export let getOptionLabel = option => extractProperty(option, "label")
export let getOptionValue = option => extractProperty(option, "value")
@ -111,27 +110,12 @@
}
</script>
<div
class="spectrum-InputGroup"
class:is-invalid={!!error}
class:is-disabled={disabled}
>
<div class="spectrum-InputGroup" class:is-disabled={disabled}>
<div
class="spectrum-Textfield spectrum-InputGroup-textfield"
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}
>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<input
{id}
on:click

View file

@ -6,7 +6,6 @@
export let id = null
export let placeholder = null
export let disabled = false
export let error = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
@ -84,7 +83,6 @@
<Picker
on:loadMore
{id}
{error}
{disabled}
{readonly}
{fieldText}

View file

@ -14,7 +14,6 @@
export let id = null
export let disabled = false
export let error = null
export let fieldText = ""
export let fieldIcon = ""
export let fieldColour = ""
@ -113,7 +112,6 @@
class="spectrum-Picker spectrum-Picker--sizeM"
class:spectrum-Picker--quiet={quiet}
{disabled}
class:is-invalid={!!error}
class:is-open={open}
aria-haspopup="listbox"
on:click={onClick}
@ -142,16 +140,6 @@
>
{fieldText}
</span>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
focusable="false"
aria-hidden="true"
aria-label="Folder"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<svg
class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
focusable="false"

View file

@ -16,7 +16,6 @@
export let id = null
export let placeholder = "Choose an option or type"
export let disabled = false
export let error = null
export let secondaryOptions = []
export let primaryOptions = []
export let secondaryFieldText = ""
@ -105,14 +104,9 @@
}
</script>
<div
class="spectrum-InputGroup"
class:is-invalid={!!error}
class:is-disabled={disabled}
>
<div class="spectrum-InputGroup" class:is-disabled={disabled}>
<div
class="spectrum-Textfield spectrum-InputGroup-textfield"
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}
class:is-full-width={!secondaryOptions.length}

View file

@ -6,7 +6,6 @@
export let direction = "vertical"
export let value = null
export let options = []
export let error = null
export let disabled = false
export let readonly = false
export let getOptionLabel = option => option
@ -40,7 +39,6 @@
<div
title={getOptionTitle(option)}
class="spectrum-Radio spectrum-FieldGroup-item spectrum-Radio--emphasized"
class:is-invalid={!!error}
class:readonly
>
<input

View file

@ -5,14 +5,13 @@
export let placeholder = null
export let disabled = false
export let readonly = false
export let error = null
export let height = null
export let id = null
export let fullScreenOffset = null
export let easyMDEOptions = null
</script>
<div class:error>
<div>
<MarkdownEditor
{value}
{placeholder}
@ -27,18 +26,4 @@
</div>
<style>
.error :global(.EasyMDEContainer .editor-toolbar) {
border-top-color: var(--spectrum-semantic-negative-color-default);
border-left-color: var(--spectrum-semantic-negative-color-default);
border-right-color: var(--spectrum-semantic-negative-color-default);
}
.error :global(.EasyMDEContainer .CodeMirror) {
border-bottom-color: var(--spectrum-semantic-negative-color-default);
border-left-color: var(--spectrum-semantic-negative-color-default);
border-right-color: var(--spectrum-semantic-negative-color-default);
}
.error :global(.EasyMDEContainer .editor-preview-side) {
border-bottom-color: var(--spectrum-semantic-negative-color-default);
border-right-color: var(--spectrum-semantic-negative-color-default);
}
</style>

View file

@ -6,7 +6,6 @@
export let id = null
export let placeholder = "Choose an option"
export let disabled = false
export let error = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
@ -71,7 +70,6 @@
on:loadMore
{quiet}
{id}
{error}
{disabled}
{readonly}
{fieldText}

View file

@ -7,7 +7,6 @@
export let value = null
export let placeholder = null
export let disabled = false
export let error = null
export let id = null
export let readonly = false
export let updateOnChange = true
@ -98,20 +97,9 @@
<div
class="spectrum-Stepper"
class:spectrum-Stepper--quiet={quiet}
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}
>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<div class="spectrum-Textfield spectrum-Stepper-textfield">
<input
{disabled}

View file

@ -6,7 +6,6 @@
export let placeholder = null
export let disabled = false
export let readonly = false
export let error = null
export let id = null
export let height = null
export let minHeight = null
@ -41,20 +40,9 @@
<div
style={`${heightString}${minHeightString}`}
class="spectrum-Textfield spectrum-Textfield--multiline"
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}
>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM
spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<!-- prettier-ignore -->
<textarea
bind:this={textarea}

View file

@ -6,7 +6,6 @@
export let placeholder = null
export let type = "text"
export let disabled = false
export let error = null
export let id = null
export let readonly = false
export let updateOnChange = true
@ -78,19 +77,9 @@
<div
class="spectrum-Textfield"
class:spectrum-Textfield--quiet={quiet}
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}
>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<input
bind:this={field}
{disabled}

View file

@ -16,6 +16,7 @@
export let appendTo = undefined
export let ignoreTimezones = false
export let range = false
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -30,7 +31,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<DatePicker
{error}
{disabled}

View file

@ -17,6 +17,7 @@
export let fileTags = []
export let maximum = undefined
export let compact = false
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -25,7 +26,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<CoreDropzone
{error}
{disabled}

View file

@ -16,6 +16,7 @@
export let autofocus
export let variables
export let showModal
export let helpText = null
export let environmentVariablesEnabled
export let handleUpgradePanel
const dispatch = createEventDispatcher()
@ -25,7 +26,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<EnvDropdown
{updateOnChange}
{error}

View file

@ -1,11 +1,13 @@
<script>
import "@spectrum-css/fieldlabel/dist/index-vars.css"
import FieldLabel from "./FieldLabel.svelte"
import Icon from "../Icon/Icon.svelte"
export let id = null
export let label = null
export let labelPosition = "above"
export let error = null
export let helpText = null
export let tooltip = ""
</script>
@ -17,6 +19,10 @@
<slot />
{#if error}
<div class="error">{error}</div>
{:else if helpText}
<div class="helpText">
<Icon name="HelpOutline" /> <span>{helpText}</span>
</div>
{/if}
</div>
</div>
@ -39,4 +45,21 @@
font-size: var(--spectrum-global-dimension-font-size-75);
margin-top: var(--spectrum-global-dimension-size-75);
}
.helpText {
display: flex;
margin-top: var(--spectrum-global-dimension-size-75);
align-items: center;
}
.helpText :global(svg) {
width: 14px;
color: var(--grey-5);
margin-right: 6px;
}
.helpText span {
color: var(--grey-7);
font-size: var(--spectrum-global-dimension-font-size-75);
}
</style>

View file

@ -14,6 +14,7 @@
export let title = null
export let value = null
export let tooltip = null
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -22,7 +23,7 @@
}
</script>
<Field {label} {labelPosition} {error} {tooltip}>
<Field {helpText} {label} {labelPosition} {error} {tooltip}>
<CoreFile
{error}
{disabled}

View file

@ -15,6 +15,7 @@
export let quiet = false
export let autofocus
export let autocomplete
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -23,7 +24,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<TextField
{updateOnChange}
{error}

View file

@ -15,6 +15,7 @@
export let updateOnChange = true
export let quiet = false
export let autofocus
export let helpText = null
export let options = []
const dispatch = createEventDispatcher()
@ -29,7 +30,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<InputDropdown
{updateOnChange}
{error}

View file

@ -18,6 +18,7 @@
export let autocomplete = false
export let searchTerm = null
export let customPopoverHeight
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -26,7 +27,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<Multiselect
{error}
{disabled}

View file

@ -26,6 +26,7 @@
export let secondaryOptions = []
export let searchTerm
export let showClearIcon = true
export let helpText = null
let primaryLabel
let secondaryLabel
@ -93,7 +94,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<PickerDropdown
{searchTerm}
{autocomplete}

View file

@ -13,6 +13,7 @@
export let getOptionLabel = option => extractProperty(option, "label")
export let getOptionValue = option => extractProperty(option, "value")
export let getOptionTitle = option => extractProperty(option, "label")
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -27,7 +28,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<RadioGroup
{error}
{disabled}

View file

@ -13,6 +13,7 @@
export let id = null
export let fullScreenOffset = null
export let easyMDEOptions = null
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -21,7 +22,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<RichTextField
{error}
{disabled}

View file

@ -11,6 +11,7 @@
export let updateOnChange = true
export let quiet = false
export let inputRef
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -19,7 +20,7 @@
}
</script>
<Field {label} {labelPosition}>
<Field {helpText} {label} {labelPosition}>
<Search
{updateOnChange}
{disabled}

View file

@ -26,6 +26,7 @@
export let align
export let footer = null
export let tag = null
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
value = e.detail
@ -40,7 +41,7 @@
}
</script>
<Field {label} {labelPosition} {error} {tooltip}>
<Field {helpText} {label} {labelPosition} {error} {tooltip}>
<Select
{quiet}
{error}

View file

@ -11,6 +11,7 @@
export let step = 1
export let disabled = false
export let error = null
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -19,6 +20,6 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<Slider {disabled} {value} {min} {max} {step} on:change={onChange} />
</Field>

View file

@ -15,6 +15,7 @@
export let min = null
export let max = null
export let step = 1
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -23,7 +24,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<Stepper
{updateOnChange}
{error}

View file

@ -12,6 +12,7 @@
export let getCaretPosition = null
export let height = null
export let minHeight = null
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -20,7 +21,7 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<TextArea
bind:getCaretPosition
{error}

View file

@ -9,6 +9,7 @@
export let text = null
export let disabled = false
export let error = null
export let helpText = null
const dispatch = createEventDispatcher()
const onChange = e => {
@ -17,6 +18,6 @@
}
</script>
<Field {label} {labelPosition} {error}>
<Field {helpText} {label} {labelPosition} {error}>
<Switch {error} {disabled} {text} {value} on:change={onChange} />
</Field>

View file

@ -2731,6 +2731,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -2862,6 +2867,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -2959,6 +2969,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -3175,6 +3190,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "boolean",
"label": "Autocomplete",
@ -3335,6 +3355,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -3559,6 +3584,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -3657,6 +3687,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -3799,6 +3834,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -3894,6 +3934,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "boolean",
"label": "Disabled",
@ -4144,6 +4189,11 @@
"label": "Label",
"key": "label"
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "text",
"label": "Extensions",
@ -4247,6 +4297,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -4355,6 +4410,11 @@
"key": "defaultValue",
"supportsConditions": false
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",
@ -6395,6 +6455,11 @@
"label": "Default value",
"key": "defaultValue"
},
{
"type": "text",
"label": "Help text",
"key": "helpText"
},
{
"type": "event",
"label": "On change",

View file

@ -13,6 +13,7 @@
export let onChange
export let maximum = undefined
export let span
export let helpText = null
let fieldState
let fieldApi
@ -76,6 +77,7 @@
{readonly}
{validation}
{span}
{helpText}
type="attachment"
bind:fieldState
bind:fieldApi

View file

@ -11,6 +11,7 @@
export let validation
export let defaultValue
export let onChange
export let helpText = null
let fieldState
let fieldApi
@ -42,6 +43,7 @@
{disabled}
{readonly}
{validation}
{helpText}
defaultValue={isTruthy(defaultValue)}
type="boolean"
bind:fieldState

View file

@ -16,6 +16,7 @@
export let beepFrequency
export let customFrequency
export let preferredCamera
export let helpText = null
let fieldState
let fieldApi
@ -38,6 +39,7 @@
{validation}
{defaultValue}
{type}
{helpText}
bind:fieldState
bind:fieldApi
>

View file

@ -15,6 +15,7 @@
export let defaultValue
export let onChange
export let span
export let helpText = null
let fieldState
let fieldApi
@ -35,6 +36,7 @@
{validation}
{defaultValue}
{span}
{helpText}
type="datetime"
bind:fieldState
bind:fieldApi

View file

@ -1,6 +1,7 @@
<script>
import Placeholder from "../Placeholder.svelte"
import { getContext, onDestroy } from "svelte"
import { Icon } from "@budibase/bbui"
export let label
export let field
@ -13,6 +14,7 @@
export let readonly = false
export let validation
export let span = 6
export let helpText = null
// Get contexts
const formContext = getContext("form")
@ -97,7 +99,14 @@
{:else}
<slot />
{#if fieldState.error}
<div class="error">{fieldState.error}</div>
<div class="error">
<Icon name="Alert" />
<span>{fieldState.error}</span>
</div>
{:else if helpText}
<div class="helpText">
<Icon name="HelpOutline" /> <span>{helpText}</span>
</div>
{/if}
{/if}
</div>
@ -127,13 +136,45 @@
position: relative;
width: 100%;
}
.error {
display: flex;
margin-top: var(--spectrum-global-dimension-size-75);
align-items: center;
}
.error :global(svg) {
width: 14px;
color: var(
--spectrum-semantic-negative-color-default,
var(--spectrum-global-color-red-500)
);
margin-right: 4px;
}
.error span {
color: var(
--spectrum-semantic-negative-color-default,
var(--spectrum-global-color-red-500)
);
font-size: var(--spectrum-global-dimension-font-size-75);
}
.helpText {
display: flex;
margin-top: var(--spectrum-global-dimension-size-75);
align-items: center;
}
.helpText :global(svg) {
width: 14px;
color: var(--grey-7);
margin-right: 6px;
}
.helpText span {
color: var(--grey-5);
font-size: var(--spectrum-global-dimension-font-size-75);
}
.spectrum-FieldLabel--right,
.spectrum-FieldLabel--left {

View file

@ -10,6 +10,7 @@
export let readonly = false
export let defaultValue = ""
export let onChange
export let helpText = null
const component = getContext("component")
const validation = [
@ -52,6 +53,7 @@
{readonly}
{validation}
{defaultValue}
{helpText}
type="json"
bind:fieldState
bind:fieldApi

View file

@ -13,6 +13,7 @@
export let defaultValue = ""
export let format = "auto"
export let onChange
export let helpText = null
let fieldState
let fieldApi
@ -62,6 +63,7 @@
{readonly}
{validation}
{defaultValue}
{helpText}
type="longform"
bind:fieldState
bind:fieldApi

View file

@ -19,6 +19,7 @@
export let optionsType = "select"
export let direction = "vertical"
export let span
export let helpText = null
let fieldState
let fieldApi
@ -60,6 +61,7 @@
{readonly}
{validation}
{span}
{helpText}
defaultValue={expandedDefaultValue}
type="array"
bind:fieldState

View file

@ -20,6 +20,7 @@
export let onChange
export let sort = true
export let span
export let helpText = null
let fieldState
let fieldApi
@ -51,6 +52,7 @@
{validation}
{defaultValue}
{span}
{helpText}
type="options"
bind:fieldState
bind:fieldApi

View file

@ -20,6 +20,7 @@
export let datasourceType = "table"
export let primaryDisplay
export let span
export let helpText = null
let fieldState
let fieldApi
@ -192,6 +193,7 @@
defaultValue={expandedDefaultValue}
{type}
{span}
{helpText}
bind:fieldState
bind:fieldApi
bind:fieldSchema

View file

@ -13,6 +13,7 @@
export let align
export let onChange
export let span
export let helpText = null
let fieldState
let fieldApi
@ -33,6 +34,7 @@
{validation}
{defaultValue}
{span}
{helpText}
type={type === "number" ? "number" : "string"}
bind:fieldState
bind:fieldApi
@ -44,7 +46,6 @@
on:change={handleChange}
disabled={fieldState.disabled}
readonly={fieldState.readonly}
error={fieldState.error}
id={fieldState.fieldId}
{placeholder}
{type}

View file

@ -1,13 +1,13 @@
const { Curl } = require("../../curl")
const fs = require("fs")
const path = require('path')
const path = require("path")
const getData = (file) => {
const getData = file => {
return fs.readFileSync(path.join(__dirname, `./data/${file}.txt`), "utf8")
}
describe("Curl Import", () => {
let curl
let curl
beforeEach(() => {
curl = new Curl()
@ -28,7 +28,7 @@ describe("Curl Import", () => {
expect(supported).toBe(false)
})
const init = async (file) => {
const init = async file => {
await curl.isSupported(getData(file))
}
@ -37,10 +37,9 @@ describe("Curl Import", () => {
const info = await curl.getInfo()
expect(info.name).toBe("example.com")
})
describe("Returns queries", () => {
const getQueries = async (file) => {
const getQueries = async file => {
await init(file)
const queries = await curl.getQueries()
expect(queries.length).toBe(1)
@ -58,7 +57,7 @@ describe("Curl Import", () => {
await testVerb("put", "update")
await testVerb("delete", "delete")
await testVerb("patch", "patch")
})
})
const testPath = async (file, urlPath) => {
const queries = await getQueries(file)
@ -66,8 +65,8 @@ describe("Curl Import", () => {
}
it("populates path", async () => {
await testPath("get", "http://example.com/")
await testPath("path", "http://example.com/paths/abc")
await testPath("get", "http://example.com/")
await testPath("path", "http://example.com/paths/abc")
})
const testHeaders = async (file, headers) => {
@ -77,7 +76,10 @@ describe("Curl Import", () => {
it("populates headers", async () => {
await testHeaders("get", {})
await testHeaders("headers", { "x-bb-header-1" : "123", "x-bb-header-2" : "456"} )
await testHeaders("headers", {
"x-bb-header-1": "123",
"x-bb-header-2": "456",
})
})
const testQuery = async (file, queryString) => {
@ -91,13 +93,15 @@ describe("Curl Import", () => {
const testBody = async (file, body) => {
const queries = await getQueries(file)
expect(queries[0].fields.requestBody).toStrictEqual(JSON.stringify(body, null, 2))
expect(queries[0].fields.requestBody).toStrictEqual(
JSON.stringify(body, null, 2)
)
}
it("populates body", async () => {
await testBody("get", undefined)
await testBody("post", { "key" : "val" })
await testBody("post", { key: "val" })
await testBody("empty-body", {})
})
})
})
})

View file

@ -1,13 +1,16 @@
const { OpenAPI2 } = require("../../openapi2")
const fs = require("fs")
const path = require('path')
const path = require("path")
const getData = (file, extension) => {
return fs.readFileSync(path.join(__dirname, `./data/${file}/${file}.${extension}`), "utf8")
return fs.readFileSync(
path.join(__dirname, `./data/${file}/${file}.${extension}`),
"utf8"
)
}
describe("OpenAPI2 Import", () => {
let openapi2
let openapi2
beforeEach(() => {
openapi2 = new OpenAPI2()
@ -47,9 +50,9 @@ describe("OpenAPI2 Import", () => {
it("returns import info", async () => {
await runTests("petstore", testImportInfo)
})
describe("Returns queries", () => {
const indexQueries = (queries) => {
const indexQueries = queries => {
return queries.reduce((acc, query) => {
acc[query.name] = query
return acc
@ -72,15 +75,15 @@ describe("OpenAPI2 Import", () => {
it("populates verb", async () => {
const assertions = {
"createEntity" : "create",
"getEntities" : "read",
"getEntity" : "read",
"updateEntity" : "update",
"patchEntity" : "patch",
"deleteEntity" : "delete"
createEntity: "create",
getEntities: "read",
getEntity: "read",
updateEntity: "update",
patchEntity: "patch",
deleteEntity: "delete",
}
await runTests("crud", testVerb, assertions)
})
})
const testPath = async (file, extension, assertions) => {
const queries = await getQueries(file, extension)
@ -91,12 +94,12 @@ describe("OpenAPI2 Import", () => {
it("populates path", async () => {
const assertions = {
"createEntity" : "http://example.com/entities",
"getEntities" : "http://example.com/entities",
"getEntity" : "http://example.com/entities/{{entityId}}",
"updateEntity" : "http://example.com/entities/{{entityId}}",
"patchEntity" : "http://example.com/entities/{{entityId}}",
"deleteEntity" : "http://example.com/entities/{{entityId}}"
createEntity: "http://example.com/entities",
getEntities: "http://example.com/entities",
getEntity: "http://example.com/entities/{{entityId}}",
updateEntity: "http://example.com/entities/{{entityId}}",
patchEntity: "http://example.com/entities/{{entityId}}",
deleteEntity: "http://example.com/entities/{{entityId}}",
}
await runTests("crud", testPath, assertions)
})
@ -109,27 +112,25 @@ describe("OpenAPI2 Import", () => {
}
const contentTypeHeader = {
"Content-Type" : "application/json",
"Content-Type": "application/json",
}
it("populates headers", async () => {
const assertions = {
"createEntity" : {
...contentTypeHeader
createEntity: {
...contentTypeHeader,
},
"getEntities" : {
getEntities: {},
getEntity: {},
updateEntity: {
...contentTypeHeader,
},
"getEntity" : {
patchEntity: {
...contentTypeHeader,
},
"updateEntity" : {
...contentTypeHeader
deleteEntity: {
"x-api-key": "{{x-api-key}}",
},
"patchEntity" : {
...contentTypeHeader
},
"deleteEntity" : {
"x-api-key" : "{{x-api-key}}",
}
}
await runTests("crud", testHeaders, assertions)
@ -138,18 +139,20 @@ describe("OpenAPI2 Import", () => {
const testQuery = async (file, extension, assertions) => {
const queries = await getQueries(file, extension)
for (let [operationId, queryString] of Object.entries(assertions)) {
expect(queries[operationId].fields.queryString).toStrictEqual(queryString)
expect(queries[operationId].fields.queryString).toStrictEqual(
queryString
)
}
}
it("populates query", async () => {
const assertions = {
"createEntity" : "",
"getEntities" : "page={{page}}&size={{size}}",
"getEntity" : "",
"updateEntity" : "",
"patchEntity" : "",
"deleteEntity" : ""
createEntity: "",
getEntities: "page={{page}}&size={{size}}",
getEntity: "",
updateEntity: "",
patchEntity: "",
deleteEntity: "",
}
await runTests("crud", testQuery, assertions)
})
@ -163,45 +166,45 @@ describe("OpenAPI2 Import", () => {
it("populates parameters", async () => {
const assertions = {
"createEntity" : [],
"getEntities" : [
createEntity: [],
getEntities: [
{
"name" : "page",
"default" : "",
name: "page",
default: "",
},
{
"name" : "size",
"default" : "",
}
name: "size",
default: "",
},
],
"getEntity" : [
getEntity: [
{
"name" : "entityId",
"default" : "",
}
name: "entityId",
default: "",
},
],
"updateEntity" : [
updateEntity: [
{
"name" : "entityId",
"default" : "",
}
name: "entityId",
default: "",
},
],
"patchEntity" : [
patchEntity: [
{
"name" : "entityId",
"default" : "",
}
name: "entityId",
default: "",
},
],
"deleteEntity" : [
deleteEntity: [
{
"name" : "entityId",
"default" : "",
name: "entityId",
default: "",
},
{
"name" : "x-api-key",
"default" : "",
}
]
name: "x-api-key",
default: "",
},
],
}
await runTests("crud", testParameters, assertions)
})
@ -209,30 +212,32 @@ describe("OpenAPI2 Import", () => {
const testBody = async (file, extension, assertions) => {
const queries = await getQueries(file, extension)
for (let [operationId, body] of Object.entries(assertions)) {
expect(queries[operationId].fields.requestBody).toStrictEqual(JSON.stringify(body, null, 2))
expect(queries[operationId].fields.requestBody).toStrictEqual(
JSON.stringify(body, null, 2)
)
}
}
it("populates body", async () => {
const assertions = {
"createEntity" : {
"name" : "name",
"type" : "type",
createEntity: {
name: "name",
type: "type",
},
"getEntities" : undefined,
"getEntity" : undefined,
"updateEntity" : {
"id": 1,
"name" : "name",
"type" : "type",
getEntities: undefined,
getEntity: undefined,
updateEntity: {
id: 1,
name: "name",
type: "type",
},
"patchEntity" : {
"id": 1,
"name" : "name",
"type" : "type",
patchEntity: {
id: 1,
name: "name",
type: "type",
},
"deleteEntity" : undefined
deleteEntity: undefined,
}
await runTests("crud", testBody, assertions)
})
})
})
})

View file

@ -1,11 +1,14 @@
const TestConfig = require("../../../../../tests/utilities/TestConfiguration")
const { RestImporter } = require("../index")
const fs = require("fs")
const path = require('path')
const { events} = require("@budibase/backend-core")
const path = require("path")
const { events } = require("@budibase/backend-core")
const getData = (file) => {
return fs.readFileSync(path.join(__dirname, `../sources/tests/${file}`), "utf8")
const getData = file => {
return fs.readFileSync(
path.join(__dirname, `../sources/tests/${file}`),
"utf8"
)
}
// openapi2 (swagger)
@ -14,7 +17,7 @@ const oapi2CrudYaml = getData("openapi2/data/crud/crud.json")
const oapi2PetstoreJson = getData("openapi2/data/petstore/petstore.json")
const oapi2PetstoreYaml = getData("openapi2/data/petstore/petstore.json")
// openapi3
// openapi3
const oapi3CrudJson = getData("openapi3/data/crud/crud.json")
const oapi3CrudYaml = getData("openapi3/data/crud/crud.json")
const oapi3PetstoreJson = getData("openapi3/data/petstore/petstore.json")
@ -35,7 +38,7 @@ const datasets = {
oapi3PetstoreJson,
oapi3PetstoreYaml,
// curl
curl
curl,
}
describe("Rest Importer", () => {
@ -45,9 +48,9 @@ describe("Rest Importer", () => {
await config.init()
})
let restImporter
let restImporter
const init = async (data) => {
const init = async data => {
restImporter = new RestImporter(data)
await restImporter.init()
}
@ -69,35 +72,35 @@ describe("Rest Importer", () => {
it("gets info", async () => {
const assertions = {
// openapi2 (swagger)
"oapi2CrudJson" : {
oapi2CrudJson: {
name: "CRUD",
},
"oapi2CrudYaml" : {
oapi2CrudYaml: {
name: "CRUD",
},
"oapi2PetstoreJson" : {
oapi2PetstoreJson: {
name: "Swagger Petstore",
},
"oapi2PetstoreYaml" :{
oapi2PetstoreYaml: {
name: "Swagger Petstore",
},
// openapi3
"oapi3CrudJson" : {
oapi3CrudJson: {
name: "CRUD",
},
"oapi3CrudYaml" : {
oapi3CrudYaml: {
name: "CRUD",
},
"oapi3PetstoreJson" : {
oapi3PetstoreJson: {
name: "Swagger Petstore - OpenAPI 3.0",
},
"oapi3PetstoreYaml" :{
oapi3PetstoreYaml: {
name: "Swagger Petstore - OpenAPI 3.0",
},
// curl
"curl": {
curl: {
name: "example.com",
}
},
}
await runTest(testGetInfo, assertions)
})
@ -109,54 +112,58 @@ describe("Rest Importer", () => {
expect(importResult.errorQueries.length).toBe(0)
expect(importResult.queries.length).toBe(assertions[key].count)
expect(events.query.imported).toBeCalledTimes(1)
expect(events.query.imported).toBeCalledWith(datasource, assertions[key].source, assertions[key].count)
expect(events.query.imported).toBeCalledWith(
datasource,
assertions[key].source,
assertions[key].count
)
jest.clearAllMocks()
}
it("imports queries", async () => {
// simple sanity assertions that the whole dataset
// simple sanity assertions that the whole dataset
// makes it through the importer
const assertions = {
// openapi2 (swagger)
"oapi2CrudJson" : {
oapi2CrudJson: {
count: 6,
source: "openapi2.0",
},
"oapi2CrudYaml" :{
oapi2CrudYaml: {
count: 6,
source: "openapi2.0"
source: "openapi2.0",
},
"oapi2PetstoreJson" : {
oapi2PetstoreJson: {
count: 20,
source: "openapi2.0"
source: "openapi2.0",
},
"oapi2PetstoreYaml" :{
oapi2PetstoreYaml: {
count: 20,
source: "openapi2.0"
source: "openapi2.0",
},
// openapi3
"oapi3CrudJson" : {
oapi3CrudJson: {
count: 6,
source: "openapi3.0"
source: "openapi3.0",
},
"oapi3CrudYaml" :{
oapi3CrudYaml: {
count: 6,
source: "openapi3.0"
source: "openapi3.0",
},
"oapi3PetstoreJson" : {
oapi3PetstoreJson: {
count: 19,
source: "openapi3.0"
source: "openapi3.0",
},
"oapi3PetstoreYaml" :{
oapi3PetstoreYaml: {
count: 19,
source: "openapi3.0"
source: "openapi3.0",
},
// curl
"curl": {
curl: {
count: 1,
source: "curl"
}
source: "curl",
},
}
await runTest(testImportQueries, assertions)
})
})
})

View file

@ -1,65 +1,75 @@
const viewTemplate = require("../viewBuilder").default;
const viewTemplate = require("../viewBuilder").default
describe("viewBuilder", () => {
describe("Filter", () => {
it("creates a view with multiple filters and conjunctions", () => {
expect(viewTemplate({
"name": "Test View",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"filters": [{
"value": "Test",
"condition": "EQUALS",
"key": "Name"
}, {
"value": "Value",
"condition": "MT",
"key": "Yes",
"conjunction": "OR"
}]
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Test View",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
filters: [
{
value: "Test",
condition: "EQUALS",
key: "Name",
},
{
value: "Value",
condition: "MT",
key: "Yes",
conjunction: "OR",
},
],
})
).toMatchSnapshot()
})
})
describe("Calculate", () => {
it("creates a view with the calculation statistics schema", () => {
expect(viewTemplate({
"name": "Calculate View",
"field": "myField",
"calculation": "stats",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"filters": []
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Calculate View",
field: "myField",
calculation: "stats",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
filters: [],
})
).toMatchSnapshot()
})
})
describe("Group By", () => {
it("creates a view emitting the group by field", () => {
expect(viewTemplate({
"name": "Test Scores Grouped By Age",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"groupBy": "age",
"field": "score",
"filters": [],
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Test Scores Grouped By Age",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
groupBy: "age",
field: "score",
filters: [],
})
).toMatchSnapshot()
})
})
describe("Calculate and filter", () => {
it("creates a view with the calculation statistics and filter schema", () => {
expect(viewTemplate({
"name": "Calculate View",
"field": "myField",
"calculation": "stats",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"filters": [
{
"value": 17,
"condition": "MT",
"key": "age",
}
]
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Calculate View",
field: "myField",
calculation: "stats",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
filters: [
{
value: 17,
condition: "MT",
key: "age",
},
],
})
).toMatchSnapshot()
})
})
});
})

View file

@ -117,7 +117,7 @@ write.push(
* /applications/{appId}/publish:
* post:
* operationId: appPublish
* summary: Unpublish an application
* summary: Publish an application
* tags:
* - applications
* parameters:

View file

@ -25,10 +25,9 @@ describe("/metrics", () => {
it("endpoint should not be publicly exposed", async () => {
await request
.get(`/api/public/v1/metrics`)
.set(config.publicHeaders())
.expect(403)
.get(`/api/public/v1/metrics`)
.set(config.publicHeaders())
.expect(403)
})
})
})

View file

@ -13,8 +13,8 @@ describe("/static", () => {
beforeAll(async () => {
app = await config.init()
})
beforeEach(()=>{
beforeEach(() => {
jest.clearAllMocks()
})
@ -22,7 +22,7 @@ describe("/static", () => {
it("should ping from builder", async () => {
await request
.post("/api/bbtel/ping")
.send({source: "builder", timezone})
.send({ source: "builder", timezone })
.set(config.defaultHeaders())
.expect(200)
@ -35,12 +35,15 @@ describe("/static", () => {
it("should ping from app preview", async () => {
await request
.post("/api/bbtel/ping")
.send({source: "app", timezone})
.send({ source: "app", timezone })
.set(config.defaultHeaders())
.expect(200)
expect(events.serve.servedAppPreview).toBeCalledTimes(1)
expect(events.serve.servedAppPreview).toBeCalledWith(config.getApp(), timezone)
expect(events.serve.servedAppPreview).toBeCalledWith(
config.getApp(),
timezone
)
expect(events.serve.servedApp).not.toBeCalled()
})
@ -50,12 +53,16 @@ describe("/static", () => {
await request
.post("/api/bbtel/ping")
.send({source: "app", timezone})
.send({ source: "app", timezone })
.set(headers)
.expect(200)
expect(events.serve.servedApp).toBeCalledTimes(1)
expect(events.serve.servedApp).toBeCalledWith(config.getProdApp(), timezone, undefined)
expect(events.serve.servedApp).toBeCalledWith(
config.getProdApp(),
timezone,
undefined
)
expect(events.serve.servedAppPreview).not.toBeCalled()
})
@ -65,12 +72,16 @@ describe("/static", () => {
await request
.post("/api/bbtel/ping")
.send({source: "app", timezone, embedded: true})
.send({ source: "app", timezone, embedded: true })
.set(headers)
.expect(200)
expect(events.serve.servedApp).toBeCalledTimes(1)
expect(events.serve.servedApp).toBeCalledWith(config.getProdApp(), timezone, true)
expect(events.serve.servedApp).toBeCalledWith(
config.getProdApp(),
timezone,
true
)
expect(events.serve.servedAppPreview).not.toBeCalled()
})
})

View file

@ -38,7 +38,7 @@ describe("/api/keys", () => {
const res = await request
.put(`/api/keys/TEST`)
.send({
value: "test"
value: "test",
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
@ -56,4 +56,4 @@ describe("/api/keys", () => {
})
})
})
})
})

View file

@ -21,4 +21,4 @@ describe("/authenticate", () => {
expect(res.body._id).toEqual(generateUserMetadataID(config.user._id))
})
})
})
})

View file

@ -29,4 +29,4 @@ describe("/component", () => {
})
})
})
})
})

View file

@ -1,7 +1,6 @@
const setup = require("./utilities")
const { events } = require("@budibase/backend-core")
describe("/dev", () => {
let request = setup.getRequest()
let config = setup.getConfig()
@ -32,9 +31,9 @@ describe("/dev", () => {
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.version).toBe('0.0.0+jest')
expect(res.body.version).toBe("0.0.0+jest")
expect(events.installation.versionChecked).toBeCalledTimes(1)
expect(events.installation.versionChecked).toBeCalledWith('0.0.0+jest')
expect(events.installation.versionChecked).toBeCalledWith("0.0.0+jest")
})
})
})
})

View file

@ -49,4 +49,4 @@ describe("/integrations", () => {
})
})
})
})
})

View file

@ -56,4 +56,4 @@ describe("/layouts", () => {
})
})
})
})
})

View file

@ -14,7 +14,10 @@ describe("/metadata", () => {
automation = await config.createAutomation()
})
async function createMetadata(data, type = MetadataTypes.AUTOMATION_TEST_INPUT) {
async function createMetadata(
data,
type = MetadataTypes.AUTOMATION_TEST_INPUT
) {
const res = await request
.post(`/api/metadata/${type}/${automation._id}`)
.send(data)
@ -53,7 +56,9 @@ describe("/metadata", () => {
describe("destroy", () => {
it("should be able to delete some test inputs", async () => {
const res = await request
.delete(`/api/metadata/${MetadataTypes.AUTOMATION_TEST_INPUT}/${automation._id}`)
.delete(
`/api/metadata/${MetadataTypes.AUTOMATION_TEST_INPUT}/${automation._id}`
)
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)

View file

@ -1,4 +1,4 @@
const tk = require( "timekeeper")
const tk = require("timekeeper")
tk.freeze(Date.now())
// Mock out postgres for this
@ -14,7 +14,7 @@ jest.mock("@budibase/backend-core", () => {
db: {
...core.db,
isProdAppID: jest.fn(),
}
},
}
})
const setup = require("./utilities")
@ -30,8 +30,7 @@ describe("/queries", () => {
afterAll(setup.afterAll)
const setupTest = async()=>{
const setupTest = async () => {
await config.init()
datasource = await config.createDatasource()
query = await config.createQuery()
@ -52,7 +51,7 @@ describe("/queries", () => {
return { datasource, query }
}
const createQuery = async (query) => {
const createQuery = async query => {
return request
.post(`/api/queries`)
.send(query)
@ -76,7 +75,7 @@ describe("/queries", () => {
_id: res.body._id,
...query,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
updatedAt: new Date().toISOString(),
})
expect(events.query.created).toBeCalledTimes(1)
expect(events.query.updated).not.toBeCalled()
@ -101,7 +100,7 @@ describe("/queries", () => {
_id: res.body._id,
...query,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
updatedAt: new Date().toISOString(),
})
expect(events.query.created).not.toBeCalled()
expect(events.query.updated).toBeCalledTimes(1)
@ -109,7 +108,7 @@ describe("/queries", () => {
})
describe("fetch", () => {
beforeEach(async() => {
beforeEach(async () => {
await setupTest()
})
@ -190,7 +189,7 @@ describe("/queries", () => {
})
describe("destroy", () => {
beforeEach(async() => {
beforeEach(async () => {
await setupTest()
})
@ -237,8 +236,8 @@ describe("/queries", () => {
.expect(200)
// these responses come from the mock
expect(res.body.schemaFields).toEqual({
"a": "string",
"b": "number",
a: "string",
b: "number",
})
expect(res.body.rows.length).toEqual(1)
expect(events.query.previewed).toBeCalledTimes(1)
@ -256,7 +255,7 @@ describe("/queries", () => {
})
describe("execute", () => {
beforeEach(async() => {
beforeEach(async () => {
await setupTest()
})
@ -302,9 +301,9 @@ describe("/queries", () => {
})
// these responses come from the mock
expect(res.body.schemaFields).toEqual({
"opts": "json",
"url": "string",
"value": "string",
opts: "json",
url: "string",
value: "string",
})
expect(res.body.rows[0].url).toEqual("http://www.google.com?test=1")
})
@ -316,9 +315,9 @@ describe("/queries", () => {
queryString: "test={{ variable3 }}",
})
expect(res.body.schemaFields).toEqual({
"opts": "json",
"url": "string",
"value": "string"
opts: "json",
url: "string",
value: "string",
})
expect(res.body.rows[0].url).toContain("doctype%20html")
})
@ -339,9 +338,9 @@ describe("/queries", () => {
queryString: "test={{ variable3 }}",
})
expect(res.body.schemaFields).toEqual({
"fails": "number",
"opts": "json",
"url": "string"
fails: "number",
opts: "json",
url: "string",
})
expect(res.body.rows[0].fails).toEqual(1)
})
@ -371,13 +370,19 @@ describe("/queries", () => {
})
describe("Current User Request Mapping", () => {
async function previewGet(datasource, fields, params) {
return config.previewQuery(request, config, datasource, fields, params)
}
async function previewPost(datasource, fields, params) {
return config.previewQuery(request, config, datasource, fields, params, "create")
return config.previewQuery(
request,
config,
datasource,
fields,
params,
"create"
)
}
it("should parse global and query level header mappings", async () => {
@ -385,120 +390,160 @@ describe("/queries", () => {
const datasource = await config.restDatasource({
defaultHeaders: {
"test": "headerVal",
"emailHdr": "{{[user].[email]}}"
}
test: "headerVal",
emailHdr: "{{[user].[email]}}",
},
})
const res = await previewGet(datasource, {
path: "www.google.com",
queryString: "email={{[user].[email]}}",
headers: {
queryHdr : "{{[user].[firstName]}}",
secondHdr : "1234"
}
queryHdr: "{{[user].[firstName]}}",
secondHdr: "1234",
},
})
const parsedRequest = JSON.parse(res.body.extra.raw)
expect(parsedRequest.opts.headers).toEqual({
"test": "headerVal",
"emailHdr": userDetails.email,
"queryHdr": userDetails.firstName,
"secondHdr" : "1234"
test: "headerVal",
emailHdr: userDetails.email,
queryHdr: userDetails.firstName,
secondHdr: "1234",
})
expect(res.body.rows[0].url).toEqual("http://www.google.com?email=" + userDetails.email.replace("@", "%40"))
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?email=" + userDetails.email.replace("@", "%40")
)
})
it("should bind the current user to query parameters", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewGet(datasource, {
path: "www.google.com",
queryString: "test={{myEmail}}&testName={{myName}}&testParam={{testParam}}",
}, {
"myEmail" : "{{[user].[email]}}",
"myName" : "{{[user].[firstName]}}",
"testParam" : "1234"
})
expect(res.body.rows[0].url).toEqual("http://www.google.com?test=" + userDetails.email.replace("@", "%40") +
"&testName=" + userDetails.firstName + "&testParam=1234")
const res = await previewGet(
datasource,
{
path: "www.google.com",
queryString:
"test={{myEmail}}&testName={{myName}}&testParam={{testParam}}",
},
{
myEmail: "{{[user].[email]}}",
myName: "{{[user].[firstName]}}",
testParam: "1234",
}
)
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?test=" +
userDetails.email.replace("@", "%40") +
"&testName=" +
userDetails.firstName +
"&testParam=1234"
)
})
it("should bind the current user the request body - plain text", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "This is plain text and this is my email: {{[user].[email]}}. This is a test param: {{testParam}}",
bodyType: "text"
}, {
"testParam" : "1234"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
"This is plain text and this is my email: {{[user].[email]}}. This is a test param: {{testParam}}",
bodyType: "text",
},
{
testParam: "1234",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
expect(parsedRequest.opts.body).toEqual(`This is plain text and this is my email: ${userDetails.email}. This is a test param: 1234`)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(parsedRequest.opts.body).toEqual(
`This is plain text and this is my email: ${userDetails.email}. This is a test param: 1234`
)
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - json", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
bodyType: "json"
}, {
"testParam" : "1234",
"userRef" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
'{"email":"{{[user].[email]}}","queryCode":{{testParam}},"userRef":"{{userRef}}"}',
bodyType: "json",
},
{
testParam: "1234",
userRef: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
const test = `{"email":"${userDetails.email}","queryCode":1234,"userRef":"${userDetails.firstName}"}`
expect(parsedRequest.opts.body).toEqual(test)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - xml", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "<note> <email>{{[user].[email]}}</email> <code>{{testParam}}</code> " +
"<ref>{{userId}}</ref> <somestring>testing</somestring> </note>",
bodyType: "xml"
}, {
"testParam" : "1234",
"userId" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
"<note> <email>{{[user].[email]}}</email> <code>{{testParam}}</code> " +
"<ref>{{userId}}</ref> <somestring>testing</somestring> </note>",
bodyType: "xml",
},
{
testParam: "1234",
userId: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
const test = `<note> <email>${userDetails.email}</email> <code>1234</code> <ref>${userDetails.firstName}</ref> <somestring>testing</somestring> </note>`
expect(parsedRequest.opts.body).toEqual(test)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - form-data", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
bodyType: "form"
}, {
"testParam" : "1234",
"userRef" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
'{"email":"{{[user].[email]}}","queryCode":{{testParam}},"userRef":"{{userRef}}"}',
bodyType: "form",
},
{
testParam: "1234",
userRef: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
@ -511,28 +556,34 @@ describe("/queries", () => {
const userRef = parsedRequest.opts.body._streams[7]
expect(userRef).toEqual(userDetails.firstName)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - encoded", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
bodyType: "encoded"
}, {
"testParam" : "1234",
"userRef" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
'{"email":"{{[user].[email]}}","queryCode":{{testParam}},"userRef":"{{userRef}}"}',
bodyType: "encoded",
},
{
testParam: "1234",
userRef: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
expect(parsedRequest.opts.body.email).toEqual(userDetails.email)
expect(parsedRequest.opts.body.queryCode).toEqual("1234")
expect(parsedRequest.opts.body.userRef).toEqual(userDetails.firstName)
})
});
})
})

View file

@ -170,7 +170,7 @@ describe("/roles", () => {
.get("/api/roles/accessible")
.set({
...config.defaultHeaders(),
"x-budibase-role": "CUSTOM_ROLE"
"x-budibase-role": "CUSTOM_ROLE",
})
.expect(200)
expect(res.body.length).toBe(3)

View file

@ -37,19 +37,23 @@ describe("/routing", () => {
await runInProd(async () => {
return request
.get(`/api/routing/client`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC,
prodApp: false
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC,
prodApp: false,
})
)
.expect(302)
})
})
it("returns the correct routing for basic user", async () => {
const res = await request
.get(`/api/routing/client`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC,
})
)
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.routes).toBeDefined()
@ -57,18 +61,20 @@ describe("/routing", () => {
subpaths: {
[route]: {
screenId: basic._id,
roleId: basic.routing.roleId
}
}
roleId: basic.routing.roleId,
},
},
})
})
it("returns the correct routing for power user", async () => {
const res = await request
.get(`/api/routing/client`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER,
})
)
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.routes).toBeDefined()
@ -76,9 +82,9 @@ describe("/routing", () => {
subpaths: {
[route]: {
screenId: power._id,
roleId: power.routing.roleId
}
}
roleId: power.routing.roleId,
},
},
})
})
})
@ -87,10 +93,12 @@ describe("/routing", () => {
it("should fetch all routes for builder", async () => {
const res = await request
.get(`/api/routing`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER,
builder: true,
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER,
builder: true,
})
)
.expect(200)
.expect("Content-Type", /json/)
expect(res.body.routes).toBeDefined()
@ -108,4 +116,4 @@ describe("/routing", () => {
})
})
})
})
})

View file

@ -36,7 +36,7 @@ describe("/screens", () => {
})
describe("save", () => {
const saveScreen = async (screen) => {
const saveScreen = async screen => {
const res = await request
.post(`/api/screens`)
.send(screen)
@ -100,4 +100,4 @@ describe("/screens", () => {
})
})
})
})
})

View file

@ -21,4 +21,4 @@ describe("/templates", () => {
expect(Array.isArray(res.body)).toEqual(true)
})
})
})
})

View file

@ -31,18 +31,18 @@ describe("/views", () => {
beforeAll(async () => {
await config.init()
})
beforeEach(async() => {
beforeEach(async () => {
table = await config.createTable(priceTable())
})
const saveView = async (view) => {
const saveView = async view => {
const viewToSave = {
name: "TestView",
field: "Price",
calculation: "stats",
tableId: table._id,
...view
...view,
}
return request
.post(`/api/views`)
@ -53,7 +53,6 @@ describe("/views", () => {
}
describe("create", () => {
it("returns a success message when the view is successfully created", async () => {
const res = await saveView()
expect(res.body.tableId).toBe(table._id)
@ -81,11 +80,13 @@ describe("/views", () => {
const res = await saveView({
calculation: null,
filters: [{
value: "1",
condition: "EQUALS",
key: "price"
}],
filters: [
{
value: "1",
condition: "EQUALS",
key: "price",
},
],
})
expect(res.body.tableId).toBe(table._id)
@ -199,18 +200,26 @@ describe("/views", () => {
})
it("updates a view filter", async () => {
await saveView({ filters: [{
value: "1",
condition: "EQUALS",
key: "price"
}] })
await saveView({
filters: [
{
value: "1",
condition: "EQUALS",
key: "price",
},
],
})
jest.clearAllMocks()
await saveView({ filters: [{
value: "2",
condition: "EQUALS",
key: "price"
}] })
await saveView({
filters: [
{
value: "2",
condition: "EQUALS",
key: "price",
},
],
})
expect(events.view.created).not.toBeCalled()
expect(events.view.updated).toBeCalledTimes(1)
@ -223,11 +232,15 @@ describe("/views", () => {
})
it("deletes a view filter", async () => {
await saveView({ filters: [{
value: "1",
condition: "EQUALS",
key: "price"
}] })
await saveView({
filters: [
{
value: "1",
condition: "EQUALS",
key: "price",
},
],
})
jest.clearAllMocks()
await saveView({ filters: [] })
@ -344,7 +357,6 @@ describe("/views", () => {
})
describe("exportView", () => {
beforeEach(() => {
jest.clearAllMocks()
})
@ -362,14 +374,14 @@ describe("/views", () => {
.expect(200)
}
const assertJsonExport = (res) => {
const assertJsonExport = res => {
const rows = JSON.parse(res.text)
expect(rows.length).toBe(1)
expect(rows[0].name).toBe("test-name")
expect(rows[0].description).toBe("ùúûü")
}
const assertCSVExport = (res) => {
const assertCSVExport = res => {
expect(res.text).toBe(`"name","description"\n"test-name","ùúûü"`)
}

View file

@ -1,34 +1,33 @@
const setup = require("./utilities")
describe("test the bash action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
it("should be able to execute a script", async () => {
it("should be able to execute a script", async () => {
let res = await setup.runStep(
"EXECUTE_BASH",
(inputs = {
code: "echo 'test'",
})
)
expect(res.stdout).toEqual("test\n")
expect(res.success).toEqual(true)
})
let res = await setup.runStep("EXECUTE_BASH",
inputs = {
code: "echo 'test'"
}
)
expect(res.stdout).toEqual("test\n")
expect(res.success).toEqual(true)
})
it("should handle a null value", async () => {
let res = await setup.runStep("EXECUTE_BASH",
inputs = {
code: null
}
)
expect(res.stdout).toEqual("Budibase bash automation failed: Invalid inputs")
})
it("should handle a null value", async () => {
let res = await setup.runStep(
"EXECUTE_BASH",
(inputs = {
code: null,
})
)
expect(res.stdout).toEqual(
"Budibase bash automation failed: Invalid inputs"
)
})
})

View file

@ -1,7 +1,7 @@
const setup = require("./utilities")
// need real Date for this test
const tk = require('timekeeper');
const tk = require("timekeeper")
tk.reset()
describe("test the delay logic", () => {

View file

@ -4,24 +4,23 @@ const fetch = require("node-fetch")
jest.mock("node-fetch")
describe("test the outgoing webhook action", () => {
let inputs
let config = setup.getConfig()
let inputs
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
inputs = {
username: "joe_bloggs",
url: "http://www.test.com",
}
})
beforeAll(async () => {
await config.init()
inputs = {
username: "joe_bloggs",
url: "http://www.test.com",
}
})
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(setup.actions.discord.stepId, inputs)
expect(res.response.url).toEqual("http://www.test.com")
expect(res.response.method).toEqual("post")
expect(res.success).toEqual(true)
})
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(setup.actions.discord.stepId, inputs)
expect(res.response.url).toEqual("http://www.test.com")
expect(res.response.method).toEqual("post")
expect(res.success).toEqual(true)
})
})

View file

@ -1,48 +1,47 @@
const setup = require("./utilities")
describe("test the execute query action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
beforeAll(async () => {
await config.init()
await config.createDatasource()
query = await config.createQuery()
await config.createDatasource()
query = await config.createQuery()
})
})
afterAll(setup.afterAll)
afterAll(setup.afterAll)
it("should be able to execute a query", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_QUERY.stepId,
inputs = {
query: { queryId: query._id }
}
)
expect(res.response).toEqual([{ a: 'string', b: 1 }])
expect(res.success).toEqual(true)
})
it("should handle a null query value", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_QUERY.stepId,
inputs = {
query: null
}
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should handle an error executing a query", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_QUERY.stepId,
inputs = {
query: { queryId: "wrong_id" }
}
)
expect(res.response).toEqual('Error: missing')
expect(res.success).toEqual(false)
})
it("should be able to execute a query", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_QUERY.stepId,
(inputs = {
query: { queryId: query._id },
})
)
expect(res.response).toEqual([{ a: "string", b: 1 }])
expect(res.success).toEqual(true)
})
it("should handle a null query value", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_QUERY.stepId,
(inputs = {
query: null,
})
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should handle an error executing a query", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_QUERY.stepId,
(inputs = {
query: { queryId: "wrong_id" },
})
)
expect(res.response).toEqual("Error: missing")
expect(res.success).toEqual(false)
})
})

View file

@ -1,48 +1,43 @@
const setup = require("./utilities")
describe("test the execute script action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
it("should be able to execute a script", async () => {
it("should be able to execute a script", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_SCRIPT.stepId,
(inputs = {
code: "return 1 + 1",
})
)
expect(res.value).toEqual(2)
expect(res.success).toEqual(true)
})
let res = await setup.runStep(setup.actions.EXECUTE_SCRIPT.stepId,
inputs = {
code: "return 1 + 1"
}
)
expect(res.value).toEqual(2)
expect(res.success).toEqual(true)
})
it("should handle a null value", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_SCRIPT.stepId,
inputs = {
code: null
}
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should be able to handle an error gracefully", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_SCRIPT.stepId,
inputs = {
code: "return something.map(x => x.name)"
}
)
expect(res.response).toEqual("ReferenceError: something is not defined")
expect(res.success).toEqual(false)
})
it("should handle a null value", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_SCRIPT.stepId,
(inputs = {
code: null,
})
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should be able to handle an error gracefully", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_SCRIPT.stepId,
(inputs = {
code: "return something.map(x => x.name)",
})
)
expect(res.response).toEqual("ReferenceError: something is not defined")
expect(res.success).toEqual(false)
})
})

View file

@ -21,7 +21,10 @@ describe("test the outgoing webhook action", () => {
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(setup.actions.OUTGOING_WEBHOOK.stepId, inputs)
const res = await setup.runStep(
setup.actions.OUTGOING_WEBHOOK.stepId,
inputs
)
expect(res.success).toEqual(true)
expect(res.response.url).toEqual("http://www.test.com")
expect(res.response.method).toEqual("POST")
@ -31,9 +34,8 @@ describe("test the outgoing webhook action", () => {
it("should return an error if something goes wrong in fetch", async () => {
const res = await setup.runStep(setup.actions.OUTGOING_WEBHOOK.stepId, {
requestMethod: "GET",
url: "www.invalid.com"
url: "www.invalid.com",
})
expect(res.success).toEqual(false)
})
})

View file

@ -1,22 +1,19 @@
const setup = require("./utilities")
describe("test the server log action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
inputs = {
text: "log message",
}
})
afterAll(setup.afterAll)
beforeAll(async () => {
await config.init()
inputs = {
text: "log message",
}
})
afterAll(setup.afterAll)
it("should be able to log the text", async () => {
let res = await setup.runStep(setup.actions.SERVER_LOG.stepId,
inputs
)
expect(res.message).toEqual(`App ${config.getAppId()} - ${inputs.text}`)
expect(res.success).toEqual(true)
})
it("should be able to log the text", async () => {
let res = await setup.runStep(setup.actions.SERVER_LOG.stepId, inputs)
expect(res.message).toEqual(`App ${config.getAppId()} - ${inputs.text}`)
expect(res.success).toEqual(true)
})
})

View file

@ -1,5 +1,9 @@
const TestConfig = require("../../tests/utilities/TestConfiguration")
const { basicRow, basicLinkedRow, basicTable } = require("../../tests/utilities/structures")
const {
basicRow,
basicLinkedRow,
basicTable,
} = require("../../tests/utilities/structures")
const LinkController = require("../linkedRows/LinkController").default
const { context } = require("@budibase/backend-core")
const { RelationshipType } = require("../../constants")
@ -16,7 +20,10 @@ describe("test the link controller", () => {
beforeEach(async () => {
const { _id } = await config.createTable()
table2 = await config.createLinkedTable(RelationshipType.MANY_TO_MANY, ["link", "link2"])
table2 = await config.createLinkedTable(RelationshipType.MANY_TO_MANY, [
"link",
"link2",
])
// update table after creating link
table1 = await config.getTable(_id)
})
@ -41,15 +48,23 @@ describe("test the link controller", () => {
async function createLinkedRow(linkField = "link", t1 = table1, t2 = table2) {
const row = await config.createRow(basicRow(t2._id))
const { _id } = await config.createRow(basicLinkedRow(t1._id, row._id, linkField))
const { _id } = await config.createRow(
basicLinkedRow(t1._id, row._id, linkField)
)
return config.getRow(t1._id, _id)
}
it("should be able to confirm if two table schemas are equal", async () => {
const controller = await createLinkController(table1)
let equal = controller.areLinkSchemasEqual(table2.schema.link, table2.schema.link)
let equal = controller.areLinkSchemasEqual(
table2.schema.link,
table2.schema.link
)
expect(equal).toEqual(true)
equal = controller.areLinkSchemasEqual(table1.schema.link, table2.schema.link)
equal = controller.areLinkSchemasEqual(
table1.schema.link,
table2.schema.link
)
expect(equal).toEqual(false)
})
@ -57,17 +72,42 @@ describe("test the link controller", () => {
const controller = await createLinkController(table1)
// empty case
let output = controller.handleRelationshipType({}, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
output = controller.handleRelationshipType({ relationshipType: RelationshipType.MANY_TO_MANY }, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
output = controller.handleRelationshipType({ relationshipType: RelationshipType.MANY_TO_ONE }, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.ONE_TO_MANY)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_ONE)
output = controller.handleRelationshipType({ relationshipType: RelationshipType.ONE_TO_MANY }, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_ONE)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.ONE_TO_MANY)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
output = controller.handleRelationshipType(
{ relationshipType: RelationshipType.MANY_TO_MANY },
{}
)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
output = controller.handleRelationshipType(
{ relationshipType: RelationshipType.MANY_TO_ONE },
{}
)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.ONE_TO_MANY
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.MANY_TO_ONE
)
output = controller.handleRelationshipType(
{ relationshipType: RelationshipType.ONE_TO_MANY },
{}
)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.MANY_TO_ONE
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.ONE_TO_MANY
)
})
it("should be able to delete a row", async () => {
@ -100,7 +140,7 @@ describe("test the link controller", () => {
it("should throw an error when validating a table which is invalid", async () => {
const controller = await createLinkController(table1)
const copyTable = {
...table1
...table1,
}
copyTable.schema.otherTableLink = {
type: "link",
@ -114,7 +154,9 @@ describe("test the link controller", () => {
error = err
}
expect(error).toBeDefined()
expect(error.message).toEqual("Cannot re-use the linked column name for a linked table.")
expect(error.message).toEqual(
"Cannot re-use the linked column name for a linked table."
)
})
it("should be able to remove a link when saving/updating the row", async () => {
@ -183,7 +225,10 @@ describe("test the link controller", () => {
it("shouldn't allow one to many having many relationships against it", async () => {
const firstTable = await config.createTable()
const { _id } = await config.createLinkedTable(RelationshipType.MANY_TO_ONE, ["link"])
const { _id } = await config.createLinkedTable(
RelationshipType.MANY_TO_ONE,
["link"]
)
const linkTable = await config.getTable(_id)
// an initial row to link around
const row = await createLinkedRow("link", linkTable, firstTable)

View file

@ -45,7 +45,9 @@ describe("test link functionality", () => {
})
it("should get the field from the link", () => {
expect(linkUtils.getRelatedTableForField(link, "otherLink")).toBe("tableID")
expect(linkUtils.getRelatedTableForField(link, "otherLink")).toBe(
"tableID"
)
})
})
@ -62,4 +64,4 @@ describe("test link functionality", () => {
})
})
})
})
})

View file

@ -3,7 +3,7 @@ const {
paramSubResource,
bodyResource,
bodySubResource,
ResourceIdGetter
ResourceIdGetter,
} = require("../resourceId")
class TestConfiguration {
@ -41,7 +41,7 @@ describe("resourceId middleware", () => {
it("generates a resourceId middleware for context query parameters", () => {
const config = new TestConfiguration(paramResource("main"))
config.setParams({
main: "test"
main: "test",
})
config.executeMiddleware()
@ -53,7 +53,7 @@ describe("resourceId middleware", () => {
const config = new TestConfiguration(paramSubResource("main", "sub"))
config.setParams({
main: "main",
sub: "test"
sub: "test",
})
config.executeMiddleware()
@ -65,7 +65,7 @@ describe("resourceId middleware", () => {
it("generates a resourceId middleware for context request body", () => {
const config = new TestConfiguration(bodyResource("main"))
config.setBody({
main: "test"
main: "test",
})
config.executeMiddleware()
@ -77,7 +77,7 @@ describe("resourceId middleware", () => {
const config = new TestConfiguration(bodySubResource("main", "sub"))
config.setBody({
main: "main",
sub: "test"
sub: "test",
})
config.executeMiddleware()
@ -94,7 +94,7 @@ describe("resourceId middleware", () => {
let config = new TestConfiguration(middleware)
config.setBody({
custom: "test",
customSub: "subtest"
customSub: "subtest",
})
config.executeMiddleware()
@ -102,4 +102,4 @@ describe("resourceId middleware", () => {
expect(config.ctx.resourceId).toEqual("test")
expect(config.ctx.subResourceId).toEqual("subtest")
})
})
})

View file

@ -10,7 +10,7 @@ class TestConfiguration {
this.ctx = {
next: this.next,
throw: this.throw
throw: this.throw,
}
}
@ -35,7 +35,7 @@ describe("Self host middleware", () => {
})
it("calls next() when SELF_HOSTED env var is set", async () => {
env.SELF_HOSTED = 1
env.SELF_HOSTED = 1
await config.executeMiddleware()
expect(config.next).toHaveBeenCalled()

View file

@ -10,7 +10,7 @@ describe("run", () => {
await config.init()
})
afterAll(config.end)
afterAll(config.end)
it("runs successfully", async () => {
const app = await config.createApp("testApp")

View file

@ -4,8 +4,8 @@ jest.mock("@budibase/backend-core", () => {
...core,
db: {
...core.db,
createNewUserEmailView: jest.fn()
}
createNewUserEmailView: jest.fn(),
},
}
})
const { context, db: dbCore } = require("@budibase/backend-core")
@ -16,19 +16,19 @@ const TestConfig = require("../../../tests/utilities/TestConfiguration")
const migration = require("../userEmailViewCasing")
describe("run", () => {
let config = new TestConfig(false)
let config = new TestConfig(false)
beforeAll(async () => {
await config.init()
})
afterAll(config.end)
it("runs successfully", async () => {
await config.doInTenant(async () => {
const globalDb = context.getGlobalDB()
await migration.run(globalDb)
expect(dbCore.createNewUserEmailView).toHaveBeenCalledTimes(1)
})
beforeAll(async () => {
await config.init()
})
afterAll(config.end)
it("runs successfully", async () => {
await config.doInTenant(async () => {
const globalDb = context.getGlobalDB()
await migration.run(globalDb)
expect(dbCore.createNewUserEmailView).toHaveBeenCalledTimes(1)
})
})
})

View file

@ -86,11 +86,11 @@ describe("Test that the object processing works correctly", () => {
})
it("check objects get converted to string JSON automatically", async () => {
const row = {a: 1}
const row = { a: 1 }
const output = await processString("{{ trigger.row }}", {
trigger: {
row,
}
},
})
expect(JSON.parse(output)).toEqual(row)
})
@ -108,9 +108,9 @@ describe("Test that the object processing works correctly", () => {
describe("check returning objects", () => {
it("should handle an array of objects", async () => {
const json = [{a: 1},{a: 2}]
const json = [{ a: 1 }, { a: 2 }]
const output = await processString("{{ testing }}", {
testing: json
testing: json,
})
expect(output).toEqual(JSON.stringify(json))
})
@ -164,9 +164,12 @@ describe("check manifest", () => {
describe("check full stops that are safe", () => {
it("should allow using an escaped full stop", async () => {
const data = {
"c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI": { "persons.firstname": "1" }
"c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI": {
"persons.firstname": "1",
},
}
const template = "{{ [c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI].[persons.firstname] }}"
const template =
"{{ [c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI].[persons.firstname] }}"
const output = await processString(template, data)
expect(output).toEqual("1")
})
@ -195,7 +198,9 @@ describe("check that disabling escaping function works", () => {
})
it("should work for two statements", () => {
expect(disableEscaping("{{ name }} welcome to {{ platform }}")).toEqual("{{{ name }}} welcome to {{{ platform }}}")
expect(disableEscaping("{{ name }} welcome to {{ platform }}")).toEqual(
"{{{ name }}} welcome to {{{ platform }}}"
)
})
it("shouldn't convert triple braces", () => {
@ -203,11 +208,15 @@ describe("check that disabling escaping function works", () => {
})
it("should work with a combination", () => {
expect(disableEscaping("{{ name }} welcome to {{{ platform }}}")).toEqual("{{{ name }}} welcome to {{{ platform }}}")
expect(disableEscaping("{{ name }} welcome to {{{ platform }}}")).toEqual(
"{{{ name }}} welcome to {{{ platform }}}"
)
})
it("should work with multiple escaped", () => {
expect(disableEscaping("{{ name }} welcome to {{ name }}")).toEqual("{{{ name }}} welcome to {{{ name }}}")
expect(disableEscaping("{{ name }} welcome to {{ name }}")).toEqual(
"{{{ name }}} welcome to {{{ name }}}"
)
})
})
@ -217,13 +226,20 @@ describe("check find hbs blocks function", () => {
})
it("should find two", () => {
expect(findHBSBlocks("{{ hello }} there {{{ name }}}")).toEqual(["{{ hello }}", "{{{ name }}}"])
expect(findHBSBlocks("{{ hello }} there {{{ name }}}")).toEqual([
"{{ hello }}",
"{{{ name }}}",
])
})
})
describe("should leave HBS blocks if not found using option", () => {
it("should replace one, leave one", async () => {
const output = await processString("{{ a }}, {{ b }}", { b: 1 }, { onlyFound: true })
const output = await processString(
"{{ a }}, {{ b }}",
{ b: 1 },
{ onlyFound: true }
)
expect(output).toBe("{{ a }}, 1")
})
})

View file

@ -68,11 +68,11 @@ describe("attempt some complex problems", () => {
describe("check behaviour with newlines", () => {
const context = {
binding: `Hello
there`
there`,
}
it("should escape new line to \\n with double brace", async () => {
const hbs = JSON.stringify({
body: "{{ binding }}"
body: "{{ binding }}",
})
const output = await processString(hbs, context, { escapeNewlines: true })
expect(JSON.parse(output).body).toBe(context.binding)
@ -80,7 +80,7 @@ describe("check behaviour with newlines", () => {
it("should work the same with triple brace", async () => {
const hbs = JSON.stringify({
body: "{{{ binding }}}"
body: "{{{ binding }}}",
})
const output = await processString(hbs, context, { escapeNewlines: true })
expect(JSON.parse(output).body).toBe(context.binding)
@ -88,9 +88,12 @@ describe("check behaviour with newlines", () => {
it("should still work with helpers disabled", async () => {
const hbs = JSON.stringify({
body: "{{ binding }}"
body: "{{ binding }}",
})
const output = await processString(hbs, context, {
escapeNewlines: true,
noHelpers: true,
})
const output = await processString(hbs, context, { escapeNewlines: true, noHelpers: true })
expect(JSON.parse(output).body).toBe(context.binding)
})
})

View file

@ -1,6 +1,4 @@
const {
convertToJS
} = require("../src/index.cjs")
const { convertToJS } = require("../src/index.cjs")
function checkLines(response, lines) {
const toCheck = response.split("\n")
@ -18,25 +16,19 @@ describe("Test that the string processing works correctly", () => {
it("basic example with square brackets", () => {
const response = convertToJS("{{ [query] }}")
checkLines(response, [
"const var1 = $(\"[query]\");",
"return `${var1}`;",
])
checkLines(response, ['const var1 = $("[query]");', "return `${var1}`;"])
})
it("handle properties", () => {
const response = convertToJS("{{ [query].id }}")
checkLines(response, [
"const var1 = $(\"[query].id\");",
"return `${var1}`;",
])
checkLines(response, ['const var1 = $("[query].id");', "return `${var1}`;"])
})
it("should convert some basic HBS strings", () => {
const response = convertToJS("Hello {{ name }}, welcome to {{ company }}!")
checkLines(response, [
"const var1 = $(\"name\");",
"const var2 = $(\"company\");",
'const var1 = $("name");',
'const var2 = $("company");',
"return `Hello ${var1}, welcome to ${var2}`;",
])
})
@ -44,7 +36,7 @@ describe("Test that the string processing works correctly", () => {
it("should handle many square brackets in helpers", () => {
const response = convertToJS("Hello {{ avg [user].[_id] [user].[_rev] }}")
checkLines(response, [
"const var1 = helpers.avg($(\"[user].[_id]\"), $(\"[user].[_rev]\"));",
'const var1 = helpers.avg($("[user].[_id]"), $("[user].[_rev]"));',
"return `Hello ${var1}`;",
])
})
@ -61,7 +53,7 @@ describe("Test that the string processing works correctly", () => {
const response = convertToJS("{{equalsLength '[1,2,3]' 3}}")
checkLines(response, [
"const var1 = helpers.equalsLength('[1,2,3]', 3);",
"return `${var1}`;"
"return `${var1}`;",
])
})
@ -84,23 +76,27 @@ describe("Test that the string processing works correctly", () => {
it("should handle a helper block", () => {
const response = convertToJS("This is the average: {{ avg array }}")
checkLines(response, [
"const var1 = helpers.avg($(\"array\"));",
'const var1 = helpers.avg($("array"));',
"return `This is the average: ${var1}`;",
])
})
it("should handle multi-variable helper", () => {
const response = convertToJS("This is the average: {{ join ( avg val1 val2 val3 ) }}")
const response = convertToJS(
"This is the average: {{ join ( avg val1 val2 val3 ) }}"
)
checkLines(response, [
"const var1 = helpers.join(helpers.avg($(\"val1\"), $(\"val2\"), $(\"val3\")));",
'const var1 = helpers.join(helpers.avg($("val1"), $("val2"), $("val3")));',
"return `This is the average: ${var1}`;",
])
})
it("should handle a complex statement", () => {
const response = convertToJS("This is the average: {{ join ( avg val1 val2 val3 ) val4 }}")
const response = convertToJS(
"This is the average: {{ join ( avg val1 val2 val3 ) val4 }}"
)
checkLines(response, [
"const var1 = helpers.join(helpers.avg($(\"val1\"), $(\"val2\"), $(\"val3\")), $(\"val4\"));",
'const var1 = helpers.join(helpers.avg($("val1"), $("val2"), $("val3")), $("val4"));',
"return `This is the average: ${var1}`;",
])
})
@ -108,7 +104,7 @@ describe("Test that the string processing works correctly", () => {
it("should handle square brackets", () => {
const response = convertToJS("This is: {{ [val thing] }}")
checkLines(response, [
"const var1 = $(\"[val thing]\");",
'const var1 = $("[val thing]");',
"return `This is: ${var1}`;",
])
})
@ -116,17 +112,19 @@ describe("Test that the string processing works correctly", () => {
it("should handle square brackets with properties", () => {
const response = convertToJS("{{ [user].[_id] }}")
checkLines(response, [
"const var1 = $(\"[user].[_id]\");",
'const var1 = $("[user].[_id]");',
"return `${var1}`;",
])
})
it("should handle multiple complex statements", () => {
const response = convertToJS("average: {{ avg ( abs val1 ) val2 }} add: {{ add 1 2 }}")
const response = convertToJS(
"average: {{ avg ( abs val1 ) val2 }} add: {{ add 1 2 }}"
)
checkLines(response, [
"const var1 = helpers.avg(helpers.abs($(\"val1\")), $(\"val2\"));",
'const var1 = helpers.avg(helpers.abs($("val1")), $("val2"));',
"const var2 = helpers.add(1, 2);",
"return `average: ${var1} add: ${var2}`;",
])
})
})
})

View file

@ -266,10 +266,7 @@ describe("test the string helpers", () => {
})
it("should allow use of the ellipsis helper", async () => {
const output = await processString(
"{{ ellipsis \"adfasdfasdfasf\" 7 }}",
{},
)
const output = await processString('{{ ellipsis "adfasdfasdfasf" 7 }}', {})
expect(output).toBe("adfasdf…")
})
})

View file

@ -140,4 +140,4 @@ describe("check JS helpers", () => {
const output = processJS(`return helpers.toInt(4.3)`)
expect(output).toBe(4)
})
})
})