chore: Hardened take flakes
This commit is contained in:
parent
1499d5bdf5
commit
5690ef521a
|
|
@ -42,7 +42,7 @@ export function connectEventStreamIfNeeded () {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.websocketAvailable || reconnectTimer != null) {
|
if (connectionState.connected || reconnectTimer != null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,6 +54,7 @@ export function initWebsocket () {
|
||||||
window.addEventListener('EventOutputChunk', onOutputChunk)
|
window.addEventListener('EventOutputChunk', onOutputChunk)
|
||||||
window.addEventListener('EventExecutionStarted', onExecutionChanged)
|
window.addEventListener('EventExecutionStarted', onExecutionChanged)
|
||||||
window.addEventListener('EventExecutionFinished', onExecutionChanged)
|
window.addEventListener('EventExecutionFinished', onExecutionChanged)
|
||||||
|
window.addEventListener('pagehide', stopEventStream)
|
||||||
listenersInitialized = true
|
listenersInitialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,7 +68,7 @@ export function requestReconnectNow () {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.websocketAvailable) {
|
if (connectionState.connected) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +110,7 @@ async function reconnectWebsocket () {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.websocketAvailable) {
|
if (connectionState.connected) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -261,10 +261,15 @@ async function startAction(actionArgs) {
|
||||||
requestReconnectNow()
|
requestReconnectNow()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await window.client.startAction(startActionArgs)
|
const response = await window.client.startAction(startActionArgs)
|
||||||
|
const trackingId = response.executionTrackingId || startActionArgs.uniqueTrackingId
|
||||||
|
|
||||||
|
if (popupOnStart.value && popupOnStart.value.includes('execution-dialog')) {
|
||||||
|
router.push(`/logs/${trackingId}`)
|
||||||
|
}
|
||||||
|
|
||||||
if (!connectionState.connected) {
|
if (!connectionState.connected) {
|
||||||
await pollExecutionUntilDone(startActionArgs.uniqueTrackingId)
|
await pollExecutionUntilDone(trackingId)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to start action:', err)
|
console.error('Failed to start action:', err)
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ import { onMounted, onUnmounted, ref, computed, watch } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { HugeiconsIcon } from '@hugeicons/vue'
|
import { HugeiconsIcon } from '@hugeicons/vue'
|
||||||
import { Loading03Icon, ArrowLeftIcon } from '@hugeicons/core-free-icons'
|
import { Loading03Icon, ArrowLeftIcon } from '@hugeicons/core-free-icons'
|
||||||
import { requestReconnectNow } from '../../js/websocket.js'
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
|
|
@ -107,8 +106,6 @@ function goBack() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDashboard() {
|
async function getDashboard() {
|
||||||
requestReconnectNow()
|
|
||||||
|
|
||||||
let title = props.title
|
let title = props.title
|
||||||
|
|
||||||
// If no specific title was provided or it's the placeholder 'default',
|
// If no specific title was provided or it's the placeholder 'default',
|
||||||
|
|
@ -167,6 +164,8 @@ async function getDashboard() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitForInitAndLoadDashboard() {
|
function waitForInitAndLoadDashboard() {
|
||||||
|
document.body.removeAttribute('loaded-dashboard')
|
||||||
|
|
||||||
if (loadingTimer) {
|
if (loadingTimer) {
|
||||||
clearInterval(loadingTimer)
|
clearInterval(loadingTimer)
|
||||||
loadingTimer = null
|
loadingTimer = null
|
||||||
|
|
@ -226,6 +225,8 @@ watch(
|
||||||
)
|
)
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
document.body.removeAttribute('loaded-dashboard')
|
||||||
|
|
||||||
// Clean up the timers when component is unmounted
|
// Clean up the timers when component is unmounted
|
||||||
if (loadingTimer) {
|
if (loadingTimer) {
|
||||||
clearInterval(loadingTimer)
|
clearInterval(loadingTimer)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
|
||||||
|
import Dashboard from './Dashboard.vue'
|
||||||
|
|
||||||
import { Wrench01Icon } from '@hugeicons/core-free-icons'
|
import { Wrench01Icon } from '@hugeicons/core-free-icons'
|
||||||
import { LeftToRightListDashIcon } from '@hugeicons/core-free-icons'
|
import { LeftToRightListDashIcon } from '@hugeicons/core-free-icons'
|
||||||
import { CellsIcon } from '@hugeicons/core-free-icons'
|
import { CellsIcon } from '@hugeicons/core-free-icons'
|
||||||
|
|
@ -9,13 +11,13 @@ const routes = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'Actions',
|
name: 'Actions',
|
||||||
component: () => import('./Dashboard.vue'),
|
component: Dashboard,
|
||||||
meta: { title: 'Actions', icon: DashboardSquare01Icon }
|
meta: { title: 'Actions', icon: DashboardSquare01Icon }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/dashboards/:title/:entityType?/:entityKey?',
|
path: '/dashboards/:title/:entityType?/:entityKey?',
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
component: () => import('./Dashboard.vue'),
|
component: Dashboard,
|
||||||
props: true,
|
props: true,
|
||||||
meta: { title: 'Dashboard' }
|
meta: { title: 'Dashboard' }
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import fs from 'fs'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { Condition } from 'selenium-webdriver'
|
import { Condition } from 'selenium-webdriver'
|
||||||
|
|
||||||
|
export const DEFAULT_UI_WAIT_MS = 3000
|
||||||
|
|
||||||
export async function getActionButtons () {
|
export async function getActionButtons () {
|
||||||
// Currently, only the active dashboard's contents are rendered,
|
// Currently, only the active dashboard's contents are rendered,
|
||||||
// so we don't need to scope the selector by dashboard title.
|
// so we don't need to scope the selector by dashboard title.
|
||||||
|
|
@ -46,20 +48,59 @@ export function takeScreenshot (webdriver, title) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRootAndWait() {
|
export async function waitForDashboardLoaded(timeoutMs = DEFAULT_UI_WAIT_MS) {
|
||||||
await webdriver.get(runner.baseUrl())
|
|
||||||
await webdriver.wait(new Condition('wait for loaded-dashboard', async function () {
|
await webdriver.wait(new Condition('wait for loaded-dashboard', async function () {
|
||||||
const body = await webdriver.findElement(By.tagName('body'))
|
const body = await webdriver.findElement(By.tagName('body'))
|
||||||
const attr = await body.getAttribute('loaded-dashboard')
|
const attr = await body.getAttribute('loaded-dashboard')
|
||||||
|
|
||||||
console.log('loaded-dashboard: ', attr)
|
console.log('loaded-dashboard: ', attr)
|
||||||
|
|
||||||
if (attr) {
|
return attr != null && attr !== ''
|
||||||
return true
|
}), timeoutMs)
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
export async function waitForLogsPage(timeoutMs = DEFAULT_UI_WAIT_MS) {
|
||||||
|
await webdriver.wait(new Condition('wait for logs page', async () => {
|
||||||
|
const url = await webdriver.getCurrentUrl()
|
||||||
|
return url.includes('/logs/') && !url.endsWith('/logs')
|
||||||
|
}), timeoutMs)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function waitForArgumentFormPage(timeoutMs = DEFAULT_UI_WAIT_MS) {
|
||||||
|
await webdriver.wait(new Condition('wait for argument form page', async () => {
|
||||||
|
const url = await webdriver.getCurrentUrl()
|
||||||
|
return url.includes('/actionBinding/') && url.includes('/argumentForm')
|
||||||
|
}), timeoutMs)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function waitForArgumentFormReady(timeoutMs = DEFAULT_UI_WAIT_MS) {
|
||||||
|
await webdriver.wait(new Condition('wait for argument form ready', async () => {
|
||||||
|
const body = await webdriver.findElement(By.tagName('body'))
|
||||||
|
const attr = await body.getAttribute('loaded-argument-form')
|
||||||
|
return attr != null && attr !== ''
|
||||||
|
}), timeoutMs)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function waitForExecutionComplete(timeoutMs = DEFAULT_UI_WAIT_MS) {
|
||||||
|
await webdriver.wait(new Condition('wait for execution status', async () => {
|
||||||
|
const statusElements = await webdriver.findElements(By.id('execution-dialog-status'))
|
||||||
|
return statusElements.length > 0
|
||||||
|
}), timeoutMs)
|
||||||
|
|
||||||
|
await webdriver.wait(new Condition('wait for execution to finish', async () => {
|
||||||
|
try {
|
||||||
|
const statusElement = await webdriver.findElement(By.id('execution-dialog-status'))
|
||||||
|
const statusText = await statusElement.getText()
|
||||||
|
return !statusText.includes('Still running')
|
||||||
|
} catch (e) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}))
|
}), timeoutMs)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getRootAndWait() {
|
||||||
|
await webdriver.get(runner.baseUrl())
|
||||||
|
await waitForDashboardLoaded()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function closeSidebar() {
|
export async function closeSidebar() {
|
||||||
|
|
@ -82,7 +123,7 @@ export async function closeSidebar() {
|
||||||
console.log('Sidebar closed, left is: *' + left, left === neededLeft ? ' (as expected)' : '')
|
console.log('Sidebar closed, left is: *' + left, left === neededLeft ? ' (as expected)' : '')
|
||||||
return left === neededLeft
|
return left === neededLeft
|
||||||
}
|
}
|
||||||
}), 10000); // Wait up to 10 seconds for the sidebar to close
|
}), DEFAULT_UI_WAIT_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openSidebar() {
|
export async function openSidebar() {
|
||||||
|
|
@ -103,7 +144,7 @@ export async function openSidebar() {
|
||||||
console.log('Sidebar opened, left is: ', left)
|
console.log('Sidebar opened, left is: ', left)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}));
|
}), DEFAULT_UI_WAIT_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getNavigationLinks() {
|
export async function getNavigationLinks() {
|
||||||
|
|
@ -123,7 +164,7 @@ export async function requireExecutionDialogStatus (webdriver, expected) {
|
||||||
console.log('Waiting for domStatus text to be: ', expected, ', it is currently: ', actual)
|
console.log('Waiting for domStatus text to be: ', expected, ', it is currently: ', actual)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}))
|
}), DEFAULT_UI_WAIT_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findExecutionDialog (webdriver) {
|
export async function findExecutionDialog (webdriver) {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ class OliveTinTestRunner {
|
||||||
|
|
||||||
class OliveTinTestRunnerStartLocalProcess extends OliveTinTestRunner {
|
class OliveTinTestRunnerStartLocalProcess extends OliveTinTestRunner {
|
||||||
async start (cfg) {
|
async start (cfg) {
|
||||||
|
if (this.ot != null && this.ot.exitCode == null) {
|
||||||
|
await this.stop()
|
||||||
|
}
|
||||||
|
|
||||||
let stdout = ""
|
let stdout = ""
|
||||||
let stderr = ""
|
let stderr = ""
|
||||||
|
|
||||||
|
|
@ -94,13 +98,23 @@ class OliveTinTestRunnerStartLocalProcess extends OliveTinTestRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
async stop () {
|
async stop () {
|
||||||
if ((await this.ot.exitCode) != null) {
|
if (this.ot == null) {
|
||||||
console.log(" OliveTin local process tried stop(), but it already exited with code", this.ot.exitCode)
|
return
|
||||||
} else {
|
|
||||||
await this.ot.kill()
|
|
||||||
console.log(" OliveTin local process killed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.ot.exitCode != null) {
|
||||||
|
console.log(' OliveTin local process tried stop(), but it already exited with code', this.ot.exitCode)
|
||||||
|
} else {
|
||||||
|
const closed = new Promise((resolve) => {
|
||||||
|
this.ot.once('close', resolve)
|
||||||
|
})
|
||||||
|
this.ot.kill('SIGTERM')
|
||||||
|
await closed
|
||||||
|
console.log(' OliveTin local process killed')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ot = null
|
||||||
|
|
||||||
if (process.env.CI === 'true') {
|
if (process.env.CI === 'true') {
|
||||||
// GitHub runners seem to need a bit more time to clean up
|
// GitHub runners seem to need a bit more time to clean up
|
||||||
await new Promise((res) => setTimeout(res, 3000))
|
await new Promise((res) => setTimeout(res, 3000))
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,14 @@ import { describe, it, before, after } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { By, Condition } from 'selenium-webdriver'
|
import { By, Condition } from 'selenium-webdriver'
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_UI_WAIT_MS,
|
||||||
getRootAndWait,
|
getRootAndWait,
|
||||||
getActionButton,
|
getActionButton,
|
||||||
takeScreenshotOnFailure,
|
takeScreenshotOnFailure,
|
||||||
getTerminalBuffer,
|
getTerminalBuffer,
|
||||||
|
waitForArgumentFormPage,
|
||||||
|
waitForLogsPage,
|
||||||
|
waitForExecutionComplete,
|
||||||
} from '../../lib/elements.js'
|
} from '../../lib/elements.js'
|
||||||
|
|
||||||
async function openCheckboxArgumentForm() {
|
async function openCheckboxArgumentForm() {
|
||||||
|
|
@ -13,13 +17,7 @@ async function openCheckboxArgumentForm() {
|
||||||
const btn = await getActionButton(webdriver, 'Test checkbox argument')
|
const btn = await getActionButton(webdriver, 'Test checkbox argument')
|
||||||
await btn.click()
|
await btn.click()
|
||||||
|
|
||||||
await webdriver.wait(
|
await waitForArgumentFormPage()
|
||||||
new Condition('wait for argument form page', async () => {
|
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/actionBinding/') && url.includes('/argumentForm')
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getCheckboxInput() {
|
async function getCheckboxInput() {
|
||||||
|
|
@ -31,42 +29,6 @@ async function submitCheckboxForm() {
|
||||||
await submitButton.click()
|
await submitButton.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForLogsPage() {
|
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for logs page', async () => {
|
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/logs/') && !url.endsWith('/logs')
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitForExecutionComplete() {
|
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for execution status', async () => {
|
|
||||||
const statusElements = await webdriver.findElements(By.id('execution-dialog-status'))
|
|
||||||
return statusElements.length > 0
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
|
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for execution to finish', async () => {
|
|
||||||
try {
|
|
||||||
const statusElement = await webdriver.findElement(By.id('execution-dialog-status'))
|
|
||||||
const statusText = await statusElement.getText()
|
|
||||||
return !statusText.includes('Executing')
|
|
||||||
} catch (e) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
|
|
||||||
// Small delay to allow terminal to write output
|
|
||||||
await webdriver.sleep(500)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitForTerminalOutput(expectedValue) {
|
async function waitForTerminalOutput(expectedValue) {
|
||||||
await webdriver.wait(
|
await webdriver.wait(
|
||||||
new Condition(`wait for checkbox value ${expectedValue} in output`, async () => {
|
new Condition(`wait for checkbox value ${expectedValue} in output`, async () => {
|
||||||
|
|
@ -88,7 +50,7 @@ async function waitForTerminalOutput(expectedValue) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
5000
|
DEFAULT_UI_WAIT_MS
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +80,6 @@ describe('config: checkbox', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Checkbox argument submits 0 by default when unchecked', async function () {
|
it('Checkbox argument submits 0 by default when unchecked', async function () {
|
||||||
this.timeout(15000)
|
|
||||||
await openCheckboxArgumentForm()
|
await openCheckboxArgumentForm()
|
||||||
|
|
||||||
const checkboxInput = await getCheckboxInput()
|
const checkboxInput = await getCheckboxInput()
|
||||||
|
|
@ -131,7 +92,6 @@ describe('config: checkbox', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Checkbox argument can be toggled and submitted', async function () {
|
it('Checkbox argument can be toggled and submitted', async function () {
|
||||||
this.timeout(15000)
|
|
||||||
await openCheckboxArgumentForm()
|
await openCheckboxArgumentForm()
|
||||||
|
|
||||||
const checkboxInput = await getCheckboxInput()
|
const checkboxInput = await getCheckboxInput()
|
||||||
|
|
@ -146,5 +106,3 @@ describe('config: checkbox', function () {
|
||||||
await waitForTerminalOutput('1')
|
await waitForTerminalOutput('1')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import { describe, it, before, after } from 'mocha'
|
import { describe, it, before, after } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { By, Condition } from 'selenium-webdriver'
|
import { By } from 'selenium-webdriver'
|
||||||
import {
|
import {
|
||||||
getRootAndWait,
|
getRootAndWait,
|
||||||
getActionButton,
|
getActionButton,
|
||||||
takeScreenshotOnFailure,
|
takeScreenshotOnFailure,
|
||||||
|
waitForArgumentFormPage,
|
||||||
|
waitForLogsPage,
|
||||||
} from '../../lib/elements.js'
|
} from '../../lib/elements.js'
|
||||||
|
|
||||||
describe('config: datetime', function () {
|
describe('config: datetime', function () {
|
||||||
|
|
@ -27,14 +29,7 @@ describe('config: datetime', function () {
|
||||||
|
|
||||||
await btn.click()
|
await btn.click()
|
||||||
|
|
||||||
// Wait for navigation to argument form page
|
await waitForArgumentFormPage()
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for argument form page', async () => {
|
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/actionBinding/') && url.includes('/argumentForm')
|
|
||||||
}),
|
|
||||||
8000
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the datetime input field
|
// Find the datetime input field
|
||||||
const datetimeInput = await webdriver.findElement(By.id('datetime'))
|
const datetimeInput = await webdriver.findElement(By.id('datetime'))
|
||||||
|
|
@ -59,14 +54,7 @@ describe('config: datetime', function () {
|
||||||
|
|
||||||
await btn.click()
|
await btn.click()
|
||||||
|
|
||||||
// Wait for navigation to argument form page
|
await waitForArgumentFormPage()
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for argument form page', async () => {
|
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/actionBinding/') && url.includes('/argumentForm')
|
|
||||||
}),
|
|
||||||
8000
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the datetime input field
|
// Find the datetime input field
|
||||||
const datetimeInput = await webdriver.findElement(By.id('datetime'))
|
const datetimeInput = await webdriver.findElement(By.id('datetime'))
|
||||||
|
|
@ -101,18 +89,10 @@ describe('config: datetime', function () {
|
||||||
)
|
)
|
||||||
await submitButton.click()
|
await submitButton.click()
|
||||||
|
|
||||||
// Wait for navigation to logs page
|
await waitForLogsPage()
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for logs page', async () => {
|
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/logs/')
|
|
||||||
}),
|
|
||||||
8000
|
|
||||||
)
|
|
||||||
|
|
||||||
// Verify we're on the logs page (action was executed)
|
// Verify we're on the logs page (action was executed)
|
||||||
const url = await webdriver.getCurrentUrl()
|
const url = await webdriver.getCurrentUrl()
|
||||||
expect(url).to.include('/logs/')
|
expect(url).to.include('/logs/')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ describe('config: enabledExpression', function () {
|
||||||
}
|
}
|
||||||
// Accept either decoded or encoded version (component should decode, but handle both)
|
// Accept either decoded or encoded version (component should decode, but handle both)
|
||||||
return attr === 'LightDashboard'
|
return attr === 'LightDashboard'
|
||||||
}), 10000)
|
}), 3000)
|
||||||
|
|
||||||
// Verify we got the correct dashboard (prefer decoded, but accept encoded)
|
// Verify we got the correct dashboard (prefer decoded, but accept encoded)
|
||||||
const body = await webdriver.findElement(By.tagName('body'))
|
const body = await webdriver.findElement(By.tagName('body'))
|
||||||
|
|
@ -127,7 +127,7 @@ describe('config: enabledExpression', function () {
|
||||||
await webdriver.get(runner.baseUrl())
|
await webdriver.get(runner.baseUrl())
|
||||||
|
|
||||||
// Wait for action buttons
|
// Wait for action buttons
|
||||||
await webdriver.wait(until.elementLocated(By.css('.action-button')), 10000)
|
await webdriver.wait(until.elementLocated(By.css('.action-button')), 3000)
|
||||||
|
|
||||||
// Find "Always Enabled Action" button
|
// Find "Always Enabled Action" button
|
||||||
const actionButtons = await webdriver.findElements(By.css('.action-button button'))
|
const actionButtons = await webdriver.findElements(By.css('.action-button button'))
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
import { describe, it, before, after } from 'mocha'
|
import { describe, it, before, after } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { By, until } from 'selenium-webdriver'
|
import { By } from 'selenium-webdriver'
|
||||||
import {
|
import {
|
||||||
getRootAndWait,
|
getRootAndWait,
|
||||||
takeScreenshot,
|
|
||||||
takeScreenshotOnFailure,
|
takeScreenshotOnFailure,
|
||||||
} from '../../lib/elements.js'
|
} from '../../lib/elements.js'
|
||||||
|
|
||||||
describe('config: entities', function () {
|
describe('config: entities', function () {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await runner.start('entities')
|
await runner.start('entities')
|
||||||
|
await getRootAndWait()
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
// Issue: https://github.com/OliveTin/OliveTin/issues/616
|
// Issue: https://github.com/OliveTin/OliveTin/issues/616
|
||||||
import { describe, it, before, after } from 'mocha'
|
import { describe, it, before, after } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { By, until, Condition } from 'selenium-webdriver'
|
import { By } from 'selenium-webdriver'
|
||||||
import {
|
import {
|
||||||
getRootAndWait,
|
getRootAndWait,
|
||||||
getActionButtons,
|
getActionButtons,
|
||||||
takeScreenshotOnFailure,
|
takeScreenshotOnFailure,
|
||||||
|
waitForLogsPage,
|
||||||
|
waitForExecutionComplete,
|
||||||
} from '../../lib/elements.js'
|
} from '../../lib/elements.js'
|
||||||
|
|
||||||
describe('config: entities', function () {
|
describe('config: entityFilesWithLongIntsUseStandardForm', function () {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await runner.start('entityFilesWithLongIntsUseStandardForm')
|
await runner.start('entityFilesWithLongIntsUseStandardForm')
|
||||||
|
await getRootAndWait()
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
|
|
@ -34,19 +37,9 @@ describe('config: entities', function () {
|
||||||
expect(await buttonInt10.getAttribute('title')).to.be.equal('Test me INT with 10 numbers')
|
expect(await buttonInt10.getAttribute('title')).to.be.equal('Test me INT with 10 numbers')
|
||||||
await buttonInt10.click()
|
await buttonInt10.click()
|
||||||
|
|
||||||
// Wait for navigation to execution view
|
await waitForLogsPage()
|
||||||
await webdriver.wait(new Condition('wait for execution view', async () => {
|
await waitForExecutionComplete()
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/logs/') && !url.endsWith('/logs')
|
|
||||||
}), 10000)
|
|
||||||
|
|
||||||
// Wait for execution to complete - look for the execution status
|
|
||||||
await webdriver.wait(new Condition('wait for execution status', async () => {
|
|
||||||
const statusElement = await webdriver.findElements(By.id('execution-dialog-status'))
|
|
||||||
return statusElement.length > 0
|
|
||||||
}), 15000)
|
|
||||||
|
|
||||||
// Check that the execution completed successfully by looking at the status
|
|
||||||
const statusElement = await webdriver.findElement(By.id('execution-dialog-status'))
|
const statusElement = await webdriver.findElement(By.id('execution-dialog-status'))
|
||||||
const statusText = await statusElement.getText()
|
const statusText = await statusElement.getText()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,32 +2,54 @@ import { describe, it, before, after } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { By, Condition } from 'selenium-webdriver'
|
import { By, Condition } from 'selenium-webdriver'
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_UI_WAIT_MS,
|
||||||
getRootAndWait,
|
getRootAndWait,
|
||||||
getActionButton,
|
getActionButton,
|
||||||
takeScreenshotOnFailure,
|
takeScreenshotOnFailure,
|
||||||
|
waitForDashboardLoaded,
|
||||||
|
waitForLogsPage,
|
||||||
|
waitForArgumentFormPage,
|
||||||
|
waitForArgumentFormReady,
|
||||||
|
waitForExecutionComplete,
|
||||||
} from '../../lib/elements.js'
|
} from '../../lib/elements.js'
|
||||||
|
|
||||||
async function openArgumentForm() {
|
async function ensureOnDashboard() {
|
||||||
|
let url = await webdriver.getCurrentUrl()
|
||||||
|
|
||||||
|
if (url.includes('/logs/')) {
|
||||||
|
const backButton = await webdriver.findElement(By.css('button[title="Go back"]'))
|
||||||
|
await backButton.click()
|
||||||
|
await webdriver.wait(
|
||||||
|
new Condition('wait for argument form after logs back', async () => {
|
||||||
|
const currentUrl = await webdriver.getCurrentUrl()
|
||||||
|
return currentUrl.includes('/argumentForm')
|
||||||
|
}),
|
||||||
|
DEFAULT_UI_WAIT_MS
|
||||||
|
)
|
||||||
|
url = await webdriver.getCurrentUrl()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.includes('/argumentForm')) {
|
||||||
|
const cancelButton = await webdriver.findElement(By.css('button[name="cancel"]'))
|
||||||
|
await cancelButton.click()
|
||||||
|
await waitForDashboardLoaded()
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionButtons = await webdriver.findElements(By.css('[title="Test suggestionsBrowserKey"]'))
|
||||||
|
if (actionButtons.length === 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await getRootAndWait()
|
await getRootAndWait()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openArgumentForm() {
|
||||||
|
await ensureOnDashboard()
|
||||||
const btn = await getActionButton(webdriver, 'Test suggestionsBrowserKey')
|
const btn = await getActionButton(webdriver, 'Test suggestionsBrowserKey')
|
||||||
await btn.click()
|
await btn.click()
|
||||||
|
|
||||||
await webdriver.wait(
|
await waitForArgumentFormPage()
|
||||||
new Condition('wait for argument form page', async () => {
|
await waitForArgumentFormReady()
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/actionBinding/') && url.includes('/argumentForm')
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
|
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for argument form ready', async () => {
|
|
||||||
const body = await webdriver.findElement(By.css('body'))
|
|
||||||
const attr = await body.getAttribute('loaded-argument-form')
|
|
||||||
return attr != null && attr !== ''
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTestInput() {
|
async function getTestInput() {
|
||||||
|
|
@ -47,41 +69,6 @@ async function submitForm() {
|
||||||
await submitButton.click()
|
await submitButton.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForLogsPage() {
|
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for logs page', async () => {
|
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/logs/') && !url.endsWith('/logs')
|
|
||||||
}),
|
|
||||||
15000
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitForExecutionComplete() {
|
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for execution status', async () => {
|
|
||||||
const statusElements = await webdriver.findElements(By.id('execution-dialog-status'))
|
|
||||||
return statusElements.length > 0
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
|
|
||||||
await webdriver.wait(
|
|
||||||
new Condition('wait for execution to finish', async () => {
|
|
||||||
try {
|
|
||||||
const statusElement = await webdriver.findElement(By.id('execution-dialog-status'))
|
|
||||||
const statusText = await statusElement.getText()
|
|
||||||
return !statusText.includes('Still running')
|
|
||||||
} catch (e) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
|
|
||||||
await webdriver.sleep(500)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getLocalStorageItem(key) {
|
async function getLocalStorageItem(key) {
|
||||||
return await webdriver.executeScript(`return localStorage.getItem('${key}')`)
|
return await webdriver.executeScript(`return localStorage.getItem('${key}')`)
|
||||||
}
|
}
|
||||||
|
|
@ -93,6 +80,7 @@ async function clearLocalStorage() {
|
||||||
describe('config: suggestionsBrowserKey', function () {
|
describe('config: suggestionsBrowserKey', function () {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await runner.start('suggestionsBrowserKey')
|
await runner.start('suggestionsBrowserKey')
|
||||||
|
await getRootAndWait()
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
|
|
@ -122,11 +110,7 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Submitting form saves value to localStorage', async function () {
|
it('Submitting form saves value to localStorage', async function () {
|
||||||
this.timeout(15000)
|
|
||||||
|
|
||||||
// Clear localStorage first
|
|
||||||
await clearLocalStorage()
|
await clearLocalStorage()
|
||||||
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
|
|
||||||
const input = await getTestInput()
|
const input = await getTestInput()
|
||||||
|
|
@ -140,7 +124,6 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
await waitForLogsPage()
|
await waitForLogsPage()
|
||||||
await waitForExecutionComplete()
|
await waitForExecutionComplete()
|
||||||
|
|
||||||
// Verify value was saved to localStorage
|
|
||||||
const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
|
const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
|
||||||
expect(stored).to.not.be.null
|
expect(stored).to.not.be.null
|
||||||
|
|
||||||
|
|
@ -150,26 +133,20 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Previously saved values appear in datalist', async function () {
|
it('Previously saved values appear in datalist', async function () {
|
||||||
this.timeout(15000)
|
|
||||||
|
|
||||||
// First, save a value to localStorage
|
|
||||||
const testValue = 'savedsuggestion456'
|
const testValue = 'savedsuggestion456'
|
||||||
await webdriver.executeScript(`
|
await webdriver.executeScript(`
|
||||||
const key = 'olivetin-suggestions-test-suggestions-key';
|
const key = 'olivetin-suggestions-test-suggestions-key';
|
||||||
localStorage.setItem(key, JSON.stringify(['${testValue}']));
|
localStorage.setItem(key, JSON.stringify(['${testValue}']));
|
||||||
`)
|
`)
|
||||||
|
|
||||||
// Open the form
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
|
|
||||||
// Check that datalist exists and contains the saved value
|
|
||||||
const datalist = await webdriver.findElement(By.id('testInput-choices'))
|
const datalist = await webdriver.findElement(By.id('testInput-choices'))
|
||||||
expect(datalist).to.not.be.null
|
expect(datalist).to.not.be.null
|
||||||
|
|
||||||
const options = await getDatalistOptions()
|
const options = await getDatalistOptions()
|
||||||
expect(options.length).to.be.greaterThan(0)
|
expect(options.length).to.be.greaterThan(0)
|
||||||
|
|
||||||
// Check if the saved value appears in the datalist
|
|
||||||
let foundValue = false
|
let foundValue = false
|
||||||
for (const option of options) {
|
for (const option of options) {
|
||||||
const value = await option.getAttribute('value')
|
const value = await option.getAttribute('value')
|
||||||
|
|
@ -182,12 +159,8 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Multiple submissions accumulate suggestions', async function () {
|
it('Multiple submissions accumulate suggestions', async function () {
|
||||||
this.timeout(20000)
|
|
||||||
|
|
||||||
// Clear localStorage first
|
|
||||||
await clearLocalStorage()
|
await clearLocalStorage()
|
||||||
|
|
||||||
// Submit first value
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
const input1 = await getTestInput()
|
const input1 = await getTestInput()
|
||||||
await input1.clear()
|
await input1.clear()
|
||||||
|
|
@ -196,7 +169,6 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
await waitForLogsPage()
|
await waitForLogsPage()
|
||||||
await waitForExecutionComplete()
|
await waitForExecutionComplete()
|
||||||
|
|
||||||
// Submit second value
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
const input2 = await getTestInput()
|
const input2 = await getTestInput()
|
||||||
await input2.clear()
|
await input2.clear()
|
||||||
|
|
@ -205,7 +177,6 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
await waitForLogsPage()
|
await waitForLogsPage()
|
||||||
await waitForExecutionComplete()
|
await waitForExecutionComplete()
|
||||||
|
|
||||||
// Verify both values are in localStorage
|
|
||||||
const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
|
const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
|
||||||
expect(stored).to.not.be.null
|
expect(stored).to.not.be.null
|
||||||
|
|
||||||
|
|
@ -213,43 +184,33 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
expect(suggestions).to.be.an('array')
|
expect(suggestions).to.be.an('array')
|
||||||
expect(suggestions).to.include('firstvalue')
|
expect(suggestions).to.include('firstvalue')
|
||||||
expect(suggestions).to.include('secondvalue')
|
expect(suggestions).to.include('secondvalue')
|
||||||
expect(suggestions[0]).to.equal('secondvalue') // Most recent should be first
|
expect(suggestions[0]).to.equal('secondvalue')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Empty values are not saved to localStorage', async function () {
|
it('Empty values are not saved to localStorage', async function () {
|
||||||
this.timeout(15000)
|
|
||||||
|
|
||||||
// Clear localStorage first
|
|
||||||
await clearLocalStorage()
|
await clearLocalStorage()
|
||||||
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
|
|
||||||
const input = await getTestInput()
|
const input = await getTestInput()
|
||||||
// Leave input empty (or clear it if it has a default)
|
|
||||||
await input.clear()
|
await input.clear()
|
||||||
|
|
||||||
await submitForm()
|
await submitForm()
|
||||||
await waitForLogsPage()
|
await waitForLogsPage()
|
||||||
await waitForExecutionComplete()
|
await waitForExecutionComplete()
|
||||||
|
|
||||||
// Verify empty value was not saved - localStorage should be null or empty-equivalent
|
|
||||||
const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
|
const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
|
||||||
// Should be null OR empty JSON array string ("[]") OR parse to empty array
|
|
||||||
if (stored !== null) {
|
if (stored !== null) {
|
||||||
const suggestions = JSON.parse(stored)
|
const suggestions = JSON.parse(stored)
|
||||||
expect(suggestions).to.be.an('array')
|
expect(suggestions).to.be.an('array')
|
||||||
expect(suggestions).to.have.length(0)
|
expect(suggestions).to.have.length(0)
|
||||||
}
|
}
|
||||||
// If stored is null, that's also acceptable - no assertion needed
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Suggestions are shared across inputs with the same suggestionsBrowserKey', async function () {
|
it('Suggestions are shared across inputs with the same suggestionsBrowserKey', async function () {
|
||||||
this.timeout(20000)
|
this.timeout(12000)
|
||||||
|
|
||||||
// Clear localStorage first
|
|
||||||
await clearLocalStorage()
|
await clearLocalStorage()
|
||||||
|
|
||||||
// Submit a value using the first input
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
const input1 = await getTestInput()
|
const input1 = await getTestInput()
|
||||||
await input1.clear()
|
await input1.clear()
|
||||||
|
|
@ -258,10 +219,8 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
await waitForLogsPage()
|
await waitForLogsPage()
|
||||||
await waitForExecutionComplete()
|
await waitForExecutionComplete()
|
||||||
|
|
||||||
// Open the form again and verify the value appears in both datalists
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
|
|
||||||
// Check first input's datalist
|
|
||||||
const datalist1 = await webdriver.findElement(By.id('testInput-choices'))
|
const datalist1 = await webdriver.findElement(By.id('testInput-choices'))
|
||||||
expect(datalist1).to.not.be.null
|
expect(datalist1).to.not.be.null
|
||||||
const options1 = await getDatalistOptions('testInput')
|
const options1 = await getDatalistOptions('testInput')
|
||||||
|
|
@ -275,7 +234,6 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
}
|
}
|
||||||
expect(foundInInput1).to.be.true
|
expect(foundInInput1).to.be.true
|
||||||
|
|
||||||
// Check second input's datalist
|
|
||||||
const datalist2 = await webdriver.findElement(By.id('testInput2-choices'))
|
const datalist2 = await webdriver.findElement(By.id('testInput2-choices'))
|
||||||
expect(datalist2).to.not.be.null
|
expect(datalist2).to.not.be.null
|
||||||
const options2 = await getDatalistOptions('testInput2')
|
const options2 = await getDatalistOptions('testInput2')
|
||||||
|
|
@ -289,7 +247,6 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
}
|
}
|
||||||
expect(foundInInput2).to.be.true
|
expect(foundInInput2).to.be.true
|
||||||
|
|
||||||
// Now submit a value using the second input
|
|
||||||
const input2 = await getTestInput2()
|
const input2 = await getTestInput2()
|
||||||
await input2.clear()
|
await input2.clear()
|
||||||
await input2.sendKeys('sharedfrominput2')
|
await input2.sendKeys('sharedfrominput2')
|
||||||
|
|
@ -297,10 +254,8 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
await waitForLogsPage()
|
await waitForLogsPage()
|
||||||
await waitForExecutionComplete()
|
await waitForExecutionComplete()
|
||||||
|
|
||||||
// Verify both values appear in both datalists
|
|
||||||
await openArgumentForm()
|
await openArgumentForm()
|
||||||
|
|
||||||
// Check that both values are in the first input's datalist
|
|
||||||
const options1After = await getDatalistOptions('testInput')
|
const options1After = await getDatalistOptions('testInput')
|
||||||
let foundValue1 = false
|
let foundValue1 = false
|
||||||
let foundValue2 = false
|
let foundValue2 = false
|
||||||
|
|
@ -316,7 +271,6 @@ describe('config: suggestionsBrowserKey', function () {
|
||||||
expect(foundValue1).to.be.true
|
expect(foundValue1).to.be.true
|
||||||
expect(foundValue2).to.be.true
|
expect(foundValue2).to.be.true
|
||||||
|
|
||||||
// Check that both values are in the second input's datalist
|
|
||||||
const options2After = await getDatalistOptions('testInput2')
|
const options2After = await getDatalistOptions('testInput2')
|
||||||
foundValue1 = false
|
foundValue1 = false
|
||||||
foundValue2 = false
|
foundValue2 = false
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,12 @@ import { describe, it, before, after } from 'mocha'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { By, Condition } from 'selenium-webdriver'
|
import { By, Condition } from 'selenium-webdriver'
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_UI_WAIT_MS,
|
||||||
getRootAndWait,
|
getRootAndWait,
|
||||||
takeScreenshotOnFailure,
|
takeScreenshotOnFailure,
|
||||||
getTerminalBuffer,
|
getTerminalBuffer,
|
||||||
|
waitForLogsPage,
|
||||||
|
waitForExecutionComplete,
|
||||||
} from '../../lib/elements.js'
|
} from '../../lib/elements.js'
|
||||||
|
|
||||||
describe('config: xtermLinkHandling', function () {
|
describe('config: xtermLinkHandling', function () {
|
||||||
|
|
@ -26,32 +29,13 @@ describe('config: xtermLinkHandling', function () {
|
||||||
await webdriver.wait(new Condition('wait for Echo URL button', async () => {
|
await webdriver.wait(new Condition('wait for Echo URL button', async () => {
|
||||||
const btns = await webdriver.findElements(By.css('[title="Echo URL"]'))
|
const btns = await webdriver.findElements(By.css('[title="Echo URL"]'))
|
||||||
return btns.length === 1
|
return btns.length === 1
|
||||||
}), 10000)
|
}), DEFAULT_UI_WAIT_MS)
|
||||||
|
|
||||||
const echoUrlButton = await webdriver.findElement(By.css('[title="Echo URL"]'))
|
const echoUrlButton = await webdriver.findElement(By.css('[title="Echo URL"]'))
|
||||||
await echoUrlButton.click()
|
await echoUrlButton.click()
|
||||||
|
|
||||||
await webdriver.wait(new Condition('wait for execution view', async () => {
|
await waitForLogsPage()
|
||||||
const url = await webdriver.getCurrentUrl()
|
await waitForExecutionComplete()
|
||||||
return url.includes('/logs/') && !url.endsWith('/logs')
|
|
||||||
}), 10000)
|
|
||||||
|
|
||||||
await webdriver.wait(new Condition('wait for execution status', async () => {
|
|
||||||
const statusElements = await webdriver.findElements(By.id('execution-dialog-status'))
|
|
||||||
return statusElements.length > 0
|
|
||||||
}), 5000)
|
|
||||||
|
|
||||||
await webdriver.wait(new Condition('wait for execution to finish', async () => {
|
|
||||||
try {
|
|
||||||
const statusElement = await webdriver.findElement(By.id('execution-dialog-status'))
|
|
||||||
const statusText = await statusElement.getText()
|
|
||||||
return !statusText.includes('Executing')
|
|
||||||
} catch (e) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}), 5000)
|
|
||||||
|
|
||||||
await webdriver.sleep(500)
|
|
||||||
|
|
||||||
const bufferText = await getTerminalBuffer()
|
const bufferText = await getTerminalBuffer()
|
||||||
expect(bufferText).to.not.be.null
|
expect(bufferText).to.not.be.null
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue