84 lines
4.0 KiB
Python
84 lines
4.0 KiB
Python
|
|
"""V8.21.3 mobile navigation must be optional, safe and theme-independent."""
|
||
|
|
import copy
|
||
|
|
import pytest
|
||
|
|
from tests.test_factory import client, create
|
||
|
|
from app import site_design_v87, builder, db
|
||
|
|
|
||
|
|
|
||
|
|
def config(tabs=True):
|
||
|
|
x=copy.deepcopy(site_design_v87.DEFAULTS)
|
||
|
|
x['mobile_tabs']={'enabled':tabs,'items':[
|
||
|
|
{'title':'首页','icon':'home','route':'/','action':'link'},
|
||
|
|
{'title':'产品','icon':'products','route':'/products/','action':'link'},
|
||
|
|
{'title':'菜单','icon':'menu','route':'/','action':'menu'},
|
||
|
|
]}
|
||
|
|
return x
|
||
|
|
|
||
|
|
@pytest.mark.parametrize('theme',['automotive','industrial','corporate','minimal'])
|
||
|
|
def test_all_four_professional_themes_render_optional_bar(client,theme):
|
||
|
|
sid=create(client,theme)
|
||
|
|
url=f'/api/sites/{sid}/site-design'
|
||
|
|
before=builder.build(sid,False)
|
||
|
|
previous=(db.DATA/'builds'/sid/before['version']/'dist/index.html').read_text()
|
||
|
|
assert 'data-mobile-tabs' not in previous
|
||
|
|
payload=config()
|
||
|
|
stored=client.put(url,json={'config':payload,'expected_revision':0})
|
||
|
|
assert stored.status_code==200,stored.text
|
||
|
|
waiting=builder.build(sid,False)
|
||
|
|
assert 'data-mobile-tabs' not in (db.DATA/'builds'/sid/waiting['version']/'dist/index.html').read_text()
|
||
|
|
published=client.post(url+'/publish',json={'expected_revision':1})
|
||
|
|
assert published.status_code==200,published.text
|
||
|
|
after=builder.build(sid,False)
|
||
|
|
dist=db.DATA/'builds'/sid/after['version']/'dist'
|
||
|
|
html=(dist/'index.html').read_text()
|
||
|
|
css=(dist/'assets/commercial.css').read_text()
|
||
|
|
js=(dist/'assets/pro.js').read_text()
|
||
|
|
assert 'data-mobile-tabs' in html and 'data-mobile-open-menu' in html
|
||
|
|
assert 'aria-current="page"' in html
|
||
|
|
assert '手机底部快捷导航' in html
|
||
|
|
assert 'sf-drawer-header' in css and 'sf-drawer-open' in css
|
||
|
|
assert 'sf-mobile-drawer-backdrop' in js and 'Escape' in js
|
||
|
|
assert len(html)>2000
|
||
|
|
|
||
|
|
|
||
|
|
def test_tabs_can_be_disabled_while_items_remain(client):
|
||
|
|
sid=create(client)
|
||
|
|
url=f'/api/sites/{sid}/site-design'
|
||
|
|
payload=config(False)
|
||
|
|
assert client.put(url,json={'config':payload,'expected_revision':0}).status_code==200
|
||
|
|
assert client.post(url+'/publish',json={'expected_revision':1}).status_code==200
|
||
|
|
dist=db.DATA/'builds'/sid/builder.build(sid,False)['version']/'dist'
|
||
|
|
assert 'data-mobile-tabs' not in (dist/'index.html').read_text()
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.parametrize('bad',[{'enabled':True,'items':[]},
|
||
|
|
{'enabled':'yes','items':[]},
|
||
|
|
{'enabled':True,'items':[{'title':'Hello','icon':'script','route':'/'}]},
|
||
|
|
{'enabled':True,'items':[{'title':'测试','icon':'home','route':'javascript:alert(1)'}]},
|
||
|
|
{'enabled':True,'items':[{'title':'测试','icon':'home','route':'//127.0.0.1'}]},
|
||
|
|
{'enabled':True,'items':[{'title':'X'*20,'icon':'home','route':'/'}]},
|
||
|
|
{'enabled':True,'items':[{'title':'1','icon':'home','route':'/'}]*6},
|
||
|
|
{'enabled':True,'items':[{'title':'ok','icon':'home','action':'eval','route':'/'}]}])
|
||
|
|
def test_invalid_mobile_tabs_rejected(bad):
|
||
|
|
payload=config()
|
||
|
|
payload['mobile_tabs']=bad
|
||
|
|
with pytest.raises(Exception):site_design_v87.validate(payload)
|
||
|
|
|
||
|
|
|
||
|
|
def test_tab_config_is_normalized_and_legacy_defaults_are_safe():
|
||
|
|
legacy={'header':{},'responsive':{},'tokens':{},'footer':{},'nav':[]}
|
||
|
|
assert site_design_v87.validate(legacy)['mobile_tabs']=={'enabled':False,'items':[]}
|
||
|
|
planned=config()
|
||
|
|
out=site_design_v87.validate(planned)
|
||
|
|
assert out['mobile_tabs']['items'][-1]['action']=='menu'
|
||
|
|
assert out['mobile_tabs']['items'][-1]['route']=='/'
|
||
|
|
|
||
|
|
|
||
|
|
def test_contact_links_are_configurable_but_unsafe_schemes_are_blocked():
|
||
|
|
for url in ('https://wa.me/12345678','tel:+8613800000000','mailto:hello@example.com'):
|
||
|
|
v=config();v['mobile_tabs']['items'][1]['route']=url
|
||
|
|
assert site_design_v87.validate(v)['mobile_tabs']['items'][1]['route']==url
|
||
|
|
for url in ('http://example.com','javascript:alert(1)','data:text/html,hi','https://user:pass@example.com/','https://bad.example/\nnewline'):
|
||
|
|
v=config();v['mobile_tabs']['items'][1]['route']=url
|
||
|
|
with pytest.raises(Exception):site_design_v87.validate(v)
|