コード例 #1
0
ファイル: Parser.cs プロジェクト: AlexTeixeira/GherkinSpec
        private Feature Parse(LineReader reader)
        {
            reader.ReadNextLine();

            var featureTags = TagParser.ParseTagsIfPresent(reader);

            if (!reader.IsFeatureStartLine)
            {
                throw new InvalidGherkinSyntaxException(
                          $"Expected the first line of a feature file to start with 'Feature:' or a tag.", reader.CurrentLineNumber);
            }

            var featureTitle     = reader.CurrentLineFeatureTitle;
            var featureNarrative = new StringBuilder();

            reader.ReadNextLine();
            while (
                !reader.IsEndOfFile &&
                !reader.IsRuleStartLine &&
                !reader.IsScenarioStartLine &&
                !reader.IsScenarioOutlineStartLine &&
                !reader.IsBackgroundStartLine &&
                !reader.IsTagLine)
            {
                featureNarrative.AppendLine(reader.CurrentLineTrimmed);
                reader.ReadNextLine();
            }

            if (reader.IsEndOfFile)
            {
                return(new Feature(
                           featureTitle,
                           featureNarrative.ToString()?.Trim(),
                           Background.Empty,
                           Enumerable.Empty <Scenario>(),
                           Enumerable.Empty <ScenarioOutline>(),
                           Enumerable.Empty <Rule>(),
                           featureTags));
            }

            var featureBackground = BackgroundParser.ParseBackgroundIfPresent(reader);

            var featureScenarios        = new List <Scenario>();
            var featureScenarioOutlines = new List <ScenarioOutline>();
            var featureRules            = new List <Rule>();

            var featureContentParser = new FeatureContentParser(featureScenarios, featureScenarioOutlines, featureRules, reader);

            featureContentParser.ParseFeatureContent();

            return(new Feature(
                       featureTitle,
                       featureNarrative.ToString()?.Trim(),
                       featureBackground,
                       featureScenarios,
                       featureScenarioOutlines,
                       featureRules,
                       featureTags));
        }
コード例 #2
0
        public static IEnumerable <Tag> ParseTagsIfPresent(LineReader reader)
        {
            if (!reader.IsTagLine)
            {
                return(Enumerable.Empty <Tag>());
            }

            var tags = new List <Tag>();

            while (reader.IsTagLine)
            {
                var tagsOnLine = reader.CurrentLineTrimmed.Split(',');
                foreach (var tag in tagsOnLine)
                {
                    var cleanTag = tag.Trim();
                    if (!cleanTag.StartsWith("@"))
                    {
                        throw new InvalidGherkinSyntaxException(
                                  "All tags must start with @.",
                                  reader.CurrentLineNumber);
                    }

                    cleanTag = cleanTag
                               .Substring(1)
                               .TrimStart();

                    tags.Add(new Tag(cleanTag));
                }

                reader.ReadNextLine();
            }

            return(tags);
        }
コード例 #3
0
        public static Scenario ParseScenario(LineReader reader, IEnumerable <Tag> tags)
        {
            var scenarioTitle = reader.CurrentLineScenarioTitle;
            var scenarioStartingLineNumber = reader.CurrentLineNumber;
            var steps = new List <IStep>();

            reader.ReadNextLine();
            while (reader.IsStepLine)
            {
                steps.Add(
                    ParseStep(reader, steps.LastOrDefault()));

                if (!reader.IsEndOfFile &&
                    !reader.IsStepLine &&
                    !reader.IsScenarioStartLine &&
                    !reader.IsScenarioOutlineStartLine &&
                    !reader.IsTagLine &&
                    !reader.IsRuleStartLine)
                {
                    throw new InvalidGherkinSyntaxException(
                              $"Expected a step (Given, When, Then, And, But), a Scenario, a Scenario Outline, a Rule or a tag, but found '{reader.CurrentLineTrimmed}'.",
                              reader.CurrentLineNumber);
                }
            }

            return(new Scenario(scenarioTitle, steps, scenarioStartingLineNumber, tags));
        }
コード例 #4
0
        private static GivenStep ParseBackgroundStep(LineReader reader)
        {
            if (!reader.IsGivenLine && !reader.IsAndLine && !reader.IsButLine)
            {
                throw new NotSupportedException(
                          $"Unrecognised step type on line '{reader.CurrentLineTrimmed}'. Only Given, And or But steps can be used in a Background.");
            }

            var stepTitle = reader.CurrentLineTrimmed;

            reader.ReadNextLine();

            var multiLineString = MultiLineStringParser.ParseMultiLineStringIfPresent(reader);

            var dataTable = DataTable.Empty;

            if (reader.IsTableLine)
            {
                dataTable = DataTableParser.ParseDataTable(reader);
            }

            return(new GivenStep(
                       stepTitle,
                       dataTable,
                       multiLineString));
        }
コード例 #5
0
        public static ScenarioOutline ParseScenarioOutline(LineReader reader, IEnumerable <Tag> tags)
        {
            var scenarioOutlineTitle = reader.CurrentLineScenarioOutlineTitle;
            var scenarioOutlineStartingLineNumber = reader.CurrentLineNumber;
            var steps    = new List <IStep>();
            var examples = DataTable.Empty;

            var alreadyConsumedExamples = false;

            reader.ReadNextLine();
            while (reader.IsStepLine)
            {
                steps.Add(
                    ParseStep(reader, steps.LastOrDefault()));

                if (reader.IsExamplesStartLine)
                {
                    if (alreadyConsumedExamples)
                    {
                        throw new InvalidGherkinSyntaxException(
                                  "A Scenario Outline can only contain one Examples section.",
                                  reader.CurrentLineNumber);
                    }

                    examples = ParseExamples(reader);
                    alreadyConsumedExamples = true;
                }

                if (!reader.IsEndOfFile &&
                    !reader.IsStepLine &&
                    !reader.IsScenarioStartLine &&
                    !reader.IsScenarioOutlineStartLine &&
                    !reader.IsTagLine &&
                    !reader.IsRuleStartLine)
                {
                    throw new InvalidGherkinSyntaxException(
                              $"Expected a step (Given, When, Then, And, But), a Scenario, a Scenario Outline, a Rule or a tag, but found '{reader.CurrentLineTrimmed}'.",
                              reader.CurrentLineNumber);
                }
            }

            if (examples.Rows.Count < 2)
            {
                throw new InvalidGherkinSyntaxException(
                          $"Scenario Outline \"{scenarioOutlineTitle}\" is missing an Examples table, or the Examples table does not contain a column-header row and at least one data row.",
                          reader.CurrentLineNumber);
            }

            return(new ScenarioOutline(
                       scenarioOutlineTitle,
                       steps,
                       examples,
                       scenarioOutlineStartingLineNumber,
                       tags));
        }
コード例 #6
0
        private void ParseNewRule(IEnumerable <Tag> tags)
        {
            AddRuleIfNeeded();

            isInRule                   = true;
            activeScenariosList        = new List <Scenario>();
            activeScenarioOutlinesList = new List <ScenarioOutline>();
            ruleTags                   = tags;

            ruleTitle = reader.CurrentLineRuleTitle;

            reader.ReadNextLine();
            ruleBackground = BackgroundParser.ParseBackgroundIfPresent(reader);
        }
コード例 #7
0
        public static DataTable ParseDataTable(LineReader reader)
        {
            var rows = new List <DataTableRow>();

            string[] columnNames = null;

            while (reader.IsTableLine)
            {
                rows.Add(ParseDataTableRow(reader, ref columnNames));
                reader.ReadNextLine();
            }
            ;

            return(new DataTable(rows));
        }
コード例 #8
0
        private static IStep ParseStep(LineReader reader, Func <DataTable, string, IStep> stepFactory)
        {
            reader.ReadNextLine();

            var multiLineString = MultiLineStringParser.ParseMultiLineStringIfPresent(reader);

            var dataTable = DataTable.Empty;

            if (reader.IsTableLine)
            {
                dataTable = DataTableParser.ParseDataTable(reader);
            }

            return(stepFactory(dataTable, multiLineString));
        }
コード例 #9
0
        private static Background ParseBackground(LineReader reader)
        {
            var startingLineNumber = reader.CurrentLineNumber;
            var steps = new List <GivenStep>();

            reader.ReadNextLine();
            while (reader.IsStepLine)
            {
                if (!(reader.IsAndLine || reader.IsButLine || reader.IsGivenLine))
                {
                    throw new InvalidGherkinSyntaxException(
                              $"Backgrounds can only contain Given, And or But steps.  Found '{reader.CurrentLineTrimmed}' instead on line {reader.CurrentLineNumber}.",
                              reader.CurrentLineNumber);
                }

                steps.Add(
                    ParseBackgroundStep(reader));
            }

            return(new Background(steps, startingLineNumber));
        }
コード例 #10
0
        public static string ParseMultiLineStringIfPresent(LineReader reader)
        {
            if (!reader.IsMultiLineStringStartOrEndLine)
            {
                return(null);
            }

            var stringBuilder = new StringBuilder();

            var blockIndentation = reader.CurrentLineIndentation;

            reader.ReadNextLineRaw();

            while (!reader.IsMultiLineStringStartOrEndLine)
            {
                if (stringBuilder.Length > 0)
                {
                    stringBuilder.AppendLine();
                }

                var line = reader.CurrentLineUntrimmed;
                if (!line.StartsWith(blockIndentation))
                {
                    throw new InvalidGherkinSyntaxException(
                              $"All lines of a multi-line string must have the same indentation as the starting quote marks, or must be indented further. Line {reader.CurrentLineNumber} contains indentation that is less than the opening quote mark line. This exception can also be thrown if there are different tabs and spaces on different lines of the block.",
                              reader.CurrentLineNumber);
                }

                line = line.Substring(blockIndentation.Length);
                stringBuilder.Append(line);

                reader.ReadNextLineRaw();
            }

            reader.ReadNextLine();

            return(stringBuilder.ToString());
        }
コード例 #11
0
 private static DataTable ParseExamples(LineReader reader)
 {
     reader.ReadNextLine();
     return(DataTableParser.ParseDataTable(reader));
 }