Update VPN client connection flow
This commit is contained in:
@@ -36,11 +36,12 @@ test('Gateway device inventory uses the existing accessible responsive drawer',
|
||||
assert.match(panel, /<Tooltip>Изменить название<\/Tooltip>/);
|
||||
assert.match(panel, /copyText\(device\.ip\)/);
|
||||
assert.match(panel, /const hasName = Boolean\(device\.alias \|\| device\.hostname\)/);
|
||||
assert.match(panel, /client-device-name\$\{hasName \? '' : ' is-address-only'\}/);
|
||||
assert.match(panel, /client-device-name-primary[\s\S]*\{hasName && <span className="client-device-name-ip"[\s\S]*client-device-name-feedback/);
|
||||
assert.match(panel, /client-device-name-feedback[\s\S]*'copied!'/);
|
||||
assert.match(panel, /COPY_FEEDBACK_MS = 5_000/);
|
||||
assert.match(panel, /client-device-name-feedback[\s\S]*client-device-edit-wrap[\s\S]*client-device-last-seen/);
|
||||
assert.match(panel, /client-device-alias-trigger[\s\S]*client-device-name-separator[\s\S]*client-device-ip/);
|
||||
assert.match(panel, /onClick=\{\(\) => startEditing\(device\)\}/);
|
||||
assert.match(panel, /\{!hasName && <span className="client-device-edit-wrap/);
|
||||
assert.match(panel, /COPY_FEEDBACK_MS = 800/);
|
||||
assert.match(panel, /IP скопирован/);
|
||||
assert.doesNotMatch(panel, /client-device-name-feedback|client-device-name-primary|is-address-only/);
|
||||
assert.doesNotMatch(panel, /client-device-title/);
|
||||
assert.match(panel, /online \? 'В сети' : <TextMorph from="Не в сети" to=\{seen\.relative\} \/>/);
|
||||
assert.match(panel, /aria-label=\{`\$\{online \? 'В сети' : 'Не в сети'\}\. Последний контакт: \$\{seen\.tooltip\}`\}/);
|
||||
@@ -61,6 +62,8 @@ test('Gateway device inventory uses the existing accessible responsive drawer',
|
||||
assert.match(panel, /TrafficChart[\s\S]*samples=\{device\.trafficHistory \|\| \[\]\}[\s\S]*scale=\{trafficScale\}[\s\S]*capacity=\{snapshot\.trafficHistoryCapacity/);
|
||||
assert.doesNotMatch(panel, /setTrafficHistory|TRAFFIC_HISTORY_LIMIT/);
|
||||
assert.match(panel, /aria-pressed=\{trafficScale === 'linear'\}[\s\S]*aria-pressed=\{trafficScale === 'log'\}/);
|
||||
assert.match(panel, /previousScale\.current !== scale[\s\S]*attributeName="points"[\s\S]*dur="520ms"/);
|
||||
assert.doesNotMatch(panel, /key=\{latest\}/);
|
||||
assert.match(panel, /createPortal\([\s\S]*client-device-traffic-point-tooltip[\s\S]*document\.body/);
|
||||
assert.match(panel, /onPointerMove=\{trackPointer\}/);
|
||||
assert.match(panel, /pinned && max > 0n && <span className="client-device-traffic-axis"[\s\S]*is-max[\s\S]*is-mid[\s\S]*is-zero/);
|
||||
@@ -101,18 +104,12 @@ test('Gateway device inventory uses the existing accessible responsive drawer',
|
||||
assert.match(styles, /@keyframes client-device-traffic-line-draw[\s\S]*stroke-dashoffset: 0/);
|
||||
assert.match(styles, /@keyframes client-device-chart-expand[\s\S]*clip-path: inset\(calc\(100% - 34px\) 0 0\)[\s\S]*scaleY\(1\)/);
|
||||
assert.match(styles, /\.client-device-policy \{[\s\S]*width: 34px;[\s\S]*border-radius: 50%/);
|
||||
assert.match(styles, /\.client-device-name \{[\s\S]*font: 700 14px\/1\.2/);
|
||||
assert.match(styles, /\.client-device-name-ip \{[\s\S]*font-size: 12px/);
|
||||
assert.match(styles, /\.client-device-alias-trigger \{[\s\S]*font: 700 14px\/1\.2/);
|
||||
assert.match(styles, /\.client-device-ip \{[\s\S]*font: 600 12px\/1\.2/);
|
||||
assert.match(styles, /\.client-device-last-seen \{[\s\S]*position: absolute;[\s\S]*top: 0;[\s\S]*left: 0;[\s\S]*font-size: 8\.5px/);
|
||||
assert.match(styles, /\.client-device-traffic strong \{[\s\S]*font-size: 10px/);
|
||||
assert.match(styles, /\.client-device-name > span \{[^}]*opacity: 0/);
|
||||
assert.match(styles, /\.client-device-name > \.client-device-name-primary \{[^}]*opacity: 1/);
|
||||
assert.match(styles, /\.client-device-name > span \{[^}]*transition: opacity 360ms[^}]*transform 480ms/);
|
||||
assert.match(styles, /\.client-device-name:not\(\.is-address-only\):hover \.client-device-name-primary[\s\S]*translateY\(-0\.18em\)/);
|
||||
assert.match(styles, /\.client-device-name:not\(\.is-address-only\):hover \.client-device-name-ip[\s\S]*opacity: 1[\s\S]*translateY\(0\) scale\(1\)/);
|
||||
assert.match(styles, /\.client-device-name-heading:has\(\.client-device-name:not\(\.is-address-only\):hover\) \+ \.client-device-edit-wrap[\s\S]*opacity: 0/);
|
||||
assert.match(styles, /\.client-device-name\.is-copied \.client-device-name-feedback[\s\S]*opacity: 1/);
|
||||
assert.match(styles, /\.client-device-name-feedback \{[^}]*font-size: 9px/);
|
||||
assert.match(styles, /\.client-device-name-separator \{[\s\S]*color: var\(--client-muted\)/);
|
||||
assert.match(styles, /\.client-device-ip\.is-copied \{[\s\S]*client-device-ip-copy 800ms/);
|
||||
assert.match(styles, /\.client-device-main \{[^}]*height: 34px[\s\S]*align-items: flex-end[\s\S]*padding-top: 11px/);
|
||||
assert.match(styles, /\.client-device-last-seen \{[^}]*height: 10px[\s\S]*align-items: center/);
|
||||
assert.match(styles, /\.client-device-traffic-value\.has-delta > \.is-total[\s\S]*translateY\(-0\.18em\)/);
|
||||
@@ -125,7 +122,7 @@ test('Gateway device inventory uses the existing accessible responsive drawer',
|
||||
assert.match(styles, /\.client-device-edit:hover svg[\s\S]*translate\(1px, -1px\) rotate\(-4deg\)/);
|
||||
assert.match(styles, /\.client-devices-sort:hover \.client-devices-sort-icon[\s\S]*rotate\(360deg\)/);
|
||||
assert.match(styles, /\.client-devices-refresh-ring circle[\s\S]*client-devices-refresh-progress 15s/);
|
||||
assert.match(styles, /@media \(prefers-reduced-motion: reduce\)[\s\S]*\.client-device-policy svg[\s\S]*\.client-device-name > span[\s\S]*\.client-device-traffic-value > span[\s\S]*\.client-device-traffic-breakdown[\s\S]*\.client-device-traffic-lines[\s\S]*\.client-text-morph-value/);
|
||||
assert.match(styles, /@media \(prefers-reduced-motion: reduce\)[\s\S]*\.client-device-policy svg[\s\S]*\.client-device-alias-trigger[\s\S]*\.client-device-ip[\s\S]*\.client-device-traffic-value > span[\s\S]*\.client-device-traffic-breakdown[\s\S]*\.client-device-traffic-lines[\s\S]*\.client-text-morph-value/);
|
||||
assert.match(styles, /\.client-drawer \{[\s\S]*z-index: 50;[\s\S]*box-shadow:/);
|
||||
assert.match(styles, /\.harbor-versions \{[\s\S]*z-index: 40/);
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import test from 'node:test';
|
||||
const root = path.resolve(import.meta.dirname, '../..');
|
||||
const styles = fs.readFileSync(path.join(root, 'src/web/styles.css'), 'utf8');
|
||||
const component = fs.readFileSync(path.join(root, 'src/web/components/ClientOverviewPage.jsx'), 'utf8');
|
||||
const diagnostics = fs.readFileSync(path.join(root, 'src/web/components/ConnectivityDiagnosticsPanel.jsx'), 'utf8');
|
||||
|
||||
function rule(selector, source = styles) {
|
||||
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
@@ -110,6 +111,17 @@ test('secondary menus share one right rail and both drawers open from the right'
|
||||
assert.match(component, /className={`client-drawer client-local-rules/);
|
||||
});
|
||||
|
||||
test('connectivity diagnostics render stable compact tables before the first run', () => {
|
||||
assert.match(diagnostics, /CONNECTIVITY_IP_SOURCES\.map/);
|
||||
assert.match(diagnostics, /const sites = \[\.\.\.CONNECTIVITY_SITES, \.\.\.customServices\]/);
|
||||
assert.equal((diagnostics.match(/<table className="client-diagnostics-table"/g) || []).length, 2);
|
||||
assert.match(diagnostics, /Добавить свой сервис/);
|
||||
assert.match(diagnostics, /client-diagnostics-refresh/);
|
||||
assert.doesNotMatch(diagnostics, /Проверить ещё раз|client-diagnostics-empty|client-diagnostics-run/);
|
||||
assert.match(rule('.client-diagnostics-feedback'), /min-height:\s*34px/);
|
||||
assert.match(rule('.client-diagnostics-table'), /table-layout:\s*fixed/);
|
||||
});
|
||||
|
||||
test('duration and Gateway access keep stable geometry without tabs', () => {
|
||||
assert.match(rule('.client-state-detail'), /min-height:\s*44px/);
|
||||
assert.match(rule('.client-duration-toggle'), /min-height:\s*44px/);
|
||||
|
||||
Reference in New Issue
Block a user