File: test_ui.py

package info (click to toggle)
lightyears 1.5.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 25,804 kB
  • sloc: python: 5,532; sh: 39; makefile: 6
file content (228 lines) | stat: -rw-r--r-- 9,032 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#
# 20,000 Light Years Into Space
# This game is licensed under GPL v2, and copyright (C) Jack Whitham 2006-21.
#

import pygame
from lib20k import game_random, map_items, network, grid, quiet_season
from lib20k.ui import User_Interface
from lib20k.primitives import *
from lib20k.game_types import *
from .unit_test import *


def test_UI() -> None:
    """Unit tests for the ui.py module.

    This is the game's user interface: the screen shows the map, the user can click
    things. These unit tests carry out various test scenarios by interacting with
    the ui using Game_Mouse_Down and others. There is some overlap with the unit
    tests of network.py which also involve creating/removing nodes and pipes; the
    difference is the API used to drive the tests, which is provided by ui.py in this
    case."""

    # create test scenario
    test_screen = Setup_For_Unit_Test()
    demo = game_random.Game_Random(1)
    net = network.Network(demo, False)
    ui = User_Interface(net, demo)
    controls_surf = pygame.Surface((200, 200))

    season_fx = quiet_season.Quiet_Season(net)

    def Draw_Things(shaking: bool) -> None:
        class Test_Season(quiet_season.Quiet_Season):
            def Is_Shaking(self) -> bool:
                return shaking

        ui.Update_Area(None)
        ui.Draw_Game(test_screen, Test_Season(net), False)
        ui.Draw_Stats(test_screen, [])
        pygame.display.flip()

    Draw_Things(False)

    # Initially the control_menu field is None, so all of these
    # input events are not routed to the control menu
    ui.Game_Mouse_Move((10, 10))
    ui.Key_Press(pygame.K_1)
    ui.Control_Mouse_Move((10, 10))
    ui.Control_Mouse_Down((10, 10))
    ui.Reset()
    Draw_Things(False)

    # Now we create the control menu by drawing it for the first time
    ui.Draw_Controls(controls_surf)

    # Now the control menu can receive events
    ui.Game_Mouse_Move((10, 10))
    ui.Key_Press(pygame.K_1)
    ui.Control_Mouse_Move((10, 10))
    ui.Control_Mouse_Down((10, 10))
    ui.Reset()
    Draw_Things(False)

    # Let us make some nodes
    # Here is a map showing where the nodes are placed (not to scale):
    #
    #    n1      n2
    #
    #    n4      n3
    #
    #    n5
    n1pos = (100, 100)
    n2pos = (200, 100)
    n3pos = (200, 200)
    n4pos = (100, 200)
    n5pos = (100, 300)
    p12pos = (150, 100)
    missed = (250, 250)

    # Build two nodes and a pipe; draw the pipe while we build it.
    # Pipe is made by implicitly starting at the most recent node.
    ui.Key_Press(pygame.K_n)        # build node (n1pos)
    ui.Game_Mouse_Move(n1pos)
    Draw_Things(False)
    ui.Game_Mouse_Down(n1pos)
    ui.Key_Press(pygame.K_n)        # build node (n2pos)
    ui.Game_Mouse_Down(n2pos)
    ui.Key_Press(pygame.K_p)        # build pipe from 2 to 1
    ui.Game_Mouse_Move(n1pos)
    Draw_Things(False)              # draw pipe under construction

    # Build another node and another pipe; this time we make the pipe
    # by explicitly clicking the start and finish nodes
    ui.Game_Mouse_Down(n1pos)
    ui.Key_Press(pygame.K_n)        # build node (n3pos)
    ui.Game_Mouse_Down(n3pos)
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Key_Press(pygame.K_p)
    ui.Game_Mouse_Down(n3pos)       # create pipe from 3 to 1
    ui.Game_Mouse_Down(n1pos)       # create pipe from 3 to 1

    # Try to build a node in a place where we can't (pipe in the way)
    ui.Key_Press(pygame.K_n)        # build node (p12pos)
    ui.Game_Mouse_Down(p12pos)
    assert ui.selection is None     # check it didn't work

    # Select various things - nothing, a pipe, a pipe that's already selected
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Game_Mouse_Move(missed)
    Draw_Things(False)              # draw with nothing selected
    ui.Game_Mouse_Down(p12pos)      # click on pipe from 2 to 1 (select it)
    ui.Game_Mouse_Down(p12pos)      # click again (already selected)

    # Test upgrade pipe, destroying nothing, and destroying a pipe
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Key_Press(pygame.K_u)
    ui.Game_Mouse_Down(p12pos)      # upgrade pipe from 2 to 1
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Key_Press(pygame.K_d)
    ui.Game_Mouse_Down(p12pos)      # destroy pipe from 2 to 1
    ui.Key_Press(pygame.K_d)
    ui.Game_Mouse_Down(missed)      # destroy nothing (missed!)

    # Test destroying a node, upgrading nothing, upgrading a node
    ui.Key_Press(pygame.K_d)
    ui.Game_Mouse_Down(n1pos)       # destroy node 1
    ui.Right_Mouse_Down()           # neutral mode
    ui.Game_Mouse_Down(n3pos)       # select node 3
    ui.Key_Press(pygame.K_u)
    ui.Game_Mouse_Down(missed)      # upgrade nothing (missed)
    ui.Key_Press(pygame.K_u)
    ui.Game_Mouse_Down(n2pos)       # upgrade node 2
    ui.Right_Mouse_Down()           # neutral mode
    ui.Game_Mouse_Down(n3pos)       # select node 3
    ui.Key_Press(pygame.K_u)        # upgrade node 3
    ui.Key_Press(pygame.K_d)        # destroy node 3
    Draw_Things(False)

    # Create a well. The user can't do this, so we reach into the grey box...
    # Test building a well node
    n4well = map_items.Well(grid.Scr_To_Grid(n4pos))
    net.Add_Grid_Item(n4well, True)
    assert net.ground_grid[grid.Scr_To_Grid(n4pos)] == n4well
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Key_Press(pygame.K_p)        # pipe mode
    ui.Game_Mouse_Down(n4pos)       # click on the well (nothing happens)
    ui.Key_Press(pygame.K_n)        # build node over the well
    ui.Game_Mouse_Down(n4pos)
    n4 = net.ground_grid[grid.Scr_To_Grid(n4pos)]
    assert n4 != n4well             # node replaces well
    assert n4 == ui.selection       # new node is selected

    # Test building more pipes
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Key_Press(pygame.K_p)        # try to build a pipe from a node to itself
    ui.Game_Mouse_Down(n2pos)
    ui.Game_Mouse_Down(n2pos)

    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Key_Press(pygame.K_p)        # build a pipe from 2 to 4
    ui.Game_Mouse_Down(n2pos)
    ui.Game_Mouse_Down(n4pos)

    # Recreate nodes destroyed earlier
    ui.Key_Press(pygame.K_n)        # build node (n1pos)
    ui.Game_Mouse_Down(n1pos)
    ui.Key_Press(pygame.K_n)        # build node (n3pos)
    ui.Game_Mouse_Down(n3pos)
    Draw_Things(False)

    # Now we can't build a pipe from 1 to 3 because it crosses the pipe from 2 to 4
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Key_Press(pygame.K_p)        # build a pipe from 1 to 3 (doesn't work)
    ui.Game_Mouse_Down(n1pos)
    ui.Game_Mouse_Down(n3pos)

    # Select node 4 and then destroy it without informing the ui; a bit like if
    # it were destroyed by the environment.
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Game_Mouse_Down(n4pos)
    assert n4 == ui.selection
    assert n4 is not None
    net.Destroy(n4)
    assert ui.selection == n4
    ui.Game_Mouse_Down(n4pos)       # select it again - outcome: nothing selected
    assert ui.selection is None
    assert net.ground_grid[grid.Scr_To_Grid(n4pos)] == n4well  # well has been restored

    # Test the control menu with mouse clicks
    centre_of: Dict[MenuCommand, SurfacePosition] = dict()
    assert ui.control_menu is not None
    for (cmd, rect) in ui.control_menu.control_rects:
        (x, y) = rect.center
        x += ui.control_menu.bbox.left
        y += ui.control_menu.bbox.top
        centre_of[cmd] = (x, y)

    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Control_Mouse_Down(centre_of[MenuCommand.UPGRADE]) # upgrade nothing
    ui.Right_Mouse_Down()           # neutral mode (deselect all)
    ui.Game_Mouse_Down(n3pos)       # select n3
    assert ui.selection is not None
    ui.Control_Mouse_Down(centre_of[MenuCommand.UPGRADE]) # upgrade n3
    ui.Game_Mouse_Down(n3pos)       # select n3
    ui.Control_Mouse_Down(centre_of[MenuCommand.BUILD_NODE]) # build nothing (n3 selected)
    ui.Control_Mouse_Down(centre_of[MenuCommand.DESTROY]) # destroy n3
    Draw_Things(False)

    # Select the city (testing Draw_Stats)
    ui.Game_Mouse_Down(grid.Grid_To_Scr(net.hub.pos))
    Draw_Things(False)

    # Earthquake!
    Draw_Things(True)

    # Build a pipe from node 1 to new node 5, then try to build over the well at 4.
    ui.Key_Press(pygame.K_n)        # build node (n5pos)
    ui.Game_Mouse_Down(n5pos)
    ui.Key_Press(pygame.K_p)        # create pipe from 5 to 1
    ui.Game_Mouse_Down(n1pos)
    assert ui.selection is None     # check pipe was created
    ui.Key_Press(pygame.K_n)        # try to create well node at 4 (pipe is in the way)
    ui.Game_Mouse_Down(n4pos)
    assert ui.selection is None     # check well node was not created
    assert net.ground_grid[grid.Scr_To_Grid(n4pos)] == n4well # well is still there
    Draw_Things(False)