private static void AddCosmosDbContainerForCleanup(
            SpecFlowContext context,
            Container container,
            Database?database = null)
        {
            if (!context.ContainsKey(CosmosDbContainersToDelete))
            {
                context.Set(new List <Container>(), CosmosDbContainersToDelete);
            }

            if (database is not null)
            {
                if (!context.ContainsKey(CosmosDbDatabasesToDelete))
                {
                    context.Set(new List <Database>(), CosmosDbDatabasesToDelete);
                }

                List <Database> databasesToDelete = context.Get <List <Database> >(CosmosDbDatabasesToDelete);
                databasesToDelete.Add(database);
            }

            List <Container> containers = context.Get <List <Container> >(CosmosDbContainersToDelete);

            containers.Add(container);
        }
        private static void AddDefaultCollectionProcessorFactories(this SpecFlowContext context)
        {
            const string defaultKey = "__defaultCollectionProcessorFactoriesAdded__";

            if (context.ContainsKey(defaultKey) && context.GetEx <bool>(defaultKey))
            {
                return;
            }

            context.Set(true, defaultKey);

            var lookup        = new Dictionary <string, CollectionProcessorFactory>(StringComparer.OrdinalIgnoreCase);
            var listProcessor = new ListProcessorFactory(context);

            AddToLookup(new ArrayProcessorFactory(context));
            AddToLookup(new EnumerableProcessorFactory(context));
            AddToLookup(new ICollectionProcessorFactory(context));
            AddToLookup(new IListProcessorFactory(context));
            AddToLookup(new IReadOnlyCollectionProcessorFactory(context));
            AddToLookup(new IReadOnlyListProcessorFactory(context));
            AddToLookup(listProcessor);

            SetCollectionProcessorFactoryLookup(context, lookup);
            SetDefaultCollectionProcessorFactory(context, listProcessor);

            void AddToLookup(CollectionProcessorFactory factory)
            => factory.CollectionKindNames.ForEach(n => lookup.Add(n, factory));
        }
        ///// <summary>Updates the context value associated with a specified key.</summary>
        ///// <typeparam name="T">The type of the value to update.</typeparam>
        ///// <param name="context">The context.</param>
        ///// <param name="key">The key.</param>
        ///// <param name="updater">The action to use to update the value.</param>
        ///// <param name="defaultValue">The value to use if the specified key is not found.</param>
        ///// <returns>The updated value.</returns>
        //public static void Update<T>(this SpecFlowContext context, string key, Action<T> updater, T defaultValue)
        //{
        //    key = NormalizeKey<T>(context, key);

        //    if (!context.ContainsKey(key))
        //        context.Set(defaultValue, key);

        //    Update(context, key, updater);
        //}

        ///// <summary>Updates the context value associated with a specified key.</summary>
        ///// <typeparam name="T">The type of the value to update.</typeparam>
        ///// <param name="context">The context.</param>
        ///// <param name="key">The key.</param>
        ///// <param name="updater">The function to use to update the value.</param>
        ///// <param name="defaultValueFactory">Factory to use to get a default value if the specified key is not found.</param>
        ///// <returns>The updated value.</returns>
        //public static T Update<T>(this SpecFlowContext context, string key, Func<T, T> updater, Func<T> defaultValueFactory)
        //{
        //    key = NormalizeKey<T>(context, key);

        //    if (!context.ContainsKey(key))
        //        context.Set(defaultValueFactory(), key);

        //    return Update(context, key, updater);
        //}

        /// <summary>Updates the context value associated with a specified key.</summary>
        /// <typeparam name="T">The type of the value to update.</typeparam>
        /// <param name="context">The context.</param>
        /// <param name="key">The key.</param>
        /// <param name="updater">The action to use to update the value.</param>
        /// <param name="defaultValueFactory">Factory to use to get a default value if the specified key is not found.</param>
        /// <returns>The updated value.</returns>
        public static void Update <T>(this SpecFlowContext context, string key, Action <T> updater, Func <T> defaultValueFactory)
        {
            key = NormalizeKey <T>(context, key);

            if (!context.ContainsKey(key))
            {
                context.Set(defaultValueFactory(), key);
            }

            Update(context, key, updater);
        }
        /// <summary>Updates the context value associated with a specified key.</summary>
        /// <typeparam name="T">The type of the value to update.</typeparam>
        /// <param name="context">The context.</param>
        /// <param name="key">The key.</param>
        /// <param name="updater">The function to use to update the value.</param>
        /// <param name="defaultValue">The value to use if the specified key is not found.</param>
        /// <returns>The updated value.</returns>
        public static T Update <T>(this SpecFlowContext context, string key, Func <T, T> updater, T defaultValue)
        {
            key = NormalizeKey <T>(context, key);

            if (!context.ContainsKey(key))
            {
                context.Set(defaultValue, key);
            }

            return(Update(context, key, updater));
        }
        protected static void CleanUpTestSession(SpecFlowContext context)
        {
            if (!context.ContainsKey("container_scope"))
            {
                return;
            }
            var scope = context.Get <ILifetimeScope>("container_scope");

            context.Remove("container_scope");
            scope.Dispose();
        }
 private static async Task TeardownCosmosDBDatabasesCoreAsync(
     SpecFlowContext context)
 {
     if (context.ContainsKey(CosmosDbDatabasesToDelete))
     {
         await Task.WhenAll(context.Get <List <Database> >(CosmosDbDatabasesToDelete)
                            .DistinctBy(database => database.Id)
                            .Select(async database => await database.DeleteAsync().ConfigureAwait(false)))
         .ConfigureAwait(false);
     }
 }
        private static void AddDefaultValueProcessors(this SpecFlowContext context)
        {
            const string defaultKey = "__defaultValueProcessorsAdded__";

            if (context.ContainsKey(defaultKey) && context.GetEx <bool>(defaultKey))
            {
                return;
            }

            context.Set(true, defaultKey);

            var typeLookup = new Dictionary <Type, IValueProcessor>();
            var lookup     = new Dictionary <string, IValueProcessor>(StringComparer.OrdinalIgnoreCase);
            var order      = new List <IValueProcessor>();

            // Auto determine.
            Add(new BoolProcessor(context));
            Add(new IntProcessor(context));
            Add(new LongProcessor(context));
            Add(new ULongProcessor(context));
            Add(new DoubleProcessor(context));
            Add(new DurationProcessor(context));
            Add(new DateTimeProcessor(context));
            Add(new DateTimeOffsetProcessor(context));
            Add(new StringProcessor(context));
            Add(new ObjectProcessor(context));

            // Need to specify type to use.
            Add(new ByteProcessor(context));
            Add(new CharProcessor(context));
            Add(new SByteProcessor(context));
            Add(new UIntProcessor(context));
            Add(new ShortProcessor(context));
            Add(new UShortProcessor(context));
            Add(new FloatProcessor(context));
            Add(new DecimalProcessor(context));
            Add(new TimeSpanProcessor(context));

            SetValueProcessorLookup(context, lookup);
            SetValueProcessorLookup(context, typeLookup);
            SetValueProcessorOrder(context, order);

            void Add(IValueProcessor processor)
            {
                typeLookup.Add(processor.DataType, processor);
                processor.DataTypeNames.ForEach(n => lookup.Add(n, processor));
                order.Add(processor);
            }
        }
        public static void AddFeatureFailure(this SpecFlowContext context, string messageContext, string message)
        {
            Dictionary <string, string> failures;

            if (context.ContainsKey(constants.featureFailure))
            {
                failures = (Dictionary <string, string>)context[constants.featureFailure];
            }
            else
            {
                failures = new Dictionary <string, string>();
            }
            failures.Add(messageContext, message);
            context[constants.featureFailure] = failures;
        }
 private static async Task TeardownCosmosDBContainersCoreAsync(SpecFlowContext context)
 {
     if (context.ContainsKey(CosmosDbContainersToDelete))
     {
         // We run this way not so much because we want to delete everything at once,
         // but because this way we do actually attempt every deletion, and then report
         // any failures at the end in one big AggregateException.
         await Task.WhenAll(context.Get <List <Container> >(CosmosDbContainersToDelete)
                            .Select(async container =>
         {
             try
             {
                 await container.DeleteContainerAsync().ConfigureAwait(false);
             }
             catch (InvalidOperationException x)
                 when(x.Message == "Unable to use database throughput in a database that has already been created.")
                 {
                     // Swallow this because it's an expected exception in certain test scenarios.
                 }
         }))
         .ConfigureAwait(false);
     }
 }
 public static Dictionary <string, string> GetFeatureFailure(this SpecFlowContext context)
 {
     return(context.ContainsKey(constants.featureFailure) ? (Dictionary <string, string>)context[constants.featureFailure] : new Dictionary <string, string>());
 }