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

testShortFileContentWithAnnotations()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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