Passed
Pull Request — master (#107)
by Simon
01:43
created

testShortAnnotateDataExtension()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 14
nc 1
nop 0
dl 0
loc 19
rs 9.4285
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);
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 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