001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.util.tester; 018 019import static org.junit.jupiter.api.Assertions.assertEquals; 020import static org.junit.jupiter.api.Assertions.assertFalse; 021import static org.junit.jupiter.api.Assertions.assertNotNull; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023import static org.junit.jupiter.api.Assertions.fail; 024 025import java.io.Serializable; 026import java.util.ArrayList; 027import java.util.Arrays; 028import java.util.List; 029import java.util.Locale; 030 031import javax.servlet.ServletContext; 032 033import org.apache.commons.collections4.CollectionUtils; 034import org.apache.wicket.Component; 035import org.apache.wicket.MarkupContainer; 036import org.apache.wicket.Page; 037import org.apache.wicket.behavior.AbstractAjaxBehavior; 038import org.apache.wicket.behavior.Behavior; 039import org.apache.wicket.feedback.ExactLevelFeedbackMessageFilter; 040import org.apache.wicket.feedback.FeedbackMessage; 041import org.apache.wicket.feedback.IFeedback; 042import org.apache.wicket.feedback.IFeedbackMessageFilter; 043import org.apache.wicket.markup.IMarkupFragment; 044import org.apache.wicket.markup.html.WebPage; 045import org.apache.wicket.markup.html.basic.Label; 046import org.apache.wicket.markup.html.form.ValidationErrorFeedback; 047import org.apache.wicket.markup.html.link.BookmarkablePageLink; 048import org.apache.wicket.markup.html.panel.FeedbackPanel; 049import org.apache.wicket.model.IModel; 050import org.apache.wicket.protocol.http.WebApplication; 051import org.apache.wicket.request.mapper.parameter.PageParameters; 052import org.apache.wicket.util.lang.Args; 053import org.apache.wicket.util.lang.Objects; 054import org.slf4j.Logger; 055import org.slf4j.LoggerFactory; 056 057/** 058 * A helper class to ease unit testing of Wicket applications without the need for a servlet 059 * container. To start a test, either use <code>startPage</code> or <code>startPanel</code>: 060 * 061 * <pre> 062 * // production page 063 * public class MyPage extends WebPage 064 * { 065 * public MyPage() 066 * { 067 * add(new Label("myMessage", "Hello!")); 068 * add(new Link("toYourPage") 069 * { 070 * public void onClick() 071 * { 072 * setResponsePage(new YourPage("Hi!")); 073 * } 074 * }); 075 * } 076 * } 077 * </pre> 078 * 079 * <pre> 080 * // test code 081 * private WicketTester tester; 082 * 083 * public void setUp() 084 * { 085 * tester = new WicketTester(); 086 * } 087 * 088 * public void testRenderMyPage() 089 * { 090 * // start and render the test page 091 * tester.startPage(MyPage.class); 092 * // assert rendered page class 093 * tester.assertRenderedPage(MyPage.class); 094 * // assert rendered label component 095 * tester.assertLabel("myMessage", "Hello!"); 096 * } 097 * </pre> 098 * 099 * The above example is straight forward: start <code>MyPage.class</code> and assert 100 * <code>Label</code> it rendered. Next, we try to navigate through a <code>Link</code>: 101 * 102 * <pre> 103 * // production page 104 * public class YourPage extends WebPage 105 * { 106 * public YourPage(String message) 107 * { 108 * add(new Label("yourMessage", message)); 109 * info("Wicket Rocks ;-)"); 110 * } 111 * } 112 * 113 * // test code 114 * public void testLinkToYourPage() 115 * { 116 * tester.startPage(MyPage.class); 117 * // click link and render 118 * tester.clickLink("toYourPage"); 119 * tester.assertRenderedPage(YourPage.class); 120 * tester.assertLabel("yourMessage", "Hi!"); 121 * } 122 * </pre> 123 * 124 * <code>tester.clickLink(path);</code> will simulate user click on the component (in this case, 125 * it's a <code>Link</code>) and render the response page <code>YourPage</code>. Ok, unit test of 126 * <code>MyPage</code> is completed. Now we test <code>YourPage</code> standalone: 127 * 128 * <pre> 129 * // test code 130 * public void testRenderYourPage() 131 * { 132 * // provide page instance source for WicketTester 133 * tester.startPage(new YourPage("mock message")); 134 * tester.assertRenderedPage(YourPage.class); 135 * tester.assertLabel("yourMessage", "mock message"); 136 * // assert feedback messages in INFO Level 137 * tester.assertInfoMessages(new String[] { "Wicket Rocks ;-)" }); 138 * } 139 * </pre> 140 * 141 * Many methods require a 'path' parameter. E.g. the page relative path can be obtained via 142 * {@link Component#getPageRelativePath()}. Since each Component has an ID/name, any Component can 143 * also be referenced by its ID {@link MarkupContainer#get(String)}. And since MarkupContainer's and 144 * its subclasses are containers which allow to add Components (in sync with the markup hierarchy), 145 * you may not only access direct children but also grandchildren like get("myPanel:myForm:myNameField") 146 * separating each ID with a ':'. 147 * 148 * <h2>Cookie handling</h2> 149 * 150 * There are some expectations about wicket tester cookie handling which should match as best as 151 * it can be with a real client server request response cycle: 152 * <ul> 153 * <li> all valid cookies set before a request is made (tester.getRequest().addCookie()) should 154 * appear in the page request</li> 155 * <li> all cookies set in the response should appear in the last response (tester.getLastResponse()) 156 * after the request is made (expired cookies and others)</li> 157 * <li> all cookies set in the response should appear even after a redirect response is made 158 * until the final response (tester.getLastResponse()) is written to the client (wicket tester)</li> 159 * <li> all valid cookies (maxAge!=0) from the last response should be added to 160 * the next request cookies (tester.getRequest().getCookies())</li> 161 * </ul> 162 * 163 * @author Ingram Chen 164 * @author Juergen Donnerstag 165 * @author Frank Bille 166 * @since 1.2.6 167 */ 168public class WicketTester extends BaseWicketTester 169{ 170 private static final Logger log = LoggerFactory.getLogger(WicketTester.class); 171 172 /** 173 * Creates a <code>WicketTester</code> and automatically creates a <code>WebApplication</code>, 174 * but the tester will have no home page. 175 */ 176 public WicketTester() 177 { 178 } 179 180 /** 181 * Creates a <code>WicketTester</code> and automatically creates a <code>WebApplication</code>. 182 * 183 * @param homePage 184 * a home page <code>Class</code> 185 */ 186 public WicketTester(final Class<? extends Page> homePage) 187 { 188 super(homePage); 189 } 190 191 /** 192 * Creates a <code>WicketTester</code>. 193 * 194 * @param application 195 * a <code>WicketTester</code> <code>WebApplication</code> object 196 */ 197 public WicketTester(final WebApplication application) 198 { 199 super(application); 200 } 201 202 /** 203 * Creates a <code>WicketTester</code> to help unit testing. 204 * 205 * @param application 206 * a <code>WicketTester</code> <code>WebApplication</code> object 207 * @param path 208 * the absolute path on disk to the web application's contents (e.g. war root) - may 209 * be <code>null</code> 210 * 211 * @see org.apache.wicket.mock.MockApplication#MockApplication() 212 */ 213 public WicketTester(final WebApplication application, final String path) 214 { 215 super(application, path); 216 } 217 218 /** 219 * Creates a <code>WicketTester</code> to help unit testing. 220 * 221 * @param application 222 * a <code>WicketTester</code> <code>WebApplication</code> object 223 * @param servletCtx 224 * the servlet context used as backend 225 */ 226 public WicketTester(WebApplication application, ServletContext servletCtx) 227 { 228 super(application, servletCtx); 229 } 230 231 /** 232 * Creates a <code>WicketTester</code> to help unit testing. 233 * 234 * @param application 235 * a <code>WicketTester</code> <code>WebApplication</code> object 236 * @param init 237 * force the application to be initialized (default = true) 238 */ 239 public WicketTester(WebApplication application, boolean init) 240 { 241 super(application, init); 242 } 243 244 /** 245 * Creates a <code>WicketTester</code> to help unit testing. 246 * 247 * @param application 248 * a <code>WicketTester</code> <code>WebApplication</code> object 249 * @param servletCtx 250 * the servlet context used as backend 251 * @param init 252 * force the application to be initialized (default = true) 253 */ 254 public WicketTester(WebApplication application, ServletContext servletCtx, boolean init) 255 { 256 super(application, servletCtx, init); 257 } 258 259 /** 260 * Returns the current Maven build directory taken from the <tt>basedir</tt> system property, or 261 * null if not set 262 * 263 * @return path with a trailing slash 264 */ 265 public static String getBasedir() 266 { 267 String basedir = System.getProperty("basedir"); 268 if (basedir != null) 269 { 270 basedir = basedir + "/"; 271 } 272 else 273 { 274 basedir = ""; 275 } 276 return basedir; 277 } 278 279 /** 280 * Asserts that the Ajax location header is present. 281 */ 282 public void assertAjaxLocation() 283 { 284 if (null != getLastResponse().getHeader("Location")) 285 { 286 fail("Location header should *not* be present when using Ajax"); 287 } 288 289 String ajaxLocation = getLastResponse().getHeader("Ajax-Location"); 290 if (null == ajaxLocation) 291 { 292 fail("Ajax-Location header should be present when using Ajax"); 293 } 294 295 int statusCode = getLastResponse().getStatus(); 296 if (statusCode != 200) 297 { 298 fail("Expected HTTP status code to be 200 (OK)"); 299 } 300 } 301 302 /** 303 * Asserts a <code>Component</code> class. 304 * 305 * @param path 306 * path to <code>Component</code> 307 * @param expectedComponentClass 308 * expected <code>Component</code> class 309 */ 310 public void assertComponent(String path, Class<? extends Component> expectedComponentClass) 311 { 312 assertResult(isComponent(path, expectedComponentClass)); 313 } 314 315 /** 316 * Asserts that the <code>Component</code> a the given path has a behavior of the given type. 317 * 318 * @param path 319 * path to <code>Component</code> 320 * @param expectedBehaviorClass 321 * expected <code>Behavior</code> class 322 */ 323 public void assertBehavior(String path, Class<? extends Behavior> expectedBehaviorClass) 324 { 325 Args.notNull(expectedBehaviorClass, "expectedBehaviorClass"); 326 327 Component component = assertExists(path); 328 List<? extends Behavior> behaviors = component.getBehaviors(expectedBehaviorClass); 329 final String message = String.format("Component '%s' has no behaviors of type '%s'", 330 component.getPageRelativePath(), expectedBehaviorClass); 331 assertResult(new Result(CollectionUtils.isEmpty(behaviors), message)); 332 } 333 334 /** 335 * Tests that a <code>Component</code> has been added to a <code>AjaxRequestTarget</code>, using 336 * {@link org.apache.wicket.ajax.AjaxRequestTarget#add(Component...)}. This method actually 337 * tests that a <code>Component</code> is on the Ajax response sent back to the client. 338 * <p> 339 * PLEASE NOTE! This method doesn't actually insert the <code>Component</code> in the client DOM 340 * tree, using JavaScript. But it shouldn't be needed because you just have to trust that Wicket 341 * Ajax JavaScript works. 342 * 343 * @param component 344 * a <code>Component</code> to be tested 345 */ 346 public void assertComponentOnAjaxResponse(Component component) 347 { 348 Result result = isComponentOnAjaxResponse(component); 349 assertResult(result); 350 } 351 352 /** 353 * Tests that a <code>Component</code> has been added to a <code>AjaxRequestTarget</code>, using 354 * {@link org.apache.wicket.ajax.AjaxRequestTarget#add(Component...)}. This method actually 355 * tests that a <code>Component</code> is on the Ajax response sent back to the client. 356 * <p> 357 * PLEASE NOTE! This method doesn't actually insert the <code>Component</code> in the client DOM 358 * tree, using JavaScript. But it shouldn't be needed because you just have to trust that Wicket 359 * Ajax JavaScript works. 360 * 361 * @param componentPath 362 * a <code>Component</code> path to test 363 */ 364 public void assertComponentOnAjaxResponse(String componentPath) 365 { 366 Component component = getComponentFromLastRenderedPage(componentPath, false); 367 assertComponentOnAjaxResponse(component); 368 } 369 370 /** 371 * Asserts the content of last rendered page contains (matches) a given regex pattern. 372 * 373 * @param pattern 374 * a regex pattern to match 375 */ 376 public void assertContains(String pattern) 377 { 378 assertResult(ifContains(pattern)); 379 } 380 381 /** 382 * The opposite of {@link #assertContains(String)}. 383 * 384 * @param pattern 385 * pattern 386 */ 387 public void assertContainsNot(String pattern) 388 { 389 assertResult(ifContainsNot(pattern)); 390 } 391 392 /** 393 * Asserts that a component's markup has loaded with the given variation 394 * 395 * @param component 396 * The component which markup to check 397 * @param expectedVariation 398 * The expected variation of the component's markup 399 */ 400 public void assertMarkupVariation(Component component, String expectedVariation) 401 { 402 Result result = Result.PASS; 403 IMarkupFragment markup = getMarkupFragment(component); 404 405 String actualVariation = markup.getMarkupResourceStream().getVariation(); 406 if (Objects.equal(expectedVariation, actualVariation) == false) 407 { 408 result = Result.fail( 409 String.format("Wrong variation for component '%s'. Actual: '%s', expected: '%s'", 410 component.getPageRelativePath(), actualVariation, expectedVariation)); 411 } 412 413 assertResult(result); 414 } 415 416 /** 417 * Asserts that a component's markup has loaded with the given style. 418 * 419 * @param component 420 * The component which markup to check 421 * @param expectedStyle 422 * The expected style of the component's markup. For example: <em>green</em> in 423 * <code>MyPanel_green.html</code> 424 */ 425 public void assertMarkupStyle(Component component, String expectedStyle) 426 { 427 Result result = Result.PASS; 428 IMarkupFragment markup = getMarkupFragment(component); 429 430 String actualStyle = markup.getMarkupResourceStream().getStyle(); 431 if (Objects.equal(expectedStyle, actualStyle) == false) 432 { 433 result = Result 434 .fail(String.format("Wrong style for component '%s'. Actual: '%s', expected: '%s'", 435 component.getPageRelativePath(), actualStyle, expectedStyle)); 436 } 437 438 assertResult(result); 439 } 440 441 /** 442 * Asserts that a component's markup has loaded with the given locale 443 * 444 * @param component 445 * The component which markup to check 446 * @param expectedLocale 447 * The expected locale of the component's markup 448 */ 449 public void assertMarkupLocale(Component component, Locale expectedLocale) 450 { 451 Result result = Result.PASS; 452 IMarkupFragment markup = getMarkupFragment(component); 453 454 Locale actualLocale = markup.getMarkupResourceStream().getLocale(); 455 if (Objects.equal(expectedLocale, actualLocale) == false) 456 { 457 result = Result 458 .fail(String.format("Wrong locale for component '%s'. Actual: '%s', expected: '%s'", 459 component.getPageRelativePath(), actualLocale, expectedLocale)); 460 } 461 462 assertResult(result); 463 } 464 465 private IMarkupFragment getMarkupFragment(Component component) 466 { 467 IMarkupFragment markup = null; 468 if (component instanceof MarkupContainer) 469 { 470 markup = ((MarkupContainer)component).getAssociatedMarkup(); 471 } 472 473 if (markup == null) 474 { 475 markup = component.getMarkup(); 476 } 477 478 if (markup == null) 479 { 480 fail(String.format("Cannot find the markup of component: %s", 481 component.getPageRelativePath())); 482 } 483 484 return markup; 485 } 486 487 /** 488 * Asserts error-level feedback messages. 489 * 490 * @param expectedErrorMessages 491 * expected error messages 492 */ 493 public void assertErrorMessages(Serializable... expectedErrorMessages) 494 { 495 assertFeedbackMessages(new ExactLevelFeedbackMessageFilter(FeedbackMessage.ERROR), 496 expectedErrorMessages); 497 } 498 499 /** 500 * Assert info-level feedback messages. 501 * 502 * @param expectedInfoMessages 503 * expected info messages 504 */ 505 public void assertInfoMessages(Serializable... expectedInfoMessages) 506 { 507 assertFeedbackMessages(new ExactLevelFeedbackMessageFilter(FeedbackMessage.INFO), 508 expectedInfoMessages); 509 } 510 511 /** 512 * Assert there are feedback messages accepted by the provided filter. 513 * 514 * @param filter 515 * the filter that will decide which messages to check 516 * @param expectedMessages 517 * expected feedback messages 518 */ 519 public void assertFeedbackMessages(IFeedbackMessageFilter filter, 520 Serializable... expectedMessages) 521 { 522 List<FeedbackMessage> feedbackMessages = getFeedbackMessages(filter); 523 List<Serializable> actualMessages = getActualFeedbackMessages(feedbackMessages); 524 WicketTesterHelper.assertEquals(Arrays.asList(expectedMessages), actualMessages); 525 } 526 527 /** 528 * Asserts that there is a feedback message provided by a given component 529 * 530 * @param component 531 * the component that provided the expected feedback message. Optional. 532 * @param key 533 * the resource key for the feedback message. Mandatory. 534 * @param model 535 * the model used for interpolating the feedback message. Optional. 536 * @param filter 537 * the filter that decides in which messages to look in. E.g. with a specific level, 538 * rendered or not, etc. 539 */ 540 public void assertComponentFeedbackMessage(Component component, String key, IModel<?> model, 541 IFeedbackMessageFilter filter) 542 { 543 Args.notNull(key, "key"); 544 545 String expectedMessage = getApplication().getResourceSettings().getLocalizer().getString( 546 key, component, model); 547 548 List<FeedbackMessage> feedbackMessages = getFeedbackMessages(filter); 549 List<Serializable> actualMessages = getActualFeedbackMessages(feedbackMessages); 550 551 assertTrue(actualMessages.contains(expectedMessage), String 552 .format("Feedback message with key '%s' cannot be found in %s", key, actualMessages)); 553 } 554 555 /** 556 * Extracts the actual messages from the passed feedback messages. Specially handles 557 * ValidationErrorFeedback messages by extracting their String message 558 * 559 * @param feedbackMessages 560 * the feedback messages 561 * @return the FeedbackMessages' messages 562 */ 563 private List<Serializable> getActualFeedbackMessages(List<FeedbackMessage> feedbackMessages) 564 { 565 List<Serializable> actualMessages = new ArrayList<>(); 566 for (FeedbackMessage feedbackMessage : feedbackMessages) 567 { 568 Serializable message = feedbackMessage.getMessage(); 569 if (message instanceof ValidationErrorFeedback) 570 { 571 actualMessages.add(message.toString()); 572 } 573 else 574 { 575 actualMessages.add(message); 576 } 577 } 578 return actualMessages; 579 } 580 581 /** 582 * Assert that a particular feedback panel is rendering certain messages. 583 * 584 * NOTE: this casts the component at the specified path to a {@link FeedbackPanel}, so it will 585 * not work with custom {@link IFeedback} implementations unless you are subclassing 586 * {@link FeedbackPanel} 587 * 588 * @param path 589 * path to the feedback panel 590 * @param messages 591 * messages expected to be rendered 592 */ 593 public void assertFeedback(String path, Serializable... messages) 594 { 595 final FeedbackPanel fbp = (FeedbackPanel)getComponentFromLastRenderedPage(path); 596 final IModel<List<FeedbackMessage>> model = fbp.getFeedbackMessagesModel(); 597 final List<FeedbackMessage> renderedMessages = model.getObject(); 598 if (renderedMessages == null) 599 { 600 fail(String.format("feedback panel at path [%s] returned null messages", path)); 601 } 602 603 if (messages.length != renderedMessages.size()) 604 { 605 fail(String.format( 606 "you expected '%d' messages for the feedback panel [%s], but there were actually '%d'", 607 messages.length, path, renderedMessages.size())); 608 } 609 610 for (int i = 0; i < messages.length && i < renderedMessages.size(); i++) 611 { 612 final Serializable expected = messages[i]; 613 boolean found = false; 614 for (FeedbackMessage actual : renderedMessages) 615 { 616 if (Objects.equal(expected, actual.getMessage())) 617 { 618 found = true; 619 break; 620 } 621 } 622 if (!found) 623 { 624 assertResult(Result.fail("Missing expected feedback message: " + expected)); 625 } 626 } 627 } 628 629 /** 630 * Asserts that a <code>Component</code> is invisible. 631 * 632 * @param path 633 * path to <code>Component</code> 634 */ 635 public void assertInvisible(String path) 636 { 637 assertResult(isInvisible(path)); 638 } 639 640 /** 641 * Asserts the text of a <code>Label</code> <code>Component</code>. 642 * 643 * @param path 644 * path to <code>Label</code> <code>Component</code> 645 * @param expectedLabelText 646 * expected text of the <code>Label</code> 647 */ 648 public void assertLabel(String path, String expectedLabelText) 649 { 650 Label label = (Label)getComponentFromLastRenderedPage(path); 651 assertEquals(expectedLabelText, label.getDefaultModelObjectAsString()); 652 } 653 654 /** 655 * Asserts the model value of a component. 656 * 657 * @param path 658 * path to the component on the page 659 * @param expectedValue 660 * expected value of the component's model 661 */ 662 public void assertModelValue(String path, Object expectedValue) 663 { 664 Component component = getComponentFromLastRenderedPage(path); 665 assertEquals(expectedValue, component.getDefaultModelObject()); 666 } 667 668 /** 669 * Asserts no error-level feedback messages. 670 */ 671 public void assertNoErrorMessage() 672 { 673 assertNoFeedbackMessage(FeedbackMessage.ERROR); 674 } 675 676 /** 677 * Asserts no info-level feedback messages. 678 */ 679 public void assertNoInfoMessage() 680 { 681 assertNoFeedbackMessage(FeedbackMessage.INFO); 682 } 683 684 /** 685 * Asserts there are no feedback messages with a certain level. 686 * 687 * @param level 688 * the level to check for 689 */ 690 public void assertNoFeedbackMessage(int level) 691 { 692 Result result = hasNoFeedbackMessage(level); 693 assertFalse(result.wasFailed(), result.getMessage()); 694 } 695 696 /** 697 * Asserts a last-rendered <code>Page</code> class. 698 * 699 * @param expectedRenderedPageClass 700 * expected class of last rendered <code>Page</code> 701 */ 702 public void assertRenderedPage(Class<? extends Page> expectedRenderedPageClass) 703 { 704 assertResult(isRenderedPage(expectedRenderedPageClass)); 705 } 706 707 /** 708 * Asserts last-rendered <code>Page</code> against an expected HTML document. 709 * <p> 710 * Use <code>-Dwicket.replace.expected.results=true</code> to automatically replace the expected 711 * output file. 712 * 713 * @param clazz 714 * <code>Class</code> used to load the file (relative to <code>clazz</code> package) 715 * @param filename 716 * expected output filename <code>String</code> 717 * @throws Exception 718 */ 719 @Override 720 public void assertResultPage(final Class<?> clazz, final String filename) throws Exception 721 { 722 String document = getLastResponseAsString(); 723 DiffUtil.validatePage(document, clazz, filename, true); 724 } 725 726 /** 727 * Asserts last-rendered <code>Page</code> against an expected HTML document as a 728 * <code>String</code> 729 * 730 * @param expectedDocument 731 * expected output <code>String</code> 732 */ 733 public void assertResultPage(final String expectedDocument) 734 { 735 // Validate the document 736 String document = getLastResponseAsString(); 737 assertEquals(expectedDocument, document); 738 } 739 740 /** 741 * Asserts that a <code>Component</code> is visible. 742 * 743 * @param path 744 * path to a <code>Component</code> 745 */ 746 public void assertVisible(String path) 747 { 748 assertResult(isVisible(path)); 749 } 750 751 /** 752 * assert component is enabled. 753 * 754 * @param path 755 * path to component 756 * 757 */ 758 public void assertEnabled(String path) 759 { 760 assertResult(isEnabled(path)); 761 } 762 763 /** 764 * assert component is enabled. 765 * 766 * @param path 767 * path to component 768 */ 769 public void assertDisabled(String path) 770 { 771 assertResult(isDisabled(path)); 772 } 773 774 /** 775 * assert form component is required. 776 * 777 * @param path 778 * path to form component 779 */ 780 public void assertRequired(String path) 781 { 782 assertResult(isRequired(path)); 783 } 784 785 /** 786 * assert form component is required. 787 * 788 * @param path 789 * path to form component 790 */ 791 public void assertNotRequired(String path) 792 { 793 assertResult(isNotRequired(path)); 794 } 795 796 /** 797 * 798 * @param result 799 */ 800 private void assertResult(Result result) 801 { 802 if (result.wasFailed()) 803 { 804 fail(result.getMessage()); 805 } 806 } 807 808 /** 809 * Checks whether a component is visible and/or enabled before usage 810 * 811 * @param component 812 */ 813 public void assertUsability(final Component component) 814 { 815 checkUsability(component, true); 816 } 817 818 /** 819 * 820 * @param link 821 */ 822 public void clickLink(Component link) 823 { 824 clickLink(link.getPageRelativePath()); 825 } 826 827 /** 828 * Asserts that that the BookmarkablePageLink identified by "id" points to the page as 829 * expected - including parameters. 830 * 831 * @param id 832 * @param pageClass 833 * @param parameters 834 */ 835 public void assertBookmarkablePageLink(final String id, 836 final Class<? extends WebPage> pageClass, final PageParameters parameters) 837 { 838 BookmarkablePageLink<?> pageLink; 839 try 840 { 841 pageLink = (BookmarkablePageLink<?>)getComponentFromLastRenderedPage(id); 842 } 843 catch (ClassCastException e) 844 { 845 throw new IllegalArgumentException( 846 "Component with id:" + id + " is not a BookmarkablePageLink"); 847 } 848 849 assertEquals(pageClass, pageLink.getPageClass(), 850 "BookmarkablePageLink: " + id + " is pointing to the wrong page"); 851 852 assertEquals(parameters, pageLink.getPageParameters(), 853 "One or more of the parameters associated with the BookmarkablePageLink: " + id + 854 " do not match"); 855 } 856 857 /** 858 * Use <code>-Dwicket.replace.expected.results=true</code> to automatically replace the expected 859 * output file. 860 * 861 * @param <T> 862 * @param testClass 863 * @param pageClass 864 * @param filename 865 * @throws Exception 866 */ 867 public <T extends Page> void executeTest(final Class<?> testClass, final Class<T> pageClass, 868 final String filename) throws Exception 869 { 870 log.info("=== " + pageClass.getName() + " ==="); 871 872 startPage(pageClass); 873 assertRenderedPage(pageClass); 874 assertResultPage(testClass, filename); 875 } 876 877 /** 878 * Use <code>-Dwicket.replace.expected.results=true</code> to automatically replace the expected 879 * output file. 880 * 881 * @param testClass 882 * @param page 883 * @param filename 884 * @throws Exception 885 */ 886 public void executeTest(final Class<?> testClass, final Page page, final String filename) 887 throws Exception 888 { 889 log.info("=== " + page.getClass().getName() + " ==="); 890 891 startPage(page); 892 assertRenderedPage(page.getClass()); 893 assertResultPage(testClass, filename); 894 } 895 896 /** 897 * Use <code>-Dwicket.replace.expected.results=true</code> to automatically replace the expected 898 * output file. 899 * 900 * @param testClass 901 * @param component 902 * @param filename 903 * @throws Exception 904 */ 905 public void executeTest(final Class<?> testClass, final Component component, 906 final String filename) throws Exception 907 { 908 log.info("=== " + component.getClass().getName() + " ==="); 909 910 startComponentInPage(component); 911 assertResultPage(testClass, filename); 912 } 913 914 /** 915 * Use <code>-Dwicket.replace.expected.results=true</code> to automatically replace the expected 916 * output file. 917 * 918 * @param <T> 919 * @param testClass 920 * @param pageClass 921 * @param parameters 922 * @param filename 923 * @throws Exception 924 */ 925 public <T extends Page> void executeTest(final Class<?> testClass, final Class<T> pageClass, 926 PageParameters parameters, final String filename) throws Exception 927 { 928 log.info("=== " + pageClass.getName() + " ==="); 929 930 startPage(pageClass, parameters); 931 assertRenderedPage(pageClass); 932 assertResultPage(testClass, filename); 933 } 934 935 /** 936 * 937 * @param testClass 938 * @param component 939 * @param filename 940 * @throws Exception 941 */ 942 public void executeListener(final Class<?> testClass, final Component component, 943 final String filename) throws Exception 944 { 945 assertNotNull(component); 946 947 log.info("=== " + testClass.getName() + " : " + component.getPageRelativePath() + " ==="); 948 949 executeListener(component); 950 assertResultPage(testClass, filename); 951 } 952 953 /** 954 * 955 * @param testClass 956 * @param behavior 957 * @param filename 958 * @throws Exception 959 */ 960 public void executeBehavior(final Class<?> testClass, final AbstractAjaxBehavior behavior, 961 final String filename) throws Exception 962 { 963 assertNotNull(behavior); 964 965 log.info("=== " + testClass.getName() + " : " + behavior.toString() + " ==="); 966 967 executeBehavior(behavior); 968 assertResultPage(testClass, filename); 969 } 970 971 /** 972 * Assert that the last request redirected to the given Url. 973 * 974 * @param expectedRedirectUrl 975 * expected 976 */ 977 public void assertRedirectUrl(String expectedRedirectUrl) 978 { 979 String actualRedirectUrl = getLastResponse().getRedirectLocation(); 980 assertEquals(expectedRedirectUrl, actualRedirectUrl); 981 } 982}