diff --git a/specifications/JSLintNet.Specifications/FileSystemWrapperStub.cs b/specifications/JSLintNet.Specifications/FileSystemWrapperStub.cs index 5a40a9f..1b2e640 100644 --- a/specifications/JSLintNet.Specifications/FileSystemWrapperStub.cs +++ b/specifications/JSLintNet.Specifications/FileSystemWrapperStub.cs @@ -9,27 +9,38 @@ public class FileSystemWrapperStub : IFileSystemWrapper { public FileSystemWrapperStub() { - this.Files = new Dictionary(); + this.TextFiles = new Dictionary(); this.FileResults = new Dictionary>(); } - public Dictionary Files { get; set; } + public Dictionary TextFiles { get; set; } public Dictionary> FileResults { get; set; } + public void AddFile(string directory, string fileName, string contents) + { + if (!this.FileResults.ContainsKey(directory)) + { + this.FileResults[directory] = new List(); + } + + this.FileResults[directory].Add(fileName); + this.TextFiles.Add(Path.Combine(directory, fileName), contents); + } + public string ReadAllText(string path, Encoding encoding) { - return this.Files[path]; + return this.TextFiles[path]; } public bool FileExists(string path) { - return this.Files.ContainsKey(path); + return this.TextFiles.ContainsKey(path); } public void WriteAllText(string path, string contents, Encoding encoding) { - this.Files[path] = contents; + this.TextFiles[path] = contents; } public string ResolveFile(string path) diff --git a/specifications/JSLintNet.Specifications/JSLintNet.Specifications.csproj b/specifications/JSLintNet.Specifications/JSLintNet.Specifications.csproj index 72b4574..d821604 100644 --- a/specifications/JSLintNet.Specifications/JSLintNet.Specifications.csproj +++ b/specifications/JSLintNet.Specifications/JSLintNet.Specifications.csproj @@ -91,16 +91,21 @@ - - + + - - + + + + True + True + TaskResources.resx + @@ -125,6 +130,8 @@ + + @@ -136,7 +143,13 @@ JSLintNet.QualityTools - + + + ResXFileCodeGenerator + TaskResources.Designer.cs + Designer + + @@ -145,6 +158,9 @@ + + + diff --git a/specifications/JSLintNet.Specifications/JSLintTaskTests.cs b/specifications/JSLintNet.Specifications/JSLintTaskTests.cs deleted file mode 100644 index 4b91d14..0000000 --- a/specifications/JSLintNet.Specifications/JSLintTaskTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace JSLintNet.Specifications -{ - using System.Collections.Generic; - using Xunit; - - [Trait("Category", "Unit")] - public class JSLintTaskTests - { - [Fact(DisplayName = "Should log JSLint errors at the correct line and column")] - public void CorrectLineColumn() - { - using (var fixture = new JSLintTaskFixture()) - { - const string File1Script = @" -var global = unknown();"; - - fixture.Instance.SourceDirectory = "Some Path"; - fixture.FileSystemWrapper.FileResults.Add( - "Some Path", - new List() - { - "file1.js" - }); - - fixture.FileSystemWrapper.Files.Add("Some Path\\file1.js", File1Script); - - var actual = fixture.Instance.Execute(); - var firstError = fixture.BuildEngine.ErrorEvents[0]; - - Assert.False(actual); - Assert.Equal(1, firstError.LineNumber); - Assert.Equal(13, firstError.ColumnNumber); - } - } - } -} diff --git a/specifications/JSLintNet.Specifications/JSLintTaskFixture.cs b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskFixture.cs similarity index 63% rename from specifications/JSLintNet.Specifications/JSLintTaskFixture.cs rename to specifications/JSLintNet.Specifications/Tasks/JSLintTaskFixture.cs index 18edba8..cdddc09 100644 --- a/specifications/JSLintNet.Specifications/JSLintTaskFixture.cs +++ b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskFixture.cs @@ -1,5 +1,6 @@ -namespace JSLintNet.Specifications +namespace JSLintNet.Specifications.Tasks { + using System; using JSLintNet.Abstractions; using JSLintNet.QualityTools; @@ -15,6 +16,18 @@ public JSLintTaskFixture() public FileSystemWrapperStub FileSystemWrapper { get; set; } + public void AddFile(string fileName, string contents) + { + var sourceDirectory = this.Instance.SourceDirectory; + + if (string.IsNullOrEmpty(sourceDirectory)) + { + throw new InvalidOperationException("Cannot add a file without first setting the source directory."); + } + + this.FileSystemWrapper.AddFile(sourceDirectory, fileName, contents); + } + protected override void BeforeResolve() { base.BeforeResolve(); diff --git a/specifications/JSLintNet.Specifications/JSLintTaskIntegration.cs b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskIntegration.cs similarity index 99% rename from specifications/JSLintNet.Specifications/JSLintTaskIntegration.cs rename to specifications/JSLintNet.Specifications/Tasks/JSLintTaskIntegration.cs index 135c7aa..f29d4ec 100644 --- a/specifications/JSLintNet.Specifications/JSLintTaskIntegration.cs +++ b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskIntegration.cs @@ -1,4 +1,4 @@ -namespace JSLintNet.Specifications +namespace JSLintNet.Specifications.Tasks { using System; using System.IO; diff --git a/specifications/JSLintNet.Specifications/Tasks/JSLintTaskTests.cs b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskTests.cs new file mode 100644 index 0000000..221163f --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskTests.cs @@ -0,0 +1,153 @@ +namespace JSLintNet.Specifications.Tasks +{ + using JSLintNet.QualityTools.Expectations; + using Xunit; + + [Trait("Category", "Unit")] + public class JSLintTaskTests + { + [Fact(DisplayName = "Should log JSLint errors at the correct line and column")] + public void CorrectLineColumn() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = "Some Path"; + fixture.AddFile("file1.js", TaskResources.WindowGlobalStrict); + + var actual = fixture.Instance.Execute(); + var firstError = fixture.BuildEngine.ErrorEvents[0]; + + Assert.False(actual); + Assert.Equal(2, firstError.LineNumber); + Assert.Equal(13, firstError.ColumnNumber); + } + } + + [Fact(DisplayName = "Should log each JSLint warning as a task error")] + public void TaskErrors() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"\\SHARE\path\"; + fixture.AddFile("first.js", TaskResources.WindowGlobalStrict); + fixture.AddFile("second.js", TaskResources.AmdNoStrict); + + fixture.Instance.Execute(); + + I.Expect(fixture.BuildEngine.ErrorEvents.Count).ToBe(3); + I.Expect(fixture.BuildEngine.WarningEvents.Count).ToBe(0); + I.Expect(fixture.BuildEngine.MessageEvents.Count).ToBe(0); + } + } + + [Fact(DisplayName = "Should log each JSLint warning as a task warning when outputting warnings")] + public void TaskWarnings() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"\\SHARE\path\"; + fixture.AddFile("JSLintNet.json", TaskResources.WarningSettings); + fixture.AddFile("first.js", TaskResources.WindowGlobalStrict); + fixture.AddFile("second.js", TaskResources.AmdNoStrict); + + fixture.Instance.Execute(); + + I.Expect(fixture.BuildEngine.ErrorEvents.Count).ToBe(0); + I.Expect(fixture.BuildEngine.WarningEvents.Count).ToBe(3); + I.Expect(fixture.BuildEngine.MessageEvents.Count).ToBe(0); + } + } + + [Fact(DisplayName = "Should log each JSLint warning as a task message when outputting messages")] + public void TaskMessages() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"\\SHARE\path\"; + fixture.AddFile("JSLintNet.json", TaskResources.MessageSettings); + fixture.AddFile("first.js", TaskResources.WindowGlobalStrict); + fixture.AddFile("second.js", TaskResources.AmdNoStrict); + + fixture.Instance.Execute(); + + I.Expect(fixture.BuildEngine.ErrorEvents.Count).ToBe(0); + I.Expect(fixture.BuildEngine.WarningEvents.Count).ToBe(0); + I.Expect(fixture.BuildEngine.MessageEvents.Count).ToBe(3); + } + } + + [Fact(DisplayName = "Should return true when no files found")] + public void NoFilesOk() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"C:\Source\"; + + var actual = fixture.Instance.Execute(); + + I.Expect(actual).ToBeTrue(); + } + } + + [Fact(DisplayName = "Should return true when no files contain errors")] + public void NoErrorsOk() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"Some Path"; + fixture.AddFile("file1.js", TaskResources.GlobalVariableDef); + + var actual = fixture.Instance.Execute(); + + I.Expect(actual).ToBeTrue(); + } + } + + [Fact(DisplayName = "Should return false when one error found")] + public void OneErrorFail() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"D:\Solution\Project Dir"; + fixture.AddFile("startup.js", TaskResources.WindowGlobalStrict); + + var actual = fixture.Instance.Execute(); + + I.Expect(fixture.Instance.ErrorCount).ToBe(1); + I.Expect(actual).ToBeFalse(); + } + } + + [Fact(DisplayName = "Should return false when many errors found")] + public void ManyErrorsFail() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"D:\Solution\Project Dir"; + fixture.AddFile("first.js", TaskResources.WindowGlobalStrict); + fixture.AddFile("second.js", TaskResources.AmdNoStrict); + + var actual = fixture.Instance.Execute(); + + I.Expect(fixture.Instance.ErrorCount).ToBe(3); + I.Expect(actual).ToBeFalse(); + } + } + + [Fact(DisplayName = "Should return true when errors found but treating errors as warnings")] + public void WarningsOk() + { + using (var fixture = new JSLintTaskFixture()) + { + fixture.Instance.SourceDirectory = @"Z:\Funky Path\repo-of-doom"; + fixture.AddFile("JSLintNet.json", TaskResources.WarningSettings); + fixture.AddFile("second.js", TaskResources.AmdNoStrict); + + var actual = fixture.Instance.Execute(); + + I.Expect(fixture.Instance.ErrorCount).ToBeGreaterThan(0); + I.Expect(actual).ToBeTrue(); + } + } + } +} diff --git a/specifications/JSLintNet.Specifications/JSLintTaskUnit.cs b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskUnit.cs similarity index 67% rename from specifications/JSLintNet.Specifications/JSLintTaskUnit.cs rename to specifications/JSLintNet.Specifications/Tasks/JSLintTaskUnit.cs index d54dc41..eece1f2 100644 --- a/specifications/JSLintNet.Specifications/JSLintTaskUnit.cs +++ b/specifications/JSLintNet.Specifications/Tasks/JSLintTaskUnit.cs @@ -1,4 +1,4 @@ -namespace JSLintNet.Specifications +namespace JSLintNet.Specifications.Tasks { using System; using System.Collections.Generic; @@ -19,125 +19,6 @@ public class JSLintTaskUnit { public class Execute : UnitBase { - [Fact(DisplayName = "Should return true when no files found")] - public void Spec01() - { - using (var testable = new ExecuteTestable()) - { - var actual = testable.Instance.Execute(); - - I.Expect(actual).ToBeTrue(); - } - } - - [Fact(DisplayName = "Should return true when no files contain errors")] - public void Spec02() - { - using (var testable = new ExecuteTestable()) - { - testable.SetupJSLintFile("file.js", 0); - - var actual = testable.Instance.Execute(); - - I.Expect(actual).ToBeTrue(); - } - } - - [Fact(DisplayName = "Should return false when one error found")] - public void Spec03() - { - using (var testable = new ExecuteTestable()) - { - testable.SetupJSLintFile("file.js", 1); - - var actual = testable.Instance.Execute(); - - I.Expect(actual).ToBeFalse(); - } - } - - [Fact(DisplayName = "Should return false when many errors found")] - public void Spec04() - { - using (var testable = new ExecuteTestable()) - { - testable.SetupJSLintFile("file1.js", 5); - testable.SetupJSLintFile("file2.js", 0); - testable.SetupJSLintFile("file3.js", 3); - - var actual = testable.Instance.Execute(); - - I.Expect(actual).ToBeFalse(); - } - } - - [Fact(DisplayName = "Should return true when errors found but treating errors as warnings")] - public void Spec05() - { - using (var testable = new ExecuteTestable()) - { - testable.SetupJSLintFile("file.js", 2); - testable.Settings.Output = Output.Warning; - testable.SettingsExist = true; - - var actual = testable.Instance.Execute(); - - I.Expect(actual).ToBeTrue(); - } - } - - [Fact(DisplayName = "Should lint the content of each file provided")] - public void Spec06() - { - using (var testable = new ExecuteTestable()) - { - testable.SetupJSLintFile("file1.js", 0); - testable.SetupJSLintFile("jsfile2.js", 0); - - testable.Instance.Execute(); - - var mock = testable.GetMock(); - - mock.Verify(x => x.Lint("file1.js contents", It.IsAny(), It.IsAny>())); - mock.Verify(x => x.Lint("jsfile2.js contents", It.IsAny(), It.IsAny>())); - mock.Verify(x => x.Lint(It.IsAny(), It.IsAny(), It.IsAny>()), Times.Exactly(2)); - } - } - - [Fact(DisplayName = "Should log each jslint error as a task error")] - public void Spec07() - { - using (var testable = new ExecuteTestable()) - { - testable.SetupJSLintFile("file1.js", 2); - testable.SetupJSLintFile("jsfile2.js", 1); - - testable.Instance.Execute(); - - I.Expect(testable.BuildEngine.ErrorEvents.Count).ToBe(3); - I.Expect(testable.BuildEngine.WarningEvents.Count).ToBe(0); - I.Expect(testable.BuildEngine.MessageEvents.Count).ToBe(0); - } - } - - [Fact(DisplayName = "Should log each jslint error as a task warning when treating errors as warnings")] - public void Spec08() - { - using (var testable = new ExecuteTestable()) - { - testable.SetupJSLintFile("file1.js", 2); - testable.SetupJSLintFile("jsfile2.js", 1); - testable.Settings.Output = Output.Warning; - testable.SettingsExist = true; - - testable.Instance.Execute(); - - I.Expect(testable.BuildEngine.ErrorEvents.Count).ToBe(0); - I.Expect(testable.BuildEngine.WarningEvents.Count).ToBe(3); - I.Expect(testable.BuildEngine.MessageEvents.Count).ToBe(0); - } - } - [Fact(DisplayName = "Should set error count to total number of error")] public void Spec09() { diff --git a/specifications/JSLintNet.Specifications/Tasks/Resources/AmdNoStrict.js b/specifications/JSLintNet.Specifications/Tasks/Resources/AmdNoStrict.js new file mode 100644 index 0000000..f9f6de7 --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/Resources/AmdNoStrict.js @@ -0,0 +1,3 @@ +define(['some-module'], function (someModule) { + return someModule; +}); diff --git a/specifications/JSLintNet.Specifications/Tasks/Resources/GlobalVariableDef.js b/specifications/JSLintNet.Specifications/Tasks/Resources/GlobalVariableDef.js new file mode 100644 index 0000000..8196c37 --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/Resources/GlobalVariableDef.js @@ -0,0 +1,7 @@ +/*global define, ko*/ + +define([], function () { + 'use strict'; + + return ko.applyBindings(); +}); diff --git a/specifications/JSLintNet.Specifications/Tasks/Resources/MessageSettings.json b/specifications/JSLintNet.Specifications/Tasks/Resources/MessageSettings.json new file mode 100644 index 0000000..2ee4b09 --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/Resources/MessageSettings.json @@ -0,0 +1,3 @@ +{ + "output": "Message" +} diff --git a/specifications/JSLintNet.Specifications/Tasks/Resources/WarningSettings.json b/specifications/JSLintNet.Specifications/Tasks/Resources/WarningSettings.json new file mode 100644 index 0000000..1ca6ce4 --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/Resources/WarningSettings.json @@ -0,0 +1,3 @@ +{ + "output": "Warning" +} diff --git a/specifications/JSLintNet.Specifications/Tasks/Resources/WindowGlobalStrict.js b/specifications/JSLintNet.Specifications/Tasks/Resources/WindowGlobalStrict.js new file mode 100644 index 0000000..c988304 --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/Resources/WindowGlobalStrict.js @@ -0,0 +1,3 @@ +'use strict'; + +var global = window.global; diff --git a/specifications/JSLintNet.Specifications/Tasks/TaskResources.Designer.cs b/specifications/JSLintNet.Specifications/Tasks/TaskResources.Designer.cs new file mode 100644 index 0000000..d2705e7 --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/TaskResources.Designer.cs @@ -0,0 +1,127 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace JSLintNet.Specifications.Tasks { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class TaskResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal TaskResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JSLintNet.Specifications.Tasks.TaskResources", typeof(TaskResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to define(['some-module'], function (someModule) { + /// return someModule; + ///}); + ///. + /// + internal static string AmdNoStrict { + get { + return ResourceManager.GetString("AmdNoStrict", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to /*global define, ko*/ + /// + ///define([], function () { + /// 'use strict'; + /// + /// return ko.applyBindings(); + ///}); + ///. + /// + internal static string GlobalVariableDef { + get { + return ResourceManager.GetString("GlobalVariableDef", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "output": "Warning" + ///} + ///. + /// + internal static string MessageSettings { + get { + return ResourceManager.GetString("MessageSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "output": "Warning" + ///} + ///. + /// + internal static string WarningSettings { + get { + return ResourceManager.GetString("WarningSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 'use strict'; + /// + ///var global = window.global; + ///. + /// + internal static string WindowGlobalStrict { + get { + return ResourceManager.GetString("WindowGlobalStrict", resourceCulture); + } + } + } +} diff --git a/specifications/JSLintNet.Specifications/Tasks/TaskResources.resx b/specifications/JSLintNet.Specifications/Tasks/TaskResources.resx new file mode 100644 index 0000000..8c2458c --- /dev/null +++ b/specifications/JSLintNet.Specifications/Tasks/TaskResources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + resources\amdnostrict.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + resources\globalvariabledef.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + resources\messagesettings.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + resources\warningsettings.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + resources\windowglobalstrict.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + \ No newline at end of file