diff options
author | scr@chromium.org <scr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-26 03:17:47 +0000 |
---|---|---|
committer | scr@chromium.org <scr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-26 03:17:47 +0000 |
commit | afb032f74a73720e93ddfde4d2729417d01192f6 (patch) | |
tree | a769d953cd44ef6a42bc572f99f260bac60579d3 | |
parent | e612ea2be73e30ec03e8cd0b0e4b5df9c2be8cca (diff) | |
download | chromium_src-afb032f74a73720e93ddfde4d2729417d01192f6.zip chromium_src-afb032f74a73720e93ddfde4d2729417d01192f6.tar.gz chromium_src-afb032f74a73720e93ddfde4d2729417d01192f6.tar.bz2 |
Add more Print Preview tests based on feedback from Demetrios' recent bug fixes.
Added guts for matching and saving arguments, and testing updating printers.
- Test that layout, color, and copies is disabled when requested.
- Test updating printers generates preview.
- Test error condition when plugin isn't available.
Also added guts to run this on trybots by faking enough when the plugin is not available.
R=dpapad@chromium.org, estade@chromium.org
BUG=89825, 88002
TEST=browser_tests --gtest_filter=PrintPreviewWebUITest.*
Review URL: http://codereview.chromium.org/7472026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94035 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/test/data/webui/print_preview.js | 221 | ||||
-rw-r--r-- | chrome/test/data/webui/test_api.js | 212 | ||||
-rw-r--r-- | chrome/test/test_navigation_observer.cc | 1 |
3 files changed, 355 insertions, 79 deletions
diff --git a/chrome/test/data/webui/print_preview.js b/chrome/test/data/webui/print_preview.js index 9b41b76..1d08f781 100644 --- a/chrome/test/data/webui/print_preview.js +++ b/chrome/test/data/webui/print_preview.js @@ -3,7 +3,7 @@ // found in the LICENSE file. /** - * TestFixture for print preview WebUI testing. + * Test fixture for print preview WebUI testing. * @extends {testing.Test} * @constructor **/ @@ -13,13 +13,17 @@ PrintPreviewWebUITest.prototype = { __proto__: testing.Test.prototype, /** - * Browse to the sample page, cause print preview & call our PreLoad(). + * Browse to the sample page, cause print preview & call PreLoad(). + * @type {string} + * @override **/ browsePrintPreload: 'print_preview_hello_world_test.html', /** * Register a mock handler to ensure expectations are met and print preview * behaves correctly. + * @type {Function} + * @override **/ PreLoad: function() { @@ -42,7 +46,7 @@ PrintPreviewWebUITest.prototype = { }; // Create the actual mock and register stubs for methods expected to be - // called before our tests run. Specific expectations can be made in the + // called before tests run. Specific expectations can be made in the // tests themselves. var mockHandler = this.mockHandler = mock(MockPrintPreviewHandler); mockHandler.stubs().getDefaultPrinter(). @@ -59,7 +63,7 @@ PrintPreviewWebUITest.prototype = { })); mockHandler.stubs().getPreview(NOT_NULL). will(callFunction(function() { - updatePrintPreview(1, 'title', true); + updatePrintPreview('title', true, 1, 1); })); mockHandler.stubs().getPrinters(). @@ -74,26 +78,74 @@ PrintPreviewWebUITest.prototype = { ]); })); - // Register our mock as a handler of the chrome.send messages. + // Register mock as a handler of the chrome.send messages. registerMockMessageCallbacks(mockHandler, MockPrintPreviewHandler); + + // Override checkCompatiblePluginExists to return a value consistent with + // the state being tested and stub out the pdf viewer if it doesn't exist, + // such as on non-official builds. When the plugin exists, use the real + // thing. + var self = this; + window.addEventListener('DOMContentLoaded', function() { + if (!this.checkCompatiblePluginExists()) + this.createPDFPlugin = self.createPDFPlugin; + + this.checkCompatiblePluginExists = + self.checkCompatiblePluginExists; + }); }, - testGenPreamble: function(testFixture, testName) { - GEN(' if (!HasPDFLib()) {'); - GEN(' LOG(WARNING)'); - GEN(' << "Skipping test ' + testFixture + '.' + testName + '"'); - GEN(' << ": No PDF Lib.";'); - GEN(' SUCCEED();'); - GEN(' return;'); - GEN(' }'); - }, + + /** + * Generate a real C++ class; don't typedef. + * @type {?string} + * @override + **/ typedefCppFixture: null, + + /** + * Create the PDF plugin or reload the existing one. This function replaces + * createPDFPlugin defined in + * chrome/browser/resources/print_preview/print_preview.js when there is no + * official pdf plugin so that the WebUI logic can be tested. It creates and + * attaches an HTMLDivElement to the |mainview| element with attributes and + * empty methods, which are used by testing and that would be provided by the + * HTMLEmbedElement when the PDF plugin exists. + * @param {string} previewUid Preview unique identifier. + */ + createPDFPlugin: function(previewUid) { + var pdfViewer = $('pdf-viewer'); + if (pdfViewer) + return; + + pdfViewer = document.createElement('div'); + pdfViewer.setAttribute('id', 'pdf-viewer'); + pdfViewer.setAttribute('type', + 'application/x-google-chrome-print-preview-pdf'); + pdfViewer.setAttribute( + 'src', 'chrome://print/' + previewUid + '/print.pdf'); + pdfViewer.setAttribute('aria-live', 'polite'); + pdfViewer.setAttribute('aria-atomic', 'true'); + function fakeFunction() {} + pdfViewer.onload = fakeFunction; + pdfViewer.goToPage = fakeFunction; + pdfViewer.removePrintButton = fakeFunction; + pdfViewer.fitToHeight = fakeFunction; + pdfViewer.grayscale = fakeFunction; + $('mainview').appendChild(pdfViewer); + onPDFLoad(); + }, + + /** + * Always return true so tests run on systems without plugin available. + * @return {boolean} Always true. + **/ + checkCompatiblePluginExists: function() { + return true; + }, }; GEN('#include "base/command_line.h"'); -GEN('#include "base/path_service.h"'); -GEN('#include "base/stringprintf.h"'); GEN('#include "chrome/browser/ui/webui/web_ui_browsertest.h"'); -GEN('#include "chrome/common/chrome_paths.h"'); GEN('#include "chrome/common/chrome_switches.h"'); GEN(''); GEN('class PrintPreviewWebUITest'); @@ -111,22 +163,131 @@ GEN(' ASSERT_TRUE(switches::IsPrintPreviewEnabled());'); GEN('#endif'); GEN(' }'); GEN(''); -GEN(' bool HasPDFLib() const {'); -GEN(' FilePath pdf;'); -GEN(' return PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) &&'); -GEN(' file_util::PathExists(pdf);'); -GEN(' }'); GEN('};'); GEN(''); +/** + * The expected length of the |printer-list| element. + * @type {number} + * @const + **/ +var printerListMinLength = 2; + +/** + * The expected index of the "foo" printer returned by the stubbed handler. + * @type {number} + * @const + **/ +var fooIndex = 0; + +/** + * The expected index of the "bar" printer returned by the stubbed handler. + * @type {number} + * @const + **/ +var barIndex = 1; + +// Test some basic assumptions about the print preview WebUI. TEST_F('PrintPreviewWebUITest', 'FLAKY_TestPrinterList', function() { var printerList = $('printer-list'); - assertTrue(!!printerList, 'printerList'); - assertTrue(printerList.options.length >= 2, 'printer-list has at least 2'); - expectEquals('FooName', printerList.options[0].text, '0 text is FooName'); - expectEquals('FooDevice', printerList.options[0].value, - '0 value is FooDevice'); - expectEquals('BarName', printerList.options[1].text, '1 text is BarName'); - expectEquals('BarDevice', printerList.options[1].value, - '1 value is BarDevice'); + assertNotEquals(null, printerList); + assertGE(printerList.options.length, printerListMinLength); + expectEquals(fooIndex, printerList.selectedIndex); + expectEquals('FooName', printerList.options[fooIndex].text, + 'fooIndex=' + fooIndex); + expectEquals('FooDevice', printerList.options[fooIndex].value, + 'fooIndex=' + fooIndex); + expectEquals('BarName', printerList.options[barIndex].text, + 'barIndex=' + barIndex); + expectEquals('BarDevice', printerList.options[barIndex].value, + 'barIndex=' + barIndex); +}); + +/** + * Verify that the section |sectionId| visibility matches |visible|. + * @param {string} sectionId The id of the section to check. + * @param {boolean} visible The expected state of visibility. + **/ +function checkSectionVisible(sectionId, visible) { + var section = $(sectionId); + assertNotEquals(null, section); + expectEquals(section.classList.contains('visible'), visible, + 'sectionId=' + sectionId); +} + +// Test that disabled settings hide the disabled sections. +TEST_F('PrintPreviewWebUITest', 'TestSectionsDisabled', function() { + this.mockHandler.expects(once()).getPrinterCapabilities('FooDevice'). + will(callFunction(function() { + updateWithPrinterCapabilities({ + disableColorOption: true, + setColorAsDefault: true, + disableCopiesOption: true, + disableLandscapeOption: true, + }); + })); + + updateControlsWithSelectedPrinterCapabilities(); + + checkSectionVisible('layout-option', false); + checkSectionVisible('color-options', false); + checkSectionVisible('copies-option', false); +}); + +// Test that changing the selected printer updates the preview. +TEST_F('PrintPreviewWebUITest', 'TestPrinterChangeUpdatesPreview', function() { + var matchAnythingSave = new SaveArgumentsMatcher(ANYTHING); + + this.mockHandler.expects(once()).getPreview(matchAnythingSave). + will(callFunction(function() { + updatePrintPreview('title', true, 2, + matchAnythingSave.argument.requestID); + })); + + var printerList = $('printer-list'); + assertNotEquals(null, printerList, 'printerList'); + assertGE(printerList.options.length, printerListMinLength); + expectEquals(fooIndex, printerList.selectedIndex, + 'fooIndex=' + fooIndex); + var oldLastPreviewRequestID = lastPreviewRequestID; + ++printerList.selectedIndex; + updateControlsWithSelectedPrinterCapabilities(); + expectNotEquals(oldLastPreviewRequestID, lastPreviewRequestID); +}); + +/** + * Test fixture to test case when no PDF plugin exists. + * @extends {PrintPreviewWebUITest} + * @constructor + **/ +function PrintPreviewNoPDFWebUITest() {} + +PrintPreviewNoPDFWebUITest.prototype = { + __proto__: PrintPreviewWebUITest.prototype, + + /** + * Provide a typedef for C++ to correspond to JS subclass. + * @type {?string} + * @override + */ + typedefCppFixture: 'PrintPreviewWebUITest', + + /** + * Always return false to simulate failure and check expected error condition. + * @return {boolean} Always false. + * @override + */ + checkCompatiblePluginExists: function() { + return false; + }, +}; + +// Test that error message is displayed when plugin doesn't exist. +TEST_F('PrintPreviewNoPDFWebUITest', 'TestErrorMessage', function() { + var errorButton = $('error-button'); + assertNotEquals(null, errorButton); + expectFalse(errorButton.disabled); + var errorText = $('error-text'); + assertNotEquals(null, errorText); + expectFalse(errorText.classList.contains('hidden')); }); diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js index 1bab30d..45af3e7 100644 --- a/chrome/test/data/webui/test_api.js +++ b/chrome/test/data/webui/test_api.js @@ -52,7 +52,7 @@ var currentTestCase = null; * When set to a string value representing a url, generate BrowsePreload * call, which will browse to the url and call fixture.PreLoad of the * currentTestCase. - * @type {String} + * @type {string} **/ browsePreload: null, @@ -61,7 +61,7 @@ var currentTestCase = null; * directory, generate BrowsePrintPreload call, which will browse to a url * representing the file, cause print, and call fixture.PreLoad of the * currentTestCase. - * @type {String} + * @type {string} **/ browsePrintPreload: null, @@ -80,9 +80,9 @@ var currentTestCase = null; testGenPostamble: null, /** - * When set to a non-null String, auto-generate typedef before generating + * When set to a non-null string, auto-generate typedef before generating * TEST*: {@code typedef typedefCppFixture testFixture}. - * @type {String} + * @type {string} **/ typedefCppFixture: 'WebUIBrowserTest', @@ -120,7 +120,7 @@ var currentTestCase = null; /** * This class is not exported and is available to hold the state of the * |currentTestCase| throughout preload and test run. - * @param {String} name The name of the test case. + * @param {string} name The name of the test case. * @param {Test} fixture The fixture object for this test case. * @param {Function} body The code to run for the test. * @constructor @@ -172,7 +172,7 @@ var currentTestCase = null; /** * Registers the message, object and callback for {@code chrome.send} - * @param {String} name The name of the message to route to this |callback|. + * @param {string} name The name of the message to route to this |callback|. * @param {Object} messageHAndler Pass as |this| when calling the |callback|. * @param {function(...)} callback Called by {@code chrome.send}. * @see sendCallbacks @@ -210,7 +210,7 @@ var currentTestCase = null; /** * Overrides {@code chrome.send} for routing messages to javascript * functions. Also fallsback to sending with the |oldChrome| object. - * @param {String} messageName The message to route. + * @param {string} messageName The message to route. * @see oldChrome **/ function send(messageName) { @@ -323,69 +323,128 @@ var currentTestCase = null; // If assertion passes, no notification will be sent to the C++ backend. /** - * When |test| !== |expected|, aborts the current test. - * @param {Boolean} test The predicate to check against |expected|. - * @param {Boolean} expected The expected value of |test|. - * @param {String=} message The message to include in the Error thrown. - * @throws {Error} upon failure. - **/ - function assertBool(test, expected, message) { - helper.registerCall(); - if (test !== expected) - throw new Error('Test Error ' + helper.getCallMessage(message) + - ': ' + test); - } - - /** * When |test| !== true, aborts the current test. - * @param {Boolean} test The predicate to check against |expected|. - * @param {String=} message The message to include in the Error thrown. + * @param {boolean} test The predicate to check against |expected|. + * @param {string=} message The message to include in the Error thrown. * @throws {Error} upon failure. **/ function assertTrue(test, message) { helper.registerCall(); if (test !== true) - throw new Error('Test Error ' + helper.getCallMessage(message) + - ': ' + test); + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + ': ' + test); } /** * When |test| !== false, aborts the current test. - * @param {Boolean} test The predicate to check against |expected|. - * @param {String=} message The message to include in the Error thrown. + * @param {boolean} test The predicate to check against |expected|. + * @param {string=} message The message to include in the Error thrown. * @throws {Error} upon failure. **/ function assertFalse(test, message) { helper.registerCall(); if (test !== false) - throw new Error('Test Error ' + helper.getCallMessage(message) + - ': ' + test); + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + ': ' + test); + } + + /** + * When |val1| < |val2|, aborts the current test. + * @param {number} val1 The number expected to be >= |val2|. + * @param {number} val2 The number expected to be < |val1|. + * @param {string=} message The message to include in the Error thrown. + **/ + function assertGE(val1, val2, message) { + helper.registerCall(); + if (val1 < val2) { + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + val1 + '<' + val2); + } + } + + /** + * When |val1| <= |val2|, aborts the current test. + * @param {number} val1 The number expected to be > |val2|. + * @param {number} val2 The number expected to be <= |val1|. + * @param {string=} message The message to include in the Error thrown. + **/ + function assertGT(val1, val2, message) { + helper.registerCall(); + if (val1 <= val2) { + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + val1 + '<=' + val2); + } } /** * When |expected| !== |actual|, aborts the current test. - * @param {*} expected The predicate to check against |expected|. - * @param {*} actual The expected value of |test|. - * @param {String=} message The message to include in the Error thrown. + * @param {*} expected The expected value of |actual|. + * @param {*} actual The predicate to check against |expected|. + * @param {string=} message The message to include in the Error thrown. * @throws {Error} upon failure. **/ function assertEquals(expected, actual, message) { helper.registerCall(); if (expected != actual) { - throw new Error('Test Error ' + helper.getCallMessage(message) + + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + '\nActual: ' + actual + '\nExpected: ' + expected); } if (typeof expected != typeof actual) { - throw new Error('Test Error (type mismatch) ' + - helper.getCallMessage(message) + + throw new Error( + 'Test Error (type mismatch) ' + helper.getCallMessage(message) + '\nActual Type: ' + typeof actual + '\nExpected Type:' + typeof expected); } } /** + * When |val1| > |val2|, aborts the current test. + * @param {number} val1 The number expected to be <= |val2|. + * @param {number} val2 The number expected to be > |val1|. + * @param {string=} message The message to include in the Error thrown. + **/ + function assertLE(val1, val2, message) { + helper.registerCall(); + if (val1 > val2) { + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + val1 + '>' + val2); + } + } + + /** + * When |val1| >= |val2|, aborts the current test. + * @param {number} val1 The number expected to be < |val2|. + * @param {number} val2 The number expected to be >= |val1|. + * @param {string=} message The message to include in the Error thrown. + **/ + function assertLT(val1, val2, message) { + helper.registerCall(); + if (val1 >= val2) { + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + val1 + '>=' + val2); + } + } + + /** + * When |notExpected| === |actual|, aborts the current test. + * @param {*} notExpected The expected value of |actual|. + * @param {*} actual The predicate to check against |notExpected|. + * @param {string=} message The message to include in the Error thrown. + * @throws {Error} upon failure. + **/ + function assertNotEquals(notExpected, actual, message) { + helper.registerCall(); + if (notExpected === actual) { + throw new Error( + 'Test Error ' + helper.getCallMessage(message) + + '\nActual: ' + actual + '\nnotExpected: ' + notExpected); + } + } + + /** * Always aborts the current test. - * @param {String=} message The message to include in the Error thrown. + * @param {string=} message The message to include in the Error thrown. * @throws {Error} always. **/ function assertNotReached(message) { @@ -427,9 +486,9 @@ var currentTestCase = null; * |errors|, runs the test surrounded by an expect to catch Errors. If * |errors| is non-empty, it reports a failure and a message by joining * |errors|. - * @param {String} testFunction The function name to call. + * @param {string} testFunction The function name to call. * @param {Array} testArguments The arguments to call |testFunction| with. - * @return {Array.<Boolean, String>} [test-succeeded, message-if-failed] + * @return {Array.<boolean, string>} [test-succeeded, message-if-failed] * @see errors * @see createExpect **/ @@ -464,8 +523,8 @@ var currentTestCase = null; /** * Creates a new test case for the given |testFixture| and |testName|. Assumes * |testFixture| describes a globally available subclass of type Test. - * @param {String} testFixture The fixture for this test case. - * @param {String} testName The name for this test case. + * @param {string} testFixture The fixture for this test case. + * @param {string} testName The name for this test case. * @return {TestCase} A newly created TestCase. **/ function createTestCase(testFixture, testName) { @@ -482,8 +541,8 @@ var currentTestCase = null; * creates a test case and calls its PreLoad for any early initialization such * as registering handlers before the page's javascript runs it's OnLoad * method. - * @param {String} testFixture The test fixture name. - * @param {String} testName The test name. + * @param {string} testFixture The test fixture name. + * @param {string} testName The test name. **/ function preloadJavascriptLibraries(testFixture, testName) { chrome = { @@ -503,8 +562,8 @@ var currentTestCase = null; * At runtime, register the testName with a test fixture. Since this method * doesn't have a test fixture, we create a dummy fixture to hold its |name| * and |testCaseBodies|. - * @param {String} testCaseName The name of the test case. - * @param {String} testName The name of the test function. + * @param {string} testCaseName The name of the test case. + * @param {string} testName The name of the test function. * @param {Function} testBody The body to execute when running this test. **/ function TEST(testCaseName, testName, testBody) { @@ -525,8 +584,8 @@ var currentTestCase = null; * At runtime, register the testName with its fixture. Stuff the |name| into * the |testFixture|'s prototype, if needed, and the |testCaseBodies| into its * constructor. - * @param {String} testFixture The name of the test fixture class. - * @param {String} testName The name of the test function. + * @param {string} testFixture The name of the test fixture class. + * @param {string} testName The name of the test function. * @param {Function} testBody The body to execute when running this test. **/ function TEST_F(testFixture, testName, testBody) { @@ -543,8 +602,8 @@ var currentTestCase = null; * runTest. If |currentTestCase| is non-null at this point, verify that * |testFixture| and |testName| agree with the preloaded values. Create * |currentTestCase|, if needed, run it, and clear the |currentTestCase|. - * @param {String} testFixture The name of the test fixture class. - * @param {String} testName The name of the test function. + * @param {string} testFixture The name of the test fixture class. + * @param {string} testName The name of the test function. * @see preloadJavascriptLibraries * @see runTest **/ @@ -591,21 +650,76 @@ var currentTestCase = null; Array.prototype.slice.call(arguments, 1)); } + /** + * Allow mock stubs() and expects() to know what arguments were passed to the + * |realMatcher|. + * @param {!Object} realMatcher The real matcher to perform matching with. + * @constructor + **/ + function SaveArgumentsMatcher(realMatcher) { + this.realMatcher_ = realMatcher; + } + + SaveArgumentsMatcher.prototype = { + /** + * Remember the argument passed to this stub invocation. + * @type {*} + **/ + argument: undefined, + + /** + * @type {Object} the object performing the real match. + * @private + */ + realMatcher_: null, + + /** + * Saves |actualArgument| for later use by the mock stub or expect. + * @param {*} actualArgument The argument to match and save. + * @return {boolean} value of calling the |realMatcher_|. + **/ + argumentMatches: function(actualArgument) { + this.argument = actualArgument; + return this.realMatcher_.argumentMatches.call(this.realMatcher_, + actualArgument); + }, + + /** + * Generic description for this Matcher object. + * @return {string} description of the matcher for this argument. + **/ + describe: function() { + return 'SaveArguments(' + + this.realMatcher_.describe.call(this.realMatcher_) + ')'; + }, + }; + // Exports. testing.Test = Test; window.assertTrue = assertTrue; window.assertFalse = assertFalse; + window.assertGE = assertGE; + window.assertGT = assertGT; window.assertEquals = assertEquals; + window.assertLE = assertLE; + window.assertLT = assertLT; + window.assertNotEquals = assertNotEquals; window.assertNotReached = assertNotReached; window.callFunction = callFunction; window.expectTrue = createExpect(assertTrue); window.expectFalse = createExpect(assertFalse); + window.expectGE = createExpect(assertGE); + window.expectGT = createExpect(assertGT); window.expectEquals = createExpect(assertEquals); + window.expectLE = createExpect(assertLE); + window.expectLT = createExpect(assertLT); + window.expectNotEquals = createExpect(assertNotEquals); window.expectNotReached = createExpect(assertNotReached); + window.preloadJavascriptLibraries = preloadJavascriptLibraries; window.registerMessageCallback = registerMessageCallback; window.registerMockMessageCallbacks = registerMockMessageCallbacks; window.runTest = runTest; - window.preloadJavascriptLibraries = preloadJavascriptLibraries; + window.SaveArgumentsMatcher = SaveArgumentsMatcher; window.TEST = TEST; window.TEST_F = TEST_F; window.GEN = GEN; diff --git a/chrome/test/test_navigation_observer.cc b/chrome/test/test_navigation_observer.cc index fab5b5c..6502f10 100644 --- a/chrome/test/test_navigation_observer.cc +++ b/chrome/test/test_navigation_observer.cc @@ -44,6 +44,7 @@ TestNavigationObserver::TestNavigationObserver( js_injection_ready_observer, int number_of_navigations) : navigation_started_(false), + navigation_entry_committed_(false), navigations_completed_(0), number_of_navigations_(number_of_navigations), js_injection_ready_observer_(js_injection_ready_observer), |