diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 484eadb..cca4062 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,9 +23,9 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 3.1.x 5.0.x 6.0.x + 7.0.x - name: Run tests run: dotnet test --collect:"XPlat Code Coverage" --logger "GitHubActions" - name: Upload coverage diff --git a/global.json b/global.json index e1a0f54..96f0cfd 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.304", + "version": "7.0.400", "rollForward": "latestMinor" } } diff --git a/src/System.IO.Abstractions.Extensions/IDirectoryInfoExtensions.cs b/src/System.IO.Abstractions.Extensions/IDirectoryInfoExtensions.cs index 472d3bd..6d1b4be 100644 --- a/src/System.IO.Abstractions.Extensions/IDirectoryInfoExtensions.cs +++ b/src/System.IO.Abstractions.Extensions/IDirectoryInfoExtensions.cs @@ -1,4 +1,7 @@ -namespace System.IO.Abstractions +using System.Collections.Generic; +using System.Linq; + +namespace System.IO.Abstractions { public static class IDirectoryInfoExtensions { @@ -13,6 +16,28 @@ public static IDirectoryInfo SubDirectory(this IDirectoryInfo info, string name) return info.FileSystem.DirectoryInfo.New(info.FileSystem.Path.Combine(info.FullName, name)); } + /// + /// Get an for the specified sub-directories + /// + /// + /// Sub-directory names (ex. "test", "test2"). Empty or null names are automatically removed from this list + /// An for the specified sub-directory + public static IDirectoryInfo SubDirectory(this IDirectoryInfo info, params string[] names) + { + return info.SubDirectory((IEnumerable)names); + } + + /// + /// Get an for the specified sub-directories + /// + /// + /// Sub-directory names (ex. "test", "test2"). Empty or null names are automatically removed from this list + /// An for the specified sub-directory + public static IDirectoryInfo SubDirectory(this IDirectoryInfo info, IEnumerable names) + { + return info.FileSystem.DirectoryInfo.New(info.FileSystem.Path.Combine(GetPaths(info, names))); + } + /// /// Get an for the specified file /// @@ -24,6 +49,28 @@ public static IFileInfo File(this IDirectoryInfo info, string name) return info.FileSystem.FileInfo.New(info.FileSystem.Path.Combine(info.FullName, name)); } + /// + /// Get an for the specified sub-directories file + /// + /// + /// Sub-directories and file name (ex. "test", "test.txt"). Empty or null names are automatically removed from this list + /// An for the specified file + public static IFileInfo File(this IDirectoryInfo info, params string[] names) + { + return info.File((IEnumerable)names); + } + + /// + /// Get an for the specified sub-directories file + /// + /// + /// Sub-directories and file name (ex. "test", "test.txt"). Empty or null names are automatically removed from this list + /// An for the specified file + public static IFileInfo File(this IDirectoryInfo info, IEnumerable names) + { + return info.FileSystem.FileInfo.New(info.FileSystem.Path.Combine(GetPaths(info, names))); + } + /// /// Throws an exception if the directory doesn't exists /// @@ -34,5 +81,12 @@ public static void ThrowIfNotFound(this IDirectoryInfo info) if (!info.Exists) throw new DirectoryNotFoundException(StringResources.Format("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION", info.FullName)); } + + private static string[] GetPaths(IDirectoryInfo info, IEnumerable names) + { + return new[] { info.FullName } + .Concat(names.Where(n => !String.IsNullOrEmpty(n))) + .ToArray(); + } } } diff --git a/src/System.IO.Abstractions.Extensions/System.IO.Abstractions.Extensions.csproj b/src/System.IO.Abstractions.Extensions/System.IO.Abstractions.Extensions.csproj index 260a31c..c58381b 100644 --- a/src/System.IO.Abstractions.Extensions/System.IO.Abstractions.Extensions.csproj +++ b/src/System.IO.Abstractions.Extensions/System.IO.Abstractions.Extensions.csproj @@ -2,7 +2,7 @@ TestableIO.System.IO.Abstractions.Extensions - net6.0;netstandard2.1;netstandard2.0;net461 + net6.0;netstandard2.1;netstandard2.0;net462 Convenience functionalities on top of System.IO.Abstractions System.IO.Abstractions $([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/../../ReleaseNotes.md")) diff --git a/tests/System.IO.Abstractions.Extensions.Tests/DirectoryInfoExtensionsTests.cs b/tests/System.IO.Abstractions.Extensions.Tests/DirectoryInfoExtensionsTests.cs index 7090f1e..d13bdbc 100644 --- a/tests/System.IO.Abstractions.Extensions.Tests/DirectoryInfoExtensionsTests.cs +++ b/tests/System.IO.Abstractions.Extensions.Tests/DirectoryInfoExtensionsTests.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using System.Collections.Generic; namespace System.IO.Abstractions.Extensions.Tests { @@ -30,6 +31,59 @@ public void SubDirectory_Extension_Test() Assert.IsFalse(fs.Directory.Exists(expectedPath)); } + [TestCase("test1", "test2")] + [TestCase("test1", "", "test2")] + [TestCase("test1", null, "test2")] + public void SubDirectoryWithParams_Extension_Test(params string[] subFolders) + { + //arrange + var fs = new FileSystem(); + var current = fs.DirectoryInfo.New(fs.Directory.GetCurrentDirectory()); + var expectedPath = fs.Path.Combine(current.FullName, "test1", "test2"); + + //make sure directory doesn't exists + Assert.IsFalse(fs.Directory.Exists(expectedPath)); + + //create directory + var created = current.SubDirectory(subFolders); + created.Create(); + + //assert it exists + Assert.IsTrue(fs.Directory.Exists(expectedPath)); + Assert.AreEqual(expectedPath, created.FullName); + + //delete directory + created.Delete(); + Assert.IsFalse(fs.Directory.Exists(expectedPath)); + } + + [TestCase("test1", "test2")] + [TestCase("test1", "", "test2")] + [TestCase("test1", null, "test2")] + public void SubDirectoryWithIEnumerable_Extension_Test(params string[] names) + { + //arrange + var fs = new FileSystem(); + var current = fs.DirectoryInfo.New(fs.Directory.GetCurrentDirectory()); + var expectedPath = fs.Path.Combine(current.FullName, "test1", "test2"); + + //make sure directory doesn't exists + Assert.IsFalse(fs.Directory.Exists(expectedPath)); + + //create directory + var list = new List(names); + var created = current.SubDirectory(list); + created.Create(); + + //assert it exists + Assert.IsTrue(fs.Directory.Exists(expectedPath)); + Assert.AreEqual(expectedPath, created.FullName); + + //delete directory + created.Delete(); + Assert.IsFalse(fs.Directory.Exists(expectedPath)); + } + [Test] public void File_Extension_Test() { @@ -58,6 +112,38 @@ public void File_Extension_Test() Assert.IsFalse(fs.File.Exists(expectedPath)); } + [TestCase("test1", "test2", "test.txt")] + [TestCase("test1", "", "test2", "test.txt")] + [TestCase("test1", null, "test2", "test.txt")] + + public void FileWithParams_Extension_Test(params string[] names) + { + //arrange + var fs = new FileSystem(); + var current = fs.DirectoryInfo.New(fs.Directory.GetCurrentDirectory()); + var expectedPath = fs.Path.Combine(current.FullName, "test1", "test2", "test.txt"); + + //make sure file doesn't exists + Assert.IsFalse(fs.File.Exists(expectedPath)); + + //act, create file + var created = current.File(names); + created.Directory.Create(); + using (var stream = created.Create()) + { + stream.Dispose(); + } + + //assert it exists + Assert.IsTrue(fs.File.Exists(expectedPath)); + Assert.AreEqual(expectedPath, created.FullName); + + //delete file + created.Delete(); + created.Directory.Delete(); + Assert.IsFalse(fs.File.Exists(expectedPath)); + } + [Test] public void ThrowIfNotFound_IfDirectoryDoesNotExists_ThrowsException() { diff --git a/tests/System.IO.Abstractions.Extensions.Tests/System.IO.Abstractions.Extensions.Tests.csproj b/tests/System.IO.Abstractions.Extensions.Tests/System.IO.Abstractions.Extensions.Tests.csproj index afa9171..ec45c06 100644 --- a/tests/System.IO.Abstractions.Extensions.Tests/System.IO.Abstractions.Extensions.Tests.csproj +++ b/tests/System.IO.Abstractions.Extensions.Tests/System.IO.Abstractions.Extensions.Tests.csproj @@ -1,8 +1,8 @@  - net6.0;net5.0;net461 - $(TargetFrameworks);net461 + net7.0;net6.0;net5.0 + $(TargetFrameworks);net462 false true