Skip to content

Commit 58c916d

Browse files
committed
MQE-2246: Implement <suite> entity use cases in MFTF SVC tool
1 parent 0108b3e commit 58c916d

File tree

63 files changed

+1907
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1907
-1
lines changed

src/Analyzer/Factory/MFTFAnalyzerFactory.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Magento\SemanticVersionChecker\Analyzer\Mftf\PageAnalyzer;
1818
use Magento\SemanticVersionChecker\Analyzer\Mftf\SectionAnalyzer;
1919
use Magento\SemanticVersionChecker\Analyzer\Mftf\TestAnalyzer;
20+
use Magento\SemanticVersionChecker\Analyzer\Mftf\SuiteAnalyzer;
2021
use Magento\SemanticVersionChecker\ClassHierarchy\DependencyGraph;
2122
use Magento\SemanticVersionChecker\MftfReport;
2223

@@ -38,7 +39,8 @@ public function create(DependencyGraph $dependencyGraph = null): AnalyzerInterfa
3839
new PageAnalyzer($report),
3940
new SectionAnalyzer($report),
4041
new TestAnalyzer($report),
41-
new ActionGroupAnalyzer($report)
42+
new ActionGroupAnalyzer($report),
43+
new SuiteAnalyzer($report)
4244
];
4345

4446
return new Analyzer($analyzers);

src/Analyzer/Mftf/SuiteAnalyzer.php

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\SemanticVersionChecker\Analyzer\Mftf;
8+
9+
use Magento\SemanticVersionChecker\MftfReport;
10+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteIncludeExcludeAdded;
11+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteIncludeExcludeRemoved;
12+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterActionChanged;
13+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterActionGroupRefChanged;
14+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterActionAdded;
15+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterActionRemoved;
16+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterActionSequenceChanged;
17+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterActionTypeChanged;
18+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterRemoveActionAdded;
19+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteBeforeAfterRemoveActionRemoved;
20+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteAdded;
21+
use Magento\SemanticVersionChecker\Operation\Mftf\Suite\SuiteRemoved;
22+
use Magento\SemanticVersionChecker\Scanner\MftfScanner;
23+
use PHPSemVerChecker\Registry\Registry;
24+
use PHPSemVerChecker\Report\Report;
25+
26+
class SuiteAnalyzer extends AbstractEntityAnalyzer
27+
{
28+
const MFTF_SUITE_BEFORE_ELEMENT = "{}before";
29+
const MFTF_SUITE_AFTER_ELEMENT = "{}after";
30+
const MFTF_SUITE_INCLUDE_ELEMENT = "{}include";
31+
const MFTF_SUITE_EXCLUDE_ELEMENT = "{}exclude";
32+
const MFTF_DATA_TYPE = 'suite';
33+
const MFTF_DATA_DIRECTORY = '/Mftf/Suite/';
34+
35+
/**
36+
* Action operations array
37+
*
38+
* @var string[][]
39+
*/
40+
private static $operations = [
41+
'stepKey' => [
42+
'add' => SuiteBeforeAfterActionAdded::class,
43+
'remove' => SuiteBeforeAfterActionRemoved::class,
44+
],
45+
'keyForRemoval' => [
46+
'add' => SuiteBeforeAfterRemoveActionAdded::class,
47+
'remove' => SuiteBeforeAfterRemoveActionRemoved::class,
48+
],
49+
];
50+
51+
/**
52+
* MFTF test.xml analyzer
53+
*
54+
* @param Registry $registryBefore
55+
* @param Registry $registryAfter
56+
* @return Report
57+
*/
58+
public function analyze(Registry $registryBefore, Registry $registryAfter)
59+
{
60+
$beforeEntities = $registryBefore->data[MftfScanner::MFTF_ENTITY] ?? [];
61+
$afterEntities = $registryAfter->data[MftfScanner::MFTF_ENTITY] ?? [];
62+
63+
foreach ($beforeEntities as $module => $entities) {
64+
$this->findAddedEntitiesInModule(
65+
$entities,
66+
$afterEntities[$module] ?? [],
67+
self::MFTF_DATA_TYPE,
68+
$this->getReport(),
69+
SuiteAdded::class,
70+
$module . '/Suite'
71+
);
72+
foreach ($entities as $entityName => $beforeEntity) {
73+
if ($beforeEntity['type'] !== self::MFTF_DATA_TYPE) {
74+
continue;
75+
}
76+
$operationTarget = $module . '/Suite/' . $entityName;
77+
$filenames = implode(", ", $beforeEntity['filePaths']);
78+
79+
// Validate suite still exists
80+
if (!isset($afterEntities[$module][$entityName])) {
81+
$operation = new SuiteRemoved($filenames, $operationTarget);
82+
$this->getReport()->add(MftfReport::MFTF_REPORT_CONTEXT, $operation);
83+
continue;
84+
}
85+
86+
//Sort Elements
87+
$beforeSuiteBeforeActions = [];
88+
$beforeSuiteAfterActions = [];
89+
$beforeSuiteIncludeElements = [];
90+
$beforeSuiteExcludeElements = [];
91+
92+
$afterSuiteBeforeActions = [];
93+
$afterSuiteAfterActions = [];
94+
$afterSuiteIncludeElements = [];
95+
$afterSuiteExcludeElements = [];
96+
97+
foreach ($beforeEntity['value'] as $beforeChild) {
98+
if ($beforeChild['name'] == self::MFTF_SUITE_BEFORE_ELEMENT) {
99+
$beforeSuiteBeforeActions = $beforeChild['value'] ?? [];
100+
} elseif ($beforeChild['name'] == self::MFTF_SUITE_AFTER_ELEMENT) {
101+
$beforeSuiteAfterActions = $beforeChild['value'] ?? [];
102+
} elseif ($beforeChild['name'] == self::MFTF_SUITE_INCLUDE_ELEMENT) {
103+
$beforeSuiteIncludeElements = $beforeChild['value'] ?? [];
104+
} elseif ($beforeChild['name'] == self::MFTF_SUITE_EXCLUDE_ELEMENT) {
105+
$beforeSuiteExcludeElements = $beforeChild['value'] ?? [];
106+
}
107+
}
108+
foreach ($afterEntities[$module][$entityName]['value'] as $afterChild) {
109+
if ($afterChild['name'] == self::MFTF_SUITE_BEFORE_ELEMENT) {
110+
$afterSuiteBeforeActions = $afterChild['value'] ?? [];
111+
} elseif ($afterChild['name'] == self::MFTF_SUITE_AFTER_ELEMENT) {
112+
$afterSuiteAfterActions = $afterChild['value'] ?? [];
113+
} elseif ($afterChild['name'] == self::MFTF_SUITE_INCLUDE_ELEMENT) {
114+
$afterSuiteIncludeElements = $afterChild['value'] ?? [];
115+
} elseif ($afterChild['name'] == self::MFTF_SUITE_EXCLUDE_ELEMENT) {
116+
$afterSuiteExcludeElements = $afterChild['value'] ?? [];
117+
}
118+
}
119+
120+
// Validate <before> <action> elements
121+
$this->validateActionsInBlock(
122+
$beforeSuiteBeforeActions,
123+
$afterSuiteBeforeActions,
124+
$this->getReport(),
125+
$filenames,
126+
$operationTarget . "/before"
127+
);
128+
129+
// Validate <after> <action> elements
130+
$this->validateActionsInBlock(
131+
$beforeSuiteAfterActions,
132+
$afterSuiteAfterActions,
133+
$this->getReport(),
134+
$filenames,
135+
$operationTarget . "/after"
136+
);
137+
138+
// Validate <include> elements
139+
$this->validateIncludesExcludes(
140+
$beforeSuiteIncludeElements,
141+
$afterSuiteIncludeElements,
142+
$this->getReport(),
143+
$filenames,
144+
$operationTarget . "/include"
145+
);
146+
147+
// Validate <exclude> elements
148+
$this->validateIncludesExcludes(
149+
$beforeSuiteExcludeElements,
150+
$afterSuiteExcludeElements,
151+
$this->getReport(),
152+
$filenames,
153+
$operationTarget . "/exclude"
154+
);
155+
}
156+
}
157+
return $this->getReport();
158+
}
159+
160+
/**
161+
* Validates all actions in given test block
162+
*
163+
* @param array $beforeTestActions
164+
* @param array $afterTestActions
165+
* @param Report $report
166+
* @param string $filenames
167+
* @param string $operationTarget
168+
* @return void
169+
*/
170+
public function validateActionsInBlock(
171+
$beforeTestActions,
172+
$afterTestActions,
173+
$report,
174+
$filenames,
175+
$operationTarget
176+
) {
177+
$this->matchAndValidateActionsSequence(
178+
$beforeTestActions,
179+
$afterTestActions,
180+
$report,
181+
$filenames,
182+
SuiteBeforeAfterActionSequenceChanged::class,
183+
$operationTarget
184+
);
185+
186+
foreach ($beforeTestActions as $testAction) {
187+
if (isset($testAction['attributes']['stepKey'])) {
188+
$elementIdentifier = 'stepKey';
189+
} elseif (isset($testAction['attributes']['keyForRemoval'])) {
190+
$elementIdentifier = 'keyForRemoval';
191+
} else {
192+
continue;
193+
}
194+
195+
$beforeFieldKey = $testAction['attributes'][$elementIdentifier];
196+
$matchingElement = $this->findMatchingElement($testAction, $afterTestActions, $elementIdentifier);
197+
if ($matchingElement === null) {
198+
$operation = new self::$operations[$elementIdentifier]['remove'](
199+
$filenames,
200+
"$operationTarget/$beforeFieldKey"
201+
);
202+
$report->add(MftfReport::MFTF_REPORT_CONTEXT, $operation);
203+
} else {
204+
$this->matchAndValidateAttributes(
205+
$testAction['attributes'],
206+
$matchingElement['attributes'],
207+
$report,
208+
$filenames,
209+
[
210+
AbstractEntityAnalyzer::DEFAULT_OPERATION_KEY => SuiteBeforeAfterActionChanged::class,
211+
'ref' => SuiteBeforeAfterActionGroupRefChanged::class,
212+
],
213+
"$operationTarget/$beforeFieldKey"
214+
);
215+
$this->matchAndValidateElementType(
216+
$testAction,
217+
$matchingElement,
218+
$report,
219+
$filenames,
220+
SuiteBeforeAfterActionTypeChanged::class,
221+
"$operationTarget/$beforeFieldKey"
222+
);
223+
}
224+
}
225+
226+
foreach (self::$operations as $identifier => $operations) {
227+
$this->findAddedElementsInArray(
228+
$beforeTestActions,
229+
$afterTestActions,
230+
$identifier,
231+
$report,
232+
$filenames,
233+
$operations['add'],
234+
$operationTarget
235+
);
236+
}
237+
}
238+
239+
/**
240+
* Validate includes and excludes elements
241+
*
242+
* @param array $beforeElements
243+
* @param array $afterElements
244+
* @param Report $report
245+
* @param string $filenames
246+
* @param string $operationTarget
247+
* @return void
248+
*/
249+
public function validateIncludesExcludes(
250+
$beforeElements,
251+
$afterElements,
252+
$report,
253+
$filenames,
254+
$operationTarget
255+
) {
256+
foreach ($beforeElements as $beforeElement) {
257+
$elementIdentifier = 'name';
258+
if (!isset($beforeElement['attributes'][$elementIdentifier])) {
259+
continue;
260+
}
261+
$beforeElementKey = $beforeElement['attributes'][$elementIdentifier];
262+
$matchingElement = $this->findMatchingElement($beforeElement, $afterElements, $elementIdentifier);
263+
264+
if ($matchingElement === null) {
265+
$operation = new SuiteIncludeExcludeRemoved($filenames, "$operationTarget/$beforeElementKey");
266+
$report->add(MftfReport::MFTF_REPORT_CONTEXT, $operation);
267+
}
268+
}
269+
270+
foreach ($afterElements as $afterElement) {
271+
$elementIdentifier = 'name';
272+
if (!isset($afterElement['attributes'][$elementIdentifier])) {
273+
continue;
274+
}
275+
$afterElementKey = $afterElement['attributes'][$elementIdentifier];
276+
$matchingElement = $this->findMatchingElement($afterElement, $beforeElements, $elementIdentifier);
277+
278+
if ($matchingElement === null) {
279+
$operation = new SuiteIncludeExcludeAdded($filenames, "$operationTarget/$afterElementKey");
280+
$report->add(MftfReport::MFTF_REPORT_CONTEXT, $operation);
281+
}
282+
}
283+
}
284+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Magento\SemanticVersionChecker\Operation\Mftf\Suite;
4+
5+
use Magento\SemanticVersionChecker\Operation\Mftf\MftfOperation;
6+
use PHPSemVerChecker\SemanticVersioning\Level;
7+
8+
/**
9+
* Suite Entity was added to the Module
10+
*/
11+
class SuiteAdded extends MftfOperation
12+
{
13+
/**
14+
* Error codes.
15+
*
16+
* @var array
17+
*/
18+
protected $code = 'M407';
19+
20+
/**
21+
* Operation Severity
22+
* @var int
23+
*/
24+
protected $level = Level::MINOR;
25+
26+
/**
27+
* Operation message.
28+
*
29+
* @var string
30+
*/
31+
protected $reason = '<suite> was added';
32+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Magento\SemanticVersionChecker\Operation\Mftf\Suite;
4+
5+
use Magento\SemanticVersionChecker\Operation\Mftf\MftfOperation;
6+
use PHPSemVerChecker\SemanticVersioning\Level;
7+
8+
/**
9+
* Suite before or after action was added from the Module
10+
*/
11+
class SuiteBeforeAfterActionAdded extends MftfOperation
12+
{
13+
/**
14+
* Error codes.
15+
*
16+
* @var array
17+
*/
18+
protected $code = 'M415';
19+
20+
/**
21+
* Operation Severity
22+
* @var int
23+
*/
24+
protected $level = Level::MINOR;
25+
26+
/**
27+
* Operation message.
28+
*
29+
* @var string
30+
*/
31+
protected $reason = '<suite> <before/after> <action> was added';
32+
}

0 commit comments

Comments
 (0)