8340785: Update description of PassFailJFrame and samples
Reviewed-by: prr
This commit is contained in:
parent
85f0442727
commit
5063494f5b
@ -79,15 +79,77 @@ import static javax.swing.SwingUtilities.invokeAndWait;
|
||||
import static javax.swing.SwingUtilities.isEventDispatchThread;
|
||||
|
||||
/**
|
||||
* Provides a framework for manual tests to display test instructions and
|
||||
* Pass/Fail buttons.
|
||||
* A framework for manual tests to display test instructions and
|
||||
* <i>Pass</i> / <i>Fail</i> buttons. The framework automatically
|
||||
* creates a frame to display the instructions, provides buttons
|
||||
* to select the test result, and handles test timeout.
|
||||
*
|
||||
* <p id="timeOutTimer">
|
||||
* The instruction UI frame displays a timer at the top which indicates
|
||||
* how much time is left. The timer can be paused using the <i>Pause</i>
|
||||
* button to the right of the time; the title of the button changes to
|
||||
* <i>Resume</i>. To resume the timer, use the <i>Resume</i> button.
|
||||
*
|
||||
* <p id="instructionText">
|
||||
* In the center, the instruction UI frame displays instructions for the
|
||||
* tester. The instructions can be either plain text or HTML. If the
|
||||
* text of the instructions starts with {@code "<html>"}, the
|
||||
* instructions are displayed as HTML, as supported by Swing, which
|
||||
* provides richer formatting options.
|
||||
* <p>
|
||||
* Instructions for the user can be either plain text or HTML as supported
|
||||
* by Swing. If the instructions start with {@code <html>}, the
|
||||
* instructions are displayed as HTML.
|
||||
* The instructions are displayed in a text component with word-wrapping
|
||||
* so that there's no horizontal scroll bar. If the text doesn't fit, a
|
||||
* vertical scroll bar is shown. Use {@code rows} and {@code columns}
|
||||
* parameters to change the size of this text component.
|
||||
* If possible, choose the number of rows and columns so that
|
||||
* the instructions fit and no scroll bars are shown.
|
||||
*
|
||||
* <p id="passFailButtons">
|
||||
* At the bottom, the instruction UI frame displays the
|
||||
* <i>Pass</i> and <i>Fail</i> buttons. The tester clicks either <i>Pass</i>
|
||||
* or <i>Fail</i> button to finish the test. When the tester clicks the
|
||||
* <i>Fail</i> button, the framework displays a dialog box prompting for
|
||||
* a reason why the test fails. The tester enters the reason and clicks
|
||||
* <i>OK</i> to close the dialog and fail the test,
|
||||
* or simply closes the dialog to fail the test without providing any reason.
|
||||
*
|
||||
* <p id="screenCapture">
|
||||
* If you enable the screenshot feature, a <i>Screenshot</i> button is
|
||||
* added to the right of the <i>Fail</i> button. The tester can choose either
|
||||
* <i>Capture Full Screen</i> (default) or <i>Capture Frames</i> and click the
|
||||
* <i>Screenshot</i> button to take a screenshot.
|
||||
* If there are multiple screens, screenshots of each screen are created.
|
||||
* If the tester selects the <i>Capture Frames</i> mode, screenshots of all
|
||||
* the windows or frames registered in the {@code PassFailJFrame} framework
|
||||
* are created.
|
||||
*
|
||||
* <p id="logArea">
|
||||
* If you enable a log area, the instruction UI frame adds a text component
|
||||
* to display log messages below the buttons.
|
||||
* Use {@link #log(String) log}, {@link #logSet(String) logSet}
|
||||
* and {@link #logClear() logClear} static methods of {@code PassFailJFrame}
|
||||
* to add or clear messages from the log area.
|
||||
*
|
||||
* <p id="awaitTestResult">
|
||||
* After you create an instance of {@code PassFailJFrame}, call the
|
||||
* {@link #awaitAndCheck() awaitAndCheck} method to stop the current thread
|
||||
* (usually the main thread) and wait until the tester clicks
|
||||
* either <i>Pass</i> or <i>Fail</i> button,
|
||||
* or until the test times out.
|
||||
* <p>
|
||||
* The call to the {@code awaitAndCheck} method is usually the last
|
||||
* statement in the {@code main} method of your test.
|
||||
* If the test fails, an exception is thrown to signal the failure to jtreg.
|
||||
* The test fails if the tester clicks the <i>Fail</i> button,
|
||||
* if the timeout occurs,
|
||||
* or if any window or frame is closed.
|
||||
* <p>
|
||||
* Before returning from {@code awaitAndCheck}, the framework disposes of
|
||||
* all the windows and frames.
|
||||
*
|
||||
* <h2 id="sampleManualTest">Sample Manual Test</h2>
|
||||
* A simple test would look like this:
|
||||
* <pre>{@code
|
||||
* {@snippet id='sampleManualTestCode' lang='java':
|
||||
* public class SampleManualTest {
|
||||
* private static final String INSTRUCTIONS =
|
||||
* "Click Pass, or click Fail if the test failed.";
|
||||
@ -95,7 +157,7 @@ import static javax.swing.SwingUtilities.isEventDispatchThread;
|
||||
* public static void main(String[] args) throws Exception {
|
||||
* PassFailJFrame.builder()
|
||||
* .instructions(INSTRUCTIONS)
|
||||
* .testUI(() -> createTestUI())
|
||||
* .testUI(SampleManualTest::createTestUI)
|
||||
* .build()
|
||||
* .awaitAndCheck();
|
||||
* }
|
||||
@ -106,39 +168,87 @@ import static javax.swing.SwingUtilities.isEventDispatchThread;
|
||||
* return testUI;
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
* }
|
||||
* <p>
|
||||
* The above example uses the {@link Builder Builder} to set the parameters of
|
||||
* the instruction frame. It is the recommended way.
|
||||
* The above example uses the {@link Builder Builder} class to set
|
||||
* the parameters of the instruction frame.
|
||||
* It is <em>the recommended way</em>.
|
||||
*
|
||||
* <p>
|
||||
* The framework will create instruction UI, it will call
|
||||
* the provided {@code createTestUI} on the Event Dispatch Thread (EDT),
|
||||
* and it will automatically position the test UI and make it visible.
|
||||
* The framework will create an instruction UI frame, it will call
|
||||
* the provided {@code createTestUI} on the Event Dispatch Thread (<dfn>EDT</dfn>),
|
||||
* and it will automatically position the test UI frame and make it visible.
|
||||
*
|
||||
* <p id="jtregTagsForTest">
|
||||
* Add the following jtreg tags before the test class declaration
|
||||
* {@snippet :
|
||||
* /*
|
||||
* * @test
|
||||
* * @summary Sample manual test
|
||||
* * @library /java/awt/regtesthelpers
|
||||
* * @build PassFailJFrame
|
||||
* * @run main/manual SampleManualTest
|
||||
* }
|
||||
* and the closing comment tag <code>*/</code>.
|
||||
* <p>
|
||||
* The {@code @library} tag points to the location of the
|
||||
* {@code PassFailJFrame} class in the source code;
|
||||
* the {@code @build} tag makes jtreg compile the {@code PassFailJFrame} class,
|
||||
* and finally the {@code @run} tag specifies it is a manual
|
||||
* test and the class to run.
|
||||
*
|
||||
* <h2 id="usingBuilder">Using {@code Builder}</h2>
|
||||
* Use methods of the {@link Builder Builder} class to set or change
|
||||
* parameters of {@code PassFailJFrame} and its instruction UI:
|
||||
* <ul>
|
||||
* <li>{@link Builder#title(String) title} sets
|
||||
* the title of the instruction UI
|
||||
* (the default is {@value #TITLE});</li>
|
||||
* <li>{@link Builder#testTimeOut(long) testTimeOut} sets
|
||||
* the timeout of the test
|
||||
* (the default is {@value #TEST_TIMEOUT});</li>
|
||||
* <li>{@link Builder#rows(int) rows} and
|
||||
* {@link Builder#columns(int) columns} control the size
|
||||
* the text component which displays the instructions
|
||||
* (the default number of rows is the number of lines in the text
|
||||
* of the instructions,
|
||||
* the default number of columns is {@value #COLUMNS});</li>
|
||||
* <li>{@link Builder#logArea() logArea} adds a log area;</li>
|
||||
* <li>{@link Builder#screenCapture() screenCapture}
|
||||
* enables screenshots.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3 id="builderTestUI">Using {@code testUI} and {@code splitUI}</h3>
|
||||
* The {@code Builder.testUI} methods accept interfaces which create one window
|
||||
* or a list of windows if the test needs multiple windows,
|
||||
* or directly a single window, an array of windows or a list of windows.
|
||||
* <p>
|
||||
* For simple test UI, use {@code Builder.splitUI}, or explicitly
|
||||
* {@code Builder.splitUIRight} or {@code Builder.splitUIBottom} with
|
||||
* a {@code PanelCreator}. The framework will call the provided
|
||||
* {@code createUIPanel} to create the component with test UI and
|
||||
* For simple test UI, use {@link Builder#splitUI(PanelCreator) splitUI},
|
||||
* or explicitly
|
||||
* {@link Builder#splitUIRight(PanelCreator) splitUIRight} or
|
||||
* {@link Builder#splitUIBottom(PanelCreator) splitUIBottom} with
|
||||
* a {@link PanelCreator PanelCreator}.
|
||||
* The framework will call the provided
|
||||
* {@code createUIPanel} method to create the component with test UI and
|
||||
* will place it as the right or bottom component in a split pane
|
||||
* along with instruction UI.
|
||||
* <p>
|
||||
* Note: <em>support for multiple windows is incomplete</em>.
|
||||
*
|
||||
* <h2 id="obsoleteSampleTest">Obsolete Sample Test</h2>
|
||||
* Alternatively, use one of the {@code PassFailJFrame} constructors to
|
||||
* create an object, then create secondary test UI, register it
|
||||
* with {@code PassFailJFrame}, position it and make it visible.
|
||||
* The following sample demonstrates it:
|
||||
* <pre>{@code
|
||||
* public class SampleOldManualTest {
|
||||
* {@snippet id='obsoleteSampleTestCode' lang='java':
|
||||
* public class ObsoleteManualTest {
|
||||
* private static final String INSTRUCTIONS =
|
||||
* "Click Pass, or click Fail if the test failed.";
|
||||
*
|
||||
* public static void main(String[] args) throws Exception {
|
||||
* PassFailJFrame passFail = new PassFailJFrame(INSTRUCTIONS);
|
||||
*
|
||||
* SwingUtilities.invokeAndWait(() -> createTestUI());
|
||||
* SwingUtilities.invokeAndWait(ObsoleteManualTest::createTestUI);
|
||||
*
|
||||
* passFail.awaitAndCheck();
|
||||
* }
|
||||
@ -151,17 +261,29 @@ import static javax.swing.SwingUtilities.isEventDispatchThread;
|
||||
* testUI.setVisible(true);
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
* }
|
||||
* <p>
|
||||
* Use methods of the {@code Builder} class or constructors of the
|
||||
* {@code PassFailJFrame} class to control other parameters:
|
||||
* <ul>
|
||||
* <li>the title of the instruction UI,</li>
|
||||
* <li>the timeout of the test,</li>
|
||||
* <li>the size of the instruction UI via rows and columns, and</li>
|
||||
* <li>to add a log area,</li>
|
||||
* <li>to enable screenshots.</li>
|
||||
* </ul>
|
||||
* This sample uses {@link #PassFailJFrame(String) a constructor} of
|
||||
* {@code PassFailJFrame} to create its instance,
|
||||
* there are several overloads provided which allow changing other parameters.
|
||||
* <p>
|
||||
* When you use the constructors, you have to explicitly create
|
||||
* your test UI window on EDT. After you create the window,
|
||||
* you need to register it with the framework using
|
||||
* {@link #addTestWindow(Window) addTestWindow}
|
||||
* to ensure the window is disposed of when the test completes.
|
||||
* Before showing the window, you have to call
|
||||
* {@link #positionTestWindow(Window, Position) positionTestWindow}
|
||||
* to position the test window near the instruction UI frame provided
|
||||
* by the framework. And finally you have to explicitly show the test UI
|
||||
* window by calling {@code setVisible(true)}.
|
||||
* <p>
|
||||
* To avoid the complexity, use the {@link Builder Builder} class
|
||||
* which provides a streamlined way to configure and create an
|
||||
* instance of {@code PassFailJFrame}.
|
||||
* <p>
|
||||
* Consider updating tests which use {@code PassFailJFrame} constructors to
|
||||
* use the builder pattern.
|
||||
*/
|
||||
public final class PassFailJFrame {
|
||||
|
||||
@ -541,7 +663,11 @@ public final class PassFailJFrame {
|
||||
: configurePlainText(instructions, rows, columns);
|
||||
text.setEditable(false);
|
||||
|
||||
main.add(new JScrollPane(text), BorderLayout.CENTER);
|
||||
JPanel textPanel = new JPanel(new BorderLayout());
|
||||
textPanel.setBorder(createEmptyBorder(4, 0, 0, 0));
|
||||
textPanel.add(new JScrollPane(text), BorderLayout.CENTER);
|
||||
|
||||
main.add(textPanel, BorderLayout.CENTER);
|
||||
|
||||
JButton btnPass = new JButton("Pass");
|
||||
btnPass.addActionListener((e) -> {
|
||||
@ -822,7 +948,7 @@ public final class PassFailJFrame {
|
||||
private static JComponent createCapturePanel() {
|
||||
JComboBox<CaptureType> screenShortType = new JComboBox<>(CaptureType.values());
|
||||
|
||||
JButton capture = new JButton("ScreenShot");
|
||||
JButton capture = new JButton("Screenshot");
|
||||
capture.addActionListener((e) ->
|
||||
captureScreen((CaptureType) screenShortType.getSelectedItem()));
|
||||
|
||||
@ -834,7 +960,7 @@ public final class PassFailJFrame {
|
||||
|
||||
private enum CaptureType {
|
||||
FULL_SCREEN("Capture Full Screen"),
|
||||
WINDOWS("Capture Individual Frame");
|
||||
WINDOWS("Capture Frames");
|
||||
|
||||
private final String type;
|
||||
CaptureType(String type) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user