Completed
Pull Request — master (#107)
by Simon
01:44
created

testShortInversePlayerRelationOfTeam()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 14
nc 1
nop 0
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
1
<?php
2
3
namespace SilverLeague\IDEAnnotator\Tests;
4
5
use PageController;
6
use PHPUnit_Framework_TestCase;
7
use RootTeam;
8
use SilverLeague\IDEAnnotator\Annotatable;
9
use SilverLeague\IDEAnnotator\AnnotateClassInfo;
10
use SilverLeague\IDEAnnotator\AnnotatePermissionChecker;
11
use SilverLeague\IDEAnnotator\DataObjectAnnotator;
12
use SilverStripe\Control\Director;
13
use SilverStripe\Core\Config\Config;
14
use SilverStripe\Core\Injector\Injector;
15
use SilverStripe\Dev\SapphireTest;
16
use SilverStripe\ORM\DataObject;
17
18
/**
19
 * Class DataObjectAnnotatorTest
20
 *
21
 * Several tests to make sure the Annotator does it's job correctly
22
 *
23
 * @mixin PHPUnit_Framework_TestCase
24
 */
25
class DataObjectAnnotatorTest extends SapphireTest
26
{
27
28
    /**
29
     * @var MockDataObjectAnnotator
30
     */
31
    private $annotator;
32
33
    /**
34
     * @var AnnotatePermissionChecker $permissionChecker
35
     */
36
    private $permissionChecker;
37
38
    /**
39
     * Setup Defaults
40
     */
41
    protected function setUp()
42
    {
43
        parent::setUp();
44
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', false);
45
46
        Config::modify()->set(DataObjectAnnotator::class, 'enabled', true);
47
        Config::modify()->set(DataObjectAnnotator::class, 'enabled_modules', ['silverleague/ideannotator']);
48
49
        $this->annotator = Injector::inst()->get(MockDataObjectAnnotator::class);
50
        $this->permissionChecker = Injector::inst()->get(AnnotatePermissionChecker::class);
51
    }
52
53
    public function testIsEnabled()
54
    {
55
        $this->assertTrue(DataObjectAnnotator::isEnabled());
56
    }
57
58
    /**
59
     * Test the expected classes show up in the Classes for Module
60
     */
61
    public function testGetClassesForModule()
62
    {
63
        $expectedClasses = [
64
            Team::class                             => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_Team.php',
65
            TeamChanged::class                      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_TeamChanged.php',
66
            TeamComment::class                      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_TeamComment.php',
67
            DocBlockMockWithDocBlock::class         => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DocBlockMockWithDocBlock.php',
68
            OtherDocBlockMockWithDocBlock::class    => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DocBlockMockWithDocBlock.php',
69
            DoubleDataObjectInOneFile1::class       => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DoubleDataObjectInOneFile.php',
70
            DoubleDataObjectInOneFile2::class       => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DoubleDataObjectInOneFile.php',
71
            SubTeam::class                          => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_SubTeam.php',
72
            Player::class                           => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_Player.php',
73
            Team_Extension::class                   => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_Team_Extension.php',
74
            Annotatable::class                      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Extensions' . DIRECTORY_SEPARATOR . 'Annotatable.php',
75
            AnnotatorPageTest_Extension::class      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'AnnotatorPageTest.php',
76
            RootTeam::class                         => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'RootTeam.php',
77
            AnnotatorPageTest::class                => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'AnnotatorPageTest.php',
78
            AnnotatorPageTestController::class      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'AnnotatorPageTest.php',
79
            TeamSupporter::class                    => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_TeamSupporter.php',
80
        ];
81
        $classes = $this->annotator->getClassesForModule('silverleague/ideannotator');
82
        // Sort the array, so we don't get accidental errors due to manual ordering
83
        ksort($expectedClasses);
84
        ksort($classes);
85
        $this->assertEquals($expectedClasses, $classes);
86
    }
87
88
89
    /**
90
     * As below, as we don't want to actively change the mocks, so enable mysite
91
     */
92
    public function testAnnotateObject()
93
    {
94
        $this->assertFalse($this->annotator->annotateObject(DataObject::class));
95
96
        Config::modify()->set(DataObjectAnnotator::class, 'enabled_modules', ['ideannotator', 'mysite']);
97
        $this->assertTrue($this->annotator->annotateObject(PageController::class));
98
    }
99
100
    /**
101
     * Not testing existing modules, as it wil actively alter the mock files, so enable mysite
102
     */
103
    public function testAnnotateModule()
104
    {
105
        $noModule = $this->annotator->annotateModule('');
106
        $this->assertFalse($noModule);
107
        $noModule = $this->annotator->annotateModule('mysite');
108
        $this->assertFalse($noModule);
109
        // Enable 'mysite' for testing
110
        Config::modify()->set(DataObjectAnnotator::class, 'enabled_modules', ['ideannotator', 'mysite']);
111
112
        $module = $this->annotator->annotateModule('mysite');
113
        $this->assertTrue($module);
114
    }
115
116
    /**
117
     * Test if the correct annotations are generated
118
     * for all database fields, relations and extensions
119
     * and that the start and end tags are present
120
     */
121
    public function testFileContentWithAnnotations()
122
    {
123
        $classInfo = new AnnotateClassInfo(Team::class);
124
        $filePath = $classInfo->getClassFilePath();
125
126
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
127
128
        // ClassName title
129
        $this->assertContains(' * Class \SilverLeague\IDEAnnotator\Tests\Team', $content);
130
131
        // database fields
132
        $this->assertContains('@property string $Title', $content);
133
        $this->assertContains('@property int $VisitCount', $content);
134
        $this->assertContains('@property float $Price', $content);
135
        $this->assertContains('@property string $Dude', $content);
136
        $this->assertContains('@property string $Dudette', $content);
137
138
        // has_one ID
139
        $this->assertContains('@property int $CaptainID', $content);
140
        // has_one relation
141
        $this->assertContains('@method \SilverLeague\IDEAnnotator\Tests\Player Captain()', $content);
142
        // has_many relation
143
        $this->assertContains(
144
            '@method \SilverStripe\ORM\DataList|\SilverLeague\IDEAnnotator\Tests\SubTeam[] SubTeams()',
145
            $content
146
        );
147
        // many_many relation
148
        $this->assertContains(
149
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Player[] Players()',
150
            $content
151
        );
152
        $this->assertContains(
153
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Player[] Reserves()',
154
            $content
155
        );
156
        $this->assertContains(
157
            '@method \SilverStripe\ORM\DataList|\SilverLeague\IDEAnnotator\Tests\TeamSupporter[] Supporters()',
158
            $content
159
        );
160
161
        // DataExtension
162
        $this->assertContains('@mixin \SilverLeague\IDEAnnotator\Tests\Team_Extension', $content);
163
    }
164
165
    /**
166
     * Test if the correct annotations are generated
167
     * for all database fields, relations and extensions
168
     * and that the start and end tags are present
169
     */
170
    public function testShortFileContentWithAnnotations()
171
    {
172
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
173
174
        $classInfo = new AnnotateClassInfo(Team::class);
175
        $filePath = $classInfo->getClassFilePath();
176
177
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
178
179
        // database fields
180
        $this->assertContains('@property string $Title', $content);
181
        $this->assertContains('@property int $VisitCount', $content);
182
        $this->assertContains('@property float $Price', $content);
183
184
        // has_one ID
185
        $this->assertContains('@property int $CaptainID', $content);
186
        // has_one relation
187
        $this->assertContains('@method Player Captain()', $content);
188
        // has_many relation
189
        $this->assertContains(
190
            '@method DataList|SubTeam[] SubTeams()',
191
            $content
192
        );
193
        // many_many relation
194
        $this->assertContains(
195
            '@method ManyManyList|Player[] Players()',
196
            $content
197
        );
198
        $this->assertContains(
199
            '@method ManyManyList|Player[] Reserves()',
200
            $content
201
        );
202
        $this->assertContains(
203
            '@method DataList|TeamSupporter[] Supporters()',
204
            $content
205
        );
206
207
        // DataExtension
208
        $this->assertContains('@mixin Team_Extension', $content);
209
    }
210
211
    
212
    public function testInversePlayerRelationOfTeam()
213
    {
214
        $classInfo = new AnnotateClassInfo(Player::class);
215
        $filePath = $classInfo->getClassFilePath();
216
217
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Player::class);
218
219
        $this->assertContains('@property boolean $IsRetired', $content);
220
        $this->assertContains('@property string $ShirtNumber', $content);
221
        $this->assertContains('@property string $Shirt', $content);
222
        $this->assertContains('@property int $FavouriteTeamID', $content);
223
        $this->assertContains('@method \SilverLeague\IDEAnnotator\Tests\Team FavouriteTeam()', $content);
224
225
        $this->assertContains(
226
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Team[] TeamPlayer()',
227
            $content
228
        );
229
        $this->assertContains(
230
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Team[] TeamReserve()',
231
            $content
232
        );
233
    }
234
235
    public function testDefaults()
236
    {
237
        $count = 0;
238
        DataObjectAnnotator::pushExtensionClass(Page::class);
239
        foreach (DataObjectAnnotator::getExtensionClasses() as $class) {
240
            if ($class === 'Page') {
241
                $count++;
242
            }
243
        }
244
        $this->assertEquals(0, $count);
245
    }
246
    
247
    public function testShortInversePlayerRelationOfTeam()
248
    {
249
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
250
251
        $classInfo = new AnnotateClassInfo(Player::class);
252
        $filePath = $classInfo->getClassFilePath();
253
254
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Player::class);
255
256
        $this->assertContains('@property boolean $IsRetired', $content);
257
        $this->assertContains('@property string $ShirtNumber', $content);
258
        $this->assertContains('@property int $FavouriteTeamID', $content);
259
        $this->assertContains('@method Team FavouriteTeam()', $content);
260
261
        $this->assertContains(
262
            '@method ManyManyList|Team[] TeamPlayer()',
263
            $content
264
        );
265
        $this->assertContains(
266
            '@method ManyManyList|Team[] TeamReserve()',
267
            $content
268
        );
269
    }
270
271
    public function testExistingMethodsWillNotBeTagged()
272
    {
273
        $classInfo = new AnnotateClassInfo(Team::class);
274
        $filePath = $classInfo->getClassFilePath();
275
276
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
277
        $this->assertNotContains(
278
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\SubTeam[] SecondarySubTeams()',
279
            $content
280
        );
281
    }
282
283
    public function testShortExistingMethodsWillNotBeTagged()
284
    {
285
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
286
287
        $classInfo = new AnnotateClassInfo(Team::class);
288
        $filePath = $classInfo->getClassFilePath();
289
290
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
291
        $this->assertNotContains(
292
            '@method ManyManyList|SubTeam[] SecondarySubTeams()',
293
            $content
294
        );
295
    }
296
297
    /**
298
     * Test that multiple annotation runs won't generate ducplicate docblocks
299
     */
300
    public function testNothingHasChangedAfterSecondAnnotation()
301
    {
302
        $classInfo = new AnnotateClassInfo(Team::class);
303
        $filePath = $classInfo->getClassFilePath();
304
        $original = file_get_contents($filePath);
305
        $firstRun = $this->annotator->getGeneratedFileContent($original, Team::class);
306
        $secondRun = $this->annotator->getGeneratedFileContent($firstRun, Team::class);
307
        $this->assertEquals($firstRun, $secondRun);
308
    }
309
310
    /**
311
     * Test that root (non-namespaced) classes get annotated
312
     */
313
    public function testRootAnnotations()
314
    {
315
        $classInfo = new AnnotateClassInfo(RootTeam::class);
316
        $filePath = $classInfo->getClassFilePath();
317
        $run = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), RootTeam::class);
318
        $this->assertContains('@property string $Title', $run);
319
    }
320
321
    /**
322
     * Test the generation of annotations for a DataExtension
323
     */
324
    public function testAnnotateDataExtension()
325
    {
326
        $classInfo = new AnnotateClassInfo(Team_Extension::class);
327
        $filePath = $classInfo->getClassFilePath();
328
        $original = file_get_contents($filePath);
329
        $annotated = $this->annotator->getGeneratedFileContent($original, Team_Extension::class);
330
331
        $this->assertContains(
332
            '@property \SilverLeague\IDEAnnotator\Tests\Team|\SilverLeague\IDEAnnotator\Tests\Team_Extension $owner',
333
            $annotated
334
        );
335
        $this->assertContains('@property string $ExtendedVarcharField', $annotated);
336
        $this->assertContains('@property int $ExtendedIntField', $annotated);
337
        $this->assertContains('@property int $ExtendedHasOneRelationshipID', $annotated);
338
        $this->assertContains(
339
            '@method \SilverLeague\IDEAnnotator\Tests\Player ExtendedHasOneRelationship()',
340
            $annotated
341
        );
342
    }
343
344
    /**
345
     * Test the generation of annotations for a DataExtension
346
     */
347
    public function testShortAnnotateDataExtension()
348
    {
349
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
350
351
        $classInfo = new AnnotateClassInfo(Team_Extension::class);
352
        $filePath = $classInfo->getClassFilePath();
353
        $original = file_get_contents($filePath);
354
        $annotated = $this->annotator->getGeneratedFileContent($original, Team_Extension::class);
355
356
        $this->assertContains(
357
            '@property Team|Team_Extension $owner',
358
            $annotated
359
        );
360
        $this->assertContains('@property string $ExtendedVarcharField', $annotated);
361
        $this->assertContains('@property int $ExtendedIntField', $annotated);
362
        $this->assertContains('@property int $ExtendedHasOneRelationshipID', $annotated);
363
        $this->assertContains(
364
            '@method Player ExtendedHasOneRelationship()',
365
            $annotated
366
        );
367
    }
368
369
    /**
370
     *
371
     */
372
    public function testTwoClassesInOneFile()
373
    {
374
        $classInfo = new AnnotateClassInfo(DoubleDataObjectInOneFile1::class);
375
        $filePath = $classInfo->getClassFilePath();
376
        $original = file_get_contents($filePath);
377
        $annotated = $this->annotator->getGeneratedFileContent($original, DoubleDataObjectInOneFile1::class);
378
379
        $this->assertContains('@property string $Title', $annotated);
380
381
        $annotated = $this->annotator->getGeneratedFileContent($annotated, DoubleDataObjectInOneFile2::class);
382
383
        $this->assertContains('@property string $Name', $annotated);
384
    }
385
386
    public function tearDown()
387
    {
388
        parent::tearDown();
389
    }
390
}
391