#!/usr/bin/env python3
"""Browser checks for @mention suggestions. Run from repository root."""
from __future__ import annotations
from pathlib import Path
from playwright.sync_api import sync_playwright
ROOT = Path(__file__).resolve().parents[1]
HTML = '''
__STYLES__
'''
def main():
source = (ROOT / 'static/js/mention-autocomplete.js').read_text()
source = source.replace('import { t } from "@rustpad/i18n";', 'const t = (key, vars, fallback) => fallback;')
styles = (ROOT / 'static/css/styles.css').read_text()
html = HTML.replace('__STYLES__', f'').replace('__SCRIPT__', source)
with sync_playwright() as playwright:
browser = playwright.chromium.launch(executable_path="/usr/bin/chromium", args=["--no-sandbox"])
try:
page = browser.new_page(viewport={"width": 870, "height": 550})
errors = []
page.on("pageerror", lambda error: errors.append(str(error)))
page.set_content(html)
page.wait_for_function("!!window.autocomplete")
editor = page.locator('#editor')
options = page.locator('.mention-suggestions__option')
page.evaluate('''() => window.autocomplete.setUsers([
{nickname:'Dominik',color:'#ff0000'},
{nickname:'Dora',color:'#00ff00'},
{nickname:'Jan Domański',color:'#ff8800'},
{nickname:'Anna',color:'red'}
])''')
editor.fill('Witaj @do')
assert options.count() == 3, options.all_text_contents()
assert options.all_text_contents() == ['@Dominik', '@Dora', '@Jan Domański']
assert editor.get_attribute('aria-expanded') == 'true'
assert options.nth(0).get_attribute('aria-selected') == 'true'
editor.press('ArrowDown')
assert options.nth(1).get_attribute('aria-selected') == 'true'
editor.press('Enter')
assert editor.input_value() == 'Witaj @Dora '
assert page.evaluate('window.mentionInputTypes.at(-1)') == 'insertReplacementText'
assert page.locator('.mention-suggestions').is_hidden()
editor.fill('Test @do')
editor.press('ArrowDown')
editor.press('ArrowDown')
editor.press('Tab')
assert editor.input_value() == 'Test @Jan Domański '
editor.fill('@d')
assert options.count() == 3
editor.press('Escape')
assert page.locator('.mention-suggestions').is_hidden()
editor.press('ArrowDown')
assert page.locator('.mention-suggestions').is_hidden(), 'Escape must dismiss the query'
editor.fill('@do')
options.first.click()
assert editor.input_value() == '@Dominik '
editor.fill('user@example.org')
assert page.locator('.mention-suggestions').is_hidden(), 'email should not trigger suggestions'
editor.fill('hello @unknown')
assert page.locator('.mention-suggestions').is_hidden(), 'only authorized members should be shown'
editor.fill('Hi @')
assert options.count() == 4
page.evaluate('window.autocomplete.setUsers([])')
assert page.locator('.mention-suggestions').is_hidden(), 'clear users on logout'
editor.fill('Hi @do')
assert page.locator('.mention-suggestions').is_hidden(), 'no guest suggestions'
page.evaluate('window.autocomplete.setUsers([{nickname:"Dominik",color:"#ff0000"}])')
editor.fill('Hi @do')
assert options.count() == 1
geometry = page.locator('.mention-suggestions').bounding_box()
shell_geometry = page.locator('.editor-shell').bounding_box()
assert geometry['x'] >= shell_geometry['x'] - 1
assert geometry['y'] >= shell_geometry['y'] - 1
assert geometry['x'] + geometry['width'] <= shell_geometry['x'] + shell_geometry['width'] + 1
assert geometry['y'] + geometry['height'] <= shell_geometry['y'] + shell_geometry['height'] + 1
editor.fill('Edycja @do.')
page.evaluate('''() => {let e = document.querySelector('#editor'); e.setSelectionRange(10,10); e.dispatchEvent(new Event('keyup'));}''')
assert options.count() == 1
editor.press('Enter')
assert editor.input_value() == 'Edycja @Dominik.' # no unnecessary space before punctuation
assert not errors, errors
print('PASS: Chromium editor completion, keyboard/mouse, privacy, positioning, punctuation')
finally:
browser.close()
if __name__ == '__main__':
main()