LSTANCZYK
10/17/2014 - 2:53 PM

TagGeneratorPlugin.cs

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using BoDi;
using TechTalk.SpecFlow.Generator;
using TechTalk.SpecFlow.Generator.Configuration;
using TechTalk.SpecFlow.Generator.Plugins;
using TechTalk.SpecFlow.Generator.UnitTestConverter;
using TechTalk.SpecFlow.Generator.UnitTestProvider;
using TechTalk.SpecFlow.Parser.SyntaxElements;
using TechTalk.SpecFlow.Utils;

// [assembly: TechTalk.SpecFlow.Infrastructure.GeneratorPlugin(typeof(CodeGenerator.Generator.SpecFlowPlugin.TagGeneratorPlugin))]

namespace CodeGenerator.Generator.SpecFlowPlugin
{
    public class TagGeneratorPlugin : IGeneratorPlugin
    {

        public void RegisterConfigurationDefaults(SpecFlowProjectConfiguration specFlowConfiguration)
        {

        }

        public void RegisterCustomizations(ObjectContainer container, SpecFlowProjectConfiguration generatorConfiguration)
        {

        }

        public void RegisterDependencies(ObjectContainer container)
        {
            container.RegisterTypeAs<TagFeatureGeneratorProvider, IFeatureGeneratorProvider>("default");
        }
    }

    public class TagFeatureGeneratorProvider : IFeatureGeneratorProvider
    {
        private readonly ObjectContainer _container;

        public TagFeatureGeneratorProvider(ObjectContainer container)
        {
            _container = container;
        }

        public int Priority
        {
            get { return int.MaxValue; }
        }

        public bool CanGenerate(Feature feature)
        {
            return true;
        }

        public IFeatureGenerator CreateGenerator(Feature feature)
        {
            return _container.Resolve<TagFeatureGenerator>();
        }
    }

    public class TagFeatureGenerator : IFeatureGenerator
    {
        private const string UserAgent = "user-agent";

        private readonly UnitTestFeatureGenerator _unitTestFeatureGenerator;

        public TagFeatureGenerator(IUnitTestGeneratorProvider testGeneratorProvider, CodeDomHelper codeDomHelper, GeneratorConfiguration generatorConfiguration, IDecoratorRegistry decoratorRegistry)
        {
            _unitTestFeatureGenerator = new UnitTestFeatureGenerator(testGeneratorProvider, codeDomHelper, generatorConfiguration, decoratorRegistry);
        }

        public CodeNamespace GenerateUnitTestFixture(Feature feature, string testClassName, string targetNamespace)
        {
            if (feature.Scenarios != null)
            {
                feature.Scenarios = feature.Scenarios
                    .Where(s => s.Tags == null || s.Tags.Count(PatternPredicate) < 2)
                    .Concat(GetUserAgentsScenarios(feature)).ToArray();
            }

            return _unitTestFeatureGenerator.GenerateUnitTestFixture(feature, testClassName, targetNamespace);
        }

        private static IEnumerable<Scenario> GetUserAgentsScenarios(Feature feature)
        {
            var scenariosWithMultiple =
               feature.Scenarios.Where(s => s.Tags != null && s.Tags.Count(PatternPredicate) > 1);

            foreach (var scenario in scenariosWithMultiple)
            {
                if (string.IsNullOrEmpty(scenario.Title))
                {
                    throw new TestGeneratorException("The scenario must have a title specified.");
                }

                int index = 0;

                foreach (var tag in scenario.Tags.Where(PatternPredicate))
                {
                    var newScenario = CopyScenario(scenario, tag, index++);

                    yield return newScenario;
                }
            }
        }

        private static Scenario CopyScenario(Scenario scenario, Tag userAgentTag, int index)
        {
            var title = string.Concat(scenario.Title, userAgentTag.Name, index);
            var tags = new Tags(scenario.Tags.Where(t => !PatternPredicate(t)).Concat(new[] { userAgentTag }).ToArray());
            var steps = new ScenarioSteps(scenario.Steps.Select(step => step.Clone()).ToArray());

            var scenarioOutline = scenario as ScenarioOutline;

            if (scenarioOutline != null)
            {
                return new ScenarioOutline(scenario.Keyword, title, scenario.Description, tags, steps,
                                           new Examples(scenarioOutline.Examples.ExampleSets));
            }

            return new Scenario(scenario.Keyword, title, scenario.Description, tags, steps);
        }

        private static bool PatternPredicate(Tag tag)
        {
            if (tag == null || tag.Name == null)
            {
                return false;
            }

            return tag.Name.StartsWith(UserAgent, StringComparison.OrdinalIgnoreCase);
        }
    }
}