This is an automated email from the ASF dual-hosted git repository. imbajin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/hugegraph-toolchain.git
commit e1f04292890198f2d4df35833d22988fc6818754 Author: dark <[email protected]> AuthorDate: Sat Aug 29 22:17:45 2026 +0800 fix(ci): finalize merged server integration - test against the resolved Server master SHA - preserve route state during configuration polling - remove temporary review images --- .github/workflows/hubble-ci.yml | 8 ++-- .../images/pr27/15-standalone-nonauth-visual.png | Bin 90401 -> 0 bytes .../images/pr27/18-standalone-nonauth-visual.png | Bin 93329 -> 0 bytes hugegraph-hubble/hubble-fe/src/App.js | 13 ++++++- hugegraph-hubble/hubble-fe/src/App.test.js | 43 ++++++++++++++++++++- 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/.github/workflows/hubble-ci.yml b/.github/workflows/hubble-ci.yml index 425e09d76..95c878045 100644 --- a/.github/workflows/hubble-ci.yml +++ b/.github/workflows/hubble-ci.yml @@ -23,10 +23,8 @@ on: env: TRAVIS_DIR: hugegraph-hubble/hubble-dist/assembly/travis - # Server PR #3159 declares the GraphSpace default-role contract as API 0.72. - # TODO: After #3159 merges, switch these values to the stable upstream branch. - HUGEGRAPH_SERVER_GIT_URL: https://github.com/hugegraph/hugegraph.git - HUGEGRAPH_SERVER_BRANCH: cx/bump-server-api-version + HUGEGRAPH_SERVER_GIT_URL: https://github.com/apache/hugegraph.git + HUGEGRAPH_SERVER_BRANCH: master jobs: hubble-ci: @@ -89,7 +87,7 @@ jobs: path: ~/.cache/ms-playwright key: ${{ runner.os }}-playwright-${{ hashFiles('hugegraph-hubble/hubble-fe/yarn.lock') }} - - name: Resolve HugeGraph Server branch + - name: Resolve HugeGraph Server revision id: server-ref run: | SERVER_COMMIT="$(git ls-remote "$HUGEGRAPH_SERVER_GIT_URL" \ diff --git a/hugegraph-hubble/docs/images/pr27/15-standalone-nonauth-visual.png b/hugegraph-hubble/docs/images/pr27/15-standalone-nonauth-visual.png deleted file mode 100644 index 0b472dac9..000000000 Binary files a/hugegraph-hubble/docs/images/pr27/15-standalone-nonauth-visual.png and /dev/null differ diff --git a/hugegraph-hubble/docs/images/pr27/18-standalone-nonauth-visual.png b/hugegraph-hubble/docs/images/pr27/18-standalone-nonauth-visual.png deleted file mode 100644 index 13e8bc6cf..000000000 Binary files a/hugegraph-hubble/docs/images/pr27/18-standalone-nonauth-visual.png and /dev/null differ diff --git a/hugegraph-hubble/hubble-fe/src/App.js b/hugegraph-hubble/hubble-fe/src/App.js index 6ea227328..70dee756e 100644 --- a/hugegraph-hubble/hubble-fe/src/App.js +++ b/hugegraph-hubble/hubble-fe/src/App.js @@ -29,6 +29,12 @@ import {useEffect, useState} from 'react'; const CONFIG_RETRY_DELAY_MS = 2000; const CONFIG_REVALIDATE_DELAY_MS = 30_000; +const routeConfigSignature = config => JSON.stringify([ + config.auth_enabled !== false, + config.pd_enabled === true, + config.graph_create_enabled === true, + config.cypher_enabled === true, +]); function App() { const [configReady, setConfigReady] = useState(false); @@ -38,6 +44,7 @@ function App() { useEffect(() => { let active = true; let hasSafeConfig = false; + let mountedConfigSignature; let retryTimer; const loadConfig = () => { api.config.getConfig().then(response => { @@ -46,8 +53,12 @@ function App() { } if (active) { hasSafeConfig = true; + const nextSignature = routeConfigSignature(response.data); setConfig(response.data); - setConfigRevision(value => value + 1); + if (nextSignature !== mountedConfigSignature) { + mountedConfigSignature = nextSignature; + setConfigRevision(value => value + 1); + } setConfigReady(true); setConfigError(false); const unverified = response.data diff --git a/hugegraph-hubble/hubble-fe/src/App.test.js b/hugegraph-hubble/hubble-fe/src/App.test.js index 5407c8b60..fa2d95a2a 100644 --- a/hugegraph-hubble/hubble-fe/src/App.test.js +++ b/hugegraph-hubble/hubble-fe/src/App.test.js @@ -16,7 +16,13 @@ * under the License. */ -import {act, render, screen, waitFor} from '@testing-library/react'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import App from './App'; import * as api from './api'; @@ -35,6 +41,7 @@ jest.mock('./routes', () => ({element}) => ( )} > {element} + <input aria-label="unsaved draft" /> </div> )); @@ -214,3 +221,37 @@ test('periodically revalidates a verified authentication mode', async () => { ); jest.useRealTimers(); }); + +test('preserves route state when periodic configuration is unchanged', async () => { + jest.useFakeTimers(); + const config = { + pd_enabled: true, + auth_enabled: true, + graph_create_enabled: true, + cypher_enabled: true, + server_capabilities_verified: true, + }; + api.config.getConfig + .mockResolvedValueOnce({status: 200, data: config}) + .mockResolvedValueOnce({status: 200, data: {...config}}); + + render( + <MemoryRouter + future={{v7_startTransition: true, v7_relativeSplatPath: true}} + > + <App /> + </MemoryRouter> + ); + const draft = await screen.findByRole('textbox', { + name: 'unsaved draft', + }); + fireEvent.change(draft, {target: {value: 'keep me'}}); + + await act(async () => { + jest.advanceTimersByTime(30_000); + }); + await waitFor(() => expect(api.config.getConfig).toHaveBeenCalledTimes(2)); + expect(screen.getByRole('textbox', {name: 'unsaved draft'})) + .toHaveValue('keep me'); + jest.useRealTimers(); +});
