صلاح قابلیت مقایسه شماتیک
Verify / test (push) Failing after 16s

This commit is contained in:
2026-11-07 15:51:09 +03:30
والد 1a12b44c24
کامیت 6b1f408fde
4فایلهای تغییر یافته به همراه26 افزوده شده و 6 حذف شده
+2
مشاهده پرونده
@@ -85,3 +85,5 @@ API_KEY="$API_KEY" .venv/bin/python scripts/compare-smoke.py original.SchDoc mod
Tests cover record reordering, component UID matching/renumbering, values, pure movement, combined movement/property edits, additions/removals, reversed wire vertices, duplicate objects, labels/net-name scope, embedded raster replacement, nonmutation, original SVG geometry, clip-ID separation, upload/authentication/CORS, per-file/combined limits, partial storage failures, a real OLE same-file comparison, private result/SVG access, failed processing and expiry cleanup. Frontend camera adapter tests cover pane offsets, synchronized world cameras, pinch, change focus and detached listeners. Synthetic unit circuits never appear as application data.
The actual local `Sheet1-before.SchDoc` / `Sheet1-after.SchDoc` pair (205/206 source records) produced 1 moved component, 2 modified wires and 1 added junction. The 1,942-record CPU sheet compared with itself produced zero changes. These are structural integration checks, not a trusted Altium visual comparison or browser UI acceptance test. No proprietary samples are redistributed. Browser interaction and visual validation require a connected browser; absence of browser QA must be reported rather than replaced by camera unit tests.
Implementation verification: 115 Python tests and 6 frontend tests passed with the native fixtures enabled. The Docker image built successfully, the Caddy configuration adapted successfully, and real HTTP comparison plus single-file smoke checks passed against PostgreSQL with two worker replicas. The comparison result and SVG routes enforced private read tokens. A connected browser was unavailable, so interactive workspace appearance and browser behavior are not claimed as verified.
+8 -4
مشاهده پرونده
@@ -1,6 +1,6 @@
body { display: flex; flex-direction: column; font-family: system-ui,sans-serif; color: #233431; background: #f4f6f5; }
* { box-sizing: border-box; }
header { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; padding: 12px 16px; border-bottom: 1px solid #d6dfda; }
header { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; min-height: 60px; padding: 12px 16px 12px 60px; border-bottom: 1px solid #d6dfda; }
header > a { color: #244d49; font-size: 15px; font-weight: 650; text-decoration: none; }
#summary, .controls { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; font-size: 12px; }
.controls { margin-left: auto; }
@@ -8,7 +8,11 @@ label { display: inline-flex; gap: 4px; align-items: center; }
button, select { border: 1px solid #cbd5ce; border-radius: 4px; padding: 5px 9px; background: white; color: inherit; font: inherit; cursor: pointer; }
button:focus-visible, select:focus-visible, .surface:focus-visible { outline: 2px solid #2676c5; outline-offset: -2px; }
#scope { margin: 0; padding: 7px 16px; font-size: 11px; color: #60716b; border-bottom: 1px solid #d6dfda; }
.workspace { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr) 270px; }
.workspace { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); grid-template-rows: minmax(0,1fr); }
.menu-open .workspace { grid-template-columns: minmax(0,1fr) minmax(0,1fr) 270px; }
body:not(.menu-open) header, body:not(.menu-open) #scope, body:not(.menu-open) aside, body:not(.menu-open) .pane h2 { display: none; }
#menu-toggle { position: fixed; top: 12px; left: 12px; z-index: 10; width: 36px; height: 36px; display: grid; place-items: center; padding: 6px; box-shadow: 0 2px 6px #00000014; }
#menu-toggle[aria-expanded="true"] { background: #e5eee9; }
.pane { min-width: 0; min-height: 0; display: flex; flex-direction: column; border-right: 1px solid #d6dfda; }
h2 { margin: 0; padding: 9px 12px; font-size: 12px; font-weight: 650; background: #edf1ee; display: flex; gap: 10px; }
h2 span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: normal; color: #61746b; }
@@ -28,7 +32,7 @@ aside { display: flex; flex-direction: column; min-height: 0; overflow: hidden;
[data-diff-hidden] { display: none; }
.no-highlights [data-diff-box] { display: none; }
[data-diff-box][data-selected] { stroke-width: 3; fill-opacity: .18; }
@media (max-width: 900px) { .workspace { grid-template-columns: minmax(0,1fr) minmax(0,1fr); grid-template-rows: minmax(0,1fr) 180px; } aside { grid-column: 1/-1; } #details { max-height: 40%; } }
@media (max-width: 550px) { .workspace { grid-template-columns: 1fr; grid-template-rows: minmax(0,1fr) minmax(0,1fr) 140px; } aside { grid-column: auto; } header { gap: 8px; }.controls { margin-left: 0; } }
@media (max-width: 900px) { .menu-open .workspace { grid-template-columns: minmax(0,1fr) minmax(0,1fr); grid-template-rows: minmax(0,1fr) 180px; } aside { grid-column: 1/-1; } #details { max-height: 40%; } }
@media (max-width: 550px) { .workspace { grid-template-columns: 1fr; grid-template-rows: minmax(0,1fr) minmax(0,1fr); } .menu-open .workspace { grid-template-columns: 1fr; grid-template-rows: minmax(0,1fr) minmax(0,1fr) 140px; } aside { grid-column: auto; } header { gap: 8px; }.controls { margin-left: 0; } }
#changes button[hidden] { display: none; }
+3 -2
مشاهده پرونده
@@ -1,6 +1,7 @@
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Schematic comparison</title><link rel="stylesheet" href="/fonts.css"><link rel="stylesheet" href="/assets/viewer.css"><link rel="stylesheet" href="/assets/compare.css"><script type="module" src="/assets/compare.js"></script></head><body>
<header><a href="/compare">Schematic Diff</a><div id="summary" aria-live="polite"></div><div class="controls"><label><input id="sync" type="checkbox" checked> Sync views</label><label><input id="highlights" type="checkbox" checked> Highlights</label><label><input id="only-changes" type="checkbox"> Changes only</label><button id="fit" type="button">Fit</button></div></header>
<button id="menu-toggle" type="button" aria-label="Show menu" title="Show menu" aria-expanded="false" aria-controls="comparison-toolbar scope comparison-changes"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16"/></svg></button>
<header id="comparison-toolbar"><a href="/compare">Schematic Diff</a><div id="summary" aria-live="polite"></div><div class="controls"><label><input id="sync" type="checkbox" checked> Sync views</label><label><input id="highlights" type="checkbox" checked> Highlights</label><label><input id="only-changes" type="checkbox"> Changes only</label><button id="fit" type="button">Fit</button></div></header>
<p id="scope">Native object comparison · Connection graphics, not a compiled electrical netlist.</p>
<main class="workspace"><section class="pane"><h2>Original <span id="old-name"></span></h2><div id="old-surface" class="surface" tabindex="0" aria-label="Original schematic"></div></section><section class="pane"><h2>Modified <span id="new-name"></span></h2><div id="new-surface" class="surface" tabindex="0" aria-label="Modified schematic"></div></section><aside><div class="change-controls"><label for="filter">Changes</label><select id="filter"><option value="all">All</option><option value="added">Added</option><option value="removed">Removed</option><option value="modified">Modified</option><option value="moved">Moved</option></select><button id="previous" aria-label="Previous change">↑</button><button id="next" aria-label="Next change">↓</button></div><nav id="changes" aria-label="Schematic changes"></nav><pre id="details" aria-live="polite"></pre></aside></main>
<main class="workspace"><section class="pane"><h2>Original <span id="old-name"></span></h2><div id="old-surface" class="surface" tabindex="0" aria-label="Original schematic"></div></section><section class="pane"><h2>Modified <span id="new-name"></span></h2><div id="new-surface" class="surface" tabindex="0" aria-label="Modified schematic"></div></section><aside id="comparison-changes"><div class="change-controls"><label for="filter">Changes</label><select id="filter"><option value="all">All</option><option value="added">Added</option><option value="removed">Removed</option><option value="modified">Modified</option><option value="moved">Moved</option></select><button id="previous" aria-label="Previous change">↑</button><button id="next" aria-label="Next change">↓</button></div><nav id="changes" aria-label="Schematic changes"></nav><pre id="details" aria-live="polite"></pre></aside></main>
<output id="state" class="loading" role="status">Loading comparison…</output></body></html>
+13
مشاهده پرونده
@@ -1,4 +1,17 @@
import { bindCamera } from './interactions.js';
const menuToggle=document.querySelector('#menu-toggle');
function setMenu(open){
document.body.classList.toggle('menu-open',open);
menuToggle.setAttribute('aria-expanded',String(open));
const label=open?'Hide menu':'Show menu';
menuToggle.setAttribute('aria-label',label);menuToggle.title=label;
}
menuToggle.addEventListener('click',()=>setMenu(!document.body.classList.contains('menu-open')));
addEventListener('keydown',event=>{
if(event.key==='Escape'&&document.body.classList.contains('menu-open')){
setMenu(false);menuToggle.focus();
}
});
const state=document.querySelector('#state'),id=location.pathname.split('/').pop();
const token=new URLSearchParams(location.hash.slice(1)).get('token')||sessionStorage.getItem(`comparison:${id}`);
if(token)sessionStorage.setItem(`comparison:${id}`,token);