public override Regex GetTestPattern(ReferencedFile referencedFile, string testFileText, ChutzpahTestSettingsFile settings)
        {
            var mochaFrameworkDefinition = MochaDefinition.GetInterfaceType(settings, referencedFile.Path, testFileText);
            var isCoffeeFile = referencedFile.Path.EndsWith(Constants.CoffeeScriptExtension, StringComparison.OrdinalIgnoreCase);
            switch (mochaFrameworkDefinition)
            {
                case Constants.MochaQunitInterface:

                    return isCoffeeFile ? RegexPatterns.MochaTddOrQunitTestRegexCoffeeScript : RegexPatterns.MochaTddOrQunitTestRegexJavaScript;

                case Constants.MochaBddInterface:

                    return isCoffeeFile ? RegexPatterns.MochaBddTestRegexCoffeeScript : RegexPatterns.MochaBddTestRegexJavaScript;

                case Constants.MochaTddInterface:

                    return isCoffeeFile ? RegexPatterns.MochaTddOrQunitTestRegexCoffeeScript : RegexPatterns.MochaTddOrQunitTestRegexJavaScript;

                case Constants.MochaExportsInterface:

                    return isCoffeeFile ? RegexPatterns.MochaExportsTestRegexCoffeeScript : RegexPatterns.MochaExportsTestRegexJavaScript;

                default:
                    return isCoffeeFile ? RegexPatterns.MochaBddTestRegexCoffeeScript : RegexPatterns.MochaBddTestRegexJavaScript;
            }
        }
Example #2
0
        public static string GetInterfaceType(ChutzpahTestSettingsFile chutzpahTestSettings, string testFilePath, string testFileText)
        {
            if(!string.IsNullOrEmpty(chutzpahTestSettings.MochaInterface) 
                && knownInterfaces.Contains(chutzpahTestSettings.MochaInterface,StringComparer.OrdinalIgnoreCase))
            {
                return chutzpahTestSettings.MochaInterface.ToLowerInvariant();
            }

            var isCoffeeFile = testFilePath.EndsWith(Constants.CoffeeScriptExtension, StringComparison.OrdinalIgnoreCase);

            if (isCoffeeFile)
            {
                if (RegexPatterns.MochaBddTestRegexCoffeeScript.IsMatch(testFileText)) return Constants.MochaBddInterface;
                if (RegexPatterns.MochaTddOrQunitTestRegexCoffeeScript.IsMatch(testFileText))
                {
                    return RegexPatterns.MochaTddSuiteRegexCoffeeScript.IsMatch(testFileText) ? Constants.MochaTddInterface : Constants.MochaQunitInterface;
                }
                if (RegexPatterns.MochaExportsTestRegexCoffeeScript.IsMatch(testFileText)) return Constants.MochaExportsInterface;
            }
            else
            {
                if (RegexPatterns.MochaBddTestRegexJavaScript.IsMatch(testFileText)) return Constants.MochaBddInterface;
                if (RegexPatterns.MochaTddOrQunitTestRegexJavaScript.IsMatch(testFileText))
                {
                    return RegexPatterns.MochaTddSuiteRegexJavaScript.IsMatch(testFileText) ? Constants.MochaTddInterface : Constants.MochaQunitInterface;
                }
                if (RegexPatterns.MochaExportsTestRegexJavaScript.IsMatch(testFileText)) return Constants.MochaExportsInterface;
            }

            return Constants.MochaBddInterface;
        }
Example #3
0
        public void Process(IFrameworkDefinition frameworkDefinition, ReferencedFile referencedFile, string testFileText, ChutzpahTestSettingsFile settings)
        {
            if (!referencedFile.IsFileUnderTest)
            {
                return;
            }

            var regExp = settings.TestPatternRegex ?? GetTestPattern(referencedFile,testFileText, settings);

            var lines = fileSystem.GetLines(referencedFile.Path);
            int lineNum = 1;

            foreach (var line in lines)
            {
                var match = regExp.Match(line);

                while (match.Success)
                {
                    var testNameGroup = match.Groups["TestName"];
                    var testName = testNameGroup.Value;

                    if (!string.IsNullOrWhiteSpace(testName))
                    {
                        referencedFile.FilePositions.Add(lineNum, testNameGroup.Index + 1, testName);
                    }

                    match = match.NextMatch();
                }

                lineNum++;
            }
        }
        private string GetTestHarnessTemplatePath(IFrameworkDefinition definition, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            string templatePath = null;

            if (!string.IsNullOrEmpty(chutzpahTestSettings.CustomTestHarnessPath))
            {
                // If CustomTestHarnessPath is absolute path then Path.Combine just returns it
                var harnessPath = Path.Combine(chutzpahTestSettings.SettingsFileDirectory, chutzpahTestSettings.CustomTestHarnessPath);
                var fullPath = fileProbe.FindFilePath(harnessPath);
                if (fullPath != null)
                {
                    ChutzpahTracer.TraceInformation("Using Custom Test Harness from {0}", fullPath);
                    templatePath = fullPath;
                }
                else
                {
                    ChutzpahTracer.TraceError("Cannot find Custom Test Harness at {0}", chutzpahTestSettings.CustomTestHarnessPath);
                }
            }

            if (templatePath == null)
            {
                templatePath = fileProbe.GetPathInfo(Path.Combine(Constants.TestFileFolder, definition.GetTestHarness(chutzpahTestSettings))).FullPath;

                ChutzpahTracer.TraceInformation("Using builtin Test Harness from {0}", templatePath);
            }
            return templatePath;
        }
 private void SetupAmdPathsIfNeeded(ChutzpahTestSettingsFile chutzpahTestSettings, List<ReferencedFile> referencedFiles, string testHarnessDirectory)
 {
     if (chutzpahTestSettings.TestHarnessReferenceMode == TestHarnessReferenceMode.AMD)
     {
         referenceProcessor.SetupAmdFilePaths(referencedFiles, testHarnessDirectory, chutzpahTestSettings);
     }
 }
        private void ProcessTransforms(ChutzpahTestSettingsFile settings, TestCaseSummary overallSummary, TransformResult results)
        {
            // Do this here per settings file in case an individual transformer has any associated state
            // - we want them fresh
            var knownTransforms =
                transformerProvider
                .GetTransformers(fileSystem)
                .ToDictionary(x => x.Name, x => x, StringComparer.InvariantCultureIgnoreCase);

            foreach (var transformConfig in settings.Transforms)
            {
                SummaryTransformer transform = null;
                if (knownTransforms.TryGetValue(transformConfig.Name, out transform))
                {
                    var outputPath = transformConfig.Path;
                    if (!fileSystem.IsPathRooted(outputPath) && !string.IsNullOrWhiteSpace(transformConfig.SettingsFileDirectory))
                    {
                        outputPath = fileSystem.GetFullPath(Path.Combine(transformConfig.SettingsFileDirectory, outputPath));
                    }

                    // TODO: In future, this would ideally split out the summary to just those parts
                    // relevant to the files associated with the settings file being handled
                    transform.Transform(overallSummary, outputPath);

                    results.AddResult(transform.Name, outputPath);
                }
            }
        }
 public override Regex GetTestPattern(ReferencedFile referencedFile, string testFileText, ChutzpahTestSettingsFile settings)
 {
     var isCoffeeFile = referencedFile.Path.EndsWith(Constants.CoffeeScriptExtension, StringComparison.OrdinalIgnoreCase);
     var regExp = isCoffeeFile
                      ? RegexPatterns.QUnitTestRegexCoffeeScript
                      : RegexPatterns.QUnitTestRegexJavaScript;
     return regExp;
 }
        public override IDictionary<string, string> GenerateCompiledSources(IEnumerable<ReferencedFile> referencedFiles, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            var compiledMap = (from referencedFile in referencedFiles
                               let content = fileSystem.GetText(referencedFile.Path)
                               let jsText = GetOrAddCompiledToCache(content, referencedFile.Path)
                               select new { FileName = referencedFile.Path, Content = jsText })
                              .ToDictionary(x => x.FileName, x => x.Content);

            return compiledMap;
        }
Example #9
0
        public TestHarness(ChutzpahTestSettingsFile chutzpahTestSettings, TestOptions testOptions, IEnumerable<ReferencedFile> referencedFiles, IFileSystemWrapper fileSystem)
        {
            this.chutzpahTestSettings = chutzpahTestSettings;
            this.testOptions = testOptions;
            this.referencedFiles = referencedFiles;
            this.fileSystem = fileSystem;

            BuildTags(referencedFiles);
            CleanupTestHarness();
        }
        public void Will_set_settings_file_directory()
        {
            var mockFileProbe = new Mock<IFileProbe>();
            var mockSerializer = new Mock<IJsonSerializer>();
            var settings = new ChutzpahTestSettingsFile();
            mockFileProbe.Setup(x => x.FindTestSettingsFile(It.IsAny<string>())).Returns(@"C:\settingsDir\settingsFile.json");
            mockSerializer.Setup(x => x.DeserializeFromFile<ChutzpahTestSettingsFile>(It.IsAny<string>())).Returns(settings);

            ChutzpahTestSettingsFile.Read("dir", mockFileProbe.Object, mockSerializer.Object);

            Assert.Equal(@"C:\settingsDir", settings.SettingsFileDirectory);
        }
        public void Will_set_custom_harness_directory_based_relative_to_settings_file_directory()
        {
            var mockFileProbe = new Mock<IFileProbe>();
            var mockSerializer = new Mock<IJsonSerializer>();
            var settings = new ChutzpahTestSettingsFile { TestHarnessLocationMode = TestHarnessLocationMode.Custom, TestHarnessDirectory = "custom" };
            mockFileProbe.Setup(x => x.FindTestSettingsFile(It.IsAny<string>())).Returns(@"C:\settingsDir2\settingsFile.json");
            mockFileProbe.Setup(x => x.FindFolderPath(@"C:\settingsDir2\custom")).Returns(@"customPath");
            mockSerializer.Setup(x => x.DeserializeFromFile<ChutzpahTestSettingsFile>(It.IsAny<string>())).Returns(settings);

            ChutzpahTestSettingsFile.Read("dir2", mockFileProbe.Object, mockSerializer.Object);

            Assert.Equal(@"customPath", settings.TestHarnessDirectory);
        }
        public void Will_get_cached_settings_given_same_starting_directory()
        {
            var mockFileProbe = new Mock<IFileProbe>();
            var mockSerializer = new Mock<IJsonSerializer>();
            var settings = new ChutzpahTestSettingsFile();
            mockFileProbe.Setup(x => x.FindTestSettingsFile("dir3")).Returns(@"C:\settingsDir3\settingsFile.json");
            mockSerializer.Setup(x => x.DeserializeFromFile<ChutzpahTestSettingsFile>(It.IsAny<string>())).Returns(settings);
            ChutzpahTestSettingsFile.Read("dir3", mockFileProbe.Object, mockSerializer.Object);

            var cached = ChutzpahTestSettingsFile.Read("dir3", mockFileProbe.Object, mockSerializer.Object);

            Assert.Equal(@"C:\settingsDir3", cached.SettingsFileDirectory);
        }
        /// <summary>
        /// Scans the test file extracting all referenced files from it.
        /// </summary>
        /// <param name="referencedFiles">The list of referenced files</param>
        /// <param name="definition">Test framework defintition</param>
        /// <param name="textToParse">The content of the file to parse and extract from</param>
        /// <param name="currentFilePath">Path to the file under test</param>
        /// <param name="chutzpahTestSettings"></param>
        /// <returns></returns>
        public void GetReferencedFiles(List<ReferencedFile> referencedFiles, IFrameworkDefinition definition, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            var filesUnderTests = referencedFiles.Where(x => x.IsFileUnderTest).ToList();

            var referencePathSet = new HashSet<string>(referencedFiles.Select(x => x.Path), StringComparer.OrdinalIgnoreCase);

            // Process the references that the user specifies in the chutzpah settings file
            foreach (var reference in chutzpahTestSettings.References.Where(reference => reference != null))
            {
                // The path we assume default to the chuzpah.json directory if the Path property is not set
                var referencePath = string.IsNullOrEmpty(reference.Path) ? reference.SettingsFileDirectory : reference.Path;

                ProcessFilePathAsReference(
                    referencePathSet,
                    definition,
                    reference.SettingsFileDirectory,
                    chutzpahTestSettings,
                    referencePath,
                    referencedFiles,
                    new ReferencePathSettings(reference));
            }

            // Process the references defined using /// <reference comments in test file contents
            foreach (var fileUnderTest in filesUnderTests)
            {
                var testFileText = fileSystem.GetText(fileUnderTest.Path);

                definition.Process(fileUnderTest, testFileText, chutzpahTestSettings);

                if (fileUnderTest.ExpandReferenceComments)
                {
                    var result = GetReferencedFiles(
                        referencePathSet,
                        definition,
                        testFileText,
                        fileUnderTest.Path,
                        chutzpahTestSettings);


                    var flattenedReferenceTree = from root in result
                                                 from flattened in FlattenReferenceGraph(root)
                                                 select flattened;

                    referencedFiles.AddRange(flattenedReferenceTree);
                }
            }
        }
        /// <summary>
        /// This will get called for the test file and all referenced files. 
        /// If the referenced file can be handled it generate a .js file and sets to the reference files generatedfilepath and adds the new file path to the temporary file collection
        /// If it can't handle the file it does nothing
        /// </summary>
        public virtual void Generate(IEnumerable<ReferencedFile> referencedFiles, IList<string> temporaryFiles, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            // Filter down to just the referenced files this generator supports
            referencedFiles = referencedFiles.Where(CanHandleFile).ToList();

            if (referencedFiles.Any())
            {
                var compiledMap = GenerateCompiledSources(referencedFiles, chutzpahTestSettings);

                foreach (var referencedFile in referencedFiles)
                {
                    if (!compiledMap.ContainsKey(referencedFile.Path)) continue;

                    var jsText = compiledMap[referencedFile.Path];
                    WriteGeneratedReferencedFile(referencedFile, jsText, temporaryFiles);
                }
            }
        }
        public override IDictionary<string, string> GenerateCompiledSources(IEnumerable<ReferencedFile> referencedFiles, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            var referenceList = (from referencedFile in referencedFiles
                                 let content = fileSystem.GetText(referencedFile.Path)
                                 select new TypeScriptFile { FileName = referencedFile.Path, Content = content }).ToList();

            InsertLibDeclarationFile(referenceList);

            var compiledMap = new Dictionary<string, string>();
            var needsCompileMap = referenceList.ToDictionary(x => x.FileName, x => x.Content);
            if (needsCompileMap.Count > 0)
            {
                var needsCompileMapJson = jsonSerializer.Serialize(needsCompileMap);

                var resultJson = typeScriptEngine.Compile(needsCompileMapJson, chutzpahTestSettings.TypeScriptCodeGenTarget.ToString(), chutzpahTestSettings.TypeScriptModuleKind.ToString());
                compiledMap = jsonSerializer.Deserialize<Dictionary<string, string>>(resultJson);
            }

            return compiledMap.ToDictionary(x => ToFilePath(x.Key), x => x.Value);
        }
        public void Process(IFrameworkDefinition frameworkDefinition, ReferencedFile referencedFile, string testFileText, ChutzpahTestSettingsFile settings)
        {
            if (!referencedFile.IsFileUnderTest)
            {
                return;
            }

            var regExp = settings.TestPatternRegex ?? GetTestPattern(referencedFile, testFileText, settings);


            int lineNum = 1;
            using (var reader = new StringReader(testFileText))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    var match = regExp.Match(line);

                    while (match.Success)
                    {
                        var testNameGroup = match.Groups["TestName"];
                        var testName = testNameGroup.Value;

                        if (!string.IsNullOrWhiteSpace(testName))
                        {
                            referencedFile.FilePositions.Add(lineNum, testNameGroup.Index + 1, testName);
                        }

                        match = match.NextMatch();
                    }

                    lineNum++;
                }
            }

        }
        /// <summary>
        /// Tests whether the given file is the framework itself or one of its core dependencies.
        /// </summary>
        /// <param name="referenceFileName">File name of a reference to test.</param>
        /// <param name="testSettingsFile"></param>
        /// <returns>True if the file is a framework dependency, otherwise false.</returns>
        public virtual bool ReferenceIsDependency(string referenceFileName, ChutzpahTestSettingsFile testSettingsFile)
        {
            string fileName = Path.GetFileName(referenceFileName);
            if (!string.IsNullOrEmpty(fileName))
            {
                return GetFileDependencies(testSettingsFile).Any(x => fileName.Equals(Path.GetFileName(x), StringComparison.InvariantCultureIgnoreCase));
            }

            return false;
        }
 /// <summary>
 /// Gets the file name of the JavaScript test runner to use with the framework.
 /// </summary>
 /// <param name="chutzpahTestSettings"></param>
 public virtual string GetTestRunner(ChutzpahTestSettingsFile chutzpahTestSettings)
 {
     return @"JSRunners\" + FrameworkKey + "Runner.js";
 }
 /// <summary>
 /// Gets the file name of the test harness to use with the framework.
 /// </summary>
 /// <param name="chutzpahTestSettings"></param>
 public abstract string GetTestHarness(ChutzpahTestSettingsFile chutzpahTestSettings);
 /// <summary>
 /// Gets a list of file dependencies to bundle with the framework test harness.
 /// </summary>
 /// <param name="chutzpahTestSettings"></param>
 public abstract IEnumerable<string> GetFileDependencies(ChutzpahTestSettingsFile chutzpahTestSettings);
 public virtual string GetBlanketScriptName(ChutzpahTestSettingsFile chutzpahTestSettings)
 {
     return "blanket_" + FrameworkKey + ".js";
 }
 public virtual Dictionary<string, string> GetFrameworkReplacements(ChutzpahTestSettingsFile chutzpahTestSettings, string testFilePath, string testFileText)
 {
     return new Dictionary<string, string>();
 }
 /// <summary>
 /// Processes a referenced file according to the framework's needs.
 /// </summary>
 /// <param name="referencedFile">A referenced file to process.</param>
 /// <param name="testFileText"></param>
 /// <param name="settings"></param>
 public void Process(ReferencedFile referencedFile, string testFileText, ChutzpahTestSettingsFile settings)
 {
     if (FileProcessors != null)
     {
         foreach (IReferencedFileProcessor item in FileProcessors)
         {
             item.Process(this, referencedFile, testFileText, settings);
         }
     }
 }
        /// <summary>
        /// Merge a selection of settings from a parent file into the current one.
        /// This merge will work as follows
        /// 1. For basic properties the child's property wins if it is different than the default
        /// 2. For complex objects the child's property wins if it is not null
        /// 3. For lists the childs items get added to the parents
        /// </summary>
        /// <param name="parent"></param>
        public ChutzpahTestSettingsFile InheritFrom(ChutzpahTestSettingsFile parent)
        {
            if (parent == null || this.IsDefaultSettings)
            {
                return(this);
            }


            this.References           = parent.References.Concat(this.References).ToList();
            this.CodeCoverageIncludes = parent.CodeCoverageIncludes.Concat(this.CodeCoverageIncludes).ToList();
            this.CodeCoverageExcludes = parent.CodeCoverageExcludes.Concat(this.CodeCoverageExcludes).ToList();
            this.CodeCoverageIgnores  = parent.CodeCoverageIgnores.Concat(this.CodeCoverageIgnores).ToList();
            this.Transforms           = parent.Transforms.Concat(this.Transforms).ToList();

            if (this.Compile == null)
            {
                this.Compile = parent.Compile;
            }


            this.AMDBaseUrl      = this.AMDBaseUrl == null ? parent.AMDBaseUrl : this.AMDBaseUrl;
            this.AMDAppDirectory = this.AMDAppDirectory == null ? parent.AMDAppDirectory : this.AMDAppDirectory;
            this.CodeCoverageSuccessPercentage = this.CodeCoverageSuccessPercentage == null ? parent.CodeCoverageSuccessPercentage : this.CodeCoverageSuccessPercentage;
            this.CustomTestHarnessPath         = this.CustomTestHarnessPath == null ? parent.CustomTestHarnessPath : this.CustomTestHarnessPath;
            this.CodeCoverageExecutionMode     = this.CodeCoverageExecutionMode == null ? parent.CodeCoverageExecutionMode : this.CodeCoverageExecutionMode;
            this.Framework                   = this.Framework == null ? parent.Framework : this.Framework;
            this.FrameworkVersion            = this.FrameworkVersion == null ? parent.FrameworkVersion : this.FrameworkVersion;
            this.MochaInterface              = this.MochaInterface == null ? parent.MochaInterface : this.MochaInterface;
            this.RootReferencePathMode       = this.RootReferencePathMode == null ? parent.RootReferencePathMode : this.RootReferencePathMode;
            this.TestFileTimeout             = this.TestFileTimeout == null ? parent.TestFileTimeout : this.TestFileTimeout;
            this.TestHarnessReferenceMode    = this.TestHarnessReferenceMode == null ? parent.TestHarnessReferenceMode : this.TestHarnessReferenceMode;
            this.TestPattern                 = this.TestPattern == null ? parent.TestPattern : this.TestPattern;
            this.UserAgent                   = this.UserAgent == null ? parent.UserAgent : this.UserAgent;
            this.EnableTestFileBatching      = this.EnableTestFileBatching == null ? parent.EnableTestFileBatching : this.EnableTestFileBatching;
            this.IgnoreResourceLoadingErrors = this.IgnoreResourceLoadingErrors == null ? parent.IgnoreResourceLoadingErrors : this.IgnoreResourceLoadingErrors;

            // Deprecated
            this.AMDBasePath = this.AMDBasePath == null ? parent.AMDBasePath : this.AMDBasePath;


            // We need to handle an inherited test harness location mode specially
            // If the parent set their mode to SettingsFileAdjacent and the current file has it set to null
            // Then we make the curent file have a Custom mode with the parent files settings directory
            if (this.TestHarnessLocationMode == null)
            {
                if (parent.TestHarnessLocationMode == Chutzpah.Models.TestHarnessLocationMode.SettingsFileAdjacent && !parent.IsDefaultSettings)
                {
                    this.TestHarnessLocationMode = Chutzpah.Models.TestHarnessLocationMode.Custom;
                    this.TestHarnessDirectory    = parent.SettingsFileDirectory;
                }
                else
                {
                    this.TestHarnessDirectory    = parent.TestHarnessDirectory;
                    this.TestHarnessLocationMode = parent.TestHarnessLocationMode;
                }
            }



            return(this);
        }
        private IList<ReferencedFile> ExpandNestedReferences(
            HashSet<string> discoveredPaths,
            IFrameworkDefinition definition,
            string currentFilePath,
            ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            try
            {
                string textToParse = fileSystem.GetText(currentFilePath);
                return GetReferencedFiles(discoveredPaths, definition, textToParse, currentFilePath, chutzpahTestSettings);
            }
            catch (IOException e)
            {
                // Unable to get file text
                ChutzpahTracer.TraceError(e, "Unable to get file text from test reference with path {0}", currentFilePath);
            }

            return new List<ReferencedFile>();
        }
        private ReferencedFile VisitReferencedFile(
            string absoluteFilePath,
            IFrameworkDefinition definition,
            HashSet<string> discoveredPaths,
            ICollection<ReferencedFile> referencedFiles,
            ChutzpahTestSettingsFile chutzpahTestSettings,
            ReferencePathSettings pathSettings)
        {
            // If the file doesn't exit exist or we have seen it already then return
            if (discoveredPaths.Contains(absoluteFilePath)) return null;

            var referencedFile = new ReferencedFile
            {
                Path = absoluteFilePath,
                IsLocal = true,
                IsTestFrameworkFile = pathSettings.IsTestFrameworkFile,
                IncludeInTestHarness = pathSettings.IncludeInTestHarness || chutzpahTestSettings.TestHarnessReferenceMode == TestHarnessReferenceMode.Normal,
                TemplateOptions = pathSettings.TemplateOptions
            };

            ChutzpahTracer.TraceInformation(
                "Added file '{0}' to referenced files. Local: {1}, IncludeInTestHarness: {2}",
                referencedFile.Path,
                referencedFile.IsLocal,
                referencedFile.IncludeInTestHarness);

            referencedFiles.Add(referencedFile);
            discoveredPaths.Add(referencedFile.Path); // Remmember this path to detect reference loops


            ChutzpahTracer.TraceInformation("Processing referenced file '{0}' for expanded references", absoluteFilePath);
            if (pathSettings.ExpandReferenceComments)
            {
                referencedFile.ReferencedFiles = ExpandNestedReferences(discoveredPaths, definition, absoluteFilePath, chutzpahTestSettings);
            }

            return referencedFile;
        }
        /// <summary>
        /// If the reference path is rooted (e.g. /some/path) and the user chose to adjust it then change it
        /// </summary>
        /// <returns></returns>
        private static string AdjustPathIfRooted(ChutzpahTestSettingsFile chutzpahTestSettings, string referencePath)
        {
            if (chutzpahTestSettings.RootReferencePathMode == RootReferencePathMode.SettingsFileDirectory &&
                (referencePath.StartsWith("/") || referencePath.StartsWith("\\")))
            {
                ChutzpahTracer.TraceInformation(
                    "Changing reference '{0}' to be rooted from settings directory '{1}'",
                    referencePath,
                    chutzpahTestSettings.SettingsFileDirectory);

                referencePath = chutzpahTestSettings.SettingsFileDirectory + referencePath;
            }

            return referencePath;
        }
        private void ProcessFilePathAsReference(
            HashSet<string> discoveredPaths,
            IFrameworkDefinition definition,
            string relativeProcessingPath,
            ChutzpahTestSettingsFile chutzpahTestSettings,
            string referencePath,
            List<ReferencedFile> referencedFiles,
            ReferencePathSettings pathSettings)
        {
            ChutzpahTracer.TraceInformation("Investigating reference file path '{0}'", referencePath);

            // Check test settings and adjust the path if it is rooted (e.g. /some/path)
            referencePath = AdjustPathIfRooted(chutzpahTestSettings, referencePath);

            var referenceUri = new Uri(referencePath, UriKind.RelativeOrAbsolute);
            string referenceFileName = Path.GetFileName(referencePath);

            //  Ignore test runner, since we use our own.
            if (definition.ReferenceIsDependency(referenceFileName, chutzpahTestSettings))
            {
                ChutzpahTracer.TraceInformation(
                    "Ignoring reference file '{0}' as a duplicate reference to {1}",
                    referenceFileName,
                    definition.FrameworkKey);
                return;
            }

            var isRelativeUri = !referenceUri.IsAbsoluteUri;

            // If this either a relative uri or a file uri 
            if (isRelativeUri || referenceUri.IsFile)
            {
                var relativeProcessingPathFolder = fileSystem.FolderExists(relativeProcessingPath)
                    ? relativeProcessingPath
                    : Path.GetDirectoryName(relativeProcessingPath);
                string relativeReferencePath = Path.Combine(relativeProcessingPathFolder, referencePath);

                // Check if reference is a file
                string absoluteFilePath = fileProbe.FindFilePath(relativeReferencePath);
                if (absoluteFilePath != null)
                {
                    VisitReferencedFile(absoluteFilePath, definition, discoveredPaths, referencedFiles, chutzpahTestSettings, pathSettings);
                    return;
                }

                // Check if reference is a folder
                string absoluteFolderPath = fileProbe.FindFolderPath(relativeReferencePath);
                if (absoluteFolderPath != null)
                {
                    var includePatterns = pathSettings.Includes.Select(x => FileProbe.NormalizeFilePath(x)).ToList();
                    var excludePatterns = pathSettings.Excludes.Select(x => FileProbe.NormalizeFilePath(x)).ToList();

                    // Find all files in this folder including sub-folders. This can be ALOT of files.
                    // Only a subset of these files Chutzpah might understand so many of these will be ignored.
                    var childFiles = fileSystem.GetFiles(absoluteFolderPath, "*.*", SearchOption.AllDirectories);
                    var validFiles = from file in childFiles
                        let normalizedFile = FileProbe.NormalizeFilePath(file)
                        where !fileProbe.IsTemporaryChutzpahFile(file)
                        && (!includePatterns.Any() || includePatterns.Any(pat => NativeImports.PathMatchSpec(normalizedFile, pat)))
                        && (!excludePatterns.Any() || !excludePatterns.Any(pat => NativeImports.PathMatchSpec(normalizedFile, pat)))
                        select file;

                    validFiles.ForEach(file => VisitReferencedFile(file, definition, discoveredPaths, referencedFiles, chutzpahTestSettings, pathSettings));

                    return;
                }

                // At this point we know that this file/folder does not exist!
                ChutzpahTracer.TraceWarning("Referenced file '{0}' which was resolved to '{1}' does not exist", referencePath, relativeReferencePath);
            }
            else if (referenceUri.IsAbsoluteUri)
            {
                var referencedFile = new ReferencedFile
                {
                    Path = referencePath,
                    IsLocal = false,
                    IncludeInTestHarness = true,
                    IsTestFrameworkFile = pathSettings.IsTestFrameworkFile,
                    TemplateOptions = pathSettings.TemplateOptions
                };

                ChutzpahTracer.TraceInformation(
                    "Added file '{0}' to referenced files. Local: {1}, IncludeInTestHarness: {2}",
                    referencedFile.Path,
                    referencedFile.IsLocal,
                    referencedFile.IncludeInTestHarness);
                referencedFiles.Add(referencedFile);
            }
        }
        private IList<ReferencedFile> GetReferencedFiles(
            HashSet<string> discoveredPaths,
            IFrameworkDefinition definition,
            string textToParse,
            string currentFilePath,
            ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            var referencedFiles = new List<ReferencedFile>();

            Regex regex = RegexPatterns.JsReferencePathRegex;
            foreach (Match match in regex.Matches(textToParse))
            {
                if (!ShouldIncludeReference(match)) continue;

                string referencePath = match.Groups["Path"].Value;

                ProcessFilePathAsReference(
                    discoveredPaths,
                    definition,
                    currentFilePath,
                    chutzpahTestSettings,
                    referencePath,
                    referencedFiles,
                    new ReferencePathSettings());
            }

            foreach (Match match in RegexPatterns.JsTemplatePathRegex.Matches(textToParse))
            {
                string referencePath = null, templateId = null, templateType = null;
                TemplateMode templateMode = TemplateMode.Raw;

                for (var i = 0; i < match.Groups["PropName"].Captures.Count; i++)
                {
                    var propName = match.Groups["PropName"].Captures[i].Value.ToLowerInvariant();
                    var propValue = match.Groups["PropValue"].Captures[i].Value;

                    switch (propName)
                    {
                        case "path":
                            referencePath = propValue;
                            break;
                        case "id":
                            templateId = propValue;
                            break;
                        case "type":
                            templateType = propValue;
                            break;
                        case "mode":
                            if(propValue.Equals("script", StringComparison.OrdinalIgnoreCase))
                            {
                                templateMode = TemplateMode.Script;
                            }
                            break;
                        default:
                            break;
                    }
                }

                referencePath = AdjustPathIfRooted(chutzpahTestSettings, referencePath);
                string relativeReferencePath = Path.Combine(Path.GetDirectoryName(currentFilePath), referencePath);
                string absoluteFilePath = fileProbe.FindFilePath(relativeReferencePath);
                if (referencedFiles.All(r => r.Path != absoluteFilePath))
                {
                    ChutzpahTracer.TraceInformation("Added html template '{0}' to referenced files", absoluteFilePath);
                    referencedFiles.Add(new ReferencedFile
                    {
                        Path = absoluteFilePath,
                        IsLocal = false,
                        IncludeInTestHarness = true,
                        TemplateOptions = new TemplateOptions
                        {
                            Mode = templateMode,
                            Id = templateId,
                            Type = templateType
                        }
                    });
                }
            }

            return referencedFiles;
        }
        /// <summary>
        /// Add the AMD file paths for the Path and GeneratePath fields
        /// </summary>
        /// <param name="referencedFiles"></param>
        /// <param name="testHarnessDirectory"></param>
        /// <param name="testSettings"></param>
        private void SetupLegacyAmdFilePaths(List<ReferencedFile> referencedFiles, string testHarnessDirectory, ChutzpahTestSettingsFile testSettings)
        {
            // If the user set a AMD base path then we must relativize the amd path's using the path from the base path to the test harness directory
            string relativeAmdRootPath = "";
            if (!string.IsNullOrEmpty(testSettings.AMDBasePath))
            {
                relativeAmdRootPath = FileProbe.GetRelativePath(testSettings.AMDBasePath, testHarnessDirectory);
            } 

            foreach (var referencedFile in referencedFiles)
            {
                referencedFile.AmdFilePath = GetLegacyAmdPath(testHarnessDirectory, referencedFile.Path, relativeAmdRootPath);

                if (!string.IsNullOrEmpty(referencedFile.GeneratedFilePath))
                {
                    referencedFile.AmdGeneratedFilePath = GetLegacyAmdPath(testHarnessDirectory, referencedFile.GeneratedFilePath, relativeAmdRootPath);
                }
            }
        }
        /// <summary>
        /// Merge a selection of settings from a parent file into the current one.
        /// This merge will work as follows
        /// 1. For basic properties the child's property wins if it is different than the default
        /// 2. For complex objects the child's property wins if it is not null
        /// 3. For lists the childs items get added to the parents
        /// </summary>
        /// <param name="parent"></param>
        public ChutzpahTestSettingsFile InheritFrom(ChutzpahTestSettingsFile parent)
        {
            if (parent == null || this.IsDefaultSettings)
            {
                return(this);
            }


            this.References           = parent.References.Concat(this.References).ToList();
            this.CodeCoverageIncludes = parent.CodeCoverageIncludes.Concat(this.CodeCoverageIncludes).ToList();
            this.CodeCoverageExcludes = parent.CodeCoverageExcludes.Concat(this.CodeCoverageExcludes).ToList();
            this.CodeCoverageIgnores  = parent.CodeCoverageIgnores.Concat(this.CodeCoverageIgnores).ToList();
            this.Transforms           = parent.Transforms.Concat(this.Transforms).ToList();

            foreach (var browserArgument in parent.BrowserArguments)
            {
                // We should only override the child if the child does not already define a value for a key
                if (this.BrowserArguments.ContainsKey(browserArgument.Key))
                {
                    continue;
                }

                this.BrowserArguments[browserArgument.Key] = browserArgument.Value;
            }

            if (this.Server == null)
            {
                this.Server = parent.Server;
            }
            else if (this.Server != null && parent.Server != null

                     // Only allow override if the parent is a force configuration which is used for testing
                     && !(parent.Server is ForcedChutzpahWebServerConfiguration)
                     )
            {
                ChutzpahTracer.TraceWarning("Ignoring Server setting in child settings file since it is already configured in parent");
                this.Server = new ChutzpahWebServerConfiguration(parent.Server);
            }

            if (this.Compile == null)
            {
                this.Compile = parent.Compile;
            }
            else if (this.Compile != null && parent.Compile != null)
            {
                this.Compile.Arguments              = this.Compile.Arguments ?? parent.Compile.Arguments;
                this.Compile.Executable             = this.Compile.Executable ?? parent.Compile.Executable;
                this.Compile.Extensions             = this.Compile.Extensions.Any() ? this.Compile.Extensions : parent.Compile.Extensions;
                this.Compile.ExtensionsWithNoOutput = this.Compile.ExtensionsWithNoOutput.Any() ? this.Compile.ExtensionsWithNoOutput : parent.Compile.ExtensionsWithNoOutput;
                this.Compile.Mode = this.Compile.Mode ?? parent.Compile.Mode;
                this.Compile.IgnoreMissingFiles = this.Compile.IgnoreMissingFiles ?? parent.Compile.IgnoreMissingFiles;
                this.Compile.UseSourceMaps      = this.Compile.UseSourceMaps ?? parent.Compile.UseSourceMaps;
                this.Compile.SkipIfUnchanged    = this.Compile.SkipIfUnchanged ?? parent.Compile.SkipIfUnchanged;
                this.Compile.WorkingDirectory   = this.Compile.WorkingDirectory ?? parent.Compile.WorkingDirectory;
                this.Compile.Timeout            = this.Compile.Timeout ?? parent.Compile.Timeout;
                this.Compile.Paths = this.Compile.Paths.Concat(parent.Compile.Paths).ToList();
            }


            this.AMDBaseUrl      = this.AMDBaseUrl ?? parent.AMDBaseUrl;
            this.AMDAppDirectory = this.AMDAppDirectory ?? parent.AMDAppDirectory;
            this.CodeCoverageSuccessPercentage = this.CodeCoverageSuccessPercentage ?? parent.CodeCoverageSuccessPercentage;
            this.CustomTestHarnessPath         = this.CustomTestHarnessPath ?? parent.CustomTestHarnessPath;
            this.CodeCoverageExecutionMode     = this.CodeCoverageExecutionMode ?? parent.CodeCoverageExecutionMode;
            this.Framework                   = this.Framework ?? parent.Framework;
            this.FrameworkVersion            = this.FrameworkVersion ?? parent.FrameworkVersion;
            this.MochaInterface              = this.MochaInterface ?? parent.MochaInterface;
            this.RootReferencePathMode       = this.RootReferencePathMode ?? parent.RootReferencePathMode;
            this.TestFileTimeout             = this.TestFileTimeout ?? parent.TestFileTimeout;
            this.TestHarnessReferenceMode    = this.TestHarnessReferenceMode ?? parent.TestHarnessReferenceMode;
            this.TestPattern                 = this.TestPattern ?? parent.TestPattern;
            this.UserAgent                   = this.UserAgent ?? parent.UserAgent;
            this.EnableTestFileBatching      = this.EnableTestFileBatching ?? parent.EnableTestFileBatching;
            this.IgnoreResourceLoadingErrors = this.IgnoreResourceLoadingErrors ?? parent.IgnoreResourceLoadingErrors;
            this.Parallelism                 = this.Parallelism ?? parent.Parallelism;
            this.EnableTracing               = this.EnableTracing ?? parent.EnableTracing;
            this.TraceFilePath               = this.TraceFilePath ?? parent.TraceFilePath;
            this.CodeCoverageTimeout         = this.CodeCoverageTimeout ?? parent.CodeCoverageTimeout;
            this.Proxy = this.Proxy ?? parent.Proxy;
            this.CreateFailedTestForFileError = this.CreateFailedTestForFileError ?? parent.CreateFailedTestForFileError;

            // Deprecated
            this.AMDBasePath = this.AMDBasePath ?? parent.AMDBasePath;


            // We need to handle an inherited test harness location mode specially
            // If the parent set their mode to SettingsFileAdjacent and the current file has it set to null
            // Then we make the current file have a Custom mode with the parent files settings directory
            if (this.TestHarnessLocationMode == null)
            {
                if (parent.TestHarnessLocationMode == Chutzpah.Models.TestHarnessLocationMode.SettingsFileAdjacent && !parent.IsDefaultSettings)
                {
                    this.TestHarnessLocationMode = Chutzpah.Models.TestHarnessLocationMode.Custom;
                    this.TestHarnessDirectory    = parent.SettingsFileDirectory;
                }
                else
                {
                    this.TestHarnessDirectory    = parent.TestHarnessDirectory;
                    this.TestHarnessLocationMode = parent.TestHarnessLocationMode;
                }
            }



            return(this);
        }
Example #32
0
        public IEnumerable<PathInfo> FindScriptFiles(ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            if (chutzpahTestSettings == null) yield break;

            foreach (var pathSettings in chutzpahTestSettings.Tests.Where(x => x != null))
            {
                var includePatterns = pathSettings.Includes.Select(x => NormalizeFilePath(x)).ToList();
                var excludePatterns = pathSettings.Excludes.Select(x => NormalizeFilePath(x)).ToList();


                // The path we assume default to the chuzpah.json directory if the Path property is not set
                var testPath = string.IsNullOrEmpty(pathSettings.Path) ? pathSettings.SettingsFileDirectory : pathSettings.Path;
                testPath = NormalizeFilePath(testPath);
                testPath = testPath != null ? Path.Combine(pathSettings.SettingsFileDirectory, testPath) : null;

                // If a file path is given just return that file
                var filePath = FindFilePath(testPath);
                if (filePath != null)
                {
                    ChutzpahTracer.TraceInformation("Found file  {0} from chutzpah.json", filePath);
                    yield return GetPathInfo(filePath);
                }

                // If a folder path is given enumerate that folder (recursively) with the optional include/exclude paths
                var folderPath = NormalizeFilePath(FindFolderPath(testPath));
                if (folderPath != null)
                {

                    var childFiles = fileSystem.GetFiles(folderPath, "*.*", SearchOption.AllDirectories);
                    var validFiles = from file in childFiles
                                     let normalizedFile = NormalizeFilePath(file)
                                     where !IsTemporaryChutzpahFile(normalizedFile)
                                             && (!includePatterns.Any() || includePatterns.Any(pat => NativeImports.PathMatchSpec(normalizedFile, pat)))
                                             && (!excludePatterns.Any() || !excludePatterns.Any(pat => NativeImports.PathMatchSpec(normalizedFile, pat)))
                                     select file;


                    foreach (var item in validFiles)
                    {
                        yield return GetPathInfo(item);
                    }
                }
            }
        }
Example #33
0
 public TestContext()
 {
     ReferencedFiles  = new List <ReferencedFile>();
     TemporaryFiles   = new List <string>();
     TestFileSettings = new ChutzpahTestSettingsFile().InheritFromDefault();
 }