ApplyCssScopesTest.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. using Microsoft.AspNetCore.StaticWebAssets.Tasks;
  4. using Microsoft.Build.Framework;
  5. using Microsoft.Build.Utilities;
  6. using Moq;
  7. namespace Microsoft.NET.Sdk.Razor.Tests
  8. {
  9. public class ApplyAllCssScopesTest
  10. {
  11. [Fact]
  12. public void ApplyAllCssScopes_AppliesScopesToRazorComponentFiles()
  13. {
  14. // Arrange
  15. var taskInstance = new ApplyCssScopes()
  16. {
  17. RazorComponents = new[]
  18. {
  19. new TaskItem("TestFiles/Pages/Counter.razor"),
  20. new TaskItem("TestFiles/Pages/Index.razor"),
  21. },
  22. RazorGenerate = Array.Empty<ITaskItem>(),
  23. ScopedCss = new[]
  24. {
  25. new TaskItem("TestFiles/Pages/Index.razor.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  26. new TaskItem("TestFiles/Pages/Counter.razor.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  27. }
  28. };
  29. // Act
  30. var result = taskInstance.Execute();
  31. // Assert
  32. result.Should().BeTrue();
  33. taskInstance.RazorComponentsWithScopes.Should().HaveCount(2);
  34. taskInstance.RazorComponentsWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/Index.razor" && rcws.GetMetadata("CssScope") == "index-scope");
  35. taskInstance.RazorComponentsWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/Counter.razor" && rcws.GetMetadata("CssScope") == "counter-scope");
  36. }
  37. [Fact]
  38. public void ApplyAllCssScopes_AppliesScopesToRazorViewFiles()
  39. {
  40. // Arrange
  41. var taskInstance = new ApplyCssScopes()
  42. {
  43. RazorGenerate = new[]
  44. {
  45. new TaskItem("TestFiles/Pages/Counter.cshtml"),
  46. new TaskItem("TestFiles/Pages/Index.cshtml"),
  47. },
  48. RazorComponents = Array.Empty<ITaskItem>(),
  49. ScopedCss = new[]
  50. {
  51. new TaskItem("TestFiles/Pages/Index.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  52. new TaskItem("TestFiles/Pages/Counter.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  53. }
  54. };
  55. // Act
  56. var result = taskInstance.Execute();
  57. // Assert
  58. result.Should().BeTrue();
  59. taskInstance.RazorGenerateWithScopes.Should().HaveCount(2);
  60. taskInstance.RazorGenerateWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/Index.cshtml" && rcws.GetMetadata("CssScope") == "index-scope");
  61. taskInstance.RazorGenerateWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/Counter.cshtml" && rcws.GetMetadata("CssScope") == "counter-scope");
  62. }
  63. [Fact]
  64. public void DoesNotApplyCssScopes_ToRazorComponentsWithoutAssociatedFiles()
  65. {
  66. // Arrange
  67. var taskInstance = new ApplyCssScopes()
  68. {
  69. RazorComponents = new[]
  70. {
  71. new TaskItem("TestFiles/Pages/Counter.razor"),
  72. new TaskItem("TestFiles/Pages/Index.razor"),
  73. new TaskItem("TestFiles/Pages/FetchData.razor"),
  74. },
  75. RazorGenerate = Array.Empty<ITaskItem>(),
  76. ScopedCss = new[]
  77. {
  78. new TaskItem("TestFiles/Pages/Index.razor.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  79. new TaskItem("TestFiles/Pages/Counter.razor.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" })
  80. }
  81. };
  82. // Act
  83. var result = taskInstance.Execute();
  84. // Assert
  85. Assert.True(result);
  86. result.Should().BeTrue();
  87. taskInstance.RazorComponentsWithScopes.Should().NotContain(rcws => rcws.ItemSpec == "TestFiles/Pages/Fetchdata.razor");
  88. }
  89. [Fact]
  90. public void DoesNotApplyCssScopes_ToRazorViewsWithoutAssociatedFiles()
  91. {
  92. // Arrange
  93. var taskInstance = new ApplyCssScopes()
  94. {
  95. RazorGenerate = new[]
  96. {
  97. new TaskItem("TestFiles/Pages/Counter.cshtml"),
  98. new TaskItem("TestFiles/Pages/Index.cshtml"),
  99. new TaskItem("TestFiles/Pages/FetchData.cshtml"),
  100. },
  101. RazorComponents = Array.Empty<ITaskItem>(),
  102. ScopedCss = new[]
  103. {
  104. new TaskItem("TestFiles/Pages/Index.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  105. new TaskItem("TestFiles/Pages/Counter.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" })
  106. }
  107. };
  108. // Act
  109. var result = taskInstance.Execute();
  110. // Assert
  111. Assert.True(result);
  112. result.Should().BeTrue();
  113. taskInstance.RazorGenerateWithScopes.Should().NotContain(rcws => rcws.ItemSpec == "TestFiles/Pages/Fetchdata.razor");
  114. }
  115. [Fact]
  116. public void ApplyAllCssScopes_FailsWhenTheScopedCss_DoesNotMatchTheRazorComponent()
  117. {
  118. // Arrange
  119. var taskInstance = new ApplyCssScopes
  120. {
  121. RazorComponents = new[]
  122. {
  123. new TaskItem("TestFiles/Pages/Counter.razor"),
  124. new TaskItem("TestFiles/Pages/Index.razor"),
  125. },
  126. RazorGenerate = Array.Empty<ITaskItem>(),
  127. ScopedCss = new[]
  128. {
  129. new TaskItem("TestFiles/Pages/Index.razor.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  130. new TaskItem("TestFiles/Pages/Counter.razor.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  131. new TaskItem("TestFiles/Pages/Profile.razor.css", new Dictionary<string, string> { ["CssScope"] = "profile-scope" }),
  132. },
  133. BuildEngine = Mock.Of<IBuildEngine>()
  134. };
  135. // Act
  136. var result = taskInstance.Execute();
  137. // Assert
  138. result.Should().BeFalse();
  139. }
  140. [Fact]
  141. public void ApplyAllCssScopes_FailsWhenTheScopedCss_DoesNotMatchTheRazorView()
  142. {
  143. // Arrange
  144. var taskInstance = new ApplyCssScopes
  145. {
  146. RazorGenerate = new[]
  147. {
  148. new TaskItem("TestFiles/Pages/Counter.cshtml"),
  149. new TaskItem("TestFiles/Pages/Index.cshtml"),
  150. },
  151. RazorComponents = Array.Empty<ITaskItem>(),
  152. ScopedCss = new[]
  153. {
  154. new TaskItem("TestFiles/Pages/Index.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  155. new TaskItem("TestFiles/Pages/Counter.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  156. new TaskItem("TestFiles/Pages/Profile.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "profile-scope" }),
  157. },
  158. BuildEngine = Mock.Of<IBuildEngine>()
  159. };
  160. // Act
  161. var result = taskInstance.Execute();
  162. // Assert
  163. result.Should().BeFalse();
  164. }
  165. [Fact]
  166. public void ScopedCssCanDefineAssociatedRazorComponentFile()
  167. {
  168. // Arrange
  169. var taskInstance = new ApplyCssScopes()
  170. {
  171. RazorComponents = new[]
  172. {
  173. new TaskItem("TestFiles/Pages/FetchData.razor")
  174. },
  175. RazorGenerate = Array.Empty<ITaskItem>(),
  176. ScopedCss = new[]
  177. {
  178. new TaskItem("TestFiles/Pages/Profile.razor.css", new Dictionary<string, string>
  179. {
  180. ["CssScope"] = "fetchdata-scope",
  181. ["RazorComponent"] = "TestFiles/Pages/FetchData.razor"
  182. })
  183. }
  184. };
  185. // Act
  186. var result = taskInstance.Execute();
  187. // Assert
  188. result.Should().BeTrue();
  189. taskInstance.RazorComponentsWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/FetchData.razor" && rcws.GetMetadata("CssScope") == "fetchdata-scope");
  190. }
  191. [Fact]
  192. public void ScopedCssCanDefineAssociatedRazorGenerateFile()
  193. {
  194. // Arrange
  195. var taskInstance = new ApplyCssScopes()
  196. {
  197. RazorGenerate = new[]
  198. {
  199. new TaskItem("TestFiles/Pages/FetchData.cshtml")
  200. },
  201. RazorComponents = Array.Empty<ITaskItem>(),
  202. ScopedCss = new[]
  203. {
  204. new TaskItem("TestFiles/Pages/Profile.cshtml.css", new Dictionary<string, string>
  205. {
  206. ["CssScope"] = "fetchdata-scope",
  207. ["View"] = "TestFiles/Pages/FetchData.cshtml"
  208. })
  209. }
  210. };
  211. // Act
  212. var result = taskInstance.Execute();
  213. // Assert
  214. result.Should().BeTrue();
  215. taskInstance.RazorGenerateWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/FetchData.cshtml" && rcws.GetMetadata("CssScope") == "fetchdata-scope");
  216. }
  217. [Fact]
  218. public void ApplyAllCssScopes_FailsWhenMultipleScopedCssFiles_MatchTheSameRazorComponent()
  219. {
  220. // Arrange
  221. var taskInstance = new ApplyCssScopes
  222. {
  223. RazorComponents = new[]
  224. {
  225. new TaskItem("TestFiles/Pages/Counter.razor"),
  226. new TaskItem("TestFiles/Pages/Index.razor"),
  227. },
  228. RazorGenerate = Array.Empty<ITaskItem>(),
  229. ScopedCss = new[]
  230. {
  231. new TaskItem("TestFiles/Pages/Index.razor.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  232. new TaskItem("TestFiles/Pages/Counter.razor.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  233. new TaskItem("TestFiles/Pages/Profile.razor.css", new Dictionary<string, string>
  234. {
  235. ["CssScope"] = "conflict-scope",
  236. ["RazorComponent"] = "TestFiles/Pages/Index.razor"
  237. }),
  238. },
  239. BuildEngine = Mock.Of<IBuildEngine>()
  240. };
  241. // Act
  242. var result = taskInstance.Execute();
  243. // Assert
  244. result.Should().BeFalse();
  245. }
  246. [Fact]
  247. public void ApplyAllCssScopes_FailsWhenMultipleScopedCssFiles_MatchTheSameRazorView()
  248. {
  249. // Arrange
  250. var taskInstance = new ApplyCssScopes
  251. {
  252. RazorGenerate = new[]
  253. {
  254. new TaskItem("TestFiles/Pages/Counter.cshtml"),
  255. new TaskItem("TestFiles/Pages/Index.cshtml"),
  256. },
  257. RazorComponents = Array.Empty<ITaskItem>(),
  258. ScopedCss = new[]
  259. {
  260. new TaskItem("TestFiles/Pages/Index.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  261. new TaskItem("TestFiles/Pages/Counter.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  262. new TaskItem("TestFiles/Pages/Profile.cshtml.css", new Dictionary<string, string>
  263. {
  264. ["CssScope"] = "conflict-scope",
  265. ["View"] = "TestFiles/Pages/Index.cshtml"
  266. }),
  267. },
  268. BuildEngine = Mock.Of<IBuildEngine>()
  269. };
  270. // Act
  271. var result = taskInstance.Execute();
  272. // Assert
  273. result.Should().BeFalse();
  274. }
  275. [Fact]
  276. public void ApplyAllCssScopes_AppliesScopesToRazorComponentAndViewFiles()
  277. {
  278. // Arrange
  279. var taskInstance = new ApplyCssScopes()
  280. {
  281. RazorComponents = new[]
  282. {
  283. new TaskItem("TestFiles/Pages/Counter.razor"),
  284. new TaskItem("TestFiles/Pages/Index.razor"),
  285. },
  286. RazorGenerate = new[]
  287. {
  288. new TaskItem("TestFiles/Pages/Home.cshtml"),
  289. new TaskItem("TestFiles/Pages/_Host.cshtml"),
  290. },
  291. ScopedCss = new[]
  292. {
  293. new TaskItem("TestFiles/Pages/Home.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "home-scope" }),
  294. new TaskItem("TestFiles/Pages/_Host.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "_host-scope" }),
  295. new TaskItem("TestFiles/Pages/Index.razor.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  296. new TaskItem("TestFiles/Pages/Counter.razor.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  297. }
  298. };
  299. // Act
  300. var result = taskInstance.Execute();
  301. // Assert
  302. result.Should().BeTrue();
  303. taskInstance.RazorComponentsWithScopes.Should().HaveCount(2);
  304. taskInstance.RazorComponentsWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/Index.razor" && rcws.GetMetadata("CssScope") == "index-scope");
  305. taskInstance.RazorComponentsWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/Counter.razor" && rcws.GetMetadata("CssScope") == "counter-scope");
  306. taskInstance.RazorGenerateWithScopes.Should().HaveCount(2);
  307. taskInstance.RazorGenerateWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/Home.cshtml" && rcws.GetMetadata("CssScope") == "home-scope");
  308. taskInstance.RazorGenerateWithScopes.Should().ContainSingle(rcws => rcws.ItemSpec == "TestFiles/Pages/_Host.cshtml" && rcws.GetMetadata("CssScope") == "_host-scope");
  309. }
  310. [Fact]
  311. public void ApplyAllCssScopes_ScopedCssComponentsDontMatchWithScopedCssViewStylesAndViceversa()
  312. {
  313. // Arrange
  314. var taskInstance = new ApplyCssScopes
  315. {
  316. RazorComponents = new[]
  317. {
  318. new TaskItem("TestFiles/Pages/Counter.razor"),
  319. new TaskItem("TestFiles/Pages/Index.razor"),
  320. },
  321. RazorGenerate = new[]
  322. {
  323. new TaskItem("TestFiles/Pages/Home.cshtml"),
  324. new TaskItem("TestFiles/Pages/_Host.cshtml"),
  325. },
  326. ScopedCss = new[]
  327. {
  328. new TaskItem("TestFiles/Pages/Home.razor.css", new Dictionary<string, string> { ["CssScope"] = "home-scope" }),
  329. new TaskItem("TestFiles/Pages/_Host.razor.css", new Dictionary<string, string> { ["CssScope"] = "_host-scope" }),
  330. new TaskItem("TestFiles/Pages/Index.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "index-scope" }),
  331. new TaskItem("TestFiles/Pages/Counter.cshtml.css", new Dictionary<string, string> { ["CssScope"] = "counter-scope" }),
  332. },
  333. BuildEngine = Mock.Of<IBuildEngine>()
  334. };
  335. // Act
  336. var result = taskInstance.Execute();
  337. // Assert
  338. result.Should().BeFalse();
  339. }
  340. }
  341. }