Test Failed
Push — main ( 99efcd...df6632 )
by Alex
14:53
created

ConnectorTest::testConnectLocations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 46
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 26
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 46
rs 9.504
1
<?php
2
3
use PHPUnit\Framework\TestCase;
4
use App\Adventure\Utils\Connector;
5
use App\Adventure\Location;
6
7
/**
8
 * Unit tests for Connector class.
9
 */
10
class ConnectorTest extends TestCase
11
{
12
    /**
13
     * Test case for connectLocations method.
14
     */
15
    public function testConnectLocations(): void
16
    {
17
        // Create two real instances of the Location class
18
        $firstLocation = new Location('', '', '');
19
        $secondLocation = new Location('', '', '');
20
21
        // Create two partial mock instances of the Location class
22
        // to mock only the connectTo method
23
        $firstLocationMock = $this->getMockBuilder(Location::class)
24
            ->disableOriginalConstructor() // Do not invoke the constructor
25
            ->onlyMethods(['connectTo'])
26
            ->getMock();
27
28
        $secondLocationMock = $this->getMockBuilder(Location::class)
29
            ->disableOriginalConstructor() // Do not invoke the constructor
30
            ->onlyMethods(['connectTo'])
31
            ->getMock();
32
33
        // Manually invoke the connectTo method to make sure the logic is excecuted as expected,
34
        // whilest also making sure that the real instances are connected
35
        // (this allows us to test the outcome using the hasConnection method for example)
36
        $firstLocationMock->expects($this->once())
37
            ->method('connectTo')
38
            ->willReturnCallback(
39
                function ($location, $direction) use ($firstLocation) {
40
                    $firstLocation->connectTo($location, $direction);
41
                }
42
            );
43
44
        $secondLocationMock->expects($this->once())
45
            ->method('connectTo')
46
            ->willReturnCallback(
47
                function ($location, $direction) use ($secondLocation) {
48
                    $secondLocation->connectTo($location, $direction);
49
                }
50
            );
51
52
        // Connect the locations in both directions
53
        $resultLocation = Connector::connectLocations($firstLocationMock, $secondLocationMock, 'north');
54
55
        // Assertions
56
        $this->assertSame($firstLocationMock, $resultLocation);
57
        $this->assertTrue($firstLocation->hasConnection('north'));
58
        $this->assertSame($secondLocationMock, $firstLocation->getConnectedLocation('north'));
59
        $this->assertTrue($secondLocation->hasConnection('south'));
60
        $this->assertSame($firstLocationMock, $secondLocation->getConnectedLocation('south'));
61
    }
62
63
    /**
64
     * Test case for connectLocations method with already connected direction.
65
     */
66
    public function testConnectLocationsThrowsException(): void
67
    {
68
        // Create two mock instances of the Location class
69
        $firstLocation = $this->createMock(Location::class);
70
        $secondLocation = $this->createMock(Location::class);
71
72
        $firstLocation->expects($this->once())
73
            ->method('hasConnection')
74
            ->willReturn(true); // This effectively says that the locations are already connected
75
76
        // Try connecting the locations (direction does not matter)
77
        $this->expectException(Exception::class);
78
        $this->expectExceptionMessage("The direction 'north' is already connected to another location.");
79
        Connector::connectLocations($firstLocation, $secondLocation, 'north');
80
    }
81
82
    /**
83
     * Test case for swapLocations method.
84
     */
85
    public function testSwapLocations(): void
86
    {
87
        // Create mock instances of the Location class
88
        $oldLocation = $this->createMock(Location::class);
89
        $newLocation = $this->createMock(Location::class);
90
91
        // Create additional mock instances of the Location class for connections
92
        $connection1 = $this->createMock(Location::class);
93
        $connection2 = $this->createMock(Location::class);
94
        $connection3 = $this->createMock(Location::class);
95
96
        // Set up the connections for the old location
97
        $oldLocation->expects($this->once())
98
            ->method('getConnectedLocations')
99
            ->willReturn([
100
                'north' => $connection1,
101
                'west' => $connection2,
102
                'east' => $connection3
103
            ]);
104
105
        // Set up the disconnectFrom method for the connections
106
        $connection1->expects($this->once())
107
            ->method('disconnectFrom');
108
        $connection2->expects($this->once())
109
            ->method('disconnectFrom');
110
        $connection3->expects($this->once())
111
            ->method('disconnectFrom');
112
113
        // Set up the connectLocations method for the new location
114
        $newLocation->expects($this->exactly(3))
115
            ->method('connectTo');
116
117
        // Perform the swap locations action
118
        $resultLocation = Connector::swapLocations($oldLocation, $newLocation);
119
120
        // Assertions
121
        $this->assertSame($newLocation, $resultLocation);
122
    }
123
}
124