91 private $actionAttributes = [];
98 private $linkedAction;
105 private $orderOffset = 0;
112 private $resolvedCustomAttributes = [];
126 private $actionOrigin = [];
142 $linkedAction =
null,
146 $this->stepKey = $stepKey;
148 $this->actionAttributes = $actionAttributes;
149 $this->linkedAction = $linkedAction;
150 $this->actionOrigin = $actionOrigin;
153 $this->orderOffset = 1;
164 return $this->stepKey;
184 return $this->actionOrigin;
199 return array_merge($this->actionAttributes, $this->resolvedCustomAttributes);
209 return $this->linkedAction;
219 return $this->orderOffset;
230 return $this->timeout;
241 $this->timeout = $timeout;
256 if (empty($this->resolvedCustomAttributes)) {
258 $this->resolveSelectorReferenceAndTimeout();
259 $this->resolveUrlReference();
260 $this->resolveDataInputReferences();
261 $this->validateTimezoneAttribute();
262 if ($this->
getType() ==
"deleteData") {
263 $this->validateMutuallyExclusiveAttributes(self::DELETE_DATA_MUTUAL_EXCLUSIVE_ATTRIBUTES);
278 $actionAttributeKeys = array_keys($this->actionAttributes);
285 if (!empty($oldAttributes)) {
289 "use of one line Assertion actions will be deprecated in MFTF 3.0.0, please use nested syntax",
290 [
"action" => $this->type,
"stepKey" => $this->stepKey]
297 $relevantAssertionAttributes = array_intersect($actionAttributeKeys, $relevantKeys);
299 if (empty($relevantAssertionAttributes)) {
303 $this->validateAssertionSchema($relevantAssertionAttributes);
306 foreach ($this->actionAttributes as $key => $subAttributes) {
307 if (in_array($key, $relevantKeys)) {
311 $this->actionAttributes[
$prefix] =
313 unset($this->actionAttributes[$key]);
324 private function validateAssertionSchema(
$attributes)
329 $singleChildTypes = [
'assertEmpty',
'assertFalse',
'assertFileExists',
'assertFileNotExists',
330 'assertIsEmpty',
'assertNotEmpty',
'assertNotNull',
'assertNull',
'assertTrue',
331 'assertElementContainsAttribute'];
333 if (!in_array($this->type, $singleChildTypes)) {
337 "{$this->type} must have both an expectedResult & actualResult defined (stepKey: {$this->stepKey})",
338 [
"action" => $this->type,
"stepKey" => $this->stepKey]
353 private function resolveSelectorReferenceAndTimeout()
355 $actionAttributeKeys = array_keys($this->actionAttributes);
358 if (empty($relevantSelectorAttributes)) {
362 foreach ($relevantSelectorAttributes as $selectorAttribute) {
363 $selector = $this->actionAttributes[$selectorAttribute];
367 $this->resolvedCustomAttributes[$selectorAttribute] =
$replacement;
381 private function resolveUrlReference()
396 "page url attribute not found and is required",
397 [
"action" => $this->type,
"url" =>
$url,
"stepKey" => $this->stepKey]
412 private function resolveDataInputReferences()
414 $actionAttributeKeys = array_keys($this->actionAttributes);
417 if (empty($relevantDataAttributes)) {
421 foreach ($relevantDataAttributes as $dataAttribute) {
422 $varInput = $this->actionAttributes[$dataAttribute];
425 $this->resolvedCustomAttributes[$dataAttribute] =
$replacement;
437 private function stripAndSplitReference($reference)
439 $strippedReference = str_replace(
'}}',
'', str_replace(
'{{',
'', $reference));
440 $strippedReference = preg_replace(
445 return explode(
'.', $strippedReference);
455 private function stripAndReturnParameters($reference)
458 $literalParametersRegex =
"/'[^']+'/";
459 $postCleanupDelimiter =
"::::";
462 if (!empty($matches)) {
463 $strippedReference = ltrim(rtrim($matches[0],
")"),
"(");
466 preg_match_all($literalParametersRegex, $strippedReference, $literalReferences);
467 $strippedReference = preg_replace($literalParametersRegex,
'&&stringReference&&', $strippedReference);
470 $strippedReference = preg_replace(
'/,/',
', ', $strippedReference);
471 $strippedReference = str_replace(
',', $postCleanupDelimiter, $strippedReference);
472 $strippedReference = str_replace(
' ',
'', $strippedReference);
475 foreach ($literalReferences[0] as $key =>
$value) {
476 $strippedReference = preg_replace(
'/&&stringReference&&/',
$value, $strippedReference, 1);
479 return explode($postCleanupDelimiter, $strippedReference);
495 private function findAndReplaceReferences($objectHandler, $inputString)
500 preg_match_all($regex, $inputString, $matches);
502 $outputString = $inputString;
504 foreach ($matches[0] as $match) {
506 $parameterized =
false;
507 list($objName) = $this->stripAndSplitReference($match);
509 $obj = $objectHandler->getObject($objName);
519 $parameterized =
false;
520 }
elseif (get_class($obj) == PageObject::class) {
521 $this->validateUrlAreaAgainstActionType($obj);
523 $parameterized = $obj->isParameterized();
524 }
elseif (get_class($obj) == SectionObject::class) {
525 list(,$objField) = $this->stripAndSplitReference($match);
526 if ($obj->getElement($objField) ==
null) {
527 throw new TestReferenceException(
528 "Could not resolve entity reference \"{$inputString}\" " 529 .
"in Action with stepKey \"{$this->getStepKey()}\"",
530 [
"input" => $inputString,
"stepKey" => $this->
getStepKey()]
533 $parameterized = $obj->getElement($objField)->isParameterized();
534 $replacement = $obj->getElement($objField)->getPrioritizedSelector();
535 $this->
setTimeout($obj->getElement($objField)->getTimeout());
536 }
elseif (get_class($obj) == EntityDataObject::class) {
537 $replacement = $this->resolveEntityDataObjectReference($obj, $match);
545 if (get_class($objectHandler) != DataObjectHandler::class) {
548 throw new TestReferenceException(
549 "Could not resolve entity reference \"{$inputString}\" " 550 .
"in Action with stepKey \"{$this->getStepKey()}\"",
551 [
"input" => $inputString,
"stepKey" => $this->
getStepKey()]
558 $outputString = str_replace($match,
$replacement, $outputString);
560 return $outputString;
569 private function validateMutuallyExclusiveAttributes(array
$attributes)
572 if (count($matches) > 1) {
573 throw new TestReferenceException(
574 "Actions of type '{$this->getType()}' must only contain one attribute of types '" 576 [
"type" => $this->
getType(),
"attributes" => $attributes]
578 }
elseif (count($matches) == 0) {
579 throw new TestReferenceException(
580 "Actions of type '{$this->getType()}' must contain at least one attribute of types '" 582 [
"type" => $this->
getType(),
"attributes" => $attributes]
594 private function validateUrlAreaAgainstActionType($obj)
596 if ($obj->getArea() ==
'external' &&
597 in_array($this->
getType(), self::EXTERNAL_URL_AREA_INVALID_ACTIONS)) {
598 throw new TestReferenceException(
599 "Page of type 'external' is not compatible with action type '{$this->getType()}'",
611 private function validateTimezoneAttribute()
614 if (isset(
$attributes[self::ACTION_ATTRIBUTE_TIMEZONE])) {
617 new \DateTimeZone($timezone);
618 }
catch (\Exception $e) {
619 throw new TestReferenceException(
620 "Timezone '{$timezone}' is not a valid timezone",
621 [
"stepKey" => $this->
getStepKey(), self::ACTION_ATTRIBUTE_TIMEZONE => $timezone]
633 private function resolveEntityDataObjectReference($obj, $match)
635 list(,$objField) = $this->stripAndSplitReference($match);
637 if (strpos($objField,
'[') ==
true) {
639 $parts = explode(
'[', $objField);
641 $index = str_replace(
']',
'', $parts[1]);
658 private function resolveParameterization($isParameterized,
$replacement, $match, $object)
660 if ($isParameterized) {
661 $parameterList = $this->stripAndReturnParameters($match) ?: [];
662 $resolvedReplacement = $this->matchParameterReferences(
$replacement, $parameterList);
667 $resolvedReplacement =
"/{{_ENV.MAGENTO_BACKEND_NAME}}/" . $resolvedReplacement;
669 return $resolvedReplacement;
681 private function matchParameterReferences($reference, $parameters)
683 preg_match_all(
'/{{[\w.]+}}/', $reference, $varMatches);
684 $varMatches[0] = array_unique($varMatches[0]);
685 $this->checkParameterCount($varMatches[0], $parameters, $reference);
691 $resolvedParameters = [];
692 foreach ($parameters as $parameter) {
693 $parameter = trim($parameter);
694 preg_match_all(
"/[$'][\w\D]+[$']/", $parameter, $stringOrPersistedMatch);
695 preg_match_all(
'/{\$[a-z][a-zA-Z\d]+}/', $parameter, $variableMatch);
696 if (!empty($stringOrPersistedMatch[0])) {
697 $resolvedParameters[] = ltrim(rtrim($parameter,
"'"),
"'");
698 }
elseif (!empty($variableMatch[0])) {
699 $resolvedParameters[] = $parameter;
701 $resolvedParameters[] = $this->findAndReplaceReferences(
703 '{{' . $parameter .
'}}' 709 foreach ($varMatches[0] as $var) {
710 $reference = str_replace($var, $resolvedParameters[$resolveIndex++], $reference);
724 private function checkParameterCount($matches, $parameters, $reference)
726 if (count($matches) > count($parameters)) {
727 if (is_array($parameters)) {
728 $parametersGiven = implode(
",", $parameters);
729 }
elseif ($parameters ==
null) {
730 $parametersGiven =
"NONE";
732 $parametersGiven = $parameters;
734 throw new TestReferenceException(
735 "Parameter Resolution Failed: Not enough parameters given for reference " .
736 $reference .
". Parameters Given: " . $parametersGiven,
737 [
"reference" => $reference,
"parametersGiven" => $parametersGiven]
739 }
elseif (count($matches) < count($parameters)) {
740 throw new TestReferenceException(
741 "Parameter Resolution Failed: Too many parameters given for reference " .
742 $reference .
". Parameters Given: " . implode(
", ", $parameters),
743 [
"reference" => $reference,
"parametersGiven" => $parameters]
745 }
elseif (count($matches) == 0) {
746 throw new TestReferenceException(
747 "Parameter Resolution Failed: No parameter matches found in parameterized element with selector " .
749 [
"reference" => $reference]
const DATA_ENABLED_ATTRIBUTES
const CEST_UNIQUE_NOTATION
elseif(isset( $params[ 'redirect_parent']))
trimAssertionAttributes()
const MERGE_ACTION_ORDER_AFTER
const ASSERTION_VALUE_ATTRIBUTE
const FUNCTION_CLOSURE_ACTIONS
const DELETE_DATA_MUTUAL_EXCLUSIVE_ATTRIBUTES
const ASSERTION_ATTRIBUTES
const MERGE_ACTION_ORDER_BEFORE
const SELECTOR_ENABLED_ATTRIBUTES
const ASSERTION_TYPE_ATTRIBUTE
const ACTION_ATTRIBUTE_SELECTOR
__construct( $stepKey, $type, $actionAttributes, $linkedAction=null, $order=ActionObject::MERGE_ACTION_ORDER_BEFORE, $actionOrigin=null)
const ACTION_ATTRIBUTE_VARIABLE_REGEX_PARAMETER
const ACTION_ATTRIBUTE_URL
const ACTION_ATTRIBUTE_VARIABLE_REGEX_PATTERN
const OLD_ASSERTION_ATTRIBUTES
const EXTERNAL_URL_AREA_INVALID_ACTIONS
const ACTION_ATTRIBUTE_TIMEZONE
getCustomActionAttributes()
if(!isset($_GET['name'])) $name