feat(windows): Add POST requests, fixes Windows CI issues, and other QOL (#1926)
* Added POST request support for Windows. * Cleanup formatting for docs * Updated test certificate * Reverted publisher name and fixed password mismatch * Fixes to Windows tests * Remove winappdriver install * Run react-native server in background * Added url encoded form support * Added support for custom headers Co-authored-by: Kennedy Mumo <kemumo@microsoft.com>
This commit is contained in:
parent
69e56c7911
commit
d352d147bd
|
@ -54,6 +54,10 @@ jobs:
|
|||
- name: Start Appium server
|
||||
shell: powershell
|
||||
run: Start-Process PowerShell -ArgumentList "yarn appium"
|
||||
|
||||
- name: Start React server
|
||||
shell: powershell
|
||||
run: Start-Process PowerShell -ArgumentList "yarn start:windows"
|
||||
|
||||
- name: Run tests
|
||||
run: yarn test:windows
|
||||
|
|
|
@ -4,28 +4,23 @@
|
|||
*/
|
||||
|
||||
import { driver, By2 } from 'selenium-appium'
|
||||
import { until } from 'selenium-webdriver';
|
||||
|
||||
const setup = require('../jest-setups/jest.setup');
|
||||
jest.setTimeout(50000);
|
||||
jest.setTimeout(150000);
|
||||
|
||||
beforeAll(() => {
|
||||
return driver.startWithCapabilities(setup.capabilites);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
return driver.quit();
|
||||
});
|
||||
const WindowsApplicationDriverUrl = "http://127.0.0.1:4723/wd/hub";
|
||||
|
||||
describe('Alert Tests', () => {
|
||||
|
||||
test('Show Alert', async () => {
|
||||
const showAlertButton = await driver.wait(until.elementLocated(By2.nativeName('Show alert')));
|
||||
await driver.startWithCapabilities(setup.capabilities, WindowsApplicationDriverUrl);
|
||||
const showAlertButton = By2.nativeName('Show alert');
|
||||
await showAlertButton.click();
|
||||
await driver.wait(until.elementLocated(By2.nativeName('Hello! I am an alert box!')));
|
||||
await By2.nativeName('OK').click();
|
||||
const dismissMessage = await driver.wait(until.elementLocated(By2.nativeName('Alert dismissed!')));
|
||||
await By2.nativeName('Hello! I am an alert box!');
|
||||
// await By2.nativeName('OK').click(); All alerts will be automatically dismissed as Windows Webview does not have support for Alerts https://github.com/MicrosoftDocs/winrt-api/blob/docs/windows.ui.xaml.controls/webview.md#use-of-alert
|
||||
const dismissMessage = By2.nativeName('Alert dismissed!');
|
||||
expect(dismissMessage).not.toBeNull();
|
||||
await driver.quit();
|
||||
});
|
||||
|
||||
});
|
|
@ -60,11 +60,12 @@ Autolinking is not yet supported for ReactNativeWindows. Make following addition
|
|||
|
||||
#### **windows/myapp.sln**
|
||||
|
||||
Add the `ReactNativeWebView` project to your solution.
|
||||
Add the `ReactNativeWebView` and `WebViewBridgeComponent` project to your solution.
|
||||
|
||||
1. Open the solution in Visual Studio 2019
|
||||
2. Right-click Solution icon in Solution Explorer > Add > Existing Project
|
||||
Select `node_modules\react-native-webview\windows\ReactNativeWebView\ReactNativeWebView.vcxproj`
|
||||
Select `node_modules\react-native-webview\windows\WebViewBridgeComponent\WebViewBridgeComponent.vcxproj`
|
||||
|
||||
#### **windows/myapp/myapp.vcxproj**
|
||||
|
||||
|
|
|
@ -323,6 +323,7 @@ _Under the hood_
|
|||
|
||||
> On iOS, ~~`injectedJavaScript` runs a method on WebView called `evaluateJavaScript:completionHandler:`~~ – this is no longer true as of version `8.2.0`. Instead, we use a `WKUserScript` with injection time `WKUserScriptInjectionTimeAtDocumentEnd`. As a consequence, `injectedJavaScript` no longer returns an evaluation value nor logs a warning to the console. In the unlikely event that your app depended upon this behaviour, please see migration steps [here](https://github.com/react-native-webview/react-native-webview/pull/1119#issuecomment-574919464) to retain equivalent behaviour.
|
||||
> On Android, `injectedJavaScript` runs a method on the Android WebView called `evaluateJavascriptWithFallback`
|
||||
> On Windows, `injectedJavaScript` runs a method on the WinRT/C++ WebView called `InvokeScriptAsync`
|
||||
|
||||
#### The `injectedJavaScriptBeforeContentLoaded` prop
|
||||
|
||||
|
|
|
@ -106,9 +106,9 @@ The object passed to `source` can have either of the following shapes:
|
|||
**Load uri**
|
||||
|
||||
- `uri` (string) - The URI to load in the `WebView`. Can be a local or remote file, and can be changed with React state or props to navigate to a new page.
|
||||
- `method` (string) - The HTTP Method to use. Defaults to GET if not specified. On Android, the only supported methods are GET and POST.
|
||||
- `method` (string) - The HTTP Method to use. Defaults to GET if not specified. On Android and Windows, the only supported methods are GET and POST.
|
||||
- `headers` (object) - Additional HTTP headers to send with the request. On Android, this can only be used with GET requests. See the [Guide](Guide.md#setting-custom-headers) for more information on setting custom headers.
|
||||
- `body` (string) - The HTTP body to send with the request. This must be a valid UTF-8 string, and will be sent exactly as specified, with no additional encoding (e.g. URL-escaping or base64) applied. On Android, this can only be used with POST requests.
|
||||
- `body` (string) - The HTTP body to send with the request. This must be a valid UTF-8 string, and will be sent exactly as specified, with no additional encoding (e.g. URL-escaping or base64) applied. On Android and Windows, this can only be used with POST requests.
|
||||
|
||||
**Static HTML**
|
||||
|
||||
|
@ -152,12 +152,14 @@ Make sure the string evaluates to a valid type (`true` works) and doesn't otherw
|
|||
On iOS, see [`WKUserScriptInjectionTimeAtDocumentEnd`](https://developer.apple.com/documentation/webkit/wkuserscriptinjectiontime/wkuserscriptinjectiontimeatdocumentend?language=objc). Be sure
|
||||
to set an [`onMessage`](Reference.md#onmessage) handler, even if it's a no-op, or the code will not be run.
|
||||
|
||||
| Type | Required | Platform |
|
||||
| ------ | -------- | ------------------- |
|
||||
| string | No | iOS, Android, macOS |
|
||||
| Type | Required | Platform |
|
||||
| ------ | -------- | ---------------------------- |
|
||||
| string | No | iOS, Android, macOS, Windows |
|
||||
|
||||
To learn more, read the [Communicating between JS and Native](Guide.md#communicating-between-js-and-native) guide.
|
||||
|
||||
_Kindly note: Windows does not have [native support for alerts](https://github.com/MicrosoftDocs/winrt-api/blob/docs/windows.ui.xaml.controls/webview.md#use-of-alert), as such any scripts to show an alert will not work._
|
||||
|
||||
Example:
|
||||
|
||||
Post message a JSON object of `window.location` to be handled by [`onMessage`](Reference.md#onmessage)
|
||||
|
@ -597,8 +599,8 @@ url
|
|||
|
||||
Function that is invoked when the scroll event is fired in the `WebView`.
|
||||
|
||||
| Type | Required | Platform |
|
||||
| -------- | -------- | ----------------------- |
|
||||
| Type | Required | Platform |
|
||||
| -------- | -------- | ---------------------------- |
|
||||
| function | No | iOS, macOS, Android, Windows |
|
||||
|
||||
Example:
|
||||
|
|
|
@ -47,7 +47,7 @@ EndProject
|
|||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
..\..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9
|
||||
..\..\node_modules\react-native-windows\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4
|
||||
..\..\node_modules\react-native-windows\ReactWindowsCore\ReactWindowsCore-Items.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4
|
||||
..\..\node_modules\react-native-windows\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9
|
||||
..\..\node_modules\react-native-windows\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13
|
||||
..\..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{729d9af8-cd9e-4427-9f6c-fb757e287729}*SharedItemsImports = 4
|
||||
|
@ -57,7 +57,6 @@ Global
|
|||
..\..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9
|
||||
..\..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9
|
||||
..\..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||
..\..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||
..\..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||
..\..\node_modules\react-native-windows\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||
..\..\node_modules\react-native-windows\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.15063.0</WindowsTargetPlatformMinVersion>
|
||||
<PackageCertificateKeyFile>WebViewWindows_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
<PackageCertificateThumbprint>82A0D300B0912A62746FFB3E6E04F88985BC2798</PackageCertificateThumbprint>
|
||||
<PackageCertificatePassword>password</PackageCertificatePassword>
|
||||
<AppxPackageSigningEnabled>true</AppxPackageSigningEnabled>
|
||||
<PackageCertificateThumbprint>1DA6E34911B18C433FE3E543D0429FC808468C89</PackageCertificateThumbprint>
|
||||
<PackageCertificatePassword></PackageCertificatePassword>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
|
@ -170,6 +170,7 @@
|
|||
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="$(SolutionDir)packages\Microsoft.UI.Xaml.2.3.191129002\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.UI.Xaml.2.3.191129002\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="Deploy" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
|
|
Binary file not shown.
|
@ -1,10 +1,12 @@
|
|||
import { windowsAppDriverCapabilities } from 'selenium-appium'
|
||||
|
||||
const { platform } = require('./jest.setup.windows');
|
||||
|
||||
switch (platform) {
|
||||
case "windows":
|
||||
const webViewWindowsAppId = 'WebViewWindows_3x6rhkkr9xcf6!App';
|
||||
module.exports = {
|
||||
capabilites: windowsAppDriverCapabilities(webViewWindowsAppId)
|
||||
capabilities: windowsAppDriverCapabilities(webViewWindowsAppId)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1 +1 @@
|
|||
platform = "windows"
|
||||
export const platform = "windows"
|
|
@ -22,7 +22,7 @@
|
|||
"build": "yarn tsc",
|
||||
"prepare": "yarn build",
|
||||
"appium": "appium",
|
||||
"test:windows": "yarn jest --setupFiles=./jest-setups/jest.setup.windows.js"
|
||||
"test:windows": "yarn jest --setupFiles=./jest-setups/jest.setup.js"
|
||||
},
|
||||
"rn-docs": {
|
||||
"title": "Webview",
|
||||
|
@ -67,10 +67,11 @@
|
|||
"react-native": "0.62.2",
|
||||
"react-native-macos": "0.60.0-microsoft.73",
|
||||
"react-native-windows": "0.62.17",
|
||||
"selenium-appium": "0.0.15",
|
||||
"selenium-appium": "1.0.2",
|
||||
"selenium-webdriver": "4.0.0-alpha.7",
|
||||
"semantic-release": "15.13.24",
|
||||
"typescript": "3.8.3"
|
||||
"typescript": "3.8.3",
|
||||
"winappdriver": "^0.0.7"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "ReactWebView.h"
|
||||
#include "JSValueXaml.h"
|
||||
|
||||
|
||||
namespace winrt {
|
||||
using namespace Microsoft::ReactNative;
|
||||
using namespace Windows::Foundation;
|
||||
|
@ -11,6 +12,8 @@ namespace winrt {
|
|||
using namespace Windows::UI;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::Web::Http;
|
||||
using namespace Windows::Web::Http::Headers;
|
||||
}
|
||||
|
||||
namespace winrt::ReactNativeWebView::implementation {
|
||||
|
@ -75,7 +78,52 @@ namespace winrt::ReactNativeWebView::implementation {
|
|||
uriString.replace(0, 7, bundleRootPath.empty() ? "ms-appx-web:///Bundle/" : bundleRootPath);
|
||||
}
|
||||
|
||||
webView.Navigate(winrt::Uri(to_hstring(uriString)));
|
||||
bool hasHeaders = srcMap.find("headers") != srcMap.end();
|
||||
auto httpRequest = winrt::HttpRequestMessage();
|
||||
httpRequest.RequestUri(winrt::Uri(to_hstring(uriString)));
|
||||
if (srcMap.find("method") != srcMap.end() && srcMap.at("method").AsString() == "POST")
|
||||
{
|
||||
httpRequest.Method(winrt::HttpMethod::Post());
|
||||
auto formBody = srcMap.at("body").AsString();
|
||||
bool isUrlEncodedForm = hasHeaders &&
|
||||
srcMap.at("headers").AsObject().find("content-type") !=
|
||||
srcMap.at("headers").AsObject().end() &&
|
||||
srcMap.at("headers").AsObject().at("content-type") == "application/x-www-form-urlencoded";
|
||||
if (isUrlEncodedForm)
|
||||
{
|
||||
auto formContent = winrt::single_threaded_observable_map<winrt::hstring, winrt::hstring>();
|
||||
auto counter = 0;
|
||||
auto current = formBody.find_first_of("&");
|
||||
while (counter <= formBody.find_last_of("&"))
|
||||
{
|
||||
auto keyValueSeparator = formBody.substr(counter, counter + current).find('=');
|
||||
if (keyValueSeparator <= current)
|
||||
{
|
||||
auto key = winrt::to_hstring(formBody.substr(counter, keyValueSeparator));
|
||||
auto value = winrt::to_hstring(formBody.substr(
|
||||
keyValueSeparator + counter + 1, current - keyValueSeparator - 1));
|
||||
formContent.Insert(key, value);
|
||||
}
|
||||
counter += current + 1;
|
||||
current = formBody.substr(counter, formBody.size() - counter).find_first_of("&");
|
||||
}
|
||||
httpRequest.Content(winrt::HttpFormUrlEncodedContent(formContent));
|
||||
httpRequest.Headers().Accept().TryParseAdd(L"application/x-www-form-urlencoded");
|
||||
}
|
||||
else
|
||||
{
|
||||
httpRequest.Content(winrt::HttpStringContent(to_hstring(formBody)));
|
||||
}
|
||||
}
|
||||
if (hasHeaders) {
|
||||
for (auto const& header : srcMap.at("headers").AsObject()) {
|
||||
auto const& headerKey = header.first;
|
||||
auto const& headerValue = header.second;
|
||||
if (headerValue.IsNull()) continue;
|
||||
httpRequest.Headers().TryAppendWithoutValidation(winrt::to_hstring(headerKey), winrt::to_hstring(headerValue.AsString()));
|
||||
}
|
||||
}
|
||||
webView.NavigateWithHttpRequestMessage(httpRequest);
|
||||
}
|
||||
else if (srcMap.find("html") != srcMap.end()) {
|
||||
auto htmlString = srcMap.at("html").AsString();
|
||||
|
|
|
@ -10,4 +10,6 @@
|
|||
#include <winrt/Windows.UI.Xaml.Controls.h>
|
||||
#include <winrt/Windows.UI.Xaml.Markup.h>
|
||||
#include <winrt/Windows.UI.Xaml.Navigation.h>
|
||||
#include <winrt/Windows.Web.Http.h>
|
||||
#include <winrt/Windows.Web.Http.Headers.h>
|
||||
#include <winrt/Microsoft.ReactNative.h>
|
||||
|
|
13
yarn.lock
13
yarn.lock
|
@ -11689,10 +11689,10 @@ scheduler@0.17.0:
|
|||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
selenium-appium@0.0.15:
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/selenium-appium/-/selenium-appium-0.0.15.tgz#27eacd40ebddc1f4af00a1c50278a394e420e2ef"
|
||||
integrity sha512-9/DGdpC8TF88h2eOaFoLIwNDG16He5o2CZOOoaeV1gwNKpkvcpCCA6SjIxgHbWm/0vGzn8TUdmbAlszIoQQzQg==
|
||||
selenium-appium@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/selenium-appium/-/selenium-appium-1.0.2.tgz#78f274c61c2edd4837ef9ffc8c855d70e5b01f29"
|
||||
integrity sha512-+aIvzAoydWhJSfsLd0fdIq7D9eas2Ck7DQxT18fe2bnm5TZE6j+2DaOVK6vUrSp/uUuG+KB9RfAuxfUXQqVPFg==
|
||||
|
||||
selenium-webdriver@3.x:
|
||||
version "3.6.0"
|
||||
|
@ -13297,6 +13297,11 @@ widest-line@^2.0.0:
|
|||
dependencies:
|
||||
string-width "^2.1.1"
|
||||
|
||||
winappdriver@^0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/winappdriver/-/winappdriver-0.0.7.tgz#77c730b1f321c7b0f389612867ae2ef8d4121e82"
|
||||
integrity sha512-Tq9BGwWmnsSdIjMIDtfH5/mdn4Qk2FO5FYAhAcoL0kZByHVtleCwoCFoLG814b4a4BEbVOizuMgY6x7bTFVY/g==
|
||||
|
||||
windows-release@^3.1.0:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999"
|
||||
|
|
Loading…
Reference in New Issue