PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/test/Microsoft.Web.Helpers.Test/ThemesTest.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 372 lines | 249 code | 66 blank | 57 comment | 0 complexity | 14fbee72b16a09fb214aa9ce637ebcc8 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Web.Hosting;
  4. using System.Web.WebPages.Scope;
  5. using Moq;
  6. using Xunit;
  7. using Assert = Microsoft.TestCommon.AssertEx;
  8. namespace Microsoft.Web.Helpers.Test
  9. {
  10. public class ThemesTest
  11. {
  12. [Fact]
  13. public void Initialize_WithBadParams_Throws()
  14. {
  15. // Arrange
  16. var mockVpp = new Mock<VirtualPathProvider>().Object;
  17. var scope = new ScopeStorageDictionary();
  18. // Act and Assert
  19. Assert.ThrowsArgumentNullOrEmptyString(() => new ThemesImplementation(mockVpp, scope).Initialize(null, "foo"), "themeDirectory");
  20. Assert.ThrowsArgumentNullOrEmptyString(() => new ThemesImplementation(mockVpp, scope).Initialize("", "foo"), "themeDirectory");
  21. Assert.ThrowsArgumentNullOrEmptyString(() => new ThemesImplementation(mockVpp, scope).Initialize("~/folder", null), "defaultTheme");
  22. Assert.ThrowsArgumentNullOrEmptyString(() => new ThemesImplementation(mockVpp, scope).Initialize("~/folder", ""), "defaultTheme");
  23. }
  24. [Fact]
  25. public void CurrentThemeThrowsIfAssignedNullOrEmpty()
  26. {
  27. // Arrange
  28. var mockVpp = new Mock<VirtualPathProvider>().Object;
  29. var scope = new ScopeStorageDictionary();
  30. var themesImpl = new ThemesImplementation(mockVpp, scope);
  31. // Act and Assert
  32. Assert.ThrowsArgumentNullOrEmptyString(() => { themesImpl.CurrentTheme = null; }, "value");
  33. Assert.ThrowsArgumentNullOrEmptyString(() => { themesImpl.CurrentTheme = String.Empty; }, "value");
  34. }
  35. [Fact]
  36. public void InvokingPropertiesAndMethodsBeforeInitializationThrows()
  37. {
  38. // Arrange
  39. var mockVpp = new Mock<VirtualPathProvider>().Object;
  40. var scope = new ScopeStorageDictionary();
  41. var themesImpl = new ThemesImplementation(mockVpp, scope);
  42. // Act and Assert
  43. Assert.Throws<InvalidOperationException>(() => themesImpl.CurrentTheme = "Foo",
  44. @"You must call the ""Themes.Initialize"" method before you call any other method of the ""Themes"" class.");
  45. Assert.Throws<InvalidOperationException>(() => { var x = themesImpl.CurrentTheme; },
  46. @"You must call the ""Themes.Initialize"" method before you call any other method of the ""Themes"" class.");
  47. Assert.Throws<InvalidOperationException>(() => { var x = themesImpl.AvailableThemes; },
  48. @"You must call the ""Themes.Initialize"" method before you call any other method of the ""Themes"" class.");
  49. Assert.Throws<InvalidOperationException>(() => { var x = themesImpl.DefaultTheme; },
  50. @"You must call the ""Themes.Initialize"" method before you call any other method of the ""Themes"" class.");
  51. Assert.Throws<InvalidOperationException>(() => { var x = themesImpl.GetResourcePath("baz"); },
  52. @"You must call the ""Themes.Initialize"" method before you call any other method of the ""Themes"" class.");
  53. Assert.Throws<InvalidOperationException>(() => { var x = themesImpl.GetResourcePath("baz", "some-file"); },
  54. @"You must call the ""Themes.Initialize"" method before you call any other method of the ""Themes"" class.");
  55. }
  56. [Fact]
  57. public void InitializeThrowsIfDefaultThemeDirectoryDoesNotExist()
  58. {
  59. // Arrange
  60. var defaultTheme = "default-theme";
  61. var themeDirectory = "theme-directory";
  62. var scope = new ScopeStorageDictionary();
  63. var themesImpl = new ThemesImplementation(GetVirtualPathProvider(themeDirectory, new Dir("not-default-theme")), scope);
  64. // Act And Assert
  65. Assert.ThrowsArgument(
  66. () => themesImpl.Initialize(themeDirectory: themeDirectory, defaultTheme: defaultTheme),
  67. "defaultTheme",
  68. "Unknown theme 'default-theme'. Ensure that a directory labeled 'default-theme' exists under the theme directory.");
  69. }
  70. [Fact]
  71. public void ThemesImplUsesScopeStorageToStoreProperties()
  72. {
  73. // Arrange
  74. var defaultTheme = "default-theme";
  75. var themeDirectory = "theme-directory";
  76. var scope = new ScopeStorageDictionary();
  77. var themesImpl = new ThemesImplementation(GetVirtualPathProvider(themeDirectory, new Dir(defaultTheme)), scope);
  78. // Act
  79. themesImpl.Initialize(themeDirectory: themeDirectory, defaultTheme: defaultTheme);
  80. // Ensure Theme use scope storage to store properties
  81. Assert.Equal(scope[ThemesImplementation.ThemesInitializedKey], true);
  82. Assert.Equal(scope[ThemesImplementation.ThemeDirectoryKey], themeDirectory);
  83. Assert.Equal(scope[ThemesImplementation.DefaultThemeKey], defaultTheme);
  84. }
  85. [Fact]
  86. public void ThemesImplUsesDefaultThemeWhenNoCurrentThemeIsSpecified()
  87. {
  88. // Arrange
  89. var defaultTheme = "default-theme";
  90. var themeDirectory = "theme-directory";
  91. var scope = new ScopeStorageDictionary();
  92. var themesImpl = new ThemesImplementation(GetVirtualPathProvider(themeDirectory, new Dir(defaultTheme)), scope);
  93. themesImpl.Initialize(themeDirectory, defaultTheme);
  94. // Act and Assert
  95. // CurrentTheme falls back to default theme when null
  96. Assert.Equal(themesImpl.CurrentTheme, defaultTheme);
  97. }
  98. [Fact]
  99. public void ThemesImplThrowsIfCurrentThemeIsInvalid()
  100. {
  101. // Arrange
  102. var defaultTheme = "default-theme";
  103. var themeDirectory = "theme-directory";
  104. var themesImpl = new ThemesImplementation(GetVirtualPathProvider(themeDirectory, new Dir(defaultTheme), new Dir("not-a-random-value")), new ScopeStorageDictionary());
  105. themesImpl.Initialize(themeDirectory, defaultTheme);
  106. // Act and Assert
  107. Assert.ThrowsArgument(() => themesImpl.CurrentTheme = "random-value",
  108. "value",
  109. "Unknown theme 'random-value'. Ensure that a directory labeled 'random-value' exists under the theme directory.");
  110. }
  111. [Fact]
  112. public void ThemesImplUsesScopeStorageToStoreCurrentTheme()
  113. {
  114. // Arrange
  115. var defaultTheme = "default-theme";
  116. var themeDirectory = "theme-directory";
  117. var currentThemeDir = "custom-theme-dir";
  118. var scope = new ScopeStorageDictionary();
  119. var themesImpl = new ThemesImplementation(GetVirtualPathProvider(themeDirectory, new Dir(defaultTheme), new Dir("custom-theme-dir")), scope);
  120. // Act
  121. themesImpl.Initialize(themeDirectory, defaultTheme);
  122. themesImpl.CurrentTheme = currentThemeDir;
  123. // Assert
  124. Assert.Equal(scope[ThemesImplementation.CurrentThemeKey], currentThemeDir);
  125. }
  126. [Fact]
  127. public void GetResourcePathThrowsIfCurrentDirectoryIsNull()
  128. {
  129. // Arrange
  130. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  131. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir(@"mobile", "wp7.css")));
  132. themesImpl.Initialize("themes", "default");
  133. // Act and Assert
  134. Assert.ThrowsArgumentNull(() => themesImpl.GetResourcePath(folder: null, fileName: "wp7.css"), "folder");
  135. }
  136. [Fact]
  137. public void GetResourcePathThrowsIfFileNameIsNullOrEmpty()
  138. {
  139. // Arrange
  140. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  141. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir(@"mobile", "wp7.css")));
  142. themesImpl.Initialize("themes", "default");
  143. // Act and Assert
  144. Assert.ThrowsArgumentNullOrEmptyString(() => themesImpl.GetResourcePath(folder: String.Empty, fileName: null), "fileName");
  145. Assert.ThrowsArgumentNullOrEmptyString(() => themesImpl.GetResourcePath(folder: String.Empty, fileName: String.Empty), "fileName");
  146. }
  147. [Fact]
  148. public void GetResourcePathReturnsItemFromThemeRootIfAvailable()
  149. {
  150. // Arrange
  151. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  152. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir(@"mobile", "wp7.css")));
  153. themesImpl.Initialize("themes", "default");
  154. // Act
  155. themesImpl.CurrentTheme = "mobile";
  156. var themePath = themesImpl.GetResourcePath(fileName: "wp7.css");
  157. // Assert
  158. Assert.Equal(themePath, @"themes/mobile/wp7.css");
  159. }
  160. [Fact]
  161. public void GetResourcePathReturnsItemFromCurrentThemeDirectoryIfAvailable()
  162. {
  163. // Arrange
  164. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  165. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir(@"mobile\styles", "wp7.css"), new Dir(@"default\styles", "main.css")));
  166. themesImpl.Initialize("themes", "default");
  167. // Act
  168. themesImpl.CurrentTheme = "mobile";
  169. var themePath = themesImpl.GetResourcePath(folder: "styles", fileName: "wp7.css");
  170. // Assert
  171. Assert.Equal(themePath, @"themes/mobile/styles/wp7.css");
  172. }
  173. [Fact]
  174. public void GetResourcePathReturnsItemFromDefaultThemeDirectoryIfNotFoundInCurrentThemeDirectory()
  175. {
  176. // Arrange
  177. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  178. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir(@"mobile\styles", "wp7.css"), new Dir(@"default\styles", "main.css")));
  179. themesImpl.Initialize("themes", "default");
  180. // Act
  181. themesImpl.CurrentTheme = "mobile";
  182. var themePath = themesImpl.GetResourcePath(folder: "styles", fileName: "main.css");
  183. // Assert
  184. Assert.Equal(themePath, @"themes/default/styles/main.css");
  185. }
  186. [Fact]
  187. public void GetResourcePathReturnsNullIfDirectoryDoesNotExist()
  188. {
  189. // Arrange
  190. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  191. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir(@"mobile\styles", "wp7.css"), new Dir(@"default\styles", "main.css")));
  192. themesImpl.Initialize("themes", "default");
  193. // Act
  194. themesImpl.CurrentTheme = "mobile";
  195. var themePath = themesImpl.GetResourcePath(folder: "does-not-exist", fileName: "main.css");
  196. // Assert
  197. Assert.Null(themePath);
  198. }
  199. [Fact]
  200. public void GetResourcePathReturnsNullIfItemNotFoundInCurrentAndDefaultThemeDirectories()
  201. {
  202. // Arrange
  203. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  204. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir(@"mobile\styles", "wp7.css"), new Dir(@"default\styles", "main.css")));
  205. themesImpl.Initialize("themes", "default");
  206. // Act
  207. themesImpl.CurrentTheme = "mobile";
  208. var themePath = themesImpl.GetResourcePath(folder: "styles", fileName: "awesome-blinking-text.css");
  209. // Assert
  210. Assert.Null(themePath);
  211. }
  212. [Fact]
  213. public void AvaliableThemesReturnsTopLevelDirectoriesUnderThemeDirectory()
  214. {
  215. // Arrange
  216. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  217. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("mobile"), new Dir("rotary-phone")));
  218. // Act
  219. themesImpl.Initialize("themes", "default");
  220. var themes = themesImpl.AvailableThemes;
  221. // Assert
  222. Assert.Equal(3, themes.Count);
  223. Assert.Equal(themes[0], "default");
  224. Assert.Equal(themes[1], "mobile");
  225. Assert.Equal(themes[2], "rotary-phone");
  226. }
  227. /// <remarks>
  228. /// // folder structure:
  229. /// // /root
  230. /// // /foo
  231. /// // /bar.cs
  232. /// // testing that a file specified as foo/bar in folder root will return null
  233. /// </remarks>
  234. [Fact]
  235. public void FileWithSlash_ReturnsNull()
  236. {
  237. // Arrange
  238. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  239. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("root"), new Dir(@"root\foo", "wp7.css"), new Dir(@"default\styles", "main.css")));
  240. // Act
  241. var actual = themesImpl.FindMatchingFile("root", "foo/bar.cs");
  242. // Assert
  243. Assert.Null(actual);
  244. }
  245. [Fact]
  246. public void DirectoryWithNoFilesReturnsNull()
  247. {
  248. // Arrange
  249. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  250. vpp: GetVirtualPathProvider("themes", new Dir("default"), new Dir("empty-dir")));
  251. // Act
  252. var actual = themesImpl.FindMatchingFile(@"themes\empty-dir", "main.css");
  253. // Assert
  254. Assert.Null(actual);
  255. }
  256. [Fact]
  257. public void MatchingFiles_ReturnsCorrectFile()
  258. {
  259. // Arrange
  260. var themesImpl = new ThemesImplementation(scopeStorage: new ScopeStorageDictionary(),
  261. vpp: GetVirtualPathProvider("themes", new Dir(@"nomatchingfiles", "foo.cs")));
  262. // Act
  263. var bar = themesImpl.FindMatchingFile(@"themes\nomatchingfiles", "bar.cs");
  264. var foo = themesImpl.FindMatchingFile(@"themes\nomatchingfiles", "foo.cs");
  265. // Assert
  266. Assert.Null(bar);
  267. Assert.Equal(@"themes/nomatchingfiles/foo.cs", foo);
  268. }
  269. private static VirtualPathProvider GetVirtualPathProvider(string themeRoot, params Dir[] fileSystem)
  270. {
  271. var mockVpp = new Mock<VirtualPathProvider>();
  272. var dirRoot = new Mock<VirtualDirectory>(themeRoot);
  273. var themeDirectories = new List<VirtualDirectory>();
  274. foreach (var directory in fileSystem)
  275. {
  276. var dir = new Mock<VirtualDirectory>(directory.Name);
  277. var directoryPath = themeRoot + '\\' + directory.Name;
  278. dir.SetupGet(d => d.Name).Returns(directory.Name);
  279. mockVpp.Setup(c => c.GetDirectory(It.Is<string>(p => p.Equals(directoryPath, StringComparison.OrdinalIgnoreCase)))).Returns(dir.Object);
  280. var fileList = new List<VirtualFile>();
  281. foreach (var item in directory.Files)
  282. {
  283. var filePath = directoryPath + '\\' + item;
  284. var file = new Mock<VirtualFile>(filePath);
  285. file.SetupGet(f => f.Name).Returns(item);
  286. fileList.Add(file.Object);
  287. }
  288. dir.SetupGet(c => c.Files).Returns(fileList);
  289. themeDirectories.Add(dir.Object);
  290. }
  291. dirRoot.SetupGet(c => c.Directories).Returns(themeDirectories);
  292. mockVpp.Setup(c => c.GetDirectory(themeRoot)).Returns(dirRoot.Object);
  293. return mockVpp.Object;
  294. }
  295. private class Dir
  296. {
  297. public Dir(string name, params string[] files)
  298. {
  299. Name = name;
  300. Files = files;
  301. }
  302. public string Name { get; private set; }
  303. public IEnumerable<string> Files { get; private set; }
  304. }
  305. }
  306. }