Commit a14ce6ec authored by dpapad's avatar dpapad Committed by Commit Bot

WebUI: Eliminate usages and remove chrome/third_party/mock4js.

Reviving original CL by @tapted at
https://chromium-review.googlesource.com/c/chromium/src/+/2173856

Bug: 844820
Change-Id: I2865e36952ae1de032b4edf4fee0903db95122f9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2531902Reviewed-by: default avatarRebekah Potter <rbpotter@chromium.org>
Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Commit-Queue: dpapad <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#827220}
parent 5a25be46
......@@ -27,13 +27,6 @@ SyncInternalsWebUITest.prototype = {
*/
runAccessibilityChecks: false,
/** @override */
preLoad: function() {
this.makeAndRegisterMockHandler([
'getAllNodes',
]);
},
/**
* Checks aboutInfo's details section for the specified field.
* @param {boolean} isValid Whether the field is valid.
......@@ -334,12 +327,9 @@ TEST_F('SyncInternalsWebUITest', 'SearchTabDoesntChangeOnItemSelect',
});
TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() {
const getAllNodesSavedArgs = new SaveMockArguments();
this.mockHandler.expects(once()).
getAllNodes(getAllNodesSavedArgs.match(ANYTHING)).
will(callFunctionWithSavedArgs(getAllNodesSavedArgs,
chrome.sync.getAllNodesCallback,
HARD_CODED_ALL_NODES));
chrome.sync.getAllNodes = (callback) => {
callback(HARD_CODED_ALL_NODES);
};
// Hit the refresh button.
$('node-browser-refresh-button').click();
......@@ -347,7 +337,7 @@ TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() {
// Check that the refresh time was updated.
expectNotEquals($('node-browser-refresh-time').textContent, 'Never');
// Verify some hard-coded assumptions. These depend on the vaue of the
// Verify some hard-coded assumptions. These depend on the value of the
// hard-coded nodes, specified elsewhere in this file.
// Start with the tree itself.
......@@ -370,12 +360,9 @@ TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() {
});
TEST_F('SyncInternalsWebUITest', 'NodeBrowserRefreshOnTabSelect', function() {
const getAllNodesSavedArgs = new SaveMockArguments();
this.mockHandler.expects(once()).
getAllNodes(getAllNodesSavedArgs.match(ANYTHING)).
will(callFunctionWithSavedArgs(getAllNodesSavedArgs,
chrome.sync.getAllNodesCallback,
HARD_CODED_ALL_NODES));
chrome.sync.getAllNodes = (callback) => {
callback(HARD_CODED_ALL_NODES);
};
// Should start with non-refreshed node browser.
expectEquals($('node-browser-refresh-time').textContent, 'Never');
......
......@@ -10,7 +10,6 @@ import("//v8/gni/v8.gni")
# Changing the size or the order of files in this array also requires changing
# src/tools/gypv8sh.py.
js2gtest_js_input_libraries = [
"//chrome/third_party/mock4js/mock4js.js",
"//chrome/test/data/webui/test_api.js",
"//chrome/test/base/js2gtest.js",
]
......
......@@ -10,7 +10,6 @@
JsTestApiConfig::JsTestApiConfig() {
constexpr const base::FilePath::CharType* kLibraries[] = {
FILE_PATH_LITERAL("chrome/third_party/mock4js/mock4js.js"),
FILE_PATH_LITERAL("third_party/chaijs/chai.js"),
};
constexpr base::FilePath::CharType kWebUITestFolder[] =
......
......@@ -59,7 +59,6 @@ js_type_check("closure_compile_local") {
js_library("test_api_js") {
sources = [ "webui/test_api.js" ]
externs_list = [
"webui/mock4js_externs.js",
"//third_party/chaijs/externs/chai-3.5.js",
"//ui/webui/resources/js/dom_automation_controller.js",
]
......
......@@ -85,7 +85,6 @@ if (include_js_tests) {
"js2gtest_browsertest.js",
"load_time_data_browsertest.js",
"management/a11y/management_a11y_test.js",
"mock4js_browsertest.js",
"net_internals/dns_view.js",
"net_internals/domain_security_policy_view.js",
"net_internals/main.js",
......
......@@ -108,64 +108,59 @@ TEST_F('WebUIBrowserAsyncGenTest', 'TestContinue', function() {
// Test that runAllActionsAsync can be called with multiple functions, and with
// bound, saved, or mixed arguments.
TEST_F('WebUIBrowserAsyncGenTest', 'TestRunAllActionsAsyncMock', function() {
this.makeAndRegisterMockHandler([
'testBoundArgs',
'testSavedArgs',
'testMixedArgs',
]);
TEST_F('WebUIBrowserAsyncGenTest', 'TestRunAllActionsAsync', function() {
// Bind some arguments.
var var1, var2;
this.mockHandler.expects(once()).testBoundArgs().will(
runAllActionsAsync(WhenTestDone.DEFAULT, callFunction(function(args) {
function testBoundArgs() {
const action1 = callFunction(function(args) {
var1 = args[0];
}, ['val1']), callFunction(function(args) {
}, ['val1']);
const action2 = callFunction(function(args) {
var2 = args[0];
}, ['val2'])));
}, ['val2']);
runAllActionsAsync(WhenTestDone.DEFAULT, action1, action2).invoke();
}
// Receive some saved arguments.
var var3, var4;
var savedArgs = new SaveMockArguments();
var savedArgs2 = new SaveMockArguments();
this.mockHandler.expects(once())
.testSavedArgs(savedArgs.match(savedArgs2.match(eq(['passedVal1']))))
.will(runAllActionsAsync(
WhenTestDone.DEFAULT,
callFunctionWithSavedArgs(savedArgs, function(args) {
function testSavedArgs(sendArg) {
const action1 = callFunctionWithSavedArgs(savedArgs, function(args) {
var3 = args[0];
}), callFunctionWithSavedArgs(savedArgs2, function(args) {
}, sendArg);
const action2 = callFunctionWithSavedArgs(savedArgs2, function(args) {
var4 = args[0];
})));
}, sendArg);
runAllActionsAsync(WhenTestDone.DEFAULT, action1, action2).invoke();
}
// Receive some saved arguments and some bound arguments.
var var5, var6, var7, var8;
this.mockHandler.expects(once())
.testMixedArgs(savedArgs.match(savedArgs2.match(eq('passedVal2'))))
.will(runAllActionsAsync(
WhenTestDone.DEFAULT,
callFunctionWithSavedArgs(
savedArgs,
function(passedArgs, boundArgs) {
function testMixedArgs(sendArg) {
const action1 =
callFunctionWithSavedArgs(savedArgs, function(passedArgs, boundArgs) {
var5 = passedArgs[0];
var6 = boundArgs[0];
},
['val6']),
callFunctionWithSavedArgs(
savedArgs2, function(passedArgs, boundArgs) {
}, sendArg, ['val6']);
const action2 =
callFunctionWithSavedArgs(savedArgs2, function(passedArgs, boundArgs) {
var7 = passedArgs[0];
var8 = boundArgs[0];
}, ['val8'])));
}, sendArg, ['val8']);
runAllActionsAsync(WhenTestDone.DEFAULT, action1, action2).invoke();
}
// Send the cases to the mocked handler & tell the C++ handler to continue2.
continueTest = this.continueTest(WhenTestDone.ASSERT, function() {
chrome.send('testBoundArgs');
chrome.send('testSavedArgs', ['passedVal1']);
chrome.send('testMixedArgs', ['passedVal2']);
chrome.send('callJS', ['continueTest2']);
window.continueTest = this.continueTest(WhenTestDone.ASSERT, function() {
testBoundArgs();
testSavedArgs(['passedVal1']);
testMixedArgs(['passedVal2']);
setTimeout(window.continueTest2, 0);
});
// Check expectations after mocks have been called.
continueTest2 = this.continueTest(WhenTestDone.ALWAYS, function() {
window.continueTest2 = this.continueTest(WhenTestDone.ALWAYS, function() {
expectEquals('val1', var1);
expectEquals('val2', var2);
expectEquals('passedVal1', var3);
......@@ -177,7 +172,7 @@ TEST_F('WebUIBrowserAsyncGenTest', 'TestRunAllActionsAsyncMock', function() {
});
// Kick off the tests asynchronously.
chrome.send('callJS', ['continueTest']);
setTimeout(window.continueTest, 0);
});
/**
......
......@@ -30,34 +30,14 @@ ChromeSendWebUITest.prototype = {
/** @inheritDoc */
browsePreload: DUMMY_URL,
/** @inheritDoc */
setUp: function() {
this.makeAndRegisterMockHandler(['checkSend']);
}
};
// Test that chrome.send can be mocked outside the preLoad method.
TEST_F('ChromeSendWebUITest', 'NotInPreload', function() {
this.mockHandler.expects(once()).checkSend();
chrome.send('checkSend');
});
/**
* Test fixture for chrome send WebUI testing with passthrough.
* @constructor
* @extends {ChromeSendWebUITest}
*/
function ChromeSendPassthroughWebUITest() {}
ChromeSendPassthroughWebUITest.prototype = {
__proto__: ChromeSendWebUITest.prototype,
};
// Test that the mocked chrome.send can call the original.
TEST_F('ChromeSendPassthroughWebUITest', 'CanCallOriginal', function() {
this.mockHandler.expects(once()).checkSend().will(callFunction(function() {
chrome.originalSend('checkSend');
}));
let invoked = false;
registerMessageCallback('checkSend', undefined, () => {
invoked = true;
});
chrome.send('checkSend');
assertTrue(invoked);
});
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for Mock4JS to ensure that expectations pass or fail as
* expected using the test framework.
* @author scr@chromium.org (Sheridan Rawlins)
* @see test_api.js
*/
GEN('#include "content/public/test/browser_test.h"');
/**
* Test fixture for Mock4JS testing.
* @constructor
* @extends {testing.Test}
*/
function Mock4JSWebUITest() {}
Mock4JSWebUITest.prototype = {
__proto__: testing.Test.prototype,
/** @inheritDoc */
browsePreload: DUMMY_URL,
/** @inheritDoc */
setUp: function() {
function MockHandler() {}
MockHandler.prototype = {
callMe: function() {},
};
this.mockHandler = mock(MockHandler);
},
};
TEST_F('Mock4JSWebUITest', 'CalledExpectPasses', function() {
this.mockHandler.expects(once()).callMe();
this.mockHandler.proxy().callMe();
});
TEST_F('Mock4JSWebUITest', 'CalledTwiceExpectTwice', function() {
this.mockHandler.expects(exactly(2)).callMe();
var proxy = this.mockHandler.proxy();
proxy.callMe();
proxy.callMe();
});
/**
* Test fixture for Mock4JS testing which is expected to fail.
* @constructor
* @extends {Mock4JSWebUITest}
*/
function Mock4JSWebUITestFails() {}
Mock4JSWebUITestFails.prototype = {
__proto__: Mock4JSWebUITest.prototype,
/** @inheritDoc */
testShouldFail: true,
};
TEST_F('Mock4JSWebUITestFails', 'NotCalledExpectFails', function() {
this.mockHandler.expects(once()).callMe();
});
TEST_F('Mock4JSWebUITestFails', 'CalledTwiceExpectOnceFails', function() {
this.mockHandler.expects(once()).callMe();
var proxy = this.mockHandler.proxy();
proxy.callMe();
proxy.callMe();
});
TEST_F('Mock4JSWebUITestFails', 'CalledOnceExpectTwiceFails', function() {
this.mockHandler.expects(exactly(2)).callMe();
var proxy = this.mockHandler.proxy();
proxy.callMe();
});
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* Limited externs used by webui testing from http://mock4js.sourceforge.net/.
* Mock4JS is not closure-annotated and unmaintained.
* TODO(crbug/844820): Eliminate/replace usage of mock4js and delete this file.
*/
function mock(klass) {}
const Mock4JS = {
verifyAllMocks: function() {},
addMockSupport: function(exports) {},
};
class Mock {
proxy() {}
expects(expectedCallCount) {}
stubs() {}
verify() {}
}
......@@ -159,13 +159,6 @@ Test.prototype = {
*/
featuresWithParameters: null,
/**
* This should be initialized by the test fixture and can be referenced
* during the test run. It holds any mocked handler methods.
* @type {?Mock}
*/
mockHandler: null,
/**
* Value is passed through call to C++ RunJavascriptF to invoke this test.
* @type {boolean}
......@@ -203,30 +196,6 @@ Test.prototype = {
*/
closureModuleDeps: [],
/**
* Create a new class to handle |messageNames|, assign it to
* |this.mockHandler|, register its messages and return it.
* @return {Mock} Mock handler class assigned to |this.mockHandler|.
*/
makeAndRegisterMockHandler: function(messageNames) {
var MockClass = makeMockClass(messageNames);
this.mockHandler = mock(MockClass);
registerMockMessageCallbacks(this.mockHandler, MockClass);
return this.mockHandler;
},
/**
* Create a container of mocked standalone functions to handle
* |functionNames|, assign it to |this.mockLocalFunctions| and return it.
* @param {!Array<string>} functionNames
* @return {Mock} Mock handler class.
* @see makeMockFunctions
*/
makeMockLocalFunctions: function(functionNames) {
this.mockLocalFunctions = makeMockFunctions(functionNames);
return this.mockLocalFunctions;
},
/**
* Override this method to perform initialization during preload (such as
* creating mocks and registering handlers).
......@@ -241,9 +210,7 @@ Test.prototype = {
setUp: function() {},
/**
* Override this method to perform tasks after running your test. If you
* create a mock class, you must call Mock4JS.verifyAllMocks() in this
* phase.
* Override this method to perform tasks after running your test.
* @type {Function}
*/
tearDown: function() {
......@@ -253,8 +220,6 @@ Test.prototype = {
noAnimationStyle.parentNode.removeChild(noAnimationStyle);
}
}
Mock4JS.verifyAllMocks();
},
/**
......@@ -454,27 +419,6 @@ function registerMessageCallback(name, messageHandler, callback) {
sendCallbacks[name] = [messageHandler, callback];
}
/**
* Register all methods of {@code mockClass.prototype} with messages of the
* same name as the method, using the proxy of the |mockObject| as the
* |messageHandler| when registering.
* @param {Mock} mockObject The mock to register callbacks against.
* @param {Function} mockClass Constructor for the mocked class.
* @see registerMessageCallback
* @see overrideChrome
*/
function registerMockMessageCallbacks(mockObject, mockClass) {
if (!deferGlobalOverrides && !originalChrome) {
overrideChrome();
}
var mockProxy = mockObject.proxy();
for (var func in mockClass.prototype) {
if (typeof mockClass.prototype[func] === 'function') {
registerMessageCallback(func, mockProxy, mockProxy[func]);
}
}
}
/**
* When preloading JavaScript libraries, this is true until the
* DOMContentLoaded event has been received as globals cannot be overridden
......@@ -483,52 +427,6 @@ function registerMockMessageCallbacks(mockObject, mockClass) {
*/
var deferGlobalOverrides = false;
/**
* Empty function for use in making mocks.
* @const
*/
function emptyFunction() {}
/**
* Make a mock from the supplied |methodNames| array.
* @param {Array<string>} methodNames Array of names of methods to mock.
* @return {Function} Constructor with prototype filled in with methods
* matching |methodNames|.
*/
function makeMockClass(methodNames) {
function MockConstructor() {}
for (var i = 0; i < methodNames.length; i++) {
MockConstructor.prototype[methodNames[i]] = emptyFunction;
}
return MockConstructor;
}
/**
* Create a new class to handle |functionNames|, add method 'functions()'
* that returns a container of standalone functions based on the mock class
* members, and return it.
* @return {Mock} Mock handler class.
*/
function makeMockFunctions(functionNames) {
var MockClass = makeMockClass(functionNames);
var mockFunctions = mock(MockClass);
var mockProxy = mockFunctions.proxy();
mockFunctions.functions_ = {};
for (var func in MockClass.prototype) {
if (typeof MockClass.prototype[func] === 'function') {
mockFunctions.functions_[func] = mockProxy[func].bind(mockProxy);
}
}
mockFunctions.functions = function() {
return this.functions_;
};
return mockFunctions;
}
/**
* Overrides {@code chrome.send} for routing messages to javascript
* functions. Also falls back to sending with the original chrome object.
......@@ -944,7 +842,6 @@ function overrideChrome() {
chrome = {
__proto__: originalChrome,
send: send,
originalSend: originalChrome.send.bind(originalChrome),
};
}
......@@ -1427,9 +1324,6 @@ function exportMock4JsHelpers() {
exports.callFunction = callFunction;
exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs;
exports.SaveMockArguments = SaveMockArguments;
// Import the Mock4JS helpers.
Mock4JS.addMockSupport(exports);
}
// Exports.
......
Copyright (C) 2009 by Tung Mac.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Name: mock4js
Short Name: mock4js
URL: http://mock4js.sourceforge.net/
Version: 0.2
License: MIT
License File: NOT_SHIPPED
Mock4JS is a dynamic-mock library for Javascript. It enables developers to write
tests that exercise and verify the interactions between the objects in the
application. Its syntax is very expressive and is closely based on jMock 1.
Local Modifications:
* Replace a fail() call with throwing Mock4JSException.
* Changed `new Function()` call in order to avoid Trusted Types violation.
/**
* PriceCache
*/
function PriceCache() {
}
PriceCache.prototype = {
getCachedPrice: function(instrumentId) {
},
setCachedPrice: function(instrumentId, price) {
}
}
/**
* PriceFetcher
*/
function PriceFetcher() {
}
PriceFetcher.prototype = {
getPriceFromServer: function(instrumentId) {
}
}
/**
* PriceService
*/
function PriceService(priceFetcher, priceCache) {
this._priceFetcher = priceFetcher;
this._priceCache = priceCache;
}
PriceService.prototype = {
getPrice: function(instrumentId) {
var price = this._priceCache.getCachedPrice(instrumentId);
if(price==null) {
price = this._priceFetcher.getPriceFromServer(instrumentId);
this._priceCache.setCachedPrice(instrumentId, price);
}
return price;
}
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Tests</title>
<link rel="stylesheet" type="text/css" href="jsunit/css/jsUnitStyle.css">
<script language="JavaScript" type="text/javascript" src="../../jsunit/app/jsUnitCore.js"></script>
<script language="JavaScript" type="text/javascript" src="../mock4js.js"></script>
<script language="JavaScript" type="text/javascript" src="PriceService.js"></script>
<script language="JavaScript" type="text/javascript">
Mock4JS.addMockSupport(this);
var mockPriceFetcher;
var mockPriceCache;
var priceService;
function setUp() {
Mock4JS.clearMocksToVerify();
mockPriceFetcher = mock(PriceFetcher);
mockPriceCache = mock(PriceCache);
priceService = new PriceService(mockPriceFetcher.proxy(), mockPriceCache.proxy());
}
function tearDown() {
Mock4JS.verifyAllMocks();
}
function testGetsPriceFromFetcherWhenPriceNotInCache() {
mockPriceCache.expects(once()).getCachedPrice("USDGBP").will(returnValue(null));
mockPriceFetcher.expects(once()).getPriceFromServer("USDGBP").will(returnValue(123.4));
mockPriceCache.expects(once()).setCachedPrice("USDGBP", 123.4);
var result = priceService.getPrice("USDGBP");
assertEquals("Should have returned price from server", 123.4, result);
}
function testDoesntGetsPriceFromFetcherWhenPriceAlreadyInCache() {
mockPriceCache.expects(once()).getCachedPrice("USDGBP").will(returnValue(123.4));
mockPriceCache.expects(never()).setCachedPrice();
mockPriceFetcher.expects(never()).getPriceFromServer("USDGBP");
var result = priceService.getPrice("USDGBP");
assertEquals("Should have returned price from cache", 123.4, result);
}
</script>
</head>
<body>
<h1>JsUnit Tests</h1>
<p>This page contains some JsUnit tests. To see them, take a look at the source.</p>
</body>
</html>
/**
* Subscriber
*/
function Subscriber() {
}
Subscriber.prototype = {
receive: function(message) {
}
}
/**
* Publisher
*/
function Publisher() {
this._subscribers = [];
}
Publisher.prototype = {
publish: function(message) {
for(var i=0; i<this._subscribers.length; i++) {
var subscriber = this._subscribers[i];
subscriber.receive(message);
}
},
add: function(subscriber) {
this._subscribers.push(subscriber);
}
}
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Tests</title>
<link rel="stylesheet" type="text/css" href="jsunit/css/jsUnitStyle.css">
<script language="JavaScript" type="text/javascript" src="../../jsunit/app/jsUnitCore.js"></script>
<script language="JavaScript" type="text/javascript" src="..//mock4js.js"></script>
<script language="JavaScript" type="text/javascript" src="Publisher.js"></script>
<script language="JavaScript" type="text/javascript">
Mock4JS.addMockSupport(this);
function setUp() {
Mock4JS.clearMocksToVerify();
}
function tearDown() {
Mock4JS.verifyAllMocks();
}
function testOneSubscriberReceivesAMessage() {
// setup
var mockSubscriber = mock(Subscriber);
var publisher = new Publisher();
publisher.add(mockSubscriber.proxy());
var message = "message";
// expectations
mockSubscriber.expects(once()).receive(message);
// execute
publisher.publish(message);
}
</script>
</head>
<body>
<h1>JsUnit Tests</h1>
<p>This page contains some JsUnit tests. To see them, take a look at the source.</p>
</body>
</html>
/**
* Mock4JS 0.2
* http://mock4js.sourceforge.net/
*/
Mock4JS = {
_mocksToVerify: [],
_convertToConstraint: function(constraintOrValue) {
if(constraintOrValue.argumentMatches) {
return constraintOrValue; // it's already an ArgumentMatcher
} else {
return new MatchExactly(constraintOrValue); // default to eq(...)
}
},
addMockSupport: function(object) {
// mock creation
object.mock = function(mockedType) {
if(!mockedType) {
throw new Mock4JSException("Cannot create mock: type to mock cannot be found or is null");
}
var newMock = new Mock(mockedType);
Mock4JS._mocksToVerify.push(newMock);
return newMock;
}
// syntactic sugar for expects()
object.once = function() {
return new CallCounter(1);
}
object.never = function() {
return new CallCounter(0);
}
object.exactly = function(expectedCallCount) {
return new CallCounter(expectedCallCount);
}
object.atLeastOnce = function() {
return new InvokeAtLeastOnce();
}
// syntactic sugar for argument expectations
object.ANYTHING = new MatchAnything();
object.NOT_NULL = new MatchAnythingBut(new MatchExactly(null));
object.NOT_UNDEFINED = new MatchAnythingBut(new MatchExactly(undefined));
object.eq = function(expectedValue) {
return new MatchExactly(expectedValue);
}
object.not = function(valueNotExpected) {
var argConstraint = Mock4JS._convertToConstraint(valueNotExpected);
return new MatchAnythingBut(argConstraint);
}
object.and = function() {
var constraints = [];
for(var i=0; i<arguments.length; i++) {
constraints[i] = Mock4JS._convertToConstraint(arguments[i]);
}
return new MatchAllOf(constraints);
}
object.or = function() {
var constraints = [];
for(var i=0; i<arguments.length; i++) {
constraints[i] = Mock4JS._convertToConstraint(arguments[i]);
}
return new MatchAnyOf(constraints);
}
object.stringContains = function(substring) {
return new MatchStringContaining(substring);
}
// syntactic sugar for will()
object.returnValue = function(value) {
return new ReturnValueAction(value);
}
object.throwException = function(exception) {
return new ThrowExceptionAction(exception);
}
},
clearMocksToVerify: function() {
Mock4JS._mocksToVerify = [];
},
verifyAllMocks: function() {
for(var i=0; i<Mock4JS._mocksToVerify.length; i++) {
Mock4JS._mocksToVerify[i].verify();
}
}
}
Mock4JSUtil = {
hasFunction: function(obj, methodName) {
return typeof obj == 'object' && typeof obj[methodName] == 'function';
},
join: function(list) {
var result = "";
for(var i=0; i<list.length; i++) {
var item = list[i];
if(Mock4JSUtil.hasFunction(item, "describe")) {
result += item.describe();
}
else if(typeof list[i] == 'string') {
result += "\""+list[i]+"\"";
} else {
result += list[i];
}
if(i<list.length-1) result += ", ";
}
return result;
}
}
Mock4JSException = function(message) {
this.message = message;
}
Mock4JSException.prototype = {
toString: function() {
return this.message;
}
}
/**
* Assert function that makes use of the constraint methods
*/
assertThat = function(expected, argumentMatcher) {
if(!argumentMatcher.argumentMatches(expected)) {
throw new Mock4JSException("Expected '"+expected+"' to be "+argumentMatcher.describe());
}
}
/**
* CallCounter
*/
function CallCounter(expectedCount) {
this._expectedCallCount = expectedCount;
this._actualCallCount = 0;
}
CallCounter.prototype = {
addActualCall: function() {
this._actualCallCount++;
if(this._actualCallCount > this._expectedCallCount) {
throw new Mock4JSException("unexpected invocation");
}
},
verify: function() {
if(this._actualCallCount < this._expectedCallCount) {
throw new Mock4JSException("expected method was not invoked the expected number of times");
}
},
describe: function() {
if(this._expectedCallCount == 0) {
return "not expected";
} else if(this._expectedCallCount == 1) {
var msg = "expected once";
if(this._actualCallCount >= 1) {
msg += " and has been invoked";
}
return msg;
} else {
var msg = "expected "+this._expectedCallCount+" times";
if(this._actualCallCount > 0) {
msg += ", invoked "+this._actualCallCount + " times";
}
return msg;
}
}
}
function InvokeAtLeastOnce() {
this._hasBeenInvoked = false;
}
InvokeAtLeastOnce.prototype = {
addActualCall: function() {
this._hasBeenInvoked = true;
},
verify: function() {
if(this._hasBeenInvoked === false) {
throw new Mock4JSException(describe());
}
},
describe: function() {
var desc = "expected at least once";
if(this._hasBeenInvoked) desc+=" and has been invoked";
return desc;
}
}
/**
* ArgumentMatchers
*/
function MatchExactly(expectedValue) {
this._expectedValue = expectedValue;
}
MatchExactly.prototype = {
argumentMatches: function(actualArgument) {
if(this._expectedValue instanceof Array) {
if(!(actualArgument instanceof Array)) return false;
if(this._expectedValue.length != actualArgument.length) return false;
for(var i=0; i<this._expectedValue.length; i++) {
if(this._expectedValue[i] != actualArgument[i]) return false;
}
return true;
} else {
return this._expectedValue == actualArgument;
}
},
describe: function() {
if(typeof this._expectedValue == "string") {
return "eq(\""+this._expectedValue+"\")";
} else {
return "eq("+this._expectedValue+")";
}
}
}
function MatchAnything() {
}
MatchAnything.prototype = {
argumentMatches: function(actualArgument) {
return true;
},
describe: function() {
return "ANYTHING";
}
}
function MatchAnythingBut(matcherToNotMatch) {
this._matcherToNotMatch = matcherToNotMatch;
}
MatchAnythingBut.prototype = {
argumentMatches: function(actualArgument) {
return !this._matcherToNotMatch.argumentMatches(actualArgument);
},
describe: function() {
return "not("+this._matcherToNotMatch.describe()+")";
}
}
function MatchAllOf(constraints) {
this._constraints = constraints;
}
MatchAllOf.prototype = {
argumentMatches: function(actualArgument) {
for(var i=0; i<this._constraints.length; i++) {
var constraint = this._constraints[i];
if(!constraint.argumentMatches(actualArgument)) return false;
}
return true;
},
describe: function() {
return "and("+Mock4JSUtil.join(this._constraints)+")";
}
}
function MatchAnyOf(constraints) {
this._constraints = constraints;
}
MatchAnyOf.prototype = {
argumentMatches: function(actualArgument) {
for(var i=0; i<this._constraints.length; i++) {
var constraint = this._constraints[i];
if(constraint.argumentMatches(actualArgument)) return true;
}
return false;
},
describe: function() {
return "or("+Mock4JSUtil.join(this._constraints)+")";
}
}
function MatchStringContaining(stringToLookFor) {
this._stringToLookFor = stringToLookFor;
}
MatchStringContaining.prototype = {
argumentMatches: function(actualArgument) {
if(typeof actualArgument != 'string') throw new Mock4JSException("stringContains() must be given a string, actually got a "+(typeof actualArgument));
return (actualArgument.indexOf(this._stringToLookFor) != -1);
},
describe: function() {
return "a string containing \""+this._stringToLookFor+"\"";
}
}
/**
* StubInvocation
*/
function StubInvocation(expectedMethodName, expectedArgs, actionSequence) {
this._expectedMethodName = expectedMethodName;
this._expectedArgs = expectedArgs;
this._actionSequence = actionSequence;
}
StubInvocation.prototype = {
matches: function(invokedMethodName, invokedMethodArgs) {
if (invokedMethodName != this._expectedMethodName) {
return false;
}
if (invokedMethodArgs.length != this._expectedArgs.length) {
return false;
}
for(var i=0; i<invokedMethodArgs.length; i++) {
var expectedArg = this._expectedArgs[i];
var invokedArg = invokedMethodArgs[i];
if(!expectedArg.argumentMatches(invokedArg)) {
return false;
}
}
return true;
},
invoked: function() {
try {
return this._actionSequence.invokeNextAction();
} catch(e) {
if(e instanceof Mock4JSException) {
throw new Mock4JSException(this.describeInvocationNameAndArgs()+" - "+e.message);
} else {
throw e;
}
}
},
will: function() {
this._actionSequence.addAll.apply(this._actionSequence, arguments);
},
describeInvocationNameAndArgs: function() {
return this._expectedMethodName+"("+Mock4JSUtil.join(this._expectedArgs)+")";
},
describe: function() {
return "stub: "+this.describeInvocationNameAndArgs();
},
verify: function() {
}
}
/**
* ExpectedInvocation
*/
function ExpectedInvocation(expectedMethodName, expectedArgs, expectedCallCounter) {
this._stubInvocation = new StubInvocation(expectedMethodName, expectedArgs, new ActionSequence());
this._expectedCallCounter = expectedCallCounter;
}
ExpectedInvocation.prototype = {
matches: function(invokedMethodName, invokedMethodArgs) {
try {
return this._stubInvocation.matches(invokedMethodName, invokedMethodArgs);
} catch(e) {
throw new Mock4JSException("method "+this._stubInvocation.describeInvocationNameAndArgs()+": "+e.message);
}
},
invoked: function() {
try {
this._expectedCallCounter.addActualCall();
} catch(e) {
throw new Mock4JSException(e.message+": "+this._stubInvocation.describeInvocationNameAndArgs());
}
return this._stubInvocation.invoked();
},
will: function() {
this._stubInvocation.will.apply(this._stubInvocation, arguments);
},
describe: function() {
return this._expectedCallCounter.describe()+": "+this._stubInvocation.describeInvocationNameAndArgs();
},
verify: function() {
try {
this._expectedCallCounter.verify();
} catch(e) {
throw new Mock4JSException(e.message+": "+this._stubInvocation.describeInvocationNameAndArgs());
}
}
}
/**
* MethodActions
*/
function ReturnValueAction(valueToReturn) {
this._valueToReturn = valueToReturn;
}
ReturnValueAction.prototype = {
invoke: function() {
return this._valueToReturn;
},
describe: function() {
return "returns "+this._valueToReturn;
}
}
function ThrowExceptionAction(exceptionToThrow) {
this._exceptionToThrow = exceptionToThrow;
}
ThrowExceptionAction.prototype = {
invoke: function() {
throw this._exceptionToThrow;
},
describe: function() {
return "throws "+this._exceptionToThrow;
}
}
function ActionSequence() {
this._ACTIONS_NOT_SETUP = "_ACTIONS_NOT_SETUP";
this._actionSequence = this._ACTIONS_NOT_SETUP;
this._indexOfNextAction = 0;
}
ActionSequence.prototype = {
invokeNextAction: function() {
if(this._actionSequence === this._ACTIONS_NOT_SETUP) {
return;
} else {
if(this._indexOfNextAction >= this._actionSequence.length) {
throw new Mock4JSException("no more values to return");
} else {
var action = this._actionSequence[this._indexOfNextAction];
this._indexOfNextAction++;
return action.invoke();
}
}
},
addAll: function() {
this._actionSequence = [];
for(var i=0; i<arguments.length; i++) {
if(typeof arguments[i] != 'object' && arguments[i].invoke === undefined) {
throw new Error("cannot add a method action that does not have an invoke() method");
}
this._actionSequence.push(arguments[i]);
}
}
}
function StubActionSequence() {
this._ACTIONS_NOT_SETUP = "_ACTIONS_NOT_SETUP";
this._actionSequence = this._ACTIONS_NOT_SETUP;
this._indexOfNextAction = 0;
}
StubActionSequence.prototype = {
invokeNextAction: function() {
if(this._actionSequence === this._ACTIONS_NOT_SETUP) {
return;
} else if(this._actionSequence.length == 1) {
// if there is only one method action, keep doing that on every invocation
return this._actionSequence[0].invoke();
} else {
if(this._indexOfNextAction >= this._actionSequence.length) {
throw new Mock4JSException("no more values to return");
} else {
var action = this._actionSequence[this._indexOfNextAction];
this._indexOfNextAction++;
return action.invoke();
}
}
},
addAll: function() {
this._actionSequence = [];
for(var i=0; i<arguments.length; i++) {
if(typeof arguments[i] != 'object' && arguments[i].invoke === undefined) {
throw new Error("cannot add a method action that does not have an invoke() method");
}
this._actionSequence.push(arguments[i]);
}
}
}
/**
* Mock
*/
function Mock(mockedType) {
if(mockedType === undefined || mockedType.prototype === undefined) {
throw new Mock4JSException("Unable to create Mock: must create Mock using a class not prototype, eg. 'new Mock(TypeToMock)' or using the convenience method 'mock(TypeToMock)'");
}
this._mockedType = mockedType.prototype;
this._expectedCallCount;
this._isRecordingExpectations = false;
this._expectedInvocations = [];
// setup proxy
// TODO(crbug.com/1087743): Support Function constructor in Trusted Types
var IntermediateClass = (function(){});
IntermediateClass.prototype = mockedType.prototype;
// TODO(crbug.com/1087743): Support Function constructor in Trusted Types
var ChildClass = (function(){});
ChildClass.prototype = new IntermediateClass();
this._proxy = new ChildClass();
this._proxy.mock = this;
for(property in mockedType.prototype) {
if(this._isPublicMethod(mockedType.prototype, property)) {
var publicMethodName = property;
this._proxy[publicMethodName] = this._createMockedMethod(publicMethodName);
this[publicMethodName] = this._createExpectationRecordingMethod(publicMethodName);
}
}
}
Mock.prototype = {
proxy: function() {
return this._proxy;
},
expects: function(expectedCallCount) {
this._expectedCallCount = expectedCallCount;
this._isRecordingExpectations = true;
this._isRecordingStubs = false;
return this;
},
stubs: function() {
this._isRecordingExpectations = false;
this._isRecordingStubs = true;
return this;
},
verify: function() {
for(var i=0; i<this._expectedInvocations.length; i++) {
var expectedInvocation = this._expectedInvocations[i];
try {
expectedInvocation.verify();
} catch(e) {
var failMsg = e.message+this._describeMockSetup();
throw new Mock4JSException(failMsg);
}
}
},
_isPublicMethod: function(mockedType, property) {
try {
var isMethod = typeof(mockedType[property]) == 'function';
var isPublic = property.charAt(0) != "_";
return isMethod && isPublic;
} catch(e) {
return false;
}
},
_createExpectationRecordingMethod: function(methodName) {
return function() {
// ensure all arguments are instances of ArgumentMatcher
var expectedArgs = [];
for(var i=0; i<arguments.length; i++) {
if(arguments[i] !== null && arguments[i] !== undefined && arguments[i].argumentMatches) {
expectedArgs[i] = arguments[i];
} else {
expectedArgs[i] = new MatchExactly(arguments[i]);
}
}
// create stub or expected invocation
var expectedInvocation;
if(this._isRecordingExpectations) {
expectedInvocation = new ExpectedInvocation(methodName, expectedArgs, this._expectedCallCount);
} else {
expectedInvocation = new StubInvocation(methodName, expectedArgs, new StubActionSequence());
}
this._expectedInvocations.push(expectedInvocation);
this._isRecordingExpectations = false;
this._isRecordingStubs = false;
return expectedInvocation;
}
},
_createMockedMethod: function(methodName) {
return function() {
// go through expectation list backwards to ensure later expectations override earlier ones
for(var i=this.mock._expectedInvocations.length-1; i>=0; i--) {
var expectedInvocation = this.mock._expectedInvocations[i];
if(expectedInvocation.matches(methodName, arguments)) {
try {
return expectedInvocation.invoked();
} catch(e) {
if(e instanceof Mock4JSException) {
throw new Mock4JSException(e.message+this.mock._describeMockSetup());
} else {
// the user setup the mock to throw a specific error, so don't modify the message
throw e;
}
}
}
}
var failMsg = "unexpected invocation: "+methodName+"("+Mock4JSUtil.join(arguments)+")"+this.mock._describeMockSetup();
throw new Mock4JSException(failMsg);
};
},
_describeMockSetup: function() {
var msg = "\nAllowed:";
for(var i=0; i<this._expectedInvocations.length; i++) {
var expectedInvocation = this._expectedInvocations[i];
msg += "\n" + expectedInvocation.describe();
}
return msg;
}
}
......@@ -29,8 +29,7 @@ def HasSameContent(filename, content):
def main ():
parser = optparse.OptionParser()
parser.set_usage(
"%prog v8_shell mock.js test_api.js js2webui.js "
parser.set_usage("%prog v8_shell test_api.js js2webui.js "
"testtype inputfile srcrootdir cxxoutfile jsoutfile")
parser.add_option('-v', '--verbose', action='store_true')
parser.add_option('-n', '--impotent', action='store_true',
......@@ -42,15 +41,14 @@ def main ():
help="Load V8's initial snapshot from external files (y/n)")
(opts, args) = parser.parse_args()
if len(args) != 9:
if len(args) != 8:
parser.error('all arguments are required.')
(v8_shell, mock_js, test_api, js2webui, test_type,
inputfile, srcrootdir, cxxoutfile, jsoutfile) = args
(v8_shell, test_api, js2webui, test_type, inputfile, srcrootdir, cxxoutfile,
jsoutfile) = args
cmd = [v8_shell]
arguments = [js2webui, inputfile, srcrootdir, opts.deps_js,
cxxoutfile, test_type]
cmd.extend(['-e', "arguments=" + json.dumps(arguments), mock_js,
test_api, js2webui])
cmd.extend(['-e', "arguments=" + json.dumps(arguments), test_api, js2webui])
if opts.verbose or opts.impotent:
print(cmd)
if not opts.impotent:
......
......@@ -320,7 +320,6 @@ KNOWN_NON_IOS_LIBRARIES = set([
os.path.join('chrome', 'installer', 'mac', 'third_party', 'xz'),
os.path.join('chrome', 'test', 'data', 'third_party', 'kraken'),
os.path.join('chrome', 'test', 'data', 'third_party', 'spaceport'),
os.path.join('chrome', 'third_party', 'mock4js'),
os.path.join('chrome', 'third_party', 'mozilla_security_manager'),
os.path.join('third_party', 'angle'),
os.path.join('third_party', 'apple_apsl'),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment