v0.33.0
This commit is contained in:
1 parent
bbfa8cbc3f
commit
2ccc598b12
49 files changed
+4771
-639
No files matched your search
+139
@@ -0,0 +1,139 @@
|
||||
from pathlib import Path
|
||||
import re, json
|
||||
from playwright.sync_api import sync_playwright
|
||||
root=Path(__file__).resolve().parents[2]
|
||||
router=(root/'src/admin/router.rs').read_text()
|
||||
|
||||
def concatenate(section):
|
||||
pattern=r'fn '+section+r'\([^)]*\)[^{]*\{'
|
||||
m=re.search(pattern,router)
|
||||
assert m, section
|
||||
text=router[m.end():]
|
||||
# The array contents are bounded by ].join("\\n") before the next function.
|
||||
text=text[:re.search(r'\]\s*\.join\("\\n"\)', text).start()]
|
||||
result=[]
|
||||
for line in text.splitlines():
|
||||
line=line.strip()
|
||||
if 'include_str!("' in line:
|
||||
path=re.search(r'include_str!\("([^"]+)"\)',line).group(1)
|
||||
result.append((root/'src/admin'/path).read_text())
|
||||
elif line=='admin_vhosts_javascript(),':
|
||||
result.append('(() => {\n'+''.join((root/'src/admin/web/vhosts'/f'{part}.js').read_text()+'\n' for part in ['core','protocol','health','rates','editor','render'])+'})();')
|
||||
elif line.startswith('"') and line.endswith('",'):
|
||||
result.append(json.loads(line[:-1]))
|
||||
return '\n'.join(result)
|
||||
bundle=concatenate('admin_app_javascript')
|
||||
assert 'window.rustProxyOverviewSamples =' in bundle
|
||||
assert bundle.index('window.rustProxyOverviewSamples =') < bundle.index('window.rustProxyOverviewSamples.onChange(')
|
||||
css=(root/'src/admin/web/style.css').read_text()
|
||||
html=(root/'src/admin/web/index.html').read_text()
|
||||
with sync_playwright() as p:
|
||||
browser=p.chromium.launch(headless=True, executable_path='/usr/bin/chromium',args=['--no-sandbox','--allow-file-access-from-files'])
|
||||
for width in [320,375,800,1440]:
|
||||
page=browser.new_page(viewport={'width':width,'height':900})
|
||||
errors=[]
|
||||
page.on('pageerror',lambda e: errors.append(str(e)))
|
||||
# Execute in a fully populated DOM without disallowed filesystem/network navigation.
|
||||
page.set_content(html.replace('/assets/app___RUSTPROXY_ASSET_ID__.js','').replace('/assets/style___RUSTPROXY_ASSET_ID__.css',''))
|
||||
page.add_style_tag(content=css)
|
||||
page.add_script_tag(content=bundle)
|
||||
page.wait_for_timeout(550)
|
||||
state=page.evaluate('''() => ({ controller:typeof window.rustProxyOverviewSamples,
|
||||
handle:typeof window.rustProxyOverviewSamples?.onChange,
|
||||
web:typeof window.rustProxyWebOverview, services:typeof window.rustProxyWebServer,
|
||||
registry: document.querySelectorAll('[data-dashboard-widget^="www_"]').length,
|
||||
htmlWidth:document.documentElement.scrollWidth,windowWidth:window.innerWidth })''')
|
||||
print(width,state,'errors',errors)
|
||||
assert state['controller']=='object' and state['handle']=='function' and state['web']=='object'
|
||||
assert state['registry']==12
|
||||
assert not [e for e in errors if 'onChange' in e or 'ReferenceError' in e or 'SyntaxError' in e or 'TypeError' in e],errors
|
||||
assert state['htmlWidth'] <= state['windowWidth'] + 2
|
||||
# The selector belongs to the same header row as the core connection;
|
||||
# hiding it on other panels must not leave an empty dashboard row.
|
||||
layout = page.evaluate('''() => {
|
||||
document.getElementById('workspace').hidden = false;
|
||||
setPanel('overview', false);
|
||||
const status = document.getElementById('connection-label');
|
||||
const sample = document.getElementById('overview-samples-toolbar');
|
||||
const row = document.querySelector('.page-intro-meta-row');
|
||||
const rect = node => { const r = node.getBoundingClientRect();
|
||||
return {x:r.x,y:r.y,width:r.width,height:r.height,right:r.right}; };
|
||||
const overview = { status:rect(status),sample:rect(sample),row:rect(row),
|
||||
visible: !sample.hidden,inside: row.contains(sample) && row.contains(status),
|
||||
overflow: document.documentElement.scrollWidth > innerWidth + 2 };
|
||||
setPanel('web-server', false);
|
||||
const notOverview = sample.hidden && !status.hidden;
|
||||
setPanel('overview', false);
|
||||
return {overview,notOverview,visibleAgain:!sample.hidden};
|
||||
}''')
|
||||
assert layout['overview']['inside'] and layout['overview']['visible']
|
||||
assert layout['notOverview'] and layout['visibleAgain']
|
||||
assert not layout['overview']['overflow'], (width, layout)
|
||||
if width >= 800:
|
||||
assert abs(layout['overview']['sample']['y'] - layout['overview']['status']['y']) <= 20, (width, layout)
|
||||
assert layout['overview']['sample']['right'] <= layout['overview']['row']['right'] + 2, (width, layout)
|
||||
# A genuinely sampled WWW metrics payload (not a screenshot-only fixture).
|
||||
report = page.evaluate('''() => {
|
||||
Object.defineProperty(window.performance, "now", {configurable:true, value:()=>window.__clock});
|
||||
window.__clock = 1000;
|
||||
currentPanel = "overview";
|
||||
document.getElementById('workspace').hidden = false;
|
||||
document.getElementById('login').hidden = true;
|
||||
document.getElementById('panel-overview').hidden = false;
|
||||
for (const n of document.querySelectorAll('[data-dashboard-widget^="www_"]')) n.hidden = false;
|
||||
function snap(k) {
|
||||
return {revision:7, web_server_metrics:{
|
||||
"public-site": {web: {requests:100+k*30, status_2xx:86+k*24, status_3xx:3+k,
|
||||
status_4xx:8+k*2, status_5xx:3+k*3, response_headers_us:4000000+k*1300000,
|
||||
response_bytes:100000+k*20000, static_requests:70+k*20, php_requests:25+k*7,
|
||||
other_requests:5+k*3, methods:[90+k*25,8+k*4,0,0,2+k],
|
||||
selected_status:[80+k*18,2,2,1,5+k,0,0,0], active_headers:0},
|
||||
php: {metrics:{requests:25+k*7, response_headers_us:2000000+k*700000,
|
||||
response_bytes:30000+k*5000,failures:[1+k,1+k,1+k,0,0,0,0,0,0]},
|
||||
capacity_limit:32, capacity_used:8, capacity_available:24}}}
|
||||
};
|
||||
}
|
||||
const before = snap(0), after = snap(1);
|
||||
// Saved custom layout from before 0.33.0 must not enable new cards.
|
||||
const savedLayout = applyDashboardLayout(['requests', 'errors'],
|
||||
normalizeHiddenDashboardWidgets([], ['requests', 'errors']));
|
||||
const newCardsHidden = [...document.querySelectorAll('[data-dashboard-widget^="www_"]')]
|
||||
.every(card=>card.hidden);
|
||||
for (const n of document.querySelectorAll('[data-dashboard-widget^="www_"]')) n.hidden = false;
|
||||
window.rustProxyWebOverview.render(before, true);
|
||||
window.__clock = 4000;
|
||||
window.rustProxyWebOverview.render(after, true);
|
||||
let ids = ['www_requests-all-line', 'www_requests-php-line',
|
||||
'www_latency-web-line', 'www_traffic-php-line', 'www_status_trend-5xx-line'];
|
||||
const linePaths = ids.map(id=>document.getElementById(id)?.getAttribute('d'));
|
||||
const statusText = document.getElementById('www_status-value').textContent;
|
||||
const capacityText = document.getElementById('www_capacity-value').textContent;
|
||||
const rateText = document.getElementById('www_php_requests-value').textContent;
|
||||
const bars = document.querySelectorAll('#www_top_services-bars .www-top-row').length;
|
||||
window.rustProxyOverviewSamples.setLimit(120);
|
||||
const historyLimit = window.rustProxyOverviewSamples.getLimit();
|
||||
currentPanel = "web-server";
|
||||
envelope = {config:{web_services:[{id:'public-site', name:'Public site',document_root:'/srv/www/public'}],vhosts:[]}};
|
||||
window.rustProxyWebServer.render();
|
||||
const details = document.querySelector('.www-service-panel');
|
||||
details.open = true;
|
||||
window.__clock = 7000;
|
||||
window.rustProxyWebServer.renderLive(before, true);
|
||||
window.__clock = 10000;
|
||||
window.rustProxyWebServer.renderLive(after, true);
|
||||
const value = details.querySelector('[data-web-live-field="requests"]')?.textContent;
|
||||
const phpCapacity = details.querySelector('[data-web-live-field="php"]')?.textContent;
|
||||
return {linePaths,statusText,capacityText,rateText,bars,historyLimit,value,phpCapacity,newCardsHidden,
|
||||
width:document.documentElement.scrollWidth};
|
||||
}''')
|
||||
print('sampled WWW',width,report)
|
||||
assert all(report['linePaths']), report
|
||||
assert report['statusText'] != '-' and report['capacityText'] == '8 / 32', report
|
||||
assert report['rateText'] not in ('-', '0.0/s'), report
|
||||
assert report['bars'] == 1 and report['historyLimit'] == 120 and report['newCardsHidden'], report
|
||||
assert report['value'] and report['phpCapacity'] == '8 / 32', report
|
||||
assert report['width'] <= width + 2, report
|
||||
assert not [e for e in errors if any(x in e for x in ('ReferenceError', 'TypeError', 'SyntaxError'))], errors
|
||||
page.close()
|
||||
browser.close()
|
||||
print('PASS: actual composed admin bundle starts without a JS TypeError')
|
||||
Reference in new issue
Block a user