"""V8.34.1: safe opt-in multi-banner and practical no-code product specs."""
from pathlib import Path
import pytest
from bs4 import BeautifulSoup
from app.blueprints import new_block, validate_blocks, render_blocks, BLOCK_PROPERTY_SCHEMA
from test_factory_v2 import factory, site
ROOT=Path(__file__).resolve().parents[1]
def slides(*titles):
return [dict(title=t,subtitle='精选车型',description='图片说明',image='/media/car.webp',button='询价',href='/contact/') for t in titles]
def test_first_slide_priority_and_succeeding_lazy():
block=new_block('hero',{'slides':slides('A','B','C')})
html=render_blocks([block],{'name':'HESU'},{'route':'/','type':'home'},[])
soup=BeautifulSoup(html,'html.parser')
images=soup.select('.sf-hero-panel img')
assert len(images)==3
assert images[0]['loading']=='eager' and images[0]['fetchpriority']=='high'
assert [im['loading'] for im in images[1:]]==['lazy','lazy']
assert len(soup.select('[data-sf-slide-step]'))==2
assert soup.select_one('.sf-hero-count').text=='1 / 3'
assert [x.text for x in soup.select('.sf-hero-copy h1')]==['A']
assert [x.text for x in soup.select('.sf-hero-copy h2')]==['B','C']
def test_slides_are_opt_in_legacy_markup_unchanged():
old={'id':'legacy-banner-01','type':'hero','title':'Original','description':'Intro','image':'/media/x.jpg'}
html=render_blocks([old],{}, {'route':'/'},[])
assert 'sf-hero-slider' not in html and 'Original' in html
with_slide=new_block('hero',{'slides':slides('A')})
assert len(BeautifulSoup(render_blocks([with_slide],{}, {'route':'/about/'},[]),'html.parser').select('.sf-hero-panel'))==1
assert 'data-sf-slide-step' not in render_blocks([with_slide],{}, {'route':'/about/'},[])
@pytest.mark.parametrize('bad',[
[dict(title='',image='javascript:alert(1)',href='javascript:alert(1)',button='hi')]})
html=render_blocks([block],{}, {'route':'/'},[])
assert ''}]
manual=new_block('attributes',{'source_mode':'custom','items':added})
custom=render_blocks([manual],{},page,[])
assert '车长' in custom and 'BYD' not in custom
assert '