Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e3b8-9815-70f2-9ac5-37bcde2c5090
70 lines
3.3 KiB
Python
70 lines
3.3 KiB
Python
"""Execute the browser transition against a small graph/DOM harness."""
|
|
import shutil
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
from railiance_fabric.graph_explorer_ui import graph_explorer_page
|
|
|
|
|
|
def test_graph_switch_replaces_data_and_retains_previous_graph_on_failure(tmp_path):
|
|
if not shutil.which("node"):
|
|
pytest.skip("Node.js is required for the UI transition test")
|
|
page = graph_explorer_page()
|
|
transition = page.split(" let graphRequest = 0;", 1)[1].split(
|
|
" const handleFilterChange", 1
|
|
)[0]
|
|
script = r'''
|
|
const assert = require("node:assert/strict");
|
|
let graphMode = "full", includeResidualsParam = false, activeMode = "full";
|
|
let selected, selectedAnchor, selectedZoneId, focusSet, manualOverrides, filterRules;
|
|
let editingRuleId, currentProfileId, allEdgeTypes;
|
|
const layerColors = {}, allNodeTypes = [], nodeTypeLabels = {};
|
|
const collapsedZoneSnapshots = new Map(), zoneContainerState = new Map(), zoneSummaries = new Map();
|
|
const modeSelect = {}, profileSelect = {}, nodeTypeFilter = {}, edgeTypeFilter = {};
|
|
const popup = {style: {}}, profileSummary = {};
|
|
const controls = {};
|
|
const document = {getElementById(id) {return controls[id] ||= {style: {}};}};
|
|
let data = [{data: {id: "old"}}], urls = [], updated = 0;
|
|
const cy = {elements: () => ({remove() {data = [];}}), add(elements) {data.push(...elements);}};
|
|
const renderChecklist = () => {}, refreshRuleBuilder = () => {}, renderRules = () => {};
|
|
const syncFilterSummaries = () => {}, applyFilters = () => {}, runLayout = () => {};
|
|
const updateUrlState = () => {updated++;}, showDetails = () => {};
|
|
const updateProfileControls = () => {}, updateProfileSummary = () => {};
|
|
const applyViewState = () => {};
|
|
let response = {ok: true, json: async () => ({elements: [{data: {id: "workplan:a"}}]})};
|
|
let fetch = async (url) => {urls.push(url); return response;};
|
|
let graphRequest = 0;
|
|
'''
|
|
script += transition + r'''
|
|
(async () => {
|
|
await switchGraph("coordination", true);
|
|
assert.equal(data[0].data.id, "workplan:a");
|
|
assert.equal(modeSelect.value, "coordination");
|
|
assert.equal(controls["include-residuals-wrap"].style.display, "");
|
|
assert.match(urls[0], /include_residuals=true/);
|
|
response = {ok: false, status: 503};
|
|
await switchGraph("full");
|
|
assert.equal(data[0].data.id, "workplan:a");
|
|
assert.equal(modeSelect.value, "coordination");
|
|
assert.match(profileSummary.textContent, /503/);
|
|
response = {ok: true, json: async () => ({elements: []})};
|
|
await switchGraph("by-access-zone");
|
|
assert.deepEqual(data, []);
|
|
assert.equal(activeMode, "by-access-zone");
|
|
assert.equal(graphMode, "full");
|
|
assert.equal(controls["include-residuals-wrap"].style.display, "none");
|
|
let resolveOld;
|
|
fetch = () => new Promise(resolve => {resolveOld = resolve;});
|
|
const oldRequest = switchGraph("coordination");
|
|
fetch = async () => ({ok: true, json: async () => ({elements: [{data: {id: "latest"}}]})});
|
|
await switchGraph("full");
|
|
resolveOld({ok: true, json: async () => ({elements: [{data: {id: "stale"}}]})});
|
|
await oldRequest;
|
|
assert.equal(data[0].data.id, "latest");
|
|
assert.equal(updated, 3);
|
|
})().catch(error => {console.error(error); process.exitCode = 1;});
|
|
'''
|
|
path = tmp_path / "switch.cjs"
|
|
path.write_text(script)
|
|
subprocess.run(["node", str(path)], check=True, capture_output=True, text=True)
|