Merge remote-tracking branch 'origin/develop' into fix/add-onboarding-tour-tenant-flag
This commit is contained in:
commit
436564709e
138 changed files with 606 additions and 6637 deletions
2
.github/workflows/release-develop.yml
vendored
2
.github/workflows/release-develop.yml
vendored
|
@ -194,5 +194,5 @@ jobs:
|
|||
PAYLOAD_VERSION: ${{ env.RELEASE_VERSION }}
|
||||
with:
|
||||
repository: budibase/budibase-deploys
|
||||
event: deploy-develop-to-qa
|
||||
event: deploy-budibase-develop-to-qa
|
||||
github_pat: ${{ secrets.GH_ACCESS_TOKEN }}
|
30
.github/workflows/smoke_test.yaml
vendored
30
.github/workflows/smoke_test.yaml
vendored
|
@ -18,30 +18,18 @@ jobs:
|
|||
- run: yarn
|
||||
- run: yarn bootstrap
|
||||
- run: yarn build
|
||||
- name: Pull cypress.env.yaml from budibase-infra
|
||||
- name: Pull from budibase-infra
|
||||
run: |
|
||||
curl -H "Authorization: token ${{ secrets.GH_PERSONAL_TOKEN }}" \
|
||||
-H 'Accept: application/vnd.github.v3.raw' \
|
||||
-o packages/builder/cypress.env.json \
|
||||
-L https://api.github.com/repos/budibase/budibase-infra/contents/test/cypress.env.json
|
||||
wc -l packages/builder/cypress.env.json
|
||||
|
||||
- name: Cypress run
|
||||
id: cypress
|
||||
continue-on-error: true
|
||||
uses: cypress-io/github-action@v2
|
||||
with:
|
||||
record: true
|
||||
install: false
|
||||
tag: nightly
|
||||
command: yarn test:e2e:ci:record
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
-o
|
||||
-L
|
||||
wc -l
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Test Reports
|
||||
path: packages/builder/cypress/reports/testReport.html
|
||||
path:
|
||||
|
||||
# TODO: enable once running in QA test env
|
||||
# - name: Configure AWS Credentials
|
||||
|
@ -54,11 +42,3 @@ jobs:
|
|||
# - name: Upload test results HTML
|
||||
# uses: aws-actions/configure-aws-credentials@v1
|
||||
# run: aws s3 cp packages/builder/cypress/reports/testReport.html s3://{{ secrets.BUDI_QA_REPORTS_BUCKET_NAME }}/$GITHUB_RUN_ID/index.html
|
||||
|
||||
- name: Cypress Discord Notify
|
||||
run: yarn test:e2e:ci:notify
|
||||
env:
|
||||
CYPRESS_WEBHOOK_URL: ${{ secrets.BUDI_QA_WEBHOOK }}
|
||||
CYPRESS_OUTCOME: ${{ steps.cypress.outcome }}
|
||||
CYPRESS_DASHBOARD_URL: ${{ steps.cypress.outputs.dashboardUrl }}
|
||||
GITHUB_RUN_URL: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.2.12-alpha.55",
|
||||
"version": "2.2.12-alpha.64",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
|
@ -51,10 +51,6 @@
|
|||
"lint:fix:eslint": "eslint --fix packages qa-core",
|
||||
"lint:fix:prettier": "prettier --write \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\" && prettier --write \"qa-core/**/*.{js,ts,svelte}\"",
|
||||
"lint:fix": "yarn run lint:fix:prettier && yarn run lint:fix:eslint",
|
||||
"test:e2e": "lerna run cy:test --stream",
|
||||
"test:e2e:ci": "lerna run cy:ci --stream",
|
||||
"test:e2e:ci:record": "lerna run cy:ci:record --stream",
|
||||
"test:e2e:ci:notify": "lerna run cy:ci:notify",
|
||||
"build:specs": "lerna run specs",
|
||||
"build:docker": "lerna run build:docker && npm run build:docker:proxy && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -",
|
||||
"build:docker:pre": "lerna run build && lerna run predocker",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/backend-core",
|
||||
"version": "2.2.12-alpha.55",
|
||||
"version": "2.2.12-alpha.64",
|
||||
"description": "Budibase backend core libraries used in server and worker",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
|
@ -23,7 +23,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@budibase/nano": "10.1.1",
|
||||
"@budibase/types": "2.2.12-alpha.55",
|
||||
"@budibase/types": "2.2.12-alpha.64",
|
||||
"@shopify/jest-koa-mocks": "5.0.1",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
"aws-cloudfront-sign": "2.2.0",
|
||||
|
|
|
@ -15,26 +15,10 @@ import { getCouchInfo } from "./connections"
|
|||
import { directCouchCall } from "./utils"
|
||||
import { getPouchDB } from "./pouchDB"
|
||||
import { WriteStream, ReadStream } from "fs"
|
||||
import { newid } from "../../newid"
|
||||
|
||||
export class DatabaseImpl implements Database {
|
||||
public readonly name: string
|
||||
private static nano: Nano.ServerScope
|
||||
private readonly pouchOpts: DatabaseOpts
|
||||
|
||||
constructor(dbName?: string, opts?: DatabaseOpts) {
|
||||
if (dbName == null) {
|
||||
throw new Error("Database name cannot be undefined.")
|
||||
}
|
||||
this.name = dbName
|
||||
this.pouchOpts = opts || {}
|
||||
if (!DatabaseImpl.nano) {
|
||||
DatabaseImpl.init()
|
||||
}
|
||||
}
|
||||
|
||||
static init() {
|
||||
const couchInfo = getCouchInfo()
|
||||
DatabaseImpl.nano = Nano({
|
||||
function buildNano(couchInfo: { url: string; cookie: string }) {
|
||||
return Nano({
|
||||
url: couchInfo.url,
|
||||
requestDefaults: {
|
||||
headers: {
|
||||
|
@ -43,6 +27,43 @@ export class DatabaseImpl implements Database {
|
|||
},
|
||||
parseUrl: false,
|
||||
})
|
||||
}
|
||||
|
||||
export function DatabaseWithConnection(
|
||||
dbName: string,
|
||||
connection: string,
|
||||
opts?: DatabaseOpts
|
||||
) {
|
||||
if (!connection) {
|
||||
throw new Error("Must provide connection details")
|
||||
}
|
||||
return new DatabaseImpl(dbName, opts, connection)
|
||||
}
|
||||
|
||||
export class DatabaseImpl implements Database {
|
||||
public readonly name: string
|
||||
private static nano: Nano.ServerScope
|
||||
private readonly instanceNano?: Nano.ServerScope
|
||||
private readonly pouchOpts: DatabaseOpts
|
||||
|
||||
constructor(dbName?: string, opts?: DatabaseOpts, connection?: string) {
|
||||
if (dbName == null) {
|
||||
throw new Error("Database name cannot be undefined.")
|
||||
}
|
||||
this.name = dbName
|
||||
this.pouchOpts = opts || {}
|
||||
if (connection) {
|
||||
const couchInfo = getCouchInfo(connection)
|
||||
this.instanceNano = buildNano(couchInfo)
|
||||
}
|
||||
if (!DatabaseImpl.nano) {
|
||||
DatabaseImpl.init()
|
||||
}
|
||||
}
|
||||
|
||||
static init() {
|
||||
const couchInfo = getCouchInfo()
|
||||
DatabaseImpl.nano = buildNano(couchInfo)
|
||||
}
|
||||
|
||||
async exists() {
|
||||
|
@ -50,6 +71,10 @@ export class DatabaseImpl implements Database {
|
|||
return response.status === 200
|
||||
}
|
||||
|
||||
private nano() {
|
||||
return this.instanceNano || DatabaseImpl.nano
|
||||
}
|
||||
|
||||
async checkSetup() {
|
||||
let shouldCreate = !this.pouchOpts?.skip_setup
|
||||
// check exists in a lightweight fashion
|
||||
|
@ -58,9 +83,9 @@ export class DatabaseImpl implements Database {
|
|||
throw new Error("DB does not exist")
|
||||
}
|
||||
if (!exists) {
|
||||
await DatabaseImpl.nano.db.create(this.name)
|
||||
await this.nano().db.create(this.name)
|
||||
}
|
||||
return DatabaseImpl.nano.db.use(this.name)
|
||||
return this.nano().db.use(this.name)
|
||||
}
|
||||
|
||||
private async updateOutput(fnc: any) {
|
||||
|
@ -101,6 +126,13 @@ export class DatabaseImpl implements Database {
|
|||
return this.updateOutput(() => db.destroy(_id, _rev))
|
||||
}
|
||||
|
||||
async post(document: AnyDocument, opts?: DatabasePutOpts) {
|
||||
if (!document._id) {
|
||||
document._id = newid()
|
||||
}
|
||||
return this.put(document, opts)
|
||||
}
|
||||
|
||||
async put(document: AnyDocument, opts?: DatabasePutOpts) {
|
||||
if (!document._id) {
|
||||
throw new Error("Cannot store document without _id field.")
|
||||
|
@ -146,7 +178,7 @@ export class DatabaseImpl implements Database {
|
|||
|
||||
async destroy() {
|
||||
try {
|
||||
await DatabaseImpl.nano.db.destroy(this.name)
|
||||
await this.nano().db.destroy(this.name)
|
||||
} catch (err: any) {
|
||||
// didn't exist, don't worry
|
||||
if (err.statusCode === 404) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import env from "../../environment"
|
||||
|
||||
export const getCouchInfo = () => {
|
||||
const urlInfo = getUrlInfo()
|
||||
export const getCouchInfo = (connection?: string) => {
|
||||
const urlInfo = getUrlInfo(connection)
|
||||
let username
|
||||
let password
|
||||
if (env.COUCH_DB_USERNAME) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/bbui",
|
||||
"description": "A UI solution used in the different Budibase projects.",
|
||||
"version": "2.2.12-alpha.55",
|
||||
"version": "2.2.12-alpha.64",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"module": "dist/bbui.es.js",
|
||||
|
@ -38,7 +38,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
||||
"@budibase/string-templates": "2.2.12-alpha.55",
|
||||
"@budibase/string-templates": "2.2.12-alpha.64",
|
||||
"@spectrum-css/accordion": "3.0.24",
|
||||
"@spectrum-css/actionbutton": "1.0.1",
|
||||
"@spectrum-css/actiongroup": "1.0.1",
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
export let longPressable = false
|
||||
export let disabled = false
|
||||
export let icon = ""
|
||||
export let dataCy = null
|
||||
export let size = "M"
|
||||
export let active = false
|
||||
export let fullWidth = false
|
||||
|
@ -37,7 +36,6 @@
|
|||
</script>
|
||||
|
||||
<button
|
||||
data-cy={dataCy}
|
||||
use:longPress
|
||||
class:spectrum-ActionButton--quiet={quiet}
|
||||
class:spectrum-ActionButton--emphasized={emphasized}
|
||||
|
@ -88,7 +86,7 @@
|
|||
}
|
||||
.is-selected:not(.spectrum-ActionButton--emphasized):not(.spectrum-ActionButton--quiet) {
|
||||
background: var(--spectrum-global-color-gray-300);
|
||||
border-color: var(--spectrum-global-color-gray-700);
|
||||
border-color: var(--spectrum-global-color-gray-500);
|
||||
}
|
||||
.noPadding {
|
||||
padding: 0;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
export let disabled = false
|
||||
export let align = "left"
|
||||
export let portalTarget
|
||||
export let dataCy
|
||||
|
||||
let anchor
|
||||
let dropdown
|
||||
|
@ -37,7 +36,7 @@
|
|||
<div use:getAnchor on:click={openMenu}>
|
||||
<slot name="control" />
|
||||
</div>
|
||||
<Popover bind:this={dropdown} {anchor} {align} {portalTarget} {dataCy}>
|
||||
<Popover bind:this={dropdown} {anchor} {align} {portalTarget}>
|
||||
<Menu>
|
||||
<slot />
|
||||
</Menu>
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
export default function positionDropdown(
|
||||
element,
|
||||
{ anchor, align, maxWidth, useAnchorWidth }
|
||||
) {
|
||||
const update = () => {
|
||||
export default function positionDropdown(element, opts) {
|
||||
let resizeObserver
|
||||
let latestOpts = opts
|
||||
|
||||
// We need a static reference to this function so that we can properly
|
||||
// clean up the scroll listener.
|
||||
const scrollUpdate = () => {
|
||||
updatePosition(latestOpts)
|
||||
}
|
||||
|
||||
// Updates the position of the dropdown
|
||||
const updatePosition = opts => {
|
||||
const { anchor, align, maxWidth, useAnchorWidth, offset = 5 } = opts
|
||||
if (!anchor) {
|
||||
return
|
||||
}
|
||||
|
||||
// Compute bounds
|
||||
const anchorBounds = anchor.getBoundingClientRect()
|
||||
const elementBounds = element.getBoundingClientRect()
|
||||
let styles = {
|
||||
|
@ -20,9 +30,9 @@ export default function positionDropdown(
|
|||
if (align === "right-outside") {
|
||||
styles.top = anchorBounds.top
|
||||
} else if (window.innerHeight - anchorBounds.bottom < 100) {
|
||||
styles.top = anchorBounds.top - elementBounds.height - 5
|
||||
styles.top = anchorBounds.top - elementBounds.height - offset
|
||||
} else {
|
||||
styles.top = anchorBounds.bottom + 5
|
||||
styles.top = anchorBounds.bottom + offset
|
||||
styles.maxHeight = window.innerHeight - anchorBounds.bottom - 20
|
||||
}
|
||||
|
||||
|
@ -36,7 +46,7 @@ export default function positionDropdown(
|
|||
if (align === "right") {
|
||||
styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
|
||||
} else if (align === "right-outside") {
|
||||
styles.left = anchorBounds.right + 10
|
||||
styles.left = anchorBounds.right + offset
|
||||
} else {
|
||||
styles.left = anchorBounds.left
|
||||
}
|
||||
|
@ -51,26 +61,47 @@ export default function positionDropdown(
|
|||
})
|
||||
}
|
||||
|
||||
// The actual svelte action callback which creates observers on the relevant
|
||||
// DOM elements
|
||||
const update = newOpts => {
|
||||
latestOpts = newOpts
|
||||
|
||||
// Cleanup old state
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
|
||||
// Do nothing if no anchor
|
||||
const { anchor } = newOpts
|
||||
if (!anchor) {
|
||||
return
|
||||
}
|
||||
|
||||
// Observe both anchor and element and resize the popover as appropriate
|
||||
resizeObserver = new ResizeObserver(() => updatePosition(newOpts))
|
||||
resizeObserver.observe(anchor)
|
||||
resizeObserver.observe(element)
|
||||
resizeObserver.observe(document.body)
|
||||
}
|
||||
|
||||
// Apply initial styles which don't need to change
|
||||
element.style.position = "absolute"
|
||||
element.style.zIndex = "9999"
|
||||
|
||||
// Observe both anchor and element and resize the popover as appropriate
|
||||
const resizeObserver = new ResizeObserver(entries => {
|
||||
entries.forEach(update)
|
||||
})
|
||||
if (anchor) {
|
||||
resizeObserver.observe(anchor)
|
||||
}
|
||||
resizeObserver.observe(element)
|
||||
resizeObserver.observe(document.body)
|
||||
// Set up a scroll listener
|
||||
document.addEventListener("scroll", scrollUpdate, true)
|
||||
|
||||
document.addEventListener("scroll", update, true)
|
||||
// Perform initial update
|
||||
update(opts)
|
||||
|
||||
return {
|
||||
update,
|
||||
destroy() {
|
||||
// Cleanup
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
document.removeEventListener("scroll", update, true)
|
||||
}
|
||||
document.removeEventListener("scroll", scrollUpdate, true)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
export let icon = undefined
|
||||
export let active = false
|
||||
export let tooltip = undefined
|
||||
export let dataCy
|
||||
export let newStyles = true
|
||||
export let id
|
||||
|
||||
|
@ -33,7 +32,6 @@
|
|||
class:disabled
|
||||
class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
|
||||
{disabled}
|
||||
data-cy={dataCy}
|
||||
on:click|preventDefault
|
||||
on:mouseover={() => (showTooltip = true)}
|
||||
on:focus={() => (showTooltip = true)}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
export let id = null
|
||||
export let readonly = false
|
||||
export let updateOnChange = true
|
||||
export let dataCy
|
||||
export let align
|
||||
export let autofocus = false
|
||||
export let variables
|
||||
|
@ -123,7 +122,6 @@
|
|||
disabled={hbsValue.length || disabled}
|
||||
{readonly}
|
||||
{id}
|
||||
data-cy={dataCy}
|
||||
value={hbsValue.length ? `{{ ${hbsValue[0]} }}` : value}
|
||||
placeholder={placeholder || ""}
|
||||
on:click
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
export let id = null
|
||||
export let text = null
|
||||
export let disabled = false
|
||||
export let dataCy = null
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const onChange = event => {
|
||||
|
@ -16,7 +15,6 @@
|
|||
|
||||
<div class="spectrum-Switch spectrum-Switch--emphasized">
|
||||
<input
|
||||
data-cy={dataCy}
|
||||
checked={value}
|
||||
{disabled}
|
||||
on:change={onChange}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
export let readonly = false
|
||||
export let updateOnChange = true
|
||||
export let quiet = false
|
||||
export let dataCy
|
||||
export let align
|
||||
export let autofocus = false
|
||||
|
||||
|
@ -89,7 +88,6 @@
|
|||
{disabled}
|
||||
{readonly}
|
||||
{id}
|
||||
data-cy={dataCy}
|
||||
value={value || ""}
|
||||
placeholder={placeholder || ""}
|
||||
on:click
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
export let error = null
|
||||
export let updateOnChange = true
|
||||
export let quiet = false
|
||||
export let dataCy
|
||||
export let autofocus
|
||||
export let variables
|
||||
export let showModal
|
||||
|
@ -28,7 +27,6 @@
|
|||
|
||||
<Field {label} {labelPosition} {error}>
|
||||
<EnvDropdown
|
||||
{dataCy}
|
||||
{updateOnChange}
|
||||
{error}
|
||||
{disabled}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
export let error = null
|
||||
export let updateOnChange = true
|
||||
export let quiet = false
|
||||
export let dataCy
|
||||
export let autofocus
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
@ -25,7 +24,6 @@
|
|||
|
||||
<Field {label} {labelPosition} {error}>
|
||||
<TextField
|
||||
{dataCy}
|
||||
{updateOnChange}
|
||||
{error}
|
||||
{disabled}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
export let error = null
|
||||
export let updateOnChange = true
|
||||
export let quiet = false
|
||||
export let dataCy
|
||||
export let autofocus
|
||||
export let options = []
|
||||
|
||||
|
@ -32,7 +31,6 @@
|
|||
|
||||
<Field {label} {labelPosition} {error}>
|
||||
<InputDropdown
|
||||
{dataCy}
|
||||
{updateOnChange}
|
||||
{error}
|
||||
{disabled}
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
export let getSecondaryOptionColour = () => {}
|
||||
export let getSecondaryOptionIcon = () => {}
|
||||
export let quiet = false
|
||||
export let dataCy
|
||||
export let autofocus
|
||||
export let primaryOptions = []
|
||||
export let secondaryOptions = []
|
||||
|
@ -98,7 +97,6 @@
|
|||
<PickerDropdown
|
||||
{searchTerm}
|
||||
{autocomplete}
|
||||
{dataCy}
|
||||
{error}
|
||||
{disabled}
|
||||
{readonly}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
export let text = null
|
||||
export let disabled = false
|
||||
export let error = null
|
||||
export let dataCy = null
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const onChange = e => {
|
||||
|
@ -19,5 +18,5 @@
|
|||
</script>
|
||||
|
||||
<Field {label} {labelPosition} {error}>
|
||||
<Switch {dataCy} {error} {disabled} {text} {value} on:change={onChange} />
|
||||
<Switch {error} {disabled} {text} {value} on:change={onChange} />
|
||||
</Field>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
const dispatch = createEventDispatcher()
|
||||
const actionMenu = getContext("actionMenu")
|
||||
|
||||
export let dataCy
|
||||
export let icon = undefined
|
||||
export let disabled = undefined
|
||||
export let noClose = false
|
||||
|
@ -35,7 +34,6 @@
|
|||
</script>
|
||||
|
||||
<li
|
||||
data-cy={dataCy}
|
||||
on:click|preventDefault={disabled ? null : onClick}
|
||||
class="spectrum-Menu-item"
|
||||
class:is-disabled={disabled}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
export let secondaryButtonText = undefined
|
||||
export let secondaryAction = undefined
|
||||
export let secondaryButtonWarning = false
|
||||
export let dataCy = null
|
||||
|
||||
const { hide, cancel } = getContext(Context.Modal)
|
||||
let loading = false
|
||||
$: confirmDisabled = disabled || loading
|
||||
|
@ -63,7 +63,6 @@
|
|||
role="dialog"
|
||||
tabindex="-1"
|
||||
aria-modal="true"
|
||||
data-cy={dataCy}
|
||||
>
|
||||
<div class="spectrum-Dialog-grid">
|
||||
{#if title || $$slots.header}
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
export let anchor
|
||||
export let align = "right"
|
||||
export let portalTarget
|
||||
export let dataCy
|
||||
export let maxWidth
|
||||
export let open = false
|
||||
export let useAnchorWidth = false
|
||||
export let dismissible = true
|
||||
export let offset = 5
|
||||
|
||||
$: target = portalTarget || getContext(Context.PopoverRoot) || ".spectrum"
|
||||
|
||||
|
@ -57,7 +57,6 @@
|
|||
</script>
|
||||
|
||||
{#if open}
|
||||
{#key anchor}
|
||||
<Portal {target}>
|
||||
<div
|
||||
tabindex="0"
|
||||
|
@ -66,7 +65,7 @@
|
|||
align,
|
||||
maxWidth,
|
||||
useAnchorWidth,
|
||||
showTip: false,
|
||||
offset,
|
||||
}}
|
||||
use:clickOutside={{
|
||||
callback: dismissible ? handleOutsideClick : () => {},
|
||||
|
@ -75,13 +74,11 @@
|
|||
on:keydown={handleEscape}
|
||||
class="spectrum-Popover is-open"
|
||||
role="presentation"
|
||||
data-cy={dataCy}
|
||||
transition:fly|local={{ y: -20, duration: 200 }}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</Portal>
|
||||
{/key}
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
export let icon = ""
|
||||
export let selected = false
|
||||
export let disabled = false
|
||||
export let dataCy
|
||||
export let badge = ""
|
||||
</script>
|
||||
|
||||
|
@ -17,7 +16,6 @@
|
|||
class:is-selected={selected}
|
||||
class:is-disabled={disabled}
|
||||
on:click
|
||||
data-cy={dataCy}
|
||||
>
|
||||
{#if heading}
|
||||
<h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}">
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"baseUrl": "http://localhost:4100",
|
||||
"video": true,
|
||||
"projectId": "bmbemn",
|
||||
"reporter": "cypress-multi-reporters",
|
||||
"reporterOptions": {
|
||||
"configFile": "reporterConfig.json"
|
||||
},
|
||||
"env": {
|
||||
"PORT": "4100",
|
||||
"WORKER_PORT": "4200",
|
||||
"JWT_SECRET": "test",
|
||||
"HOST_IP": ""
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"budibase": "CB373643-3FC4-4902-9E31-449C0ED066B6"
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"id": 8739,
|
||||
"name": "Jane",
|
||||
"email": "jane@example.com"
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Leanne Graham",
|
||||
"username": "Bret",
|
||||
"email": "Sincere@april.biz",
|
||||
"address": {
|
||||
"street": "Kulas Light",
|
||||
"suite": "Apt. 556",
|
||||
"city": "Gwenborough",
|
||||
"zipcode": "92998-3874",
|
||||
"geo": {
|
||||
"lat": "-37.3159",
|
||||
"lng": "81.1496"
|
||||
}
|
||||
},
|
||||
"phone": "1-770-736-8031 x56442",
|
||||
"website": "hildegard.org",
|
||||
"company": {
|
||||
"name": "Romaguera-Crona",
|
||||
"catchPhrase": "Multi-layered client-server neural-net",
|
||||
"bs": "harness real-time e-markets"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Ervin Howell",
|
||||
"username": "Antonette",
|
||||
"email": "Shanna@melissa.tv",
|
||||
"address": {
|
||||
"street": "Victor Plains",
|
||||
"suite": "Suite 879",
|
||||
"city": "Wisokyburgh",
|
||||
"zipcode": "90566-7771",
|
||||
"geo": {
|
||||
"lat": "-43.9509",
|
||||
"lng": "-34.4618"
|
||||
}
|
||||
},
|
||||
"phone": "010-692-6593 x09125",
|
||||
"website": "anastasia.net",
|
||||
"company": {
|
||||
"name": "Deckow-Crist",
|
||||
"catchPhrase": "Proactive didactic contingency",
|
||||
"bs": "synergize scalable supply-chains"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Clementine Bauch",
|
||||
"username": "Samantha",
|
||||
"email": "Nathan@yesenia.net",
|
||||
"address": {
|
||||
"street": "Douglas Extension",
|
||||
"suite": "Suite 847",
|
||||
"city": "McKenziehaven",
|
||||
"zipcode": "59590-4157",
|
||||
"geo": {
|
||||
"lat": "-68.6102",
|
||||
"lng": "-47.0653"
|
||||
}
|
||||
},
|
||||
"phone": "1-463-123-4447",
|
||||
"website": "ramiro.info",
|
||||
"company": {
|
||||
"name": "Romaguera-Jacobson",
|
||||
"catchPhrase": "Face to face bifurcated interface",
|
||||
"bs": "e-enable strategic applications"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Patricia Lebsack",
|
||||
"username": "Karianne",
|
||||
"email": "Julianne.OConner@kory.org",
|
||||
"address": {
|
||||
"street": "Hoeger Mall",
|
||||
"suite": "Apt. 692",
|
||||
"city": "South Elvis",
|
||||
"zipcode": "53919-4257",
|
||||
"geo": {
|
||||
"lat": "29.4572",
|
||||
"lng": "-164.2990"
|
||||
}
|
||||
},
|
||||
"phone": "493-170-9623 x156",
|
||||
"website": "kale.biz",
|
||||
"company": {
|
||||
"name": "Robel-Corkery",
|
||||
"catchPhrase": "Multi-tiered zero tolerance productivity",
|
||||
"bs": "transition cutting-edge web services"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Chelsey Dietrich",
|
||||
"username": "Kamren",
|
||||
"email": "Lucio_Hettinger@annie.ca",
|
||||
"address": {
|
||||
"street": "Skiles Walks",
|
||||
"suite": "Suite 351",
|
||||
"city": "Roscoeview",
|
||||
"zipcode": "33263",
|
||||
"geo": {
|
||||
"lat": "-31.8129",
|
||||
"lng": "62.5342"
|
||||
}
|
||||
},
|
||||
"phone": "(254)954-1289",
|
||||
"website": "demarco.info",
|
||||
"company": {
|
||||
"name": "Keebler LLC",
|
||||
"catchPhrase": "User-centric fault-tolerant solution",
|
||||
"bs": "revolutionize end-to-end systems"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Mrs. Dennis Schulist",
|
||||
"username": "Leopoldo_Corkery",
|
||||
"email": "Karley_Dach@jasper.info",
|
||||
"address": {
|
||||
"street": "Norberto Crossing",
|
||||
"suite": "Apt. 950",
|
||||
"city": "South Christy",
|
||||
"zipcode": "23505-1337",
|
||||
"geo": {
|
||||
"lat": "-71.4197",
|
||||
"lng": "71.7478"
|
||||
}
|
||||
},
|
||||
"phone": "1-477-935-8478 x6430",
|
||||
"website": "ola.org",
|
||||
"company": {
|
||||
"name": "Considine-Lockman",
|
||||
"catchPhrase": "Synchronised bottom-line interface",
|
||||
"bs": "e-enable innovative applications"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Kurtis Weissnat",
|
||||
"username": "Elwyn.Skiles",
|
||||
"email": "Telly.Hoeger@billy.biz",
|
||||
"address": {
|
||||
"street": "Rex Trail",
|
||||
"suite": "Suite 280",
|
||||
"city": "Howemouth",
|
||||
"zipcode": "58804-1099",
|
||||
"geo": {
|
||||
"lat": "24.8918",
|
||||
"lng": "21.8984"
|
||||
}
|
||||
},
|
||||
"phone": "210.067.6132",
|
||||
"website": "elvis.io",
|
||||
"company": {
|
||||
"name": "Johns Group",
|
||||
"catchPhrase": "Configurable multimedia task-force",
|
||||
"bs": "generate enterprise e-tailers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Nicholas Runolfsdottir V",
|
||||
"username": "Maxime_Nienow",
|
||||
"email": "Sherwood@rosamond.me",
|
||||
"address": {
|
||||
"street": "Ellsworth Summit",
|
||||
"suite": "Suite 729",
|
||||
"city": "Aliyaview",
|
||||
"zipcode": "45169",
|
||||
"geo": {
|
||||
"lat": "-14.3990",
|
||||
"lng": "-120.7677"
|
||||
}
|
||||
},
|
||||
"phone": "586.493.6943 x140",
|
||||
"website": "jacynthe.com",
|
||||
"company": {
|
||||
"name": "Abernathy Group",
|
||||
"catchPhrase": "Implemented secondary concept",
|
||||
"bs": "e-enable extensible e-tailers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Glenna Reichert",
|
||||
"username": "Delphine",
|
||||
"email": "Chaim_McDermott@dana.io",
|
||||
"address": {
|
||||
"street": "Dayna Park",
|
||||
"suite": "Suite 449",
|
||||
"city": "Bartholomebury",
|
||||
"zipcode": "76495-3109",
|
||||
"geo": {
|
||||
"lat": "24.6463",
|
||||
"lng": "-168.8889"
|
||||
}
|
||||
},
|
||||
"phone": "(775)976-6794 x41206",
|
||||
"website": "conrad.com",
|
||||
"company": {
|
||||
"name": "Yost and Sons",
|
||||
"catchPhrase": "Switchable contextually-based project",
|
||||
"bs": "aggregate real-time technologies"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Clementina DuBuque",
|
||||
"username": "Moriah.Stanton",
|
||||
"email": "Rey.Padberg@karina.biz",
|
||||
"address": {
|
||||
"street": "Kattie Turnpike",
|
||||
"suite": "Suite 198",
|
||||
"city": "Lebsackbury",
|
||||
"zipcode": "31428-2261",
|
||||
"geo": {
|
||||
"lat": "-38.2386",
|
||||
"lng": "57.2232"
|
||||
}
|
||||
},
|
||||
"phone": "024-648-3804",
|
||||
"website": "ambrose.net",
|
||||
"company": {
|
||||
"name": "Hoeger LLC",
|
||||
"catchPhrase": "Centralized empowering task-force",
|
||||
"bs": "target end-to-end tables"
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,45 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['all'], () => {
|
||||
xcontext("Add Multi-Option Datatype", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
it("should create a new table, with data", () => {
|
||||
cy.createTable("Multi Data")
|
||||
cy.addColumn("Multi Data", "Test Data", "Multi-select", "1\n2\n3\n4\n5")
|
||||
cy.addRowMultiValue(["1", "2", "3", "4", "5"])
|
||||
})
|
||||
|
||||
it("should add form with multi select picker, containing 5 options", () => {
|
||||
cy.navigateToFrontend()
|
||||
// Add data provider
|
||||
cy.searchAndAddComponent("Data Provider")
|
||||
cy.get(interact.DATASOURCE_PROP_CONTROL).click()
|
||||
cy.get(interact.DROPDOWN).contains("Multi Data").click()
|
||||
// Add Form with schema to match table
|
||||
cy.searchAndAddComponent("Form")
|
||||
cy.get(interact.DATASOURCE_PROP_CONTROL).click()
|
||||
cy.get(interact.DROPDOWN).contains("Multi Data").click()
|
||||
// Add multi-select picker to form
|
||||
cy.searchAndAddComponent("Multi-select Picker").then(componentId => {
|
||||
cy.get(interact.DATASOURCE_FIELD_CONTROL).type("Test Data").type("{enter}")
|
||||
cy.wait(1000)
|
||||
cy.getComponent(componentId).contains("Choose some options").click()
|
||||
// Check picker has 5 items
|
||||
cy.getComponent(componentId).find("li").should("have.length", 5)
|
||||
// Select all items
|
||||
for (let i = 1; i < 6; i++) {
|
||||
cy.getComponent(componentId).find("li").contains(i).click()
|
||||
}
|
||||
// Check items have been selected
|
||||
cy.getComponent(componentId)
|
||||
.find(interact.SPECTRUM_PICKER_LABEL)
|
||||
.contains("(5)")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,43 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['all'], () => {
|
||||
xcontext("Add Radio Buttons", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
it("should add Radio Buttons options picker on form, add data, and confirm", () => {
|
||||
cy.navigateToFrontend()
|
||||
cy.searchAndAddComponent("Form")
|
||||
cy.searchAndAddComponent("Options Picker").then((componentId) => {
|
||||
// Provide field setting
|
||||
cy.get(interact.DATASOURCE_FIELD_CONTROL).type("1")
|
||||
// Open dropdown and select Radio buttons
|
||||
cy.get(interact.OPTION_TYPE_PROP_CONTROL).click().then(() => {
|
||||
cy.get(interact.SPECTRUM_POPOVER).contains('Radio buttons')
|
||||
.click()
|
||||
})
|
||||
const radioButtonsTotal = 3
|
||||
// Add values and confirm total
|
||||
addRadioButtonData(radioButtonsTotal)
|
||||
cy.getComponent(componentId).find('[type="radio"]')
|
||||
.should('have.length', radioButtonsTotal)
|
||||
})
|
||||
})
|
||||
|
||||
const addRadioButtonData = (totalRadioButtons) => {
|
||||
cy.get(interact.OPTION_SOURCE_PROP_CONROL).click().then(() => {
|
||||
cy.get(interact.SPECTRUM_POPOVER).contains('Custom')
|
||||
.click()
|
||||
.wait(1000)
|
||||
})
|
||||
cy.addCustomSourceOptions(totalRadioButtons)
|
||||
}
|
||||
|
||||
after(() => {
|
||||
cy.deleteAllApps()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,116 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
const interact = require('../../support/interact')
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
xcontext("Account Portals", () => {
|
||||
|
||||
const bbUserEmail = "bbuser@test.com"
|
||||
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.deleteApp("Cypress Tests")
|
||||
cy.createApp("Cypress Tests", false)
|
||||
|
||||
// Create new user
|
||||
cy.wait(500)
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
cy.createUser(bbUserEmail)
|
||||
cy.contains("bbuser").click()
|
||||
cy.wait(500)
|
||||
|
||||
// Reset password
|
||||
cy.get(".title").within(() => {
|
||||
cy.get(interact.SPECTRUM_ICON).click({ force: true })
|
||||
})
|
||||
cy.get(interact.SPECTRUM_MENU).within(() => {
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("Force password reset").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID)
|
||||
.find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('pwd')
|
||||
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true })
|
||||
|
||||
// Login as new user and set password
|
||||
cy.logOut()
|
||||
cy.get('@pwd').then((pwd) => {
|
||||
cy.login(bbUserEmail, pwd)
|
||||
})
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test")
|
||||
}
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Reset your password").click({ force: true })
|
||||
//cy.logoutNoAppGrid()
|
||||
})
|
||||
|
||||
xit("should verify Standard Portal", () => {
|
||||
// Development access should be disabled (Admin access is already disabled)
|
||||
cy.login()
|
||||
cy.setUserRole("bbuser", "App User")
|
||||
bbUserLogin()
|
||||
|
||||
// Verify Standard Portal
|
||||
cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections
|
||||
cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button
|
||||
cy.get(".app").should('not.exist') // No apps -> no roles assigned to user
|
||||
cy.get(interact.CONTAINER).should('contain', bbUserEmail) // Message containing users email
|
||||
|
||||
cy.logoutNoAppGrid()
|
||||
})
|
||||
|
||||
xit("should verify Admin Portal", () => {
|
||||
cy.login()
|
||||
// Configure user role
|
||||
cy.setUserRole("bbuser", "Admin")
|
||||
bbUserLogin()
|
||||
|
||||
// Verify available options for Admin portal
|
||||
cy.get(interact.SPECTRUM_SIDENAV)
|
||||
.should('contain', 'Apps')
|
||||
//.and('contain', 'Usage')
|
||||
.and('contain', 'Users')
|
||||
.and('contain', 'Auth')
|
||||
.and('contain', 'Email')
|
||||
.and('contain', 'Organisation')
|
||||
.and('contain', 'Theming')
|
||||
.and('contain', 'Update')
|
||||
//.and('contain', 'Upgrade')
|
||||
|
||||
cy.logOut()
|
||||
})
|
||||
|
||||
xit("should verify Development Portal", () => {
|
||||
// Only Development access should be enabled
|
||||
cy.login()
|
||||
cy.setUserRole("bbuser", "Developer")
|
||||
bbUserLogin()
|
||||
|
||||
// Verify available options for Admin portal
|
||||
cy.get(interact.SPECTRUM_SIDENAV)
|
||||
.should('contain', 'Apps')
|
||||
//.and('contain', 'Usage')
|
||||
.and('not.contain', 'Users')
|
||||
.and('not.contain', 'Auth')
|
||||
.and('not.contain', 'Email')
|
||||
.and('not.contain', 'Organisation')
|
||||
.and('contain', 'Theming')
|
||||
.and('not.contain', 'Update')
|
||||
.and('not.contain', 'Upgrade')
|
||||
|
||||
cy.logOut()
|
||||
})
|
||||
|
||||
const bbUserLogin = () => {
|
||||
// Login as bbuser
|
||||
cy.logOut()
|
||||
cy.login(bbUserEmail, "test")
|
||||
}
|
||||
|
||||
after(() => {
|
||||
cy.login()
|
||||
// Delete BB user
|
||||
cy.deleteUser(bbUserEmail)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,178 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
// const interact = require("../support/interact")
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
xcontext("Auth Configuration", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
})
|
||||
|
||||
after(() => {
|
||||
cy.get(".spectrum-SideNav li").contains("Auth").click()
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq("/builder/portal/manage/auth")
|
||||
})
|
||||
|
||||
cy.get("[data-cy=new-scope-input]").clear()
|
||||
|
||||
cy.get("div.content").scrollTo("bottom")
|
||||
cy.get("[data-cy=oidc-active]").click()
|
||||
|
||||
cy.get("[data-cy=oidc-active]").should('not.be.checked')
|
||||
|
||||
cy.intercept("POST", "/api/global/configs").as("updateAuth")
|
||||
cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true })
|
||||
cy.wait("@updateAuth")
|
||||
cy.get("@updateAuth").its("response.statusCode").should("eq", 200)
|
||||
|
||||
cy.get(".spectrum-Toast-content")
|
||||
.contains("Settings saved")
|
||||
.should("be.visible")
|
||||
})
|
||||
|
||||
it("Should allow updating of the OIDC config", () => {
|
||||
cy.get(".spectrum-SideNav li").contains("Auth").click()
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq("/builder/portal/manage/auth")
|
||||
})
|
||||
cy.get("div.content").scrollTo("bottom")
|
||||
cy.get(".spectrum-Toast .spectrum-ClearButton").click()
|
||||
|
||||
cy.get("input[data-cy=configUrl]").type("http://budi-auth.com/v2")
|
||||
cy.get("input[data-cy=clientID]").type("34ac6a13-f24a-4b52-c70d-fa544ffd11b2")
|
||||
cy.get("input[data-cy=clientSecret]").type("12A8Q~4nS_DWhOOJ2vWIRsNyDVsdtXPD.Zxa9df_")
|
||||
|
||||
cy.get("button[data-cy=oidc-save]").should("not.be.disabled");
|
||||
|
||||
cy.intercept("POST", "/api/global/configs").as("updateAuth")
|
||||
cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true })
|
||||
cy.wait("@updateAuth")
|
||||
cy.get("@updateAuth").its("response.statusCode").should("eq", 200)
|
||||
|
||||
cy.get(".spectrum-Toast-content")
|
||||
.contains("Settings saved")
|
||||
.should("be.visible")
|
||||
})
|
||||
|
||||
it("Should display default scopes in advanced config.", () => {
|
||||
cy.get(".spectrum-SideNav li").contains("Auth").click()
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq("/builder/portal/manage/auth")
|
||||
})
|
||||
cy.get("div.content").scrollTo("bottom")
|
||||
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4)
|
||||
|
||||
cy.get(".spectrum-Tags-item").contains("openid")
|
||||
cy.get(".spectrum-Tags-item").contains("openid").find(".spectrum-ClearButton").should("not.exist")
|
||||
|
||||
cy.get(".spectrum-Tags-item").contains("offline_access")
|
||||
cy.get(".spectrum-Tags-item").contains("email")
|
||||
cy.get(".spectrum-Tags-item").contains("profile")
|
||||
})
|
||||
|
||||
it("Add a new scopes", () => {
|
||||
cy.get(".spectrum-SideNav li").contains("Auth").click()
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq("/builder/portal/manage/auth")
|
||||
})
|
||||
cy.get("div.content").scrollTo("bottom")
|
||||
|
||||
cy.get("[data-cy=new-scope-input]").type("Sample{enter}")
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 5)
|
||||
cy.get(".spectrum-Tags-item").contains("Sample")
|
||||
|
||||
cy.get(".auth-form input.spectrum-Textfield-input").type("Another ")
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 6)
|
||||
cy.get(".spectrum-Tags-item").contains("Another")
|
||||
|
||||
cy.get("button[data-cy=oidc-save]").should("not.be.disabled");
|
||||
|
||||
cy.intercept("POST", "/api/global/configs").as("updateAuth")
|
||||
cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true })
|
||||
cy.wait("@updateAuth")
|
||||
cy.get("@updateAuth").its("response.statusCode").should("eq", 200)
|
||||
|
||||
cy.reload()
|
||||
|
||||
cy.get("div.content").scrollTo("bottom")
|
||||
|
||||
cy.get(".spectrum-Tags-item").contains("openid")
|
||||
cy.get(".spectrum-Tags-item").contains("offline_access")
|
||||
cy.get(".spectrum-Tags-item").contains("email")
|
||||
cy.get(".spectrum-Tags-item").contains("profile")
|
||||
cy.get(".spectrum-Tags-item").contains("Sample")
|
||||
cy.get(".spectrum-Tags-item").contains("Another")
|
||||
})
|
||||
|
||||
it("Should allow the removal of auth scopes", () => {
|
||||
cy.get(".spectrum-SideNav li").contains("Auth").click()
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq("/builder/portal/manage/auth")
|
||||
})
|
||||
cy.get("div.content").scrollTo("bottom")
|
||||
|
||||
cy.get(".spectrum-Tags-item").contains("offline_access").parent().find(".spectrum-ClearButton").click()
|
||||
cy.get(".spectrum-Tags-item").contains("profile").parent().find(".spectrum-ClearButton").click()
|
||||
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4)
|
||||
|
||||
cy.get(".spectrum-Tags-item").contains("offline_access").should("not.exist")
|
||||
cy.get(".spectrum-Tags-item").contains("profile").should("not.exist")
|
||||
|
||||
cy.get("button[data-cy=oidc-save]").should("not.be.disabled");
|
||||
|
||||
cy.intercept("POST", "/api/global/configs").as("updateAuth")
|
||||
cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true })
|
||||
cy.wait("@updateAuth")
|
||||
cy.get("@updateAuth").its("response.statusCode").should("eq", 200)
|
||||
|
||||
cy.get(".spectrum-Toast-content")
|
||||
.contains("Settings saved")
|
||||
.should("be.visible")
|
||||
|
||||
cy.reload()
|
||||
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4)
|
||||
|
||||
cy.get(".spectrum-Tags-item").contains("offline_access").should("not.exist")
|
||||
cy.get(".spectrum-Tags-item").contains("profile").should("not.exist")
|
||||
})
|
||||
|
||||
it("Should allow auth scopes to be reset to the core defaults.", () => {
|
||||
cy.get(".spectrum-SideNav li").contains("Auth").click()
|
||||
|
||||
cy.get("div.content").scrollTo("bottom")
|
||||
|
||||
cy.get("[data-cy=restore-oidc-default-scopes]").click({ force: true })
|
||||
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4)
|
||||
|
||||
cy.get(".spectrum-Tags-item").contains("openid")
|
||||
cy.get(".spectrum-Tags-item").contains("offline_access")
|
||||
cy.get(".spectrum-Tags-item").contains("email")
|
||||
cy.get(".spectrum-Tags-item").contains("profile")
|
||||
})
|
||||
|
||||
it("Should not allow invalid characters in the auth scopes", () => {
|
||||
cy.get("[data-cy=new-scope-input]").type("thisIsInvalid\\{enter}")
|
||||
cy.get(".spectrum-Form-itemField .error").contains("Auth scopes cannot contain spaces, double quotes or backslashes")
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4)
|
||||
|
||||
cy.get("[data-cy=new-scope-input]").clear()
|
||||
|
||||
cy.get("[data-cy=new-scope-input]").type("alsoInvalid\"{enter}")
|
||||
cy.get(".spectrum-Form-itemField .error").contains("Auth scopes cannot contain spaces, double quotes or backslashes")
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4)
|
||||
|
||||
cy.get("[data-cy=new-scope-input]").clear()
|
||||
})
|
||||
|
||||
it("Should not allow duplicate auth scopes", () => {
|
||||
cy.get("[data-cy=new-scope-input]").type("offline_access{enter}")
|
||||
cy.get(".spectrum-Form-itemField .error").contains("Auth scope already exists")
|
||||
cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
|
@ -1,238 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
const interact = require('../../support/interact')
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
xcontext("User Management", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.deleteApp("Cypress Tests")
|
||||
cy.createApp("Cypress Tests", false)
|
||||
})
|
||||
|
||||
xit("should create a user via basic onboarding", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000})
|
||||
cy.createUser("bbuser@test.com")
|
||||
cy.get(interact.SPECTRUM_TABLE).should("contain", "bbuser")
|
||||
})
|
||||
|
||||
xit("should confirm App User role for a New User", () => {
|
||||
cy.contains("bbuser").click()
|
||||
cy.get(".spectrum-Form-itemField").eq(3).should('contain', 'App User')
|
||||
|
||||
// User should not have app access
|
||||
cy.get(".spectrum-Heading").contains("Apps").parent().within(() => {
|
||||
cy.get(interact.LIST_ITEMS, { timeout: 500 }).should("contain", "This user has access to no apps")
|
||||
})
|
||||
})
|
||||
|
||||
if (Cypress.env("TEST_ENV")) {
|
||||
xit("should assign role types", () => {
|
||||
// 3 apps minimum required - to assign an app to each role type
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
|
||||
.its("body")
|
||||
.then(val => {
|
||||
if (val.length < 3) {
|
||||
for (let i = 1; i < 3; i++) {
|
||||
const uuid = () => Cypress._.random(0, 1e6)
|
||||
const name = uuid()
|
||||
if(i < 1){
|
||||
cy.createApp(name, false)
|
||||
} else {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000})
|
||||
cy.wait(1000)
|
||||
cy.get(interact.CREATE_APP_BUTTON, { timeout: 2000 }).click({ force: true })
|
||||
cy.createAppFromScratch(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
// Navigate back to the user
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000})
|
||||
cy.get(interact.SPECTRUM_SIDENAV).contains("Users").click()
|
||||
cy.get(interact.SPECTRUM_TABLE, { timeout: 1000 }).contains("bbuser").click()
|
||||
cy.get(interact.SPECTRUM_HEADING).contains("bbuser", { timeout: 2000})
|
||||
for (let i = 0; i < 3; i++) {
|
||||
cy.get(interact.SPECTRUM_TABLE, { timeout: 3000})
|
||||
.eq(1)
|
||||
.find(interact.SPECTRUM_TABLE_ROW)
|
||||
.eq(0)
|
||||
.find(interact.SPECTRUM_TABLE_CELL)
|
||||
.eq(0)
|
||||
.click()
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 1000 })
|
||||
.contains("Choose an option")
|
||||
.click()
|
||||
.then(() => {
|
||||
if (i == 0) {
|
||||
cy.get(interact.SPECTRUM_MENU, { timeout: 2000 }).contains("Admin").click({ force: true })
|
||||
}
|
||||
else if (i == 1) {
|
||||
cy.get(interact.SPECTRUM_MENU, { timeout: 2000 }).contains("Power").click({ force: true })
|
||||
}
|
||||
else if (i == 2) {
|
||||
cy.get(interact.SPECTRUM_MENU, { timeout: 2000 }).contains("Basic").click({ force: true })
|
||||
}
|
||||
cy.get(interact.SPECTRUM_BUTTON, { timeout: 2000 })
|
||||
.contains("Update role")
|
||||
.click({ force: true })
|
||||
})
|
||||
cy.reload()
|
||||
cy.wait(1000)
|
||||
}
|
||||
// Confirm roles exist within Configure roles table
|
||||
cy.get(interact.SPECTRUM_TABLE, { timeout: 20000 })
|
||||
.eq(0)
|
||||
.within(assginedRoles => {
|
||||
expect(assginedRoles).to.contain("Admin")
|
||||
expect(assginedRoles).to.contain("Power")
|
||||
expect(assginedRoles).to.contain("Basic")
|
||||
})
|
||||
})
|
||||
|
||||
xit("should unassign role types", () => {
|
||||
// Set each app within Configure roles table to 'No Access'
|
||||
cy.get(interact.SPECTRUM_TABLE)
|
||||
.eq(0)
|
||||
.find(interact.SPECTRUM_TABLE_ROW)
|
||||
.its("length")
|
||||
.then(len => {
|
||||
for (let i = 0; i < len; i++) {
|
||||
cy.get(interact.SPECTRUM_TABLE)
|
||||
.eq(0)
|
||||
.find(interact.SPECTRUM_TABLE_ROW)
|
||||
.eq(0)
|
||||
.find(interact.SPECTRUM_TABLE_CELL)
|
||||
.eq(0)
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.get(interact.SPECTRUM_PICKER).eq(1).click({ force: true })
|
||||
cy.get(interact.SPECTRUM_POPOVER, { timeout: 500 }).contains("No Access").click()
|
||||
})
|
||||
cy.get(interact.SPECTRUM_BUTTON)
|
||||
.contains("Update role")
|
||||
.click({ force: true })
|
||||
}
|
||||
})
|
||||
// Confirm Configure roles table no longer has any apps in it
|
||||
cy.get(interact.SPECTRUM_TABLE, { timeout: 1000 }).eq(0).contains("No rows found")
|
||||
})
|
||||
}
|
||||
|
||||
xit("should enable Developer access and verify application access", () => {
|
||||
// Enable Developer access
|
||||
cy.get(interact.FIELD)
|
||||
.eq(4)
|
||||
.within(() => {
|
||||
cy.get(interact.SPECTRUM_SWITCH_INPUT).click({ force: true })
|
||||
})
|
||||
// No Access table should now be empty
|
||||
cy.get(interact.CONTAINER)
|
||||
.contains("No Access")
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(interact.SPECTRUM_TABLE).contains("No rows found")
|
||||
})
|
||||
|
||||
// Each app within Configure roles should have Admin access
|
||||
cy.get(interact.SPECTRUM_TABLE)
|
||||
.eq(0)
|
||||
.find(interact.SPECTRUM_TABLE_ROW)
|
||||
.its("length")
|
||||
.then(len => {
|
||||
for (let i = 0; i < len; i++) {
|
||||
cy.get(interact.SPECTRUM_TABLE)
|
||||
.eq(0)
|
||||
.find(interact.SPECTRUM_TABLE_ROW)
|
||||
.eq(i)
|
||||
.contains("Admin")
|
||||
cy.wait(500)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
xit("should disable Developer access and verify application access", () => {
|
||||
// Disable Developer access
|
||||
cy.get(interact.FIELD)
|
||||
.eq(4)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Switch-input").click({ force: true })
|
||||
})
|
||||
// Configure roles table should now be empty
|
||||
cy.get(interact.CONTAINER)
|
||||
.contains("Configure roles")
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(interact.SPECTRUM_TABLE).contains("No rows found")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should edit user details within user details page", () => {
|
||||
// Add First name
|
||||
cy.get(interact.FIELD, { timeout: 1000 }).eq(1).within(() => {
|
||||
cy.wait(500)
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 }).wait(500).clear().click().type("bb")
|
||||
})
|
||||
// Add Last name
|
||||
cy.get(interact.FIELD, { timeout: 1000 }).eq(2).within(() => {
|
||||
cy.wait(500)
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 }).click().wait(500).clear().type("test")
|
||||
})
|
||||
cy.get(interact.FIELD, { timeout: 1000 }).eq(0).click()
|
||||
// Reload page
|
||||
cy.reload()
|
||||
|
||||
// Confirm details have been saved
|
||||
cy.get(interact.FIELD, { timeout: 20000 }).eq(1).within(() => {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "bb")
|
||||
})
|
||||
cy.get(interact.FIELD, { timeout: 1000 }).eq(2).within(() => {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 }).should('have.value', "test")
|
||||
})
|
||||
})
|
||||
|
||||
xit("should reset the users password", () => {
|
||||
cy.get(".title").within(() => {
|
||||
cy.get(interact.SPECTRUM_ICON).click({ force: true })
|
||||
})
|
||||
cy.get(interact.SPECTRUM_MENU).within(() => {
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("Force password reset").click({ force: true })
|
||||
})
|
||||
|
||||
// Reset password modal
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID)
|
||||
.find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('pwd')
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").should('not.exist')
|
||||
|
||||
// Logout, then login with new password
|
||||
cy.logOut()
|
||||
cy.get('@pwd').then((pwd) => {
|
||||
cy.login("bbuser@test.com", pwd)
|
||||
})
|
||||
|
||||
// Reset password screen
|
||||
for (let i = 0; i < 2; i++) {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test")
|
||||
}
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Reset your password").click({ force: true })
|
||||
|
||||
// Confirm user logged in afer password change
|
||||
cy.login("bbuser@test.com", "test")
|
||||
cy.get(".avatar > .icon").click({ force: true })
|
||||
|
||||
cy.get(".spectrum-Menu-item").contains("Update user information").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
|
||||
.eq(0)
|
||||
.invoke('val').should('eq', 'bbuser@test.com')
|
||||
|
||||
// Logout and login as previous user
|
||||
cy.logoutNoAppGrid()
|
||||
cy.login()
|
||||
})
|
||||
|
||||
xit("should delete a user", () => {
|
||||
cy.deleteUser("bbuser@test.com")
|
||||
cy.get(interact.SPECTRUM_TABLE, { timeout: 4000 }).should("not.have.text", "bbuser")
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,114 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
const interact = require('../../support/interact')
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
context("User Settings Menu", () => {
|
||||
|
||||
before(() => {
|
||||
cy.login()
|
||||
})
|
||||
|
||||
it("should update user information via user settings menu", () => {
|
||||
const fname = "test"
|
||||
const lname = "user"
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.updateUserInformation(fname, lname)
|
||||
|
||||
// Go to user info and confirm name update
|
||||
cy.contains("Users").click()
|
||||
cy.contains("test@test.com").click()
|
||||
|
||||
cy.get(interact.FIELD, { timeout: 1000 }).eq(1).within(() => {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', fname)
|
||||
})
|
||||
cy.get(interact.FIELD).eq(2).within(() => {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', lname)
|
||||
})
|
||||
})
|
||||
|
||||
xit("should allow copying of the users API key", () => {
|
||||
cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true })
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("View API key").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => {
|
||||
cy.get(interact.SPECTRUM_ICON).click({ force: true })
|
||||
})
|
||||
// There may be timing issues with this on the smoke build
|
||||
cy.wait(500)
|
||||
cy.get(".spectrum-Toast-content")
|
||||
.contains("URL copied to clipboard")
|
||||
.should("be.visible")
|
||||
})
|
||||
|
||||
it("should allow API key regeneration", () => {
|
||||
cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true })
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("View API key").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => {
|
||||
cy.get(interact.SPECTRUM_ICON).click({ force: true })
|
||||
})
|
||||
// Get initial API key value
|
||||
cy.get(interact.SPECTRUM_DIALOG_CONTENT)
|
||||
.find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('keyOne')
|
||||
|
||||
// Click re-generate key button
|
||||
cy.get("button").contains("Regenerate key").click({ force: true })
|
||||
|
||||
// Verify API key was changed
|
||||
cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => {
|
||||
cy.get('@keyOne').then((keyOne) => {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').should('not.eq', keyOne)
|
||||
})
|
||||
})
|
||||
cy.closeModal()
|
||||
})
|
||||
|
||||
it("should update password", () => {
|
||||
// Access Update password modal
|
||||
cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true })
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true })
|
||||
|
||||
// Enter new password and update
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
// password set to 'newpwd'
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("newpwd")
|
||||
}
|
||||
cy.get("button").contains("Update password").click({ force: true })
|
||||
})
|
||||
|
||||
// Logout & in with new password
|
||||
//cy.logOut()
|
||||
cy.login("test@test.com", "newpwd")
|
||||
})
|
||||
|
||||
xit("should open and close developer mode", () => {
|
||||
cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true })
|
||||
|
||||
// Close developer mode & verify
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("Close developer mode").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections
|
||||
cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button
|
||||
cy.get(".app").should('not.exist') // At least one app should be available
|
||||
|
||||
// Open developer mode & verify
|
||||
cy.get(".avatar > .icon").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("Open developer mode").click({ force: true })
|
||||
cy.get(".app-table").should('exist') // config sections available
|
||||
cy.get(interact.CREATE_APP_BUTTON).should('exist') // create app button available
|
||||
})
|
||||
|
||||
after(() => {
|
||||
// Change password back to original value
|
||||
cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true })
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test")
|
||||
}
|
||||
cy.get("button").contains("Update password").click({ force: true })
|
||||
})
|
||||
// Remove users name
|
||||
cy.updateUserInformation()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,442 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
import clientPackage from "@budibase/client/package.json"
|
||||
|
||||
filterTests(["all"], () => {
|
||||
xcontext("Application Overview screen", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.deleteAllApps()
|
||||
cy.createApp("Cypress Tests")
|
||||
})
|
||||
|
||||
xit("Should be accessible from the applications list", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .title")
|
||||
.eq(0)
|
||||
.invoke("attr", "data-cy")
|
||||
.then($dataCy => {
|
||||
const dataCy = $dataCy
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.click({ force: true })
|
||||
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq("/builder/portal/overview/" + dataCy)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Find a more suitable place for this.
|
||||
xit("Should allow unlocking in the app list", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
|
||||
cy.get(".appTable .lock-status").eq(0).contains("Locked by you").click()
|
||||
|
||||
cy.unlockApp({ owned: true })
|
||||
|
||||
cy.get(".appTable").should("exist")
|
||||
cy.get(".lock-status").should("not.be.visible")
|
||||
})
|
||||
|
||||
xit("Should allow unlocking in the app overview screen", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Edit")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.wait(1000)
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".lock-status").eq(0).contains("Locked by you").click()
|
||||
|
||||
cy.unlockApp({ owned: true })
|
||||
|
||||
cy.get(".lock-status").should("not.be.visible")
|
||||
})
|
||||
|
||||
xit("Should reflect the deploy state of an app that hasn't been published.", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".header-right button.spectrum-Button[data-cy='view-app']").should(
|
||||
"be.disabled"
|
||||
)
|
||||
|
||||
cy.get(".spectrum-Tabs-item.is-selected").contains("Overview")
|
||||
cy.get(".overview-tab").should("be.visible")
|
||||
|
||||
cy.get(".overview-tab [data-cy='app-status']").within(() => {
|
||||
cy.get(".status-display").contains("Unpublished")
|
||||
cy.get(".status-display .icon svg[aria-label='GlobeStrike']").should(
|
||||
"exist"
|
||||
)
|
||||
cy.get(".status-text").contains("-")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should reflect the app deployment state", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Edit")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
|
||||
cy.wait(500)
|
||||
cy.get(".toprightnav button.spectrum-Button", { timeout: 2000 })
|
||||
.contains("Publish")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Modal [data-cy='deploy-app-modal']")
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Button").contains("Publish").click({ force: true })
|
||||
cy.wait(1000)
|
||||
})
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".header-right button.spectrum-Button[data-cy='view-app']").should(
|
||||
"not.be.disabled"
|
||||
)
|
||||
|
||||
cy.get(".overview-tab [data-cy='app-status']").within(() => {
|
||||
cy.get(".status-display").contains("Published")
|
||||
cy.get(".status-display .icon svg[aria-label='GlobeCheck']").should(
|
||||
"exist"
|
||||
)
|
||||
cy.get(".status-text").contains("Last published a few seconds ago")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should reflect an application that has been unpublished", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Edit")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
|
||||
cy.get(".deployment-top-nav svg[aria-label='Globe']").click({
|
||||
force: true,
|
||||
})
|
||||
|
||||
cy.get("[data-cy='publish-popover-menu']").should("be.visible")
|
||||
cy.get(
|
||||
"[data-cy='publish-popover-menu'] [data-cy='publish-popover-action']"
|
||||
).click({ force: true })
|
||||
|
||||
cy.get("[data-cy='unpublish-modal']")
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(".confirm-wrap button").click({ force: true })
|
||||
})
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.wait(1000)
|
||||
cy.get(".appTable .app-row-actions button", { timeout: 10000 })
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".overview-tab [data-cy='app-status']").within(() => {
|
||||
cy.get(".status-display").contains("Unpublished")
|
||||
cy.get(".status-display .icon svg[aria-label='GlobeStrike']").should(
|
||||
"exist"
|
||||
)
|
||||
cy.get(".status-text").contains("Last published a few seconds ago")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should allow the editing of the application icon and colour", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".edit-hover", { timeout: 1000 }).eq(0).click({ force: true })
|
||||
// Select random icon
|
||||
cy.wait(400)
|
||||
cy.get(".grid").within(() => {
|
||||
cy.get(".icon-item")
|
||||
.eq(Math.floor(Math.random() * 23) + 1)
|
||||
.click()
|
||||
})
|
||||
// Select random colour
|
||||
cy.get(".fill").click()
|
||||
cy.get(".colors").within(() => {
|
||||
cy.get(".color")
|
||||
.eq(Math.floor(Math.random() * 33) + 1)
|
||||
.click()
|
||||
})
|
||||
cy.intercept("**/applications/**").as("iconChange")
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
cy.wait("@iconChange")
|
||||
cy.get("@iconChange").its("response.statusCode").should("eq", 200)
|
||||
// Confirm icon has changed from default
|
||||
// Confirm colour has been applied
|
||||
cy.get(".spectrum-ActionButton-label").contains("Back").click({ force: true })
|
||||
cy.get(".appTable", { timeout: 2000 }).within(() => {
|
||||
cy.get("[aria-label]")
|
||||
.eq(0)
|
||||
.children()
|
||||
.should("have.attr", "xlink:href")
|
||||
.and("not.contain", "#spectrum-icon-18-Apps")
|
||||
cy.get(".title")
|
||||
.children()
|
||||
.children()
|
||||
.should("have.attr", "style")
|
||||
.and("contains", "color")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should reflect the last time the application was edited", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".header-right button").contains("Edit").click({ force: true })
|
||||
|
||||
cy.navigateToFrontend()
|
||||
|
||||
cy.searchAndAddComponent("Headline").then(componentId => {
|
||||
cy.getComponent(componentId).should("exist")
|
||||
})
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".overview-tab [data-cy='edited-by']").within(() => {
|
||||
cy.get(".editor-name").contains("You")
|
||||
cy.get(".last-edit-text").contains("Last edited a few seconds ago")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should reflect application version is up-to-date", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".overview-tab [data-cy='app-version']").within(() => {
|
||||
cy.get(".version-status").contains("You're running the latest!")
|
||||
})
|
||||
})
|
||||
|
||||
it("Should navigate to the settings tab when clicking the App Version card header", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Tabs-item.is-selected").contains("Overview")
|
||||
cy.get(".overview-tab").should("be.visible")
|
||||
|
||||
cy.get(".overview-tab [data-cy='app-version'] .dash-card-header").click({
|
||||
force: true,
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Tabs-item.is-selected").contains("Settings")
|
||||
cy.get(".settings-tab").should("be.visible")
|
||||
cy.get(".overview-tab").should("not.exist")
|
||||
})
|
||||
|
||||
it("Should allow the upgrading of an application, if available.", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.wait(500)
|
||||
|
||||
cy.location().then(loc => {
|
||||
const params = loc.pathname.split("/")
|
||||
const appId = params[params.length - 1]
|
||||
cy.log(appId)
|
||||
//Downgrade the app for the test
|
||||
cy.alterAppVersion(appId, "0.0.1-alpha.0").then(() => {
|
||||
cy.reload()
|
||||
cy.log("Current deployment version: " + clientPackage.version)
|
||||
|
||||
cy.get(".version-status a", { timeout: 5000 }).contains("Update").click()
|
||||
cy.get(".spectrum-Tabs-item.is-selected").contains("Settings")
|
||||
|
||||
cy.get(".version-section .page-action button")
|
||||
.contains("Update")
|
||||
.click({ force: true })
|
||||
|
||||
cy.intercept("POST", "**/applications/**/client/update").as(
|
||||
"updateVersion"
|
||||
)
|
||||
cy.get(".spectrum-Modal.is-open button")
|
||||
.contains("Update")
|
||||
.click({ force: true })
|
||||
|
||||
cy.wait("@updateVersion")
|
||||
.its("response.statusCode")
|
||||
.should("eq", 200)
|
||||
.then(() => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Tabs-item")
|
||||
.contains("Overview")
|
||||
.click({ force: true })
|
||||
cy.get(".overview-tab [data-cy='app-version']").within(() => {
|
||||
cy.get(".spectrum-Heading").contains(clientPackage.version)
|
||||
cy.get(".version-status").contains("You're running the latest!")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should allow editing of the app details.", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Tabs-item").contains("Settings").click()
|
||||
cy.get(".spectrum-Tabs-item.is-selected").contains("Settings")
|
||||
cy.get(".settings-tab").should("be.visible")
|
||||
|
||||
cy.get(".details-section .page-action button")
|
||||
.contains("Edit")
|
||||
.click({ force: true })
|
||||
cy.updateAppName("sample name")
|
||||
|
||||
//publish and check its disabled
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
cy.wait(500)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Edit")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
|
||||
cy.get(".toprightnav button.spectrum-Button")
|
||||
.contains("Publish")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Modal [data-cy='deploy-app-modal']")
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Button").contains("Publish").click({ force: true })
|
||||
cy.wait(1000)
|
||||
})
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 10000 })
|
||||
cy.get(".appTable .app-row-actions button", { timeout: 5000 })
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Tabs-item").contains("Settings").click()
|
||||
cy.get(".spectrum-Tabs-item.is-selected").contains("Settings")
|
||||
|
||||
cy.get(".details-section .page-action .spectrum-Button").scrollIntoView()
|
||||
cy.get(".details-section .page-action .spectrum-Button", { timeout: 1000 }).should(
|
||||
"be.disabled"
|
||||
)
|
||||
})
|
||||
|
||||
xit("Should allow copying of the published application Id", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Button").contains("Edit").click({ force: true })
|
||||
})
|
||||
|
||||
cy.publishApp("sample-name")
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".app-overview-actions-icon > .icon").click({ force: true })
|
||||
|
||||
cy.get("[data-cy='app-overview-menu-popover']")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Menu-item")
|
||||
.contains("Copy App ID")
|
||||
.click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Toast-content")
|
||||
.contains("App ID copied to clipboard.")
|
||||
.should("be.visible")
|
||||
})
|
||||
|
||||
xit("Should allow unpublishing of the application via the Unpublish link", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
|
||||
cy.get(`[data-cy="app-status"]`).within(() => {
|
||||
cy.contains("Unpublish").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get("[data-cy='unpublish-modal']")
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(".confirm-wrap button").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(".overview-tab [data-cy='app-status']").within(() => {
|
||||
cy.get(".status-display").contains("Unpublished")
|
||||
cy.get(".status-display .icon svg[aria-label='GlobeStrike']")
|
||||
.should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should allow deleting of the application", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.get(".appTable .app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
cy.get(".app-overview-actions-icon > .icon").click({ force: true })
|
||||
|
||||
cy.get("[data-cy='app-overview-menu-popover']")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Menu-item")
|
||||
.contains("Delete")
|
||||
.click({ force: true })
|
||||
cy.wait(500)
|
||||
})
|
||||
|
||||
//The test application was renamed earlier in the spec
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get("input").type("sample name")
|
||||
cy.get(".spectrum-Button--warning").click()
|
||||
})
|
||||
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq("/builder/portal/apps")
|
||||
})
|
||||
|
||||
cy.get(".appTable").should("not.exist")
|
||||
|
||||
cy.get(".welcome .container h1").contains("Let's create your first app!")
|
||||
})
|
||||
|
||||
after(() => {
|
||||
cy.deleteAllApps()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,108 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
import { APP_TABLE_APP_NAME, DEPLOY_SUCCESS_MODAL } from "../support/interact";
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['all'], () => {
|
||||
xcontext("Publish Application Workflow", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.deleteAllApps()
|
||||
cy.createApp("Cypress Tests", false)
|
||||
})
|
||||
|
||||
xit("Should reflect the unpublished status correctly", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
|
||||
cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0)
|
||||
.within(() => {
|
||||
cy.contains("Unpublished")
|
||||
cy.get(interact.GLOBESTRIKE).should("exist")
|
||||
})
|
||||
|
||||
cy.get(interact.APP_TABLE_ROW_ACTION).eq(0)
|
||||
.within(() => {
|
||||
cy.get(interact.SPECTRUM_BUTTON_TEMPLATE).contains("Edit").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(interact.DEPLOYMENT_TOP_NAV_GLOBESTRIKE).should("exist")
|
||||
cy.get(interact.DEPLOYMENT_TOP_GLOBE).should("not.exist")
|
||||
})
|
||||
|
||||
xit("Should publish an application and correctly reflect that", () => {
|
||||
//Assuming the previous test was run and the unpublished app is open in edit mode.
|
||||
cy.get(interact.TOPRIGHTNAV_BUTTON_SPECTRUM).contains("Publish").click({ force: true })
|
||||
|
||||
cy.get(interact.DEPLOY_APP_MODAL).should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force: true })
|
||||
});
|
||||
|
||||
//Verify that the app url is presented correctly to the user
|
||||
cy.get(interact.DEPLOY_SUCCESS_MODAL, { timeout: 1000 })
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
let appUrl = Cypress.config().baseUrl + '/app/cypress-tests'
|
||||
cy.get(interact.DEPLOY_APP_URL_INPUT).should('have.value', appUrl)
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Done").click({ force: true })
|
||||
})
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
|
||||
cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0)
|
||||
.within(() => {
|
||||
cy.contains("Published")
|
||||
cy.get(interact.GLOBE).should("exist")
|
||||
})
|
||||
|
||||
cy.get(interact.APP_TABLE_ROW_ACTION).eq(0)
|
||||
.within(() => {
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Manage")
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Edit").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(interact.DEPLOYMENT_TOP_GLOBE).should("exist").click({ force: true })
|
||||
|
||||
cy.get(interact.PUBLISH_POPOVER_MENU).should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(interact.PUBLISH_POPOVER_ACTION).should("exist")
|
||||
cy.get("button").contains("View app").should("exist")
|
||||
cy.get(interact.PUBLISH_POPOVER_MESSAGE).should("have.text", "Last published a few seconds ago")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Should unpublish an application using the link and reflect the status change", () => {
|
||||
//Assuming the previous test app exists and is published
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
|
||||
cy.get(interact.APP_TABLE_STATUS).eq(0)
|
||||
.within(() => {
|
||||
cy.contains("Published")
|
||||
cy.get("svg[aria-label='Globe']").should("exist")
|
||||
})
|
||||
|
||||
cy.get(interact.APP_TABLE).eq(0)
|
||||
.within(() => {
|
||||
cy.get(interact.APP_TABLE_APP_NAME).click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(interact.DEPLOYMENT_TOP_GLOBE).should("exist").click({ force: true })
|
||||
|
||||
cy.get("[data-cy='publish-popover-menu']")
|
||||
.within(() => {
|
||||
cy.get(interact.PUBLISH_POPOVER_ACTION).click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(interact.UNPUBLISH_MODAL).should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(interact.CONFIRM_WRAP_BUTTON).click({ force: true }
|
||||
)
|
||||
})
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 6000 })
|
||||
cy.wait(500)
|
||||
cy.get(interact.APP_TABLE_STATUS, { timeout: 10000 }).eq(0).contains("Unpublished")
|
||||
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,101 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['smoke', 'all'], () => {
|
||||
xcontext("Auto Screens UI", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.deleteAllApps()
|
||||
})
|
||||
|
||||
it("should disable the autogenerated screen options if no sources are available", () => {
|
||||
cy.createApp("First Test App", false)
|
||||
cy.closeModal();
|
||||
|
||||
cy.navigateToAutogeneratedModal()
|
||||
cy.get(interact.CONFIRM_WRAP_SPE_BUTTON).should('be.disabled')
|
||||
|
||||
cy.deleteAllApps()
|
||||
});
|
||||
|
||||
it("should not display incompatible sources", () => {
|
||||
cy.createApp("Test App")
|
||||
|
||||
cy.selectExternalDatasource("REST")
|
||||
cy.selectExternalDatasource("S3")
|
||||
cy.get(interact.SPECTRUM_MODAL).within(() => {
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Save and continue to query").click({ force : true })
|
||||
})
|
||||
|
||||
cy.navigateToAutogeneratedModal()
|
||||
|
||||
cy.get(interact.DATA_SOURCE_ENTRY).should('have.length', 1)
|
||||
cy.get(interact.DATA_SOURCE_ENTRY)
|
||||
|
||||
cy.deleteAllApps()
|
||||
});
|
||||
|
||||
it("should generate internal table screens", () => {
|
||||
cy.createTestApp()
|
||||
// Create Autogenerated screens from the internal table
|
||||
cy.createDatasourceScreen(["Cypress Tests"])
|
||||
// Confirm screens have been auto generated
|
||||
cy.get(interact.BODY).should('contain', "cypress-tests")
|
||||
.and('contain', 'cypress-tests/:id')
|
||||
.and('contain', 'cypress-tests/new/row')
|
||||
})
|
||||
|
||||
it("should generate multiple internal table screens at once", () => {
|
||||
const initialTable = "Cypress Tests"
|
||||
const secondTable = "Table Two"
|
||||
// Create a second internal table
|
||||
cy.createTable(secondTable)
|
||||
// Create Autogenerated screens from the internal tables
|
||||
cy.createDatasourceScreen([initialTable, secondTable])
|
||||
// Confirm screens have been auto generated
|
||||
// Previously generated tables are suffixed with numbers - as expected
|
||||
cy.wait(1000)
|
||||
cy.get(interact.BODY).should('contain', 'cypress-tests-2')
|
||||
.and('contain', 'cypress-tests-2/:id')
|
||||
.and('contain', 'cypress-tests-2/new/row')
|
||||
.and('contain', 'table-two')
|
||||
.and('contain', 'table-two/:id')
|
||||
.and('contain', 'table-two/new/row')
|
||||
})
|
||||
|
||||
it("should generate multiple internal table screens with the same screen access level", () => {
|
||||
//The tables created in the previous step still exist
|
||||
cy.createTable("Table Three")
|
||||
cy.createTable("Table Four")
|
||||
cy.createDatasourceScreen(["Table Three", "Table Four"], "Admin")
|
||||
|
||||
// Filter screens to Admin
|
||||
cy.filterScreensAccessLevel('Admin')
|
||||
|
||||
cy.get(interact.BODY).should('contain', 'table-three')
|
||||
.and('contain', 'table-three/:id')
|
||||
.and('contain', 'table-three/new/row')
|
||||
.and('contain', 'table-four')
|
||||
.and('contain', 'table-four/:id')
|
||||
.and('contain', 'table-four/new/row')
|
||||
.and('not.contain', 'table-two')
|
||||
.and('not.contain', 'cypress-tests')
|
||||
})
|
||||
|
||||
if (Cypress.env("TEST_ENV")) {
|
||||
it("should generate datasource screens", () => {
|
||||
// Using MySQL datasource for testing this
|
||||
const datasource = "MySQL"
|
||||
// Select & configure MySQL datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.addDatasourceConfig(datasource)
|
||||
// Create Autogenerated screens from a MySQL table - MySQL contains books table
|
||||
cy.createDatasourceScreen(["books"])
|
||||
|
||||
cy.get(interact.BODY).should('contain', 'books')
|
||||
.and('contain', 'books/:id')
|
||||
.and('contain', 'books/new/row')
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,235 +0,0 @@
|
|||
import filterTests from '../support/filterTests'
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['smoke', 'all'], () => {
|
||||
context("Create an Application", () => {
|
||||
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.deleteAllApps()
|
||||
})
|
||||
|
||||
if (!(Cypress.env("TEST_ENV"))) {
|
||||
it.skip("should show the new user UI/UX", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder/portal/apps/create`, { timeout: 5000 }) //added /portal/apps/create
|
||||
cy.wait(1000)
|
||||
cy.get(interact.CREATE_APP_BUTTON, { timeout: 10000 }).contains('Start from scratch').should("exist")
|
||||
|
||||
cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist")
|
||||
cy.get(interact.TEMPLATE_CATEGORY).should("exist")
|
||||
|
||||
cy.get(interact.APP_TABLE).should("not.exist")
|
||||
})
|
||||
}
|
||||
|
||||
xit("should provide filterable templates", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
cy.wait(500)
|
||||
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
|
||||
.its("body")
|
||||
.then(val => {
|
||||
if (val.length > 0) {
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("View Templates").click({ force: true })
|
||||
}
|
||||
})
|
||||
|
||||
cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist")
|
||||
cy.get(interact.TEMPLATE_CATEGORY).should("exist")
|
||||
|
||||
cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).its('length').should('be.gt', 1)
|
||||
cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).its('length').should('be.gt', 2)
|
||||
|
||||
cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).eq(1).click()
|
||||
cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).should('have.length', 1)
|
||||
|
||||
cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).eq(0).click()
|
||||
cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).its('length').should('be.gt', 1)
|
||||
})
|
||||
|
||||
it("should enforce a valid url before submission", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 10000 })
|
||||
|
||||
// Start create app process. If apps already exist, click second button
|
||||
cy.wait(1000)
|
||||
cy.get(interact.CREATE_APP_BUTTON, { timeout: 3000 }).click({ force: true })
|
||||
|
||||
const appName = "Cypress Tests"
|
||||
cy.get(interact.SPECTRUM_MODAL).within(() => {
|
||||
|
||||
cy.get(interact.APP_NAME_INPUT).eq(0).should('have.focus')
|
||||
|
||||
//Auto fill
|
||||
cy.get(interact.APP_NAME_INPUT).eq(0).clear()
|
||||
cy.get(interact.APP_NAME_INPUT).eq(0).type(appName).should("have.value", appName).blur()
|
||||
cy.get(interact.APP_NAME_INPUT).eq(1).should("have.value", "/cypress-tests")
|
||||
cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('not.be.disabled')
|
||||
|
||||
//Empty the app url - disabled create
|
||||
cy.get(interact.APP_NAME_INPUT).eq(1).clear().blur()
|
||||
cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('be.disabled')
|
||||
|
||||
//Invalid url
|
||||
cy.get(interact.APP_NAME_INPUT).eq(1).type("/new app-url").blur()
|
||||
cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('be.disabled')
|
||||
|
||||
//Specifically alter the url
|
||||
cy.get(interact.APP_NAME_INPUT).eq(1).clear()
|
||||
cy.get(interact.APP_NAME_INPUT).eq(1).type("another-app-name").blur()
|
||||
cy.get(interact.APP_NAME_INPUT).eq(1).should("have.value", "/another-app-name")
|
||||
cy.get(interact.APP_NAME_INPUT).eq(0).should("have.value", appName)
|
||||
cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('not.be.disabled')
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
it.skip("should create the first application from scratch", () => {
|
||||
const appName = "Cypress Tests"
|
||||
cy.createApp(appName, false)
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
|
||||
cy.applicationInAppTable(appName)
|
||||
cy.deleteApp(appName)
|
||||
})
|
||||
|
||||
it.skip("should create the first application from scratch with a default name", () => {
|
||||
cy.updateUserInformation("", "")
|
||||
cy.createApp("", false)
|
||||
cy.applicationInAppTable("My app")
|
||||
cy.deleteApp("My app")
|
||||
})
|
||||
|
||||
it("should create the first application from scratch, using the users first name as the default app name", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
|
||||
cy.updateUserInformation("Ted", "Userman")
|
||||
|
||||
cy.createApp("", false)
|
||||
cy.applicationInAppTable("Teds app")
|
||||
cy.deleteApp("Teds app")
|
||||
|
||||
// Accomodate names that end in 'S'
|
||||
cy.updateUserInformation("Chris", "Userman")
|
||||
|
||||
cy.createApp("", false)
|
||||
cy.applicationInAppTable("Chris app")
|
||||
cy.deleteApp("Chris app")
|
||||
|
||||
cy.updateUserInformation("", "")
|
||||
})
|
||||
|
||||
it("should create an application from an export", () => {
|
||||
const exportedApp = 'cypress/fixtures/exported-app.txt'
|
||||
|
||||
cy.importApp(exportedApp, "")
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 2000 })
|
||||
cy.applicationInAppTable("My app")
|
||||
cy.get(".app-table .name").eq(0).click()
|
||||
cy.closeModal()
|
||||
cy.get(`[aria-label="ShowMenu"]`).click()
|
||||
cy.get(".spectrum-Menu").within(() => {
|
||||
cy.contains("Overview").click()
|
||||
})
|
||||
cy.get(".app-overview-actions-icon").within(() => {
|
||||
cy.get(".spectrum-Icon").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Menu").contains("Delete").click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get("input").type("My app")
|
||||
})
|
||||
cy.get(".spectrum-Button--warning").click()
|
||||
})
|
||||
|
||||
it("should create an application from an export, using the users first name as the default app name", () => {
|
||||
const exportedApp = 'cypress/fixtures/exported-app.txt'
|
||||
|
||||
cy.updateUserInformation("Ted", "Userman")
|
||||
cy.importApp(exportedApp, "")
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.applicationInAppTable("Teds app")
|
||||
cy.get(".app-table .name").eq(0).click()
|
||||
cy.closeModal()
|
||||
cy.get(`[aria-label="ShowMenu"]`).click()
|
||||
cy.get(".spectrum-Menu").within(() => {
|
||||
cy.contains("Overview").click()
|
||||
})
|
||||
cy.get(".app-overview-actions-icon").within(() => {
|
||||
cy.get(".spectrum-Icon").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Menu").contains("Delete").click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get("input").type("Teds app")
|
||||
})
|
||||
cy.get(".spectrum-Button--warning").click()
|
||||
cy.updateUserInformation("", "")
|
||||
})
|
||||
|
||||
xit("should generate the first application from a template", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.wait(500)
|
||||
|
||||
// Navigate to Create new app section if apps already exist
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
|
||||
.its("body")
|
||||
.then(val => {
|
||||
if (val.length > 0) {
|
||||
cy.get(interact.CREATE_APP_BUTTON).click({ force: true })
|
||||
}
|
||||
})
|
||||
|
||||
cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist")
|
||||
cy.get(interact.TEMPLATE_CATEGORY).should("exist")
|
||||
|
||||
// Select template
|
||||
cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).eq(0).within(() => {
|
||||
const card = cy.get('.template-card').eq(0).should("exist");
|
||||
const cardOverlay = card.get('.template-thumbnail-action-overlay').should("exist")
|
||||
cardOverlay.invoke("show")
|
||||
cardOverlay.get("button").contains("Use template").should("exist").click({ force: true })
|
||||
})
|
||||
|
||||
// CMD Create app from theme card
|
||||
cy.get(".spectrum-Modal").should('be.visible')
|
||||
|
||||
const templateName = cy.get(".spectrum-Modal .template-thumbnail-text")
|
||||
templateName.invoke('text')
|
||||
.then(templateNameText => {
|
||||
const templateNameParsed = "/" + templateNameText.toLowerCase().replace(/\s+/g, "-")
|
||||
cy.get(interact.SPECTRUM_MODAL_INPUT).eq(0).should("have.value", templateNameText)
|
||||
cy.get(interact.SPECTRUM_MODAL_INPUT).eq(1).should("have.value", templateNameParsed)
|
||||
|
||||
cy.get(".spectrum-Modal .spectrum-ButtonGroup").contains("Create app").click()
|
||||
cy.wait(5000)
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
cy.wait(2000)
|
||||
|
||||
cy.applicationInAppTable(templateNameText)
|
||||
cy.deleteApp(templateNameText)
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
it("should display a second application and app filtering", () => {
|
||||
// Create first app
|
||||
const appName = "Cypress Tests"
|
||||
cy.createApp(appName)
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
|
||||
// Create second app
|
||||
const secondAppName = "Second App Demo"
|
||||
cy.createApp(secondAppName)
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||
|
||||
//Both applications should exist and be searchable
|
||||
cy.searchForApplication(appName)
|
||||
cy.searchForApplication(secondAppName)
|
||||
|
||||
cy.deleteApp(secondAppName)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
|
@ -1,64 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['smoke', 'all'], () => {
|
||||
xcontext("Create a automation", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
xit("should create a automation", () => {
|
||||
cy.createTestTableWithData()
|
||||
cy.wait(2000)
|
||||
cy.contains("Automate").click()
|
||||
cy.get(interact.SPECTRUM_BUTTON_TEMPLATE).contains("Add automation").click({ force: true })
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.get("input").type("Add Row")
|
||||
cy.contains("Row Created").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_BUTTON_CTA, { timeout: 500 }).click()
|
||||
})
|
||||
|
||||
// Setup trigger
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL).click()
|
||||
cy.wait(500)
|
||||
cy.contains("dog").click()
|
||||
// Create action
|
||||
cy.get('[aria-label="AddCircle"]', { timeout: 2000 }).click()
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.wait(1000)
|
||||
cy.contains("Create Row").trigger('mouseover').click().click()
|
||||
cy.get(interact.SPECTRUM_BUTTON_CTA).click()
|
||||
})
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL).eq(1).click()
|
||||
cy.contains("dog").click()
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
|
||||
.first()
|
||||
.type("{{ trigger.row.name }}", { parseSpecialCharSequences: false })
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
|
||||
.eq(1)
|
||||
.type("11")
|
||||
cy.contains("Finish and test automation").click()
|
||||
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL, { timeout: 1000 }).click()
|
||||
cy.contains("dog").click()
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 })
|
||||
.first()
|
||||
.type("automationGoodboy")
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
|
||||
.eq(1)
|
||||
.type("11")
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
|
||||
.eq(2)
|
||||
.type("123456")
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
|
||||
.eq(3)
|
||||
.type("123456")
|
||||
cy.contains("Test").click()
|
||||
})
|
||||
cy.contains("Data").click()
|
||||
cy.contains("automationGoodboy")
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,66 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
|
||||
filterTests(['smoke', 'all'], () => {
|
||||
context("Create Bindings", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
cy.navigateToFrontend()
|
||||
})
|
||||
|
||||
it("should add a current user binding", () => {
|
||||
cy.searchAndAddComponent("Paragraph").then(componentId => {
|
||||
addSettingBinding("text", ["Current User", "_id"], "Current User._id")
|
||||
})
|
||||
cy.deleteComponentByName("New Paragraph")
|
||||
})
|
||||
|
||||
it("should handle an invalid binding", () => {
|
||||
cy.searchAndAddComponent("Paragraph").then(componentId => {
|
||||
// Cypress needs to escape curly brackets
|
||||
cy.get("[data-cy=setting-text] input")
|
||||
.type("{{}{{}{{} Current User._id {}}{}}")
|
||||
.blur()
|
||||
cy.getComponent(componentId).should("have.text", "{{{ [user].[_id] }}")
|
||||
cy.deleteComponentByName("New Paragraph")
|
||||
})
|
||||
})
|
||||
|
||||
xit("should add a URL param binding", () => {
|
||||
const paramName = "foo"
|
||||
cy.createScreen(`/test/:${paramName}`)
|
||||
cy.searchAndAddComponent("Paragraph").then(componentId => {
|
||||
addSettingBinding("text", ["URL", paramName], `URL.${paramName}`)
|
||||
// The builder preview pages don't have a real URL, so all we can do
|
||||
// is check that we were able to bind to the property, and that the
|
||||
// component exists on the page
|
||||
cy.getComponent(componentId).should("have.text", "New Paragraph")
|
||||
})
|
||||
})
|
||||
|
||||
it("should add a binding with a handlebars helper", () => {
|
||||
cy.searchAndAddComponent("Paragraph").then(componentId => {
|
||||
// Cypress needs to escape curly brackets
|
||||
cy.get("[data-cy=setting-text] input")
|
||||
.type("{{}{{} add 1 2 {}}{}}")
|
||||
.blur()
|
||||
cy.getComponent(componentId).should("have.text", "3")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const addSettingBinding = (setting, bindingCategories, bindingText, clickOption = true) => {
|
||||
cy.get(`[data-cy="setting-${setting}"] [data-cy=text-binding-button]`).click()
|
||||
cy.get(".category-list li").contains(bindingCategories[0])
|
||||
cy.get(".drawer").within(() => {
|
||||
if (clickOption) {
|
||||
cy.get(".category-list li").contains(bindingCategories[0]).click()
|
||||
cy.get("li.binding").contains(bindingCategories[1]).click()
|
||||
cy.get("textarea").should("have.value", `{{ ${bindingText} }}`)
|
||||
} else {
|
||||
cy.get("textarea").type(bindingText)
|
||||
}
|
||||
cy.contains("Save").click()
|
||||
})
|
||||
}
|
||||
})
|
|
@ -1,275 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require("../support/interact")
|
||||
|
||||
filterTests(["all"], () => {
|
||||
xcontext("Create Components", () => {
|
||||
let headlineId
|
||||
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
cy.createTable("dog")
|
||||
cy.addColumn("dog", "name", "Text")
|
||||
cy.addColumn("dog", "age", "Number")
|
||||
cy.addColumn("dog", "breed", "Options")
|
||||
|
||||
cy.navigateToFrontend()
|
||||
cy.wait(1000) //allow the iframe some wiggle room
|
||||
})
|
||||
|
||||
//Use the tree to delete a selected component
|
||||
const deleteSelectedComponent = () => {
|
||||
cy.get(
|
||||
".nav-item.selected .actions > div > .icon"
|
||||
).click({
|
||||
force: true,
|
||||
})
|
||||
cy.get(".spectrum-Popover.is-open li").contains("Delete").click()
|
||||
cy.get(".spectrum-Modal button").contains("Delete Component").click({
|
||||
force: true,
|
||||
})
|
||||
}
|
||||
|
||||
it("should add a container", () => {
|
||||
cy.searchAndAddComponent("Container").then(componentId => {
|
||||
cy.getComponent(componentId).should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
it("should add a headline", () => {
|
||||
cy.searchAndAddComponent("Headline").then(componentId => {
|
||||
headlineId = componentId
|
||||
cy.getComponent(headlineId).should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
it("should change the text of the headline", () => {
|
||||
const text = "Lorem ipsum dolor sit amet."
|
||||
cy.get("[data-cy=setting-text] input").type(text).blur()
|
||||
cy.getComponent(headlineId).should("have.text", text)
|
||||
})
|
||||
|
||||
it("should change the size of the headline", () => {
|
||||
cy.get("[data-cy=setting-size]").scrollIntoView().click()
|
||||
cy.get("[data-cy=setting-size]").within(() => {
|
||||
cy.get(".spectrum-Form-item li.spectrum-Menu-item")
|
||||
.contains("3XL")
|
||||
.click()
|
||||
})
|
||||
|
||||
cy.getComponent(headlineId).within(() => {
|
||||
cy.get(".spectrum-Heading").should("have.css", "font-size", "60px")
|
||||
})
|
||||
})
|
||||
|
||||
it("should create a form and reset to match schema", () => {
|
||||
cy.searchAndAddComponent("Form").then(() => {
|
||||
cy.get("[data-cy=setting-dataSource]").contains("Custom").click()
|
||||
cy.get(interact.DROPDOWN).contains("dog").click()
|
||||
cy.wait(500)
|
||||
cy.searchAndAddComponent("Field Group").then(fieldGroupId => {
|
||||
cy.contains("Update form fields").click()
|
||||
cy.get(".spectrum-Modal")
|
||||
.get(".confirm-wrap .spectrum-Button")
|
||||
.click()
|
||||
cy.wait(500)
|
||||
cy.getComponent(fieldGroupId).within(() => {
|
||||
cy.contains("name").should("exist")
|
||||
cy.contains("age").should("exist")
|
||||
cy.contains("breed").should("exist")
|
||||
// cy.contains("image").should("exist")
|
||||
})
|
||||
cy.getComponent(fieldGroupId).find("input").should("have.length", 2)
|
||||
cy.getComponent(fieldGroupId)
|
||||
.find(interact.SPECTRUM_PICKER)
|
||||
.should("have.length", 1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("deletes a component", () => {
|
||||
cy.searchAndAddComponent("Paragraph").then(componentId => {
|
||||
cy.get("[data-cy=setting-_instanceName] input").type(componentId).blur()
|
||||
cy.get(
|
||||
".nav-item.selected .actions > div > .icon"
|
||||
).click({
|
||||
force: true,
|
||||
})
|
||||
cy.get(".spectrum-Popover.is-open li").contains("Delete").click()
|
||||
cy.get(".spectrum-Modal button").contains("Delete Component").click({
|
||||
force: true,
|
||||
})
|
||||
cy.getComponent(componentId).should("not.exist")
|
||||
})
|
||||
})
|
||||
|
||||
it("should clear the iframe place holder when a form field has been set", () => {
|
||||
cy.searchAndAddComponent("Form").then(formId => {
|
||||
//For deletion
|
||||
cy.get("[data-cy=setting-_instanceName] input")
|
||||
.clear()
|
||||
.type(formId)
|
||||
.blur()
|
||||
cy.get("[data-cy=setting-dataSource]").contains("Custom").click()
|
||||
cy.get(".dropdown").contains("dog").click()
|
||||
|
||||
const fieldTypeToColumnName = {
|
||||
"Text Field": "name",
|
||||
"Number Field": "age",
|
||||
"Options Picker": "breed",
|
||||
}
|
||||
|
||||
const componentTypeLabels = Object.keys(fieldTypeToColumnName)
|
||||
|
||||
const testFieldFocusOnCreate = componentLabel => {
|
||||
cy.log("Adding: " + componentLabel)
|
||||
return cy.searchAndAddComponent(componentLabel).then(componentId => {
|
||||
cy.get("[data-cy=setting-field] button.spectrum-Picker").click()
|
||||
|
||||
//Click the first appropriate field. They are filtered by type
|
||||
cy.get(
|
||||
"[data-cy=setting-field] .spectrum-Popover.is-open li.spectrum-Menu-item"
|
||||
)
|
||||
.contains(fieldTypeToColumnName[componentLabel])
|
||||
.click()
|
||||
cy.wait(500)
|
||||
cy.getComponent(componentId)
|
||||
.find(".component-placeholder")
|
||||
.should("not.exist")
|
||||
})
|
||||
}
|
||||
|
||||
cy.wait(500)
|
||||
cy.wrap(componentTypeLabels)
|
||||
.each(label => {
|
||||
return testFieldFocusOnCreate(label)
|
||||
})
|
||||
.then(() => {
|
||||
cy.get(".nav-item")
|
||||
.contains(formId)
|
||||
.click({ force: true })
|
||||
deleteSelectedComponent()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should populate the provider for charts with a data provider in its path", () => {
|
||||
cy.searchAndAddComponent("Data Provider").then(providerId => {
|
||||
//For deletion
|
||||
cy.get("[data-cy=setting-_instanceName] input")
|
||||
.clear()
|
||||
.type(providerId)
|
||||
.blur()
|
||||
cy.get("[data-cy=setting-dataSource]")
|
||||
.contains("Choose an option")
|
||||
.click()
|
||||
cy.get(`[data-cy=dataSource-popover-${providerId}] ul li`)
|
||||
.contains("dog")
|
||||
.click()
|
||||
|
||||
const chartTypeLabels = [
|
||||
"Bar Chart",
|
||||
"Line Chart",
|
||||
"Area Chart",
|
||||
"Pie Chart",
|
||||
"Donut Chart",
|
||||
"Candlestick Chart",
|
||||
]
|
||||
|
||||
const testFocusOnCreate = chartLabel => {
|
||||
cy.log("Adding: " + chartLabel)
|
||||
cy.searchAndAddComponent(chartLabel).then(componentId => {
|
||||
cy.get(
|
||||
"[data-cy=dataProvider-prop-control] .spectrum-Picker"
|
||||
).should("not.have.class", "is-focused")
|
||||
|
||||
// Pre populated.
|
||||
cy.get("[data-cy=dataProvider-prop-control] .spectrum-Picker-label")
|
||||
.contains(providerId)
|
||||
.should("exist")
|
||||
})
|
||||
}
|
||||
cy.wait(1000)
|
||||
cy.wrap(chartTypeLabels)
|
||||
.each(label => {
|
||||
return testFocusOnCreate(label)
|
||||
})
|
||||
.then(() => {
|
||||
cy.get(".nav-item")
|
||||
.contains(providerId)
|
||||
.click({ force: true })
|
||||
deleteSelectedComponent()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should replace the placeholder when a url is set on an image", () => {
|
||||
cy.searchAndAddComponent("Image").then(imageId => {
|
||||
cy.get("[data-cy=setting-_instanceName] input")
|
||||
.clear()
|
||||
.type(imageId)
|
||||
.blur()
|
||||
//return $("New Data Provider.Rows")[0]["Attachment"][0]["url"]
|
||||
//No minio, so just enter something local that will not reslove
|
||||
cy.get("[data-cy=url-prop-control] input[type=text]")
|
||||
.type("cypress/fixtures/ghost.png")
|
||||
.blur()
|
||||
cy.getComponent(imageId)
|
||||
.find(".component-placeholder")
|
||||
.should("not.exist")
|
||||
cy.getComponent(imageId).find(`img[alt=${imageId}]`).should("exist")
|
||||
cy.get(".nav-item")
|
||||
.contains(imageId)
|
||||
.click({ force: true })
|
||||
deleteSelectedComponent()
|
||||
})
|
||||
})
|
||||
|
||||
it("should add a markdown component.", () => {
|
||||
cy.searchAndAddComponent("Markdown Viewer").then(markdownId => {
|
||||
cy.get("[data-cy=setting-_instanceName] input")
|
||||
.clear()
|
||||
.type(markdownId)
|
||||
.blur()
|
||||
cy.get(
|
||||
"[data-cy=value-prop-control] input[type=text].spectrum-Textfield-input"
|
||||
)
|
||||
.type("# Hi")
|
||||
.blur()
|
||||
cy.getComponent(markdownId)
|
||||
.find(".component-placeholder")
|
||||
.should("not.exist")
|
||||
cy.getComponent(markdownId)
|
||||
.find(".editor-preview-full h1")
|
||||
.contains("Hi")
|
||||
cy.get(".nav-item")
|
||||
.contains(markdownId)
|
||||
.click({ force: true })
|
||||
deleteSelectedComponent()
|
||||
})
|
||||
})
|
||||
|
||||
it("should direct the user when adding an Icon component.", () => {
|
||||
cy.searchAndAddComponent("Icon").then(iconId => {
|
||||
cy.get("[data-cy=setting-_instanceName] input")
|
||||
.clear()
|
||||
.type(iconId)
|
||||
.blur()
|
||||
cy.get("[data-cy=icon-prop-control] .spectrum-ActionButton").click()
|
||||
cy.get("[data-cy=icon-popover].spectrum-Popover.is-open").within(() => {
|
||||
cy.get(".search-input input").type("save").blur()
|
||||
cy.get(".search-input button").click({ force: true })
|
||||
cy.get(".icon-area .icon-container").eq(0).click({ force: true })
|
||||
})
|
||||
cy.getComponent(iconId)
|
||||
.find(".component-placeholder")
|
||||
.should("not.exist")
|
||||
cy.getComponent(iconId).find("i.ri-save-fill").should("exist")
|
||||
cy.get(".nav-item")
|
||||
.contains(iconId)
|
||||
.click({ force: true })
|
||||
deleteSelectedComponent()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,54 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
xcontext("Screen Tests", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
cy.navigateToFrontend()
|
||||
})
|
||||
|
||||
it.skip("Should successfully create a screen", () => {
|
||||
cy.createScreen("test")
|
||||
cy.get(interact.BODY).within(() => {
|
||||
cy.contains("/test").should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
it("Should update the url", () => {
|
||||
cy.createScreen("test with spaces")
|
||||
cy.get(interact.BODY).within(() => {
|
||||
cy.contains("/test-with-spaces").should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
it.skip("should delete all screens then create first screen via button", () => {
|
||||
cy.deleteAllScreens()
|
||||
|
||||
cy.contains("Create first screen").click()
|
||||
cy.get(interact.BODY, { timeout: 2000 }).should('contain', '/home')
|
||||
})
|
||||
|
||||
it("Should create and filter screens by access level", () => {
|
||||
const accessLevels = ["Basic", "Admin", "Public", "Power"]
|
||||
|
||||
for (const access of accessLevels) {
|
||||
// Create screen with specified access level
|
||||
cy.createScreen(access, access)
|
||||
// Filter by access level and confirm screen visible
|
||||
cy.filterScreensAccessLevel(access)
|
||||
cy.get(interact.BODY).within(() => {
|
||||
cy.get(interact.NAV_ITEM).should('contain', access.toLowerCase())
|
||||
})
|
||||
}
|
||||
|
||||
// Filter by All screens - Confirm all screens visible
|
||||
cy.filterScreensAccessLevel("All screens")
|
||||
cy.get(interact.BODY).should('contain', accessLevels[0])
|
||||
.and('contain', accessLevels[1])
|
||||
.and('contain', accessLevels[2])
|
||||
.and('contain', accessLevels[3])
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,112 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
xcontext("Create a Table", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
it("should create a new Table", () => {
|
||||
cy.createTable("dog")
|
||||
// Check if Table exists
|
||||
cy.get(interact.TABLE_TITLE_H1, { timeout: 1000 }).should("have.text", "dog")
|
||||
})
|
||||
|
||||
it("adds a new column to the table", () => {
|
||||
cy.addColumn("dog", "name", "Text")
|
||||
cy.contains("name").should("be.visible")
|
||||
})
|
||||
|
||||
it("creates a row in the table", () => {
|
||||
cy.addRow(["Rover"])
|
||||
cy.contains("Rover").should("be.visible")
|
||||
})
|
||||
|
||||
it("updates a column on the table", () => {
|
||||
cy.get(interact.TABLE_TITLE).click()
|
||||
cy.get(interact.SPECTRUM_TABLE_EDIT).click()
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
|
||||
cy.get("input").eq(0).type("updated", { force: true })
|
||||
// Unset table display column
|
||||
cy.get(interact.SPECTRUM_SWITCH_INPUT).eq(1).click()
|
||||
cy.contains("Save Column").click()
|
||||
})
|
||||
cy.contains("nameupdated ").should("contain", "nameupdated")
|
||||
})
|
||||
|
||||
it("edits a row", () => {
|
||||
cy.contains("button", "Edit").click({ force: true })
|
||||
cy.wait(500)
|
||||
cy.get(interact.SPECTRUM_MODAL_INPUT).clear()
|
||||
cy.get(interact.SPECTRUM_MODAL_INPUT).type("Updated")
|
||||
cy.contains("Save").click()
|
||||
cy.contains("Updated").should("have.text", "Updated")
|
||||
})
|
||||
|
||||
it("deletes a row", () => {
|
||||
cy.get(interact.SPECTRUM_CHECKBOX_INPUT).check({ force: true })
|
||||
cy.contains("Delete 1 row").click()
|
||||
cy.get(interact.SPECTRUM_MODAL).contains("Delete").click()
|
||||
cy.contains("RoverUpdated").should("not.exist")
|
||||
})
|
||||
|
||||
if (Cypress.env("TEST_ENV")) {
|
||||
// No Pagination in CI - Test env only for the next two tests
|
||||
xit("Adds 15 rows and checks pagination", () => {
|
||||
// 10 rows per page, 15 rows should create 2 pages within table
|
||||
const totalRows = 16
|
||||
for (let i = 1; i < totalRows; i++) {
|
||||
cy.addRow([i])
|
||||
}
|
||||
cy.reload()
|
||||
cy.get(interact.SPECTRUM_PAGINATION, { timeout: 2000 }).within(() => {
|
||||
cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).click()
|
||||
})
|
||||
cy.get(interact.SPECTRUM_PAGINATION).within(() => {
|
||||
cy.get(interact.SPECTRUM_BODY_SECOND).contains("Page 2")
|
||||
})
|
||||
})
|
||||
|
||||
xit("Deletes rows and checks pagination", () => {
|
||||
// Delete rows, removing second page from table
|
||||
cy.get(interact.SPECTRUM_CHECKBOX_INPUT).check({ force: true })
|
||||
cy.get(interact.POPOVERS).within(() => {
|
||||
cy.get(interact.SPECTRUM_BUTTON).click({ force: true })
|
||||
})
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID).contains("Delete").click({ force: true })
|
||||
|
||||
// Confirm table only has one page
|
||||
cy.get(interact.SPECTRUM_PAGINATION, { timeout: 1000 }).within(() => {
|
||||
cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).should("not.be.enabled")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
it("deletes a column", () => {
|
||||
const columnName = "nameupdated"
|
||||
cy.get(interact.TABLE_TITLE).click()
|
||||
cy.get(interact.SPECTRUM_TABLE_EDIT).click()
|
||||
cy.contains("Delete").click()
|
||||
cy.get(interact.DELETE_COLUMN_CONFIRM).type(columnName)
|
||||
cy.contains("Delete Column").click()
|
||||
cy.contains("nameupdated").should("not.exist")
|
||||
})
|
||||
|
||||
it("deletes a table", () => {
|
||||
cy.get(interact.NAV_ITEM)
|
||||
.contains("dog")
|
||||
.parents(interact.NAV_ITEM)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get(interact.ACTION_SPECTRUM_ICON).click({ force: true })
|
||||
})
|
||||
cy.get(interact.SPECTRUM_MENU_CHILD2).click()
|
||||
cy.get(interact.DELETE_TABLE_CONFIRM).type("dog")
|
||||
cy.contains("Delete Table").click()
|
||||
cy.contains("dog").should("not.exist")
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,161 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['smoke', 'all'], () => {
|
||||
xcontext("Create a View", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
cy.createTable("data")
|
||||
cy.addColumn("data", "group", "Text")
|
||||
cy.addColumn("data", "age", "Number")
|
||||
cy.addColumn("data", "rating", "Number")
|
||||
|
||||
// 6 Rows
|
||||
cy.addRow(["Students", 25, 1])
|
||||
cy.addRow(["Students", 20, 3])
|
||||
cy.addRow(["Students", 18, 6])
|
||||
cy.addRow(["Students", 25, 2])
|
||||
cy.addRow(["Teachers", 49, 5])
|
||||
cy.addRow(["Teachers", 36, 3])
|
||||
})
|
||||
|
||||
xit("creates a view", () => {
|
||||
cy.contains("Create view").click()
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.get("input").type("Test View")
|
||||
cy.get("button").contains("Create View").click({ force: true })
|
||||
})
|
||||
cy.contains(interact.TABLE_TITLE_H1, "Test View", { timeout: 10000 })
|
||||
cy.get(".table-wrapper").within(() => {
|
||||
cy.get(interact.TITLE).then($headers => {
|
||||
expect($headers).to.have.length(3)
|
||||
const headers = Array.from($headers).map(header =>
|
||||
header.textContent.trim()
|
||||
)
|
||||
expect(removeSpacing(headers)).to.deep.eq(["group", "age", "rating"])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
xit("filters the view by age over 10", () => {
|
||||
cy.contains("Filter").click()
|
||||
cy.contains("Add Filter").click()
|
||||
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL).eq(0).click()
|
||||
cy.contains("age").click({ force: true })
|
||||
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL).eq(1).click()
|
||||
cy.contains("More Than").click({ force: true })
|
||||
|
||||
cy.get("input").type(18)
|
||||
cy.contains("Save").click()
|
||||
})
|
||||
|
||||
cy.get(interact.SPECTRUM_TABLE_ROW).get($values => {
|
||||
expect($values).to.have.length(5)
|
||||
})
|
||||
})
|
||||
|
||||
xit("creates a stats calculation view based on age", () => {
|
||||
cy.wait(1000)
|
||||
cy.contains("Calculate").click()
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL).eq(0).click()
|
||||
cy.contains("Statistics").click()
|
||||
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL).eq(1).click()
|
||||
cy.contains("age").click({ force: true })
|
||||
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Save").click({ force: true })
|
||||
})
|
||||
|
||||
cy.wait(1000)
|
||||
cy.get(".table-wrapper").within(() => {
|
||||
cy.get(interact.TITLE).then($headers => {
|
||||
expect($headers).to.have.length(7)
|
||||
const headers = Array.from($headers).map(header =>
|
||||
header.textContent.trim()
|
||||
)
|
||||
expect(removeSpacing(headers)).to.deep.eq([
|
||||
"field",
|
||||
"sum",
|
||||
"min",
|
||||
"max",
|
||||
"count",
|
||||
"sumsqr",
|
||||
"avg",
|
||||
])
|
||||
})
|
||||
})
|
||||
cy.get(interact.SPECTRUM_TABLE_CELL).then($values => {
|
||||
let values = Array.from($values).map(header => header.textContent.trim())
|
||||
expect(values).to.deep.eq(["age", "155", "20", "49", "5", "5347", "31"])
|
||||
})
|
||||
})
|
||||
|
||||
xit("groups the view by group", () => {
|
||||
cy.contains("Group by").click()
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.get(interact.SPECTRUM_PICKER_LABEL).eq(0).click()
|
||||
cy.contains("group").click()
|
||||
cy.contains("Save").click()
|
||||
})
|
||||
cy.wait(1000)
|
||||
cy.contains("Students").should("be.visible")
|
||||
cy.contains("Teachers").should("be.visible")
|
||||
|
||||
cy.get(interact.SPECTRUM_TABLE_CELL).then($values => {
|
||||
let values = Array.from($values).map(header => header.textContent.trim())
|
||||
expect(values).to.deep.eq([
|
||||
"Students",
|
||||
"70",
|
||||
"20",
|
||||
"25",
|
||||
"3",
|
||||
"1650",
|
||||
"23.333333333333332",
|
||||
"Teachers",
|
||||
"85",
|
||||
"36",
|
||||
"49",
|
||||
"2",
|
||||
"3697",
|
||||
"42.5",
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
xit("renames a view", () => {
|
||||
cy.contains(interact.NAV_ITEM, "Test View")
|
||||
.find(".actions .icon.open-popover")
|
||||
.click({ force: true })
|
||||
cy.get(interact.SPECTRUM_MENU_ITEM_LABEL).contains("Edit").click()
|
||||
cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
|
||||
cy.get("input").type(" Updated")
|
||||
cy.contains("Save").click()
|
||||
})
|
||||
cy.wait(1000)
|
||||
cy.contains("Test View Updated").should("be.visible")
|
||||
})
|
||||
|
||||
it("deletes a view", () => {
|
||||
cy.contains(interact.NAV_ITEM, "Test View Updated")
|
||||
.find(".actions .icon.open-popover")
|
||||
.click({ force: true })
|
||||
cy.contains("Delete").click()
|
||||
cy.contains("Delete View").click()
|
||||
cy.wait(500)
|
||||
cy.contains("TestView Updated").should("not.exist")
|
||||
})
|
||||
})
|
||||
|
||||
function removeSpacing(headers) {
|
||||
let newHeaders = []
|
||||
for (let header of headers) {
|
||||
newHeaders.push(header.replace(/\s\s+/g, " "))
|
||||
}
|
||||
return newHeaders
|
||||
}
|
||||
})
|
|
@ -1,86 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
|
||||
filterTests(['all'], () => {
|
||||
xcontext("Custom Theming Properties", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
cy.navigateToFrontend()
|
||||
})
|
||||
|
||||
/* Default Values:
|
||||
Button roundness = Large
|
||||
Accent colour = Blue 600
|
||||
Accent colour (hover) = Blue 500
|
||||
Navigation bar background colour = Gray 100
|
||||
Navigation bar text colour = Gray 800 */
|
||||
it("should reset the color property values", () => {
|
||||
// Open Theme modal and change colours
|
||||
cy.get(".spectrum-ActionButton-label").contains("Theme").click()
|
||||
cy.get(".spectrum-Picker").contains("Large").click()
|
||||
.parents()
|
||||
.get(".spectrum-Menu-itemLabel").contains("None").click()
|
||||
changeThemeColors()
|
||||
// Reset colours
|
||||
cy.get(".spectrum-Button-label").contains("Reset").click({force: true})
|
||||
// Check values have reset
|
||||
checkThemeColorDefaults()
|
||||
})
|
||||
|
||||
/* Button Roundness Values:
|
||||
None = 0
|
||||
Small = 4px
|
||||
Medium = 8px
|
||||
Large = 16px */
|
||||
it("should test button roundness", () => {
|
||||
const buttonRoundnessValues = ["0", "4px", "8px", "16px"]
|
||||
// Add button, change roundness and confirm value
|
||||
cy.addComponent("Button", null).then((componentId) => {
|
||||
buttonRoundnessValues.forEach(function (item, index){
|
||||
cy.get(".spectrum-ActionButton-label").contains("Theme").click()
|
||||
cy.get(".setting").contains("Button roundness").parent()
|
||||
.get(".select-wrapper").click()
|
||||
cy.get(".spectrum-Popover").find('li').eq(index).click()
|
||||
cy.get(".spectrum-Button").contains("View changes").click({force: true})
|
||||
cy.reload()
|
||||
cy.getComponent(componentId)
|
||||
.parents(".svelte-xiqd1c").eq(0).should('have.attr', 'style').and('contains', `--buttonBorderRadius:${item}`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const changeThemeColors = () => {
|
||||
// Changes the theme colours
|
||||
cy.get(".spectrum-FieldLabel").contains("Accent color")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.find('[title="Red 400"]').click()
|
||||
cy.get(".spectrum-FieldLabel").contains("Accent color (hover)")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.find('[title="Orange 400"]').click()
|
||||
cy.get(".spectrum-FieldLabel").contains("Navigation bar background color")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.find('[title="Yellow 400"]').click()
|
||||
cy.get(".spectrum-FieldLabel").contains("Navigation bar text color")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.find('[title="Green 400"]').click()
|
||||
}
|
||||
|
||||
const checkThemeColorDefaults = () => {
|
||||
cy.get(".spectrum-FieldLabel").contains("Accent color")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.get('[title="Blue 600"]').children().find('[aria-label="Checkmark"]')
|
||||
cy.get(".spectrum-Dialog-grid").click()
|
||||
cy.get(".spectrum-FieldLabel").contains("Accent color (hover)")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.get('[title="Blue 500"]').children().find('[aria-label="Checkmark"]')
|
||||
cy.get(".spectrum-Dialog-grid").click()
|
||||
cy.get(".spectrum-FieldLabel").contains("Navigation bar background color")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.get('[title="Gray 100"]').children().find('[aria-label="Checkmark"]')
|
||||
cy.get(".spectrum-Dialog-grid").click()
|
||||
cy.get(".spectrum-FieldLabel").contains("Navigation bar text color")
|
||||
.parent().find(".container.svelte-z3cm5a").click()
|
||||
.get('[title="Gray 800"]').children().find('[aria-label="Checkmark"]')
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,42 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
|
||||
filterTests(['all'], () => {
|
||||
xcontext("Datasource Wizard", () => {
|
||||
if (Cypress.env("TEST_ENV")) {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
it("should navigate in and out of a datasource via wizard", () => {
|
||||
// Select PostgreSQL and add config (without fetch)
|
||||
const datasource = "Oracle"
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.addDatasourceConfig(datasource, true)
|
||||
|
||||
// Navigate back within datasource wizard
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Button").contains("Back").click({ force: true })
|
||||
})
|
||||
|
||||
// Select PostgreSQL datasource again
|
||||
cy.get(".item-list", { timeout: 1000 }).contains(datasource).click()
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||
})
|
||||
|
||||
// Fetch tables after selection
|
||||
// Previously entered config should not have been saved
|
||||
// Config is back to default values
|
||||
// Modal will close and provide 500 error
|
||||
cy.intercept('**/datasources').as('datasourceConnection')
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Button").contains("Save and fetch tables").click({ force: true })
|
||||
})
|
||||
cy.wait("@datasourceConnection")
|
||||
cy.get("@datasourceConnection").its('response.body')
|
||||
.should('have.property', 'status', 500)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,229 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
|
||||
filterTests(["all"], () => {
|
||||
xcontext("MySQL Datasource Testing", () => {
|
||||
if (Cypress.env("TEST_ENV")) {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
const datasource = "MySQL"
|
||||
const queryName = "Cypress Test Query"
|
||||
const queryRename = "CT Query Rename"
|
||||
|
||||
it("Should add MySQL datasource without configuration", () => {
|
||||
// Select MySQL datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
// Attempt to fetch tables without applying configuration
|
||||
cy.intercept("**/datasources").as("datasource")
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Save and fetch tables")
|
||||
.click({ force: true })
|
||||
cy.wait(500)
|
||||
// Intercept Request after button click & apply assertions
|
||||
cy.wait("@datasource")
|
||||
cy.get("@datasource")
|
||||
.its("response.body")
|
||||
.should(
|
||||
"have.property",
|
||||
"message",
|
||||
"connect ECONNREFUSED 127.0.0.1:3306"
|
||||
)
|
||||
cy.get("@datasource")
|
||||
.its("response.body")
|
||||
.should("have.property", "status", 500)
|
||||
cy.get(".spectrum-Button").contains("Skip table fetch").click({ force: true })
|
||||
})
|
||||
|
||||
it("should add MySQL datasource and fetch tables", () => {
|
||||
// Add & configure MySQL datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.intercept("**/datasources").as("datasource")
|
||||
cy.addDatasourceConfig(datasource)
|
||||
// Check response from datasource after adding configuration
|
||||
cy.wait("@datasource")
|
||||
cy.get("@datasource").its("response.statusCode").should("eq", 200)
|
||||
// Confirm fetch tables was successful
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(0)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("be.gt", 0)
|
||||
})
|
||||
|
||||
it("should check table fetching error", () => {
|
||||
// MySQL test datasource contains tables without primary keys
|
||||
cy.get(".spectrum-InLineAlert")
|
||||
.should("contain", "Error fetching tables")
|
||||
.and("contain", "No primary key constraint found")
|
||||
})
|
||||
|
||||
it("should define a One relationship type", () => {
|
||||
// Select relationship type & configure
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Define relationship")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Picker").eq(0).click()
|
||||
cy.get(".spectrum-Popover").contains("One").click()
|
||||
cy.get(".spectrum-Picker").eq(1).click()
|
||||
cy.get(".spectrum-Popover").contains("REGIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(2).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
cy.get(".spectrum-Picker").eq(3).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRIES").click()
|
||||
cy.get(".spectrum-Picker").eq(4).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
})
|
||||
// Save relationship & reload page
|
||||
cy.get(".spectrum-ButtonGroup").within(() => {
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
})
|
||||
cy.reload()
|
||||
|
||||
// Confirm table length & column name
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 1)
|
||||
cy.get(".spectrum-Table-cell").should("contain", "COUNTRIES to REGIONS")
|
||||
})
|
||||
|
||||
it("should define a Many relationship type", () => {
|
||||
// Select relationship type & configure
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Define relationship")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Picker").eq(0).click()
|
||||
cy.get(".spectrum-Popover").contains("Many").click()
|
||||
cy.get(".spectrum-Picker").eq(1).click()
|
||||
cy.get(".spectrum-Popover").contains("LOCATIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(2).click()
|
||||
cy.get(".spectrum-Popover").contains("REGIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(3).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRIES").click()
|
||||
cy.get(".spectrum-Picker").eq(4).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRY_ID").click()
|
||||
cy.get(".spectrum-Picker").eq(5).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
// Save relationship & reload page
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
cy.reload()
|
||||
cy.wait(1000)
|
||||
})
|
||||
// Confirm table length & relationship name
|
||||
cy.get(".spectrum-Table", { timeout: 1000 })
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 2)
|
||||
cy.get(".spectrum-Table-cell").should(
|
||||
"contain",
|
||||
"LOCATIONS through COUNTRIES → REGIONS"
|
||||
)
|
||||
})
|
||||
|
||||
it("should delete relationships", () => {
|
||||
// Delete both relationships
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.then(len => {
|
||||
for (let i = 0; i < len; i++) {
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Table-cell").eq(0).click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Delete")
|
||||
.click({ force: true })
|
||||
})
|
||||
cy.reload()
|
||||
cy.wait(500)
|
||||
}
|
||||
// Confirm relationships no longer exist
|
||||
cy.get(".spectrum-Body").should(
|
||||
"contain",
|
||||
"No relationships configured"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("should add a query", () => {
|
||||
// Add query
|
||||
cy.get(".spectrum-Button").contains("Add query").click({ force: true })
|
||||
cy.get(".spectrum-Form-item")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get("input").type(queryName)
|
||||
})
|
||||
// Insert Query within Fields section
|
||||
cy.get(".CodeMirror textarea")
|
||||
.eq(0)
|
||||
.type("SELECT * FROM books", { force: true })
|
||||
// Intercept query execution
|
||||
cy.intercept("**/queries/preview").as("query")
|
||||
cy.get(".spectrum-Button").contains("Run Query").click({ force: true })
|
||||
cy.wait(500)
|
||||
cy.wait("@query")
|
||||
// Assert against Status Code & Body
|
||||
cy.get("@query").its("response.statusCode").should("eq", 200)
|
||||
cy.get("@query").its("response.body").should("not.be.empty")
|
||||
// Save query
|
||||
cy.intercept("POST", "**/queries").as("saveQuery")
|
||||
cy.get(".spectrum-Button").contains("Save Query").click({ force: true })
|
||||
cy.wait("@saveQuery")
|
||||
cy.get("@saveQuery").its("response.statusCode").should("eq", 200)
|
||||
cy.get(".nav-item").should("contain", queryName)
|
||||
})
|
||||
|
||||
it("should duplicate a query", () => {
|
||||
/// Get query nav item - QueryName
|
||||
cy.get(".nav-item")
|
||||
.contains(queryName)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").eq(1).click({ force: true })
|
||||
})
|
||||
// Select and confirm duplication
|
||||
cy.get(".spectrum-Menu").contains("Duplicate").click()
|
||||
cy.get(".nav-item").should("contain", queryName + " (1)")
|
||||
})
|
||||
|
||||
it("should edit a query name", () => {
|
||||
// Rename query
|
||||
cy.get(".spectrum-Form-item")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get("input").clear().type(queryRename)
|
||||
})
|
||||
// Click on a nav item
|
||||
cy.get(".nav-item").first().click()
|
||||
// Confirm name change
|
||||
cy.get(".nav-item").should("contain", queryRename)
|
||||
})
|
||||
|
||||
it("should delete a query", () => {
|
||||
// Get query nav item - QueryName
|
||||
cy.get(".nav-item")
|
||||
.contains(queryRename)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").eq(1).click({ force: true })
|
||||
})
|
||||
// Select Delete
|
||||
cy.get(".spectrum-Menu").contains("Delete").click()
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Delete Query")
|
||||
.click({ force: true })
|
||||
// Confirm deletion
|
||||
cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryRename)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,229 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
|
||||
filterTests(["all"], () => {
|
||||
xcontext("Oracle Datasource Testing", () => {
|
||||
if (Cypress.env("TEST_ENV")) {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
const datasource = "Oracle"
|
||||
const queryName = "Cypress Test Query"
|
||||
const queryRename = "CT Query Rename"
|
||||
|
||||
it("Should add Oracle datasource and skip table fetch", () => {
|
||||
// Select Oracle datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
// Skip table fetch - no config added
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Skip table fetch")
|
||||
.click({ force: true })
|
||||
cy.wait(500)
|
||||
// Confirm config contains localhost
|
||||
cy.get(".spectrum-Textfield-input", { timeout: 500 })
|
||||
.eq(1)
|
||||
.should("have.value", "localhost")
|
||||
// Add another Oracle datasource, configure & skip table fetch
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.addDatasourceConfig(datasource, true)
|
||||
// Confirm config and no tables
|
||||
cy.get(".spectrum-Textfield-input")
|
||||
.eq(1)
|
||||
.should("have.value", Cypress.env("oracle").HOST)
|
||||
cy.get(".spectrum-Body").eq(2).should("contain", "No tables found.")
|
||||
})
|
||||
|
||||
it("Should add Oracle datasource and fetch tables without configuration", () => {
|
||||
// Select Oracle datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
// Attempt to fetch tables without applying configuration
|
||||
cy.intercept("**/datasources").as("datasource")
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Save and fetch tables")
|
||||
.click({ force: true })
|
||||
// Intercept Request after button click & apply assertions
|
||||
cy.wait("@datasource")
|
||||
cy.get("@datasource")
|
||||
.its("response.body")
|
||||
.should("have.property", "status", 500)
|
||||
cy.get(".spectrum-Button").contains("Skip table fetch").click({ force: true })
|
||||
})
|
||||
|
||||
xit("should add Oracle datasource and fetch tables", () => {
|
||||
// Add & configure Oracle datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.intercept("**/datasources").as("datasource")
|
||||
cy.addDatasourceConfig(datasource)
|
||||
// Check response from datasource after adding configuration
|
||||
cy.wait("@datasource")
|
||||
cy.get("@datasource").its("response.statusCode").should("eq", 200)
|
||||
// Confirm fetch tables was successful
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(0)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("be.gt", 0)
|
||||
})
|
||||
|
||||
xit("should define a One relationship type", () => {
|
||||
// Select relationship type & configure
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Define relationship")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Picker").eq(0).click()
|
||||
cy.get(".spectrum-Popover").contains("One").click()
|
||||
cy.get(".spectrum-Picker").eq(1).click()
|
||||
cy.get(".spectrum-Popover").contains("REGIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(2).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
cy.get(".spectrum-Picker").eq(3).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRIES").click()
|
||||
cy.get(".spectrum-Picker").eq(4).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
// Save relationship & reload page
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
cy.reload()
|
||||
})
|
||||
// Confirm table length & column name
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 1)
|
||||
cy.get(".spectrum-Table-cell").should("contain", "COUNTRIES to REGIONS")
|
||||
})
|
||||
|
||||
xit("should define a Many relationship type", () => {
|
||||
// Select relationship type & configure
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Define relationship")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Picker").eq(0).click()
|
||||
cy.get(".spectrum-Popover").contains("Many").click()
|
||||
cy.get(".spectrum-Picker").eq(1).click()
|
||||
cy.get(".spectrum-Popover").contains("LOCATIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(2).click()
|
||||
cy.get(".spectrum-Popover").contains("REGIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(3).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRIES").click()
|
||||
cy.get(".spectrum-Picker").eq(4).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRY_ID").click()
|
||||
cy.get(".spectrum-Picker").eq(5).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
// Save relationship & reload page
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
cy.reload()
|
||||
})
|
||||
// Confirm table length & relationship name
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 2)
|
||||
cy.get(".spectrum-Table-cell").should(
|
||||
"contain",
|
||||
"LOCATIONS through COUNTRIES → REGIONS"
|
||||
)
|
||||
})
|
||||
|
||||
xit("should delete relationships", () => {
|
||||
// Delete both relationships
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.then(len => {
|
||||
for (let i = 0; i < len; i++) {
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Table-row").eq(0).click()
|
||||
})
|
||||
cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Delete")
|
||||
.click({ force: true })
|
||||
})
|
||||
cy.reload()
|
||||
}
|
||||
// Confirm relationships no longer exist
|
||||
cy.get(".spectrum-Body").should(
|
||||
"contain",
|
||||
"No relationships configured"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
xit("should add a query", () => {
|
||||
// Add query
|
||||
cy.get(".spectrum-Button").contains("Add query").click({ force: true })
|
||||
cy.get(".spectrum-Form-item")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get("input").type(queryName)
|
||||
})
|
||||
// Insert Query within Fields section
|
||||
cy.get(".CodeMirror textarea")
|
||||
.eq(0)
|
||||
.type("SELECT * FROM JOBS", { force: true })
|
||||
// Intercept query execution
|
||||
cy.intercept("**/queries/preview").as("query")
|
||||
cy.get(".spectrum-Button").contains("Run Query").click({ force: true })
|
||||
cy.wait(500)
|
||||
cy.wait("@query")
|
||||
// Assert against Status Code & Body
|
||||
cy.get("@query").its("response.statusCode").should("eq", 200)
|
||||
cy.get("@query").its("response.body").should("not.be.empty")
|
||||
// Save query
|
||||
cy.get(".spectrum-Button").contains("Save Query").click({ force: true })
|
||||
cy.get(".nav-item").should("contain", queryName)
|
||||
})
|
||||
|
||||
xit("should duplicate a query", () => {
|
||||
// Get query nav item
|
||||
cy.get(".nav-item")
|
||||
.contains(queryName)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").eq(1).click({ force: true })
|
||||
})
|
||||
// Select and confirm duplication
|
||||
cy.get(".spectrum-Menu").contains("Duplicate").click()
|
||||
cy.get(".nav-item").should("contain", queryName + " (1)")
|
||||
})
|
||||
|
||||
xit("should edit a query name", () => {
|
||||
// Rename query
|
||||
cy.get(".spectrum-Form-item")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get("input").clear().type(queryRename)
|
||||
})
|
||||
// Save query
|
||||
cy.get(".spectrum-Button").contains("Save Query").click({ force: true })
|
||||
cy.get(".nav-item").should("contain", queryRename)
|
||||
})
|
||||
|
||||
xit("should delete a query", () => {
|
||||
// Get query nav item - QueryName
|
||||
cy.get(".nav-item")
|
||||
.contains(queryName)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").eq(1).click({ force: true })
|
||||
})
|
||||
|
||||
// Select Delete
|
||||
cy.get(".spectrum-Menu").contains("Delete").click()
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Delete Query")
|
||||
.click({ force: true })
|
||||
|
||||
// Confirm deletion
|
||||
cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryName)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,283 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
|
||||
filterTests(["all"], () => {
|
||||
xcontext("PostgreSQL Datasource Testing", () => {
|
||||
if (Cypress.env("TEST_ENV")) {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
const datasource = "PostgreSQL"
|
||||
const queryName = "Cypress Test Query"
|
||||
const queryRename = "CT Query Rename"
|
||||
|
||||
xit("Should add PostgreSQL datasource without configuration", () => {
|
||||
// Select PostgreSQL datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
// Attempt to fetch tables without applying configuration
|
||||
cy.intercept("**/datasources").as("datasource")
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Save and fetch tables")
|
||||
.click({ force: true })
|
||||
// Intercept Request after button click & apply assertions
|
||||
cy.wait("@datasource")
|
||||
cy.get("@datasource")
|
||||
.its("response.body")
|
||||
.should("have.property", "status", 500)
|
||||
cy.get(".spectrum-Button").contains("Skip table fetch").click({ force: true })
|
||||
})
|
||||
|
||||
it("should add PostgreSQL datasource and fetch tables", () => {
|
||||
// Add & configure PostgreSQL datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.intercept("**/datasources").as("datasource")
|
||||
cy.addDatasourceConfig(datasource)
|
||||
// Check response from datasource after adding configuration
|
||||
cy.wait("@datasource")
|
||||
cy.get("@datasource").its("response.statusCode").should("eq", 200)
|
||||
cy.wait(2000)
|
||||
// Confirm fetch tables was successful
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(0)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("be.gt", 0)
|
||||
})
|
||||
|
||||
it("should define a One relationship type", () => {
|
||||
// Select relationship type & configure
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Define relationship")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Picker").eq(0).click()
|
||||
cy.get(".spectrum-Popover").contains("One").click()
|
||||
cy.get(".spectrum-Picker").eq(1).click()
|
||||
cy.get(".spectrum-Popover").contains("REGIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(2).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
cy.get(".spectrum-Picker").eq(3).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRIES").click()
|
||||
cy.get(".spectrum-Picker").eq(4).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
// Save relationship & reload page
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
cy.reload()
|
||||
})
|
||||
// Confirm table length & column name
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 1)
|
||||
cy.get(".spectrum-Table-cell").should("contain", "COUNTRIES to REGIONS")
|
||||
})
|
||||
|
||||
it("should define a Many relationship type", () => {
|
||||
// Select relationship type & configure
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Define relationship")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Picker").eq(0).click()
|
||||
cy.get(".spectrum-Popover").contains("Many").click()
|
||||
cy.get(".spectrum-Picker").eq(1).click()
|
||||
cy.get(".spectrum-Popover").contains("LOCATIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(2).click()
|
||||
cy.get(".spectrum-Popover").contains("REGIONS").click()
|
||||
cy.get(".spectrum-Picker").eq(3).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRIES").click()
|
||||
cy.get(".spectrum-Picker").eq(4).click()
|
||||
cy.get(".spectrum-Popover").contains("COUNTRY_ID").click()
|
||||
cy.get(".spectrum-Picker").eq(5).click()
|
||||
cy.get(".spectrum-Popover").contains("REGION_ID").click()
|
||||
// Save relationship & reload page
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
cy.reload()
|
||||
})
|
||||
// Confirm table length & relationship name
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 2)
|
||||
cy.get(".spectrum-Table-cell").should(
|
||||
"contain",
|
||||
"LOCATIONS through COUNTRIES → REGIONS"
|
||||
)
|
||||
})
|
||||
|
||||
it("should delete a relationship", () => {
|
||||
cy.get(".hierarchy-items-container").contains("PostgreSQL").click({ force: true })
|
||||
cy.reload()
|
||||
// Delete one relationship
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Table-cell").eq(0).click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
|
||||
cy.get(".spectrum-Button").contains("Delete").click({ force: true })
|
||||
})
|
||||
cy.reload()
|
||||
cy.wait(500)
|
||||
// Confirm relationship was deleted
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(1)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 1)
|
||||
})
|
||||
|
||||
it("should add a query", () => {
|
||||
// Add query
|
||||
cy.get(".spectrum-Button").contains("Add query").click({ force: true })
|
||||
cy.get(".spectrum-Form-item")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get("input").type(queryName)
|
||||
})
|
||||
// Insert Query within Fields section
|
||||
cy.get(".CodeMirror textarea")
|
||||
.eq(0)
|
||||
.type("SELECT * FROM books", { force: true })
|
||||
// Intercept query execution
|
||||
cy.intercept("**/queries/preview").as("query")
|
||||
cy.get(".spectrum-Button").contains("Run Query").click({ force: true })
|
||||
cy.wait(500)
|
||||
cy.wait("@query")
|
||||
// Assert against Status Code & Body
|
||||
cy.get("@query").its("response.statusCode").should("eq", 200)
|
||||
cy.get("@query").its("response.body").should("not.be.empty")
|
||||
// Save query
|
||||
cy.intercept("**/queries").as("saveQuery")
|
||||
cy.get(".spectrum-Button").contains("Save Query").click({ force: true })
|
||||
cy.wait("@saveQuery")
|
||||
cy.get(".spectrum-Tabs-content", { timeout: 2000 }).should("contain", queryName)
|
||||
})
|
||||
|
||||
it("should switch to schema with no tables", () => {
|
||||
// Switch Schema - To one without any tables
|
||||
cy.get(".hierarchy-items-container").contains("PostgreSQL").click({ force: true })
|
||||
switchSchema("randomText")
|
||||
|
||||
// No tables displayed
|
||||
cy.get(".spectrum-Body", { timeout: 10000 }).eq(2, { timeout: 10000 }).should("contain", "No tables found")
|
||||
|
||||
// Previously created query should be visible
|
||||
cy.get(".spectrum-Table").should("contain", queryName)
|
||||
})
|
||||
|
||||
it("should switch schemas", () => {
|
||||
// Switch schema - To one with tables
|
||||
switchSchema("1")
|
||||
|
||||
// Confirm tables exist - Check for specific one
|
||||
cy.get(".spectrum-Table", { timeout: 20000 }).eq(0).should("contain", "test")
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(0)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("eq", 1)
|
||||
|
||||
// Confirm specific table visible within left nav bar
|
||||
cy.get(".hierarchy-items-container").should("contain", "test")
|
||||
|
||||
// Switch back to public schema
|
||||
switchSchema("public")
|
||||
|
||||
// Confirm tables exist - again
|
||||
cy.get(".spectrum-Table", { timeout: 20000 }).eq(0).should("contain", "REGIONS")
|
||||
cy.get(".spectrum-Table")
|
||||
.eq(0)
|
||||
.find(".spectrum-Table-row")
|
||||
.its("length")
|
||||
.should("be.gt", 1)
|
||||
|
||||
// Confirm specific table visible within left nav bar
|
||||
cy.get(".hierarchy-items-container").should("contain", "REGIONS")
|
||||
|
||||
// No relationships and one query
|
||||
cy.get(".spectrum-Body")
|
||||
.eq(3)
|
||||
.should("contain", "No relationships configured.")
|
||||
cy.get(".spectrum-Table").eq(1).should("contain", queryName)
|
||||
})
|
||||
|
||||
it("should duplicate a query", () => {
|
||||
// Locate previously created query
|
||||
cy.get(".nav-item")
|
||||
.contains(queryName)
|
||||
.siblings(".actions")
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").click({ force: true })
|
||||
})
|
||||
// Select and confirm duplication
|
||||
cy.get(".spectrum-Menu").contains("Duplicate").click()
|
||||
cy.get(".nav-item").should("contain", queryName + " (1)")
|
||||
})
|
||||
|
||||
it("should edit a query name", () => {
|
||||
// Access query
|
||||
cy.get(".hierarchy-items-container", { timeout: 2000 })
|
||||
//.contains(queryName + " (1)")
|
||||
.contains(queryName)
|
||||
.click({ force: true })
|
||||
|
||||
// Rename query
|
||||
cy.wait(1000)
|
||||
cy.get(".spectrum-Form-item", { timeout: 2000 })
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get("input").clear().type(queryRename)
|
||||
})
|
||||
|
||||
// Click on a nav item and confirm name change
|
||||
cy.get(".nav-item").first().click()
|
||||
// Confirm name change
|
||||
cy.get(".nav-item").should("contain", queryRename)
|
||||
})
|
||||
|
||||
it("should delete a query", () => {
|
||||
// Get query nav item - QueryName
|
||||
cy.get(".nav-item")
|
||||
.contains(queryRename)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").eq(1).click({ force: true })
|
||||
})
|
||||
// Select Delete
|
||||
cy.get(".spectrum-Menu").contains("Delete").click()
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Delete Query")
|
||||
.click({ force: true })
|
||||
// Confirm deletion
|
||||
cy.reload()
|
||||
cy.get(".nav-item", { timeout: 30000 }).contains(datasource).click({ force: true })
|
||||
cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryRename)
|
||||
})
|
||||
|
||||
const switchSchema = schema => {
|
||||
// Edit configuration - Change Schema
|
||||
cy.get(".spectrum-Textfield")
|
||||
.eq(6)
|
||||
.within(() => {
|
||||
cy.get("input").clear().type(schema)
|
||||
})
|
||||
// Save configuration & fetch
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Fetch tables")
|
||||
.click({ force: true })
|
||||
// Click fetch tables again within modal
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Fetch tables")
|
||||
.click({ force: true })
|
||||
})
|
||||
cy.reload()
|
||||
cy.wait(1000)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,45 +0,0 @@
|
|||
import filterTests from "../../support/filterTests"
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
xcontext("REST Datasource Testing", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
const datasource = "REST"
|
||||
const restUrl = "https://api.openbrewerydb.org/breweries"
|
||||
|
||||
it("Should add REST datasource with incorrect API", () => {
|
||||
// Select REST datasource
|
||||
cy.selectExternalDatasource(datasource)
|
||||
// Enter incorrect api & attempt to send query
|
||||
cy.get(".query-buttons", { timeout: 1000 }).contains("Add query").click({ force: true })
|
||||
cy.intercept("**/preview").as("queryError")
|
||||
cy.get("input").clear().type("random text")
|
||||
cy.get(".spectrum-Button").contains("Send").click({ force: true })
|
||||
// Intercept Request after button click & apply assertions
|
||||
cy.wait("@queryError")
|
||||
cy.get("@queryError")
|
||||
.its("response.body")
|
||||
.should("have.property", "message", "Invalid URL: http://random text")
|
||||
cy.get("@queryError")
|
||||
.its("response.body")
|
||||
.should("have.property", "status", 400)
|
||||
})
|
||||
|
||||
it("should add and configure a REST datasource", () => {
|
||||
// Select REST datasource and create query
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.wait(500)
|
||||
// createRestQuery confirms query creation
|
||||
cy.createRestQuery("GET", restUrl, "/breweries")
|
||||
// Confirm status code response within REST datasource
|
||||
cy.get(".stats", { timeout: 1000 }).within(() => {
|
||||
cy.get(".spectrum-FieldLabel")
|
||||
.eq(0)
|
||||
.should("contain", 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,147 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require("../support/interact")
|
||||
|
||||
filterTests(["smoke", "all"], () => {
|
||||
context("Query Level Transformers", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
it("should write a transformer function", () => {
|
||||
// Add REST datasource - contains API for breweries
|
||||
const datasource = "REST"
|
||||
const restUrl = "https://api.openbrewerydb.org/breweries"
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.createRestQuery("GET", restUrl, "breweries")
|
||||
cy.reload()
|
||||
cy.contains(".nav-item-content", "breweries", { timeout: 20000 }).click()
|
||||
cy.contains(interact.SPECTRUM_TABS_ITEM, "Transformer", { timeout: 5000 }).click({ force: true })
|
||||
// Get Transformer Function from file
|
||||
cy.readFile("cypress/support/queryLevelTransformerFunction.js").then(
|
||||
transformerFunction => {
|
||||
cy.get(interact.CODEMIRROR_TEXTAREA, { timeout: 5000 })
|
||||
// Highlight current text and overwrite with file contents
|
||||
.type(Cypress.platform === "darwin" ? "{cmd}a" : "{ctrl}a", {
|
||||
force: true,
|
||||
})
|
||||
.type(transformerFunction, { parseSpecialCharSequences: false })
|
||||
}
|
||||
)
|
||||
// Send Query
|
||||
cy.intercept("**/queries/preview").as("query")
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Save").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Send").click({ force: true })
|
||||
cy.wait("@query")
|
||||
// Assert against Status Code, body, & body rows
|
||||
cy.get("@query").its("response.statusCode").should("eq", 200)
|
||||
cy.get("@query").its("response.body").should("not.be.empty")
|
||||
cy.get("@query").its("response.body.rows").should("not.be.empty")
|
||||
})
|
||||
|
||||
it("should add data to the previous query", () => {
|
||||
// Add REST datasource - contains API for breweries
|
||||
const datasource = "REST"
|
||||
const restUrl = "https://api.openbrewerydb.org/breweries"
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.createRestQuery("GET", restUrl, "breweries")
|
||||
cy.reload()
|
||||
cy.contains(".nav-item-content", "breweries", { timeout: 2000 }).click()
|
||||
cy.contains(interact.SPECTRUM_TABS_ITEM, "Transformer", { timeout: 5000 }).click({ force: true })
|
||||
// Get Transformer Function with Data from file
|
||||
cy.readFile(
|
||||
"cypress/support/queryLevelTransformerFunctionWithData.js"
|
||||
).then(transformerFunction => {
|
||||
//console.log(transformerFunction[1])
|
||||
cy.get(interact.CODEMIRROR_TEXTAREA)
|
||||
// Highlight current text and overwrite with file contents
|
||||
.type(Cypress.platform === "darwin" ? "{cmd}a" : "{ctrl}a", {
|
||||
force: true,
|
||||
})
|
||||
.type(transformerFunction, { parseSpecialCharSequences: false })
|
||||
})
|
||||
// Send Query
|
||||
cy.intercept("**/queries/preview").as("query")
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Send").click({ force: true })
|
||||
cy.wait("@query")
|
||||
// Assert against Status Code, body, & body rows
|
||||
cy.get("@query").its("response.statusCode").should("eq", 200)
|
||||
cy.get("@query").its("response.body").should("not.be.empty")
|
||||
cy.get("@query").its("response.body.rows").should("not.be.empty")
|
||||
})
|
||||
|
||||
it("should run an invalid query within the transformer section", () => {
|
||||
// Add REST datasource - contains API for breweries
|
||||
const datasource = "REST"
|
||||
const restUrl = "https://api.openbrewerydb.org/breweries"
|
||||
cy.selectExternalDatasource(datasource)
|
||||
cy.createRestQuery("GET", restUrl, "breweries")
|
||||
cy.reload()
|
||||
cy.contains(".nav-item-content", "breweries", { timeout: 10000 }).click()
|
||||
cy.contains(interact.SPECTRUM_TABS_ITEM, "Transformer", { timeout: 5000 }).click({ force: true })
|
||||
// Clear the code box and add "test"
|
||||
cy.get(interact.CODEMIRROR_TEXTAREA)
|
||||
.type(Cypress.platform === "darwin" ? "{cmd}a" : "{ctrl}a", {
|
||||
force: true,
|
||||
})
|
||||
.type("test")
|
||||
// Run Query and intercept
|
||||
cy.intercept("**/preview").as("queryError")
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Send").click({ force: true })
|
||||
cy.wait("@queryError")
|
||||
cy.wait(500)
|
||||
// Assert against message and status for the query error
|
||||
cy.get("@queryError")
|
||||
.its("response.body")
|
||||
.should("have.property", "message", "test is not defined")
|
||||
cy.get("@queryError")
|
||||
.its("response.body")
|
||||
.should("have.property", "status", 400)
|
||||
})
|
||||
|
||||
xit("should run an invalid query via POST request", () => {
|
||||
// POST request with transformer as null
|
||||
cy.request({
|
||||
method: "POST",
|
||||
url: `${Cypress.config().baseUrl}/api/queries/`,
|
||||
body: {
|
||||
fields: { headers: {}, queryString: null, path: null },
|
||||
parameters: [],
|
||||
schema: {},
|
||||
name: "test",
|
||||
queryVerb: "read",
|
||||
transformer: null,
|
||||
datasourceId: "test",
|
||||
},
|
||||
// Expected 400 error - Transformer must be a string
|
||||
failOnStatusCode: false,
|
||||
}).then(response => {
|
||||
expect(response.status).to.equal(400)
|
||||
expect(response.body.message).to.include(
|
||||
'Invalid body - "transformer" must be a string'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
xit("should run an empty query", () => {
|
||||
// POST request with Transformer as an empty string
|
||||
cy.request({
|
||||
method: "POST",
|
||||
url: `${Cypress.config().baseUrl}/api/queries/preview`,
|
||||
body: {
|
||||
fields: { headers: {}, queryString: null, path: null },
|
||||
queryVerb: "read",
|
||||
transformer: "",
|
||||
datasourceId: "test",
|
||||
},
|
||||
// Expected 400 error - Transformer is not allowed to be empty
|
||||
failOnStatusCode: false,
|
||||
}).then(response => {
|
||||
expect(response.status).to.equal(400)
|
||||
expect(response.body.message).to.include(
|
||||
'Invalid body - "transformer" is not allowed to be empty'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,112 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require("../support/interact")
|
||||
|
||||
filterTests(["all"], () => {
|
||||
xcontext("Rename an App", () => {
|
||||
beforeEach(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
it("should rename an unpublished application", () => {
|
||||
const appName = "Cypress Tests"
|
||||
const appRename = "Cypress Renamed"
|
||||
// Rename app, Search for app, Confirm name was changed
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
renameApp(appName, appRename)
|
||||
cy.reload()
|
||||
cy.searchForApplication(appRename)
|
||||
cy.get(interact.APP_TABLE).find(interact.TITLE).should("have.length", 1)
|
||||
cy.applicationInAppTable(appRename)
|
||||
// Set app name back to Cypress Tests
|
||||
cy.reload()
|
||||
renameApp(appRename, appName)
|
||||
})
|
||||
|
||||
xit("Should rename a published application", () => {
|
||||
// It is not possible to rename a published application
|
||||
const appName = "Cypress Tests"
|
||||
const appRename = "Cypress Renamed"
|
||||
// Publish the app
|
||||
cy.get(interact.TOP_RIGHT_NAV)
|
||||
cy.get(interact.SPECTRUM_BUTTON)
|
||||
.contains("Publish")
|
||||
.click({ force: true })
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
|
||||
// Click publish again within the modal
|
||||
cy.get(interact.SPECTRUM_BUTTON)
|
||||
.contains("Publish")
|
||||
.click({ force: true })
|
||||
})
|
||||
// Rename app, Search for app, Confirm name was changed
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
renameApp(appName, appRename, true)
|
||||
cy.get(interact.APP_TABLE).find(interact.WRAPPER).should("have.length", 1)
|
||||
cy.applicationInAppTable(appRename)
|
||||
})
|
||||
|
||||
it("Should try to rename an application to have no name", () => {
|
||||
const appName = "Cypress Tests"
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
renameApp(appName, " ", false, true)
|
||||
// Close modal and confirm name has not been changed
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 1000 }).contains("Cancel").click()
|
||||
cy.applicationInAppTable(appName)
|
||||
})
|
||||
|
||||
xit("Should create two applications with the same name", () => {
|
||||
// It is not possible to have applications with the same name
|
||||
const appName = "Cypress Tests"
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
cy.get(interact.SPECTRUM_BUTTON), { timeout: 500 }
|
||||
.contains("Create app")
|
||||
.click({ force: true })
|
||||
cy.contains(/Start from scratch/).click()
|
||||
cy.get(interact.SPECTRUM_MODAL).within(() => {
|
||||
cy.get("input").eq(0).type(appName)
|
||||
cy.get(interact.SPECTRUM_BUTTON_GROUP)
|
||||
.contains("Create app")
|
||||
.click({ force: true })
|
||||
cy.get(interact.ERROR).should(
|
||||
"have.text",
|
||||
"Another app with the same name already exists"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("should validate application names", () => {
|
||||
// App name must be letters, numbers and spaces only
|
||||
// This test checks numbers and special characters specifically
|
||||
const appName = "Cypress Tests"
|
||||
const numberName = 12345
|
||||
const specialCharName = "£$%^"
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 })
|
||||
renameApp(appName, numberName)
|
||||
cy.applicationInAppTable(numberName)
|
||||
renameApp(numberName, specialCharName)
|
||||
cy.get(interact.ERROR).should(
|
||||
"have.text",
|
||||
"App name must be letters, numbers and spaces only"
|
||||
)
|
||||
// Set app name back to Cypress Tests
|
||||
renameApp(numberName, appName)
|
||||
})
|
||||
|
||||
const renameApp = (originalName, changedName, published, noName) => {
|
||||
cy.searchForApplication(originalName)
|
||||
cy.get(interact.APP_TABLE, { timeout: 1000 }).within(() => {
|
||||
cy.get(".app-row-actions button")
|
||||
.contains("Manage")
|
||||
.eq(0)
|
||||
.click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Tabs-item").contains("Settings").click()
|
||||
cy.get(".spectrum-Tabs-item.is-selected").contains("Settings")
|
||||
cy.get(".settings-tab").should("be.visible")
|
||||
cy.get(".details-section .page-action button")
|
||||
.contains("Edit")
|
||||
.click({ force: true })
|
||||
cy.updateAppName(changedName, noName)
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,75 +0,0 @@
|
|||
import filterTests from "../support/filterTests"
|
||||
const interact = require('../support/interact')
|
||||
|
||||
filterTests(['smoke', 'all'], () => {
|
||||
xcontext("Revert apps", () => {
|
||||
before(() => {
|
||||
cy.login()
|
||||
cy.createTestApp()
|
||||
})
|
||||
|
||||
it("should try to revert an unpublished app", () => {
|
||||
// Click revert icon
|
||||
cy.get(interact.TOP_RIGHT_NAV).within(() => {
|
||||
cy.get(interact.AREA_LABEL_REVERT).click({ force: true })
|
||||
})
|
||||
cy.get(interact.SPECTRUM_MODAL).within(() => {
|
||||
// Enter app name before revert
|
||||
cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).type("Cypress Tests")
|
||||
cy.intercept('**/revert').as('revertApp')
|
||||
// Click Revert
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Revert").click({ force: true })
|
||||
// Intercept Request after button click & apply assertions
|
||||
cy.wait("@revertApp")
|
||||
cy.get("@revertApp").its('response.body').should('have.property', 'message', "App has not yet been deployed")
|
||||
cy.get("@revertApp").its('response.body').should('have.property', 'status', 400)
|
||||
})
|
||||
})
|
||||
|
||||
it("should revert a published app", () => {
|
||||
cy.navigateToFrontend()
|
||||
|
||||
// Add initial component - Paragraph
|
||||
cy.searchAndAddComponent("Paragraph")
|
||||
// Publish app
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force: true })
|
||||
cy.get(interact.SPECTRUM_BUTTON_GROUP).within(() => {
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force: true })
|
||||
})
|
||||
cy.wait(1000) // Wait for next modal to finish loading
|
||||
cy.get(interact.SPECTRUM_BUTTON_GROUP, { timeout: 1000 }).within(() => {
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Done").click({ force: true })
|
||||
})
|
||||
|
||||
// Add second component - Button
|
||||
cy.searchAndAddComponent("Button")
|
||||
// Click Revert
|
||||
cy.get(interact.TOP_RIGHT_NAV).within(() => {
|
||||
cy.get(interact.AREA_LABEL_REVERT).click({ force: true })
|
||||
})
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
|
||||
cy.get("input").type("Cypress Tests")
|
||||
// Click Revert
|
||||
cy.get(interact.SPECTRUM_BUTTON).contains("Revert").click({ force: true })
|
||||
cy.wait(2000) // Wait for app to finish reverting
|
||||
})
|
||||
// Confirm Paragraph component is still visible
|
||||
cy.get(interact.ROOT, { timeout: 1000 }).contains("New Paragraph")
|
||||
// Confirm Button component is not visible
|
||||
cy.get(interact.ROOT, { timeout: 1000 }).should("not.have.text", "New Button")
|
||||
})
|
||||
|
||||
it("should enter incorrect app name when reverting", () => {
|
||||
// Click Revert
|
||||
cy.get(interact.TOP_RIGHT_NAV, { timeout: 1000 }).within(() => {
|
||||
cy.get(interact.AREA_LABEL_REVERT).click({ force: true })
|
||||
})
|
||||
// Enter incorrect app name
|
||||
cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
|
||||
cy.get("input").type("Cypress Tests")
|
||||
// Revert button within modal should be disabled
|
||||
cy.get(interact.SPECTRUM_BUTTON).eq(1).should('be.disabled')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,23 +0,0 @@
|
|||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
require("cypress-terminal-report/src/installLogsPrinter")(on)
|
||||
}
|
|
@ -1,945 +0,0 @@
|
|||
Cypress.on("uncaught:exception", () => {
|
||||
return false
|
||||
})
|
||||
|
||||
// ACCOUNTS & USERS
|
||||
Cypress.Commands.add("login", (email, password) => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.url()
|
||||
.should("include", "/builder/")
|
||||
.then(url => {
|
||||
if (url.includes("builder/admin")) {
|
||||
// create admin user
|
||||
cy.get("input").first().type("test@test.com")
|
||||
cy.get('input[type="password"]').first().type("test")
|
||||
cy.get('input[type="password"]').eq(1).type("test")
|
||||
cy.contains("Create super admin user").click({ force: true })
|
||||
}
|
||||
if (url.includes("builder/auth") || url.includes("builder/admin")) {
|
||||
// login
|
||||
cy.contains("Sign in to Budibase").then(() => {
|
||||
if (email == null) {
|
||||
cy.get("input").first().type("test@test.com")
|
||||
cy.get('input[type="password"]').type("test")
|
||||
} else {
|
||||
cy.get("input").first().type(email)
|
||||
cy.get('input[type="password"]').type(password)
|
||||
}
|
||||
cy.get("button").first().click({ force: true })
|
||||
cy.wait(1000)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("logOut", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.get(".user-dropdown .avatar > .icon").click({ force: true })
|
||||
cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => {
|
||||
cy.get("li[data-cy='user-logout']").click({ force: true })
|
||||
})
|
||||
cy.wait(2000)
|
||||
})
|
||||
|
||||
Cypress.Commands.add("logoutNoAppGrid", () => {
|
||||
// Logs user out when app grid is not present
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.get(".avatar > .icon").click({ force: true })
|
||||
cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => {
|
||||
cy.get(".spectrum-Menu-item").contains("Log out").click({ force: true })
|
||||
})
|
||||
cy.wait(2000)
|
||||
})
|
||||
|
||||
Cypress.Commands.add("createUser", (email, permission) => {
|
||||
cy.contains("Users").click()
|
||||
cy.get(`[data-cy="add-user"]`).click()
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
// Enter email
|
||||
cy.get(".spectrum-Textfield-input").clear().click().type(email)
|
||||
|
||||
// Select permission, if applicable
|
||||
// Default is App User
|
||||
if (permission != null) {
|
||||
cy.get(".spectrum-Picker-label").click()
|
||||
cy.get(".spectrum-Menu").within(() => {
|
||||
cy.get(".spectrum-Menu-item")
|
||||
.contains(permission)
|
||||
.click({ force: true })
|
||||
})
|
||||
}
|
||||
// Add user
|
||||
cy.get(".spectrum-Button").contains("Add users").click({ force: true })
|
||||
cy.get(".spectrum-ActionButton").contains("Add email").should("not.exist")
|
||||
})
|
||||
// Onboarding modal
|
||||
cy.get(".spectrum-Dialog-grid", { timeout: 5000 }).contains(
|
||||
"Choose your onboarding"
|
||||
)
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".onboarding-type").eq(1).click()
|
||||
cy.get(".spectrum-Button").contains("Done").click({ force: true })
|
||||
cy.get(".spectrum-Button").contains("Cancel").should("not.exist")
|
||||
})
|
||||
|
||||
// Accounts created modal - Click Done button
|
||||
cy.get(".spectrum-Button").contains("Done").click({ force: true })
|
||||
})
|
||||
|
||||
Cypress.Commands.add("deleteUser", email => {
|
||||
// Assumes user has access to Users section
|
||||
cy.contains("Users", { timeout: 2000 }).click()
|
||||
cy.contains(email).click()
|
||||
|
||||
cy.get(".title").within(() => {
|
||||
cy.get(".spectrum-Icon").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Menu").within(() => {
|
||||
cy.get(".spectrum-Menu-item").contains("Delete").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Dialog-grid").contains("Delete user").click({ force: true })
|
||||
})
|
||||
|
||||
Cypress.Commands.add("updateUserInformation", (firstName, lastName) => {
|
||||
cy.get(".user-dropdown .icon", { timeout: 2000 }).click({
|
||||
force: true,
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => {
|
||||
cy.get("li[data-cy='user-info']").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Modal.is-open").within(() => {
|
||||
cy.get("[data-cy='user-first-name']").clear()
|
||||
|
||||
if (!firstName || firstName == "") {
|
||||
cy.get("[data-cy='user-first-name']").invoke("val").should("be.empty")
|
||||
} else {
|
||||
cy.get("[data-cy='user-first-name']")
|
||||
.type(firstName)
|
||||
.should("have.value", firstName)
|
||||
.blur()
|
||||
}
|
||||
|
||||
cy.get("[data-cy='user-last-name']").clear()
|
||||
|
||||
if (!lastName || lastName == "") {
|
||||
cy.get("[data-cy='user-last-name']").invoke("val").should("be.empty")
|
||||
} else {
|
||||
cy.get("[data-cy='user-last-name']")
|
||||
.type(lastName)
|
||||
.should("have.value", lastName)
|
||||
.blur()
|
||||
}
|
||||
cy.get(".confirm-wrap").within(() => {
|
||||
cy.get("button").contains("Save").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Dialog-grid").should("not.exist")
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("setUserRole", (user, role) => {
|
||||
cy.contains("Users").click()
|
||||
cy.contains(user).click()
|
||||
|
||||
// Set Role
|
||||
cy.wait(500)
|
||||
cy.get(".spectrum-Form-itemField")
|
||||
.eq(3)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Picker-label").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Menu").within(() => {
|
||||
cy.get(".spectrum-Menu-itemLabel").contains(role).click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Form-itemField").eq(3).should("contain", role)
|
||||
})
|
||||
|
||||
// APPLICATIONS
|
||||
Cypress.Commands.add("createTestApp", () => {
|
||||
const appName = "Cypress Tests"
|
||||
cy.deleteApp(appName)
|
||||
cy.createApp(appName, "This app is used for Cypress testing.")
|
||||
})
|
||||
|
||||
Cypress.Commands.add("createApp", (name, addDefaultTable) => {
|
||||
const shouldCreateDefaultTable =
|
||||
typeof addDefaultTable != "boolean" ? true : addDefaultTable
|
||||
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.url({ timeout: 30000 }).should("include", "/apps")
|
||||
cy.get(`[data-cy="create-app-btn"]`, { timeout: 5000 }).click({ force: true })
|
||||
|
||||
// If apps already exist
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`, {
|
||||
timeout: 5000,
|
||||
})
|
||||
.its("body")
|
||||
.then(val => {
|
||||
if (val.length > 0) {
|
||||
cy.get(`[data-cy="create-app-btn"]`, { timeout: 5000 }).click({
|
||||
force: true,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get("input").eq(0).should("have.focus")
|
||||
if (name && name != "") {
|
||||
cy.get("input").eq(0).clear()
|
||||
cy.get("input").eq(0).type(name).should("have.value", name).blur()
|
||||
}
|
||||
cy.get(".spectrum-ButtonGroup")
|
||||
.contains("Create app")
|
||||
.click({ force: true })
|
||||
cy.wait(2000)
|
||||
})
|
||||
if (shouldCreateDefaultTable) {
|
||||
cy.createTable("Cypress Tests", true)
|
||||
}
|
||||
})
|
||||
|
||||
Cypress.Commands.add("deleteApp", name => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.wait(2000)
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
|
||||
.its("body")
|
||||
.then(val => {
|
||||
const findAppName = val.some(val => val.name == name)
|
||||
if (findAppName) {
|
||||
if (val.length > 0) {
|
||||
const appId = val.reduce((acc, app) => {
|
||||
if (name === app.name) {
|
||||
acc = app.appId
|
||||
}
|
||||
return acc
|
||||
}, "")
|
||||
|
||||
if (appId == "") {
|
||||
return
|
||||
}
|
||||
|
||||
// Go to app overview
|
||||
const appIdParsed = appId.split("_").pop()
|
||||
const actionEleId = `[data-cy=row_actions_${appIdParsed}]`
|
||||
cy.get(actionEleId).click()
|
||||
cy.get(`[aria-label="ShowMenu"]`).click()
|
||||
cy.get(".spectrum-Menu").within(() => {
|
||||
cy.contains("Overview").click()
|
||||
})
|
||||
|
||||
cy.wait(500)
|
||||
|
||||
// Unpublish first if needed
|
||||
cy.get(`[data-cy="app-status"]`).then($status => {
|
||||
if ($status.text().includes("- Unpublish")) {
|
||||
// Exact match for Unpublish
|
||||
cy.contains("Unpublish").click({ force: true })
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.contains("Unpublish app").click({ force: true })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Delete app
|
||||
cy.get(".app-overview-actions-icon").within(() => {
|
||||
cy.get(".spectrum-Icon").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Menu").contains("Delete").click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get("input").type(name)
|
||||
})
|
||||
cy.get(".spectrum-Button--warning").click()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("deleteAllApps", () => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.wait(500)
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`, {
|
||||
timeout: 5000,
|
||||
})
|
||||
.its("body")
|
||||
.then(val => {
|
||||
for (let i = 0; i < val.length; i++) {
|
||||
cy.deleteApp(val[i].name)
|
||||
cy.reload()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("unlockApp", unlock_config => {
|
||||
let config = { ...unlock_config }
|
||||
|
||||
cy.get(".spectrum-Modal .spectrum-Dialog[data-cy='app-lock-modal']")
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
if (config.owned) {
|
||||
cy.get(".spectrum-Dialog-heading").contains("Locked by you")
|
||||
cy.get(".lock-expiry-body").contains(
|
||||
"This lock will expire in 10 minutes from now"
|
||||
)
|
||||
|
||||
cy.intercept("**/lock").as("unlockApp")
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Release Lock")
|
||||
.click({ force: true })
|
||||
cy.wait("@unlockApp")
|
||||
cy.get("@unlockApp").its("response.statusCode").should("eq", 200)
|
||||
cy.get("@unlockApp").its("response.body").should("deep.equal", {
|
||||
message: "Lock released successfully.",
|
||||
})
|
||||
} else {
|
||||
//Show the name ?
|
||||
cy.get(".lock-expiry-body").should("not.be.visible")
|
||||
cy.get(".spectrum-Button").contains("Done")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("updateAppName", (changedName, noName) => {
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
if (noName == true) {
|
||||
cy.get("input").clear()
|
||||
cy.get(".spectrum-Dialog-grid")
|
||||
.click()
|
||||
.contains("App name must be letters, numbers and spaces only")
|
||||
return cy
|
||||
}
|
||||
cy.get("input").clear()
|
||||
cy.get("input")
|
||||
.eq(0)
|
||||
.type(changedName)
|
||||
.should("have.value", changedName)
|
||||
.blur()
|
||||
cy.get(".spectrum-ButtonGroup").contains("Save").click({ force: true })
|
||||
cy.wait(500)
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("publishApp", resolvedAppPath => {
|
||||
// Assumes you have navigated to an application first
|
||||
cy.get(".toprightnav button.spectrum-Button")
|
||||
.contains("Publish")
|
||||
.click({ force: true })
|
||||
|
||||
cy.get(".spectrum-Modal [data-cy='deploy-app-modal']")
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Button").contains("Publish").click({ force: true })
|
||||
cy.wait(1000)
|
||||
})
|
||||
|
||||
// Verify that the app url is presented correctly to the user
|
||||
cy.get(".spectrum-Modal [data-cy='deploy-app-success-modal']")
|
||||
.should("be.visible")
|
||||
.within(() => {
|
||||
let appUrl = Cypress.config().baseUrl + "/app/" + resolvedAppPath
|
||||
cy.get("[data-cy='deployed-app-url'] input").should("have.value", appUrl)
|
||||
cy.get(".spectrum-Button").contains("Done").click({ force: true })
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("alterAppVersion", (appId, version) => {
|
||||
return cy
|
||||
.request("put", `${Cypress.config().baseUrl}/api/applications/${appId}`, {
|
||||
version: version || "0.0.1-alpha.0",
|
||||
})
|
||||
.then(resp => {
|
||||
expect(resp.status).to.eq(200)
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("importApp", (exportFilePath, name) => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
|
||||
.its("body")
|
||||
.then(val => {
|
||||
if (val.length > 0) {
|
||||
cy.get(`[data-cy="create-app-btn"]`).click({ force: true })
|
||||
}
|
||||
cy.wait(500)
|
||||
cy.get(`[data-cy="import-app-btn"]`).click({
|
||||
force: true,
|
||||
})
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get("input").eq(1).should("have.focus")
|
||||
|
||||
cy.get(".spectrum-Dropzone").selectFile(exportFilePath, {
|
||||
action: "drag-drop",
|
||||
})
|
||||
|
||||
cy.get(".gallery .filename").contains("exported-app.txt")
|
||||
|
||||
if (name && name != "") {
|
||||
cy.get("input").eq(0).type(name).should("have.value", name).blur()
|
||||
}
|
||||
cy.get(".confirm-wrap button")
|
||||
.should("not.be.disabled")
|
||||
.click({ force: true })
|
||||
cy.wait(3000)
|
||||
})
|
||||
})
|
||||
|
||||
// Filters visible with 1 or more
|
||||
Cypress.Commands.add("searchForApplication", appName => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.wait(2000)
|
||||
|
||||
// No app filter functionality if only 1 app exists
|
||||
cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`)
|
||||
.its("body")
|
||||
.then(val => {
|
||||
if (val.length < 2) {
|
||||
return
|
||||
} else {
|
||||
// Searches for the app
|
||||
cy.get(".spectrum-Search").then(() => {
|
||||
cy.get(".spectrum-Textfield").within(() => {
|
||||
cy.get("input").eq(0).clear({ force: true })
|
||||
cy.get("input").eq(0).type(appName, { force: true })
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Assumes there are no others
|
||||
Cypress.Commands.add("applicationInAppTable", appName => {
|
||||
cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 })
|
||||
cy.get(".app-table", { timeout: 30000 }).within(() => {
|
||||
cy.get(".title").contains(appName).should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("createAppFromScratch", appName => {
|
||||
cy.get(`[data-cy="create-app-btn"]`)
|
||||
.contains("Start from scratch")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get("input")
|
||||
.eq(0)
|
||||
.clear()
|
||||
.type(appName)
|
||||
.should("have.value", appName)
|
||||
.blur()
|
||||
cy.get(".spectrum-ButtonGroup").contains("Create app").click()
|
||||
cy.wait(10000)
|
||||
})
|
||||
cy.createTable("Cypress Tests", true)
|
||||
})
|
||||
|
||||
// TABLES
|
||||
Cypress.Commands.add("createTable", (tableName, initialTable) => {
|
||||
// Creates an internal Budibase DB table
|
||||
if (!initialTable) {
|
||||
cy.navigateToDataSection()
|
||||
}
|
||||
cy.get(`[data-cy="new-datasource"]`, { timeout: 20000 }).click()
|
||||
cy.wait(2000)
|
||||
cy.get(".item", { timeout: 2000 })
|
||||
.contains("Budibase DB")
|
||||
.click({ force: true })
|
||||
.then(() => {
|
||||
cy.get(".spectrum-Button", { timeout: 2000 })
|
||||
.contains("Continue")
|
||||
.click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Modal").contains("Create Table", { timeout: 10000 })
|
||||
cy.get(".spectrum-Modal", { timeout: 2000 }).within(() => {
|
||||
cy.get("input", { timeout: 2000 }).first().type(tableName).blur()
|
||||
cy.get(".spectrum-ButtonGroup").contains("Create").click()
|
||||
})
|
||||
// Ensure modal has closed and table is created
|
||||
cy.get(".spectrum-Modal", { timeout: 2000 }).should("not.exist")
|
||||
cy.get(".nav-item", { timeout: 2000 })
|
||||
.contains("Budibase DB")
|
||||
.click({ force: true })
|
||||
cy.get(".nav-item-content", { timeout: 2000 }).should("contain", tableName)
|
||||
})
|
||||
|
||||
Cypress.Commands.add("createTestTableWithData", () => {
|
||||
cy.createTable("dog")
|
||||
cy.addColumn("dog", "name", "Text")
|
||||
cy.addColumn("dog", "age", "Number")
|
||||
})
|
||||
|
||||
Cypress.Commands.add(
|
||||
"addColumn",
|
||||
(tableName, columnName, type, multiOptions = null) => {
|
||||
// Select Table
|
||||
cy.selectTable(tableName)
|
||||
cy.contains(".nav-item", tableName).click()
|
||||
cy.contains("Create column").click()
|
||||
|
||||
// Configure column
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get("input").first().type(columnName)
|
||||
|
||||
// Unset table display column
|
||||
cy.contains("display column").click({ force: true })
|
||||
cy.get(".spectrum-Picker-label").click()
|
||||
cy.contains(type).click()
|
||||
|
||||
// Add options for Multi-select Type
|
||||
if (multiOptions !== null) {
|
||||
cy.get(".spectrum-Textfield-input").eq(1).type(multiOptions)
|
||||
}
|
||||
|
||||
cy.contains("Save Column").click()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
Cypress.Commands.add("addRow", values => {
|
||||
cy.contains("Create row").click()
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
cy.get("input").eq(i).type(values[i]).blur()
|
||||
}
|
||||
cy.get(".spectrum-ButtonGroup").contains("Create").click()
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("addRowMultiValue", values => {
|
||||
cy.contains("Create row").click()
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get(".spectrum-Form-itemField")
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.get(".spectrum-Popover").within(() => {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
cy.get(".spectrum-Menu-item").eq(i).click()
|
||||
}
|
||||
})
|
||||
cy.get(".spectrum-Dialog-grid").click("top")
|
||||
cy.get(".spectrum-ButtonGroup").contains("Create").click()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("selectTable", tableName => {
|
||||
cy.get(".nav-item").contains("Budibase DB").click()
|
||||
cy.contains(".nav-item", tableName).click()
|
||||
})
|
||||
|
||||
Cypress.Commands.add("addCustomSourceOptions", totalOptions => {
|
||||
cy.get('[data-cy="customOptions-prop-control"]').within(() => {
|
||||
cy.get(".spectrum-ActionButton-label").click({ force: true })
|
||||
})
|
||||
for (let i = 0; i < totalOptions; i++) {
|
||||
// Add radio button options
|
||||
cy.get(".spectrum-Button-label", { timeout: 1000 })
|
||||
.contains("Add Option")
|
||||
.click({ force: true })
|
||||
.then(() => {
|
||||
cy.get("[placeholder='Label']", { timeout: 500 }).eq(i).type(i)
|
||||
cy.get("[placeholder='Value']").eq(i).type(i)
|
||||
})
|
||||
}
|
||||
// Save options
|
||||
cy.get(".spectrum-Button").contains("Save").click({ force: true })
|
||||
})
|
||||
|
||||
// DESIGN SECTION
|
||||
Cypress.Commands.add("searchAndAddComponent", component => {
|
||||
// Open component menu
|
||||
cy.get(".icon-side-nav").within(() => {
|
||||
cy.get(".icon-side-nav-item").eq(1).click()
|
||||
})
|
||||
cy.get(".add-component > .spectrum-Button")
|
||||
.contains("Add component")
|
||||
.click({ force: true })
|
||||
cy.get(".container", { timeout: 1000 }).within(() => {
|
||||
cy.get(".title").should("contain", "Add component")
|
||||
|
||||
// Search and add component
|
||||
cy.get(".spectrum-Textfield-input").clear().type(component)
|
||||
cy.get(".body").within(() => {
|
||||
cy.get(".component")
|
||||
.contains(new RegExp("^" + component + "$"), { timeout: 3000 })
|
||||
.click({ force: true })
|
||||
})
|
||||
})
|
||||
cy.wait(1000)
|
||||
cy.location().then(loc => {
|
||||
const params = loc.pathname.split("/")
|
||||
const componentId = params[params.length - 1]
|
||||
cy.getComponent(componentId, { timeout: 3000 }).should("exist")
|
||||
return cy.wrap(componentId)
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("deleteComponentByName", componentName => {
|
||||
cy.get(".body")
|
||||
.eq(0)
|
||||
.contains(componentName)
|
||||
.siblings(".actions")
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").click({ force: true })
|
||||
})
|
||||
cy.get(".spectrum-Menu").contains("Delete").click()
|
||||
cy.get(".spectrum-Dialog").contains("Delete Component").click()
|
||||
})
|
||||
|
||||
Cypress.Commands.add("addComponent", (category, component) => {
|
||||
if (category) {
|
||||
cy.get(`[data-cy="category-${category}"]`, { timeout: 3000 }).click({
|
||||
force: true,
|
||||
})
|
||||
}
|
||||
cy.wait(500)
|
||||
if (component) {
|
||||
cy.get(`[data-cy="component-${component}"]`, { timeout: 3000 }).click({
|
||||
force: true,
|
||||
})
|
||||
}
|
||||
cy.wait(1000)
|
||||
cy.location().then(loc => {
|
||||
const params = loc.pathname.split("/")
|
||||
const componentId = params[params.length - 1]
|
||||
cy.getComponent(componentId, { timeout: 3000 }).should("exist")
|
||||
return cy.wrap(componentId)
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("getComponent", componentId => {
|
||||
return cy
|
||||
.get("iframe")
|
||||
.its("0.contentDocument")
|
||||
.should("exist")
|
||||
.its("body")
|
||||
.should("not.be.undefined")
|
||||
.then(cy.wrap)
|
||||
.find(`[data-id='${componentId}']`)
|
||||
})
|
||||
|
||||
Cypress.Commands.add("createScreen", (route, accessLevelLabel) => {
|
||||
// Blank Screen
|
||||
cy.contains("Design").click()
|
||||
cy.get(".spectrum-Button").contains("Add screen").click({ force: true })
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get("[data-cy='blank-screen']").click()
|
||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||
})
|
||||
cy.wait(500)
|
||||
cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
|
||||
cy.get(".spectrum-Form-itemField").eq(0).type(route)
|
||||
cy.get(".confirm-wrap").contains("Continue").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Modal", { timeout: 1000 }).within(() => {
|
||||
if (accessLevelLabel) {
|
||||
cy.get(".spectrum-Picker-label").click()
|
||||
cy.wait(500)
|
||||
cy.contains(accessLevelLabel).click()
|
||||
}
|
||||
cy.get(".spectrum-Button").contains("Done").click({ force: true })
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add(
|
||||
"createDatasourceScreen",
|
||||
(datasourceNames, accessLevelLabel) => {
|
||||
cy.contains("Design").click()
|
||||
cy.get(".spectrum-Button").contains("Add screen").click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get("[data-cy='autogenerated-screens']").click()
|
||||
cy.intercept("**/api/datasources").as("autoScreens")
|
||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||
cy.wait("@autoScreens")
|
||||
cy.wait(5000)
|
||||
})
|
||||
cy.get("[data-cy='autogenerated-screens']").should("not.exist")
|
||||
cy.get("[data-cy='data-source-modal']", { timeout: 10000 }).within(() => {
|
||||
for (let i = 0; i < datasourceNames.length; i++) {
|
||||
cy.get(".data-source-entry")
|
||||
.contains(datasourceNames[i], { timeout: 20000 })
|
||||
.click({ force: true })
|
||||
// Ensure the check mark is visible
|
||||
cy.get(".data-source-entry")
|
||||
.contains(datasourceNames[i])
|
||||
.get(".data-source-check", { timeout: 20000 })
|
||||
.should("exist")
|
||||
}
|
||||
|
||||
cy.get(".spectrum-Button").contains("Confirm").click({ force: true })
|
||||
})
|
||||
|
||||
cy.get(".spectrum-Modal", { timeout: 10000 }).within(() => {
|
||||
if (accessLevelLabel) {
|
||||
cy.get(".spectrum-Picker-label", { timeout: 10000 }).click()
|
||||
cy.contains(accessLevelLabel).click()
|
||||
}
|
||||
cy.get(".spectrum-Button").contains("Done").click({ force: true })
|
||||
})
|
||||
|
||||
cy.contains("Design").click()
|
||||
}
|
||||
)
|
||||
|
||||
Cypress.Commands.add(
|
||||
"createAutogeneratedScreens",
|
||||
(screenNames, accessLevelLabel) => {
|
||||
cy.navigateToAutogeneratedModal()
|
||||
|
||||
for (let i = 0; i < screenNames.length; i++) {
|
||||
cy.get(".data-source-entry").contains(screenNames[i]).click()
|
||||
}
|
||||
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
if (accessLevelLabel) {
|
||||
cy.get(".spectrum-Picker-label").click()
|
||||
cy.wait(500)
|
||||
cy.contains(accessLevelLabel).click()
|
||||
}
|
||||
cy.get(".spectrum-Button").contains("Confirm").click({ force: true })
|
||||
cy.wait(4000)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
Cypress.Commands.add("filterScreensAccessLevel", accessLevel => {
|
||||
// Filters screens by access level dropdown
|
||||
cy.get(".body").within(() => {
|
||||
cy.get(".spectrum-Form-item").eq(1).click()
|
||||
})
|
||||
cy.get(".spectrum-Menu").within(() => {
|
||||
cy.contains(accessLevel).click()
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add("deleteScreen", screen => {
|
||||
// Navigates to Design section and deletes specified screen
|
||||
cy.contains("Design").click()
|
||||
cy.get(".body").within(() => {
|
||||
cy.contains(screen)
|
||||
.siblings(".actions")
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Icon").click({ force: true })
|
||||
})
|
||||
})
|
||||
cy.get(".spectrum-Menu > .spectrum-Menu-item > .spectrum-Menu-itemLabel")
|
||||
.contains("Delete")
|
||||
.click()
|
||||
|
||||
cy.get(
|
||||
".spectrum-Dialog-grid > .spectrum-ButtonGroup > .confirm-wrap > .spectrum-Button"
|
||||
).click({ force: true })
|
||||
cy.get(".spectrum-Dialog-grid", { timeout: 10000 }).should("not.exist")
|
||||
})
|
||||
|
||||
Cypress.Commands.add("deleteAllScreens", () => {
|
||||
// Deletes all screens
|
||||
cy.get(".body")
|
||||
.find(".nav-item")
|
||||
.its("length")
|
||||
.then(len => {
|
||||
for (let i = 0; i < len; i++) {
|
||||
cy.get(".body > .nav-item")
|
||||
.eq(0)
|
||||
.invoke("text")
|
||||
.then(text => {
|
||||
cy.deleteScreen(text.trim())
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// NAVIGATION
|
||||
Cypress.Commands.add("navigateToFrontend", () => {
|
||||
// Clicks on Design tab and then the Home nav item
|
||||
cy.wait(500)
|
||||
cy.intercept("**/preview").as("preview")
|
||||
cy.contains("Design").click()
|
||||
cy.wait("@preview")
|
||||
cy.get("@preview").then(res => {
|
||||
if (res.statusCode != 200) {
|
||||
cy.reload()
|
||||
}
|
||||
})
|
||||
cy.get(".spectrum-Search", { timeout: 20000 }).type("/")
|
||||
cy.get(".nav-item", { timeout: 2000 }).contains("home").click({ force: true })
|
||||
})
|
||||
|
||||
Cypress.Commands.add("navigateToDataSection", () => {
|
||||
// Clicks on the Data tab
|
||||
cy.wait(500)
|
||||
cy.contains("Data").click()
|
||||
})
|
||||
|
||||
Cypress.Commands.add("navigateToAutogeneratedModal", () => {
|
||||
// Screen name must already exist within datasource
|
||||
cy.contains("Design").click()
|
||||
cy.get(".spectrum-Button").contains("Add screen").click({ force: true })
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get(".item", { timeout: 2000 })
|
||||
.contains("Autogenerated screens")
|
||||
.click({ force: true })
|
||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||
cy.wait(500)
|
||||
})
|
||||
})
|
||||
|
||||
// DATASOURCES
|
||||
Cypress.Commands.add("selectExternalDatasource", datasourceName => {
|
||||
// Navigates to Data Section
|
||||
cy.navigateToDataSection()
|
||||
// Open Datasource modal
|
||||
cy.get(".container").within(() => {
|
||||
cy.get("[data-cy='new-datasource']").click()
|
||||
})
|
||||
// Clicks specified datasource & continue
|
||||
cy.get(".item-list", { timeout: 1000 }).contains(datasourceName).click()
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||
})
|
||||
cy.wait(500)
|
||||
})
|
||||
|
||||
Cypress.Commands.add("addDatasourceConfig", (datasource, skipFetch) => {
|
||||
// selectExternalDatasource should be called prior to this
|
||||
// Adds the config for specified datasource & fetches tables
|
||||
// Currently supports MySQL, PostgreSQL, Oracle
|
||||
// Host IP Address
|
||||
cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => {
|
||||
cy.get(".form-row")
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get(".spectrum-Textfield").within(() => {
|
||||
if (datasource == "Oracle") {
|
||||
cy.get("input").clear().type(Cypress.env("oracle").HOST)
|
||||
} else {
|
||||
cy.get("input")
|
||||
.clear({ force: true })
|
||||
.type(Cypress.env("HOST_IP"), { force: true })
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
// Database Name
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
if (datasource == "MySQL") {
|
||||
cy.get(".form-row")
|
||||
.eq(4)
|
||||
.within(() => {
|
||||
cy.get("input").clear().type(Cypress.env("mysql").DATABASE)
|
||||
})
|
||||
} else {
|
||||
cy.get(".form-row")
|
||||
.eq(2)
|
||||
.within(() => {
|
||||
if (datasource == "PostgreSQL") {
|
||||
cy.get("input").clear().type(Cypress.env("postgresql").DATABASE)
|
||||
}
|
||||
if (datasource == "Oracle") {
|
||||
cy.get("input").clear().type(Cypress.env("oracle").DATABASE)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
// User
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
if (datasource == "MySQL") {
|
||||
cy.get(".form-row")
|
||||
.eq(2)
|
||||
.within(() => {
|
||||
cy.get("input").clear().type(Cypress.env("mysql").USER)
|
||||
})
|
||||
} else {
|
||||
cy.get(".form-row")
|
||||
.eq(3)
|
||||
.within(() => {
|
||||
if (datasource == "PostgreSQL") {
|
||||
cy.get("input").clear().type(Cypress.env("postgresql").USER)
|
||||
}
|
||||
if (datasource == "Oracle") {
|
||||
cy.get("input").clear().type(Cypress.env("oracle").USER)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
// Password
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
if (datasource == "MySQL") {
|
||||
cy.get(".form-row")
|
||||
.eq(3)
|
||||
.within(() => {
|
||||
cy.get("input").clear().type(Cypress.env("mysql").PASSWORD)
|
||||
})
|
||||
} else {
|
||||
cy.get(".form-row")
|
||||
.eq(4)
|
||||
.within(() => {
|
||||
if (datasource == "PostgreSQL") {
|
||||
cy.get("input").clear().type(Cypress.env("postgresql").PASSWORD)
|
||||
}
|
||||
if (datasource == "Oracle") {
|
||||
cy.get("input").clear().type(Cypress.env("oracle").PASSWORD)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
// Click to fetch tables
|
||||
if (skipFetch) {
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Skip table fetch")
|
||||
.click({ force: true })
|
||||
})
|
||||
} else {
|
||||
cy.intercept("**/tables").as("datasourceTables")
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
cy.get(".spectrum-Button")
|
||||
.contains("Save and fetch tables")
|
||||
.click({ force: true })
|
||||
})
|
||||
// Wait for tables to be fetched
|
||||
cy.wait("@datasourceTables", { timeout: 60000 })
|
||||
}
|
||||
})
|
||||
|
||||
Cypress.Commands.add("createRestQuery", (method, restUrl, queryPrettyName) => {
|
||||
// addExternalDatasource should be called prior to this
|
||||
// Configures REST datasource & sends query
|
||||
cy.get(".spectrum-Button", { timeout: 1000 })
|
||||
.contains("Add query")
|
||||
.click({ force: true })
|
||||
// Select Method & add Rest URL
|
||||
cy.get(".spectrum-Picker-label").eq(1).click()
|
||||
cy.get(".spectrum-Menu").contains(method).click()
|
||||
cy.get("input").clear().type(restUrl)
|
||||
// Send query
|
||||
cy.get(".spectrum-Button").contains("Send").click({ force: true })
|
||||
cy.get(".spectrum-Button", { timeout: 500 })
|
||||
.contains("Save")
|
||||
.click({ force: true })
|
||||
cy.get(".hierarchy-items-container")
|
||||
.should("contain", method)
|
||||
.and("contain", queryPrettyName)
|
||||
})
|
||||
|
||||
// MISC
|
||||
Cypress.Commands.add("closeModal", () => {
|
||||
cy.get(".spectrum-Modal", { timeout: 2000 }).within(() => {
|
||||
cy.get(".close-icon").click()
|
||||
})
|
||||
// Confirm modal has closed
|
||||
cy.get(".spectrum-Modal", { timeout: 10000 }).should("not.exist")
|
||||
})
|
||||
|
||||
Cypress.Commands.add("expandBudibaseConnection", () => {
|
||||
if (Cypress.$(".nav-item > .content > .opened").length === 0) {
|
||||
// expand the Budibase DB connection string
|
||||
cy.get(".icon.arrow").eq(0).click()
|
||||
}
|
||||
})
|
|
@ -1,3 +0,0 @@
|
|||
Cypress.Cookies.defaults({
|
||||
preserve: "budibase:auth",
|
||||
})
|
|
@ -1,16 +0,0 @@
|
|||
const filterTests = (testTags, runTest) => {
|
||||
// testTags is an array of tags
|
||||
// runTest is all tests
|
||||
if (Cypress.env("TEST_TAGS")) {
|
||||
const tags = Cypress.env("TEST_TAGS").split("/")
|
||||
const found = testTags.some($testTags => tags.includes($testTags))
|
||||
|
||||
if (found) {
|
||||
runTest()
|
||||
}
|
||||
} else {
|
||||
runTest()
|
||||
}
|
||||
}
|
||||
|
||||
export default filterTests
|
|
@ -1,22 +0,0 @@
|
|||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import "./commands"
|
||||
import "./cookies"
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
require("cypress-terminal-report/src/installLogsCollector")()
|
|
@ -1,136 +0,0 @@
|
|||
// createApp test
|
||||
export const CREATE_APP_BUTTON = '[data-cy="create-app-btn"]'
|
||||
export const TEMPLATE_CATEGORY_FILTER = ".template-category-filters"
|
||||
export const TEMPLATE_CATEGORY = ".template-categories"
|
||||
export const APP_TABLE = ".appTable"
|
||||
export const SPECTRUM_BUTTON_TEMPLATE = ".spectrum-Button"
|
||||
export const TEMPLATE_CATEGORY_ACTIONGROUP = ".template-category"
|
||||
export const TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON =
|
||||
".template-category-filters .spectrum-ActionButton"
|
||||
export const SPECTRUM_MODAL = ".spectrum-Modal"
|
||||
export const APP_NAME_INPUT = "input" // we need to update this with atribute cy-data;
|
||||
export const SPECTRUM_BUTTON_GROUP = ".spectrum-ButtonGroup"
|
||||
export const SPECTRUM_MODAL_INPUT = ".spectrum-Modal input"
|
||||
|
||||
//AddMultiOptionDatatype
|
||||
export const CATEGORY_DATA = '[data-cy="category-Data"]'
|
||||
export const COMPONENT_DATA_PROVIDER = '[data-cy="component-Data Provider"]'
|
||||
export const DATASOURCE_PROP_CONTROL = '[data-cy="dataSource-prop-control"]'
|
||||
export const DROPDOWN = ".dropdown"
|
||||
export const SPECTRUM_PICKER_LABEL = ".spectrum-Picker-label"
|
||||
export const DATASOURCE_FIELD_CONTROL = '[data-cy="field-prop-control"]'
|
||||
export const OPTION_TYPE_PROP_CONTROL = '[data-cy="optionsType-prop-control'
|
||||
|
||||
//AddRadioButtons
|
||||
export const SPECTRUM_POPOVER = ".spectrum-Popover"
|
||||
export const OPTION_SOURCE_PROP_CONROL = '[data-cy="optionsSource-prop-control'
|
||||
export const APP_TABLE_STATUS = ".appTable .app-status"
|
||||
export const APP_TABLE_ROW_ACTION = ".appTable .app-row-actions"
|
||||
export const APP_TABLE_APP_NAME = '[data-cy="app-name-link"]'
|
||||
export const DEPLOYMENT_TOP_NAV_GLOBESTRIKE =
|
||||
".deployment-top-nav svg[aria-label=GlobeStrike]"
|
||||
export const DEPLOYMENT_TOP_GLOBE = ".deployment-top-nav svg[aria-label=Globe]"
|
||||
export const PUBLISH_POPOVER_MENU = '[data-cy="publish-popover-menu"]'
|
||||
export const PUBLISH_POPOVER_ACTION = '[data-cy="publish-popover-action"]'
|
||||
export const PUBLISH_POPOVER_MESSAGE = ".publish-popover-message"
|
||||
export const SPECTRUM_BUTTON = ".spectrum-Button"
|
||||
export const SPECTRUM_LINK = ".spectrum-Link"
|
||||
export const TOPRIGHTNAV_BUTTON_SPECTRUM = ".toprightnav button.spectrum-Button"
|
||||
|
||||
//createComponents
|
||||
export const SETTINGS = "[data-cy=Settings]"
|
||||
export const SETTINGS_INPUT = "[data-cy=setting-text] input"
|
||||
export const DESIGN = "[data-cy=Design]"
|
||||
export const FONT_SIZE_PROP_CONTROL = "[data-cy=font-size-prop-control]"
|
||||
export const DATA_CY_DATASOURCE = "[data-cy=setting-dataSource]"
|
||||
export const DROPDOWN_CONTAINER = ".dropdown-container"
|
||||
export const SPECTRUM_PICKER = ".spectrum-Picker"
|
||||
|
||||
//autoScreens
|
||||
export const LABEL_ADD_CIRCLE = "[aria-label=AddCircle]"
|
||||
export const ITEM_DISABLED = ".item.disabled"
|
||||
export const CONFIRM_WRAP_SPE_BUTTON = ".confirm-wrap .spectrum-Button"
|
||||
export const DATA_SOURCE_ENTRY = ".data-source-entry"
|
||||
export const BODY = ".body"
|
||||
|
||||
//publishWorkFlow
|
||||
export const DEPLOY_APP_MODAL = ".spectrum-Modal [data-cy=deploy-app-modal]"
|
||||
export const DEPLOY_SUCCESS_MODAL =
|
||||
".spectrum-Modal [data-cy=deploy-app-success-modal]"
|
||||
export const DEPLOY_APP_URL_INPUT = "[data-cy=deployed-app-url] input"
|
||||
export const GLOBESTRIKE = "svg[aria-label=GlobeStrike]"
|
||||
export const GLOBE = "svg[aria-label=Globe]"
|
||||
export const UNPUBLISH_MODAL = "[data-cy=unpublish-modal]"
|
||||
export const CONFIRM_WRAP_BUTTON = ".confirm-wrap button"
|
||||
export const DEPLOYMENT_TOP_NAV = ".deployment-top-nav"
|
||||
|
||||
//changeAppiconAndColour
|
||||
export const APP_ROW_ACTION = ".app-row-actions-icon"
|
||||
export const SPECTRUM_MENU = ".spectrum-Menu"
|
||||
export const ICON_ITEM = ".icon-item"
|
||||
export const FILL = ".fill"
|
||||
export const COLOURSS = ".colors"
|
||||
export const AREA_LABEL = "[aria-label]"
|
||||
export const TITLE = ".title"
|
||||
export const GRID = ".grid"
|
||||
export const COLOUR = ".color"
|
||||
|
||||
//createAutomation
|
||||
export const ADD_BUTTON_SPECTRUM = ".add-button .spectrum-Icon"
|
||||
export const MODAL_INNER_WRAPPER = ".modal-inner-wrapper"
|
||||
export const SPECTRUM_BUTTON_CTA = ".spectrum-Button--cta"
|
||||
export const SPECTRUM_TEXTFIELD_INPUT = ".spectrum-Textfield-input"
|
||||
|
||||
//createTable
|
||||
export const TABLE_TITLE_H1 = ".table-title h1"
|
||||
export const TABLE_TITLE = ".title"
|
||||
export const SPECTRUM_TABLE_EDIT = ".spectrum-Table-editIcon > use"
|
||||
export const SPECTRUM_SWITCH_INPUT = ".spectrum-Switch-input"
|
||||
export const SPECTRUM_CHECKBOX_INPUT = ".spectrum-Checkbox-input"
|
||||
export const SPECTRUM_PAGINATION = ".spectrum-Pagination"
|
||||
export const SPECTRUM_ACTION_BUTTON = ".spectrum-ActionButton"
|
||||
export const SPECTRUM_BODY_SECOND = ".spectrum-Body--secondary"
|
||||
export const POPOVERS = ".popovers"
|
||||
export const SPECTRUM_DIALOG_GRID = ".spectrum-Dialog-grid"
|
||||
export const DELETE_COLUMN_CONFIRM = '[data-cy="delete-column-confirm"]'
|
||||
export const NAV_ITEM = ".nav-item"
|
||||
export const ACTION_SPECTRUM_ICON = ".actions .spectrum-Icon"
|
||||
export const SPECTRUM_MENU_CHILD2 = ".spectrum-Menu > :nth-child(2)"
|
||||
export const DELETE_TABLE_CONFIRM = '[data-cy="delete-table-confirm"]'
|
||||
|
||||
//adminAndManagement Folder
|
||||
export const SPECTRUM_TABLE = ".spectrum-Table"
|
||||
export const SPECTRUM_SIDENAV = ".spectrum-SideNav"
|
||||
export const SPECTRUM_TABLE_ROW = ".spectrum-Table-row"
|
||||
export const SPECTRUM_TABLE_CELL = ".spectrum-Table-cell"
|
||||
export const FIELD = ".field"
|
||||
export const CONTAINER = ".container"
|
||||
export const REGENERATE = ".regenerate"
|
||||
export const SPECTRUM_DIALOG_CONTENT = ".spectrum-Dialog-content"
|
||||
export const SPECTRUM_ICON = ".spectrum-Icon"
|
||||
export const SPECTRUM_HEADING = ".spectrum-Heading"
|
||||
export const SPECTRUM_FORM_ITEMFIELD = ".spectrum-Form-itemField"
|
||||
export const LIST_ITEMS = ".list-items"
|
||||
|
||||
//createView
|
||||
export const SPECTRUM_MENU_ITEM_LABEL = ".spectrum-Menu-itemLabel"
|
||||
|
||||
//revertApp
|
||||
export const TOP_RIGHT_NAV = ".toprightnav"
|
||||
export const AREA_LABEL_REVERT = "[aria-label=Revert]"
|
||||
export const ROOT = ".root"
|
||||
|
||||
//queryLevelTransformers
|
||||
export const SPECTRUM_TABS_ITEM = ".spectrum-Tabs-itemLabel"
|
||||
export const CODEMIRROR_TEXTAREA = ".CodeMirror textarea"
|
||||
|
||||
//renameApplication
|
||||
export const WRAPPER = ".wrapper"
|
||||
export const ERROR = ".error"
|
||||
export const AREA_LABEL_MORE = "[aria-label=More]"
|
||||
export const APP_ROW_ACTION_MENU_POPOVER =
|
||||
'[data-cy="app-row-actions-menu-popover"]'
|
||||
export const SPECTRUM_MENU_ITEM = ".spectrum-Menu-item"
|
||||
|
||||
//commands
|
||||
export const HOME_LOGO = ".home-logo"
|
|
@ -1,14 +0,0 @@
|
|||
/* eslint-disable */
|
||||
const breweries = data
|
||||
const totals = {}
|
||||
|
||||
for (let brewery of breweries)
|
||||
{const state = brewery.state
|
||||
if (totals[state] == null)
|
||||
{totals[state] = 1
|
||||
} else
|
||||
{totals[state]++
|
||||
}
|
||||
}
|
||||
const entries = Object.entries(totals)
|
||||
return entries.map(([state, count]) => ({ state, count }))
|
|
@ -1,31 +0,0 @@
|
|||
/* eslint-disable */
|
||||
const breweries = data
|
||||
const totals = {}
|
||||
for (let brewery of breweries)
|
||||
{const state = brewery.state
|
||||
if (totals[state] == null)
|
||||
{totals[state] = 1
|
||||
} else
|
||||
{totals[state]++
|
||||
}
|
||||
}
|
||||
const stateCodes =
|
||||
{texas: "tx",
|
||||
colorado: "co",
|
||||
florida: "fl",
|
||||
iwoa: "ia",
|
||||
louisiana: "la",
|
||||
california: "ca",
|
||||
pennsylvania: "pa",
|
||||
georgia: "ga",
|
||||
"new hampshire": "nh",
|
||||
virginia: "va",
|
||||
michigan: "mi",
|
||||
maryland: "md",
|
||||
ohio: "oh",
|
||||
}
|
||||
const entries = Object.entries(totals)
|
||||
return entries.map(([state, count]) =>
|
||||
{stateCodes[state.toLowerCase()]
|
||||
return { state, count, flag: "http://flags.ox3.in/svg/us/${stateCode}.svg" }
|
||||
})
|
|
@ -1,4 +0,0 @@
|
|||
// @ts-ignore
|
||||
import { run } from "../setup"
|
||||
|
||||
run("../../server/src/index", "../../worker/src/index")
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/builder",
|
||||
"version": "2.2.12-alpha.55",
|
||||
"version": "2.2.12-alpha.64",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -9,20 +9,7 @@
|
|||
"dev:builder": "routify -c dev:vite",
|
||||
"dev:vite": "vite --host 0.0.0.0",
|
||||
"rollup": "rollup -c -w",
|
||||
"test": "jest",
|
||||
"cy:setup": "ts-node ./cypress/ts/setup.ts",
|
||||
"cy:setup:ci": "node ./cypress/setup.js",
|
||||
"cy:open": "cypress open",
|
||||
"cy:run": "cypress run",
|
||||
"cy:run:ci": "cypress run --headed --browser chrome --spec cypress/integration/createApp.spec.js",
|
||||
"cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record",
|
||||
"cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run",
|
||||
"cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci",
|
||||
"cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record; npm run cy:ci:report",
|
||||
"cy:ci:report": "mochawesome-merge cypress/reports/*.json > cypress/reports/testReport.json && marge cypress/reports/testReport.json --reportDir cypress/reports --inline",
|
||||
"cy:ci:notify": "node scripts/cypressResultsWebhook",
|
||||
"cy:debug": "start-server-and-test cy:setup http://localhost:4100/builder cy:open",
|
||||
"cy:debug:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:open"
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"globals": {
|
||||
|
@ -71,10 +58,10 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "2.2.12-alpha.55",
|
||||
"@budibase/client": "2.2.12-alpha.55",
|
||||
"@budibase/frontend-core": "2.2.12-alpha.55",
|
||||
"@budibase/string-templates": "2.2.12-alpha.55",
|
||||
"@budibase/bbui": "2.2.12-alpha.64",
|
||||
"@budibase/client": "2.2.12-alpha.64",
|
||||
"@budibase/frontend-core": "2.2.12-alpha.64",
|
||||
"@budibase/string-templates": "2.2.12-alpha.64",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
const cypressConfig = require("../cypress.json")
|
||||
const testConfig = require("./testConfig.json")
|
||||
|
||||
// normal development system
|
||||
const SERVER_PORT = cypressConfig.env.PORT
|
||||
const WORKER_PORT = cypressConfig.env.WORKER_PORT
|
||||
const SERVER_PORT = testConfig.env.PORT
|
||||
const WORKER_PORT = testConfig.env.WORKER_PORT
|
||||
|
||||
if (!process.env.NODE_ENV) {
|
||||
process.env.NODE_ENV = "cypress"
|
||||
}
|
||||
process.env.ENABLE_ANALYTICS = "0"
|
||||
process.env.JWT_SECRET = cypressConfig.env.JWT_SECRET
|
||||
process.env.JWT_SECRET = testConfig.env.JWT_SECRET
|
||||
process.env.SELF_HOSTED = 1
|
||||
process.env.WORKER_URL = `http://localhost:${WORKER_PORT}/`
|
||||
process.env.APPS_URL = `http://localhost:${SERVER_PORT}/`
|
||||
|
@ -23,10 +23,7 @@ process.env.ALLOW_DEV_AUTOMATIONS = 1
|
|||
// Stop info logs polluting test outputs
|
||||
process.env.LOG_LEVEL = "error"
|
||||
|
||||
exports.run = (
|
||||
serverLoc = "../../server/dist",
|
||||
workerLoc = "../../worker/dist"
|
||||
) => {
|
||||
exports.run = (serverLoc = "../server/dist", workerLoc = "../worker/dist") => {
|
||||
// require("dotenv").config({ path: resolve(dir, ".env") })
|
||||
// don't make this a variable or top level require
|
||||
// it will cause environment module to be loaded prematurely
|
|
@ -509,21 +509,24 @@ const getSelectedRowsBindings = asset => {
|
|||
return bindings
|
||||
}
|
||||
|
||||
export const makeStateBinding = key => {
|
||||
return {
|
||||
type: "context",
|
||||
runtimeBinding: `${makePropSafe("state")}.${makePropSafe(key)}`,
|
||||
readableBinding: `State.${key}`,
|
||||
category: "State",
|
||||
icon: "AutomatedSegment",
|
||||
display: { name: key },
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all state bindings that are globally available.
|
||||
*/
|
||||
const getStateBindings = () => {
|
||||
let bindings = []
|
||||
if (get(store).clientFeatures?.state) {
|
||||
const safeState = makePropSafe("state")
|
||||
bindings = getAllStateVariables().map(key => ({
|
||||
type: "context",
|
||||
runtimeBinding: `${safeState}.${makePropSafe(key)}`,
|
||||
readableBinding: `State.${key}`,
|
||||
category: "State",
|
||||
icon: "AutomatedSegment",
|
||||
display: { name: key },
|
||||
}))
|
||||
bindings = getAllStateVariables().map(makeStateBinding)
|
||||
}
|
||||
return bindings
|
||||
}
|
||||
|
|
|
@ -42,13 +42,7 @@
|
|||
</script>
|
||||
|
||||
{#if type === "options" && meta.constraints.inclusion.length !== 0}
|
||||
<Select
|
||||
{label}
|
||||
data-cy="{meta.name}-select"
|
||||
bind:value
|
||||
options={meta.constraints.inclusion}
|
||||
sort
|
||||
/>
|
||||
<Select {label} bind:value options={meta.constraints.inclusion} sort />
|
||||
{:else if type === "datetime"}
|
||||
<DatePicker
|
||||
{error}
|
||||
|
@ -61,7 +55,7 @@
|
|||
{:else if type === "attachment"}
|
||||
<Dropzone {label} {error} bind:value />
|
||||
{:else if type === "boolean"}
|
||||
<Toggle text={label} {error} bind:value data-cy="{meta.name}-input" />
|
||||
<Toggle text={label} {error} bind:value />
|
||||
{:else if type === "array" && meta.constraints.inclusion.length !== 0}
|
||||
<Multiselect
|
||||
bind:value
|
||||
|
@ -87,12 +81,5 @@
|
|||
{error}
|
||||
/>
|
||||
{:else}
|
||||
<Input
|
||||
{label}
|
||||
data-cy="{meta.name}-input"
|
||||
{type}
|
||||
{error}
|
||||
bind:value
|
||||
disabled={readonly}
|
||||
/>
|
||||
<Input {label} {type} {error} bind:value disabled={readonly} />
|
||||
{/if}
|
||||
|
|
|
@ -546,9 +546,5 @@
|
|||
Your data will be deleted and this action cannot be undone - enter the column
|
||||
name to confirm.
|
||||
</p>
|
||||
<Input
|
||||
dataCy="delete-column-confirm"
|
||||
bind:value={deleteColName}
|
||||
placeholder={originalName}
|
||||
/>
|
||||
<Input bind:value={deleteColName} placeholder={originalName} />
|
||||
</ConfirmDialog>
|
||||
|
|
|
@ -119,7 +119,6 @@
|
|||
selection is always undefined -->
|
||||
<Select
|
||||
label="Role"
|
||||
data-cy="roleId-select"
|
||||
bind:value={row.roleId}
|
||||
options={$roles}
|
||||
getOptionLabel={role => role.name}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Button data-cy="edit-row" secondary small on:click={showModal}>Edit</Button>
|
||||
<Button secondary small on:click={showModal}>Edit</Button>
|
||||
<Modal bind:this={modal}>
|
||||
<svelte:component this={modalContentComponent} {row} />
|
||||
</Modal>
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
disabled={error || !name || !datasource?.type}
|
||||
>
|
||||
<Input
|
||||
data-cy="datasource-name-input"
|
||||
label="Datasource Name"
|
||||
on:input={checkValid}
|
||||
bind:value={name}
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
export let indented
|
||||
</script>
|
||||
|
||||
<div
|
||||
data-cy="table-nav-item"
|
||||
class:indented
|
||||
class:selected
|
||||
on:click
|
||||
class={className}
|
||||
>
|
||||
<div class:indented class:selected on:click class={className}>
|
||||
<i class={icon} />
|
||||
<span>{title}</span>
|
||||
<slot />
|
||||
|
|
|
@ -108,7 +108,6 @@
|
|||
disabled={error || !name || (rows.length && !allValid)}
|
||||
>
|
||||
<Input
|
||||
data-cy="table-name-input"
|
||||
thin
|
||||
label="Table Name"
|
||||
on:input={checkValid}
|
||||
|
|
|
@ -134,11 +134,7 @@
|
|||
This action cannot be undone - to continue please enter the table name below
|
||||
to confirm.
|
||||
</p>
|
||||
<Input
|
||||
bind:value={deleteTableName}
|
||||
placeholder={table.name}
|
||||
dataCy="delete-table-confirm"
|
||||
/>
|
||||
<Input bind:value={deleteTableName} placeholder={table.name} />
|
||||
</ConfirmDialog>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
<Modal bind:this={appLockModal}>
|
||||
<ModalContent
|
||||
title={lockedByHeading}
|
||||
dataCy={"app-lock-modal"}
|
||||
showConfirmButton={false}
|
||||
showCancelButton={false}
|
||||
>
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
export let onCancel = undefined
|
||||
export let warning = true
|
||||
export let disabled
|
||||
export let dataCy = null
|
||||
|
||||
let modal
|
||||
|
||||
|
@ -29,7 +28,6 @@
|
|||
{cancelText}
|
||||
{warning}
|
||||
{disabled}
|
||||
{dataCy}
|
||||
>
|
||||
<Body size="S">
|
||||
{body}
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
export let title = ""
|
||||
export let actionIcon
|
||||
export let action
|
||||
export let dataCy
|
||||
|
||||
$: actionDefined = typeof action === "function"
|
||||
</script>
|
||||
|
||||
<div class="dash-card" data-cy={dataCy}>
|
||||
<div class="dash-card">
|
||||
<div class="dash-card-header" class:active={actionDefined} on:click={action}>
|
||||
<span class="dash-card-title">
|
||||
<Detail size="M">{title}</Detail>
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
<div class="template-categories">
|
||||
<Layout gap="XL" noPadding>
|
||||
{#each filteredCategories as category}
|
||||
<div class="template-category" data-cy={category.name}>
|
||||
<div class="template-category">
|
||||
<Detail size="M">{category.name}</Detail>
|
||||
<div class="template-grid">
|
||||
{#each category.templates as templateEntry}
|
||||
|
|
|
@ -66,11 +66,7 @@
|
|||
{error}
|
||||
/>
|
||||
{#if !disabled}
|
||||
<div
|
||||
class="icon"
|
||||
on:click={bindingDrawer.show}
|
||||
data-cy="text-binding-button"
|
||||
>
|
||||
<div class="icon" on:click={bindingDrawer.show}>
|
||||
<Icon size="S" name="FlashOn" />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
export let label = null
|
||||
export let value
|
||||
export let dataCy = null
|
||||
|
||||
const copyToClipboard = val => {
|
||||
const dummy = document.createElement("textarea")
|
||||
|
@ -16,7 +15,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div data-cy={dataCy}>
|
||||
<div>
|
||||
<Input readonly {value} {label} />
|
||||
<div class="icon" on:click={() => copyToClipboard(value)}>
|
||||
<Icon size="S" name="Copy" />
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
title="Publish to production"
|
||||
confirmText="Publish"
|
||||
onConfirm={publishApp}
|
||||
dataCy={"deploy-app-modal"}
|
||||
>
|
||||
The changes you have made will be published to the production version of the
|
||||
application.
|
||||
|
@ -88,12 +87,7 @@
|
|||
|
||||
<!-- Publish complete -->
|
||||
<Modal bind:this={publishCompleteModal}>
|
||||
<ModalContent
|
||||
confirmText="Done"
|
||||
cancelText="View App"
|
||||
onCancel={viewApp}
|
||||
dataCy="deploy-app-success-modal"
|
||||
>
|
||||
<ModalContent confirmText="Done" cancelText="View App" onCancel={viewApp}>
|
||||
<div slot="header" class="app-published-header">
|
||||
<svg
|
||||
width="26px"
|
||||
|
@ -105,11 +99,7 @@
|
|||
</svg>
|
||||
<span class="app-published-header-text">App Published!</span>
|
||||
</div>
|
||||
<CopyInput
|
||||
value={publishedUrl}
|
||||
label="You can view your app at:"
|
||||
dataCy="deployed-app-url"
|
||||
/>
|
||||
<CopyInput value={publishedUrl} label="You can view your app at:" />
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
|
|
|
@ -124,10 +124,11 @@
|
|||
bind:this={publishPopover}
|
||||
align="right"
|
||||
disabled={!isPublished}
|
||||
dataCy="publish-popover-menu"
|
||||
anchor={publishPopoverAnchor}
|
||||
offset={10}
|
||||
>
|
||||
<Layout gap="M">
|
||||
<div class="popover-content">
|
||||
<Layout noPadding gap="M">
|
||||
<Heading size="XS">Your published app</Heading>
|
||||
<Body size="S">
|
||||
<span class="publish-popover-message">
|
||||
|
@ -141,19 +142,19 @@
|
|||
)}
|
||||
</span>
|
||||
</Body>
|
||||
<div class="publish-popover-actions">
|
||||
<div class="buttons">
|
||||
<Button
|
||||
warning={true}
|
||||
icon="GlobeStrike"
|
||||
disabled={!isPublished}
|
||||
on:click={unpublishApp}
|
||||
dataCy="publish-popover-action"
|
||||
>
|
||||
Unpublish
|
||||
</Button>
|
||||
<Button cta on:click={viewApp}>View app</Button>
|
||||
</div>
|
||||
</Layout>
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -172,7 +173,6 @@
|
|||
title="Confirm unpublish"
|
||||
okText="Unpublish app"
|
||||
onOk={confirmUnpublishApp}
|
||||
dataCy={"unpublish-modal"}
|
||||
>
|
||||
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
|
||||
</ConfirmDialog>
|
||||
|
@ -183,11 +183,8 @@
|
|||
</div>
|
||||
|
||||
<style>
|
||||
.publish-popover-actions :global([data-cy="publish-popover-action"]) {
|
||||
margin-right: var(--spacing-s);
|
||||
}
|
||||
:global([data-cy="publish-popover-menu"]) {
|
||||
padding: 10px;
|
||||
.popover-content {
|
||||
padding: var(--spacing-xl);
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
hoverable
|
||||
on:click={revertModal.show}
|
||||
tooltip="Revert changes"
|
||||
dataCy="revert-application-topnav"
|
||||
/>
|
||||
<Modal bind:this={revertModal}>
|
||||
<ModalContent
|
||||
|
|
|
@ -11,7 +11,10 @@
|
|||
} from "@budibase/bbui"
|
||||
import { getAvailableActions } from "./index"
|
||||
import { generate } from "shortid"
|
||||
import { getEventContextBindings } from "builderStore/dataBinding"
|
||||
import {
|
||||
getEventContextBindings,
|
||||
makeStateBinding,
|
||||
} from "builderStore/dataBinding"
|
||||
import { currentAsset, store } from "builderStore"
|
||||
|
||||
const flipDurationMs = 150
|
||||
|
@ -52,7 +55,7 @@
|
|||
actions,
|
||||
selectedAction?.id
|
||||
)
|
||||
$: allBindings = eventContexBindings.concat(bindings)
|
||||
$: allBindings = getAllBindings(bindings, eventContexBindings, actions)
|
||||
$: {
|
||||
// Ensure each action has a unique ID
|
||||
if (actions) {
|
||||
|
@ -111,6 +114,33 @@
|
|||
function handleDndFinalize(e) {
|
||||
actions = e.detail.items
|
||||
}
|
||||
|
||||
const getAllBindings = (bindings, eventContextBindings, actions) => {
|
||||
let allBindings = eventContextBindings.concat(bindings)
|
||||
|
||||
// Ensure bindings are generated for all "update state" action keys
|
||||
actions
|
||||
.filter(action => {
|
||||
// Find all "Update State" actions which set values
|
||||
return (
|
||||
action[EVENT_TYPE_KEY] === "Update State" &&
|
||||
action.parameters?.type === "set" &&
|
||||
action.parameters.key
|
||||
)
|
||||
})
|
||||
.forEach(action => {
|
||||
// Check we have a binding for this action, and generate one if not
|
||||
const stateBinding = makeStateBinding(action.parameters.key)
|
||||
const hasKey = allBindings.some(binding => {
|
||||
return binding.runtimeBinding === stateBinding.runtimeBinding
|
||||
})
|
||||
if (!hasKey) {
|
||||
allBindings.push(stateBinding)
|
||||
}
|
||||
})
|
||||
|
||||
return allBindings
|
||||
}
|
||||
</script>
|
||||
|
||||
<DrawerContent>
|
||||
|
@ -186,7 +216,7 @@
|
|||
<div class="selected-action-container">
|
||||
<svelte:component
|
||||
this={selectedActionComponent}
|
||||
parameters={selectedAction.parameters}
|
||||
bind:parameters={selectedAction.parameters}
|
||||
bindings={allBindings}
|
||||
{nested}
|
||||
/>
|
||||
|
|
|
@ -193,11 +193,7 @@
|
|||
</Drawer>
|
||||
{/if}
|
||||
</div>
|
||||
<Popover
|
||||
bind:this={dropdownRight}
|
||||
anchor={anchorRight}
|
||||
dataCy={`dataSource-popover-${$store.selectedComponentId}`}
|
||||
>
|
||||
<Popover bind:this={dropdownRight} anchor={anchorRight}>
|
||||
<div class="dropdown">
|
||||
<div class="title">
|
||||
<Heading size="XS">Tables</Heading>
|
||||
|
|
|
@ -121,12 +121,7 @@
|
|||
{displayValue}
|
||||
</ActionButton>
|
||||
</div>
|
||||
<Popover
|
||||
bind:this={dropdown}
|
||||
on:open={setSelectedUI}
|
||||
anchor={buttonAnchor}
|
||||
dataCy="icon-popover"
|
||||
>
|
||||
<Popover bind:this={dropdown} on:open={setSelectedUI} anchor={buttonAnchor}>
|
||||
<div class="container">
|
||||
<div class="search-area">
|
||||
<div class="alphabet-area">
|
||||
|
|
|
@ -74,17 +74,13 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="property-control"
|
||||
class:highlighted={highlighted && nullishValue}
|
||||
data-cy={`setting-${key}`}
|
||||
>
|
||||
<div class="property-control" class:highlighted={highlighted && nullishValue}>
|
||||
{#if type !== "boolean" && label}
|
||||
<div class="label">
|
||||
<Label>{label}</Label>
|
||||
</div>
|
||||
{/if}
|
||||
<div data-cy={`${key}-prop-control`} class="control">
|
||||
<div id={`${key}-prop-control`} class="control">
|
||||
<svelte:component
|
||||
this={control}
|
||||
{componentInstance}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
let developmentValue
|
||||
let useProductionValue = true
|
||||
|
||||
const HasSpacesRegex = /[\\"\s]/
|
||||
|
||||
const deleteVariable = async name => {
|
||||
try {
|
||||
await environment.deleteVariable(name)
|
||||
|
@ -47,10 +49,16 @@
|
|||
</script>
|
||||
|
||||
<ModalContent
|
||||
disabled={HasSpacesRegex.test(name)}
|
||||
onConfirm={() => saveVariable()}
|
||||
title={!row ? "Add new environment variable" : "Edit environment variable"}
|
||||
>
|
||||
<Input disabled={row} label="Name" bind:value={name} />
|
||||
<Input
|
||||
disabled={row}
|
||||
label="Name"
|
||||
bind:value={name}
|
||||
error={HasSpacesRegex.test(name) && "Must not include spaces"}
|
||||
/>
|
||||
<div>
|
||||
<Heading size="XS">Production</Heading>
|
||||
<Input
|
||||
|
|
|
@ -108,16 +108,18 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
{#key tourStepKey}
|
||||
{#if tourKey}
|
||||
{#key tourStepKey}
|
||||
<Popover
|
||||
align={tourStep?.align}
|
||||
bind:this={popover}
|
||||
anchor={popoverAnchor}
|
||||
dataCy="tour-popover-menu"
|
||||
maxWidth={300}
|
||||
dismissible={false}
|
||||
offset={15}
|
||||
>
|
||||
<Layout gap="M">
|
||||
<div class="tour-content">
|
||||
<Layout noPadding gap="M">
|
||||
<div class="tour-header">
|
||||
<Heading size="XS">{tourStep?.title || "-"}</Heading>
|
||||
<div>{`${tourStepIdx + 1}/${tourSteps?.length}`}</div>
|
||||
|
@ -148,19 +150,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</div>
|
||||
</Popover>
|
||||
{/key}
|
||||
{/key}
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.tour-content {
|
||||
padding: var(--spacing-xl);
|
||||
}
|
||||
.tour-navigation {
|
||||
grid-gap: var(--spectrum-alias-grid-baseline);
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
:global([data-cy="tour-popover-menu"]) {
|
||||
padding: 10px;
|
||||
margin-top: var(--spacing-l);
|
||||
}
|
||||
.tour-body :global(.feature-list) {
|
||||
margin-bottom: 0px;
|
||||
padding-left: var(--spacing-xl);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div>
|
||||
In this section you can mange the data for your app:
|
||||
In this section you can manage the data for your app:
|
||||
<ul class="feature-list">
|
||||
<li>Connect data sources</li>
|
||||
<li>Edit data</li>
|
||||
|
|
|
@ -23,14 +23,6 @@
|
|||
Personalise the platform by adding your first name and last name.
|
||||
</Body>
|
||||
<Input disabled bind:value={$auth.user.email} label="Email" />
|
||||
<Input
|
||||
bind:value={$values.firstName}
|
||||
label="First name"
|
||||
dataCy="user-first-name"
|
||||
/>
|
||||
<Input
|
||||
bind:value={$values.lastName}
|
||||
label="Last name"
|
||||
dataCy="user-last-name"
|
||||
/>
|
||||
<Input bind:value={$values.firstName} label="First name" />
|
||||
<Input bind:value={$values.lastName} label="Last name" />
|
||||
</ModalContent>
|
||||
|
|
|
@ -30,11 +30,11 @@
|
|||
</script>
|
||||
|
||||
<div class="app-row" on:click={handleDefaultClick}>
|
||||
<div class="title" data-cy={`${app.devId}`}>
|
||||
<div class="title">
|
||||
<div class="app-icon">
|
||||
<Icon size="L" name={app.icon?.name || "Apps"} color={app.icon?.color} />
|
||||
</div>
|
||||
<div class="name" data-cy="app-name-link">
|
||||
<div class="name">
|
||||
<Heading size="S">
|
||||
{app.name}
|
||||
</Heading>
|
||||
|
@ -56,7 +56,7 @@
|
|||
<Body size="S">{app.deployed ? "Published" : "Unpublished"}</Body>
|
||||
</div>
|
||||
|
||||
<div class="app-row-actions" data-cy={`row_actions_${app.appId}`}>
|
||||
<div class="app-row-actions">
|
||||
<AppLockModal {app} buttonSize="M" />
|
||||
<Button size="S" secondary on:click={goToOverview}>Manage</Button>
|
||||
<Button size="S" primary disabled={app.lockedOther} on:click={goToBuilder}>
|
||||
|
|
|
@ -138,7 +138,6 @@
|
|||
}
|
||||
|
||||
$goto(`/builder/app/${createdApp.instance._id}`)
|
||||
// apps.load()
|
||||
} catch (error) {
|
||||
creating = false
|
||||
console.error(error)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
import { ModalContent, Toggle, Body, InlineAlert } from "@budibase/bbui"
|
||||
import { licensing } from "stores/portal"
|
||||
|
||||
export let app
|
||||
export let published
|
||||
|
@ -17,11 +16,9 @@
|
|||
</script>
|
||||
|
||||
<ModalContent {title} {confirmText} onConfirm={exportApp}>
|
||||
{#if licensing.environmentVariablesEnabled}
|
||||
<InlineAlert
|
||||
header="Do not share your budibase application exports publicly as they may contain sensitive information such as database credentials or secret keys."
|
||||
/>
|
||||
{/if}
|
||||
<Body
|
||||
>Apps can be exported with or without data that is within internal tables -
|
||||
select this below.</Body
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
<div class="data">
|
||||
<Panel title="Sources" borderRight>
|
||||
<Layout paddingX="L" paddingY="XL" gap="S">
|
||||
<Button dataCy={`new-datasource`} cta on:click={modal.show}>
|
||||
Add source
|
||||
</Button>
|
||||
<Button cta on:click={modal.show}>Add source</Button>
|
||||
<CreateDatasourceModal bind:modal />
|
||||
<DatasourceNavigator />
|
||||
</Layout>
|
||||
|
|
|
@ -204,7 +204,7 @@
|
|||
store.actions.settings.highlight(data.setting)
|
||||
|
||||
// Also scroll setting into view
|
||||
const selector = `[data-cy="${data.setting}-prop-control"`
|
||||
const selector = `#${data.setting}-prop-control`
|
||||
const element = document.querySelector(selector)?.parentElement
|
||||
if (element) {
|
||||
element.scrollIntoView({
|
||||
|
|
|
@ -256,7 +256,6 @@
|
|||
draggable="true"
|
||||
on:dragstart={() => onDragStart(component.component)}
|
||||
on:dragend={onDragEnd}
|
||||
data-cy={`component-${component.name}`}
|
||||
class="component"
|
||||
class:selected={selectedIndex ===
|
||||
orderMap[component.component]}
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<span data-cy="data-source-modal">
|
||||
<span>
|
||||
<ModalContent
|
||||
title="Autogenerated screens"
|
||||
confirmText="Confirm"
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
selectedScreenMode = blankScreenModeKey
|
||||
}}
|
||||
>
|
||||
<div data-cy="blank-screen" class="content screen-type-wrap">
|
||||
<div class="content screen-type-wrap">
|
||||
<Icon name="WebPage" />
|
||||
<div class="screen-type-text">
|
||||
<Heading size="XS">Blank screen</Heading>
|
||||
|
@ -60,7 +60,7 @@
|
|||
class:disabled={!$tables.list.filter(table => table._id !== "ta_users")
|
||||
.length}
|
||||
>
|
||||
<div data-cy="autogenerated-screens" class="content screen-type-wrap">
|
||||
<div class="content screen-type-wrap">
|
||||
<Icon name="WebPages" />
|
||||
<div class="screen-type-text">
|
||||
<Heading size="XS">Autogenerated screens</Heading>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue