diff --git a/.github/workflows/tests_with_context_path.yml b/.github/workflows/tests_with_context_path.yml
new file mode 100644
index 000000000..7411b594b
--- /dev/null
+++ b/.github/workflows/tests_with_context_path.yml
@@ -0,0 +1,88 @@
+name: Run Tests With Context Path
+
+on:
+ push:
+
+jobs:
+ run_tests_with_context_path:
+ name: Running Tests With Context Path
+ runs-on: ubuntu-latest
+
+ env:
+ QDB_HTTP_CONTEXT_PATH: "/context"
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: "recursive"
+
+ - uses: actions/setup-java@v4
+ with:
+ java-version: "17"
+ distribution: "temurin"
+ cache: maven
+
+ - name: Build QuestDB
+ run: mvn clean package -f packages/browser-tests/questdb/pom.xml -DskipTests -P build-binaries
+
+ - name: Extract QuestDB
+ run: tar -xzf packages/browser-tests/questdb/core/target/questdb-*-rt-linux-x86-64.tar.gz -C tmp/
+
+ - name: Create DB Root
+ run: mkdir tmp/dbroot
+
+ - name: Start QuestDB
+ run: ./tmp/questdb-*-rt-linux-x86-64/bin/questdb.sh start -d ./tmp/dbroot
+ env:
+ QDB_DEV_MODE_ENABLED: "true"
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: "yarn"
+
+ - name: Install dependencies
+ run: yarn install --immutable --immutable-cache
+
+ - name: Build @questdb/react-components
+ run: yarn workspace @questdb/react-components run build
+
+ - name: Build @questdb/web-console
+ run: yarn workspace @questdb/web-console run build
+
+ - name: Run bundle watcher on @questdb/web-console
+ run: yarn workspace @questdb/web-console bundlewatch
+
+ - name: Run @questdb/web-console unit tests
+ run: yarn workspace @questdb/web-console run test:prod
+
+ - name: Run browser-tests test - auth
+ run: node packages/web-console/serve-dist.js & yarn workspace browser-tests test:auth
+
+ - name: Stop QuestDB
+ run: ./tmp/questdb-*-rt-linux-x86-64/bin/questdb.sh stop
+
+ - name: Start QuestDB, set auth credentials
+ run: ./tmp/questdb-*-rt-linux-x86-64/bin/questdb.sh start -d ./tmp/dbroot
+ env:
+ QDB_DEV_MODE_ENABLED: "true"
+ QDB_HTTP_USER: "admin"
+ QDB_HTTP_PASSWORD: "quest"
+
+ - name: Run browser-tests test
+ run: yarn workspace browser-tests test
+
+ - name: Print Log Files
+ if: success() || failure()
+ run: cat tmp/dbroot/log/*
+
+ - name: Save QuestDB log on test failure
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: questdb-log
+ path: tmp/dbroot/log/*
+
+ - name: Stop QuestDB
+ if: success() || failure()
+ run: ./tmp/questdb-*-rt-linux-x86-64/bin/questdb.sh stop
diff --git a/packages/browser-tests/cypress.config.js b/packages/browser-tests/cypress.config.js
index a06221c92..9f9357913 100644
--- a/packages/browser-tests/cypress.config.js
+++ b/packages/browser-tests/cypress.config.js
@@ -3,13 +3,16 @@ const {
addMatchImageSnapshotPlugin,
} = require("@simonsmith/cypress-image-snapshot/plugin");
+const contextPath = process.env.QDB_HTTP_CONTEXT_PATH || ""
+const baseUrl = `http://localhost:9999${contextPath}`;
+
module.exports = defineConfig({
defaultCommandTimeout: 10000,
e2e: {
defaultCommandTimeout: 30000,
screenshotOnRunFailure: false,
video: false,
- baseUrl: "http://localhost:9999",
+ baseUrl: baseUrl,
viewportWidth: 1280,
viewportHeight: 720,
specPattern: "cypress/integration/**/*.spec.js",
diff --git a/packages/browser-tests/cypress/commands.js b/packages/browser-tests/cypress/commands.js
index 4eaa67983..136d89429 100644
--- a/packages/browser-tests/cypress/commands.js
+++ b/packages/browser-tests/cypress/commands.js
@@ -13,7 +13,8 @@ addMatchImageSnapshotCommand({
const { ctrlOrCmd, escapeRegExp } = require("./utils");
-const baseUrl = "http://localhost:9999";
+const contextPath = process.env.QDB_HTTP_CONTEXT_PATH || ""
+const baseUrl = `http://localhost:9999${contextPath}`;
const tableSchemas = {
btc_trades:
diff --git a/packages/browser-tests/cypress/integration/auth/auth.spec.js b/packages/browser-tests/cypress/integration/auth/auth.spec.js
index d634985c9..0d6c1b4f1 100644
--- a/packages/browser-tests/cypress/integration/auth/auth.spec.js
+++ b/packages/browser-tests/cypress/integration/auth/auth.spec.js
@@ -1,6 +1,7 @@
///
-const baseUrl = "http://localhost:9999";
+const contextPath = process.env.QDB_HTTP_CONTEXT_PATH || ""
+const baseUrl = `http://localhost:9999${contextPath}`;
const interceptSettings = (payload) => {
cy.intercept({ method: "GET", url: `${baseUrl}/settings` }, payload).as(
diff --git a/packages/browser-tests/cypress/integration/console/editor.spec.js b/packages/browser-tests/cypress/integration/console/editor.spec.js
index 332506fdf..97b7cd8f5 100644
--- a/packages/browser-tests/cypress/integration/console/editor.spec.js
+++ b/packages/browser-tests/cypress/integration/console/editor.spec.js
@@ -1,6 +1,7 @@
///
-const baseUrl = "http://localhost:9999";
+const contextPath = process.env.QDB_HTTP_CONTEXT_PATH || ""
+const baseUrl = `http://localhost:9999${contextPath}`;
const getTabDragHandleByTitle = (title) =>
`.chrome-tab[data-tab-title="${title}"] .chrome-tab-drag-handle`;
diff --git a/packages/browser-tests/cypress/integration/console/grid.spec.js b/packages/browser-tests/cypress/integration/console/grid.spec.js
index 933909c5a..f69487096 100644
--- a/packages/browser-tests/cypress/integration/console/grid.spec.js
+++ b/packages/browser-tests/cypress/integration/console/grid.spec.js
@@ -1,7 +1,5 @@
///
-const baseUrl = "http://localhost:9999";
-
const rowHeight = 30;
const assertRowCount = () => {
diff --git a/packages/browser-tests/cypress/integration/console/navbars.spec.js b/packages/browser-tests/cypress/integration/console/navbars.spec.js
index 17893d1b4..b24e5880e 100644
--- a/packages/browser-tests/cypress/integration/console/navbars.spec.js
+++ b/packages/browser-tests/cypress/integration/console/navbars.spec.js
@@ -1,7 +1,5 @@
///
-const baseUrl = "http://localhost:9999";
-
describe("Sidebar tests", () => {
beforeEach(() => {
cy.loadConsoleWithAuth();
diff --git a/packages/browser-tests/cypress/integration/console/result_charts.spec.js b/packages/browser-tests/cypress/integration/console/result_charts.spec.js
index 59c5c84dd..e465a52b7 100644
--- a/packages/browser-tests/cypress/integration/console/result_charts.spec.js
+++ b/packages/browser-tests/cypress/integration/console/result_charts.spec.js
@@ -1,7 +1,5 @@
///
-const baseUrl = "http://localhost:9999";
-
describe("questdb charts", () => {
beforeEach(() => {
cy.loadConsoleWithAuth();
diff --git a/packages/browser-tests/cypress/integration/console/schema.spec.js b/packages/browser-tests/cypress/integration/console/schema.spec.js
index b6ca64699..591386c00 100644
--- a/packages/browser-tests/cypress/integration/console/schema.spec.js
+++ b/packages/browser-tests/cypress/integration/console/schema.spec.js
@@ -1,6 +1,7 @@
///
-const baseUrl = "http://localhost:9999";
+const contextPath = process.env.QDB_HTTP_CONTEXT_PATH || ""
+const baseUrl = `http://localhost:9999${contextPath}`;
const tables = [
"btc_trades",
diff --git a/packages/browser-tests/cypress/integration/console/telemetry.spec.js b/packages/browser-tests/cypress/integration/console/telemetry.spec.js
index 7aaa80e7b..924bbbb96 100644
--- a/packages/browser-tests/cypress/integration/console/telemetry.spec.js
+++ b/packages/browser-tests/cypress/integration/console/telemetry.spec.js
@@ -1,13 +1,11 @@
///
-const baseUrl = "http://localhost:9999";
-
const toggleTelemetry = (enabled) => {
// expected dataset format of the first row:
// [id, enabled, version, os, package]
cy.interceptQuery("telemetry_config LIMIT -1", "telemetryConfig", (req) => {
return req.continue((res) => {
- // enable telemetry to kick start the process on the client side
+ // enable telemetry to kick-start the process on the client side
res.body.dataset[0][1] = enabled;
return res;
});
diff --git a/packages/browser-tests/cypress/integration/console/warnings.spec.js b/packages/browser-tests/cypress/integration/console/warnings.spec.js
index f3f1b573e..6536cd869 100644
--- a/packages/browser-tests/cypress/integration/console/warnings.spec.js
+++ b/packages/browser-tests/cypress/integration/console/warnings.spec.js
@@ -1,7 +1,5 @@
///
-const baseUrl = "http://localhost:9999";
-
describe("System configuration - no warnings", () => {
before(() => {
cy.loadConsoleWithAuth(true);
diff --git a/packages/browser-tests/questdb b/packages/browser-tests/questdb
index c83d63d57..034c5b22e 160000
--- a/packages/browser-tests/questdb
+++ b/packages/browser-tests/questdb
@@ -1 +1 @@
-Subproject commit c83d63d57bf80e08aa4681cbcc1e462d12d5f570
+Subproject commit 034c5b22e2a868fc8c80780f088a151929e025f7
diff --git a/packages/web-console/README.md b/packages/web-console/README.md
index 33d1f6005..0710638a1 100644
--- a/packages/web-console/README.md
+++ b/packages/web-console/README.md
@@ -36,8 +36,8 @@ If the server has a context path configured with the `http.context.path` option,
the dev server is aware of it, and it proxies requests accordingly.\
We can set the context path with the following environment variable before starting dev server:
```
-CONTEXT_PATH=/instance2
-export CONTEXT_PATH
+QDB_HTTP_CONTEXT_PATH=/instance2
+export QDB_HTTP_CONTEXT_PATH
yarn workspace @questdb/web-console start
```
@@ -46,7 +46,7 @@ After the above the web console is available on [localhost:9999/instance2/](http
If the context path is removed from the server configuration, we also need to clear the environment variable,
and restart the dev server:
```
-unset CONTEXT_PATH
+unset QDB_HTTP_CONTEXT_PATH
yarn workspace @questdb/web-console start
```
diff --git a/packages/web-console/serve-dist.js b/packages/web-console/serve-dist.js
index 88ea82001..fad28aa77 100644
--- a/packages/web-console/serve-dist.js
+++ b/packages/web-console/serve-dist.js
@@ -3,20 +3,25 @@ const url = require("url")
const fs = require("fs")
const path = require("path")
+const contextPath = process.env.QDB_HTTP_CONTEXT_PATH || ""
+
const server = http.createServer((req, res) => {
const { method } = req
- const urlData = url.parse(req.url)
+ const baseUrl = "http://" + req.headers.host + contextPath;
+ const reqUrl = new url.URL(req.url, baseUrl);
+ const reqPath = reqUrl.pathname + reqUrl.search;
+ const reqPathName = reqUrl.pathname;
if (
- urlData.pathname.startsWith("/exec") ||
- urlData.pathname.startsWith("/settings") ||
- urlData.pathname.startsWith("/warnings")
+ reqPathName.startsWith("/exec") ||
+ reqPathName.startsWith("/settings") ||
+ reqPathName.startsWith("/warnings")
) {
// proxy /exec requests to localhost:9000
const options = {
hostname: "localhost",
port: 9000,
- path: urlData.path,
+ path: contextPath + reqPath,
method,
headers: req.headers,
}
@@ -34,16 +39,16 @@ const server = http.createServer((req, res) => {
"packages",
"web-console",
"dist",
- ["", "/"].some((p) => urlData.pathname === p)
+ ["", "/"].some((p) => reqPathName === p)
? "index.html"
- : urlData.pathname,
+ : reqPathName,
)
const fileStream = fs.createReadStream(filePath)
fileStream.on("error", (err) => {
if (err.code === "ENOENT") {
res.statusCode = 404
- res.end(`File not found: ${urlData}`)
+ res.end(`File not found: ${reqPath}`)
} else {
res.statusCode = 500
res.end(`Server error: ${err}`)
diff --git a/packages/web-console/webpack.config.js b/packages/web-console/webpack.config.js
index d6e51e878..7199f0b5b 100644
--- a/packages/web-console/webpack.config.js
+++ b/packages/web-console/webpack.config.js
@@ -41,7 +41,7 @@ const config = {
port: 9999,
backendUrl: "http://127.0.0.1:9000",
isProduction: process.env.NODE_ENV === "production",
- contextPath: process.env.CONTEXT_PATH || "",
+ contextPath: process.env.QDB_HTTP_CONTEXT_PATH || "",
}
module.exports = {
diff --git a/run_browser_tests.sh b/run_browser_tests.sh
index 7973b3cef..12e3942de 100755
--- a/run_browser_tests.sh
+++ b/run_browser_tests.sh
@@ -30,8 +30,8 @@ yarn workspace @questdb/web-console run build
# Start proxy
node packages/web-console/serve-dist.js &
-PID="$!"
-echo "Proxy started, PID=$PID"
+PID1="$!"
+echo "Proxy started, PID=$PID1"
# Switch dev mode on
export QDB_DEV_MODE_ENABLED=true
@@ -41,6 +41,8 @@ export QDB_DEV_MODE_ENABLED=true
yarn workspace browser-tests test:auth
./tmp/questdb-*/bin/questdb.sh stop
+read -p "Press any key to continue... " -n1 -s
+
# Switch authentication on
export QDB_HTTP_USER=admin
export QDB_HTTP_PASSWORD=quest
@@ -50,5 +52,25 @@ export QDB_HTTP_PASSWORD=quest
yarn workspace browser-tests test
./tmp/questdb-*/bin/questdb.sh stop
+read -p "Press any key to continue... " -n1 -s
+
+# Set context path
+export QDB_HTTP_CONTEXT_PATH=/context1
+
+# Restart proxy to pickup context path
+kill -SIGTERM $PID1
+sleep 1
+node packages/web-console/serve-dist.js &
+PID2="$!"
+echo "Proxy started, PID=$PID2"
+
+# Cleanup snapshots for second run
+rm -rf packages/browser-tests/cypress/snapshots/*
+
+# Running tests with context path
+./tmp/questdb-*/bin/questdb.sh start -d tmp/dbroot
+yarn workspace browser-tests test
+./tmp/questdb-*/bin/questdb.sh stop
+
# Stop proxy
-kill -SIGTERM $PID
+kill -SIGTERM $PID2