ExcelImportExportTest::testTransaction()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 36
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 19
nc 4
nop 0
dl 0
loc 36
rs 9.6333
c 0
b 0
f 0
1
<?php
2
3
namespace LeKoala\ExcelImportExport\Test;
4
5
use Exception;
6
use LeKoala\ExcelImportExport\ExcelGridFieldExportButton;
7
use SilverStripe\Security\Group;
8
use SilverStripe\Security\Member;
9
use SilverStripe\Dev\SapphireTest;
10
use LeKoala\ExcelImportExport\ExcelImportExport;
11
use LeKoala\ExcelImportExport\ExcelMemberBulkLoader;
12
use LeKoala\ExcelImportExport\Test\Mocks\TestExcelMember;
13
14
/**
15
 * Tests for ExcelImportExport
16
 */
17
class ExcelImportExportTest extends SapphireTest
18
{
19
    /**
20
     * Defines the fixture file to use for this test class
21
     * @var string
22
     */
23
    protected static $fixture_file = 'ExcelImportExportTest.yml';
24
    protected static $extra_dataobjects = [
25
        TestExcelMember::class,
26
    ];
27
28
    public function testGetAllFields(): void
29
    {
30
        $fields = ExcelImportExport::allFieldsForClass(Member::class);
31
        $this->assertNotEmpty($fields);
32
    }
33
34
    public function testExportedFields(): void
35
    {
36
        $fields = ExcelImportExport::exportFieldsForClass(Member::class);
37
        $this->assertNotEmpty($fields);
38
        $this->assertNotContains('Password', $fields);
39
    }
40
41
    public function testCanImportMembers(): void
42
    {
43
        $count = Member::get()->count();
44
        $firstGroup = Group::get()->filter('Code', 'Administrators')->first();
45
        $membersCount = $firstGroup->Members()->count();
46
47
        // ; separator is properly detected thanks to auto separator feature
48
        $loader = new ExcelMemberBulkLoader();
49
        $result = $loader->load(__DIR__ . '/data/members.csv');
50
51
        $this->assertEquals(1, $result->CreatedCount());
52
53
        $newCount = Member::get()->count();
54
        $firstGroup = Group::get()->filter('Code', 'Administrators')->first();
55
        $newMembersCount = $firstGroup->Members()->count();
56
57
        $this->assertEquals($count + 1, $newCount);
58
        $this->assertEquals($membersCount + 1, $newMembersCount, "Groups are not updated");
59
60
        // format is handled according to file extension
61
        $loader = new ExcelMemberBulkLoader();
62
        $result = $loader->load(__DIR__ . '/data/members.xlsx');
63
64
        $this->assertEquals(1, $result->CreatedCount());
65
        $this->assertEquals(0, $result->UpdatedCount());
66
67
        $newCount = Member::get()->count();
68
        $firstGroup = Group::get()->filter('Code', 'Administrators')->first();
69
        $newMembersCount = $firstGroup->Members()->count();
70
71
        $this->assertEquals($count + 2, $newCount);
72
        $this->assertEquals($membersCount + 2, $newMembersCount, "Groups are not updated");
73
74
        // Loading again does nothing new
75
        $result = $loader->load(__DIR__ . '/data/members.xlsx');
76
77
        $this->assertEquals(0, $result->CreatedCount());
78
        $this->assertEquals(1, $result->UpdatedCount());
79
80
        $newCount = Member::get()->count();
81
        $firstGroup = Group::get()->filter('Code', 'Administrators')->first();
82
        $newMembersCount = $firstGroup->Members()->count();
83
84
        $this->assertEquals($count + 2, $newCount);
85
        $this->assertEquals($membersCount + 2, $newMembersCount, "Groups are not updated");
86
    }
87
88
    public function testSanitize(): void
89
    {
90
        $dangerousInput = '=1+2";=1+2';
91
92
        $actual = ExcelGridFieldExportButton::sanitizeValue($dangerousInput);
93
        $expected = "\t" . $dangerousInput;
94
        $this->assertEquals($expected, $actual);
95
    }
96
97
    public function testImportMultipleClasses(): void
98
    {
99
        $beforeCount = Member::get()->count();
100
101
        $loader = new ExcelMemberBulkLoader();
102
        $result = $loader->load(__DIR__ . '/data/members-class.csv');
103
104
        $totalCount = Member::get()->count();
105
        $this->assertEquals(2, $result->CreatedCount());
106
        $this->assertEquals($beforeCount, $totalCount - 2);
107
108
        // Is a subclass AND a base class
109
        $member = TestExcelMember::get()->filter('Email', '[email protected]')->first();
110
        $this->assertNotEmpty($member);
111
        $member = Member::get()->filter('Email', '[email protected]')->first();
112
        $this->assertNotEmpty($member);
113
114
        // Not a subclass
115
        $member = TestExcelMember::get()->filter('Email', '[email protected]')->first();
116
        $this->assertEmpty($member);
117
118
        // Checking duplicate still works even with custom class
119
        $loader = new ExcelMemberBulkLoader();
120
        $result = $loader->load(__DIR__ . '/data/members-class.csv');
121
122
        $this->assertEquals(0, $result->CreatedCount());
123
        $this->assertEquals(2, $result->UpdatedCount());
124
125
        $newTotalCount = Member::get()->count();
126
        $this->assertEquals($newTotalCount, $totalCount);
127
    }
128
129
    public function testImportMigrateClasses(): void
130
    {
131
        // For members, duplicate is done on emails
132
        $duplicateEmail = '[email protected]';
133
134
        $baseMember = new Member();
135
        $baseMember->Email = $duplicateEmail;
136
        $baseMember->write();
137
138
        $loader = new ExcelMemberBulkLoader();
139
        $result = $loader->processData([
140
            [
141
                'ID' => $baseMember->ID,
142
                'ClassName' => TestExcelMember::class,
143
                'Email' => $duplicateEmail,
144
            ]
145
        ]);
146
147
        $this->assertEquals(0, $result->CreatedCount());
148
        $this->assertEquals(1, $result->UpdatedCount());
149
150
        // Check that our existing member has the new class
151
        $member = TestExcelMember::get()->filter('Email', $duplicateEmail)->first();
152
        $this->assertNotEmpty($member);
153
        $this->assertEquals($baseMember->ID, $member->ID);
154
    }
155
156
    public function testTransaction()
157
    {
158
        $beforeCount = Member::get()->count();
159
160
        $loader = new ExcelMemberBulkLoader();
161
        $loader->setUseTransaction(true);
162
163
        try {
164
            $result = $loader->load(__DIR__ . '/data/members-invalid.csv');
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
165
        } catch (Exception $e) {
166
            // expected to fail
167
        }
168
169
        // First row was not created because it was rolled back
170
        $member = Member::get()->filter('Email', '[email protected]')->first();
171
        $this->assertEmpty($member);
172
173
        $newTotalCount = Member::get()->count();
174
        $this->assertEquals($newTotalCount, $beforeCount);
175
176
177
        $loader = new ExcelMemberBulkLoader();
178
        $loader->setUseTransaction(false);
179
180
        try {
181
            $result = $loader->load(__DIR__ . '/data/members-invalid.csv');
182
        } catch (Exception $e) {
183
            // expected to fail
184
        }
185
186
        // First row was created because it was not rolled back
187
        $member = Member::get()->filter('Email', '[email protected]')->first();
188
        $this->assertNotEmpty($member);
189
190
        $newTotalCount = Member::get()->count();
191
        $this->assertEquals($newTotalCount - 1, $beforeCount);
192
    }
193
}
194