From 5be7d30231492d507c7074224f85b6c8b6cbc1a6 Mon Sep 17 00:00:00 2001
From: Nate McMaster <nate.mcmaster@microsoft.com>
Date: Wed, 13 Feb 2019 20:47:04 -0800
Subject: [PATCH] Replace npm commands with yarn

---
 NuGet.config                                    |  1 +
 build.ps1                                       |  2 ++
 build/tasks/RepoTasks.csproj                    |  1 +
 eng/targets/Npm.Common.targets                  | 17 ++++++++++-------
 global.json                                     |  2 +-
 ...oft.AspNetCore.Components.Browser.JS.npmproj |  4 ++--
 src/Components/Browser.JS/src/package.json      |  1 +
 ...rosoft.AspNetCore.Components.E2ETests.csproj |  9 ++++++---
 src/Components/test/E2ETest/package.json        |  1 +
 .../CORS.FunctionalTests.npmproj                |  2 +-
 .../CORS/test/FunctionalTests/package.json      |  1 +
 .../Microsoft.AspNetCore.NodeServices.csproj    | 11 +++++++++--
 src/Middleware/NodeServices/src/package.json    |  1 +
 .../src/Microsoft.AspNetCore.SpaServices.csproj | 11 +++++++++--
 src/Middleware/SpaServices/src/package.json     |  1 +
 .../SignalR.Npm.FunctionalTests.npmproj         | 15 ++++++---------
 .../clients/ts/FunctionalTests/package.json     |  4 ++--
 .../ts/signalr-protocol-msgpack/README.md       |  4 ++++
 src/SignalR/clients/ts/signalr/README.md        |  4 ++++
 src/SignalR/clients/ts/signalr/package.json     | 10 +++++-----
 src/SignalR/docs/JSFunctionalTests.md           |  2 +-
 21 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/NuGet.config b/NuGet.config
index 1b75d58a6a0..f56f587302a 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -9,5 +9,6 @@
     -->
     <add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
     <add key="myget.org aspnetcore-tools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json" />
+    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
   </packageSources>
 </configuration>
diff --git a/build.ps1 b/build.ps1
index 6e5a86f93c6..86fe4a6c5fe 100644
--- a/build.ps1
+++ b/build.ps1
@@ -306,6 +306,7 @@ $MSBuildArguments += "/p:TargetOsName=win"
 Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
 
 try {
+    $env:KOREBUILD_KEEPGLOBALJSON = 1
     Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $PSScriptRoot -ConfigFile $ConfigFile -CI:$CI
     if ($ForceCoreMsbuild) {
         $global:KoreBuildSettings.MSBuildType = 'core'
@@ -315,4 +316,5 @@ try {
 finally {
     Remove-Module 'KoreBuild' -ErrorAction Ignore
     Remove-Item env:DOTNET_HOME
+    Remove-Item env:KOREBUILD_KEEPGLOBALJSON
 }
diff --git a/build/tasks/RepoTasks.csproj b/build/tasks/RepoTasks.csproj
index a6836228db3..8615952bb71 100644
--- a/build/tasks/RepoTasks.csproj
+++ b/build/tasks/RepoTasks.csproj
@@ -14,6 +14,7 @@
     <PackageReference Remove="Internal.AspNetCore.Sdk" />
     <PackageReference Include="NuGet.Build.Tasks" Version="4.9.3" />
     <PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
+    <PackageReference Include="Yarn.MSBuild" Version="1.13.0" />
   </ItemGroup>
 
   <ItemGroup Condition="'$(BuildInstallers)' == 'true' AND '$(TargetOsName)' == 'win'">
diff --git a/eng/targets/Npm.Common.targets b/eng/targets/Npm.Common.targets
index 79f975532f1..4138c089333 100644
--- a/eng/targets/Npm.Common.targets
+++ b/eng/targets/Npm.Common.targets
@@ -1,11 +1,15 @@
 <Project DefaultTargets="Build" InitialTargets="_CheckForInvalidConfiguration">
 
+  <!-- Version of this SDK is set in global.json -->
+  <Sdk Name="Yarn.MSBuild" />
+
   <PropertyGroup>
     <NormalizedPackageId>$(PackageId.Replace('@','').Replace('/','-'))</NormalizedPackageId>
     <PackageFileName>$(NormalizedPackageId)-$(PackageVersion).tgz</PackageFileName>
     <PackageJson>$(MSBuildProjectDirectory)\package.json</PackageJson>
     <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)' == ''">$(MSBuildProjectDirectory)\obj\</BaseIntermediateOutputPath>
     <IntermediateOutputPath>$([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)'))$(Configuration)\</IntermediateOutputPath>
+    <InstallArgs Condition="'$(RestoreLockedMode)' == 'true'">--frozen-lockfile</InstallArgs>
   </PropertyGroup>
 
   <Target Name="_CheckForInvalidConfiguration">
@@ -13,9 +17,8 @@
   </Target>
 
   <Target Name="Restore">
-    <Message Importance="High" Text="Running npm install on $(MSBuildProjectFullPath)" />
-    <Exec Command="npm ci" Condition="'$(CI)' == 'true'" />
-    <Exec Command="npm install --no-optional" Condition="'$(CI)' != 'true'" />
+    <Message Importance="High" Text="Running yarn install on $(MSBuildProjectFullPath)" />
+    <Yarn Command="install $(InstallArgs)" />
   </Target>
 
   <Target Name="PrepareForBuild">
@@ -28,7 +31,7 @@
   </Target>
 
   <Target Name="Build" DependsOnTargets="PrepareForBuild;ResolveProjectReferences">
-    <Exec Command="npm run build" IgnoreStandardErrorWarningFormat="true" Condition="'$(IsBuildable)' != 'false'" />
+    <Yarn Command="run build" Condition="'$(IsBuildable)' != 'false'" StandardOutputImportance="High" StandardErrorImportance="High" />
   </Target>
 
   <PropertyGroup>
@@ -50,8 +53,8 @@
 
     <Copy SourceFiles="$(PackageJson)" DestinationFiles="$(_BackupPackageJson)" />
 
-    <Exec Command="npm --no-git-tag-version --allow-same-version version $(PackageVersion)" StandardOutputImportance="Normal" StandardErrorImportance="Normal" />
-    <Exec Command="npm pack" StandardOutputImportance="Normal" StandardErrorImportance="Normal" />
+    <Yarn Command="version --no-git-tag-version --new-version $(PackageVersion)" />
+    <Yarn Command="pack --filename $(PackageFileName)" />
 
     <Move SourceFiles="$(_PackageTargetPath)" DestinationFolder="$(PackageOutputPath)" />
     <Message Importance="High" Text="$(MSBuildProjectName) -> $(_PackageTargetPath)" />
@@ -66,7 +69,7 @@
 
   <Target Name="Test" Condition="'$(IsTestProject)' == 'true'">
     <Message Importance="High" Text="Running npm tests for $(MSBuildProjectName)" />
-    <Exec Command="npm $(NpmTestArgs)" IgnoreStandardErrorWarningFormat="true" />
+    <Yarn Command="$(NpmTestArgs)" StandardOutputImportance="High" StandardErrorImportance="High" />
   </Target>
 
 </Project>
diff --git a/global.json b/global.json
index b4fc896ff3e..8a1e66d6bf2 100644
--- a/global.json
+++ b/global.json
@@ -3,6 +3,6 @@
     "version": "3.0.100-preview-010184"
   },
   "msbuild-sdks": {
-    "Internal.AspNetCore.Sdk": "3.0.0-build-20190219.1"
+    "Yarn.MSBuild": "1.13.0"
   }
 }
diff --git a/src/Components/Browser.JS/src/Microsoft.AspNetCore.Components.Browser.JS.npmproj b/src/Components/Browser.JS/src/Microsoft.AspNetCore.Components.Browser.JS.npmproj
index f2215281b4d..93d6097acfe 100644
--- a/src/Components/Browser.JS/src/Microsoft.AspNetCore.Components.Browser.JS.npmproj
+++ b/src/Components/Browser.JS/src/Microsoft.AspNetCore.Components.Browser.JS.npmproj
@@ -17,8 +17,8 @@
           Inputs="@(WebpackInputs)"
           Outputs="dist\components.webassembly.js;dist\components.server.js">
     <RemoveDir Directories="dist" />
-    <Exec Command="npm run build:debug" Condition="'$(Configuration)' == 'Debug'" />
-    <Exec Command="npm run build:production" Condition="'$(Configuration)' != 'Debug'" />
+    <Yarn Command="run build:debug" Condition="'$(Configuration)' == 'Debug'" />
+    <Yarn Command="run build:production" Condition="'$(Configuration)' != 'Debug'" />
   </Target>
 
 </Project>
diff --git a/src/Components/Browser.JS/src/package.json b/src/Components/Browser.JS/src/package.json
index 0a25d7414c9..bbbe8e840a4 100644
--- a/src/Components/Browser.JS/src/package.json
+++ b/src/Components/Browser.JS/src/package.json
@@ -1,5 +1,6 @@
 {
   "name": "microsoft.aspnetcore.components.browser.js",
+  "private": true,
   "version": "0.0.1",
   "description": "",
   "main": "index.js",
diff --git a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj
index 5a886ef6359..c19c9a59fbe 100644
--- a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj
+++ b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj
@@ -18,9 +18,12 @@
     <Compile Include="$(SharedSourceRoot)Process\**\*.cs" LinkBase="Shared" />
   </ItemGroup>
 
-  <Target Name="EnsureNpmRestored" BeforeTargets="Build" Condition="!Exists('node_modules') AND '$(BlazorAllTests)'=='true'">
-    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
-    <Exec Command="npm ci" />
+  <!-- Version of this SDK is set in global.json -->
+  <Sdk Name="Yarn.MSBuild" />
+
+  <Target Name="EnsureNodeJSRestored" BeforeTargets="Build" Condition="'$(BlazorAllTests)'=='true'">
+    <Message Text="Running yarn install on $(MSBuildProjectFile)" Importance="High" />
+    <Yarn Command="install" />
   </Target>
 
   <ItemGroup>
diff --git a/src/Components/test/E2ETest/package.json b/src/Components/test/E2ETest/package.json
index ec0a2b01569..a84e769eb42 100644
--- a/src/Components/test/E2ETest/package.json
+++ b/src/Components/test/E2ETest/package.json
@@ -3,6 +3,7 @@
   "version": "0.0.1",
   "description": "Not a real package. This file exists only to declare dependencies.",
   "main": "index.js",
+  "private": true,
   "scripts": {
     "selenium-standalone": "selenium-standalone",
     "prepare": "selenium-standalone install"
diff --git a/src/Middleware/CORS/test/FunctionalTests/CORS.FunctionalTests.npmproj b/src/Middleware/CORS/test/FunctionalTests/CORS.FunctionalTests.npmproj
index 4581b617fcf..5f99a4e5612 100644
--- a/src/Middleware/CORS/test/FunctionalTests/CORS.FunctionalTests.npmproj
+++ b/src/Middleware/CORS/test/FunctionalTests/CORS.FunctionalTests.npmproj
@@ -14,7 +14,7 @@
 
   <Target Name="InstallPuppeteer" BeforeTargets="Restore">
     <!-- Explicitly install puppeteer. This will install the bundled Chromium as part of restore instead of as part of execution -->
-    <Exec Command="npm install puppeteer" />
+    <Yarn Command="add puppeteer" />
   </Target>
 
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />
diff --git a/src/Middleware/CORS/test/FunctionalTests/package.json b/src/Middleware/CORS/test/FunctionalTests/package.json
index 11fcdca4255..5c179dd000b 100644
--- a/src/Middleware/CORS/test/FunctionalTests/package.json
+++ b/src/Middleware/CORS/test/FunctionalTests/package.json
@@ -1,4 +1,5 @@
 {
+  "private": true,
   "devDependencies": {
     "jest": "^23.6.0",
     "merge": "^1.2.1",
diff --git a/src/Middleware/NodeServices/src/Microsoft.AspNetCore.NodeServices.csproj b/src/Middleware/NodeServices/src/Microsoft.AspNetCore.NodeServices.csproj
index fc460f6afed..27df62162b7 100644
--- a/src/Middleware/NodeServices/src/Microsoft.AspNetCore.NodeServices.csproj
+++ b/src/Middleware/NodeServices/src/Microsoft.AspNetCore.NodeServices.csproj
@@ -17,8 +17,15 @@
     <Reference Include="Newtonsoft.Json" />
   </ItemGroup>
 
-  <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
-    <Exec Command="npm install" />
+  <!-- Version of this SDK is set in global.json -->
+  <Sdk Name="Yarn.MSBuild" />
+
+  <Target Name="YarnInstall">
+    <Message Text="Running yarn install on $(MSBuildProjectFile)" Importance="High" />
+    <Yarn Command="install" />
+  </Target>
+
+  <Target Name="PrepublishScript" DependsOnTargets="YarnInstall" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
     <Exec Command="node node_modules/webpack/bin/webpack.js" />
   </Target>
 
diff --git a/src/Middleware/NodeServices/src/package.json b/src/Middleware/NodeServices/src/package.json
index f234bc6063f..4cf72434107 100644
--- a/src/Middleware/NodeServices/src/package.json
+++ b/src/Middleware/NodeServices/src/package.json
@@ -2,6 +2,7 @@
   "name": "nodeservices",
   "version": "1.0.0",
   "description": "This is not really an NPM package and will not be published. This file exists only to reference compilation tools.",
+  "private": true,
   "main": "index.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
diff --git a/src/Middleware/SpaServices/src/Microsoft.AspNetCore.SpaServices.csproj b/src/Middleware/SpaServices/src/Microsoft.AspNetCore.SpaServices.csproj
index 94ff1d4f92e..3a165db8c53 100644
--- a/src/Middleware/SpaServices/src/Microsoft.AspNetCore.SpaServices.csproj
+++ b/src/Middleware/SpaServices/src/Microsoft.AspNetCore.SpaServices.csproj
@@ -20,8 +20,15 @@
     <Reference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" />
   </ItemGroup>
 
-  <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
-    <Exec Command="npm install" />
+  <!-- Version of this SDK is set in global.json -->
+  <Sdk Name="Yarn.MSBuild" />
+
+  <Target Name="YarnInstall">
+    <Message Text="Running yarn install on $(MSBuildProjectFile)" Importance="High" />
+    <Yarn Command="install" />
+  </Target>
+
+  <Target Name="PrepublishScript" DependsOnTargets="YarnInstall" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
     <Exec Command="node node_modules/webpack/bin/webpack.js" />
   </Target>
 
diff --git a/src/Middleware/SpaServices/src/package.json b/src/Middleware/SpaServices/src/package.json
index 7ee819c7814..9e9cd841acf 100644
--- a/src/Middleware/SpaServices/src/package.json
+++ b/src/Middleware/SpaServices/src/package.json
@@ -2,6 +2,7 @@
   "name": "spaservices",
   "version": "1.0.0",
   "description": "This is not really an NPM package and will not be published. This file exists only to reference compilation tools.",
+  "private": true,
   "main": "index.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
diff --git a/src/SignalR/clients/ts/FunctionalTests/SignalR.Npm.FunctionalTests.npmproj b/src/SignalR/clients/ts/FunctionalTests/SignalR.Npm.FunctionalTests.npmproj
index 1a94cfe658a..bff023ed16b 100644
--- a/src/SignalR/clients/ts/FunctionalTests/SignalR.Npm.FunctionalTests.npmproj
+++ b/src/SignalR/clients/ts/FunctionalTests/SignalR.Npm.FunctionalTests.npmproj
@@ -8,12 +8,10 @@
     <_TestSauceArgs>--verbose --no-color --configuration $(Configuration) --sauce-user "$(SauceUser)" --sauce-key "$(SauceKey)"</_TestSauceArgs>
     <_TestSauceArgs Condition="'$(BrowserTestHostName)' != ''">$(_TestSauceArgs) --use-hostname "$(BrowserTestHostName)"</_TestSauceArgs>
     <NpmTestArgs Condition="'$(DailyTests)' != 'true'">run test:local -- --no-color --configuration $(Configuration)</NpmTestArgs>
-
-
   </PropertyGroup>
 
   <ItemGroup>
-    <ProjectReference Include="FunctionalTests.csproj" Condition="'$(BuildManaged)' != 'false'" />
+    <ProjectReference Include="FunctionalTests.csproj" Condition="'$(BuildManaged)' == 'true'" />
     <ProjectReference Include="..\signalr\signalr.npmproj" />
     <ProjectReference Include="..\signalr-protocol-msgpack\signalr-protocol-msgpack.npmproj" />
   </ItemGroup>
@@ -21,21 +19,20 @@
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />
 
   <Target Name="Test" Condition="'$(IsTestProject)' == 'true'">
-    <Message Importance="High" Text="Running npm tests for $(MSBuildProjectName)" />
-    <Exec Condition="'$(DailyTests)' != 'true'" Command="npm $(NpmTestArgs)" IgnoreStandardErrorWarningFormat="true" />
+    <Message Importance="High" Text="Running tests for $(MSBuildProjectName)" />
+    <Yarn Condition="'$(DailyTests)' != 'true'" Command="$(NpmTestArgs)" />
     <CallTarget Condition="'$(DailyTests)' == 'true'" Targets="RunBrowserTests" />
   </Target>
 
   <Target Name="RunBrowserTests">
     <Message Text="Running JavaScript client Browser tests" Importance="high" />
-    <Exec Command="npm run test:inner -- --no-color --configuration $(Configuration)" WorkingDirectory="$(RepositoryRoot)src/SignalR/clients/ts/FunctionalTests" IgnoreStandardErrorWarningFormat="true" />
+    <Yarn Command="run test:inner -- --no-color --configuration $(Configuration)" WorkingDirectory="$(RepositoryRoot)src/SignalR/clients/ts/FunctionalTests" />
     <Message Text="Running JavaScript tests" Importance="high" />
 
     <!-- Skip the "inner" test run when we're running DailyTests -->
-    <Exec Command="npm run test:inner -- --no-color --configuration $(Configuration)"
+    <Yarn Command="run test:inner -- --no-color --configuration $(Configuration)"
           Condition="'$(DailyTests)' != 'true'"
-          WorkingDirectory="$(RepositoryRoot)src/SignalR/clients/ts/FunctionalTests"
-          IgnoreStandardErrorWarningFormat="true" />
+          WorkingDirectory="$(RepositoryRoot)src/SignalR/clients/ts/FunctionalTests" />
 
     <PropertyGroup>
       <BrowserTestHostName Condition="'$(CI)' == 'true'">sauce.local</BrowserTestHostName>
diff --git a/src/SignalR/clients/ts/FunctionalTests/package.json b/src/SignalR/clients/ts/FunctionalTests/package.json
index 02d0cf30e99..f67658af39b 100644
--- a/src/SignalR/clients/ts/FunctionalTests/package.json
+++ b/src/SignalR/clients/ts/FunctionalTests/package.json
@@ -5,8 +5,8 @@
   "description": "",
   "main": "index.js",
   "dependencies": {
-    "@aspnet/signalr": "file:../signalr",
-    "@aspnet/signalr-protocol-msgpack": "file:../signalr-protocol-msgpack",
+    "@aspnet/signalr": "link:../signalr",
+    "@aspnet/signalr-protocol-msgpack": "link:../signalr-protocol-msgpack",
     "msgpack5": "^4.0.2"
   },
   "devDependencies": {
diff --git a/src/SignalR/clients/ts/signalr-protocol-msgpack/README.md b/src/SignalR/clients/ts/signalr-protocol-msgpack/README.md
index 6541df90ac5..c4d74f16b50 100644
--- a/src/SignalR/clients/ts/signalr-protocol-msgpack/README.md
+++ b/src/SignalR/clients/ts/signalr-protocol-msgpack/README.md
@@ -5,6 +5,10 @@ MsgPack support for SignalR for ASP.NET Core
 ```bash
 npm install @aspnet/signalr-protocol-msgpack
 ```
+or
+```bash
+yarn add @aspnet/signalr-protocol-msgpack
+```
 
 ## Usage
 
diff --git a/src/SignalR/clients/ts/signalr/README.md b/src/SignalR/clients/ts/signalr/README.md
index f38a93401ed..644e4eb2db9 100644
--- a/src/SignalR/clients/ts/signalr/README.md
+++ b/src/SignalR/clients/ts/signalr/README.md
@@ -5,6 +5,10 @@ JavaScript and TypeScript clients for SignalR for ASP.NET Core
 ```bash
 npm install @aspnet/signalr
 ```
+or
+```bash
+yarn add @aspnet/signalr
+```
 
 ## Usage
 
diff --git a/src/SignalR/clients/ts/signalr/package.json b/src/SignalR/clients/ts/signalr/package.json
index cb2f600b2b5..288d444f234 100644
--- a/src/SignalR/clients/ts/signalr/package.json
+++ b/src/SignalR/clients/ts/signalr/package.json
@@ -39,14 +39,14 @@
     "src/**/*"
   ],
   "devDependencies": {
-    "es6-promise": "^4.2.2",
-    "@types/node": "^10.9.4",
     "@types/eventsource": "^1.0.2",
-    "@types/request": "^2.47.1"
+    "@types/node": "^10.9.4",
+    "@types/request": "^2.47.1",
+    "es6-promise": "^4.2.2"
   },
   "dependencies": {
-    "ws": "^6.0.0",
     "eventsource": "^1.0.7",
-    "request": "^2.88.0"
+    "request": "^2.88.0",
+    "ws": "^6.0.0"
   }
 }
diff --git a/src/SignalR/docs/JSFunctionalTests.md b/src/SignalR/docs/JSFunctionalTests.md
index 27a7392fb44..a7e5a26fd27 100644
--- a/src/SignalR/docs/JSFunctionalTests.md
+++ b/src/SignalR/docs/JSFunctionalTests.md
@@ -13,7 +13,7 @@ Our JavaScript client functional tests are written using [Jasmine](https://jasmi
 
 ### Iterating
 
-The `npm test` command will take a while, because it will build the `clients\ts\signalr`, `clients\ts\signalr-protocol-msgpack` and `clients\ts\FunctionalTests` folders as well as `dotnet build` the `clients\ts\FunctionalTests` folder (to build the server-side components). If you are making changes, it's nice to be able to build only the things you need to build. To skip all the optional build steps, you can run `npm run test:inner` in `clients\ts\FunctionalTests`. This will skip building `clients\ts\signalr` and `clients\signalr-protocol-msgpack` (it will still build the `clients\ts\FunctionalTests` folder). If you make changes to those libraries, you have to manually build those directories.
+The `npm test` command will take a while, because it will build the `clients\ts\signalr`, `clients\ts\signalr-protocol-msgpack` and `clients\ts\FunctionalTests` folders as well as `dotnet build` the `clients\ts\FunctionalTests` folder (to build the server-side components). If you are making changes, it's nice to be able to build only the things you need to build. To skip all the optional build steps, you can run `yarn run test:inner` in `clients\ts\FunctionalTests`. This will skip building `clients\ts\signalr` and `clients\signalr-protocol-msgpack` (it will still build the `clients\ts\FunctionalTests` folder). If you make changes to those libraries, you have to manually build those directories.
 
 ## Running tests from the browser
 
-- 
GitLab