blob: 38a8d8c5e96d043579f85269ab0506dd53c668f1 [file]
<?php
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
declare(strict_types=1);
final class SharedFeatureParser
{
public static function load(string $featureFile): array
{
if (!is_file($featureFile)) {
throw new RuntimeException("feature file not found at {$featureFile}");
}
$lines = file($featureFile, FILE_IGNORE_NEW_LINES);
if ($lines === false) {
throw new RuntimeException("failed to read feature file at {$featureFile}");
}
$backgroundSteps = [];
$scenarios = [];
$currentScenario = null;
$currentSteps = [];
$section = null;
foreach ($lines as $line) {
$line = trim($line);
if ($line === '' || str_starts_with($line, '#') || str_starts_with($line, '@')) {
continue;
}
if ($line === 'Background:') {
$section = 'background';
continue;
}
if (str_starts_with($line, 'Scenario:')) {
if ($currentScenario !== null) {
$scenarios[$currentScenario] = $currentSteps;
}
$currentScenario = trim(substr($line, strlen('Scenario:')));
$currentSteps = [];
$section = 'scenario';
continue;
}
if (preg_match('/^(Scenario Outline|Rule|Examples):|^\|/', $line) === 1) {
throw new RuntimeException("Unsupported BDD structure: {$line}");
}
if (preg_match('/^(Given|When|Then|And|But|\*) (.+)$/', $line, $matches) !== 1) {
continue;
}
if ($section === null) {
throw new RuntimeException("BDD step appears before Background or Scenario: {$line}");
}
if ($section === 'background') {
$backgroundSteps[] = $matches[2];
} elseif ($currentScenario !== null) {
$currentSteps[] = $matches[2];
}
}
if ($currentScenario !== null) {
$scenarios[$currentScenario] = $currentSteps;
}
if ($backgroundSteps === [] || $scenarios === []) {
throw new RuntimeException("feature must contain a background and at least one scenario: {$featureFile}");
}
$cases = [];
foreach ($scenarios as $scenarioName => $scenarioSteps) {
if ($scenarioSteps === []) {
throw new RuntimeException("scenario has no steps: {$scenarioName}");
}
$cases[$scenarioName] = [$scenarioName, [...$backgroundSteps, ...$scenarioSteps]];
}
return $cases;
}
}