/src/Cassette.UnitTests/FileSystemWatchingBundleRebuilder.cs

https://github.com/mickdelaney/cassette · C# · 312 lines · 250 code · 62 blank · 0 comment · 0 complexity · 9b5e742a70c8e3e9e0606c4c26147b97 MD5 · raw file

  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Threading;
  5. using Cassette.BundleProcessing;
  6. using Cassette.IO;
  7. using Moq;
  8. using Xunit;
  9. namespace Cassette
  10. {
  11. public class FileSystemWatchingBundleRebuilder_Tests : IDisposable
  12. {
  13. readonly BundleCollection bundles;
  14. readonly FileSystemWatchingBundleRebuilder rebuilder;
  15. readonly Mock<IConfiguration<BundleCollection>> bundleConfiguration;
  16. readonly TempDirectory tempDirectory;
  17. readonly Mock<IFileSearch> fileSearch;
  18. public FileSystemWatchingBundleRebuilder_Tests()
  19. {
  20. tempDirectory = new TempDirectory();
  21. Directory.CreateDirectory(Path.Combine(tempDirectory, "cache"));
  22. var settings = new CassetteSettings
  23. {
  24. SourceDirectory = new FileSystemDirectory(tempDirectory),
  25. CacheDirectory = new FileSystemDirectory(Path.Combine(tempDirectory, "cache")),
  26. IsFileSystemWatchingEnabled = true
  27. };
  28. bundles = new BundleCollection(settings, Mock.Of<IFileSearchProvider>(), Mock.Of<IBundleFactoryProvider>());
  29. bundleConfiguration = new Mock<IConfiguration<BundleCollection>>();
  30. var bundle = new TestableBundle("~");
  31. var asset1 = new StubAsset("~/test.js");
  32. var asset2 = new StubAsset("~/sub/test2.js");
  33. asset1.AddRawFileReference("~/image.png");
  34. bundle.Assets.Add(asset1);
  35. bundle.Assets.Add(asset2);
  36. bundles.Add(bundle);
  37. fileSearch = new Mock<IFileSearch>();
  38. fileSearch
  39. .Setup(s => s.IsMatch(It.IsAny<string>()))
  40. .Returns<string>(path => path.EndsWith(".js"));
  41. var initializer = new BundleCollectionInitializer(new[] { bundleConfiguration.Object }, new ExternalBundleGenerator(Mock.Of<IBundleFactoryProvider>(), settings));
  42. rebuilder = new FileSystemWatchingBundleRebuilder(settings, bundles, initializer, new[] { fileSearch.Object });
  43. }
  44. [Fact]
  45. public void WhenNewFileCreated_ThenRebuild()
  46. {
  47. rebuilder.Start();
  48. CreateFile("test.js");
  49. AssertBundleCollectionRebuilt();
  50. }
  51. [Fact]
  52. public void WhenFileCreatedNotMatchingFileSearch_ThenDontRebuild()
  53. {
  54. fileSearch.Setup(s => s.IsMatch(It.IsAny<string>())).Returns(false);
  55. rebuilder.Start();
  56. CreateFile("test.txt");
  57. AssertBundleCollectionNotRebuilt();
  58. }
  59. [Fact]
  60. public void WhenFileDeleted_ThenRebuild()
  61. {
  62. CreateFile("test.js");
  63. rebuilder.Start();
  64. DeleteFile("test.js");
  65. AssertBundleCollectionRebuilt();
  66. }
  67. [Fact]
  68. public void WhenFileUnknownToCassetteDeleted_ThenDontRebuild()
  69. {
  70. CreateFile("unknown.js");
  71. rebuilder.Start();
  72. DeleteFile("unknown.js");
  73. AssertBundleCollectionNotRebuilt();
  74. }
  75. [Fact]
  76. public void WhenFileChanged_ThenRebuild()
  77. {
  78. CreateFile("test.js");
  79. rebuilder.Start();
  80. ChangeFile("test.js");
  81. AssertBundleCollectionRebuilt();
  82. }
  83. [Fact]
  84. public void WhenFileNotKnownByCassetteChanged_ThenDontRebuild()
  85. {
  86. CreateFile("unknown.js");
  87. rebuilder.Start();
  88. ChangeFile("unknown.js");
  89. AssertBundleCollectionNotRebuilt();
  90. }
  91. [Fact]
  92. public void WhenKnownFileRenamed_ThenRebuild()
  93. {
  94. CreateFile("test.js");
  95. rebuilder.Start();
  96. RenameFile("test.js", "test.xxx");
  97. AssertBundleCollectionRebuilt();
  98. }
  99. [Fact]
  100. public void WhenUnknownFileRenamedSoItMatchesFileSearch_ThenRebuild()
  101. {
  102. CreateFile("test.xxx");
  103. rebuilder.Start();
  104. RenameFile("test.xxx", "test.js");
  105. AssertBundleCollectionRebuilt();
  106. }
  107. [Fact]
  108. public void WhenSubDirectoryOfBundleRenamed_ThenBuild()
  109. {
  110. CreateDirectory("sub");
  111. CreateFile("sub/test2.js");
  112. rebuilder.Start();
  113. RenameDirectory("sub", "renamed-sub");
  114. AssertBundleCollectionRebuilt();
  115. }
  116. [Fact]
  117. public void WhenRawFileReferencedFileIsChanged_ThenRebuild()
  118. {
  119. CreateFile("image.png");
  120. rebuilder.Start();
  121. ChangeFile("image.png");
  122. AssertBundleCollectionRebuilt();
  123. }
  124. [Fact]
  125. public void WhenRawFileReferencedFileIsDeleted_ThenRebuild()
  126. {
  127. CreateFile("image.png");
  128. rebuilder.Start();
  129. DeleteFile("image.png");
  130. AssertBundleCollectionRebuilt();
  131. }
  132. [Fact]
  133. public void WhenCacheFileIsChanged_ThenDontRebuild()
  134. {
  135. rebuilder.Start();
  136. CreateFile("cache/cached-file.js");
  137. AssertBundleCollectionNotRebuilt();
  138. }
  139. [Fact]
  140. public void WhenBundleTxtCreated_ThenRebuild()
  141. {
  142. rebuilder.Start();
  143. CreateFile("bundle.txt");
  144. AssertBundleCollectionRebuilt();
  145. }
  146. [Fact]
  147. public void WhenBundleTxtChanged_ThenRebuild()
  148. {
  149. CreateFile("bundle.txt");
  150. rebuilder.Start();
  151. ChangeFile("bundle.txt");
  152. AssertBundleCollectionRebuilt();
  153. }
  154. [Fact]
  155. public void WhenBundleTxtDeleted_ThenRebuild()
  156. {
  157. CreateFile("bundle.txt");
  158. rebuilder.Start();
  159. DeleteFile("bundle.txt");
  160. AssertBundleCollectionRebuilt();
  161. }
  162. [Fact]
  163. public void WhenScriptBundleTxtCreated_ThenRebuild()
  164. {
  165. rebuilder.Start();
  166. CreateFile("scriptbundle.txt");
  167. AssertBundleCollectionRebuilt();
  168. }
  169. [Fact]
  170. public void WhenOtherBundleTxtCreated_ThenDontRebuild()
  171. {
  172. rebuilder.Start();
  173. CreateFile("other-bundle.txt");
  174. AssertBundleCollectionNotRebuilt();
  175. }
  176. class TestTraceListener : TraceListener
  177. {
  178. public TestTraceListener()
  179. {
  180. Filter = new EventTypeFilter(SourceLevels.All);
  181. }
  182. public object TraceDataObject { get; set; }
  183. public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
  184. {
  185. base.TraceData(eventCache, source, eventType, id, data);
  186. TraceDataObject = data;
  187. }
  188. public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
  189. {
  190. base.TraceData(eventCache, source, eventType, id, data);
  191. TraceDataObject = data;
  192. }
  193. public override void Write(string message)
  194. {
  195. }
  196. public override void WriteLine(string message)
  197. {
  198. }
  199. }
  200. void CreateFile(string filename)
  201. {
  202. File.WriteAllText(Path.Combine(tempDirectory, filename), "");
  203. }
  204. void CreateDirectory(string path)
  205. {
  206. Directory.CreateDirectory(Path.Combine(tempDirectory, path));
  207. }
  208. void RenameFile(string currentFilename, string newFilename)
  209. {
  210. File.Move(
  211. Path.Combine(tempDirectory, currentFilename),
  212. Path.Combine(tempDirectory, newFilename)
  213. );
  214. }
  215. void RenameDirectory(string currentPath, string newPath)
  216. {
  217. Directory.Move(
  218. Path.Combine(tempDirectory, currentPath),
  219. Path.Combine(tempDirectory, newPath)
  220. );
  221. }
  222. void ChangeFile(string filename)
  223. {
  224. File.WriteAllText(Path.Combine(tempDirectory, filename), Guid.NewGuid().ToString());
  225. }
  226. void DeleteFile(string filename)
  227. {
  228. File.Delete(Path.Combine(tempDirectory, filename));
  229. }
  230. void PauseForEvent()
  231. {
  232. Thread.Sleep(200); // Wait for the file system change event to fire.
  233. }
  234. void AssertBundleCollectionRebuilt()
  235. {
  236. PauseForEvent();
  237. bundleConfiguration.Verify(d => d.Configure(bundles), Times.Once());
  238. }
  239. void AssertBundleCollectionNotRebuilt()
  240. {
  241. PauseForEvent();
  242. bundleConfiguration.Verify(d => d.Configure(bundles), Times.Never());
  243. }
  244. public void Dispose()
  245. {
  246. rebuilder.Dispose();
  247. tempDirectory.Dispose();
  248. }
  249. }
  250. }