1import cairocffi
2import pytest
3
4from libqtile import images
5from libqtile.widget import battery
6from libqtile.widget.battery import (
7    Battery,
8    BatteryIcon,
9    BatteryState,
10    BatteryStatus,
11)
12from test.widgets.conftest import TEST_DIR
13
14
15class DummyBattery:
16    def __init__(self, status):
17        self._status = status
18
19    def update_status(self):
20        return self._status
21
22
23class DummyErrorBattery:
24    def __init__(self, **config):
25        pass
26
27    def update_status(self):
28        raise RuntimeError("err")
29
30
31def dummy_load_battery(bat):
32    def load_battery(**config):
33        return DummyBattery(bat)
34
35    return load_battery
36
37
38def test_text_battery_charging(monkeypatch):
39    loaded_bat = BatteryStatus(
40        state=BatteryState.CHARGING,
41        percent=0.5,
42        power=15.,
43        time=1729,
44    )
45
46    with monkeypatch.context() as manager:
47        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
48        batt = Battery()
49
50    text = batt.poll()
51    assert text == "^ 50% 0:28 15.00 W"
52
53
54def test_text_battery_discharging(monkeypatch):
55    loaded_bat = BatteryStatus(
56        state=BatteryState.DISCHARGING,
57        percent=0.5,
58        power=15.,
59        time=1729,
60    )
61
62    with monkeypatch.context() as manager:
63        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
64        batt = Battery()
65
66    text = batt.poll()
67    assert text == "V 50% 0:28 15.00 W"
68
69
70def test_text_battery_full(monkeypatch):
71    loaded_bat = BatteryStatus(
72        state=BatteryState.FULL,
73        percent=0.5,
74        power=15.,
75        time=1729,
76    )
77
78    with monkeypatch.context() as manager:
79        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
80        batt = Battery()
81
82    text = batt.poll()
83    assert text == "Full"
84
85    with monkeypatch.context() as manager:
86        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
87        batt = Battery(show_short_text=False)
88
89    text = batt.poll()
90    assert text == "= 50% 0:28 15.00 W"
91
92
93def test_text_battery_empty(monkeypatch):
94    loaded_bat = BatteryStatus(
95        state=BatteryState.EMPTY,
96        percent=0.5,
97        power=15.,
98        time=1729,
99    )
100
101    with monkeypatch.context() as manager:
102        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
103        batt = Battery()
104
105    text = batt.poll()
106    assert text == "Empty"
107
108    with monkeypatch.context() as manager:
109        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
110        batt = Battery(show_short_text=False)
111
112    text = batt.poll()
113    assert text == "x 50% 0:28 15.00 W"
114
115    loaded_bat = BatteryStatus(
116        state=BatteryState.UNKNOWN,
117        percent=0.,
118        power=15.,
119        time=1729,
120    )
121
122    with monkeypatch.context() as manager:
123        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
124        batt = Battery()
125
126    text = batt.poll()
127    assert text == "Empty"
128
129
130def test_text_battery_unknown(monkeypatch):
131    loaded_bat = BatteryStatus(
132        state=BatteryState.UNKNOWN,
133        percent=0.5,
134        power=15.,
135        time=1729,
136    )
137
138    with monkeypatch.context() as manager:
139        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
140        batt = Battery()
141
142    text = batt.poll()
143    assert text == "? 50% 0:28 15.00 W"
144
145
146def test_text_battery_hidden(monkeypatch):
147    loaded_bat = BatteryStatus(
148        state=BatteryState.DISCHARGING,
149        percent=0.5,
150        power=15.,
151        time=1729,
152    )
153
154    with monkeypatch.context() as manager:
155        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
156        batt = Battery(hide_threshold=0.6)
157
158    text = batt.poll()
159    assert text != ""
160
161    with monkeypatch.context() as manager:
162        manager.setattr(battery, "load_battery", dummy_load_battery(loaded_bat))
163        batt = Battery(hide_threshold=0.4)
164
165    text = batt.poll()
166    assert text == ""
167
168
169def test_text_battery_error(monkeypatch):
170    with monkeypatch.context() as manager:
171        manager.setattr(battery, "load_battery", DummyErrorBattery)
172        batt = Battery()
173
174    text = batt.poll()
175    assert text == "Error: err"
176
177
178def test_images_fail():
179    """Test BatteryIcon() with a bad theme_path
180
181    This theme path doesn't contain all of the required images.
182    """
183    batt = BatteryIcon(theme_path=TEST_DIR)
184    with pytest.raises(images.LoadingError):
185        batt.setup_images()
186
187
188def test_images_good(tmpdir, fake_bar, svg_img_as_pypath):
189    """Test BatteryIcon() with a good theme_path
190
191    This theme path does contain all of the required images.
192    """
193    for name in BatteryIcon.icon_names:
194        target = tmpdir.join(name + '.svg')
195        svg_img_as_pypath.copy(target)
196
197    batt = BatteryIcon(theme_path=str(tmpdir))
198    batt.fontsize = 12
199    batt.bar = fake_bar
200    batt.setup_images()
201    assert len(batt.surfaces) == len(BatteryIcon.icon_names)
202    for name, surfpat in batt.surfaces.items():
203        assert isinstance(surfpat, cairocffi.SurfacePattern)
204
205
206def test_images_default(fake_bar):
207    """Test BatteryIcon() with the default theme_path
208
209    Ensure that the default images are successfully loaded.
210    """
211    batt = BatteryIcon()
212    batt.fontsize = 12
213    batt.bar = fake_bar
214    batt.setup_images()
215    assert len(batt.surfaces) == len(BatteryIcon.icon_names)
216    for name, surfpat in batt.surfaces.items():
217        assert isinstance(surfpat, cairocffi.SurfacePattern)
218