1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-06-08 18:20:20 +00:00

fix(webjob): test coverage for _executionTasks=true requests without file upload (#883)

* test(cypress): show individual errors

* test(cypress): half the cypress integration test timeout

* test(cypress): add parallel tests, timeout and reports

* test(cypress): use allSettled instead of all

* test(runner): pre-render pending test cards
This commit is contained in:
Sead Mulahasanović
2026-05-12 09:53:11 +02:00
committed by GitHub
parent eb1186b4b9
commit 55db8f45ab
7 changed files with 259 additions and 27 deletions
+4 -2
View File
@@ -66,10 +66,11 @@ export class TestSuiteElement extends HTMLElement {
const passed = completedTests.filter((t) => t.status === 'passed').length
const failed = completedTests.filter((t) => t.status === 'failed').length
const running = completedTests.filter((t) => t.status === 'running').length
const pending = completedTests.filter((t) => t.status === 'pending').length
const statsEl = this.shadow.querySelector('.stats')
if (statsEl) {
statsEl.textContent = `Passed: ${passed} | Failed: ${failed} | Running: ${running}`
statsEl.textContent = `Passed: ${passed} | Failed: ${failed} | Running: ${running} | Pending: ${pending}`
}
}
@@ -80,11 +81,12 @@ export class TestSuiteElement extends HTMLElement {
const passed = completedTests.filter((t) => t.status === 'passed').length
const failed = completedTests.filter((t) => t.status === 'failed').length
const running = completedTests.filter((t) => t.status === 'running').length
const pending = completedTests.filter((t) => t.status === 'pending').length
this.shadow.innerHTML = `
<div class="header">
<h2>${name}</h2>
<div class="stats">Passed: ${passed} | Failed: ${failed} | Running: ${running}</div>
<div class="stats">Passed: ${passed} | Failed: ${failed} | Running: ${running} | Pending: ${pending}</div>
</div>
<div class="tests" id="tests-container"></div>
`
+26 -9
View File
@@ -30,12 +30,14 @@ export class TestRunner {
) => void
): Promise<CompletedTestSuite[]> {
this.isRunning = true
this.completedTestSuites = []
this.completedTestSuites = this.testSuites.map((suite) => ({
name: suite.name,
completedTests: []
}))
for (let i = 0; i < this.testSuites.length; i++) {
const suite = this.testSuites[i]
await this.runTestSuite(suite, i, onUpdate)
}
await Promise.allSettled(
this.testSuites.map((suite, i) => this.runTestSuite(suite, i, onUpdate))
)
this.isRunning = false
return this.completedTestSuites
@@ -49,7 +51,23 @@ export class TestRunner {
currentIndex: number
) => void
): Promise<CompletedTestSuite> {
const completedTests: CompletedTest[] = []
// Seed all tests as pending so every card renders before any run starts.
const completedTests: CompletedTest[] = suite.tests.map((test) => ({
test,
result: false,
error: null,
executionTime: 0,
status: 'pending'
}))
if (onUpdate) {
this.completedTestSuites[suiteIndex] = {
name: suite.name,
completedTests: [...completedTests]
}
onUpdate([...this.completedTestSuites], suiteIndex * 1000)
}
let context: unknown
// Run beforeAll if exists
@@ -62,15 +80,14 @@ export class TestRunner {
const test = suite.tests[i]
const currentIndex = suiteIndex * 1000 + i
// Set status to running
const runningTest: CompletedTest = {
// Flip pending → running
completedTests[i] = {
test,
result: false,
error: null,
executionTime: 0,
status: 'running'
}
completedTests.push(runningTest)
// Notify update
if (onUpdate) {
+3 -1
View File
@@ -23,6 +23,7 @@ import { fileUploadTests } from './testSuites/FileUpload'
import { computeTests } from './testSuites/Compute'
import { sasjsRequestTests } from './testSuites/SasjsRequests'
import { specialCaseTests } from './testSuites/SpecialCases'
import { executionTasksTests } from './testSuites/executionTasks'
async function init() {
const appContainer = document.getElementById('app')
@@ -104,8 +105,9 @@ function showTests(
fileUploadTests(adapter)
]
// Add compute tests for SASVIYA only
// Add tests for SASVIYA only
if (adapter.getSasjsConfig().serverType === 'SASVIYA') {
testSuites.push(executionTasksTests(adapter))
testSuites.push(computeTests(adapter, appLoc))
}
@@ -0,0 +1,61 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import SASjs from '@sasjs/adapter'
import type { TestSuite } from '../types'
const tableData: any = { table1: [{ col1: 'first col value' }] }
const fileData: any = { table1: [{ col1: 'value with ; semicolon' }] }
export const executionTasksTests = (adapter: SASjs): TestSuite => ({
name: '_executionTasks=true behaviour',
tests: [
{
title: 'sends table data in body',
description: 'table payload, no _executionTasks flag',
test: () =>
adapter
.request('services/common/sendArr', tableData, {
useComputeApi: null
})
.then((res: any) => ({ ok: true, res }))
.catch((e: any) => ({ ok: false, error: e })),
assertion: (res: any) => res?.ok === true
},
{
title: 'sends table data when _executionTasks=true',
description: 'table payload with _executionTasks=true',
test: () =>
adapter
.request('services/common/sendArr&_executionTasks=true', tableData, {
useComputeApi: null
})
.then((res: any) => ({ ok: true, res }))
.catch((e: any) => ({ ok: false, error: e })),
assertion: (res: any) => res?.ok === true
},
{
title: 'uploads as file when payload has semicolons',
description: 'semicolon payload, no _executionTasks flag',
test: () =>
adapter
.request('services/common/sendArr', fileData, {
useComputeApi: null
})
.then((res: any) => ({ ok: true, res }))
.catch((e: any) => ({ ok: false, error: e })),
assertion: (res: any) => res?.ok === true
},
{
title:
'uploads as file when _executionTasks=true and payload has semicolons',
description: 'semicolon payload with _executionTasks=true',
test: () =>
adapter
.request('services/common/sendArr&_executionTasks=true', fileData, {
useComputeApi: null
})
.then((res: any) => ({ ok: true, res }))
.catch((e: any) => ({ ok: false, error: e })),
assertion: (res: any) => res?.ok === true
}
]
})