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