Refactor ConsoleApiTest to use stored Matchers instead of an intermediate struct

Summary:
bypass-github-export-checks

Changelog: [Internal]

Rewrites all `ConsoleApiTest` test cases to use matchers instead of a homegrown solution for buffering `EXPECT_*` calls.

Reviewed By: robhogan

Differential Revision: D55485495

fbshipit-source-id: 1aa50bbbb5a3b02280ed4a0bee59682716b4fd7e
This commit is contained in:
Moti Zilberman
2024-04-18 08:00:37 -07:00
committed by Facebook GitHub Bot
parent 0276500d19
commit ddc9bd1ff3
2 changed files with 354 additions and 185 deletions
@@ -47,11 +47,6 @@ struct Params {
class ConsoleApiTest
: public JsiIntegrationPortableTest<JsiIntegrationTestHermesEngineAdapter>,
public WithParamInterface<Params> {
struct ExpectedConsoleApiCall {
std::string type;
std::string argsJson;
};
protected:
void SetUp() override {
JsiIntegrationPortableTest::SetUp();
@@ -68,13 +63,11 @@ class ConsoleApiTest
JsiIntegrationPortableTest::TearDown();
}
void expectConsoleApiCall(std::string type, std::string argsJson) {
ExpectedConsoleApiCall call{
.type = std::move(type), .argsJson = std::move(argsJson)};
void expectConsoleApiCall(Matcher<folly::dynamic> paramsMatcher) {
if (runtimeEnabled_) {
expectConsoleApiCallImpl(std::move(call));
expectConsoleApiCallImpl(std::move(paramsMatcher));
} else {
expectedConsoleApiCalls_.emplace_back(call);
expectedConsoleApiCalls_.emplace_back(paramsMatcher);
}
}
@@ -87,11 +80,10 @@ class ConsoleApiTest
}
private:
void expectConsoleApiCallImpl(ExpectedConsoleApiCall call) {
void expectConsoleApiCallImpl(Matcher<folly::dynamic> paramsMatcher) {
this->expectMessageFromPage(JsonParsed(AllOf(
AtJsonPtr("/method", "Runtime.consoleAPICalled"),
AtJsonPtr("/params/type", call.type),
AtJsonPtr("/params/args", Eq(folly::parseJson(call.argsJson))))));
AtJsonPtr("/params", std::move(paramsMatcher)))));
}
void enableRuntimeDomain() {
@@ -143,7 +135,7 @@ class ConsoleApiTest
}
}
std::vector<ExpectedConsoleApiCall> expectedConsoleApiCalls_;
std::vector<Matcher<folly::dynamic>> expectedConsoleApiCalls_;
bool runtimeEnabled_{false};
};
@@ -171,91 +163,128 @@ class ConsoleApiTestWithPreExistingConsole : public ConsoleApiTest {
TEST_P(ConsoleApiTest, testConsoleLog) {
InSequence s;
expectConsoleApiCall("log", R"([{
"type": "string",
"value": "hello"
}, {
"type": "string",
"value": "world"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "log"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "hello"
}, {
"type": "string",
"value": "world"
}])"_json)));
eval("console.log('hello', 'world');");
}
TEST_P(ConsoleApiTest, testConsoleDebug) {
InSequence s;
expectConsoleApiCall("debug", R"([{
"type": "string",
"value": "hello fusebox"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "debug"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "hello fusebox"
}])"_json)));
eval("console.debug('hello fusebox');");
}
TEST_P(ConsoleApiTest, testConsoleInfo) {
InSequence s;
expectConsoleApiCall("info", R"([{
"type": "string",
"value": "you should know this"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "info"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "you should know this"
}])"_json)));
eval("console.info('you should know this');");
}
TEST_P(ConsoleApiTest, testConsoleError) {
InSequence s;
expectConsoleApiCall("error", R"([{
"type": "string",
"value": "uh oh"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "error"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "uh oh"
}])"_json)));
eval("console.error('uh oh');");
}
TEST_P(ConsoleApiTest, testConsoleWarn) {
InSequence s;
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "careful"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "careful"
}])"_json)));
eval("console.warn('careful');");
}
TEST_P(ConsoleApiTest, testConsoleDir) {
InSequence s;
expectConsoleApiCall("dir", R"([{
"type": "string",
"value": "something"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "dir"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "something"
}])"_json)));
eval("console.dir('something');");
}
TEST_P(ConsoleApiTest, testConsoleDirxml) {
InSequence s;
expectConsoleApiCall("dirxml", R"([{
"type": "string",
"value": "pretend this is a DOM element"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "dirxml"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "pretend this is a DOM element"
}])"_json)));
eval("console.dirxml('pretend this is a DOM element');");
}
TEST_P(ConsoleApiTest, testConsoleTable) {
InSequence s;
expectConsoleApiCall("table", R"([{
"type": "string",
"value": "pretend this is a complex object"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "table"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "pretend this is a complex object"
}])"_json)));
eval("console.table('pretend this is a complex object');");
}
TEST_P(ConsoleApiTest, testConsoleTrace) {
InSequence s;
expectConsoleApiCall("trace", R"([{
"type": "string",
"value": "trace trace"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "trace"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "trace trace"
}])"_json)));
eval("console.trace('trace trace');");
}
TEST_P(ConsoleApiTest, testConsoleClear) {
InSequence s;
expectConsoleApiCall("clear", "[]");
expectConsoleApiCall(
AllOf(AtJsonPtr("/type", "clear"), AtJsonPtr("/args", "[]"_json)));
eval("console.clear();");
}
@@ -264,27 +293,41 @@ TEST_P(ConsoleApiTest, testConsoleClearAfterOtherCall) {
if (isRuntimeDomainEnabled()) {
// This should only be delivered if console notifications are enabled, not
// when they're being cached for later.
expectConsoleApiCall("log", R"([{
"type": "string",
"value": "hello"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "log"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "hello"
}])"_json)));
}
expectConsoleApiCall("clear", "[]");
expectConsoleApiCall(
AllOf(AtJsonPtr("/type", "clear"), AtJsonPtr("/args", "[]"_json)));
eval("console.log('hello');");
eval("console.clear();");
}
TEST_P(ConsoleApiTest, testConsoleGroup) {
InSequence s;
expectConsoleApiCall("startGroup", R"([{
"type": "string",
"value": "group title"
}])");
expectConsoleApiCall("log", R"([{
"type": "string",
"value": "in group"
}])");
expectConsoleApiCall("endGroup", "[]");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "startGroup"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "group title"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "log"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "in group"
}])"_json)));
expectConsoleApiCall(
AllOf(AtJsonPtr("/type", "endGroup"), AtJsonPtr("/args", "[]"_json)));
eval("console.group('group title');");
eval("console.log('in group');");
eval("console.groupEnd();");
@@ -292,15 +335,24 @@ TEST_P(ConsoleApiTest, testConsoleGroup) {
TEST_P(ConsoleApiTest, testConsoleGroupCollapsed) {
InSequence s;
expectConsoleApiCall("startGroupCollapsed", R"([{
"type": "string",
"value": "group collapsed title"
}])");
expectConsoleApiCall("log", R"([{
"type": "string",
"value": "in group collapsed"
}])");
expectConsoleApiCall("endGroup", "[]");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "startGroupCollapsed"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "group collapsed title"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "log"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "in group collapsed"
}])"_json)));
expectConsoleApiCall(
AllOf(AtJsonPtr("/type", "endGroup"), AtJsonPtr("/args", "[]"_json)));
eval("console.groupCollapsed('group collapsed title');");
eval("console.log('in group collapsed');");
eval("console.groupEnd();");
@@ -308,93 +360,149 @@ TEST_P(ConsoleApiTest, testConsoleGroupCollapsed) {
TEST_P(ConsoleApiTest, testConsoleAssert) {
InSequence s;
expectConsoleApiCall("assert", R"([{
"type": "string",
"value": "Assertion failed: something is bad"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "assert"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Assertion failed: something is bad"
}])"_json)));
eval("console.assert(true, 'everything is good');");
eval("console.assert(false, 'something is bad');");
expectConsoleApiCall("assert", R"([{
"type": "string",
"value": "Assertion failed"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "assert"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Assertion failed"
}])"_json)));
eval("console.assert();");
}
TEST_P(ConsoleApiTest, testConsoleCount) {
InSequence s;
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "default: 1"
}])");
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "default: 2"
}])");
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "default: 3"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "default: 1"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "default: 2"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "default: 3"
}])"_json)));
eval("console.count();");
eval("console.count('default');");
eval("console.count();");
eval("console.countReset();");
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "default: 1"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "default: 1"
}])"_json)));
eval("console.count();");
eval("console.countReset('default');");
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "default: 1"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "default: 1"
}])"_json)));
eval("console.count();");
}
TEST_P(ConsoleApiTest, testConsoleCountLabel) {
InSequence s;
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "foo: 1"
}])");
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "foo: 2"
}])");
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "foo: 3"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "foo: 1"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "foo: 2"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "foo: 3"
}])"_json)));
eval("console.count('foo');");
eval("console.count('foo');");
eval("console.count('foo');");
eval("console.countReset('foo');");
expectConsoleApiCall("count", R"([{
"type": "string",
"value": "foo: 1"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "count"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "foo: 1"
}])"_json)));
eval("console.count('foo');");
}
TEST_P(ConsoleApiTest, testConsoleCountResetInvalidLabel) {
InSequence s;
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Count for 'default' does not exist"
}])");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Count for 'default' does not exist"
}])");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Count for 'foo' does not exist"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Count for 'default' does not exist"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Count for 'default' does not exist"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Count for 'foo' does not exist"
}])"_json)));
eval("console.countReset();");
eval("console.countReset('default');");
eval("console.countReset('foo');");
@@ -405,50 +513,82 @@ TEST_P(ConsoleApiTest, testConsoleCountResetInvalidLabel) {
TEST_P(ConsoleApiTest, testConsoleTimeExistingLabel) {
eval("console.time();");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'default' already exists"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'default' already exists"
}])"_json)));
eval("console.time('default');");
eval("console.time('foo');");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'foo' already exists"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'foo' already exists"
}])"_json)));
eval("console.time('foo');");
}
TEST_P(ConsoleApiTest, testConsoleTimeInvalidLabel) {
InSequence s;
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'foo' does not exist"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'foo' does not exist"
}])"_json)));
eval("console.timeEnd();");
eval("console.timeEnd('default');");
eval("console.timeEnd('foo');");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "Timer 'foo' does not exist"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'default' does not exist"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "Timer 'foo' does not exist"
}])"_json)));
eval("console.timeLog();");
eval("console.timeLog('default');");
eval("console.timeLog('foo');");
@@ -456,10 +596,14 @@ TEST_P(ConsoleApiTest, testConsoleTimeInvalidLabel) {
TEST_P(ConsoleApiTest, testConsoleSilentlyClearedOnReload) {
InSequence s;
expectConsoleApiCall("log", R"([{
"type": "string",
"value": "hello"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "log"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "hello"
}])"_json)));
eval("console.log('hello');");
// If there are any expectations we haven't checked yet, clear them
@@ -475,27 +619,43 @@ TEST_P(ConsoleApiTest, testConsoleSilentlyClearedOnReload) {
}
reload();
expectConsoleApiCall("log", R"([{
"type": "string",
"value": "world"
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "log"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "world"
}])"_json)));
eval("console.log('world');");
}
TEST_P(ConsoleApiTestWithPreExistingConsole, testPreExistingConsoleObject) {
InSequence s;
expectConsoleApiCall("log", R"([{
"type": "string",
"value": "hello"
}])");
expectConsoleApiCall("warning", R"([{
"type": "string",
"value": "world"
}])");
expectConsoleApiCall("table", R"([{
"type": "number",
"value": 42
}])");
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "log"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "hello"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "warning"),
AtJsonPtr(
"/args",
R"([{
"type": "string",
"value": "world"
}])"_json)));
expectConsoleApiCall(AllOf(
AtJsonPtr("/type", "table"),
AtJsonPtr(
"/args",
R"([{
"type": "number",
"value": 42
}])"_json)));
eval("console.log('hello');");
eval("console.warn('world');");
// NOTE: not present in the pre-existing console object
@@ -77,4 +77,13 @@ MATCHER_P2(
return false;
}
/**
* A user-defined literal for constructing a folly::dynamic from a JSON
* string. Not technically specific to GMock, but convenient to have in a test
* suite.
*/
inline folly::dynamic operator""_json(const char* s, size_t n) {
return folly::parseJson(std::string{s, n});
}
} // namespace facebook