Project

General

Profile

Download (5.91 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / test / haketilo_test / unit / test_broadcast.py @ fd9f2fc4

1
# SPDX-License-Identifier: CC0-1.0
2

    
3
"""
4
Haketilo unit tests - message broadcasting
5
"""
6

    
7
# This file is part of Haketilo
8
#
9
# Copyright (C) 2021, Wojtek Kosior
10
#
11
# This program is free software: you can redistribute it and/or modify
12
# it under the terms of the CC0 1.0 Universal License as published by
13
# the Creative Commons Corporation.
14
#
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
# CC0 1.0 Universal License for more details.
19

    
20
import pytest
21
from selenium.webdriver.support.ui import WebDriverWait
22

    
23
from ..script_loader import load_script
24
from .utils import broker_js
25

    
26
test_page_html = '''
27
<!DOCTYPE html>
28
<script src="/testpage.js"></script>
29
<h2>d0 (channel `somebodyoncetoldme`)</h2>
30
<div id="d0"></div>
31
<h2>d1 (channel `worldisgonnarollme`)</h2>
32
<div id="d1"></div>
33
<h2>d2 (both channels)</h2>
34
<div id="d2"></div>
35
'''
36

    
37
@pytest.mark.ext_data({
38
    'background_script': broker_js,
39
    'test_page':         test_page_html,
40
    'extra_files': {
41
        'testpage.js':   lambda: load_script('common/broadcast.js')
42
    }
43
})
44
@pytest.mark.usefixtures('webextension')
45
def test_broadcast(driver, execute_in_page, wait_elem_text):
46
    """
47
    A test that verifies the broadcasting system based on WebExtension messaging
48
    API and implemented in `background/broadcast_broker.js` and
49
    `common/broadcast.js` works correctly.
50
    """
51
    # The broadcast facility is meant to enable message distribution between
52
    # multiple contexts (e.g. different tabs/windows). Let's open the same
53
    # extension's test page in a second window.
54
    driver.execute_script(
55
        '''
56
        window.open(window.location.href, "_blank");
57
        window.open(window.location.href, "_blank");
58
        ''')
59
    WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) == 3)
60
    windows = [*driver.window_handles]
61

    
62
    # Let's first test if a simple message can be successfully broadcasted
63
    driver.switch_to.window(windows[0])
64
    execute_in_page(
65
        '''
66
        const divs = [0, 1, 2].map(n => document.getElementById("d" + n));
67
        let appender = n => (t => divs[n].append("\\n" + `[${t[0]}, ${t[1]}]`));
68
        let listener0 = listener_connection(appender(0));
69
        subscribe(listener0, "somebodyoncetoldme");
70
        ''')
71

    
72
    driver.switch_to.window(windows[1])
73
    execute_in_page(
74
        '''
75
        let sender0 = sender_connection();
76
        out(sender0, "somebodyoncetoldme", "iaintthesharpesttool");
77
        ''')
78

    
79
    driver.switch_to.window(windows[0])
80
    wait_elem_text('d0', '[somebodyoncetoldme, iaintthesharpesttool]')
81

    
82
    # Let's add 2 more listeners
83
    driver.switch_to.window(windows[0])
84
    execute_in_page(
85
        '''
86
        let listener1 = listener_connection(appender(1));
87
        subscribe(listener1, "worldisgonnarollme");
88
        let listener2 = listener_connection(appender(2));
89
        subscribe(listener2, "worldisgonnarollme");
90
        subscribe(listener2, "somebodyoncetoldme");
91
        ''')
92

    
93
    # Let's send one message to one channel and one to the other. Verify they
94
    # were received by the rght listeners.
95
    driver.switch_to.window(windows[1])
96
    execute_in_page(
97
        '''
98
        out(sender0, "somebodyoncetoldme", "intheshed");
99
        out(sender0, "worldisgonnarollme", "shewaslooking");
100
        ''')
101

    
102
    driver.switch_to.window(windows[0])
103
    wait_elem_text('d0', 'intheshed')
104
    wait_elem_text('d1', 'shewaslooking')
105
    wait_elem_text('d2', 'intheshed')
106
    wait_elem_text('d2', 'shewaslooking')
107

    
108
    text = execute_in_page('returnval(divs[0].innerText);')
109
    assert 'shewaslooking' not in text
110
    text = execute_in_page('returnval(divs[1].innerText);')
111
    assert 'intheshed' not in text
112

    
113
    # Let's create a second sender in third window and use it to send messages
114
    # with the 'prepare' feature.
115
    driver.switch_to.window(windows[2])
116
    execute_in_page(
117
        '''
118
        let sender1 = sender_connection();
119
        prepare(sender1, "somebodyoncetoldme", "kindadumb");
120
        out(sender1, "worldisgonnarollme", "withherfinger");
121
        ''')
122

    
123
    driver.switch_to.window(windows[0])
124
    wait_elem_text('d1', 'withherfinger')
125
    text = execute_in_page('returnval(divs[0].innerText);')
126
    assert 'kindadumb' not in text
127

    
128
    driver.switch_to.window(windows[2])
129
    execute_in_page('flush(sender1);')
130

    
131
    driver.switch_to.window(windows[0])
132
    wait_elem_text('d0', 'kindadumb')
133

    
134
    # Let's verify that prepare()'d messages are properly discarded when
135
    # discard() is called.
136
    driver.switch_to.window(windows[2])
137
    execute_in_page(
138
        '''
139
        prepare(sender1, "somebodyoncetoldme", "andherthumb");
140
        discard(sender1);
141
        prepare(sender1, "somebodyoncetoldme", "andhermiddlefinger");
142
        flush(sender1);
143
        ''')
144

    
145
    driver.switch_to.window(windows[0])
146
    wait_elem_text('d0', 'andhermiddlefinger')
147
    text = execute_in_page('returnval(divs[0].innerText);')
148
    assert 'andherthumb' not in text
149

    
150
    # Let's verify prepare()'d messages are properly auto-flushed when the other
151
    # end of the connection gets killed (e.g. because browser tab gets closed).
152
    driver.switch_to.window(windows[2])
153
    execute_in_page(
154
        '''
155
        prepare(sender1, "worldisgonnarollme", "intheshape", 500);
156
        ''')
157
    driver.close()
158

    
159
    driver.switch_to.window(windows[0])
160
    wait_elem_text('d2', 'intheshape')
161

    
162
    # Verify listener's connection gets closed properly.
163
    execute_in_page('close(listener0); close(listener1);')
164

    
165
    driver.switch_to.window(windows[1])
166
    execute_in_page('out(sender0, "worldisgonnarollme", "ofanL");')
167
    execute_in_page('out(sender0, "somebodyoncetoldme", "forehead");')
168

    
169
    driver.switch_to.window(windows[0])
170
    wait_elem_text('d2', 'ofanL')
171
    wait_elem_text('d2', 'forehead')
172
    for i in (0, 1):
173
        text = execute_in_page('returnval(divs[arguments[0]].innerText);', i)
174
        assert 'ofanL' not in text
175
        assert 'forehead' not in text
(4-4/25)