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 }}
|
PAYLOAD_VERSION: ${{ env.RELEASE_VERSION }}
|
||||||
with:
|
with:
|
||||||
repository: budibase/budibase-deploys
|
repository: budibase/budibase-deploys
|
||||||
event: deploy-develop-to-qa
|
event: deploy-budibase-develop-to-qa
|
||||||
github_pat: ${{ secrets.GH_ACCESS_TOKEN }}
|
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
|
||||||
- run: yarn bootstrap
|
- run: yarn bootstrap
|
||||||
- run: yarn build
|
- run: yarn build
|
||||||
- name: Pull cypress.env.yaml from budibase-infra
|
- name: Pull from budibase-infra
|
||||||
run: |
|
run: |
|
||||||
curl -H "Authorization: token ${{ secrets.GH_PERSONAL_TOKEN }}" \
|
curl -H "Authorization: token ${{ secrets.GH_PERSONAL_TOKEN }}" \
|
||||||
-H 'Accept: application/vnd.github.v3.raw' \
|
-H 'Accept: application/vnd.github.v3.raw' \
|
||||||
-o packages/builder/cypress.env.json \
|
-o
|
||||||
-L https://api.github.com/repos/budibase/budibase-infra/contents/test/cypress.env.json
|
-L
|
||||||
wc -l packages/builder/cypress.env.json
|
wc -l
|
||||||
|
|
||||||
- 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 }}
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: Test Reports
|
name: Test Reports
|
||||||
path: packages/builder/cypress/reports/testReport.html
|
path:
|
||||||
|
|
||||||
# TODO: enable once running in QA test env
|
# TODO: enable once running in QA test env
|
||||||
# - name: Configure AWS Credentials
|
# - name: Configure AWS Credentials
|
||||||
|
@ -54,11 +42,3 @@ jobs:
|
||||||
# - name: Upload test results HTML
|
# - name: Upload test results HTML
|
||||||
# uses: aws-actions/configure-aws-credentials@v1
|
# 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
|
# 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",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -51,10 +51,6 @@
|
||||||
"lint:fix:eslint": "eslint --fix packages qa-core",
|
"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: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",
|
"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: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": "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",
|
"build:docker:pre": "lerna run build && lerna run predocker",
|
||||||
|
@ -84,4 +80,4 @@
|
||||||
"install:pro": "bash scripts/pro/install.sh",
|
"install:pro": "bash scripts/pro/install.sh",
|
||||||
"dep:clean": "yarn clean && yarn bootstrap"
|
"dep:clean": "yarn clean && yarn bootstrap"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"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",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
"types": "dist/src/index.d.ts",
|
"types": "dist/src/index.d.ts",
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/nano": "10.1.1",
|
"@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",
|
"@shopify/jest-koa-mocks": "5.0.1",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
"aws-cloudfront-sign": "2.2.0",
|
"aws-cloudfront-sign": "2.2.0",
|
||||||
|
|
|
@ -15,18 +15,47 @@ import { getCouchInfo } from "./connections"
|
||||||
import { directCouchCall } from "./utils"
|
import { directCouchCall } from "./utils"
|
||||||
import { getPouchDB } from "./pouchDB"
|
import { getPouchDB } from "./pouchDB"
|
||||||
import { WriteStream, ReadStream } from "fs"
|
import { WriteStream, ReadStream } from "fs"
|
||||||
|
import { newid } from "../../newid"
|
||||||
|
|
||||||
|
function buildNano(couchInfo: { url: string; cookie: string }) {
|
||||||
|
return Nano({
|
||||||
|
url: couchInfo.url,
|
||||||
|
requestDefaults: {
|
||||||
|
headers: {
|
||||||
|
Authorization: couchInfo.cookie,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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 {
|
export class DatabaseImpl implements Database {
|
||||||
public readonly name: string
|
public readonly name: string
|
||||||
private static nano: Nano.ServerScope
|
private static nano: Nano.ServerScope
|
||||||
|
private readonly instanceNano?: Nano.ServerScope
|
||||||
private readonly pouchOpts: DatabaseOpts
|
private readonly pouchOpts: DatabaseOpts
|
||||||
|
|
||||||
constructor(dbName?: string, opts?: DatabaseOpts) {
|
constructor(dbName?: string, opts?: DatabaseOpts, connection?: string) {
|
||||||
if (dbName == null) {
|
if (dbName == null) {
|
||||||
throw new Error("Database name cannot be undefined.")
|
throw new Error("Database name cannot be undefined.")
|
||||||
}
|
}
|
||||||
this.name = dbName
|
this.name = dbName
|
||||||
this.pouchOpts = opts || {}
|
this.pouchOpts = opts || {}
|
||||||
|
if (connection) {
|
||||||
|
const couchInfo = getCouchInfo(connection)
|
||||||
|
this.instanceNano = buildNano(couchInfo)
|
||||||
|
}
|
||||||
if (!DatabaseImpl.nano) {
|
if (!DatabaseImpl.nano) {
|
||||||
DatabaseImpl.init()
|
DatabaseImpl.init()
|
||||||
}
|
}
|
||||||
|
@ -34,15 +63,7 @@ export class DatabaseImpl implements Database {
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
const couchInfo = getCouchInfo()
|
const couchInfo = getCouchInfo()
|
||||||
DatabaseImpl.nano = Nano({
|
DatabaseImpl.nano = buildNano(couchInfo)
|
||||||
url: couchInfo.url,
|
|
||||||
requestDefaults: {
|
|
||||||
headers: {
|
|
||||||
Authorization: couchInfo.cookie,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parseUrl: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async exists() {
|
async exists() {
|
||||||
|
@ -50,6 +71,10 @@ export class DatabaseImpl implements Database {
|
||||||
return response.status === 200
|
return response.status === 200
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private nano() {
|
||||||
|
return this.instanceNano || DatabaseImpl.nano
|
||||||
|
}
|
||||||
|
|
||||||
async checkSetup() {
|
async checkSetup() {
|
||||||
let shouldCreate = !this.pouchOpts?.skip_setup
|
let shouldCreate = !this.pouchOpts?.skip_setup
|
||||||
// check exists in a lightweight fashion
|
// check exists in a lightweight fashion
|
||||||
|
@ -58,9 +83,9 @@ export class DatabaseImpl implements Database {
|
||||||
throw new Error("DB does not exist")
|
throw new Error("DB does not exist")
|
||||||
}
|
}
|
||||||
if (!exists) {
|
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) {
|
private async updateOutput(fnc: any) {
|
||||||
|
@ -101,6 +126,13 @@ export class DatabaseImpl implements Database {
|
||||||
return this.updateOutput(() => db.destroy(_id, _rev))
|
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) {
|
async put(document: AnyDocument, opts?: DatabasePutOpts) {
|
||||||
if (!document._id) {
|
if (!document._id) {
|
||||||
throw new Error("Cannot store document without _id field.")
|
throw new Error("Cannot store document without _id field.")
|
||||||
|
@ -146,7 +178,7 @@ export class DatabaseImpl implements Database {
|
||||||
|
|
||||||
async destroy() {
|
async destroy() {
|
||||||
try {
|
try {
|
||||||
await DatabaseImpl.nano.db.destroy(this.name)
|
await this.nano().db.destroy(this.name)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
// didn't exist, don't worry
|
// didn't exist, don't worry
|
||||||
if (err.statusCode === 404) {
|
if (err.statusCode === 404) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import env from "../../environment"
|
import env from "../../environment"
|
||||||
|
|
||||||
export const getCouchInfo = () => {
|
export const getCouchInfo = (connection?: string) => {
|
||||||
const urlInfo = getUrlInfo()
|
const urlInfo = getUrlInfo(connection)
|
||||||
let username
|
let username
|
||||||
let password
|
let password
|
||||||
if (env.COUCH_DB_USERNAME) {
|
if (env.COUCH_DB_USERNAME) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/bbui",
|
"name": "@budibase/bbui",
|
||||||
"description": "A UI solution used in the different Budibase projects.",
|
"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",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
"@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/accordion": "3.0.24",
|
||||||
"@spectrum-css/actionbutton": "1.0.1",
|
"@spectrum-css/actionbutton": "1.0.1",
|
||||||
"@spectrum-css/actiongroup": "1.0.1",
|
"@spectrum-css/actiongroup": "1.0.1",
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
export let longPressable = false
|
export let longPressable = false
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let icon = ""
|
export let icon = ""
|
||||||
export let dataCy = null
|
|
||||||
export let size = "M"
|
export let size = "M"
|
||||||
export let active = false
|
export let active = false
|
||||||
export let fullWidth = false
|
export let fullWidth = false
|
||||||
|
@ -37,7 +36,6 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
data-cy={dataCy}
|
|
||||||
use:longPress
|
use:longPress
|
||||||
class:spectrum-ActionButton--quiet={quiet}
|
class:spectrum-ActionButton--quiet={quiet}
|
||||||
class:spectrum-ActionButton--emphasized={emphasized}
|
class:spectrum-ActionButton--emphasized={emphasized}
|
||||||
|
@ -88,7 +86,7 @@
|
||||||
}
|
}
|
||||||
.is-selected:not(.spectrum-ActionButton--emphasized):not(.spectrum-ActionButton--quiet) {
|
.is-selected:not(.spectrum-ActionButton--emphasized):not(.spectrum-ActionButton--quiet) {
|
||||||
background: var(--spectrum-global-color-gray-300);
|
background: var(--spectrum-global-color-gray-300);
|
||||||
border-color: var(--spectrum-global-color-gray-700);
|
border-color: var(--spectrum-global-color-gray-500);
|
||||||
}
|
}
|
||||||
.noPadding {
|
.noPadding {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let align = "left"
|
export let align = "left"
|
||||||
export let portalTarget
|
export let portalTarget
|
||||||
export let dataCy
|
|
||||||
|
|
||||||
let anchor
|
let anchor
|
||||||
let dropdown
|
let dropdown
|
||||||
|
@ -37,7 +36,7 @@
|
||||||
<div use:getAnchor on:click={openMenu}>
|
<div use:getAnchor on:click={openMenu}>
|
||||||
<slot name="control" />
|
<slot name="control" />
|
||||||
</div>
|
</div>
|
||||||
<Popover bind:this={dropdown} {anchor} {align} {portalTarget} {dataCy}>
|
<Popover bind:this={dropdown} {anchor} {align} {portalTarget}>
|
||||||
<Menu>
|
<Menu>
|
||||||
<slot />
|
<slot />
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
export default function positionDropdown(
|
export default function positionDropdown(element, opts) {
|
||||||
element,
|
let resizeObserver
|
||||||
{ anchor, align, maxWidth, useAnchorWidth }
|
let latestOpts = opts
|
||||||
) {
|
|
||||||
const update = () => {
|
// 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) {
|
if (!anchor) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute bounds
|
||||||
const anchorBounds = anchor.getBoundingClientRect()
|
const anchorBounds = anchor.getBoundingClientRect()
|
||||||
const elementBounds = element.getBoundingClientRect()
|
const elementBounds = element.getBoundingClientRect()
|
||||||
let styles = {
|
let styles = {
|
||||||
|
@ -20,9 +30,9 @@ export default function positionDropdown(
|
||||||
if (align === "right-outside") {
|
if (align === "right-outside") {
|
||||||
styles.top = anchorBounds.top
|
styles.top = anchorBounds.top
|
||||||
} else if (window.innerHeight - anchorBounds.bottom < 100) {
|
} else if (window.innerHeight - anchorBounds.bottom < 100) {
|
||||||
styles.top = anchorBounds.top - elementBounds.height - 5
|
styles.top = anchorBounds.top - elementBounds.height - offset
|
||||||
} else {
|
} else {
|
||||||
styles.top = anchorBounds.bottom + 5
|
styles.top = anchorBounds.bottom + offset
|
||||||
styles.maxHeight = window.innerHeight - anchorBounds.bottom - 20
|
styles.maxHeight = window.innerHeight - anchorBounds.bottom - 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +46,7 @@ export default function positionDropdown(
|
||||||
if (align === "right") {
|
if (align === "right") {
|
||||||
styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
|
styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
|
||||||
} else if (align === "right-outside") {
|
} else if (align === "right-outside") {
|
||||||
styles.left = anchorBounds.right + 10
|
styles.left = anchorBounds.right + offset
|
||||||
} else {
|
} else {
|
||||||
styles.left = anchorBounds.left
|
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
|
// Apply initial styles which don't need to change
|
||||||
element.style.position = "absolute"
|
element.style.position = "absolute"
|
||||||
element.style.zIndex = "9999"
|
element.style.zIndex = "9999"
|
||||||
|
|
||||||
// Observe both anchor and element and resize the popover as appropriate
|
// Set up a scroll listener
|
||||||
const resizeObserver = new ResizeObserver(entries => {
|
document.addEventListener("scroll", scrollUpdate, true)
|
||||||
entries.forEach(update)
|
|
||||||
})
|
|
||||||
if (anchor) {
|
|
||||||
resizeObserver.observe(anchor)
|
|
||||||
}
|
|
||||||
resizeObserver.observe(element)
|
|
||||||
resizeObserver.observe(document.body)
|
|
||||||
|
|
||||||
document.addEventListener("scroll", update, true)
|
// Perform initial update
|
||||||
|
update(opts)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
update,
|
||||||
destroy() {
|
destroy() {
|
||||||
resizeObserver.disconnect()
|
// Cleanup
|
||||||
document.removeEventListener("scroll", update, true)
|
if (resizeObserver) {
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
}
|
||||||
|
document.removeEventListener("scroll", scrollUpdate, true)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
export let icon = undefined
|
export let icon = undefined
|
||||||
export let active = false
|
export let active = false
|
||||||
export let tooltip = undefined
|
export let tooltip = undefined
|
||||||
export let dataCy
|
|
||||||
export let newStyles = true
|
export let newStyles = true
|
||||||
export let id
|
export let id
|
||||||
|
|
||||||
|
@ -33,7 +32,6 @@
|
||||||
class:disabled
|
class:disabled
|
||||||
class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
|
class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
|
||||||
{disabled}
|
{disabled}
|
||||||
data-cy={dataCy}
|
|
||||||
on:click|preventDefault
|
on:click|preventDefault
|
||||||
on:mouseover={() => (showTooltip = true)}
|
on:mouseover={() => (showTooltip = true)}
|
||||||
on:focus={() => (showTooltip = true)}
|
on:focus={() => (showTooltip = true)}
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
export let id = null
|
export let id = null
|
||||||
export let readonly = false
|
export let readonly = false
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
export let dataCy
|
|
||||||
export let align
|
export let align
|
||||||
export let autofocus = false
|
export let autofocus = false
|
||||||
export let variables
|
export let variables
|
||||||
|
@ -123,7 +122,6 @@
|
||||||
disabled={hbsValue.length || disabled}
|
disabled={hbsValue.length || disabled}
|
||||||
{readonly}
|
{readonly}
|
||||||
{id}
|
{id}
|
||||||
data-cy={dataCy}
|
|
||||||
value={hbsValue.length ? `{{ ${hbsValue[0]} }}` : value}
|
value={hbsValue.length ? `{{ ${hbsValue[0]} }}` : value}
|
||||||
placeholder={placeholder || ""}
|
placeholder={placeholder || ""}
|
||||||
on:click
|
on:click
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
export let id = null
|
export let id = null
|
||||||
export let text = null
|
export let text = null
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let dataCy = null
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const onChange = event => {
|
const onChange = event => {
|
||||||
|
@ -16,7 +15,6 @@
|
||||||
|
|
||||||
<div class="spectrum-Switch spectrum-Switch--emphasized">
|
<div class="spectrum-Switch spectrum-Switch--emphasized">
|
||||||
<input
|
<input
|
||||||
data-cy={dataCy}
|
|
||||||
checked={value}
|
checked={value}
|
||||||
{disabled}
|
{disabled}
|
||||||
on:change={onChange}
|
on:change={onChange}
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
export let readonly = false
|
export let readonly = false
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
export let quiet = false
|
export let quiet = false
|
||||||
export let dataCy
|
|
||||||
export let align
|
export let align
|
||||||
export let autofocus = false
|
export let autofocus = false
|
||||||
|
|
||||||
|
@ -89,7 +88,6 @@
|
||||||
{disabled}
|
{disabled}
|
||||||
{readonly}
|
{readonly}
|
||||||
{id}
|
{id}
|
||||||
data-cy={dataCy}
|
|
||||||
value={value || ""}
|
value={value || ""}
|
||||||
placeholder={placeholder || ""}
|
placeholder={placeholder || ""}
|
||||||
on:click
|
on:click
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
export let error = null
|
export let error = null
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
export let quiet = false
|
export let quiet = false
|
||||||
export let dataCy
|
|
||||||
export let autofocus
|
export let autofocus
|
||||||
export let variables
|
export let variables
|
||||||
export let showModal
|
export let showModal
|
||||||
|
@ -28,7 +27,6 @@
|
||||||
|
|
||||||
<Field {label} {labelPosition} {error}>
|
<Field {label} {labelPosition} {error}>
|
||||||
<EnvDropdown
|
<EnvDropdown
|
||||||
{dataCy}
|
|
||||||
{updateOnChange}
|
{updateOnChange}
|
||||||
{error}
|
{error}
|
||||||
{disabled}
|
{disabled}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
export let error = null
|
export let error = null
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
export let quiet = false
|
export let quiet = false
|
||||||
export let dataCy
|
|
||||||
export let autofocus
|
export let autofocus
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
@ -25,7 +24,6 @@
|
||||||
|
|
||||||
<Field {label} {labelPosition} {error}>
|
<Field {label} {labelPosition} {error}>
|
||||||
<TextField
|
<TextField
|
||||||
{dataCy}
|
|
||||||
{updateOnChange}
|
{updateOnChange}
|
||||||
{error}
|
{error}
|
||||||
{disabled}
|
{disabled}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
export let error = null
|
export let error = null
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
export let quiet = false
|
export let quiet = false
|
||||||
export let dataCy
|
|
||||||
export let autofocus
|
export let autofocus
|
||||||
export let options = []
|
export let options = []
|
||||||
|
|
||||||
|
@ -32,7 +31,6 @@
|
||||||
|
|
||||||
<Field {label} {labelPosition} {error}>
|
<Field {label} {labelPosition} {error}>
|
||||||
<InputDropdown
|
<InputDropdown
|
||||||
{dataCy}
|
|
||||||
{updateOnChange}
|
{updateOnChange}
|
||||||
{error}
|
{error}
|
||||||
{disabled}
|
{disabled}
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
export let getSecondaryOptionColour = () => {}
|
export let getSecondaryOptionColour = () => {}
|
||||||
export let getSecondaryOptionIcon = () => {}
|
export let getSecondaryOptionIcon = () => {}
|
||||||
export let quiet = false
|
export let quiet = false
|
||||||
export let dataCy
|
|
||||||
export let autofocus
|
export let autofocus
|
||||||
export let primaryOptions = []
|
export let primaryOptions = []
|
||||||
export let secondaryOptions = []
|
export let secondaryOptions = []
|
||||||
|
@ -98,7 +97,6 @@
|
||||||
<PickerDropdown
|
<PickerDropdown
|
||||||
{searchTerm}
|
{searchTerm}
|
||||||
{autocomplete}
|
{autocomplete}
|
||||||
{dataCy}
|
|
||||||
{error}
|
{error}
|
||||||
{disabled}
|
{disabled}
|
||||||
{readonly}
|
{readonly}
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
export let text = null
|
export let text = null
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let error = null
|
export let error = null
|
||||||
export let dataCy = null
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const onChange = e => {
|
const onChange = e => {
|
||||||
|
@ -19,5 +18,5 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Field {label} {labelPosition} {error}>
|
<Field {label} {labelPosition} {error}>
|
||||||
<Switch {dataCy} {error} {disabled} {text} {value} on:change={onChange} />
|
<Switch {error} {disabled} {text} {value} on:change={onChange} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const actionMenu = getContext("actionMenu")
|
const actionMenu = getContext("actionMenu")
|
||||||
|
|
||||||
export let dataCy
|
|
||||||
export let icon = undefined
|
export let icon = undefined
|
||||||
export let disabled = undefined
|
export let disabled = undefined
|
||||||
export let noClose = false
|
export let noClose = false
|
||||||
|
@ -35,7 +34,6 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<li
|
<li
|
||||||
data-cy={dataCy}
|
|
||||||
on:click|preventDefault={disabled ? null : onClick}
|
on:click|preventDefault={disabled ? null : onClick}
|
||||||
class="spectrum-Menu-item"
|
class="spectrum-Menu-item"
|
||||||
class:is-disabled={disabled}
|
class:is-disabled={disabled}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
export let secondaryButtonText = undefined
|
export let secondaryButtonText = undefined
|
||||||
export let secondaryAction = undefined
|
export let secondaryAction = undefined
|
||||||
export let secondaryButtonWarning = false
|
export let secondaryButtonWarning = false
|
||||||
export let dataCy = null
|
|
||||||
const { hide, cancel } = getContext(Context.Modal)
|
const { hide, cancel } = getContext(Context.Modal)
|
||||||
let loading = false
|
let loading = false
|
||||||
$: confirmDisabled = disabled || loading
|
$: confirmDisabled = disabled || loading
|
||||||
|
@ -63,7 +63,6 @@
|
||||||
role="dialog"
|
role="dialog"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
data-cy={dataCy}
|
|
||||||
>
|
>
|
||||||
<div class="spectrum-Dialog-grid">
|
<div class="spectrum-Dialog-grid">
|
||||||
{#if title || $$slots.header}
|
{#if title || $$slots.header}
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
export let anchor
|
export let anchor
|
||||||
export let align = "right"
|
export let align = "right"
|
||||||
export let portalTarget
|
export let portalTarget
|
||||||
export let dataCy
|
|
||||||
export let maxWidth
|
export let maxWidth
|
||||||
export let open = false
|
export let open = false
|
||||||
export let useAnchorWidth = false
|
export let useAnchorWidth = false
|
||||||
export let dismissible = true
|
export let dismissible = true
|
||||||
|
export let offset = 5
|
||||||
|
|
||||||
$: target = portalTarget || getContext(Context.PopoverRoot) || ".spectrum"
|
$: target = portalTarget || getContext(Context.PopoverRoot) || ".spectrum"
|
||||||
|
|
||||||
|
@ -57,31 +57,28 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if open}
|
{#if open}
|
||||||
{#key anchor}
|
<Portal {target}>
|
||||||
<Portal {target}>
|
<div
|
||||||
<div
|
tabindex="0"
|
||||||
tabindex="0"
|
use:positionDropdown={{
|
||||||
use:positionDropdown={{
|
anchor,
|
||||||
anchor,
|
align,
|
||||||
align,
|
maxWidth,
|
||||||
maxWidth,
|
useAnchorWidth,
|
||||||
useAnchorWidth,
|
offset,
|
||||||
showTip: false,
|
}}
|
||||||
}}
|
use:clickOutside={{
|
||||||
use:clickOutside={{
|
callback: dismissible ? handleOutsideClick : () => {},
|
||||||
callback: dismissible ? handleOutsideClick : () => {},
|
anchor,
|
||||||
anchor,
|
}}
|
||||||
}}
|
on:keydown={handleEscape}
|
||||||
on:keydown={handleEscape}
|
class="spectrum-Popover is-open"
|
||||||
class="spectrum-Popover is-open"
|
role="presentation"
|
||||||
role="presentation"
|
transition:fly|local={{ y: -20, duration: 200 }}
|
||||||
data-cy={dataCy}
|
>
|
||||||
transition:fly|local={{ y: -20, duration: 200 }}
|
<slot />
|
||||||
>
|
</div>
|
||||||
<slot />
|
</Portal>
|
||||||
</div>
|
|
||||||
</Portal>
|
|
||||||
{/key}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
export let icon = ""
|
export let icon = ""
|
||||||
export let selected = false
|
export let selected = false
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let dataCy
|
|
||||||
export let badge = ""
|
export let badge = ""
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
class:is-selected={selected}
|
class:is-selected={selected}
|
||||||
class:is-disabled={disabled}
|
class:is-disabled={disabled}
|
||||||
on:click
|
on:click
|
||||||
data-cy={dataCy}
|
|
||||||
>
|
>
|
||||||
{#if heading}
|
{#if heading}
|
||||||
<h2 class="spectrum-SideNav-heading" id="nav-heading-{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",
|
"name": "@budibase/builder",
|
||||||
"version": "2.2.12-alpha.55",
|
"version": "2.2.12-alpha.64",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -9,20 +9,7 @@
|
||||||
"dev:builder": "routify -c dev:vite",
|
"dev:builder": "routify -c dev:vite",
|
||||||
"dev:vite": "vite --host 0.0.0.0",
|
"dev:vite": "vite --host 0.0.0.0",
|
||||||
"rollup": "rollup -c -w",
|
"rollup": "rollup -c -w",
|
||||||
"test": "jest",
|
"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"
|
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"globals": {
|
"globals": {
|
||||||
|
@ -71,10 +58,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "2.2.12-alpha.55",
|
"@budibase/bbui": "2.2.12-alpha.64",
|
||||||
"@budibase/client": "2.2.12-alpha.55",
|
"@budibase/client": "2.2.12-alpha.64",
|
||||||
"@budibase/frontend-core": "2.2.12-alpha.55",
|
"@budibase/frontend-core": "2.2.12-alpha.64",
|
||||||
"@budibase/string-templates": "2.2.12-alpha.55",
|
"@budibase/string-templates": "2.2.12-alpha.64",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/free-solid-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
|
// normal development system
|
||||||
const SERVER_PORT = cypressConfig.env.PORT
|
const SERVER_PORT = testConfig.env.PORT
|
||||||
const WORKER_PORT = cypressConfig.env.WORKER_PORT
|
const WORKER_PORT = testConfig.env.WORKER_PORT
|
||||||
|
|
||||||
if (!process.env.NODE_ENV) {
|
if (!process.env.NODE_ENV) {
|
||||||
process.env.NODE_ENV = "cypress"
|
process.env.NODE_ENV = "cypress"
|
||||||
}
|
}
|
||||||
process.env.ENABLE_ANALYTICS = "0"
|
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.SELF_HOSTED = 1
|
||||||
process.env.WORKER_URL = `http://localhost:${WORKER_PORT}/`
|
process.env.WORKER_URL = `http://localhost:${WORKER_PORT}/`
|
||||||
process.env.APPS_URL = `http://localhost:${SERVER_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
|
// Stop info logs polluting test outputs
|
||||||
process.env.LOG_LEVEL = "error"
|
process.env.LOG_LEVEL = "error"
|
||||||
|
|
||||||
exports.run = (
|
exports.run = (serverLoc = "../server/dist", workerLoc = "../worker/dist") => {
|
||||||
serverLoc = "../../server/dist",
|
|
||||||
workerLoc = "../../worker/dist"
|
|
||||||
) => {
|
|
||||||
// require("dotenv").config({ path: resolve(dir, ".env") })
|
// require("dotenv").config({ path: resolve(dir, ".env") })
|
||||||
// don't make this a variable or top level require
|
// don't make this a variable or top level require
|
||||||
// it will cause environment module to be loaded prematurely
|
// it will cause environment module to be loaded prematurely
|
|
@ -509,21 +509,24 @@ const getSelectedRowsBindings = asset => {
|
||||||
return bindings
|
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.
|
* Gets all state bindings that are globally available.
|
||||||
*/
|
*/
|
||||||
const getStateBindings = () => {
|
const getStateBindings = () => {
|
||||||
let bindings = []
|
let bindings = []
|
||||||
if (get(store).clientFeatures?.state) {
|
if (get(store).clientFeatures?.state) {
|
||||||
const safeState = makePropSafe("state")
|
bindings = getAllStateVariables().map(makeStateBinding)
|
||||||
bindings = getAllStateVariables().map(key => ({
|
|
||||||
type: "context",
|
|
||||||
runtimeBinding: `${safeState}.${makePropSafe(key)}`,
|
|
||||||
readableBinding: `State.${key}`,
|
|
||||||
category: "State",
|
|
||||||
icon: "AutomatedSegment",
|
|
||||||
display: { name: key },
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,13 +42,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if type === "options" && meta.constraints.inclusion.length !== 0}
|
{#if type === "options" && meta.constraints.inclusion.length !== 0}
|
||||||
<Select
|
<Select {label} bind:value options={meta.constraints.inclusion} sort />
|
||||||
{label}
|
|
||||||
data-cy="{meta.name}-select"
|
|
||||||
bind:value
|
|
||||||
options={meta.constraints.inclusion}
|
|
||||||
sort
|
|
||||||
/>
|
|
||||||
{:else if type === "datetime"}
|
{:else if type === "datetime"}
|
||||||
<DatePicker
|
<DatePicker
|
||||||
{error}
|
{error}
|
||||||
|
@ -61,7 +55,7 @@
|
||||||
{:else if type === "attachment"}
|
{:else if type === "attachment"}
|
||||||
<Dropzone {label} {error} bind:value />
|
<Dropzone {label} {error} bind:value />
|
||||||
{:else if type === "boolean"}
|
{: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}
|
{:else if type === "array" && meta.constraints.inclusion.length !== 0}
|
||||||
<Multiselect
|
<Multiselect
|
||||||
bind:value
|
bind:value
|
||||||
|
@ -87,12 +81,5 @@
|
||||||
{error}
|
{error}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<Input
|
<Input {label} {type} {error} bind:value disabled={readonly} />
|
||||||
{label}
|
|
||||||
data-cy="{meta.name}-input"
|
|
||||||
{type}
|
|
||||||
{error}
|
|
||||||
bind:value
|
|
||||||
disabled={readonly}
|
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -546,9 +546,5 @@
|
||||||
Your data will be deleted and this action cannot be undone - enter the column
|
Your data will be deleted and this action cannot be undone - enter the column
|
||||||
name to confirm.
|
name to confirm.
|
||||||
</p>
|
</p>
|
||||||
<Input
|
<Input bind:value={deleteColName} placeholder={originalName} />
|
||||||
dataCy="delete-column-confirm"
|
|
||||||
bind:value={deleteColName}
|
|
||||||
placeholder={originalName}
|
|
||||||
/>
|
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
|
@ -119,7 +119,6 @@
|
||||||
selection is always undefined -->
|
selection is always undefined -->
|
||||||
<Select
|
<Select
|
||||||
label="Role"
|
label="Role"
|
||||||
data-cy="roleId-select"
|
|
||||||
bind:value={row.roleId}
|
bind:value={row.roleId}
|
||||||
options={$roles}
|
options={$roles}
|
||||||
getOptionLabel={role => role.name}
|
getOptionLabel={role => role.name}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</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}>
|
<Modal bind:this={modal}>
|
||||||
<svelte:component this={modalContentComponent} {row} />
|
<svelte:component this={modalContentComponent} {row} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
disabled={error || !name || !datasource?.type}
|
disabled={error || !name || !datasource?.type}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
data-cy="datasource-name-input"
|
|
||||||
label="Datasource Name"
|
label="Datasource Name"
|
||||||
on:input={checkValid}
|
on:input={checkValid}
|
||||||
bind:value={name}
|
bind:value={name}
|
||||||
|
|
|
@ -6,13 +6,7 @@
|
||||||
export let indented
|
export let indented
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div class:indented class:selected on:click class={className}>
|
||||||
data-cy="table-nav-item"
|
|
||||||
class:indented
|
|
||||||
class:selected
|
|
||||||
on:click
|
|
||||||
class={className}
|
|
||||||
>
|
|
||||||
<i class={icon} />
|
<i class={icon} />
|
||||||
<span>{title}</span>
|
<span>{title}</span>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
@ -108,7 +108,6 @@
|
||||||
disabled={error || !name || (rows.length && !allValid)}
|
disabled={error || !name || (rows.length && !allValid)}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
data-cy="table-name-input"
|
|
||||||
thin
|
thin
|
||||||
label="Table Name"
|
label="Table Name"
|
||||||
on:input={checkValid}
|
on:input={checkValid}
|
||||||
|
|
|
@ -134,11 +134,7 @@
|
||||||
This action cannot be undone - to continue please enter the table name below
|
This action cannot be undone - to continue please enter the table name below
|
||||||
to confirm.
|
to confirm.
|
||||||
</p>
|
</p>
|
||||||
<Input
|
<Input bind:value={deleteTableName} placeholder={table.name} />
|
||||||
bind:value={deleteTableName}
|
|
||||||
placeholder={table.name}
|
|
||||||
dataCy="delete-table-confirm"
|
|
||||||
/>
|
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -74,7 +74,6 @@
|
||||||
<Modal bind:this={appLockModal}>
|
<Modal bind:this={appLockModal}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title={lockedByHeading}
|
title={lockedByHeading}
|
||||||
dataCy={"app-lock-modal"}
|
|
||||||
showConfirmButton={false}
|
showConfirmButton={false}
|
||||||
showCancelButton={false}
|
showCancelButton={false}
|
||||||
>
|
>
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
export let onCancel = undefined
|
export let onCancel = undefined
|
||||||
export let warning = true
|
export let warning = true
|
||||||
export let disabled
|
export let disabled
|
||||||
export let dataCy = null
|
|
||||||
|
|
||||||
let modal
|
let modal
|
||||||
|
|
||||||
|
@ -29,7 +28,6 @@
|
||||||
{cancelText}
|
{cancelText}
|
||||||
{warning}
|
{warning}
|
||||||
{disabled}
|
{disabled}
|
||||||
{dataCy}
|
|
||||||
>
|
>
|
||||||
<Body size="S">
|
<Body size="S">
|
||||||
{body}
|
{body}
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
export let title = ""
|
export let title = ""
|
||||||
export let actionIcon
|
export let actionIcon
|
||||||
export let action
|
export let action
|
||||||
export let dataCy
|
|
||||||
|
|
||||||
$: actionDefined = typeof action === "function"
|
$: actionDefined = typeof action === "function"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="dash-card" data-cy={dataCy}>
|
<div class="dash-card">
|
||||||
<div class="dash-card-header" class:active={actionDefined} on:click={action}>
|
<div class="dash-card-header" class:active={actionDefined} on:click={action}>
|
||||||
<span class="dash-card-title">
|
<span class="dash-card-title">
|
||||||
<Detail size="M">{title}</Detail>
|
<Detail size="M">{title}</Detail>
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
<div class="template-categories">
|
<div class="template-categories">
|
||||||
<Layout gap="XL" noPadding>
|
<Layout gap="XL" noPadding>
|
||||||
{#each filteredCategories as category}
|
{#each filteredCategories as category}
|
||||||
<div class="template-category" data-cy={category.name}>
|
<div class="template-category">
|
||||||
<Detail size="M">{category.name}</Detail>
|
<Detail size="M">{category.name}</Detail>
|
||||||
<div class="template-grid">
|
<div class="template-grid">
|
||||||
{#each category.templates as templateEntry}
|
{#each category.templates as templateEntry}
|
||||||
|
|
|
@ -66,11 +66,7 @@
|
||||||
{error}
|
{error}
|
||||||
/>
|
/>
|
||||||
{#if !disabled}
|
{#if !disabled}
|
||||||
<div
|
<div class="icon" on:click={bindingDrawer.show}>
|
||||||
class="icon"
|
|
||||||
on:click={bindingDrawer.show}
|
|
||||||
data-cy="text-binding-button"
|
|
||||||
>
|
|
||||||
<Icon size="S" name="FlashOn" />
|
<Icon size="S" name="FlashOn" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
export let label = null
|
export let label = null
|
||||||
export let value
|
export let value
|
||||||
export let dataCy = null
|
|
||||||
|
|
||||||
const copyToClipboard = val => {
|
const copyToClipboard = val => {
|
||||||
const dummy = document.createElement("textarea")
|
const dummy = document.createElement("textarea")
|
||||||
|
@ -16,7 +15,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div data-cy={dataCy}>
|
<div>
|
||||||
<Input readonly {value} {label} />
|
<Input readonly {value} {label} />
|
||||||
<div class="icon" on:click={() => copyToClipboard(value)}>
|
<div class="icon" on:click={() => copyToClipboard(value)}>
|
||||||
<Icon size="S" name="Copy" />
|
<Icon size="S" name="Copy" />
|
||||||
|
|
|
@ -66,7 +66,6 @@
|
||||||
title="Publish to production"
|
title="Publish to production"
|
||||||
confirmText="Publish"
|
confirmText="Publish"
|
||||||
onConfirm={publishApp}
|
onConfirm={publishApp}
|
||||||
dataCy={"deploy-app-modal"}
|
|
||||||
>
|
>
|
||||||
The changes you have made will be published to the production version of the
|
The changes you have made will be published to the production version of the
|
||||||
application.
|
application.
|
||||||
|
@ -88,12 +87,7 @@
|
||||||
|
|
||||||
<!-- Publish complete -->
|
<!-- Publish complete -->
|
||||||
<Modal bind:this={publishCompleteModal}>
|
<Modal bind:this={publishCompleteModal}>
|
||||||
<ModalContent
|
<ModalContent confirmText="Done" cancelText="View App" onCancel={viewApp}>
|
||||||
confirmText="Done"
|
|
||||||
cancelText="View App"
|
|
||||||
onCancel={viewApp}
|
|
||||||
dataCy="deploy-app-success-modal"
|
|
||||||
>
|
|
||||||
<div slot="header" class="app-published-header">
|
<div slot="header" class="app-published-header">
|
||||||
<svg
|
<svg
|
||||||
width="26px"
|
width="26px"
|
||||||
|
@ -105,11 +99,7 @@
|
||||||
</svg>
|
</svg>
|
||||||
<span class="app-published-header-text">App Published!</span>
|
<span class="app-published-header-text">App Published!</span>
|
||||||
</div>
|
</div>
|
||||||
<CopyInput
|
<CopyInput value={publishedUrl} label="You can view your app at:" />
|
||||||
value={publishedUrl}
|
|
||||||
label="You can view your app at:"
|
|
||||||
dataCy="deployed-app-url"
|
|
||||||
/>
|
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
|
|
@ -124,36 +124,37 @@
|
||||||
bind:this={publishPopover}
|
bind:this={publishPopover}
|
||||||
align="right"
|
align="right"
|
||||||
disabled={!isPublished}
|
disabled={!isPublished}
|
||||||
dataCy="publish-popover-menu"
|
|
||||||
anchor={publishPopoverAnchor}
|
anchor={publishPopoverAnchor}
|
||||||
|
offset={10}
|
||||||
>
|
>
|
||||||
<Layout gap="M">
|
<div class="popover-content">
|
||||||
<Heading size="XS">Your published app</Heading>
|
<Layout noPadding gap="M">
|
||||||
<Body size="S">
|
<Heading size="XS">Your published app</Heading>
|
||||||
<span class="publish-popover-message">
|
<Body size="S">
|
||||||
{processStringSync(
|
<span class="publish-popover-message">
|
||||||
"Last published {{ duration time 'millisecond' }} ago",
|
{processStringSync(
|
||||||
{
|
"Last published {{ duration time 'millisecond' }} ago",
|
||||||
time:
|
{
|
||||||
new Date().getTime() -
|
time:
|
||||||
new Date(latestDeployments[0].updatedAt).getTime(),
|
new Date().getTime() -
|
||||||
}
|
new Date(latestDeployments[0].updatedAt).getTime(),
|
||||||
)}
|
}
|
||||||
</span>
|
)}
|
||||||
</Body>
|
</span>
|
||||||
<div class="publish-popover-actions">
|
</Body>
|
||||||
<Button
|
<div class="buttons">
|
||||||
warning={true}
|
<Button
|
||||||
icon="GlobeStrike"
|
warning={true}
|
||||||
disabled={!isPublished}
|
icon="GlobeStrike"
|
||||||
on:click={unpublishApp}
|
disabled={!isPublished}
|
||||||
dataCy="publish-popover-action"
|
on:click={unpublishApp}
|
||||||
>
|
>
|
||||||
Unpublish
|
Unpublish
|
||||||
</Button>
|
</Button>
|
||||||
<Button cta on:click={viewApp}>View app</Button>
|
<Button cta on:click={viewApp}>View app</Button>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
</div>
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -172,7 +173,6 @@
|
||||||
title="Confirm unpublish"
|
title="Confirm unpublish"
|
||||||
okText="Unpublish app"
|
okText="Unpublish app"
|
||||||
onOk={confirmUnpublishApp}
|
onOk={confirmUnpublishApp}
|
||||||
dataCy={"unpublish-modal"}
|
|
||||||
>
|
>
|
||||||
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
|
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
@ -183,11 +183,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.publish-popover-actions :global([data-cy="publish-popover-action"]) {
|
.popover-content {
|
||||||
margin-right: var(--spacing-s);
|
padding: var(--spacing-xl);
|
||||||
}
|
|
||||||
:global([data-cy="publish-popover-menu"]) {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
}
|
||||||
.buttons {
|
.buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
hoverable
|
hoverable
|
||||||
on:click={revertModal.show}
|
on:click={revertModal.show}
|
||||||
tooltip="Revert changes"
|
tooltip="Revert changes"
|
||||||
dataCy="revert-application-topnav"
|
|
||||||
/>
|
/>
|
||||||
<Modal bind:this={revertModal}>
|
<Modal bind:this={revertModal}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
|
|
|
@ -11,7 +11,10 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { getAvailableActions } from "./index"
|
import { getAvailableActions } from "./index"
|
||||||
import { generate } from "shortid"
|
import { generate } from "shortid"
|
||||||
import { getEventContextBindings } from "builderStore/dataBinding"
|
import {
|
||||||
|
getEventContextBindings,
|
||||||
|
makeStateBinding,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
import { currentAsset, store } from "builderStore"
|
import { currentAsset, store } from "builderStore"
|
||||||
|
|
||||||
const flipDurationMs = 150
|
const flipDurationMs = 150
|
||||||
|
@ -52,7 +55,7 @@
|
||||||
actions,
|
actions,
|
||||||
selectedAction?.id
|
selectedAction?.id
|
||||||
)
|
)
|
||||||
$: allBindings = eventContexBindings.concat(bindings)
|
$: allBindings = getAllBindings(bindings, eventContexBindings, actions)
|
||||||
$: {
|
$: {
|
||||||
// Ensure each action has a unique ID
|
// Ensure each action has a unique ID
|
||||||
if (actions) {
|
if (actions) {
|
||||||
|
@ -111,6 +114,33 @@
|
||||||
function handleDndFinalize(e) {
|
function handleDndFinalize(e) {
|
||||||
actions = e.detail.items
|
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>
|
</script>
|
||||||
|
|
||||||
<DrawerContent>
|
<DrawerContent>
|
||||||
|
@ -186,7 +216,7 @@
|
||||||
<div class="selected-action-container">
|
<div class="selected-action-container">
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={selectedActionComponent}
|
this={selectedActionComponent}
|
||||||
parameters={selectedAction.parameters}
|
bind:parameters={selectedAction.parameters}
|
||||||
bindings={allBindings}
|
bindings={allBindings}
|
||||||
{nested}
|
{nested}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -193,11 +193,7 @@
|
||||||
</Drawer>
|
</Drawer>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<Popover
|
<Popover bind:this={dropdownRight} anchor={anchorRight}>
|
||||||
bind:this={dropdownRight}
|
|
||||||
anchor={anchorRight}
|
|
||||||
dataCy={`dataSource-popover-${$store.selectedComponentId}`}
|
|
||||||
>
|
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading size="XS">Tables</Heading>
|
<Heading size="XS">Tables</Heading>
|
||||||
|
|
|
@ -121,12 +121,7 @@
|
||||||
{displayValue}
|
{displayValue}
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
<Popover
|
<Popover bind:this={dropdown} on:open={setSelectedUI} anchor={buttonAnchor}>
|
||||||
bind:this={dropdown}
|
|
||||||
on:open={setSelectedUI}
|
|
||||||
anchor={buttonAnchor}
|
|
||||||
dataCy="icon-popover"
|
|
||||||
>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="search-area">
|
<div class="search-area">
|
||||||
<div class="alphabet-area">
|
<div class="alphabet-area">
|
||||||
|
|
|
@ -74,17 +74,13 @@
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div class="property-control" class:highlighted={highlighted && nullishValue}>
|
||||||
class="property-control"
|
|
||||||
class:highlighted={highlighted && nullishValue}
|
|
||||||
data-cy={`setting-${key}`}
|
|
||||||
>
|
|
||||||
{#if type !== "boolean" && label}
|
{#if type !== "boolean" && label}
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<Label>{label}</Label>
|
<Label>{label}</Label>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div data-cy={`${key}-prop-control`} class="control">
|
<div id={`${key}-prop-control`} class="control">
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={control}
|
this={control}
|
||||||
{componentInstance}
|
{componentInstance}
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
let developmentValue
|
let developmentValue
|
||||||
let useProductionValue = true
|
let useProductionValue = true
|
||||||
|
|
||||||
|
const HasSpacesRegex = /[\\"\s]/
|
||||||
|
|
||||||
const deleteVariable = async name => {
|
const deleteVariable = async name => {
|
||||||
try {
|
try {
|
||||||
await environment.deleteVariable(name)
|
await environment.deleteVariable(name)
|
||||||
|
@ -47,10 +49,16 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent
|
<ModalContent
|
||||||
|
disabled={HasSpacesRegex.test(name)}
|
||||||
onConfirm={() => saveVariable()}
|
onConfirm={() => saveVariable()}
|
||||||
title={!row ? "Add new environment variable" : "Edit environment variable"}
|
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>
|
<div>
|
||||||
<Heading size="XS">Production</Heading>
|
<Heading size="XS">Production</Heading>
|
||||||
<Input
|
<Input
|
||||||
|
|
|
@ -108,59 +108,62 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#key tourStepKey}
|
{#if tourKey}
|
||||||
<Popover
|
{#key tourStepKey}
|
||||||
align={tourStep?.align}
|
<Popover
|
||||||
bind:this={popover}
|
align={tourStep?.align}
|
||||||
anchor={popoverAnchor}
|
bind:this={popover}
|
||||||
dataCy="tour-popover-menu"
|
anchor={popoverAnchor}
|
||||||
maxWidth={300}
|
maxWidth={300}
|
||||||
dismissible={false}
|
dismissible={false}
|
||||||
>
|
offset={15}
|
||||||
<Layout gap="M">
|
>
|
||||||
<div class="tour-header">
|
<div class="tour-content">
|
||||||
<Heading size="XS">{tourStep?.title || "-"}</Heading>
|
<Layout noPadding gap="M">
|
||||||
<div>{`${tourStepIdx + 1}/${tourSteps?.length}`}</div>
|
<div class="tour-header">
|
||||||
|
<Heading size="XS">{tourStep?.title || "-"}</Heading>
|
||||||
|
<div>{`${tourStepIdx + 1}/${tourSteps?.length}`}</div>
|
||||||
|
</div>
|
||||||
|
<Body size="S">
|
||||||
|
<span class="tour-body">
|
||||||
|
{#if tourStep.layout}
|
||||||
|
<svelte:component this={tourStep.layout} />
|
||||||
|
{:else}
|
||||||
|
{tourStep?.body || ""}
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</Body>
|
||||||
|
<div class="tour-footer">
|
||||||
|
<div class="tour-navigation">
|
||||||
|
{#if tourStepIdx > 0}
|
||||||
|
<Button
|
||||||
|
secondary
|
||||||
|
on:click={previousStep}
|
||||||
|
disabled={tourStepIdx == 0}
|
||||||
|
>
|
||||||
|
<div>Back</div>
|
||||||
|
</Button>
|
||||||
|
{/if}
|
||||||
|
<Button cta on:click={nextStep}>
|
||||||
|
<div>{lastStep ? "Finish" : "Next"}</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
</div>
|
</div>
|
||||||
<Body size="S">
|
</Popover>
|
||||||
<span class="tour-body">
|
{/key}
|
||||||
{#if tourStep.layout}
|
{/if}
|
||||||
<svelte:component this={tourStep.layout} />
|
|
||||||
{:else}
|
|
||||||
{tourStep?.body || ""}
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
</Body>
|
|
||||||
<div class="tour-footer">
|
|
||||||
<div class="tour-navigation">
|
|
||||||
{#if tourStepIdx > 0}
|
|
||||||
<Button
|
|
||||||
secondary
|
|
||||||
on:click={previousStep}
|
|
||||||
disabled={tourStepIdx == 0}
|
|
||||||
>
|
|
||||||
<div>Back</div>
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
<Button cta on:click={nextStep}>
|
|
||||||
<div>{lastStep ? "Finish" : "Next"}</div>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
</Popover>
|
|
||||||
{/key}
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.tour-content {
|
||||||
|
padding: var(--spacing-xl);
|
||||||
|
}
|
||||||
.tour-navigation {
|
.tour-navigation {
|
||||||
grid-gap: var(--spectrum-alias-grid-baseline);
|
grid-gap: var(--spectrum-alias-grid-baseline);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
}
|
}
|
||||||
:global([data-cy="tour-popover-menu"]) {
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: var(--spacing-l);
|
|
||||||
}
|
|
||||||
.tour-body :global(.feature-list) {
|
.tour-body :global(.feature-list) {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
padding-left: var(--spacing-xl);
|
padding-left: var(--spacing-xl);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div>
|
<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">
|
<ul class="feature-list">
|
||||||
<li>Connect data sources</li>
|
<li>Connect data sources</li>
|
||||||
<li>Edit data</li>
|
<li>Edit data</li>
|
||||||
|
|
|
@ -23,14 +23,6 @@
|
||||||
Personalise the platform by adding your first name and last name.
|
Personalise the platform by adding your first name and last name.
|
||||||
</Body>
|
</Body>
|
||||||
<Input disabled bind:value={$auth.user.email} label="Email" />
|
<Input disabled bind:value={$auth.user.email} label="Email" />
|
||||||
<Input
|
<Input bind:value={$values.firstName} label="First name" />
|
||||||
bind:value={$values.firstName}
|
<Input bind:value={$values.lastName} label="Last name" />
|
||||||
label="First name"
|
|
||||||
dataCy="user-first-name"
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
bind:value={$values.lastName}
|
|
||||||
label="Last name"
|
|
||||||
dataCy="user-last-name"
|
|
||||||
/>
|
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -30,11 +30,11 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="app-row" on:click={handleDefaultClick}>
|
<div class="app-row" on:click={handleDefaultClick}>
|
||||||
<div class="title" data-cy={`${app.devId}`}>
|
<div class="title">
|
||||||
<div class="app-icon">
|
<div class="app-icon">
|
||||||
<Icon size="L" name={app.icon?.name || "Apps"} color={app.icon?.color} />
|
<Icon size="L" name={app.icon?.name || "Apps"} color={app.icon?.color} />
|
||||||
</div>
|
</div>
|
||||||
<div class="name" data-cy="app-name-link">
|
<div class="name">
|
||||||
<Heading size="S">
|
<Heading size="S">
|
||||||
{app.name}
|
{app.name}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
<Body size="S">{app.deployed ? "Published" : "Unpublished"}</Body>
|
<Body size="S">{app.deployed ? "Published" : "Unpublished"}</Body>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="app-row-actions" data-cy={`row_actions_${app.appId}`}>
|
<div class="app-row-actions">
|
||||||
<AppLockModal {app} buttonSize="M" />
|
<AppLockModal {app} buttonSize="M" />
|
||||||
<Button size="S" secondary on:click={goToOverview}>Manage</Button>
|
<Button size="S" secondary on:click={goToOverview}>Manage</Button>
|
||||||
<Button size="S" primary disabled={app.lockedOther} on:click={goToBuilder}>
|
<Button size="S" primary disabled={app.lockedOther} on:click={goToBuilder}>
|
||||||
|
|
|
@ -138,7 +138,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$goto(`/builder/app/${createdApp.instance._id}`)
|
$goto(`/builder/app/${createdApp.instance._id}`)
|
||||||
// apps.load()
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
creating = false
|
creating = false
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { ModalContent, Toggle, Body, InlineAlert } from "@budibase/bbui"
|
import { ModalContent, Toggle, Body, InlineAlert } from "@budibase/bbui"
|
||||||
import { licensing } from "stores/portal"
|
|
||||||
|
|
||||||
export let app
|
export let app
|
||||||
export let published
|
export let published
|
||||||
|
@ -17,11 +16,9 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent {title} {confirmText} onConfirm={exportApp}>
|
<ModalContent {title} {confirmText} onConfirm={exportApp}>
|
||||||
{#if licensing.environmentVariablesEnabled}
|
<InlineAlert
|
||||||
<InlineAlert
|
header="Do not share your budibase application exports publicly as they may contain sensitive information such as database credentials or secret keys."
|
||||||
header="Do not share your budibase application exports publicly as they may contain sensitive information such as database credentials or secret keys."
|
/>
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
<Body
|
<Body
|
||||||
>Apps can be exported with or without data that is within internal tables -
|
>Apps can be exported with or without data that is within internal tables -
|
||||||
select this below.</Body
|
select this below.</Body
|
||||||
|
|
|
@ -11,9 +11,7 @@
|
||||||
<div class="data">
|
<div class="data">
|
||||||
<Panel title="Sources" borderRight>
|
<Panel title="Sources" borderRight>
|
||||||
<Layout paddingX="L" paddingY="XL" gap="S">
|
<Layout paddingX="L" paddingY="XL" gap="S">
|
||||||
<Button dataCy={`new-datasource`} cta on:click={modal.show}>
|
<Button cta on:click={modal.show}>Add source</Button>
|
||||||
Add source
|
|
||||||
</Button>
|
|
||||||
<CreateDatasourceModal bind:modal />
|
<CreateDatasourceModal bind:modal />
|
||||||
<DatasourceNavigator />
|
<DatasourceNavigator />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -204,7 +204,7 @@
|
||||||
store.actions.settings.highlight(data.setting)
|
store.actions.settings.highlight(data.setting)
|
||||||
|
|
||||||
// Also scroll setting into view
|
// 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
|
const element = document.querySelector(selector)?.parentElement
|
||||||
if (element) {
|
if (element) {
|
||||||
element.scrollIntoView({
|
element.scrollIntoView({
|
||||||
|
|
|
@ -256,7 +256,6 @@
|
||||||
draggable="true"
|
draggable="true"
|
||||||
on:dragstart={() => onDragStart(component.component)}
|
on:dragstart={() => onDragStart(component.component)}
|
||||||
on:dragend={onDragEnd}
|
on:dragend={onDragEnd}
|
||||||
data-cy={`component-${component.name}`}
|
|
||||||
class="component"
|
class="component"
|
||||||
class:selected={selectedIndex ===
|
class:selected={selectedIndex ===
|
||||||
orderMap[component.component]}
|
orderMap[component.component]}
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<span data-cy="data-source-modal">
|
<span>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title="Autogenerated screens"
|
title="Autogenerated screens"
|
||||||
confirmText="Confirm"
|
confirmText="Confirm"
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
selectedScreenMode = blankScreenModeKey
|
selectedScreenMode = blankScreenModeKey
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div data-cy="blank-screen" class="content screen-type-wrap">
|
<div class="content screen-type-wrap">
|
||||||
<Icon name="WebPage" />
|
<Icon name="WebPage" />
|
||||||
<div class="screen-type-text">
|
<div class="screen-type-text">
|
||||||
<Heading size="XS">Blank screen</Heading>
|
<Heading size="XS">Blank screen</Heading>
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
class:disabled={!$tables.list.filter(table => table._id !== "ta_users")
|
class:disabled={!$tables.list.filter(table => table._id !== "ta_users")
|
||||||
.length}
|
.length}
|
||||||
>
|
>
|
||||||
<div data-cy="autogenerated-screens" class="content screen-type-wrap">
|
<div class="content screen-type-wrap">
|
||||||
<Icon name="WebPages" />
|
<Icon name="WebPages" />
|
||||||
<div class="screen-type-text">
|
<div class="screen-type-text">
|
||||||
<Heading size="XS">Autogenerated screens</Heading>
|
<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