Completed
Pull Request — master (#107)
by Simon
01:41
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\DataObjectAnnotator;
9
use SilverLeague\IDEAnnotator\Extensions\Annotatable;
10
use SilverLeague\IDEAnnotator\Helpers\AnnotateClassInfo;
11
use SilverLeague\IDEAnnotator\Helpers\AnnotatePermissionChecker;
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);
0 ignored issues
show
Bug introduced by
The type SilverLeague\IDEAnnotator\Tests\Page was not found. Did you mean Page? If so, make sure to prefix the type with \.
Loading history...
241
        foreach (DataObjectAnnotator::getExtensionClasses() as $class) {
242
            if ($class === 'Page') {
243
                $count++;
244
            }
245
        }
246
        $this->assertEquals(0, $count);
247
    }
248
249
    public function testSetExtensionClasses()
250
    {
251
        $classes = DataObjectAnnotator::getExtensionClasses();
252
        unset($classes[20]);
253
        $expected = [
254
            'SilverLeague\IDEAnnotator\Tests\AnnotatorPageTestController',
255
            'SilverLeague\IDEAnnotator\Tests\Team',
256
            'SilverStripe\Admin\ModalController',
257
            'SilverStripe\AssetAdmin\Forms\FileFormFactory',
258
            'SilverStripe\CMS\Controllers\ContentController',
259
            'SilverStripe\CMS\Controllers\ModelAsController',
260
            'SilverStripe\Control\Controller',
261
            'SilverStripe\Dev\DevBuildController',
262
            'SilverStripe\Forms\Form',
263
            'SilverStripe\Security\Group',
264
            'SilverStripe\Forms\GridField\GridFieldConfig_Base',
265
            'SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor',
266
            'SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor',
267
            'SilverStripe\Forms\GridField\GridFieldDetailForm',
268
            'SilverStripe\Forms\GridField\GridFieldPrintButton',
269
            'SilverStripe\ORM\FieldType\DBField',
270
            'SilverStripe\GraphQL\Scaffolding\Scaffolders\DataObjectScaffolder',
271
            'SilverStripe\GraphQL\Scaffolding\Scaffolders\SchemaScaffolder',
272
            'SilverStripe\GraphQL\Scaffolding\Scaffolders\CRUD\Read',
273
            'SilverStripe\GraphQL\Scaffolding\Scaffolders\CRUD\ReadOne',
274
        ];
275
        DataObjectAnnotator::setExtensionClasses($classes);
276
277
        $this->assertEquals($expected, DataObjectAnnotator::getExtensionClasses());
278
    }
279
280
    public function testShortInversePlayerRelationOfTeam()
281
    {
282
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
283
284
        $classInfo = new AnnotateClassInfo(Player::class);
285
        $filePath = $classInfo->getClassFilePath();
286
287
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Player::class);
288
289
        $this->assertContains('@property boolean $IsRetired', $content);
290
        $this->assertContains('@property string $ShirtNumber', $content);
291
        $this->assertContains('@property int $FavouriteTeamID', $content);
292
        $this->assertContains('@method Team FavouriteTeam()', $content);
293
294
        $this->assertContains(
295
            '@method ManyManyList|Team[] TeamPlayer()',
296
            $content
297
        );
298
        $this->assertContains(
299
            '@method ManyManyList|Team[] TeamReserve()',
300
            $content
301
        );
302
    }
303
304
    public function testExistingMethodsWillNotBeTagged()
305
    {
306
        $classInfo = new AnnotateClassInfo(Team::class);
307
        $filePath = $classInfo->getClassFilePath();
308
309
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
310
        $this->assertNotContains(
311
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\SubTeam[] SecondarySubTeams()',
312
            $content
313
        );
314
    }
315
316
    public function testShortExistingMethodsWillNotBeTagged()
317
    {
318
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
319
320
        $classInfo = new AnnotateClassInfo(Team::class);
321
        $filePath = $classInfo->getClassFilePath();
322
323
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
324
        $this->assertNotContains(
325
            '@method ManyManyList|SubTeam[] SecondarySubTeams()',
326
            $content
327
        );
328
    }
329
330
    /**
331
     * Test that multiple annotation runs won't generate ducplicate docblocks
332
     */
333
    public function testNothingHasChangedAfterSecondAnnotation()
334
    {
335
        $classInfo = new AnnotateClassInfo(Team::class);
336
        $filePath = $classInfo->getClassFilePath();
337
        $original = file_get_contents($filePath);
338
        $firstRun = $this->annotator->getGeneratedFileContent($original, Team::class);
339
        $secondRun = $this->annotator->getGeneratedFileContent($firstRun, Team::class);
340
        $this->assertEquals($firstRun, $secondRun);
341
    }
342
343
    /**
344
     * Test that root (non-namespaced) classes get annotated
345
     */
346
    public function testRootAnnotations()
347
    {
348
        $classInfo = new AnnotateClassInfo(RootTeam::class);
349
        $filePath = $classInfo->getClassFilePath();
350
        $run = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), RootTeam::class);
351
        $this->assertContains('@property string $Title', $run);
352
    }
353
354
    /**
355
     * Test the generation of annotations for a DataExtension
356
     */
357
    public function testAnnotateDataExtension()
358
    {
359
        $classInfo = new AnnotateClassInfo(Team_Extension::class);
360
        $filePath = $classInfo->getClassFilePath();
361
        $original = file_get_contents($filePath);
362
        $annotated = $this->annotator->getGeneratedFileContent($original, Team_Extension::class);
363
364
        $this->assertContains(
365
            '@property \SilverLeague\IDEAnnotator\Tests\Team|\SilverLeague\IDEAnnotator\Tests\Team_Extension $owner',
366
            $annotated
367
        );
368
        $this->assertContains('@property string $ExtendedVarcharField', $annotated);
369
        $this->assertContains('@property int $ExtendedIntField', $annotated);
370
        $this->assertContains('@property int $ExtendedHasOneRelationshipID', $annotated);
371
        $this->assertContains(
372
            '@method \SilverLeague\IDEAnnotator\Tests\Player ExtendedHasOneRelationship()',
373
            $annotated
374
        );
375
    }
376
377
    /**
378
     * Test the generation of annotations for a DataExtension
379
     */
380
    public function testShortAnnotateDataExtension()
381
    {
382
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
383
384
        $classInfo = new AnnotateClassInfo(Team_Extension::class);
385
        $filePath = $classInfo->getClassFilePath();
386
        $original = file_get_contents($filePath);
387
        $annotated = $this->annotator->getGeneratedFileContent($original, Team_Extension::class);
388
389
        $this->assertContains(
390
            '@property Team|Team_Extension $owner',
391
            $annotated
392
        );
393
        $this->assertContains('@property string $ExtendedVarcharField', $annotated);
394
        $this->assertContains('@property int $ExtendedIntField', $annotated);
395
        $this->assertContains('@property int $ExtendedHasOneRelationshipID', $annotated);
396
        $this->assertContains(
397
            '@method Player ExtendedHasOneRelationship()',
398
            $annotated
399
        );
400
    }
401
402
    /**
403
     *
404
     */
405
    public function testTwoClassesInOneFile()
406
    {
407
        $classInfo = new AnnotateClassInfo(DoubleDataObjectInOneFile1::class);
408
        $filePath = $classInfo->getClassFilePath();
409
        $original = file_get_contents($filePath);
410
        $annotated = $this->annotator->getGeneratedFileContent($original, DoubleDataObjectInOneFile1::class);
411
412
        $this->assertContains('@property string $Title', $annotated);
413
414
        $annotated = $this->annotator->getGeneratedFileContent($annotated, DoubleDataObjectInOneFile2::class);
415
416
        $this->assertContains('@property string $Name', $annotated);
417
    }
418
419
    public function tearDown()
420
    {
421
        parent::tearDown();
422
    }
423
}
424