PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/test/System.Web.WebPages.Test/WebPage/LayoutTest.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 714 lines | 525 code | 71 blank | 118 comment | 0 complexity | c1d291e57e5933f213d1ec2123374d14 MD5 | raw file
  1. using System.Globalization;
  2. using System.Web.WebPages.Resources;
  3. using Moq;
  4. using Xunit;
  5. using Assert = Microsoft.TestCommon.AssertEx;
  6. namespace System.Web.WebPages.Test
  7. {
  8. public class LayoutTest
  9. {
  10. [Fact]
  11. public void LayoutBasicTest()
  12. {
  13. var layoutPath = "~/Layout.cshtml";
  14. LayoutBasicTestInternal(layoutPath);
  15. }
  16. [Fact]
  17. public void RelativeLayoutPageTest()
  18. {
  19. var pagePath = "~/MyApp/index.cshtml";
  20. var layoutPath = "~/MyFiles/Layout.cshtml";
  21. var layoutPage = "../MyFiles/Layout.cshtml";
  22. LayoutBasicTestInternal(layoutPath, pagePath, layoutPage);
  23. }
  24. [Fact]
  25. public void AppRelativeLayoutPageTest()
  26. {
  27. var pagePath = "~/MyApp/index.cshtml";
  28. var layoutPath = "~/MyFiles/Layout.cshtml";
  29. var layoutPage = "~/MyFiles/Layout.cshtml";
  30. LayoutBasicTestInternal(layoutPath, pagePath, layoutPage);
  31. }
  32. [Fact]
  33. public void SourceFileWithLayoutPageTest()
  34. {
  35. // Arrange
  36. var pagePath = "~/MyApp/index.cshtml";
  37. var layoutPath = "~/MyFiles/Layout.cshtml";
  38. var layoutPage = "~/MyFiles/Layout.cshtml";
  39. var content = "hello world";
  40. var title = "MyPage";
  41. var page = CreatePageWithLayout(
  42. p =>
  43. {
  44. p.PageData["Title"] = title;
  45. p.WriteLiteral(content);
  46. },
  47. p =>
  48. {
  49. p.WriteLiteral(p.PageData["Title"]);
  50. p.Write(p.RenderBody());
  51. }, pagePath, layoutPath, layoutPage);
  52. var request = new Mock<HttpRequestBase>();
  53. request.SetupGet(c => c.Path).Returns("/myapp/index.cshtml");
  54. request.SetupGet(c => c.RawUrl).Returns("http://localhost:8080/index.cshtml");
  55. request.SetupGet(c => c.IsLocal).Returns(true);
  56. request.Setup(c => c.MapPath(It.IsAny<string>())).Returns<string>(c => c);
  57. request.Setup(c => c.Browser.IsMobileDevice).Returns(false);
  58. request.Setup(c => c.Cookies).Returns(new HttpCookieCollection());
  59. var result = Utils.RenderWebPage(page, request: request.Object);
  60. Assert.Equal(2, page.PageContext.SourceFiles.Count);
  61. Assert.True(page.PageContext.SourceFiles.Contains("~/MyApp/index.cshtml"));
  62. Assert.True(page.PageContext.SourceFiles.Contains("~/MyFiles/Layout.cshtml"));
  63. }
  64. private static void LayoutBasicTestInternal(string layoutPath, string pagePath = "~/index.cshtml", string layoutPage = "Layout.cshtml")
  65. {
  66. // The page ~/index.cshtml does the following:
  67. // PageData["Title"] = "MyPage";
  68. // Layout = "Layout.cshtml";
  69. // WriteLiteral("hello world");
  70. //
  71. // The layout page ~/Layout.cshtml does the following:
  72. // WriteLiteral(Title);
  73. // RenderBody();
  74. //
  75. // Expected rendered result is "MyPagehello world"
  76. var content = "hello world";
  77. var title = "MyPage";
  78. var result = RenderPageWithLayout(
  79. p =>
  80. {
  81. p.PageData["Title"] = title;
  82. p.WriteLiteral(content);
  83. },
  84. p =>
  85. {
  86. p.WriteLiteral(p.PageData["Title"]);
  87. p.Write(p.RenderBody());
  88. },
  89. pagePath, layoutPath, layoutPage);
  90. Assert.Equal(title + content, result);
  91. }
  92. [Fact]
  93. public void LayoutNestedTest()
  94. {
  95. // Testing nested layout pages
  96. //
  97. // The page ~/index.cshtml does the following:
  98. // PageData["Title"] = "MyPage";
  99. // Layout = "Layout1.cshtml";
  100. // WriteLiteral("hello world");
  101. //
  102. // The first layout page ~/Layout1.cshtml does the following:
  103. // Layout = "Layout2.cshtml";
  104. // WriteLiteral("<layout1>");
  105. // RenderBody();
  106. // WriteLiteral("</layout1>");
  107. //
  108. // The second layout page ~/Layout2.cshtml does the following:
  109. // WriteLiteral(Title);
  110. // WriteLiteral("<layout2>");
  111. // RenderBody();
  112. // WriteLiteral("</layout2>");
  113. //
  114. // Expected rendered result is "MyPage<layout2><layout1>hello world</layout1></layout2>"
  115. var layout2Path = "~/Layout2.cshtml";
  116. var layout2 = Utils.CreatePage(
  117. p =>
  118. {
  119. p.WriteLiteral(p.PageData["Title"]);
  120. p.WriteLiteral("<layout2>");
  121. p.Write(p.RenderBody());
  122. p.WriteLiteral("</layout2>");
  123. },
  124. layout2Path);
  125. var layout1Path = "~/Layout1.cshtml";
  126. var layout1 = Utils.CreatePage(
  127. p =>
  128. {
  129. p.Layout = "Layout2.cshtml";
  130. p.WriteLiteral("<layout1>");
  131. p.Write(p.RenderBody());
  132. p.WriteLiteral("</layout1>");
  133. },
  134. layout1Path);
  135. var page = Utils.CreatePage(
  136. p =>
  137. {
  138. p.PageData["Title"] = "MyPage";
  139. p.Layout = "Layout1.cshtml";
  140. p.WriteLiteral("hello world");
  141. });
  142. Utils.AssignObjectFactoriesAndDisplayModeProvider(page, layout1, layout2);
  143. var result = Utils.RenderWebPage(page);
  144. Assert.Equal("MyPage<layout2><layout1>hello world</layout1></layout2>", result);
  145. }
  146. [Fact]
  147. public void LayoutSectionsTest()
  148. {
  149. // Testing nested layout pages with sections
  150. //
  151. // The page ~/index.cshtml does the following:
  152. // PageData["Title"] = "MyPage";
  153. // Layout = "Layout1.cshtml";
  154. // DefineSection("header1", () => {
  155. // WriteLiteral("index header");
  156. // });
  157. // WriteLiteral("hello world");
  158. // DefineSection("footer1", () => {
  159. // WriteLiteral("index footer");
  160. // });
  161. //
  162. // The first layout page ~/Layout1.cshtml does the following:
  163. // Layout = "Layout2.cshtml";
  164. // DefineSection("header2", () => {
  165. // WriteLiteral("<layout1 header>");
  166. // RenderSection("header1");
  167. // WriteLiteral("</layout1 header>");
  168. // });
  169. // WriteLiteral("<layout1>");
  170. // RenderBody();
  171. // WriteLiteral("</layout1>");
  172. // DefineSection("footer2", () => {
  173. // WriteLiteral("<layout1 footer>");
  174. // RenderSection("header2");
  175. // WriteLiteral("</layout1 footer>");
  176. // });
  177. //
  178. // The second layout page ~/Layout2.cshtml does the following:
  179. // WriteLiteral(Title);
  180. // WriteLiteral("\n<layout2 header>");
  181. // RenderSection("header2");
  182. // WriteLiteral("</layout2 header>\n");
  183. // WriteLiteral("<layout2>");
  184. // RenderBody();
  185. // WriteLiteral("</layout2>\n");
  186. // WriteLiteral("<layout2 footer>");
  187. // RenderSection("footer");
  188. // WriteLiteral("</layout2 footer>");
  189. //
  190. // Expected rendered result is:
  191. // MyPage
  192. // <layout2 header><layout1 header>index header</layout1 header></layout2 header>
  193. // <layout2><layout1>hello world</layout1></layout2>"
  194. // <layout2 footer><layout1 footer>index footer</layout1 footer></layout2 footer>
  195. var layout2Path = "~/Layout2.cshtml";
  196. var layout2 = Utils.CreatePage(
  197. p =>
  198. {
  199. p.WriteLiteral(p.PageData["Title"]);
  200. p.WriteLiteral("\r\n");
  201. p.WriteLiteral("<layout2 header>");
  202. p.Write(p.RenderSection("header2"));
  203. p.WriteLiteral("</layout2 header>");
  204. p.WriteLiteral("\r\n");
  205. p.WriteLiteral("<layout2>");
  206. p.Write(p.RenderBody());
  207. p.WriteLiteral("</layout2>");
  208. p.WriteLiteral("\r\n");
  209. p.WriteLiteral("<layout2 footer>");
  210. p.Write(p.RenderSection("footer2"));
  211. p.WriteLiteral("</layout2 footer>");
  212. },
  213. layout2Path);
  214. var layout1Path = "~/Layout1.cshtml";
  215. var layout1 = Utils.CreatePage(
  216. p =>
  217. {
  218. p.Layout = "Layout2.cshtml";
  219. p.DefineSection("header2", () =>
  220. {
  221. p.WriteLiteral("<layout1 header>");
  222. p.Write(p.RenderSection("header1"));
  223. p.WriteLiteral("</layout1 header>");
  224. });
  225. p.WriteLiteral("<layout1>");
  226. p.Write(p.RenderBody());
  227. p.WriteLiteral("</layout1>");
  228. p.DefineSection("footer2", () =>
  229. {
  230. p.WriteLiteral("<layout1 footer>");
  231. p.Write(p.RenderSection("footer1"));
  232. p.WriteLiteral("</layout1 footer>");
  233. });
  234. },
  235. layout1Path);
  236. var page = Utils.CreatePage(
  237. p =>
  238. {
  239. p.PageData["Title"] = "MyPage";
  240. p.Layout = "Layout1.cshtml";
  241. p.DefineSection("header1", () => { p.WriteLiteral("index header"); });
  242. p.WriteLiteral("hello world");
  243. p.DefineSection("footer1", () => { p.WriteLiteral("index footer"); });
  244. });
  245. Utils.AssignObjectFactoriesAndDisplayModeProvider(page, layout1, layout2);
  246. var result = Utils.RenderWebPage(page);
  247. var expected = @"MyPage
  248. <layout2 header><layout1 header>index header</layout1 header></layout2 header>
  249. <layout2><layout1>hello world</layout1></layout2>
  250. <layout2 footer><layout1 footer>index footer</layout1 footer></layout2 footer>";
  251. Assert.Equal(expected, result);
  252. }
  253. [Fact]
  254. public void LayoutSectionsNestedNamesTest()
  255. {
  256. // Tests nested layout using the same section names at different levels.
  257. //
  258. // The page ~/index.cshtml does the following:
  259. // Layout = "Layout1.cshtml";
  260. // @section body {
  261. // body in index
  262. // }
  263. //
  264. // The page ~/layout1.cshtml does the following:
  265. // Layout = "Layout2.cshtml";
  266. // @section body {
  267. // body in layout1
  268. // @RenderSection("body")
  269. // }
  270. //
  271. // The page ~/layout2.cshtml does the following:
  272. // body in layout2
  273. // @RenderSection("body")
  274. //
  275. // Expected rendered result is:
  276. // body in layout2 body in layout1 body in index
  277. var layout2Path = "~/Layout2.cshtml";
  278. var layout2 = Utils.CreatePage(
  279. p =>
  280. {
  281. p.WriteLiteral("body in layout2 ");
  282. p.Write(p.RenderSection("body"));
  283. },
  284. layout2Path);
  285. var layout1Path = "~/Layout1.cshtml";
  286. var layout1 = Utils.CreatePage(
  287. p =>
  288. {
  289. p.Layout = "Layout2.cshtml";
  290. p.DefineSection("body", () =>
  291. {
  292. p.WriteLiteral("body in layout1 ");
  293. p.Write(p.RenderSection("body"));
  294. });
  295. },
  296. layout1Path);
  297. var page = Utils.CreatePage(
  298. p =>
  299. {
  300. p.Layout = "Layout1.cshtml";
  301. p.DefineSection("body", () => { p.WriteLiteral("body in index"); });
  302. });
  303. Utils.AssignObjectFactoriesAndDisplayModeProvider(page, layout1, layout2);
  304. var result = Utils.RenderWebPage(page);
  305. var expected = "body in layout2 body in layout1 body in index";
  306. Assert.Equal(expected, result);
  307. }
  308. [Fact]
  309. public void CaseInsensitiveSectionNamesTest()
  310. {
  311. var page = CreatePageWithLayout(
  312. p =>
  313. {
  314. p.Write("123");
  315. p.DefineSection("abc", () => { p.Write("abc"); });
  316. p.DefineSection("XYZ", () => { p.Write("xyz"); });
  317. p.Write("456");
  318. },
  319. p =>
  320. {
  321. p.Write(p.RenderSection("AbC"));
  322. p.Write(p.RenderSection("xyZ"));
  323. p.Write(p.RenderBody());
  324. });
  325. var result = Utils.RenderWebPage(page);
  326. var expected = "abcxyz123456";
  327. Assert.Equal(expected, result);
  328. }
  329. [Fact]
  330. public void MissingLayoutPageTest()
  331. {
  332. var layoutPage = "Layout.cshtml";
  333. var page = Utils.CreatePage(
  334. p =>
  335. {
  336. p.PageData["Title"] = "MyPage";
  337. p.Layout = layoutPage;
  338. });
  339. var layoutPath1 = "~/Layout.cshtml";
  340. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  341. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_LayoutPageNotFound, layoutPage, layoutPath1));
  342. }
  343. [Fact]
  344. public void RenderBodyAlreadyCalledTest()
  345. {
  346. // Layout page calls RenderBody more than once.
  347. var page = CreatePageWithLayout(
  348. p => { },
  349. p =>
  350. {
  351. p.Write(p.RenderBody());
  352. p.Write(p.RenderBody());
  353. });
  354. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page), WebPageResources.WebPage_RenderBodyAlreadyCalled);
  355. }
  356. [Fact]
  357. public void RenderBodyNotCalledTest()
  358. {
  359. // Page does not define any sections, but layout page does not call RenderBody
  360. var layoutPath = "~/Layout.cshtml";
  361. var page = CreatePageWithLayout(
  362. p => { },
  363. p => { },
  364. layoutPath: layoutPath);
  365. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  366. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_RenderBodyNotCalled, layoutPath));
  367. }
  368. [Fact]
  369. public void RenderBodyCalledDirectlyTest()
  370. {
  371. // A Page that is not a layout page calls the RenderBody method
  372. var page = Utils.CreatePage(p => { p.RenderBody(); });
  373. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  374. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_CannotRequestDirectly, "~/index.cshtml", "RenderBody"));
  375. }
  376. [Fact]
  377. public void RenderSectionCalledDirectlyTest()
  378. {
  379. // A Page that is not a layout page calls the RenderBody method
  380. var page = Utils.CreatePage(p => { p.RenderSection(""); });
  381. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  382. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_CannotRequestDirectly, "~/index.cshtml", "RenderSection"));
  383. }
  384. [Fact]
  385. public void SectionAlreadyDefinedTest()
  386. {
  387. // The page calls DefineSection more than once on the same name
  388. var sectionName = "header";
  389. var page = Utils.CreatePage(p =>
  390. {
  391. p.Layout = "Layout.cshtml";
  392. p.DefineSection(sectionName, () => { });
  393. p.DefineSection(sectionName, () => { });
  394. });
  395. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  396. String.Format(CultureInfo.InvariantCulture, WebPageResources.WebPage_SectionAleadyDefined, sectionName));
  397. }
  398. [Fact]
  399. public void SectionAlreadyDefinedCaseInsensitiveTest()
  400. {
  401. // The page calls DefineSection more than once on the same name but with different casing
  402. var name1 = "section1";
  403. var name2 = "SecTion1";
  404. var page = Utils.CreatePage(p =>
  405. {
  406. p.Layout = "Layout.cshtml";
  407. p.DefineSection(name1, () => { });
  408. p.DefineSection(name2, () => { });
  409. });
  410. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  411. String.Format(CultureInfo.InvariantCulture, WebPageResources.WebPage_SectionAleadyDefined, name2));
  412. }
  413. [Fact]
  414. public void SectionNotDefinedTest()
  415. {
  416. // Layout page calls RenderSection on a name that has not been defined.
  417. var sectionName = "NoSuchSection";
  418. var page = CreatePageWithLayout(
  419. p => { },
  420. p => { p.Write(p.RenderSection(sectionName)); });
  421. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  422. String.Format(CultureInfo.InvariantCulture, WebPageResources.WebPage_SectionNotDefined, sectionName));
  423. }
  424. [Fact]
  425. public void SectionAlreadyRenderedTest()
  426. {
  427. // Layout page calls RenderSection on the same name more than once.
  428. var sectionName = "header";
  429. var page = CreatePageWithLayout(
  430. p =>
  431. {
  432. p.Layout = "Layout.cshtml";
  433. p.DefineSection(sectionName, () => { });
  434. },
  435. p =>
  436. {
  437. p.Write(p.RenderSection(sectionName));
  438. p.Write(p.RenderSection(sectionName));
  439. });
  440. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  441. String.Format(CultureInfo.InvariantCulture, WebPageResources.WebPage_SectionAleadyRendered, sectionName));
  442. }
  443. [Fact]
  444. public void SectionsNotRenderedTest()
  445. {
  446. // Layout page does not render all the defined sections.
  447. var layoutPath = "~/Layout.cshtml";
  448. var sectionName1 = "section1";
  449. var sectionName2 = "section2";
  450. var sectionName3 = "section3";
  451. var sectionName4 = "section4";
  452. var sectionName5 = "section5";
  453. // A dummy section action that does nothing
  454. SectionWriter sectionAction = () => { };
  455. // The page defines 5 sections.
  456. var page = CreatePageWithLayout(
  457. p =>
  458. {
  459. p.DefineSection(sectionName1, sectionAction);
  460. p.DefineSection(sectionName2, sectionAction);
  461. p.DefineSection(sectionName3, sectionAction);
  462. p.DefineSection(sectionName4, sectionAction);
  463. p.DefineSection(sectionName5, sectionAction);
  464. },
  465. // The layout page renders only two of the sections
  466. p =>
  467. {
  468. p.Write(p.RenderSection(sectionName2));
  469. p.Write(p.RenderSection(sectionName4));
  470. },
  471. layoutPath: layoutPath);
  472. var sectionsNotRendered = "section1; section3; section5";
  473. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  474. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_SectionsNotRendered, layoutPath, sectionsNotRendered));
  475. }
  476. [Fact]
  477. public void SectionsNotRenderedRenderBodyTest()
  478. {
  479. // Layout page does not render all the defined sections, but it calls RenderBody.
  480. var layoutPath = "~/Layout.cshtml";
  481. var sectionName1 = "section1";
  482. var sectionName2 = "section2";
  483. // A dummy section action that does nothing
  484. SectionWriter sectionAction = () => { };
  485. var page = CreatePageWithLayout(
  486. p =>
  487. {
  488. p.DefineSection(sectionName1, sectionAction);
  489. p.DefineSection(sectionName2, sectionAction);
  490. },
  491. // The layout page only calls RenderBody
  492. p => { p.Write(p.RenderBody()); },
  493. layoutPath: layoutPath);
  494. var sectionsNotRendered = "section1; section2";
  495. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  496. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_SectionsNotRendered, layoutPath, sectionsNotRendered));
  497. }
  498. [Fact]
  499. public void InvalidPageTypeTest()
  500. {
  501. var layoutPath = "~/Layout.js";
  502. var contents = "hello world";
  503. var page = Utils.CreatePage(p =>
  504. {
  505. p.Layout = layoutPath;
  506. p.Write(contents);
  507. });
  508. var layoutPage = new object();
  509. var objectFactory = new Mock<IVirtualPathFactory>();
  510. objectFactory.Setup(c => c.Exists(It.IsAny<string>())).Returns<string>(p => layoutPath.Equals(p, StringComparison.OrdinalIgnoreCase));
  511. objectFactory.Setup(c => c.CreateInstance(It.IsAny<string>())).Returns<string>(_ => layoutPage as WebPageBase);
  512. page.VirtualPathFactory = objectFactory.Object;
  513. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  514. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_InvalidPageType, layoutPath));
  515. Assert.Throws<HttpException>(() => Utils.RenderWebPage(page),
  516. String.Format(CultureInfo.CurrentCulture, WebPageResources.WebPage_InvalidPageType, layoutPath));
  517. }
  518. [Fact]
  519. public void ValidPageTypeTest()
  520. {
  521. var layoutPath = "~/Layout.js";
  522. var contents = "hello world";
  523. var page = Utils.CreatePage(p =>
  524. {
  525. p.Layout = layoutPath;
  526. p.Write(contents);
  527. });
  528. var layoutPage = Utils.CreatePage(p => p.WriteLiteral(p.RenderBody()), layoutPath);
  529. Utils.AssignObjectFactoriesAndDisplayModeProvider(page, layoutPage);
  530. Assert.Equal(contents, Utils.RenderWebPage(page));
  531. }
  532. [Fact]
  533. public void IsSectionDefinedTest()
  534. {
  535. // Tests for the IsSectionDefined method
  536. // Only sections named section1 and section3 are defined.
  537. var page = CreatePageWithLayout(
  538. p =>
  539. {
  540. p.DefineSection("section1", () => { });
  541. p.DefineSection("section3", () => { });
  542. },
  543. p =>
  544. {
  545. p.Write(p.RenderSection("section1"));
  546. p.Write(p.RenderSection("section3"));
  547. p.Write("section1: " + p.IsSectionDefined("section1") + "; ");
  548. p.Write("section2: " + p.IsSectionDefined("section2") + "; ");
  549. p.Write("section3: " + p.IsSectionDefined("section3") + "; ");
  550. p.Write("section4: " + p.IsSectionDefined("section4") + "; ");
  551. });
  552. var result = Utils.RenderWebPage(page);
  553. var expected = "section1: True; section2: False; section3: True; section4: False; ";
  554. Assert.Equal(expected, result);
  555. }
  556. [Fact]
  557. public void OptionalSectionsTest()
  558. {
  559. // Only sections named section1 and section3 are defined.
  560. var page = CreatePageWithLayout(
  561. p =>
  562. {
  563. p.DefineSection("section1", () => { p.Write("section1 "); });
  564. p.DefineSection("section3", () => { p.Write("section3"); });
  565. },
  566. p =>
  567. {
  568. p.Write(p.RenderSection("section1", required: false));
  569. p.Write(p.RenderSection("section2", required: false));
  570. p.Write(p.RenderSection("section3", required: false));
  571. p.Write(p.RenderSection("section4", required: false));
  572. });
  573. var result = Utils.RenderWebPage(page);
  574. var expected = "section1 section3";
  575. Assert.Equal(expected, result);
  576. }
  577. [Fact]
  578. public void PageDataTest()
  579. {
  580. // Layout page uses items in PageData set by content page
  581. var contents = "my contents";
  582. var page = CreatePageWithLayout(
  583. p =>
  584. {
  585. p.PageData["contents"] = contents;
  586. p.Write(" body");
  587. },
  588. p =>
  589. {
  590. p.Write(p.PageData["contents"]);
  591. p.Write(p.RenderBody());
  592. });
  593. var result = Utils.RenderWebPage(page);
  594. var expected = contents + " body";
  595. Assert.Equal(expected, result);
  596. }
  597. [Fact]
  598. public void RenderPageAndLayoutPage()
  599. {
  600. //Dev10 bug 928341 - a page that has a layout page, and the page calls RenderPage should not cause an error
  601. var layoutPagePath = "~/layout.cshtml";
  602. var page = Utils.CreatePage(p =>
  603. {
  604. p.DefineSection("foo", () => { p.Write("This is foo"); });
  605. p.Write(p.RenderPage("bar.cshtml"));
  606. p.Layout = layoutPagePath;
  607. });
  608. var layoutPage = Utils.CreatePage(p =>
  609. {
  610. p.Write(p.RenderBody());
  611. p.Write(" ");
  612. p.Write(p.RenderSection("foo"));
  613. }, layoutPagePath);
  614. var subPage = Utils.CreatePage(p => p.Write("This is bar"), "~/bar.cshtml");
  615. Utils.AssignObjectFactoriesAndDisplayModeProvider(page, layoutPage, subPage);
  616. var result = Utils.RenderWebPage(page);
  617. var expected = "This is bar This is foo";
  618. Assert.Equal(expected, result);
  619. }
  620. public static string RenderPageWithLayout(Action<WebPage> pageExecuteAction, Action<WebPage> layoutExecuteAction,
  621. string pagePath = "~/index.cshtml", string layoutPath = "~/Layout.cshtml", string layoutPage = "Layout.cshtml")
  622. {
  623. var page = CreatePageWithLayout(pageExecuteAction, layoutExecuteAction, pagePath, layoutPath, layoutPage);
  624. return Utils.RenderWebPage(page);
  625. }
  626. public static MockPage CreatePageWithLayout(Action<WebPage> pageExecuteAction, Action<WebPage> layoutExecuteAction,
  627. string pagePath = "~/index.cshtml", string layoutPath = "~/Layout.cshtml", string layoutPageName = "Layout.cshtml")
  628. {
  629. var page = Utils.CreatePage(
  630. p =>
  631. {
  632. p.Layout = layoutPageName;
  633. pageExecuteAction(p);
  634. },
  635. pagePath);
  636. var layoutPage = Utils.CreatePage(
  637. p => { layoutExecuteAction(p); },
  638. layoutPath);
  639. Utils.AssignObjectFactoriesAndDisplayModeProvider(layoutPage, page);
  640. return page;
  641. }
  642. }
  643. }