Ok, this is a very specific problem I have been struggling with for over a week now. I am developing a SAP UI5 application where UI testing is done via Opa5/QUnit. Serving the application directly via npm does work without problems, however, using Karma (targeting a headless approach) two problems have surfaced which seem to be caused by the used custom Middleware:
res.status()
/res.header()
do not work (only native node methods likeres.setHeader()
)- Using a body parser (no matter wheter
express.json()
or deprecatedbodyparser.json()
), the parser middleware seems to be working forever until the browser request fails after exact 20 or 40 seconds (Chrome only shows the "Stalled" timebar). This happens very often, but not always.
While there is a workaround for the first issue (but still - would be interesting to know why this happens only with Karma) I can't find a solution for the failing requests. I tried changing the browser Karma uses, changing from HTML to script mode, including several plugins and also analyzed packets via Wireshark because browsers show no difference at all between normal and Karma execution.
Through Wireshark I found out that the Karma browser keeps closing Websockets after requests are done while the normal browser doesn't (even when application is served via Karma). Also, in rare cases of working POST JSON requests, content length or processing time do not seem to have an effect.
karma.conf.js:
module.exports = function(config) {
"use strict";
config.set({
frameworks: ['ui5'],
reporters: ["progress"],
browsers: ["Chrome_without_security"],
ui5: {
mode: "html",
testpage: "webapp/test/integration/opaTests.qunit.html",
configPath: "ui5-testing.yaml",
},
customLaunchers: {
Chrome_without_security: {
base: 'Chrome',
flags: ['--disable-web-security', '--no-sandbox']
}
},
singleRun: true,
browserNoActivityTimeout: 400000,
//logLevel: config.LOG_DEBUG,
});
};
ui5-testing.yaml:
specVersion: '2.1'
metadata:
name: grunt-build
type: application
framework:
name: SAPUI5
version: "1.84.0"
libraries:
- name: sap.m
- name: sap.ui.core
- name: sap.ui.layout
- name: sap.ui.support
development: true
- name: sap.ui.table
- name: sap.ui.unified
#- name: sap.ui.model
- name: sap.ushell
development: true
- name: themelib_sap_fiori_3
optional: true
- name: themelib_sap_belize
optional: true
#- name: themelib_sap_bluecrystal
# optional: true
- name: sap.f
- name: sap.tnt
resources:
configuration:
paths:
webapp: /webapp
server:
customMiddleware:
- name: proxy
beforeMiddleware: serveResources
configuration:
testing: true
---
specVersion: '2.1'
kind: extension
type: server-middleware
metadata:
name: proxy
middleware:
path: lib/middleware/proxy.js
proxy.js:
const express = require('express')
module.exports = function ({
resources,
middlewareUtil,
options
}) {
require('dotenv').config();
const axios = require('axios')
var admin = require('firebase-admin');
const app = express();
...
app.use(express.json());
app.use((req, res, next) => { // Most POST Requests with application/json header do not enter this!
...
}
return app;
};
Requesting method (example):
upsert: function (aElements, iTimeout) {
let that = this;
return new Promise((resolve, reject) => {
let sBody = JSON.stringify(aElements);
let xhr = new XMLHttpRequest();
xhr.open('POST', UPSERT_URL, true);
xhr.onload = function (oResponse) {
that.proceedResponse(oResponse, this)
.then(() => resolve())
.catch(iStatus => reject(iStatus));
};
xhr.onerror = function (oError) {
reject(oError);
};
xhr.ontimeout = function (oError) {
console.error(`The request for ${UPSERT_URL} timed out.`);
reject(oError);
};
xhr.timeout = iTimeout;
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(sBody);
});
},
Normal call: ui5 serve -p 8080 -o /test/integration/opaTests.qunit.html --config ui5-testing.yaml
Karma call: karma start
Maybe someone is able to help me here, thank you very much!