1# Copyright (c) 2020 Guangwang Huang
2#
3# Permission is hereby granted, free of charge, to any person obtaining a copy
4# of this software and associated documentation files (the "Software"), to deal
5# in the Software without restriction, including without limitation the rights
6# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7# copies of the Software, and to permit persons to whom the Software is
8# furnished to do so, subject to the following conditions:
9#
10# The above copyright notice and this permission notice shall be included in
11# all copies or substantial portions of the Software.
12#
13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19# SOFTWARE.
20
21import os
22import re
23import subprocess
24
25import pytest
26
27import libqtile.bar
28import libqtile.config
29import libqtile.layout
30import libqtile.widget
31from libqtile.confreader import Config
32from libqtile.lazy import lazy
33
34
35class ServerConfig(Config):
36    auto_fullscreen = True
37    keys = [
38        libqtile.config.Key(['mod4'], 'Return', lazy.spawn('xterm')),
39        libqtile.config.Key(['mod4'], 't', lazy.spawn('xterm'),
40                            desc='dummy description'),
41        libqtile.config.Key([], 'y', desc='noop'),
42        libqtile.config.KeyChord(['mod4'], 'q', [
43            libqtile.config.KeyChord([], 'q', [
44                libqtile.config.Key([], 'a', lazy.togroup('a')),
45            ]),  # unnamed
46            libqtile.config.Key([], 'b', lazy.togroup('b')),
47        ], mode='named')
48    ]
49    mouse = []
50    groups = [
51        libqtile.config.Group("a"),
52        libqtile.config.Group("b"),
53        libqtile.config.Group("c"),
54    ]
55    layouts = [
56        libqtile.layout.Stack(num_stacks=1),
57        libqtile.layout.Stack(num_stacks=2),
58        libqtile.layout.Stack(num_stacks=3),
59    ]
60    floating_layout = libqtile.resources.default_config.floating_layout
61    screens = [
62        libqtile.config.Screen(
63            bottom=libqtile.bar.Bar(
64                [
65                    libqtile.widget.TextBox(name="one"),
66                ],
67                20
68            ),
69        ),
70        libqtile.config.Screen(
71            bottom=libqtile.bar.Bar(
72                [
73                    libqtile.widget.TextBox(name="two"),
74                ],
75                20
76            ),
77        )
78    ]
79
80
81server_config = pytest.mark.parametrize("manager", [ServerConfig], indirect=True)
82
83
84def run_qtile_cmd(args):
85    cmd = os.path.join(os.path.dirname(__file__), '..', 'bin', 'qtile')
86    argv = [cmd, "cmd-obj"]
87    argv.extend(args.split())
88    pipe = subprocess.Popen(argv, stdout=subprocess.PIPE)
89    output, _ = pipe.communicate()
90    return eval(output.decode())  # as returned by pprint.pprint
91
92
93@server_config
94def test_qtile_cmd(manager):
95
96    manager.test_window("foo")
97    wid = manager.c.window.info()["id"]
98
99    for obj in ["window", "group", "screen"]:
100        assert run_qtile_cmd('-s {} -o {} -f info'.format(manager.sockfile, obj))
101
102    layout = run_qtile_cmd('-s {} -o layout -f info'.format(manager.sockfile))
103    assert layout['name'] == 'stack'
104    assert layout['group'] == 'a'
105
106    window = run_qtile_cmd('-s {} -o window {} -f info'.format(manager.sockfile, wid))
107    assert window['id'] == wid
108    assert window['name'] == 'foo'
109    assert window['group'] == 'a'
110
111    group = run_qtile_cmd('-s {} -o group {} -f info'.format(manager.sockfile, 'a'))
112    assert group['name'] == 'a'
113    assert group['screen'] == 0
114    assert group['layouts'] == ['stack', 'stack', 'stack']
115    assert group['focus'] == 'foo'
116
117    assert run_qtile_cmd('-s {} -o screen {} -f info'.format(manager.sockfile, 0)) == \
118        {'height': 600, 'index': 0, 'width': 800, 'x': 0, 'y': 0}
119
120    bar = run_qtile_cmd('-s {} -o bar {} -f info'.format(manager.sockfile, 'bottom'))
121    assert bar['height'] == 20
122    assert bar['width'] == 800
123    assert bar['size'] == 20
124    assert bar['position'] == 'bottom'
125
126
127@server_config
128def test_display_kb(manager):
129    from pprint import pprint
130    cmd = '-s {} -o cmd -f display_kb'.format(manager.sockfile)
131    table = run_qtile_cmd(cmd)
132    print(table)
133    pprint(table)
134    assert table.count('\n') >= 2
135    assert re.match(r"(?m)^Mode\s{3,}KeySym\s{3,}Mod\s{3,}Command\s{3,}Desc\s*$",
136                    table)
137    assert re.search(r"(?m)^<root>\s{3,}Return\s{3,}mod4\s{3,}spawn\('xterm'\)\s*$",
138                     table)
139    assert re.search(r"(?m)^<root>\s{3,}t\s{3,}mod4\s{3,}spawn\('xterm'\)\s{3,}dummy description\s*$",
140                     table)
141    assert re.search(r"(?m)^<root>\s{3,}q\s{3,}mod4\s{13,}Enter named mode\s*$",
142                     table)
143    assert re.search(r"(?m)^named\s{3,}q\s{13,}Enter <unnamed> mode\s*$",
144                     table)
145    assert re.search(r"(?m)^named\s{3,}b\s{9,}togroup\('b'\)\s*$",
146                     table)
147    assert re.search(r"(?m)^named>_\s{3,}a\s{9,}togroup\('a'\)\s*$",
148                     table)
149    assert re.search(r"(?m)^<root>\s{3,}y\s{9,}\s*$", table) is None
150