1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Symbiote\AdvancedWorkflow\Tests; |
4
|
|
|
|
5
|
|
|
use SilverStripe\Core\Injector\Injector; |
6
|
|
|
use SilverStripe\Dev\SapphireTest; |
7
|
|
|
use SilverStripe\Security\Member; |
8
|
|
|
use SilverStripe\View\ArrayData; |
9
|
|
|
use Symbiote\AdvancedWorkflow\Admin\WorkflowDefinitionExporter; |
10
|
|
|
use Symbiote\AdvancedWorkflow\Admin\WorkflowDefinitionImporter; |
11
|
|
|
use Symbiote\AdvancedWorkflow\DataObjects\ImportedWorkflowTemplate; |
12
|
|
|
use Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction; |
13
|
|
|
use Symbiote\AdvancedWorkflow\DataObjects\WorkflowDefinition; |
14
|
|
|
use Symbiote\AdvancedWorkflow\DataObjects\WorkflowTransition; |
15
|
|
|
use Symbiote\AdvancedWorkflow\Templates\WorkflowTemplate; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Tests for workflow import/export logic. |
19
|
|
|
* |
20
|
|
|
* @author [email protected] |
21
|
|
|
* @license BSD License (http://silverstripe.org/bsd-license/) |
22
|
|
|
* @package advancedworkflow |
23
|
|
|
* @subpackage tests |
24
|
|
|
*/ |
25
|
|
|
class WorkflowImportExportTest extends SapphireTest |
26
|
|
|
{ |
27
|
|
|
protected static $fixture_file = 'workflowtemplateimport.yml'; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Utility method, used in tests |
31
|
|
|
* @return WorkflowDefinition |
32
|
|
|
*/ |
33
|
|
View Code Duplication |
protected function createDefinition() |
|
|
|
|
34
|
|
|
{ |
35
|
|
|
$definition = new WorkflowDefinition(); |
36
|
|
|
$definition->Title = "Dummy Workflow Definition"; |
|
|
|
|
37
|
|
|
$definition->write(); |
38
|
|
|
|
39
|
|
|
$stepOne = new WorkflowAction(); |
40
|
|
|
$stepOne->Title = "Step One"; |
|
|
|
|
41
|
|
|
$stepOne->WorkflowDefID = $definition->ID; |
|
|
|
|
42
|
|
|
$stepOne->write(); |
43
|
|
|
|
44
|
|
|
$stepTwo = new WorkflowAction(); |
45
|
|
|
$stepTwo->Title = "Step Two"; |
|
|
|
|
46
|
|
|
$stepTwo->WorkflowDefID = $definition->ID; |
|
|
|
|
47
|
|
|
$stepTwo->write(); |
48
|
|
|
|
49
|
|
|
$transitionOne = new WorkflowTransition(); |
50
|
|
|
$transitionOne->Title = 'Step One T1'; |
|
|
|
|
51
|
|
|
$transitionOne->ActionID = $stepOne->ID; |
|
|
|
|
52
|
|
|
$transitionOne->NextActionID = $stepTwo->ID; |
|
|
|
|
53
|
|
|
$transitionOne->write(); |
54
|
|
|
|
55
|
|
|
return $definition; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Create a WorkflowDefinition with some actions. Ensure an expected length of formatted template. |
60
|
|
|
*/ |
61
|
|
|
public function testFormatWithActions() |
62
|
|
|
{ |
63
|
|
|
$definition = $this->createDefinition(); |
64
|
|
|
$exporter = Injector::inst()->createWithArgs(WorkflowDefinitionExporter::class, array($definition->ID)); |
65
|
|
|
$member = new Member(); |
66
|
|
|
$member->FirstName = 'joe'; |
67
|
|
|
$member->Surname = 'bloggs'; |
68
|
|
|
$exporter->setMember($member); |
69
|
|
|
$templateData = new ArrayData(array( |
70
|
|
|
'ExportMetaData' => $exporter->ExportMetaData(), |
71
|
|
|
'ExportActions' => $exporter->getDefinition()->Actions() |
72
|
|
|
)); |
73
|
|
|
|
74
|
|
|
$formatted = $exporter->format($templateData); |
75
|
|
|
$numActions = count(preg_split("#\R#", $formatted)); |
76
|
|
|
|
77
|
|
|
$this->assertNotEmpty($formatted); |
78
|
|
|
// Seems arbitrary, but if no actions, then the resulting YAML file is exactly 18 lines long |
79
|
|
|
$this->assertGreaterThan(18, $numActions); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Create a WorkflowDefinition with NO actions. Ensure an expected length of formatted template. |
84
|
|
|
*/ |
85
|
|
|
public function testFormatWithoutActions() |
86
|
|
|
{ |
87
|
|
|
$definition = $this->createDefinition(); |
88
|
|
|
$exporter = Injector::inst()->createWithArgs(WorkflowDefinitionExporter::class, array($definition->ID)); |
89
|
|
|
$member = new Member(); |
90
|
|
|
$member->FirstName = 'joe'; |
91
|
|
|
$member->Surname = 'bloggs'; |
92
|
|
|
$exporter->setMember($member); |
93
|
|
|
$templateData = new ArrayData(array()); |
94
|
|
|
|
95
|
|
|
$formatted = $exporter->format($templateData); |
96
|
|
|
$numActions = count(preg_split("#\R#", $formatted)); |
97
|
|
|
|
98
|
|
|
// Seems arbitrary, but if no actions, then the resulting YAML file is exactly 19 lines long |
99
|
|
|
$this->assertEquals(19, $numActions); |
100
|
|
|
|
101
|
|
|
// Ensure outputted YAML has no blank lines, where SS's control structures would normally be |
102
|
|
|
$numBlanks = preg_match("#^\s*$#m", $formatted); |
103
|
|
|
$this->assertEquals(0, $numBlanks); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Tests a badly formatted YAML import for parsing (no headers) |
108
|
|
|
*/ |
109
|
|
|
public function testParseBadYAMLNoHeaderImport() |
110
|
|
|
{ |
111
|
|
|
$importer = new WorkflowDefinitionImporter(); |
112
|
|
|
$this->setExpectedException('Exception', 'Invalid YAML format.'); |
|
|
|
|
113
|
|
|
$source = <<<'EOD' |
114
|
|
|
SilverStripe\Core\Injector\Injector\Injector: |
115
|
|
|
ExportedWorkflow: |
116
|
|
|
class: Symbiote\AdvancedWorkflow\Templates\WorkflowTemplate |
117
|
|
|
constructor: |
118
|
|
|
- 'My Workflow 4 20/02/2014 03-12-55' |
119
|
|
|
- 'Exported from localhost on 20/02/2014 03:12:55 by joe bloggs using SilverStripe versions Framework 4.0.0-beta3' |
120
|
|
|
- 0.2 |
121
|
|
|
- 0 |
122
|
|
|
- 3 |
123
|
|
|
properties: |
124
|
|
|
structure: |
125
|
|
|
'Step One': |
126
|
|
|
type: Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction |
127
|
|
|
transitions: |
128
|
|
|
- Step One T1: 'Step Two' |
129
|
|
|
'Step Two': |
130
|
|
|
type: Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction |
131
|
|
|
Symbiote\AdvancedWorkflow\Services\WorkflowService: |
132
|
|
|
properties: |
133
|
|
|
templates: |
134
|
|
|
- %$ExportedWorkflow |
135
|
|
|
EOD; |
136
|
|
|
|
137
|
|
|
$importer->parseYAMLImport($source); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Tests a badly formatted YAML import for parsing (missing YML colon) |
142
|
|
|
*/ |
143
|
|
|
public function testParseBadYAMLMalformedImport() |
144
|
|
|
{ |
145
|
|
|
$importer = new WorkflowDefinitionImporter(); |
146
|
|
|
$this->setExpectedException('SilverStripe\\ORM\\ValidationException', 'Invalid YAML format. Unable to parse.'); |
|
|
|
|
147
|
|
|
$source = <<<'EOD' |
148
|
|
|
--- |
149
|
|
|
Name: exportedworkflow |
150
|
|
|
--- |
151
|
|
|
# Missing colon on line below |
152
|
|
|
SilverStripe\Core\Injector\Injector |
153
|
|
|
ExportedWorkflow: |
154
|
|
|
class: Symbiote\AdvancedWorkflow\Templates\WorkflowTemplate |
155
|
|
|
constructor: |
156
|
|
|
- 'My Workflow 4 20/02/2014 03-12-55' |
157
|
|
|
- 'Exported from localhost on 20/02/2014 03-12-55 by joe bloggs using SilverStripe versions Framework 4.0.0-beta3' |
158
|
|
|
- 0.2 |
159
|
|
|
- 0 |
160
|
|
|
- 3 |
161
|
|
|
properties: |
162
|
|
|
structure: |
163
|
|
|
'Step One' |
164
|
|
|
type: Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction |
165
|
|
|
transitions: |
166
|
|
|
- Step One T1: 'Step Two' |
167
|
|
|
'Step Two': |
168
|
|
|
type: Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction |
169
|
|
|
Symbiote\AdvancedWorkflow\Services\WorkflowService: |
170
|
|
|
properties: |
171
|
|
|
templates: |
172
|
|
|
- %$ExportedWorkflow |
173
|
|
|
EOD; |
174
|
|
|
|
175
|
|
|
$importer->parseYAMLImport($source); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Tests a well-formatted YAML import for parsing |
180
|
|
|
*/ |
181
|
|
|
public function testParseGoodYAMLImport() |
182
|
|
|
{ |
183
|
|
|
$importer = new WorkflowDefinitionImporter(); |
184
|
|
|
$source = <<<'EOD' |
185
|
|
|
--- |
186
|
|
|
Name: exportedworkflow |
187
|
|
|
--- |
188
|
|
|
SilverStripe\Core\Injector\Injector: |
189
|
|
|
ExportedWorkflow: |
190
|
|
|
class: Symbiote\AdvancedWorkflow\Templates\WorkflowTemplate |
191
|
|
|
constructor: |
192
|
|
|
- 'My Workflow 4 20/02/2014 03-12-55' |
193
|
|
|
- 'Exported from localhost on 20/02/2014 03-12-55 by joe bloggs using SilverStripe versions Framework 4.0.0-beta3' |
194
|
|
|
- 0.2 |
195
|
|
|
- 0 |
196
|
|
|
- 3 |
197
|
|
|
properties: |
198
|
|
|
structure: |
199
|
|
|
'Step One': |
200
|
|
|
type: Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction |
201
|
|
|
transitions: |
202
|
|
|
- Step One T1: 'Step Two' |
203
|
|
|
'Step Two': |
204
|
|
|
type: Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction |
205
|
|
|
Symbiote\AdvancedWorkflow\Services\WorkflowService: |
206
|
|
|
properties: |
207
|
|
|
templates: |
208
|
|
|
- %$ExportedWorkflow |
209
|
|
|
EOD; |
210
|
|
|
|
211
|
|
|
$this->assertNotEmpty($importer->parseYAMLImport($source)); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Given no ImportedWorkflowTemplate fixture/input data, tests an empty array is returned |
216
|
|
|
* by WorkflowDefinitionImporter#getImportedWorkflows() |
217
|
|
|
*/ |
218
|
|
|
public function testGetImportedWorkflowsNone() |
219
|
|
|
{ |
220
|
|
|
$this->clearFixtures(); |
221
|
|
|
$importer = new WorkflowDefinitionImporter(); |
222
|
|
|
$imports = $importer->getImportedWorkflows(); |
223
|
|
|
$this->assertEmpty($imports); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Given a single ImportedWorkflowTemplate fixture/input data, tests an non-empty array is returned |
228
|
|
|
* by WorkflowDefinitionImporter#getImportedWorkflows() |
229
|
|
|
*/ |
230
|
|
|
public function testGetImportedWorkflowsOne() |
231
|
|
|
{ |
232
|
|
|
$name = 'My Workflow 21/02/2014 09-01-29'; |
233
|
|
|
// Pretend a ImportedWorkflowTemplate object has been created by WorkflowBulkLoader |
234
|
|
|
$this->objFromFixture(ImportedWorkflowTemplate::class, 'Import01'); |
235
|
|
|
|
236
|
|
|
/** @var WorkflowDefinitionImporter $importer */ |
237
|
|
|
$importer = singleton(WorkflowDefinitionImporter::class); |
238
|
|
|
$import = $importer->getImportedWorkflows($name); |
239
|
|
|
|
240
|
|
|
$this->assertNotEmpty($import); |
241
|
|
|
$this->assertInstanceOf(WorkflowTemplate::class, $import); |
242
|
|
|
$this->assertEquals($name, $import->getName()); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Given many ImportedWorkflowTemplate fixture/input data, tests an non-empty array is returned |
247
|
|
|
* by WorkflowDefinitionImporter#getImportedWorkflows() |
248
|
|
|
*/ |
249
|
|
|
public function testGetImportedWorkflowsMany() |
250
|
|
|
{ |
251
|
|
|
// Pretend some ImportedWorkflowTemplate objects have been created by WorkflowBulkLoader |
252
|
|
|
$this->objFromFixture(ImportedWorkflowTemplate::class, 'Import02'); |
253
|
|
|
$this->objFromFixture(ImportedWorkflowTemplate::class, 'Import03'); |
254
|
|
|
|
255
|
|
|
$importer = singleton(WorkflowDefinitionImporter::class); |
256
|
|
|
$imports = $importer->getImportedWorkflows(); |
257
|
|
|
|
258
|
|
|
$this->assertNotEmpty($imports); |
259
|
|
|
$this->assertInternalType('array', $imports); |
260
|
|
|
$this->assertGreaterThan(1, count($imports)); |
261
|
|
|
} |
262
|
|
|
} |
263
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.