Enable integration test web application (#12714)
* Create TestServices project
This commit is contained in:
Родитель
86bf444670
Коммит
a09af289ff
|
@ -60,7 +60,7 @@ parameters:
|
|||
- X86ReleaseFabric:
|
||||
BuildConfiguration: Release
|
||||
BuildPlatform: x86
|
||||
UseFabric: true
|
||||
UseFabric: true
|
||||
|
||||
jobs:
|
||||
- ${{ each config in parameters.buildMatrix }}:
|
||||
|
@ -78,11 +78,14 @@ jobs:
|
|||
|
||||
#5059 - Disable failing or intermittent tests (IntegrationTestHarness,WebSocket,Logging).
|
||||
#10732 - WebSocketIntegrationTest::SendReceiveSsl fails on Windows Server 2022.
|
||||
#12714 - Disable for first deployment of test website.
|
||||
# RNTesterIntegrationTests::WebSocket
|
||||
# RNTesterIntegrationTests::WebSocketBlob
|
||||
- name: Desktop.IntegrationTests.Filter
|
||||
value: >
|
||||
(FullyQualifiedName!=RNTesterIntegrationTests::Blob)&
|
||||
(FullyQualifiedName!=RNTesterIntegrationTests::IntegrationTestHarness)&
|
||||
(FullyQualifiedName!=WebSocketResourcePerformanceTest::ProcessThreadsPerResource)&
|
||||
(FullyQualifiedName!=RNTesterIntegrationTests::WebSocket)&
|
||||
(FullyQualifiedName!=RNTesterIntegrationTests::WebSocketBlob)&
|
||||
(FullyQualifiedName!=WebSocketIntegrationTest::SendReceiveSsl)&
|
||||
(FullyQualifiedName!=Microsoft::React::Test::HttpOriginPolicyIntegrationTest)
|
||||
#6799 -
|
||||
|
@ -100,6 +103,31 @@ jobs:
|
|||
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
|
||||
|
||||
steps:
|
||||
# Set up IIS tests {
|
||||
- pwsh: |
|
||||
Install-WindowsFeature -Name Web-Server, Web-Scripting-Tools
|
||||
displayName: Install IIS
|
||||
|
||||
- pwsh: |
|
||||
Invoke-WebRequest `
|
||||
-Uri 'https://download.visualstudio.microsoft.com/download/pr/20598243-c38f-4538-b2aa-af33bc232f80/ea9b2ca232f59a6fdc84b7a31da88464/dotnet-hosting-8.0.3-win.exe' `
|
||||
-OutFile dotnet-hosting-8.0.3-win.exe
|
||||
|
||||
Write-Host 'Installing .NET hosting bundle'
|
||||
Start-Process -Wait -FilePath .\dotnet-hosting-8.0.3-win.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART'
|
||||
Write-Host 'Installed .NET hosting bundle'
|
||||
|
||||
Invoke-WebRequest `
|
||||
-Uri 'https://download.visualstudio.microsoft.com/download/pr/f2ec926e-0d98-4a8b-8c70-722ccc2ca0e5/b59941b0c60f16421679baafdb7e9338/dotnet-sdk-7.0.407-win-x64.exe' `
|
||||
-OutFile dotnet-sdk-7.0.407-win-x64.exe
|
||||
|
||||
Write-Host 'Installing .NET 7 SDK'
|
||||
Start-Process -Wait -FilePath .\dotnet-sdk-7.0.407-win-x64.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART'
|
||||
Write-Host 'Installed .NET 7 SDK'
|
||||
displayName: Install the .NET Core Hosting Bundle
|
||||
|
||||
# } Set up IIS tests
|
||||
|
||||
- template: ../templates/checkout-shallow.yml
|
||||
|
||||
- template: ../templates/prepare-js-env.yml
|
||||
|
@ -168,11 +196,89 @@ jobs:
|
|||
filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tfs\Start-TestServers.ps1
|
||||
arguments: -SourcesDirectory $(Build.SourcesDirectory)\vnext -Preload -SleepSeconds 120
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Publish Test Website
|
||||
inputs:
|
||||
command: publish
|
||||
publishWebProjects: false
|
||||
zipAfterPublish: false
|
||||
projects: $(Build.SourcesDirectory)\vnext\TestWebsite\Microsoft.ReactNative.Test.Website.csproj
|
||||
arguments: --configuration ${{ matrix.BuildConfiguration }}
|
||||
|
||||
- pwsh: |
|
||||
# Create and make available to IIS
|
||||
$cert = New-SelfSignedCertificate `
|
||||
-Type SSLServerAuthentication `
|
||||
-KeyExportPolicy Exportable `
|
||||
-Subject 'CN=localhost' `
|
||||
-NotAfter ([DateTime]::Now).AddHours(2) `
|
||||
-CertStoreLocation Cert:\LocalMachine\My\
|
||||
|
||||
$certPath = "${env:TEMP}\localhost.pfx"
|
||||
$certPass = -join ('a'..'z' | Get-Random -Count 32) | ConvertTo-SecureString -AsPlainText -Force
|
||||
$certHash = $cert.Thumbprint
|
||||
Write-Host "##vso[task.setvariable variable=TestWebsiteCertificateThumbprint]$certHash"
|
||||
|
||||
# Export PFX
|
||||
$cert | Export-PfxCertificate -FilePath $certPath -Password $certPass
|
||||
|
||||
# Trust globally
|
||||
Import-PfxCertificate `
|
||||
-Exportable `
|
||||
-FilePath $certPath `
|
||||
-Password $certPass `
|
||||
-CertStoreLocation Cert:\LocalMachine\Root\
|
||||
displayName: Install SSL Certificate
|
||||
|
||||
- task: IISWebAppManagementOnMachineGroup@0
|
||||
displayName: Create Test Website
|
||||
inputs:
|
||||
EnableIIS: false
|
||||
IISDeploymentType: IISWebsite
|
||||
ActionIISWebsite: CreateOrUpdateWebsite
|
||||
SSLCertThumbPrint: $(TestWebsiteCertificateThumbprint)
|
||||
# IIS Website
|
||||
WebsiteName: RNW Test Website
|
||||
WebsitePhysicalPath: $(Build.SourcesDirectory)\vnext\target\${{ matrix.BuildPlatform }}\${{ matrix.BuildConfiguration }}\Microsoft.ReactNative.Test.Website\Publish
|
||||
WebsitePhysicalPathAuth: WebsiteUserPassThrough
|
||||
CreateOrUpdateAppPoolForWebsite: false
|
||||
ConfigureAuthenticationForWebsite: false
|
||||
# IIS Application pool
|
||||
AppPoolNameForWebsite: DefaultAppPool
|
||||
# IIS Bindings
|
||||
# See https://stackoverflow.com/questions/60089756
|
||||
AddBinding: true
|
||||
Bindings: |
|
||||
{
|
||||
bindings: [
|
||||
{
|
||||
"protocol": "http",
|
||||
"ipAddress": "*",
|
||||
"port": "5555",
|
||||
"sslThumbprint": "",
|
||||
"sniFlag": false
|
||||
},
|
||||
{
|
||||
"protocol": "https",
|
||||
"ipAddress": "*",
|
||||
"port": "5543",
|
||||
"sslThumbprint": "$(TestWebsiteCertificateThumbprint)",
|
||||
"sniFlag": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Check the metro bundle server
|
||||
displayName: Ensure servers readiness
|
||||
inputs:
|
||||
targetType: 'inline'
|
||||
script: Invoke-WebRequest -UseBasicParsing -Uri "http://localhost:8081/IntegrationTests/IntegrationTestsApp.bundle?platform=windows&dev=true"
|
||||
script: |
|
||||
# Test website
|
||||
Invoke-WebRequest -Uri 'http://localhost:5555'
|
||||
Invoke-WebRequest -Uri 'https://localhost:5543'
|
||||
|
||||
# Bundler
|
||||
Invoke-WebRequest -UseBasicParsing -Uri "http://localhost:8081/IntegrationTests/IntegrationTestsApp.bundle?platform=windows&dev=true"
|
||||
|
||||
- task: VSTest@2
|
||||
displayName: Run Desktop Integration Tests
|
||||
|
|
|
@ -140,6 +140,7 @@ package-lock.json
|
|||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
vnext/.vscode/*
|
||||
|
||||
#JavaScript files
|
||||
*.jsbundle
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
>
|
||||
<Output TaskParameter="ExitCode" ItemName="_ReactNativeYarnExitCode"/>
|
||||
</Exec>
|
||||
|
||||
|
||||
<Message Text="yarn install: Succeeded" Condition="'%(_ReactNativeYarnExitCode.Identity)' == '0'" Importance="High" />
|
||||
<Message Text="yarn install: Failed" Condition="'%(_ReactNativeYarnExitCode.Identity)' != '0'" Importance="High" />
|
||||
|
||||
|
@ -91,8 +91,10 @@
|
|||
VCTargetsPath;
|
||||
UserRootDir;
|
||||
ProjectHome;
|
||||
BaseIntermediateOutputPath;
|
||||
IntermediateOutputPath;
|
||||
OutputPath;
|
||||
OS;
|
||||
" />
|
||||
<_VarsCustom Include="
|
||||
RootDir;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "prerelease",
|
||||
"comment": "Implement test website",
|
||||
"packageName": "react-native-windows",
|
||||
"email": "julio.rocha@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -743,6 +743,46 @@ TEST_CLASS(HttpOriginPolicyIntegrationTest)
|
|||
TestOriginPolicy(serverArgs, clientArgs, s_shouldFail);
|
||||
} // FullCors304ForSimpleGetFails
|
||||
|
||||
TEST_METHOD(OfficeDev_OfficeJS_4144)
|
||||
{
|
||||
SetRuntimeOptionString("Http.GlobalOrigin", "http://orig.in");
|
||||
SetRuntimeOptionInt("Http.OriginPolicy", static_cast<int32_t>(OriginPolicy::CrossOriginResourceSharing));
|
||||
|
||||
ClientParams clientArgs(http::verb::get, {} /*headers*/);
|
||||
auto resource = IHttpResource::Make();
|
||||
resource->SetOnResponse([&clientArgs](int64_t, IHttpResource::Response&& res)
|
||||
{
|
||||
clientArgs.Response = std::move(res);
|
||||
});
|
||||
resource->SetOnData([&clientArgs](int64_t, string&& content)
|
||||
{
|
||||
clientArgs.ResponseContent = std::move(content);
|
||||
clientArgs.ContentPromise.set_value();
|
||||
});
|
||||
resource->SetOnError([&clientArgs](int64_t, string&& message, bool)
|
||||
{
|
||||
clientArgs.ErrorMessage = std::move(message);
|
||||
clientArgs.ContentPromise.set_value();
|
||||
});
|
||||
|
||||
resource->SendRequest(
|
||||
string { http::to_string(clientArgs.Method).data() },
|
||||
string { "http://localhost:5555/officedev/office-js/issues/4144"},
|
||||
0, /*requestId*/
|
||||
std::move(clientArgs.RequestHeaders),
|
||||
{ { "string", "" } }, /*data*/
|
||||
"text",
|
||||
false, /*useIncrementalUpdates*/
|
||||
0, /*timeout*/
|
||||
clientArgs.WithCredentials, /*withCredentials*/
|
||||
[](int64_t) {} /*reactCallback*/
|
||||
);
|
||||
|
||||
clientArgs.ContentPromise.get_future().wait();
|
||||
|
||||
Assert::AreEqual({}, clientArgs.ErrorMessage);
|
||||
}
|
||||
|
||||
TEST_METHOD(FullCorsPreflightSucceeds)
|
||||
{
|
||||
ServerParams serverArgs(s_port);
|
||||
|
|
|
@ -209,7 +209,6 @@ TEST_CLASS (RNTesterIntegrationTests) {
|
|||
}
|
||||
|
||||
BEGIN_TEST_METHOD_ATTRIBUTE(WebSocketBlob)
|
||||
TEST_IGNORE()
|
||||
END_TEST_METHOD_ATTRIBUTE()
|
||||
TEST_METHOD(WebSocketBlob) {
|
||||
auto result = m_runner.RunTest("IntegrationTests/WebSocketBlobTest", "WebSocketBlobTest");
|
||||
|
|
|
@ -280,7 +280,44 @@ TEST_CLASS (WebSocketIntegrationTest)
|
|||
END_TEST_METHOD_ATTRIBUTE()
|
||||
TEST_METHOD(SendReceiveSsl)
|
||||
{
|
||||
SendReceiveCloseBase(/*isSecure*/ true);
|
||||
auto ws = IWebSocketResource::Make();
|
||||
promise<size_t> sentSizePromise;
|
||||
ws->SetOnSend([&sentSizePromise](size_t size)
|
||||
{
|
||||
sentSizePromise.set_value(size);
|
||||
});
|
||||
promise<string> receivedPromise;
|
||||
ws->SetOnMessage([&receivedPromise](size_t size, const string& message, bool isBinary)
|
||||
{
|
||||
receivedPromise.set_value(message);
|
||||
});
|
||||
string clientError{};
|
||||
ws->SetOnError([&clientError, &sentSizePromise, &receivedPromise](Error err)
|
||||
{
|
||||
clientError = err.Message;
|
||||
sentSizePromise.set_value(0);
|
||||
receivedPromise.set_value("");
|
||||
});
|
||||
|
||||
string sent = "prefix";
|
||||
auto expectedSize = sent.size();
|
||||
ws->Connect("wss://localhost:5543/rnw/websockets/echosuffix");
|
||||
ws->Send(std::move(sent));
|
||||
|
||||
// Block until response is received. Fail in case of a remote endpoint failure.
|
||||
auto sentSizeFuture = sentSizePromise.get_future();
|
||||
sentSizeFuture.wait();
|
||||
auto sentSize = sentSizeFuture.get();
|
||||
auto receivedFuture = receivedPromise.get_future();
|
||||
receivedFuture.wait();
|
||||
string received = receivedFuture.get();
|
||||
Assert::AreEqual({}, clientError);
|
||||
|
||||
ws->Close(CloseCode::Normal, "Closing after reading");
|
||||
|
||||
Assert::AreEqual({}, clientError);
|
||||
Assert::AreEqual(expectedSize, sentSize);
|
||||
Assert::AreEqual({"prefix_response"}, received);
|
||||
}
|
||||
|
||||
BEGIN_TEST_METHOD_ATTRIBUTE(SendBinary)
|
||||
|
|
|
@ -59,6 +59,9 @@ TEST_CLASS (WebSocketResourcePerformanceTest) {
|
|||
/// several times, then measure the amount of allocated threads. Important. This
|
||||
/// test must be run in isolation (no other tests running concurrently).
|
||||
///
|
||||
BEGIN_TEST_METHOD_ATTRIBUTE(ProcessThreadsPerResource)
|
||||
TEST_IGNORE()
|
||||
END_TEST_METHOD_ATTRIBUTE()
|
||||
TEST_METHOD(ProcessThreadsPerResource) {
|
||||
// About 3 seconds total running time.
|
||||
// 6, if we increase this value to 100.
|
||||
|
@ -71,11 +74,6 @@ TEST_CLASS (WebSocketResourcePerformanceTest) {
|
|||
bool errorFound = false;
|
||||
string errorMessage;
|
||||
|
||||
auto server = std::make_shared<Test::WebSocketServer>(s_port);
|
||||
server->SetMessageFactory([](string &&message) { return message + "_response"; });
|
||||
// TODO: #4493 - Allow TestWebSocketServer to handle multiple incoming messages.
|
||||
// server->Start();
|
||||
|
||||
// WebSocket resources scope.
|
||||
{
|
||||
vector<shared_ptr<IWebSocketResource>> resources;
|
||||
|
@ -112,7 +110,7 @@ TEST_CLASS (WebSocketResourcePerformanceTest) {
|
|||
errorFound = true;
|
||||
errorMessage = error.Message;
|
||||
});
|
||||
ws->Connect("ws://localhost:" + std::to_string(s_port));
|
||||
ws->Connect("ws://localhost:5555");
|
||||
|
||||
resources.push_back(std::move(ws));
|
||||
} // Create and store WS resources.
|
||||
|
@ -127,8 +125,6 @@ TEST_CLASS (WebSocketResourcePerformanceTest) {
|
|||
ws->Close();
|
||||
}
|
||||
}
|
||||
// TODO: #4493 - Allow TestWebSocketServer to handle multiple incoming messages.
|
||||
// server->Stop();
|
||||
|
||||
int32_t finalThreadCount = threadCount.load();
|
||||
int64_t threadsPerResource = (finalThreadCount - startThreadCount) / resourceTotal;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
[MSBuild]::NormalizeDirectory on relative paths since cwd is not always correct. This logic should prefer to operate
|
||||
on full paths and avoid extra normalization.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<PropertyGroup Label="NodeNativeDeps" Condition="'$(IgnoreNodeNativeDeps)' != 'true'">
|
||||
<ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$(MSBuildThisFileDirectory)</ReactNativeWindowsDir>
|
||||
|
||||
<ReactNativeDir Condition="'$(ReactNativeDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native\package.json'))\node_modules\react-native\</ReactNativeDir>
|
||||
|
@ -80,4 +80,4 @@
|
|||
<RestoreUseStaticGraphEvaluation Condition="'$(BuildingInsideVisualStudio)' == 'true' AND $([MSBuild]::VersionLessThan('$(MSBuildVersion)', '17.6')) AND '$(DisableRestoreUseStaticGraphEvaluation)' != 'true'">true</RestoreUseStaticGraphEvaluation>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
|
@ -105,6 +105,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx",
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon.UnitTests", "ReactCommon.UnitTests\ReactCommon.UnitTests.vcxproj", "{B0941079-7441-4A69-868C-FE5EC62C2E9E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ReactNative.Test.Website", "TestWebsite\Microsoft.ReactNative.Test.Website.csproj", "{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
|
@ -285,6 +287,18 @@ Global
|
|||
{B0941079-7441-4A69-868C-FE5EC62C2E9E}.Release|x64.ActiveCfg = Release|x64
|
||||
{B0941079-7441-4A69-868C-FE5EC62C2E9E}.Release|x64.Build.0 = Release|x64
|
||||
{B0941079-7441-4A69-868C-FE5EC62C2E9E}.Release|x86.ActiveCfg = Release|x64
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C5B2EB41-849E-41F7-BC70-DEFF26F09E5E}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -30,16 +30,15 @@ param (
|
|||
|
||||
[switch] $NoRun,
|
||||
|
||||
[switch] $UseNodeWsServer,
|
||||
|
||||
[switch] $List,
|
||||
|
||||
[System.IO.FileInfo] $VsTest = "${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise\" +
|
||||
"Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe",
|
||||
[System.IO.FileInfo] $VsTest =
|
||||
"$(& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath)\" +
|
||||
"Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe",
|
||||
|
||||
[System.IO.DirectoryInfo] $ReactNativeLocation = "$($PSScriptRoot | Split-Path)",
|
||||
|
||||
[System.IO.FileInfo] $NodePath = (Get-Command node.exe).Definition,
|
||||
[System.IO.FileInfo] $DotNetPath = (Get-Command dotnet.exe).Definition,
|
||||
|
||||
[System.IO.FileInfo] $NpmPath = (Get-Command npm.cmd).Definition
|
||||
)
|
||||
|
@ -59,9 +58,7 @@ if ($List) {
|
|||
# Ensure test services are online.
|
||||
if (! $NoServers) {
|
||||
$packager = Find-Packager
|
||||
if ($UseNodeWsServer.IsPresent) {
|
||||
$wsServer = Find-WebSocketServer
|
||||
}
|
||||
$webSite = Find-TestWebsiteServer
|
||||
$notFound = $false
|
||||
|
||||
if (!$packager) {
|
||||
|
@ -72,17 +69,26 @@ if (! $NoServers) {
|
|||
Write-Host 'Found Packager.'
|
||||
}
|
||||
|
||||
if (!$wsServer -and $UseNodeWsServer.IsPresent) {
|
||||
Write-Warning 'WebSocket server not found. Attempting to start...'
|
||||
Start-WebSocketServer -ReactNativeLocation $ReactNativeLocation -NodePath $NodePath
|
||||
if (!$webSite) {
|
||||
Start-Process `
|
||||
-FilePath $DotNetPath `
|
||||
-PassThru `
|
||||
-ArgumentList `
|
||||
run,
|
||||
--project,
|
||||
$ReactNativeLocation\TestWebSite\Microsoft.ReactNative.Test.Website.csproj
|
||||
|
||||
$notFound = $true
|
||||
} elseif ($UseNodeWsServer.IsPresent) {
|
||||
Write-Host 'Found WebSocket server.'
|
||||
} else {
|
||||
Write-Host 'Found Test Website Server'
|
||||
}
|
||||
|
||||
if ($Preload -and $notFound) {
|
||||
Start-Sleep -Seconds $Delay
|
||||
|
||||
# Ensure test website responds to default HTTP GET request.
|
||||
Invoke-WebRequest -Uri 'http://localhost:5555'
|
||||
|
||||
# Preload the RNTesterApp integration bundle for better performance in integration tests.
|
||||
Invoke-WebRequest -UseBasicParsing -Uri "http://localhost:8081/IntegrationTests/IntegrationTestsApp.bundle?platform=windows&dev=true" | Out-Null
|
||||
}
|
||||
|
@ -92,8 +98,9 @@ if ($NoRun) {
|
|||
Exit
|
||||
}
|
||||
|
||||
$filter = ''
|
||||
if ($Include.Count) {
|
||||
$filter = "(FullyQualifiedName~" + ($Include -join ')&(FullyQualifiedName~') + ")"
|
||||
$filter += "(FullyQualifiedName~" + ($Include -join ')&(FullyQualifiedName~') + ")"
|
||||
}
|
||||
|
||||
if ($Exclude.Count) {
|
||||
|
@ -101,4 +108,8 @@ if ($Exclude.Count) {
|
|||
}
|
||||
|
||||
# Run Integration Test assemblies.
|
||||
& $VsTest $Assemblies --InIsolation --Platform:$Platform ('', "--TestCaseFilter:$filter")[$filter.Length -gt 0]
|
||||
if ($filter.Length -gt 0) {
|
||||
& $VsTest $Assemblies --InIsolation --Platform:$Platform "--TestCaseFilter:$filter"
|
||||
} else {
|
||||
& $VsTest $Assemblies --InIsolation --Platform:$Platform
|
||||
}
|
||||
|
|
|
@ -61,24 +61,6 @@ function Start-Packager {
|
|||
return Start-Npm -WorkingDirectory $ReactNativeLocation -NoNewWindow:$NoNewWindow -NpmPath $NpmPath
|
||||
}
|
||||
|
||||
function Start-WebSocketServer {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateScript({Test-Path $_})]
|
||||
[string] $ReactNativeLocation,
|
||||
|
||||
[switch] $NoNewWindow,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateScript({Test-Path $_})]
|
||||
[string] $NodePath
|
||||
)
|
||||
|
||||
return Start-Node -ScriptPath $ReactNativeLocation\IntegrationTests\websocket_integration_test_server.js `
|
||||
-NoNewWindow:$NoNewWindow `
|
||||
-NodePath $NodePath
|
||||
}
|
||||
|
||||
function Find-Packager {
|
||||
try {
|
||||
return Get-Process -Id (Get-NetTCPConnection -ErrorAction Ignore -LocalPort 8081).OwningProcess
|
||||
|
@ -88,23 +70,15 @@ function Find-Packager {
|
|||
}
|
||||
}
|
||||
|
||||
function Find-WebSocketServer {
|
||||
function Find-TestWebsiteServer {
|
||||
try {
|
||||
return Get-Process -Id (Get-NetTCPConnection -ErrorAction Ignore -LocalPort 5555).OwningProcess
|
||||
return Get-Process -id (Get-NetTCPConnection -ErrorAction Ignore -LocalPort 5555).OwningProcess
|
||||
}
|
||||
catch {
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-WebSocketServer {
|
||||
$proc = Find-WebSocketServer
|
||||
|
||||
if ($proc) {
|
||||
Stop-Process $proc
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-Packager {
|
||||
$proc = Find-Packager
|
||||
|
||||
|
|
|
@ -9,9 +9,7 @@ param (
|
|||
|
||||
[switch] $Preload,
|
||||
|
||||
[int] $SleepSeconds = 10,
|
||||
|
||||
[switch] $UseNodeWsServer
|
||||
[int] $SleepSeconds = 10
|
||||
)
|
||||
|
||||
Write-Host "Starting packager"
|
||||
|
@ -26,17 +24,6 @@ Start-Process npm -PassThru `
|
|||
|
||||
Write-Host 'Started packager'
|
||||
|
||||
if ($UseNodeWsServer.IsPresent) {
|
||||
Write-Host 'Starting WebSocket server'
|
||||
|
||||
Start-Process -PassThru `
|
||||
-FilePath (Get-Command node.exe).Definition `
|
||||
-ArgumentList "${SourcesDirectory}\IntegrationTests\websocket_integration_test_server.js" `
|
||||
-OutVariable wsProc
|
||||
|
||||
Write-Host 'Started WebSocket server'
|
||||
}
|
||||
|
||||
if ($Preload) {
|
||||
Write-Host 'Preloading bundles'
|
||||
|
||||
|
@ -50,10 +37,3 @@ if ($Preload) {
|
|||
|
||||
# Use the environment variables input below to pass secret variables to this script.
|
||||
Write-Host "##vso[task.setvariable variable=PackagerId;]$($packagerProc.Id)"
|
||||
|
||||
if ($UseNodeWsServer.IsPresent) {
|
||||
Write-Host "##vso[task.setvariable variable=WebSocketServerId;]$($wsProc.Id)"
|
||||
return ($packagerProc, $wsProc)
|
||||
} else {
|
||||
return ($packagerProc)
|
||||
}
|
||||
|
|
|
@ -4,14 +4,9 @@
|
|||
# Stop-TestServers.ps1
|
||||
#
|
||||
param (
|
||||
$WebSocketServerId = $env:WebSocketServerId,
|
||||
$PackagerId = $env:PackagerId
|
||||
)
|
||||
|
||||
Write-Host 'Stopping WebSocket server'
|
||||
Stop-Process -Id $WebSocketServerId
|
||||
Write-Host 'Stopped WebSocket server'
|
||||
|
||||
Write-Host 'Stopping packager'
|
||||
Stop-Process -Id $PackagerId
|
||||
Write-Host 'Stopped packager'
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<IgnoreNodeNativeDeps>true</IgnoreNodeNativeDeps>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- This import will noop when customer code is built. This import is here to help building the bits in the react-native-windows repository. -->
|
||||
<Import Condition="Exists($([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')))" Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,108 @@
|
|||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Facebook.React.Test
|
||||
{
|
||||
public sealed class RNTesterIntegrationTests
|
||||
{
|
||||
static List<WebSocket> wsConnections = new List<WebSocket>();
|
||||
|
||||
public static async Task WebSocketTest(HttpContext context)
|
||||
{
|
||||
var announcement = @"
|
||||
WebSocket integration test server
|
||||
|
||||
This will send each incoming message back, with the string '_response' appended.
|
||||
An incoming message of 'exit' will shut down the server.
|
||||
";
|
||||
await Console.Out.WriteLineAsync(announcement);
|
||||
|
||||
using var ws = await context.WebSockets.AcceptWebSocketAsync();
|
||||
wsConnections.Add(ws);
|
||||
|
||||
if (ws.State == WebSocketState.Open)
|
||||
{
|
||||
var connectMessage = "hello";
|
||||
var bytes = Encoding.UTF8.GetBytes(connectMessage);
|
||||
var segment = new ArraySegment<byte>(bytes);
|
||||
|
||||
await ws.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ws.State == WebSocketState.Open)
|
||||
{
|
||||
async Task<string> receiveMessage(WebSocket socket)
|
||||
{
|
||||
// Read incoming message
|
||||
var inputBytes = new byte[1024];
|
||||
WebSocketReceiveResult result;
|
||||
int total = 0;
|
||||
do
|
||||
{
|
||||
result = await socket.ReceiveAsync(new ArraySegment<byte>(inputBytes), CancellationToken.None);
|
||||
total += result.Count;
|
||||
} while (result != null && !result.EndOfMessage);
|
||||
|
||||
return Encoding.UTF8.GetString(inputBytes, 0, total);
|
||||
};
|
||||
var inputMessage = await receiveMessage(ws);
|
||||
await Console.Out.WriteLineAsync($"Received message: {inputMessage}");
|
||||
|
||||
if (inputMessage == "exit")
|
||||
{
|
||||
await Console.Out.WriteLineAsync("WebSocket integration test server exit");
|
||||
}
|
||||
|
||||
var outputMessage = $"{inputMessage}_response";
|
||||
var outputBytes = Encoding.UTF8.GetBytes(outputMessage);
|
||||
|
||||
await ws.SendAsync(outputBytes, WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
}
|
||||
else if (ws.State == WebSocketState.Closed || ws.State == WebSocketState.Aborted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task WebSocketBinaryTest(HttpContext context)
|
||||
{
|
||||
var ws = await context.WebSockets.AcceptWebSocketAsync();
|
||||
wsConnections.Add(ws);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ws.State == WebSocketState.Open)
|
||||
{
|
||||
async Task<string> receiveMessage(WebSocket socket)
|
||||
{
|
||||
// Read incoming message
|
||||
var inputBytes = new byte[1024];
|
||||
WebSocketReceiveResult result;
|
||||
int total = 0;
|
||||
do
|
||||
{
|
||||
result = await socket.ReceiveAsync(new ArraySegment<byte>(inputBytes), CancellationToken.None);
|
||||
total += result.Count;
|
||||
} while (result != null && !result.EndOfMessage);
|
||||
|
||||
return Encoding.UTF8.GetString(inputBytes, 0, total);
|
||||
};
|
||||
var incomingMessage = await receiveMessage(ws);
|
||||
await Console.Out.WriteLineAsync($"Message received: [{incomingMessage}]");
|
||||
|
||||
var outgoingBytes = new byte[] { 4, 5, 6, 7 };
|
||||
|
||||
await ws.SendAsync(outgoingBytes, WebSocketMessageType.Binary, true, CancellationToken.None);
|
||||
}
|
||||
else if(ws.State == WebSocketState.Closed || ws.State == WebSocketState.Aborted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<IntDir>$(IntDir)$(TargetFramework)\</IntDir>
|
||||
<OutDir>$(OutDir)$(TargetFramework)\</OutDir>
|
||||
<BaseIntermediateOutputPath>$(MSBuildProjectExtensionsPath)</BaseIntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'https' " />
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'http' " />
|
||||
<ItemGroup>
|
||||
<None Remove="Facebook\" />
|
||||
<None Remove="Facebook\React\" />
|
||||
<None Remove="Facebook\React\Test\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Facebook\" />
|
||||
<Folder Include="Facebook\React\" />
|
||||
<Folder Include="Facebook\React\Test\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,17 @@
|
|||
using System.Text;
|
||||
|
||||
namespace Microsoft.Office.Test
|
||||
{
|
||||
public sealed class OfficeJsTests
|
||||
{
|
||||
public static async Task Issue4144(HttpContext context)
|
||||
{
|
||||
var response = context.Response;
|
||||
response.ContentType = "text/plain";
|
||||
response.StatusCode = 200;
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes("Check headers: [Access-Control-Allow-Origin]");
|
||||
await response.Body.WriteAsync(bytes);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.React.Test
|
||||
{
|
||||
public sealed class WebSocketTests
|
||||
{
|
||||
static List<WebSocket> wsConnections = new List<WebSocket>();
|
||||
|
||||
public static async Task EchoSuffix(HttpContext context)
|
||||
{
|
||||
var announcement = @"This will send each incoming message back, with the string '_response' appended.";
|
||||
await Console.Out.WriteLineAsync(announcement);
|
||||
|
||||
using var ws = await context.WebSockets.AcceptWebSocketAsync();
|
||||
wsConnections.Add(ws);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ws.State == WebSocketState.Open)
|
||||
{
|
||||
async Task<string> receiveMessage(WebSocket socket)
|
||||
{
|
||||
// Read incoming message
|
||||
var inputBytes = new byte[1024];
|
||||
WebSocketReceiveResult result;
|
||||
int total = 0;
|
||||
do
|
||||
{
|
||||
result = await socket.ReceiveAsync(new ArraySegment<byte>(inputBytes), CancellationToken.None);
|
||||
total += result.Count;
|
||||
} while (result != null && !result.EndOfMessage);
|
||||
|
||||
return Encoding.UTF8.GetString(inputBytes, 0, total);
|
||||
};
|
||||
var inputMessage = await receiveMessage(ws);
|
||||
await Console.Out.WriteLineAsync($"Received message: {inputMessage}");
|
||||
|
||||
var outputMessage = $"{inputMessage}_response";
|
||||
var outputBytes = Encoding.UTF8.GetBytes(outputMessage);
|
||||
|
||||
await ws.SendAsync(outputBytes, WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
}
|
||||
else if (ws.State == WebSocketState.Closed || ws.State == WebSocketState.Aborted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// CORS middleware
|
||||
//TODO: Subordinate to specific set of tests
|
||||
var originPolicyName = "AllowedOrigins";
|
||||
builder.Services.AddCors(
|
||||
options =>
|
||||
{
|
||||
options.AddPolicy(
|
||||
name: originPolicyName,
|
||||
policy =>
|
||||
{
|
||||
policy
|
||||
.WithOrigins("http://orig.in")
|
||||
.WithMethods("GET")
|
||||
;
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
app.UseWebSockets();
|
||||
app.UseCors();
|
||||
app.UseStaticFiles();
|
||||
|
||||
// See https://github.com/dotnet/aspnetcore/blob/v7.0.15/src/Http/Routing/src/RequestDelegateRouteBuilderExtensions.cs
|
||||
// app.Map("/", () => "Sample HTTP Response");
|
||||
async Task DefaultRequestDelegate(HttpContext context)
|
||||
{
|
||||
var response = context.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
|
||||
var bytes = System.Text.Encoding.UTF8.GetBytes("Sample HTTP Response");
|
||||
await response.Body.WriteAsync(bytes);
|
||||
}
|
||||
|
||||
#region Request Mappings
|
||||
|
||||
app.Map("/", async context =>
|
||||
{
|
||||
if (context.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
// ws://localhost:5555
|
||||
// See react-native/IntegrationTests/websocket_integration_test_server.js
|
||||
// Note, the referred code has been removed in React Native 0.73
|
||||
await Facebook.React.Test.RNTesterIntegrationTests.WebSocketTest(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
await DefaultRequestDelegate(context);
|
||||
}
|
||||
});
|
||||
|
||||
app.Map(
|
||||
"/rnw/rntester/websocketbinarytest",
|
||||
Facebook.React.Test.RNTesterIntegrationTests.WebSocketBinaryTest
|
||||
);
|
||||
|
||||
app.Map(
|
||||
"/rnw/websockets/echosuffix",
|
||||
Microsoft.React.Test.WebSocketTests.EchoSuffix
|
||||
);
|
||||
|
||||
app.MapGet(
|
||||
"/officedev/office-js/issues/4144",
|
||||
Microsoft.Office.Test.OfficeJsTests.Issue4144)
|
||||
.RequireCors(originPolicyName);
|
||||
|
||||
#endregion Request Mappings
|
||||
|
||||
await app.RunAsync();
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:5555",
|
||||
"sslPort": 5543
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:5543;http://localhost:5555",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true
|
||||
},
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5555",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
# Integration Test Website
|
||||
|
||||
This is a generic ASP.NET Core application that provides arbitrary HTTP responses and WebSocket endpoints to validate React Native Windows's functionality.
|
||||
|
||||
It is meant to complement (and partially replace) the in-process C++ test servers used for integration which have very limited functionality and are hard to program against.
|
||||
|
||||
This application enhances web testing via a number of features such as:
|
||||
- Server-side Origin Policy (CORS) enforcement
|
||||
- Static file serving
|
||||
- HTTP authentication and authorization
|
||||
- HTTP sessions
|
||||
- Response caching
|
||||
- Cookie handling
|
||||
|
||||
Deploying this website in Continuous Integration/Delivery environments also removes the dependency on remote web endpoints for end to end scenarios.
|
||||
|
||||
## Usage
|
||||
|
||||
### Developer Workflow
|
||||
|
||||
1. Build React Native Windows.
|
||||
1. Start the Node Packager.
|
||||
```pwsh
|
||||
Set-Location vnext
|
||||
npm run start
|
||||
```
|
||||
1. Trust the .NET-provided development SSL certificate:\
|
||||
This should be a one-time step per .NET version.\
|
||||
See https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl#trust-the-aspnet-core-https-development-certificate-on-windows-and-macos.
|
||||
```cmd
|
||||
dotnet dev-certs https --trust
|
||||
```
|
||||
1. Start this website.
|
||||
```cmd
|
||||
dotnet run --project vnext\TestWebSite
|
||||
```
|
||||
1. Run integration tests.
|
||||
|
||||
### Continuous Integration Workflow
|
||||
The website gets deployed to a web server.\
|
||||
This reduces the process management overhead and increases stability and availability in CI environments.
|
||||
|
||||
The website can also be installed on a development environment.\
|
||||
*Note: This would require to update the website's publish directory with any new changes, but removes the need to manage the additonal process and terminal window.*
|
||||
|
||||
Here are the steps for Micrososoft's IIS:
|
||||
1. Publish the website.
|
||||
```pwsh
|
||||
Set-Location vnext\TestWebSite
|
||||
dotnet publish
|
||||
```
|
||||
1. Install IIS.
|
||||
1. Install the .NET 7 SDK.\
|
||||
https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/sdk-7.0.407-windows-x64-installer
|
||||
1. Install the ASP.NET Core Hosting Bundle.\
|
||||
https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-aspnetcore-8.0.3-windows-hosting-bundle-installer
|
||||
1. Create or update a website that binds ports `5555` to `http` and `5543` to `https`.\
|
||||
*For `https`, any trusted SSL certificate will work. There is no need to install `localhost.cicert`.*
|
||||
1. Set the location to the publish directory (i.e. `C:\repo\react-native-windows\vnext\target\x64\Debug\Microsoft.ReactNative.Test.Website\Publish`)
|
||||
|
||||
## Technical Information
|
||||
|
||||
- The website is meant to run on ports `5555` (`http`, `ws`) and `5543` (`https`, `wss`).\
|
||||
This can be modified via command line arguments or in [Properties/launchSettings.json](Properties/launchSettings.json).
|
||||
- For encryption, self-signed PKCS12 certificate `localhost.cicert` is used (DevOps only).
|
||||
The certificate is set to expire on January 1st, 2030.\
|
||||
After that date, new one must be generated.
|
||||
|
||||
### Replacing the DevOps SSL certificate
|
||||
|
||||
1. Generate a new self-signed x509 web certificate.\
|
||||
Use common name `CN=localhost`.
|
||||
1. Replace the `localhost.cicert` with the new certificate.
|
||||
1. Update the password in the Continuous Integration system.\
|
||||
*The certificate password is mapped to DevOps variable `$(TestWebsiteCertPassword)`.*
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 25.0.1706.8
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Test.Website", "..\Microsoft.ReactNative.Test.Website.csproj", "{E2DD641B-CA1C-4161-A00A-ADAACF4DF1AE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E2DD641B-CA1C-4161-A00A-ADAACF4DF1AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E2DD641B-CA1C-4161-A00A-ADAACF4DF1AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E2DD641B-CA1C-4161-A00A-ADAACF4DF1AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E2DD641B-CA1C-4161-A00A-ADAACF4DF1AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {911C0A3A-86DF-41D8-8855-8459B78AB7E3}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net7.0": {}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.6 KiB |
|
@ -0,0 +1 @@
|
|||
Sample Static Text File
|
|
@ -23,124 +23,40 @@ class BlobTest extends React.Component<{...}, State> {
|
|||
state: State = {
|
||||
statusCode: 0,
|
||||
xhr: new XMLHttpRequest(),
|
||||
// https://www.facebook.com/favicon.ico
|
||||
// http://localhost:5555/static/react.png
|
||||
// cspell:disable
|
||||
expected:
|
||||
'data:application/octet-stream;base64,' +
|
||||
'AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAA' +
|
||||
'AAABACAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOFl' +
|
||||
'BiviZgKP4WYB1f//////////4WUA1eJmAI/hawYrAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAA/4ArBuNpA5TkawP942kC/+NpAv///////////+NpAv/jaQL/5GoD/eNp' +
|
||||
'A5T/gCsGAAAAAAAAAAAAAAAA/4ArBuVvBL3lbgT/5W4E/+VuBP/lbgT/////////' +
|
||||
'///lbgT/5W4E/+VuBP/lbgT/5W8Evf+AKwYAAAAAAAAAAOlzBZTncwX/53MF/+dz' +
|
||||
'Bf/ncwX/53MF////////////53MF/+dzBf/ncwb/53MF/+dzBv/pcweUAAAAAO19' +
|
||||
'DCvpeAf96HcH/+l4B//odwf/6XgH/+l4B////////////+h3B//odwf/6XgH/+h3' +
|
||||
'B//peAf/6nkH/e19DCvrfQmP630J/+t9Cf/rfAn/630J/+t8Cf/rfAn/////////' +
|
||||
'///rfQn/630J/+p8CP/rfQn/6nwI/+p8CP/rfQuP7YEL1e2BCv/tgQr/7IEK/+2B' +
|
||||
'Cv/////////////////////////////////uiRj/7IEK/+2CCv/tggr/7YIM1e6G' +
|
||||
'DfPvhgz/74YM/++HDP/vhgz/////////////////////////////////8Zw4/++G' +
|
||||
'DP/uhgz/7oYM/+6GDPPwiw7z8IsN//CLDf/wiw3/8IsN//CLDf/wiw3/////////' +
|
||||
'///wig3/8IoN//CLDf/wig3/8IsN//CLDf/xjA/z85EQ1fOQD//zkA//85AP//OQ' +
|
||||
'D//zkA//85AP////////////8o8P//KPD//ykA//8o8P//KQD//ykA//85EQ1fSU' +
|
||||
'EI/1lRH/9ZUR//SUEP/1lRH/9JQQ//SUEP/+9uz///////jDev/0mRz/9ZUR//SV' +
|
||||
'Ef/1lRH/9ZUR//SUEI/5mhgr95kS/faZEv/2mRL/9pkS//aZEv/2mRL//Nqo////' +
|
||||
'//////////////rLhv/3mhL/9pkS//eZEv35mhgrAAAAAPifFZT4nhT/+Z8U//ie' +
|
||||
'FP/5nxT/+Z8U//ikI//83a3//vjw//78+f/7yX3/+J4T//ieFP/4nxWUAAAAAAAA' +
|
||||
'AAD/qisG+6MWvfqjFf/6oxX/+qMV//qjFf/6oxX/+qMV//qjFf/6oxX/+qIV//qj' +
|
||||
'Ff/7oxa9/6orBgAAAAAAAAAAAAAAAP+qKwb9qRiU/agW/fyoF//8qBf//agX//yo' +
|
||||
'F//9qBf//agX//2oF/39qRiU/6orBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+y' +
|
||||
'Hiv/rRmP/6wZ1f+tGPP/rBjz/64Z1f+vGY//sh4rAAAAAAAAAAAAAAAAAAAAAPAP' +
|
||||
'AADAAwAAgAEAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAB' +
|
||||
'AACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+A' +
|
||||
'AAbiZQRH4GMAlf//////////////////////////4GQAv+BjAJXiZQBH/4AABgAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOpqCxjiZgKW4WYB8eJmAf/hZQH/////////' +
|
||||
'///////////////////hZgH/4mYB/+FmAf/iZwHx4mYClupqCxgAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9t' +
|
||||
'JAfkagSC42kC9ONoAv/jaAL/4mgC/+NoAv///////////////////////////+Jo' +
|
||||
'Af/iaAL/4mgB/+JoAv/iaAL/42kC9ORqBIL/bSQHAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADqagsY5GoEx+NqA//jagP/42oD/+Nq' +
|
||||
'A//kawP/42oD////////////////////////////42oD/+RrA//jagP/5GsD/+Rr' +
|
||||
'A//kawP/5GsD/+RsBMfqdQsYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAA6HEGLeVuBOPlbQT/5GwD/+VtBP/kbAP/5GwD/+VtBP/kbAP/////////' +
|
||||
'///////////////////kbAP/5G0D/+RsA//kbQP/5G0D/+RtA//kbQP/5G0D/+Ru' +
|
||||
'A+PocQYtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOp1CxjmcAbj5W8E/+Vv' +
|
||||
'BP/lbwT/5W8E/+VvBP/lbwT/5W8E/+VvBP///////////////////////////+Vv' +
|
||||
'BP/mcAX/5W8E/+ZwBf/mcAX/5W8E/+ZwBf/lbwT/5W8E/+ZwBuPqdQsYAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAD/kiQH53IFx+ZyBf/mcQX/5nEF/+ZxBf/mcQX/5nEF/+Zx' +
|
||||
'Bf/ncgX/5nEF////////////////////////////53IG/+ZxBf/ncgb/5nEF/+Zx' +
|
||||
'Bf/mcgX/5nEF/+ZyBf/mcgX/5nEF/+dyBcf/kiQHAAAAAAAAAAAAAAAAAAAAAOd2' +
|
||||
'CILodAb/53QG/+h0Bv/odAb/6HQG/+h0Bv/odAb/6HQG/+d0Bv/odAb/////////' +
|
||||
'///////////////////ndAX/53QG/+d0Bf/ndAb/53QG/+h1Bv/ndAb/6HUG/+h1' +
|
||||
'Bv/ndAX/6HUG/+d2BoIAAAAAAAAAAAAAAADqgAsY6HYG9Oh2B//odgb/6HYH/+h2' +
|
||||
'B//odgb/6HYH/+h2Bv/odgb/6HYH/+h2Bv///////////////////////////+l3' +
|
||||
'B//odgb/6XcH/+h2Bv/odgb/6HYH/+h2Bv/odgf/6HYH/+h2Bv/odgf/6HYG9OqA' +
|
||||
'CxgAAAAAAAAAAOt6CZbpeQj/6nkI/+l5CP/qeQj/6nkI/+l5B//qeQj/6XkH/+l5' +
|
||||
'B//peQf/6XkH////////////////////////////6XkI/+l5B//peQj/6XkH/+l5' +
|
||||
'B//peQj/6XkH/+l5CP/peQj/6XkH/+l5CP/peQf/63oJlgAAAAD/gCsG7H0K8et8' +
|
||||
'Cf/qewj/63wJ/+p7CP/qewj/6nsI/+p7CP/qewj/6nsI/+t8Cf/qewj/////////' +
|
||||
'///////////////////qewj/6nwJ/+p7CP/qfAn/6nwJ/+p7CP/qfAn/6nsI/+p7' +
|
||||
'CP/rfAn/6nsI/+t8Cf/sfQrx/4ArBu2BC0frfQn/630J/+t+Cf/rfQn/634J/+t+' +
|
||||
'Cf/rfgn/634J////////////////////////////////////////////////////' +
|
||||
'///////////////////zs27/634J/+x+Cf/rfgn/634J/+t+Cf/rfgn/634J/+t+' +
|
||||
'Cf/tgQtH7IAKleyACv/sgAr/7IAK/+yACv/sgAr/7IAK/+yACv/sgAr/////////' +
|
||||
'//////////////////////////////////////////////////////////////XC' +
|
||||
'iv/sgAr/7IAK/+yACv/sgAr/7IAJ/+yACv/sgAn/7IAJ/+yACpXugwu/7YML/+2D' +
|
||||
'C//tggr/7YML/+2CCv/tggr/7YIK/+2CCv//////////////////////////////' +
|
||||
'////////////////////////////////////////+NKn/+2DC//tggr/7YML/+2D' +
|
||||
'C//tgwv/7YML/+2DC//tgwv/7oMLv++GDNnuhQv/7oUL/+6FC//uhQv/7oUL/+6F' +
|
||||
'C//vhQz/7oUL////////////////////////////////////////////////////' +
|
||||
'///////////////////64cT/7oUL/+6FC//uhQv/7oUL/+6EC//uhQv/7oQL/+6E' +
|
||||
'C//vhgzZ74gO8++IDP/viAz/74cM/++IDP/vhwz/74cM/++HDP/vhwz/////////' +
|
||||
'//////////////////////////////////////////////////////////////3w' +
|
||||
'4f/viA3/74cM/++IDf/viA3/74cM/++IDf/vhwz/74cM/++HDfPwiw7z8IoN//CK' +
|
||||
'Df/wig3/8IoN//CKDf/wig3/8IkN//CKDf/wiQ3/8IkN//CKDf/wiQ3/////////' +
|
||||
'///////////////////wiQ3/8IoN//CJDf/wig3/8IoN//CJDf/wig3/8IkN//CJ' +
|
||||
'Df/wiQ3/8IkN//CJDf/wiQ3/8IsO8/KNDtnxjA7/8YwO//GMDf/xjA7/8YwN//GM' +
|
||||
'Df/xjA3/8YwN//GMDf/xjA3/8YwO//GMDf////////////////////////////GM' +
|
||||
'Dv/xjA7/8YwO//GMDv/xjA7/8YwO//GMDv/xjA7/8YwO//GMDv/xjA7/8YwO//GM' +
|
||||
'Dv/yjQ7Z8o8Pv/KPD//yjw//8o8P//KPD//yjw//8o8P//KPD//yjw//8o8P//KP' +
|
||||
'D//yjg7/8o8P////////////////////////////8Y4O//KODv/xjg7/8o4O//KO' +
|
||||
'Dv/yjg7/8o4O//KODv/yjg7/8o8P//KODv/yjw//8o8P//OQEL/zkQ+V85EP//OR' +
|
||||
'D//zkQ//85EP//ORD//zkQ//85EP//ORD//zkQ//85EP//OREP/zkQ///vr0////' +
|
||||
'///////////////////0myb/85EQ//ORD//zkRD/85EQ//ORD//zkRD/85EP//OR' +
|
||||
'D//zkQ//85EP//ORD//zkQ//85EPlfSXEkf0kxD/9JMQ//SUEP/0kxD/9JQQ//SU' +
|
||||
'EP/zkxD/9JQQ//OTEP/zkxD/9JQQ//OTEP/86tD///////////////////////rV' +
|
||||
'ov/1nSb/85MQ//STEP/0kxD/9JMQ//STEP/0kxD/9JMQ//SUEP/0kxD/9JQQ//SU' +
|
||||
'EP/0kxJH/6orBvWWEvH1lhH/9ZYR//WWEf/1lhH/9ZYR//WWEf/1lhH/9ZYR//WW' +
|
||||
'Ef/1lhH/9ZYR//vZq///////////////////////////////////////////////' +
|
||||
'///1lhH/9ZYR//WWEf/1lhH/9ZYR//WWEf/1lhH/9ZYS8f+qKwYAAAAA95kTlvaY' +
|
||||
'Ev/2mBH/9pgS//aYEf/2mBH/9ZgR//aYEf/1mBH/9ZgR//aYEv/1mBH/+LFN////' +
|
||||
'//////////////////////////////////////////////aYEv/1mBH/9pgS//aY' +
|
||||
'Ev/1mBH/9pgS//WYEf/3mRGWAAAAAAAAAAD/nxUY+JwU9PebE//3mxP/95sT//eb' +
|
||||
'E//3mxP/95sT//ebE//3mxP/95oS//ebE//3mhL//OK7////////////////////' +
|
||||
'////////////////////////95sT//ebE//3mxP/95sT//aaEv/3mxP/95sT9P+f' +
|
||||
'FRgAAAAAAAAAAAAAAAD5nxSC+J0T//idE//4nRP/+J0T//ecE//4nRP/95wT//ec' +
|
||||
'E//4nRP/95wT//idE//4pSf//efF////////////////////////////////////' +
|
||||
'///4nRP/950T//idE//4nRP/+J0T//idE//5nxSCAAAAAAAAAAAAAAAAAAAAAP+2' +
|
||||
'JAf6oBXH+aAU//mgFP/5oBT/+J8U//mgFP/4nxT/+J8U//mfFP/4nxT/+Z8U//mf' +
|
||||
'FP/5oRf/+86H//7w2v/+/Pj//v36//758f/+8+P//evQ//mgFP/5nxT/+aAU//mg' +
|
||||
'FP/4nxT/+qAVx/+2JAcAAAAAAAAAAAAAAAAAAAAAAAAAAP+qFRj7oxXj+aEU//mh' +
|
||||
'FP/6ohX/+aEU//qiFf/6ohX/+qIV//qiFf/6ohX/+qIV//mhFP/6ohX/+aEU//mh' +
|
||||
'FP/6ohX/+aEU//qiFf/6ohX/+aEU//qiFf/5oRT/+aEU//ujFeP/qhUYAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+mFi78pBXj+6QV//ukFv/7pBX/+6QW//uk' +
|
||||
'Fv/6pBX/+6QW//qkFf/6pBX/+6QW//qkFf/7pBb/+6QW//ulFv/7pBb/+6UW//ul' +
|
||||
'Fv/7pBX/+6UW//ukFf/8pBXj/6QXLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAP+qIBj8qBfH/KcW//ynF//8pxb//KcW//ynFv/8pxb//KcW//yn' +
|
||||
'Fv/7phb//KcW//umFv/7phb/+6YW//umFv/7phb/+6YW//ynFv/7phb//KgXx/+q' +
|
||||
'IBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+2' +
|
||||
'JAf9qxiC/akY9PypF//8qRf//KgX//ypF//8qBf//KgX//2pF//8qBf//akX//2p' +
|
||||
'F//9qRf//akX//2pF//9qRf//qkY9P2rGIL/tiQHAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/tSAY/60alv+s' +
|
||||
'GPH+rBj//qwY//6sGP/+rBj//asY//6sGP/9qxj//asY//2rF//9qxj//qsX8f2s' +
|
||||
'GJb/tSAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9UrBv+wGUf/rxqV/68Zv/+v' +
|
||||
'Gtn/rhnz/64Z8/+vGtn/rxm//68alf+wGUf/1SsGAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/AA///AAD//AAAP/gAAB/wAAAP4AAAB8AA' +
|
||||
'AAPAAAADgAAAAYAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAACAAAABgAAAAcAAAAPAAAAD4AAAB/AAAA/4AAAf/AAAP/8A' +
|
||||
'AP//wAP/',
|
||||
'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' +
|
||||
'uP2D2H8BsGL5W7blULYAAAAASUVORK5CYII=',
|
||||
// cspell:enable
|
||||
};
|
||||
|
||||
|
@ -150,7 +66,7 @@ class BlobTest extends React.Component<{...}, State> {
|
|||
statusCode: this.state.xhr.status,
|
||||
});
|
||||
};
|
||||
this.state.xhr.open('GET', 'https://www.facebook.com/favicon.ico');
|
||||
this.state.xhr.open('GET', 'http://localhost:5555/static/react.png');
|
||||
this.state.xhr.setRequestHeader('Accept-Encoding', 'utf-8');
|
||||
this.state.xhr.responseType = 'blob';
|
||||
this.state.xhr.send();
|
||||
|
|
|
@ -16,7 +16,7 @@ const {AppRegistry, View} = ReactNative;
|
|||
const {TestModule} = ReactNative.NativeModules;
|
||||
|
||||
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
||||
const DEFAULT_WS_URL = 'ws://localhost:5557/';
|
||||
const DEFAULT_WS_URL = 'ws://localhost:5555/rnw/rntester/websocketbinarytest';
|
||||
|
||||
const WS_EVENTS = ['close', 'error', 'message', 'open'];
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче