feat: add qualified research exports and accessible voice handoff
This commit is contained in:
1 parent
135e0c0da2
commit
08b7e20be8
4 files changed
+74
-16
No files matched your search
@@ -18,6 +18,9 @@ def fixture(page, replay=False):
|
||||
calls.append((method, path, body))
|
||||
if path == '/api/auth/me': data = {'user': dict(id='alice', username='alice', role='user', status='ready')}
|
||||
elif path == '/voices': data = {'voices': []}
|
||||
elif path == '/api/research': data = {'available':True,'mode':'hermes_tools','reason':''}
|
||||
elif path.endswith('/export'):
|
||||
r.fulfill(body='private export',content_type='text/plain'); return
|
||||
elif path == '/api/capabilities': data = {'version':1,'features':{}}
|
||||
elif path == '/api/preferences':
|
||||
if method == 'PUT': preferences.update(body); preferences['revision'] += 1
|
||||
@@ -150,3 +153,53 @@ def test_archived_move_sync_conflict_and_mobile_actions():
|
||||
expect(page.locator('#chatTitle')).to_have_text('Newest revision')
|
||||
expect(page.locator('#chatNotice')).to_contain_text('Conversation refreshed')
|
||||
browser.close()
|
||||
|
||||
|
||||
def test_voice_history_refresh_keyboard_focus_and_large_text():
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
page = browser.new_page(viewport={'width':1280,'height':900}, reduced_motion='reduce')
|
||||
calls, streams, conversations, messages = fixture(page)
|
||||
page.goto('https://hope.test/'); page.wait_for_load_state('networkidle')
|
||||
page.get_by_role('button',name='A saved thought',exact=True).click()
|
||||
expect(page.locator('#chatTitle')).to_have_text('A saved thought')
|
||||
expect(page.locator('#chatTimeline')).to_contain_text('Original question')
|
||||
page.locator('#primaryInput').fill('Keep my draft')
|
||||
page.evaluate("window.dispatchEvent(new CustomEvent('hope:voice-state',{detail:{active:true,conversation_id:'c1'}}))")
|
||||
messages['c1'].append(dict(id='voice1',role='assistant',content='Saved voice reply with [source](https://example.com/report)',status='completed'))
|
||||
page.evaluate("window.dispatchEvent(new CustomEvent('hope:voice-state',{detail:{active:false,conversation_id:'c1'}}))")
|
||||
expect(page.locator('#chatTimeline')).to_contain_text('Saved voice reply')
|
||||
expect(page.locator('#primaryInput')).to_have_value('Keep my draft')
|
||||
expect(page.locator('#chatTimeline a')).to_have_attribute('href','https://example.com/report')
|
||||
expect(page.locator('#chatNotice')).to_contain_text('Voice conversation saved')
|
||||
page.screenshot(path='/tmp/hope-chat-opal-desktop.png')
|
||||
page.keyboard.press('Control+k'); expect(page.locator('#conversationSearch')).to_be_focused()
|
||||
page.keyboard.press('Escape')
|
||||
page.locator('#openPreferences').click(); expect(page.locator('#preferencesDialog')).to_be_visible()
|
||||
page.keyboard.press('Escape'); expect(page.locator('#openPreferences')).to_be_focused()
|
||||
# Native controls remain usable at large text and narrow effective viewport.
|
||||
page.set_viewport_size({'width':640,'height':900})
|
||||
page.add_style_tag(content='html {font-size: 200% !important;}')
|
||||
assert page.evaluate('document.documentElement.scrollWidth <= innerWidth')
|
||||
page.locator('#drawerOpen').click(); page.keyboard.press('Escape')
|
||||
expect(page.locator('#drawerOpen')).to_be_focused()
|
||||
assert page.evaluate("getComputedStyle(document.getElementById('drawerOpen')).outlineStyle") != 'none'
|
||||
browser.close()
|
||||
|
||||
|
||||
def test_qualified_research_and_private_export():
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
page = browser.new_page(); calls, streams, conversations, messages = fixture(page)
|
||||
page.goto('https://hope.test/'); page.wait_for_load_state('networkidle')
|
||||
expect(page.locator('#researchMode')).to_be_visible()
|
||||
page.locator('#researchMode').select_option('research')
|
||||
page.locator('#primaryInput').fill('Research this topic'); page.locator('#primarySend').click()
|
||||
expect(page.locator('#chatTimeline')).to_contain_text('Answer')
|
||||
assert next(body for method,path,body in calls if method == 'POST' and path.endswith('/messages'))['mode'] == 'research'
|
||||
with page.expect_download() as info: page.locator('#exportMarkdown').click()
|
||||
assert info.value.suggested_filename.endswith('.md')
|
||||
with page.expect_download() as info: page.locator('#exportJSON').click()
|
||||
assert info.value.suggested_filename.endswith('.json')
|
||||
assert all('/api/conversations/' in path for method,path,body in calls if path.endswith('/export'))
|
||||
browser.close()
|
||||
Reference in new issue
Block a user