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