Completed
Pull Request — master (#107)
by Simon
02:23
created

DataObjectAnnotatorTest::tearDown()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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