Skip to content

Commit c8085b5

Browse files
authored
Enable WebSocketModule unit tests (microsoft#4538)
* Prototype mockable MessageQueueThread and JSExecutor * Declare MockJSExecutor::CallFunctionFunctor * Add missing using std::unique_ptr * Use WebSocketModule::MethodId * clang format * Make WebSocketModule methods override instead of virtual. * Allow WebSocketModule to use custom resource factory * Rename *Impl to *Mock * Move Instance mocks into separate source files * Move Instance mocks into separate source files * Change files * clang format * Define WebSocketModule::SetResourceFactory
1 parent a09aa19 commit c8085b5

11 files changed

+376
-13
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "none",
3+
"packageName": "react-native-windows",
4+
"email": "julio@rochsquadron.net",
5+
"dependentChangeType": "none",
6+
"date": "2020-04-09T23:51:25.594Z"
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"type": "none",
3+
"comment": "Allow WebSocketModule to use custom resource factory",
4+
"packageName": "react-native-windows",
5+
"email": "julio@rochsquadron.net",
6+
"dependentChangeType": "none",
7+
"date": "2020-04-09T23:51:56.846Z"
8+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include "InstanceMocks.h"
2+
3+
#include <cxxreact/ModuleRegistry.h>
4+
5+
using namespace facebook::react;
6+
7+
using folly::dynamic;
8+
using std::function;
9+
using std::make_shared;
10+
using std::make_unique;
11+
using std::shared_ptr;
12+
using std::string;
13+
using std::unique_ptr;
14+
using std::vector;
15+
16+
namespace Microsoft::React::Test {
17+
#pragma region MockMessageQueueThread
18+
void MockMessageQueueThread::runOnQueue(function<void()> &&work) /*override*/
19+
{
20+
work();
21+
}
22+
23+
void MockMessageQueueThread::runOnQueueSync(function<void()> &&work) /*override*/
24+
{
25+
work();
26+
}
27+
28+
void MockMessageQueueThread::quitSynchronous() /*override*/ {}
29+
#pragma endregion // MockMessageQueueThread
30+
31+
#pragma region MockInstanceCallback
32+
33+
void MockInstanceCallback::onBatchComplete() /*override*/ {}
34+
void MockInstanceCallback::incrementPendingJSCalls() /*override*/ {}
35+
void MockInstanceCallback::decrementPendingJSCalls() /*override*/ {}
36+
37+
#pragma endregion // MockInstanceCallback
38+
39+
#pragma region MockJSExecutor
40+
41+
void MockJSExecutor::loadApplicationScript(unique_ptr<const JSBigString> script, string sourceURL) {}
42+
void MockJSExecutor::setBundleRegistry(unique_ptr<RAMBundleRegistry> bundleRegistry) {}
43+
void MockJSExecutor::registerBundle(uint32_t bundleId, const string &bundlePath) {}
44+
45+
void MockJSExecutor::callFunction(const string &moduleId, const string &methodId, const dynamic &arguments) {
46+
if (CallFunctionMock) {
47+
CallFunctionMock(moduleId, methodId, arguments);
48+
}
49+
}
50+
51+
void MockJSExecutor::invokeCallback(const double callbackId, const dynamic &arguments) {}
52+
void MockJSExecutor::setGlobalVariable(string propName, unique_ptr<const JSBigString> jsonValue) {}
53+
void *MockJSExecutor::getJavaScriptContext() {
54+
return nullptr;
55+
}
56+
57+
bool MockJSExecutor::isInspectable() {
58+
return false;
59+
}
60+
std::string MockJSExecutor::getDescription() {
61+
return {};
62+
}
63+
void MockJSExecutor::handleMemoryPressure(__unused int pressureLevel) {}
64+
void MockJSExecutor::destroy() {}
65+
void MockJSExecutor::flush() {}
66+
67+
#pragma endregion // MockJSExecutor
68+
69+
#pragma region MockJSExecutorFactory
70+
71+
unique_ptr<JSExecutor> MockJSExecutorFactory::createJSExecutor(
72+
shared_ptr<ExecutorDelegate> delegate,
73+
shared_ptr<MessageQueueThread> jsQueue) /*override*/
74+
{
75+
if (CreateJSExecutorMock) {
76+
return CreateJSExecutorMock(delegate, jsQueue);
77+
}
78+
79+
return make_unique<MockJSExecutor>();
80+
}
81+
82+
#pragma endregion // MockJSExecutorFactory
83+
84+
shared_ptr<Instance> CreateMockInstance(shared_ptr<JSExecutorFactory> jsef) {
85+
auto instance = make_shared<Instance>();
86+
auto callback = make_unique<MockInstanceCallback>();
87+
auto jsQueue = make_shared<MockMessageQueueThread>();
88+
auto moduleRegistry = make_shared<ModuleRegistry>(
89+
vector<unique_ptr<NativeModule>>(), // modules
90+
nullptr // moduleNotFoundCallback
91+
);
92+
93+
instance->initializeBridge(std::move(callback), jsef, jsQueue, moduleRegistry);
94+
95+
return instance;
96+
}
97+
98+
} // namespace Microsoft::React::Test
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#pragma once
2+
3+
#include <cxxreact/Instance.h>
4+
#include <cxxreact/JSBigString.h>
5+
#include <cxxreact/JSExecutor.h>
6+
#include <cxxreact/MessageQueueThread.h>
7+
#include <cxxreact/RAMBundleRegistry.h>
8+
9+
namespace Microsoft::React::Test {
10+
std::shared_ptr<facebook::react::Instance> CreateMockInstance(std::shared_ptr<facebook::react::JSExecutorFactory> jsef);
11+
12+
class MockMessageQueueThread : public facebook::react::MessageQueueThread {
13+
public:
14+
#pragma region MessageQueueThread overrides
15+
16+
void runOnQueue(std::function<void()> &&) override;
17+
18+
void runOnQueueSync(std::function<void()> &&) override;
19+
20+
void quitSynchronous() override;
21+
22+
#pragma endregion // MessageQueueThread overrides
23+
};
24+
25+
class MockInstanceCallback : public facebook::react::InstanceCallback {
26+
public:
27+
#pragma region InstanceCallback overrides
28+
29+
void onBatchComplete() override;
30+
void incrementPendingJSCalls() override;
31+
void decrementPendingJSCalls() override;
32+
33+
#pragma endregion // InstanceCallback overrides
34+
};
35+
36+
class MockJSExecutor : public facebook::react::JSExecutor {
37+
public:
38+
std::function<void(const std::string &, const std::string &, const folly::dynamic &)> CallFunctionMock;
39+
40+
#pragma region JSExecutor overrides
41+
42+
void loadApplicationScript(std::unique_ptr<const facebook::react::JSBigString> script, std::string sourceURL)
43+
override;
44+
45+
void setBundleRegistry(std::unique_ptr<facebook::react::RAMBundleRegistry> bundleRegistry) override;
46+
47+
void registerBundle(uint32_t bundleId, const std::string &bundlePath) override;
48+
49+
void callFunction(const std::string &moduleId, const std::string &methodId, const folly::dynamic &arguments) override;
50+
51+
void invokeCallback(const double callbackId, const folly::dynamic &arguments) override;
52+
53+
void setGlobalVariable(std::string propName, std::unique_ptr<const facebook::react::JSBigString> jsonValue) override;
54+
55+
void *getJavaScriptContext() override;
56+
57+
bool isInspectable() override;
58+
59+
std::string getDescription() override;
60+
61+
void handleMemoryPressure(__unused int pressureLevel) override;
62+
63+
void destroy() override;
64+
65+
void flush() override;
66+
67+
#pragma endregion // JSExecutor overrides
68+
};
69+
70+
class MockJSExecutorFactory : public facebook::react::JSExecutorFactory {
71+
public:
72+
std::function<std::unique_ptr<facebook::react::JSExecutor>(
73+
std::shared_ptr<facebook::react::ExecutorDelegate>,
74+
std::shared_ptr<facebook::react::MessageQueueThread>)>
75+
CreateJSExecutorMock;
76+
77+
#pragma region JSExecutorFactory overrides
78+
79+
std::unique_ptr<facebook::react::JSExecutor> createJSExecutor(
80+
std::shared_ptr<facebook::react::ExecutorDelegate> delegate,
81+
std::shared_ptr<facebook::react::MessageQueueThread> jsQueue) override;
82+
83+
#pragma endregion // JSExecutorFactory overrides
84+
};
85+
86+
} // namespace Microsoft::React::Test

vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,14 @@
8787
<ClCompile Include="EmptyUIManagerModule.cpp" />
8888
<ClCompile Include="LayoutAnimationTests.cpp" />
8989
<ClCompile Include="MemoryMappedBufferTests.cpp" />
90+
<ClCompile Include="InstanceMocks.cpp" />
9091
<ClCompile Include="UnicodeConversionTest.cpp" />
9192
<ClCompile Include="UnicodeTestStrings.cpp" />
9293
<ClCompile Include="StringConversionTest_Desktop.cpp" />
9394
<ClCompile Include="UIManagerModuleTest.cpp" />
9495
<ClCompile Include="UtilsTest.cpp" />
9596
<ClCompile Include="WebSocketJSExecutorTest.cpp" />
97+
<ClCompile Include="WebSocketMocks.cpp" />
9698
<ClCompile Include="WebSocketModuleTest.cpp" />
9799
<ClCompile Include="WebSocketTest.cpp" />
98100
</ItemGroup>
@@ -104,7 +106,9 @@
104106
<ItemGroup>
105107
<ClInclude Include="AsyncStorageTestClass.h" />
106108
<ClInclude Include="EmptyUIManagerModule.h" />
109+
<ClInclude Include="InstanceMocks.h" />
107110
<ClInclude Include="UnicodeTestStrings.h" />
111+
<ClInclude Include="WebSocketMocks.h" />
108112
</ItemGroup>
109113
<ItemGroup>
110114
<ProjectReference Include="..\Desktop\React.Windows.Desktop.vcxproj">

vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
<ClCompile Include="MemoryMappedBufferTests.cpp">
4747
<Filter>Source Files</Filter>
4848
</ClCompile>
49+
<ClCompile Include="WebSocketMocks.cpp">
50+
<Filter>Source Files</Filter>
51+
</ClCompile>
52+
<ClCompile Include="InstanceMocks.cpp">
53+
<Filter>Source Files</Filter>
54+
</ClCompile>
4955
</ItemGroup>
5056
<ItemGroup>
5157
<None Include="packages.config" />
@@ -68,5 +74,11 @@
6874
<ClInclude Include="UnicodeTestStrings.h">
6975
<Filter>Header Files</Filter>
7076
</ClInclude>
77+
<ClInclude Include="WebSocketMocks.h">
78+
<Filter>Header Files</Filter>
79+
</ClInclude>
80+
<ClInclude Include="InstanceMocks.h">
81+
<Filter>Header Files</Filter>
82+
</ClInclude>
7183
</ItemGroup>
7284
</Project>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "WebSocketMocks.h"
2+
3+
using std::function;
4+
using std::string;
5+
6+
namespace Microsoft::React::Test {
7+
#pragma region IWebSocketResource overrides
8+
9+
void MockWebSocketResource::Connect(const Protocols &, const Options &) /*override*/
10+
{
11+
m_onConnect();
12+
}
13+
14+
void MockWebSocketResource::Ping() /*override*/ {}
15+
16+
void MockWebSocketResource::Send(const string &) /*override*/ {}
17+
18+
void MockWebSocketResource::SendBinary(const string &) /*override*/ {}
19+
20+
void MockWebSocketResource::Close(CloseCode, const string &) /*override*/ {}
21+
22+
IWebSocketResource::ReadyState MockWebSocketResource::GetReadyState() const /*override*/
23+
{
24+
return ReadyState::Open;
25+
}
26+
27+
void MockWebSocketResource::SetOnConnect(function<void()> &&onConnect) /*override*/
28+
{
29+
m_onConnect = std::move(onConnect);
30+
}
31+
32+
void MockWebSocketResource::SetOnPing(function<void()> &&) /*override*/ {}
33+
34+
void MockWebSocketResource::SetOnSend(function<void(size_t)> &&) /*override*/ {}
35+
36+
void MockWebSocketResource::SetOnMessage(function<void(size_t, const string &)> &&) /*override*/ {}
37+
38+
void MockWebSocketResource::SetOnClose(function<void(CloseCode, const string &)> &&) /*override*/ {}
39+
40+
void MockWebSocketResource::SetOnError(function<void(Error &&)> &&) /*override*/ {}
41+
42+
#pragma endregion IWebSocketResource overrides
43+
} // namespace Microsoft::React::Test
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <IWebSocketResource.h>
4+
5+
namespace Microsoft::React::Test {
6+
struct MockWebSocketResource : public IWebSocketResource {
7+
#pragma region IWebSocketResource overrides
8+
9+
void Connect(const Protocols &, const Options &) override;
10+
11+
void Ping() override;
12+
13+
void Send(const std::string &) override;
14+
15+
void SendBinary(const std::string &) override;
16+
17+
void Close(CloseCode, const std::string &) override;
18+
19+
ReadyState GetReadyState() const override;
20+
21+
void SetOnConnect(std::function<void()> &&onConnect) override;
22+
23+
void SetOnPing(std::function<void()> &&) override;
24+
25+
void SetOnSend(std::function<void(size_t)> &&) override;
26+
27+
void SetOnMessage(std::function<void(size_t, const std::string &)> &&) override;
28+
29+
void SetOnClose(std::function<void(CloseCode, const std::string &)> &&) override;
30+
31+
void SetOnError(std::function<void(Error &&)> &&) override;
32+
33+
#pragma endregion IWebSocketResource overrides
34+
35+
private:
36+
std::function<void()> m_onConnect;
37+
};
38+
39+
} // namespace Microsoft::React::Test

0 commit comments

Comments
 (0)