From 35495a336ca7b09b63fb320cba1f7ed3db68f843 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 15 Sep 2019 19:37:54 +0100 Subject: [PATCH 01/12] Update to ASP.NET Core 3.0 preview 9 Update to preview 9 of ASP.NET Core 3.0. Use C# 8 language features. Update BundlerMinifier.Core. Use System.Text.Json instead of Newtonsoft.Json. Use MediaTypeNames constants. --- global.json | 2 +- src/ApplePayJS/ApplePayJS.csproj | 11 +++----- src/ApplePayJS/Clients/ApplePayClient.cs | 23 +++++++++------ src/ApplePayJS/Clients/MerchantCertificate.cs | 28 +++++++++---------- .../Clients/MerchantSessionRequest.cs | 18 ++++++------ src/ApplePayJS/Controllers/HomeController.cs | 11 ++++---- src/ApplePayJS/Models/ApplePayOptions.cs | 8 +++--- src/ApplePayJS/Models/HomeModel.cs | 4 +-- .../Models/ValidateMerchantSessionModel.cs | 2 +- src/ApplePayJS/Program.cs | 10 +++---- src/ApplePayJS/Startup.cs | 20 +++++++------ 11 files changed, 71 insertions(+), 66 deletions(-) diff --git a/global.json b/global.json index 89b3b0f4..79a76ed5 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.2.402" + "version": "3.0.100-preview9-014004" } } diff --git a/src/ApplePayJS/ApplePayJS.csproj b/src/ApplePayJS/ApplePayJS.csproj index c4e74d3f..ba1e9a69 100644 --- a/src/ApplePayJS/ApplePayJS.csproj +++ b/src/ApplePayJS/ApplePayJS.csproj @@ -1,14 +1,14 @@  - inprocess + InProcess Martin Costello JustEat.ApplePayJS Just Eat Just Eat (c) 2016-$([System.DateTime]::Now.ToString(yyyy)) latest en-US + enable Exe - https://avatars3.githubusercontent.com/u/1516790?v=3&s=100 JustEat.ApplePayJS Apache-2.0 https://github.com/justeat/ApplePayJSSample @@ -19,7 +19,7 @@ git $(PackageProjectUrl).git JustEat.ApplePayJS - netcoreapp2.2 + netcoreapp3.0 latest JustEat.ApplePayJS 3.0.0 @@ -28,9 +28,6 @@ - - - true @@ -50,6 +47,6 @@ - + diff --git a/src/ApplePayJS/Clients/ApplePayClient.cs b/src/ApplePayJS/Clients/ApplePayClient.cs index 29587ba9..d13d6445 100644 --- a/src/ApplePayJS/Clients/ApplePayClient.cs +++ b/src/ApplePayJS/Clients/ApplePayClient.cs @@ -1,8 +1,10 @@ using System; using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; namespace JustEat.ApplePayJS.Clients { @@ -15,19 +17,24 @@ public ApplePayClient(HttpClient httpClient) _httpClient = httpClient; } - public async Task GetMerchantSessionAsync( + public async Task GetMerchantSessionAsync( Uri requestUri, MerchantSessionRequest request, CancellationToken cancellationToken = default) { // POST the data to create a valid Apple Pay merchant session. - using (var response = await _httpClient.PostAsJsonAsync(requestUri, request, cancellationToken)) - { - response.EnsureSuccessStatusCode(); + string json = JsonSerializer.Serialize(request); - // Read the opaque merchant session JSON from the response body. - return await response.Content.ReadAsAsync(cancellationToken); - } + using var content = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json); + + using var response = await _httpClient.PostAsync(requestUri, content, cancellationToken); + + response.EnsureSuccessStatusCode(); + + // Read the opaque merchant session JSON from the response body. + using var stream = await response.Content.ReadAsStreamAsync(); + + return await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken); } } } diff --git a/src/ApplePayJS/Clients/MerchantCertificate.cs b/src/ApplePayJS/Clients/MerchantCertificate.cs index 351068d3..903a8d31 100644 --- a/src/ApplePayJS/Clients/MerchantCertificate.cs +++ b/src/ApplePayJS/Clients/MerchantCertificate.cs @@ -32,7 +32,7 @@ public string GetMerchantIdentifier() { try { - var merchantCertificate = GetCertificate(); + using var merchantCertificate = GetCertificate(); return GetMerchantIdentifier(merchantCertificate); } catch (InvalidOperationException) @@ -76,23 +76,21 @@ private X509Certificate2 LoadCertificateFromStore() // your application, but it is also required to be able to use an X.509 // certificate with a private key if the user profile is not available, // such as when using IIS hosting in an environment such as Microsoft Azure. - using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) - { - store.Open(OpenFlags.ReadOnly); - - var certificates = store.Certificates.Find( - X509FindType.FindByThumbprint, - _options.MerchantCertificateThumbprint?.Trim(), - validOnly: false); + using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser); + store.Open(OpenFlags.ReadOnly); - if (certificates.Count < 1) - { - throw new InvalidOperationException( - $"Could not find Apple Pay merchant certificate with thumbprint '{_options.MerchantCertificateThumbprint}' from store '{store.Name}' in location '{store.Location}'."); - } + var certificates = store.Certificates.Find( + X509FindType.FindByThumbprint, + _options.MerchantCertificateThumbprint?.Trim(), + validOnly: false); - return certificates[0]; + if (certificates.Count < 1) + { + throw new InvalidOperationException( + $"Could not find Apple Pay merchant certificate with thumbprint '{_options.MerchantCertificateThumbprint}' from store '{store.Name}' in location '{store.Location}'."); } + + return certificates[0]; } } } diff --git a/src/ApplePayJS/Clients/MerchantSessionRequest.cs b/src/ApplePayJS/Clients/MerchantSessionRequest.cs index 07eb9289..14fcc062 100644 --- a/src/ApplePayJS/Clients/MerchantSessionRequest.cs +++ b/src/ApplePayJS/Clients/MerchantSessionRequest.cs @@ -1,19 +1,19 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace JustEat.ApplePayJS.Clients { public class MerchantSessionRequest { - [JsonProperty("merchantIdentifier")] - public string MerchantIdentifier { get; set; } + [JsonPropertyName("merchantIdentifier")] + public string? MerchantIdentifier { get; set; } - [JsonProperty("displayName")] - public string DisplayName { get; set; } + [JsonPropertyName("displayName")] + public string? DisplayName { get; set; } - [JsonProperty("initiative")] - public string Initiative { get; set; } + [JsonPropertyName("initiative")] + public string? Initiative { get; set; } - [JsonProperty("initiativeContext")] - public string InitiativeContext { get; set; } + [JsonPropertyName("initiativeContext")] + public string? InitiativeContext { get; set; } } } diff --git a/src/ApplePayJS/Controllers/HomeController.cs b/src/ApplePayJS/Controllers/HomeController.cs index 06a6ab09..1c94e1c6 100644 --- a/src/ApplePayJS/Controllers/HomeController.cs +++ b/src/ApplePayJS/Controllers/HomeController.cs @@ -4,6 +4,8 @@ namespace JustEat.ApplePayJS.Controllers { using System; + using System.Net.Mime; + using System.Text.Json; using System.Threading; using System.Threading.Tasks; using JustEat.ApplePayJS.Clients; @@ -11,7 +13,6 @@ namespace JustEat.ApplePayJS.Controllers using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Models; - using Newtonsoft.Json.Linq; public class HomeController : Controller { @@ -42,7 +43,7 @@ public IActionResult Index() } [HttpPost] - [Produces("application/json")] + [Produces(MediaTypeNames.Application.Json)] [Route("applepay/validate", Name = "MerchantValidation")] public async Task Validate([FromBody] ValidateMerchantSessionModel model, CancellationToken cancellationToken = default) { @@ -51,7 +52,7 @@ public async Task Validate([FromBody] ValidateMerchantSessionMode // these servers are available here: https://developer.apple.com/documentation/applepayjs/setting_up_server_requirements if (!ModelState.IsValid || string.IsNullOrWhiteSpace(model?.ValidationUrl) || - !Uri.TryCreate(model.ValidationUrl, UriKind.Absolute, out Uri requestUri)) + !Uri.TryCreate(model.ValidationUrl, UriKind.Absolute, out Uri? requestUri)) { return BadRequest(); } @@ -65,10 +66,10 @@ public async Task Validate([FromBody] ValidateMerchantSessionMode MerchantIdentifier = _certificate.GetMerchantIdentifier(), }; - JObject merchantSession = await _client.GetMerchantSessionAsync(requestUri, request, cancellationToken); + JsonDocument merchantSession = await _client.GetMerchantSessionAsync(requestUri, request, cancellationToken); // Return the merchant session as-is to the JavaScript as JSON. - return Json(merchantSession); + return Json(merchantSession.RootElement); } public IActionResult Error() => View(); diff --git a/src/ApplePayJS/Models/ApplePayOptions.cs b/src/ApplePayJS/Models/ApplePayOptions.cs index 9a549a17..3749dd7f 100644 --- a/src/ApplePayJS/Models/ApplePayOptions.cs +++ b/src/ApplePayJS/Models/ApplePayOptions.cs @@ -5,14 +5,14 @@ namespace JustEat.ApplePayJS.Models { public class ApplePayOptions { - public string StoreName { get; set; } + public string? StoreName { get; set; } public bool UseCertificateStore { get; set; } - public string MerchantCertificateFileName { get; set; } + public string? MerchantCertificateFileName { get; set; } - public string MerchantCertificatePassword { get; set; } + public string? MerchantCertificatePassword { get; set; } - public string MerchantCertificateThumbprint { get; set; } + public string? MerchantCertificateThumbprint { get; set; } } } diff --git a/src/ApplePayJS/Models/HomeModel.cs b/src/ApplePayJS/Models/HomeModel.cs index af07e74e..d6bc6c5f 100644 --- a/src/ApplePayJS/Models/HomeModel.cs +++ b/src/ApplePayJS/Models/HomeModel.cs @@ -2,8 +2,8 @@ namespace JustEat.ApplePayJS.Models { public class HomeModel { - public string MerchantId { get; set; } + public string? MerchantId { get; set; } - public string StoreName { get; set; } + public string? StoreName { get; set; } } } diff --git a/src/ApplePayJS/Models/ValidateMerchantSessionModel.cs b/src/ApplePayJS/Models/ValidateMerchantSessionModel.cs index 21edf06e..e6d2a9de 100644 --- a/src/ApplePayJS/Models/ValidateMerchantSessionModel.cs +++ b/src/ApplePayJS/Models/ValidateMerchantSessionModel.cs @@ -9,6 +9,6 @@ public class ValidateMerchantSessionModel { [DataType(DataType.Url)] [Required] - public string ValidationUrl { get; set; } + public string? ValidationUrl { get; set; } } } diff --git a/src/ApplePayJS/Program.cs b/src/ApplePayJS/Program.cs index 99b45ed2..ecd07550 100644 --- a/src/ApplePayJS/Program.cs +++ b/src/ApplePayJS/Program.cs @@ -3,18 +3,18 @@ namespace JustEat.ApplePayJS { - using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; + using Microsoft.Extensions.Hosting; public static class Program { public static void Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup(); + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults((builder) => builder.UseStartup()); } } diff --git a/src/ApplePayJS/Startup.cs b/src/ApplePayJS/Startup.cs index aacf62d3..f7c58ddf 100644 --- a/src/ApplePayJS/Startup.cs +++ b/src/ApplePayJS/Startup.cs @@ -11,26 +11,27 @@ namespace JustEat.ApplePayJS using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Hosting; using Models; public class Startup { - public Startup(IHostingEnvironment env, IConfiguration configuration) + public Startup(IHostEnvironment environment, IConfiguration configuration) { Configuration = configuration; - Environment = env; + Environment = environment; } public IConfiguration Configuration { get; } - public IHostingEnvironment Environment { get; } + public IHostEnvironment Environment { get; } public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure(Configuration.GetSection("ApplePay")); - services.AddAntiforgery(options => + services.AddAntiforgery((options) => { options.Cookie.Name = "antiforgerytoken"; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; @@ -38,7 +39,7 @@ public void ConfigureServices(IServiceCollection services) }); services.AddMvc( - options => + (options) => { // Apple Pay JS requires pages to be served over HTTPS if (Environment.IsProduction()) @@ -47,7 +48,7 @@ public void ConfigureServices(IServiceCollection services) options.Filters.Add(new RequireHttpsAttribute()); } }) - .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); // Register class for managing the application's use of the Apple Pay merchant certificate services.AddSingleton(); @@ -73,9 +74,9 @@ public void ConfigureServices(IServiceCollection services) }); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app) { - if (env.IsDevelopment()) + if (Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } @@ -94,7 +95,8 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) ServeUnknownFileTypes = true, // Required to serve the files in the .well-known folder }); - app.UseMvcWithDefaultRoute(); + app.UseRouting(); + app.UseEndpoints((endpoints) => endpoints.MapDefaultControllerRoute()); } } } From d8b5ed2b36b20b0b29555740dd54c13375aacc7d Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 15 Sep 2019 19:39:51 +0100 Subject: [PATCH 02/12] Update README.md Update README to mention ASP.NET Core 3.0. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 64f6746b..db113828 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ |:-:|:-:|:-:| | **Build Status** | [![Build status](https://img.shields.io/travis/justeat/ApplePayJSSample/master.svg)](https://travis-ci.org/justeat/ApplePayJSSample) | [![Build status](https://img.shields.io/appveyor/ci/justeattech/applepayjssample/master.svg)](https://ci.appveyor.com/project/justeattech/applepayjssample) | -This repository contains a sample implementation of [Apple Pay JS](https://developer.apple.com/reference/applepayjs/) using ASP.NET Core 2.2 written in C# and JavaScript. +This repository contains a sample implementation of [Apple Pay JS](https://developer.apple.com/reference/applepayjs/) using ASP.NET Core 3.0 written in C# and JavaScript. ## Overview @@ -24,7 +24,7 @@ The key components to look at for the implementation are: To setup the repository to run the sample, perform the steps below: - 1. Install the [.NET Core 2.2.402 SDK](https://www.microsoft.com/net/download/core), Visual Studio 2019 or Visual Studio Code. + 1. Install the [.NET Core 3.0.100 SDK](https://www.microsoft.com/net/download/core), Visual Studio 2019 or Visual Studio Code. 1. Fork this repository. 1. Clone the repository from your fork to your local machine: ```git clone https://github.com/{username}/ApplePayJSSample.git``` 1. Restore the Bower, npm and NuGet packages. From 7a3e87e2c64e45fdbf148430a59b23b9de5b5006 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 15 Sep 2019 19:40:15 +0100 Subject: [PATCH 03/12] Add VS Code assets to solution Add the files for Visual Studio Code to the solution file. --- ApplePayJS.sln | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ApplePayJS.sln b/ApplePayJS.sln index df0e8291..8d6dd5a9 100644 --- a/ApplePayJS.sln +++ b/ApplePayJS.sln @@ -29,6 +29,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{A4EF .github\PULL_REQUEST_TEMPLATE.md = .github\PULL_REQUEST_TEMPLATE.md EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".vscode", ".vscode", "{F99C01C5-8B5D-4BDD-B40B-35DE14D08D57}" + ProjectSection(SolutionItems) = preProject + .vscode\launch.json = .vscode\launch.json + .vscode\tasks.json = .vscode\tasks.json + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -46,6 +52,7 @@ Global GlobalSection(NestedProjects) = preSolution {4CFD067B-FD1A-4303-9322-3138E9104B1F} = {ABF2B260-1BAE-45CD-9348-C163CA02ECA3} {A4EFB4F4-BC05-4A67-89AC-4D7D21B71D4E} = {C697BCC9-C4F9-4AD8-8336-E90A239865DE} + {F99C01C5-8B5D-4BDD-B40B-35DE14D08D57} = {C697BCC9-C4F9-4AD8-8336-E90A239865DE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8797D09A-407D-424A-A8F0-22FB26F0650C} From e1de2e932fed85c4abc8fe578e3a2e83d53ce3e6 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 15 Sep 2019 19:41:27 +0100 Subject: [PATCH 04/12] Update VS Code launch target Fix missing update to 3.0 from 2.2. --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d6519312..a1fa166a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "build", - "program": "${workspaceRoot}/src/ApplePayJS/bin/Debug/netcoreapp2.2/JustEat.ApplePayJS.dll", + "program": "${workspaceRoot}/src/ApplePayJS/bin/Debug/netcoreapp3.0/JustEat.ApplePayJS.dll", "args": [], "cwd": "${workspaceRoot}/src/ApplePayJS", "stopAtEntry": false, From aaeedb9ae934631928df950bffaf3a0aa338ec98 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 15 Sep 2019 19:43:54 +0100 Subject: [PATCH 05/12] Update CI YAML files Update the YAML files for CI to latest images etc. --- .travis.yml | 6 ++++-- appveyor.yml | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9a531df0..c3153fa3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ sudo: required dist: xenial +language: csharp +mono: none os: - linux @@ -24,8 +26,8 @@ addons: - libunwind8 install: - - npm install -g bower - - npm install -g npm + - npm install --global bower + - npm install --global npm script: - ./build.sh diff --git a/appveyor.yml b/appveyor.yml index fa7a4535..94978bd7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -os: Visual Studio 2017 +os: Visual Studio 2019 version: 3.0.{build} environment: @@ -10,8 +10,8 @@ branches: - master install: - - ps: npm install -g bower --loglevel=error - - ps: npm install -g npm + - ps: npm install --global bower --loglevel=error + - ps: npm install --global npm build_script: - ps: .\Build.ps1 From 5968a8ad67727ed204387192bf2e8cc77cf93b39 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 15 Sep 2019 22:21:39 +0100 Subject: [PATCH 06/12] Add missing copyright headers Add copyright header to files where it was missing. --- src/ApplePayJS/Clients/ApplePayClient.cs | 3 +++ src/ApplePayJS/Clients/MerchantCertificate.cs | 3 +++ src/ApplePayJS/Clients/MerchantSessionRequest.cs | 3 +++ src/ApplePayJS/Models/HomeModel.cs | 3 +++ src/ApplePayJS/Views/Home/_Polyfill.cshtml | 5 +++++ 5 files changed, 17 insertions(+) diff --git a/src/ApplePayJS/Clients/ApplePayClient.cs b/src/ApplePayJS/Clients/ApplePayClient.cs index d13d6445..aaa3528b 100644 --- a/src/ApplePayJS/Clients/ApplePayClient.cs +++ b/src/ApplePayJS/Clients/ApplePayClient.cs @@ -1,3 +1,6 @@ +// Copyright (c) Just Eat, 2016. All rights reserved. +// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. + using System; using System.Net.Http; using System.Net.Mime; diff --git a/src/ApplePayJS/Clients/MerchantCertificate.cs b/src/ApplePayJS/Clients/MerchantCertificate.cs index 903a8d31..4e4ac73a 100644 --- a/src/ApplePayJS/Clients/MerchantCertificate.cs +++ b/src/ApplePayJS/Clients/MerchantCertificate.cs @@ -1,3 +1,6 @@ +// Copyright (c) Just Eat, 2016. All rights reserved. +// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. + using System; using System.Security.Cryptography.X509Certificates; using System.Text; diff --git a/src/ApplePayJS/Clients/MerchantSessionRequest.cs b/src/ApplePayJS/Clients/MerchantSessionRequest.cs index 14fcc062..73dab2ae 100644 --- a/src/ApplePayJS/Clients/MerchantSessionRequest.cs +++ b/src/ApplePayJS/Clients/MerchantSessionRequest.cs @@ -1,3 +1,6 @@ +// Copyright (c) Just Eat, 2016. All rights reserved. +// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. + using System.Text.Json.Serialization; namespace JustEat.ApplePayJS.Clients diff --git a/src/ApplePayJS/Models/HomeModel.cs b/src/ApplePayJS/Models/HomeModel.cs index d6bc6c5f..c84a82dc 100644 --- a/src/ApplePayJS/Models/HomeModel.cs +++ b/src/ApplePayJS/Models/HomeModel.cs @@ -1,3 +1,6 @@ +// Copyright (c) Just Eat, 2016. All rights reserved. +// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. + namespace JustEat.ApplePayJS.Models { public class HomeModel diff --git a/src/ApplePayJS/Views/Home/_Polyfill.cshtml b/src/ApplePayJS/Views/Home/_Polyfill.cshtml index b1de3032..c6520eb0 100644 --- a/src/ApplePayJS/Views/Home/_Polyfill.cshtml +++ b/src/ApplePayJS/Views/Home/_Polyfill.cshtml @@ -1,3 +1,8 @@ +@* + Copyright (c) Just Eat, 2016. All rights reserved. + Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. +*@ + @model string @* Use this polyfill during development to test your Apple Pay JS implementation From d0cc05273eb62a489405069f9853119c3271e231 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 15 Sep 2019 22:48:49 +0100 Subject: [PATCH 07/12] Add integration test Add UI integration test using a self-hosted HTTP server with a dummy Apple Pay merchant certificate and Selenium. --- .travis.yml | 3 + ApplePayJS.sln | 10 ++ Build.ps1 | 3 + Directory.Build.props | 20 +++ appveyor.yml | 1 + build.sh | 1 + src/ApplePayJS/ApplePayJS.csproj | 10 -- .../ApplePayJS.Tests/ApplePayJS.Tests.csproj | 29 ++++ tests/ApplePayJS.Tests/IntegrationTests.cs | 90 ++++++++++ .../MerchantCertificateGenerator.cs | 49 ++++++ tests/ApplePayJS.Tests/TestFixture.cs | 164 ++++++++++++++++++ tests/ApplePayJS.Tests/applepay-dev.pfx | Bin 0 -> 2510 bytes tests/ApplePayJS.Tests/localhost-dev.pfx | Bin 0 -> 4037 bytes tests/ApplePayJS.Tests/testsettings.json | 17 ++ tests/ApplePayJS.Tests/xunit.runner.json | 3 + 15 files changed, 390 insertions(+), 10 deletions(-) create mode 100644 Directory.Build.props create mode 100644 tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj create mode 100644 tests/ApplePayJS.Tests/IntegrationTests.cs create mode 100644 tests/ApplePayJS.Tests/MerchantCertificateGenerator.cs create mode 100644 tests/ApplePayJS.Tests/TestFixture.cs create mode 100644 tests/ApplePayJS.Tests/applepay-dev.pfx create mode 100644 tests/ApplePayJS.Tests/localhost-dev.pfx create mode 100644 tests/ApplePayJS.Tests/testsettings.json create mode 100644 tests/ApplePayJS.Tests/xunit.runner.json diff --git a/.travis.yml b/.travis.yml index c3153fa3..397cb1f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,10 +20,13 @@ addons: apt: packages: - gettext + - google-chrome-stable - libcurl4-openssl-dev - libicu-dev - libssl-dev - libunwind8 + sources: + - google-chrome install: - npm install --global bower diff --git a/ApplePayJS.sln b/ApplePayJS.sln index 8d6dd5a9..69363c86 100644 --- a/ApplePayJS.sln +++ b/ApplePayJS.sln @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Build.ps1 = Build.ps1 build.sh = build.sh CODE_OF_CONDUCT.md = CODE_OF_CONDUCT.md + Directory.Build.props = Directory.Build.props global.json = global.json LICENSE = LICENSE NuGet.config = NuGet.config @@ -35,6 +36,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".vscode", ".vscode", "{F99C .vscode\tasks.json = .vscode\tasks.json EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{3F1B1211-EEF9-482B-93CD-6FF250907EB9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplePayJS.Tests", "tests\ApplePayJS.Tests\ApplePayJS.Tests.csproj", "{20EE5C1E-2059-4291-93F6-AA0F76C08EBE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,6 +50,10 @@ Global {4CFD067B-FD1A-4303-9322-3138E9104B1F}.Debug|Any CPU.Build.0 = Debug|Any CPU {4CFD067B-FD1A-4303-9322-3138E9104B1F}.Release|Any CPU.ActiveCfg = Release|Any CPU {4CFD067B-FD1A-4303-9322-3138E9104B1F}.Release|Any CPU.Build.0 = Release|Any CPU + {20EE5C1E-2059-4291-93F6-AA0F76C08EBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20EE5C1E-2059-4291-93F6-AA0F76C08EBE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20EE5C1E-2059-4291-93F6-AA0F76C08EBE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20EE5C1E-2059-4291-93F6-AA0F76C08EBE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -53,6 +62,7 @@ Global {4CFD067B-FD1A-4303-9322-3138E9104B1F} = {ABF2B260-1BAE-45CD-9348-C163CA02ECA3} {A4EFB4F4-BC05-4A67-89AC-4D7D21B71D4E} = {C697BCC9-C4F9-4AD8-8336-E90A239865DE} {F99C01C5-8B5D-4BDD-B40B-35DE14D08D57} = {C697BCC9-C4F9-4AD8-8336-E90A239865DE} + {20EE5C1E-2059-4291-93F6-AA0F76C08EBE} = {3F1B1211-EEF9-482B-93CD-6FF250907EB9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8797D09A-407D-424A-A8F0-22FB26F0650C} diff --git a/Build.ps1 b/Build.ps1 index 3b981dbf..16539a86 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -58,6 +58,9 @@ else { Write-Host "Publishing solution..." -ForegroundColor Green & $dotnet publish $solutionFile --output $OutputPath --configuration $Configuration +Write-Host "Running tests..." -ForegroundColor Green +& $dotnet test $solutionFile --output $OutputPath --configuration $Configuration + if ($LASTEXITCODE -ne 0) { throw "dotnet publish failed with exit code $LASTEXITCODE" } diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..50bc9752 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,20 @@ + + + Martin Costello + Just Eat + Just Eat (c) 2016-$([System.DateTime]::Now.ToString(yyyy)) + latest + en-US + enable + Apache-2.0 + https://github.com/justeat/ApplePayJSSample + $(PackageProjectUrl)/releases + false + applepay + git + $(PackageProjectUrl).git + latest + 3.0.0 + + + diff --git a/appveyor.yml b/appveyor.yml index 94978bd7..d78288a6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,7 @@ branches: install: - ps: npm install --global bower --loglevel=error - ps: npm install --global npm + - ps: choco upgrade googlechrome --confirm --ignore-checksums --no-progress build_script: - ps: .\Build.ps1 diff --git a/build.sh b/build.sh index a73cb7de..8d05745d 100755 --- a/build.sh +++ b/build.sh @@ -35,3 +35,4 @@ if [ "$dotnet_version" != "$CLI_VERSION" ]; then fi dotnet publish ./ApplePayJS.sln --output $artifacts/publish --configuration $configuration || exit 1 +dotnet test ./ApplePayJS.sln --output $artifacts --configuration $configuration || exit 1 diff --git a/src/ApplePayJS/ApplePayJS.csproj b/src/ApplePayJS/ApplePayJS.csproj index ba1e9a69..f3c79a45 100644 --- a/src/ApplePayJS/ApplePayJS.csproj +++ b/src/ApplePayJS/ApplePayJS.csproj @@ -1,13 +1,7 @@  InProcess - Martin Costello JustEat.ApplePayJS - Just Eat - Just Eat (c) 2016-$([System.DateTime]::Now.ToString(yyyy)) - latest - en-US - enable Exe JustEat.ApplePayJS Apache-2.0 @@ -16,14 +10,10 @@ false applepay true - git - $(PackageProjectUrl).git JustEat.ApplePayJS netcoreapp3.0 latest JustEat.ApplePayJS - 3.0.0 - diff --git a/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj b/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj new file mode 100644 index 00000000..94f6d0a3 --- /dev/null +++ b/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj @@ -0,0 +1,29 @@ + + + netcoreapp3.0 + false + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/ApplePayJS.Tests/IntegrationTests.cs b/tests/ApplePayJS.Tests/IntegrationTests.cs new file mode 100644 index 00000000..1eb33b4b --- /dev/null +++ b/tests/ApplePayJS.Tests/IntegrationTests.cs @@ -0,0 +1,90 @@ +// Copyright (c) Just Eat, 2016. All rights reserved. +// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. + +using System; +using System.IO; +using System.Threading.Tasks; +using JustEat.HttpClientInterception; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; +using OpenQA.Selenium.Support.UI; +using Shouldly; +using Xunit; +using Xunit.Abstractions; + +namespace ApplePayJS.Tests +{ + public class IntegrationTests : IAsyncLifetime + { + public IntegrationTests(ITestOutputHelper outputHelper) + { + Fixture = new TestFixture() + { + OutputHelper = outputHelper, + }; + } + + private TestFixture Fixture { get; } + + public async Task InitializeAsync() + { + await Fixture.StartServerAsync(); + } + + public Task DisposeAsync() + { + if (Fixture != null) + { + Fixture.Dispose(); + } + + return Task.CompletedTask; + } + + [Fact] + public void Can_Pay_With_Apple_Pay() + { + // Arrange + var builder = new HttpRequestInterceptionBuilder() + .Requests() + .ForPost() + .ForUrl("https://apple-pay-gateway-cert.apple.com/paymentservices/startSession") + .Responds() + .WithJsonContent(new { }) + .RegisterWith(Fixture.Interceptor); + + using var driver = CreateWebDriver(); + driver.Navigate().GoToUrl(Fixture.ServerAddress); + + // Act + driver.FindElement(By.Id("amount")).Clear(); + driver.FindElement(By.Id("amount")).SendKeys("1.23"); + driver.FindElement(By.Id("apple-pay-button")).Click(); + + // Assert + var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5)); + wait.Until((p) => p.FindElement(By.ClassName("card-name")).Displayed); + + driver.FindElement(By.ClassName("card-name")).Text.ShouldBe("American Express"); + driver.FindElement(By.Id("billing-contact")).FindElement(By.ClassName("contact-name")).Text.ShouldBe("John Smith"); + driver.FindElement(By.Id("shipping-contact")).FindElement(By.ClassName("contact-name")).Text.ShouldBe("John Smith"); + } + + private static IWebDriver CreateWebDriver() + { + string chromeDriverDirectory = Path.GetDirectoryName(typeof(IntegrationTests).Assembly.Location) ?? "."; + + var options = new ChromeOptions() + { + AcceptInsecureCertificates = true, + }; + + if (!System.Diagnostics.Debugger.IsAttached) + { + options.AddArgument("--headless"); + } + + return new ChromeDriver(chromeDriverDirectory, options); + } + } +} diff --git a/tests/ApplePayJS.Tests/MerchantCertificateGenerator.cs b/tests/ApplePayJS.Tests/MerchantCertificateGenerator.cs new file mode 100644 index 00000000..4a47a145 --- /dev/null +++ b/tests/ApplePayJS.Tests/MerchantCertificateGenerator.cs @@ -0,0 +1,49 @@ +// Copyright (c) Just Eat, 2016. All rights reserved. +// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. + +using System; +using System.IO; +using System.Net; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using Xunit; + +namespace ApplePayJS.Tests +{ + public static class MerchantCertificateGenerator + { + [Fact(Skip = "Enable this test to generate a new dummy Apple Pay merchant certificate to use for the tests.")] + public static async Task Generate_Fake_Apple_Pay_Merchant_Certificate() + { + // Arrange + string certificateName = "applepay.local"; + string certificatePassword = "Pa55w0rd!"; + string certificateFileName = "CHANGE_ME"; + + var builder = new SubjectAlternativeNameBuilder(); + builder.AddIpAddress(IPAddress.Loopback); + builder.AddIpAddress(IPAddress.IPv6Loopback); + builder.AddDnsName("localhost"); + + var distinguishedName = new X500DistinguishedName($"CN={certificateName}"); + + using var key = RSA.Create(2048); + var request = new CertificateRequest(distinguishedName, key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + + request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyAgreement | X509KeyUsageFlags.KeyEncipherment, false)); + request.CertificateExtensions.Add(new X509Extension("1.2.840.113635.100.6.32", Guid.NewGuid().ToByteArray(), false)); + request.CertificateExtensions.Add(builder.Build()); + + var utcNow = DateTimeOffset.UtcNow; + + X509Certificate2 certificate = request.CreateSelfSigned(utcNow.AddDays(-1), utcNow.AddDays(3650)); + certificate.FriendlyName = certificateName; + + byte[] pfxBytes = certificate.Export(X509ContentType.Pfx, certificatePassword); + + File.Delete(certificateFileName); + await File.WriteAllBytesAsync(certificateFileName, pfxBytes); + } + } +} diff --git a/tests/ApplePayJS.Tests/TestFixture.cs b/tests/ApplePayJS.Tests/TestFixture.cs new file mode 100644 index 00000000..19247fb2 --- /dev/null +++ b/tests/ApplePayJS.Tests/TestFixture.cs @@ -0,0 +1,164 @@ +// Copyright (c) Just Eat, 2016. All rights reserved. +// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. + +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using JustEat.ApplePayJS; +using JustEat.HttpClientInterception; +using MartinCostello.Logging.XUnit; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Http; +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace ApplePayJS.Tests +{ + public class TestFixture : WebApplicationFactory, ITestOutputHelperAccessor + { + private IHost? _host; + private bool _disposed; + + public TestFixture() + : base() + { + ClientOptions.AllowAutoRedirect = false; + ClientOptions.BaseAddress = new Uri("https://localhost"); + Interceptor = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration(); + } + + public HttpClientInterceptorOptions Interceptor { get; } + + public ITestOutputHelper? OutputHelper { get; set; } + + public Uri ServerAddress => ClientOptions.BaseAddress; + + public async Task StartServerAsync() + { + if (_host == null) + { + await CreateHttpServer(); + } + } + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.ConfigureServices( + (services) => services.AddSingleton( + (_) => new HttpRequestInterceptionFilter(Interceptor))); + + builder.ConfigureAppConfiguration(ConfigureTests) + .ConfigureLogging((loggingBuilder) => loggingBuilder.ClearProviders().AddXUnit(this).AddDebug()) + .UseContentRoot(GetContentRootPath()); + + builder.ConfigureKestrel( + (kestrelOptions) => kestrelOptions.ConfigureHttpsDefaults( + (connectionOptions) => connectionOptions.ServerCertificate = new X509Certificate2("localhost-dev.pfx", "Pa55w0rd!"))); + + builder.UseUrls(ServerAddress.ToString()); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (!_disposed) + { + if (disposing) + { + _host?.Dispose(); + } + + _disposed = true; + } + } + + private static void ConfigureTests(IConfigurationBuilder builder) + { + string? directory = Path.GetDirectoryName(typeof(TestFixture).Assembly.Location); + string fullPath = Path.Combine(directory ?? ".", "testsettings.json"); + + builder.AddJsonFile(fullPath); + } + + private static Uri FindFreeServerAddress() + { + int port = GetFreePortNumber(); + + return new UriBuilder() + { + Scheme = "https", + Host = "localhost", + Port = port, + }.Uri; + } + + private static int GetFreePortNumber() + { + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + + try + { + return ((IPEndPoint)listener.LocalEndpoint).Port; + } + finally + { + listener.Stop(); + } + } + + private async Task CreateHttpServer() + { + // Configure the server address for the server to listen on for HTTP requests + ClientOptions.BaseAddress = FindFreeServerAddress(); + + var builder = CreateHostBuilder().ConfigureWebHost(ConfigureWebHost); + + _host = builder.Build(); + + // Force creation of the Kestrel server and start it + var hostedService = _host.Services.GetService(); + await hostedService.StartAsync(default); + } + + private string GetContentRootPath() + { + var attribute = GetTestAssemblies() + .SelectMany((p) => p.GetCustomAttributes()) + .Where((p) => string.Equals(p.Key, "JustEat.ApplePayJS", StringComparison.OrdinalIgnoreCase)) + .OrderBy((p) => p.Priority) + .First(); + + return attribute.ContentRootPath; + } + + private sealed class HttpRequestInterceptionFilter : IHttpMessageHandlerBuilderFilter + { + internal HttpRequestInterceptionFilter(HttpClientInterceptorOptions options) + { + Options = options; + } + + private HttpClientInterceptorOptions Options { get; } + + public Action Configure(Action next) + { + return (builder) => + { + next(builder); + builder.AdditionalHandlers.Add(Options.CreateHttpMessageHandler()); + }; + } + } + } +} diff --git a/tests/ApplePayJS.Tests/applepay-dev.pfx b/tests/ApplePayJS.Tests/applepay-dev.pfx new file mode 100644 index 0000000000000000000000000000000000000000..dad6b947008c7e448741bf4656fcca6769f2830a GIT binary patch literal 2510 zcmZXUc{mjM8pmfd48~zflYMCtGYw;3PqG!+4T&U!AxmLwqeTpjV=4QdkS#(Y63MP{ zvP?n`V@sAXcCL~ocTUf_=RWtjf4slt^LgI)_t)=>qrmj)#h=fo$?y+$gyMm!Se|Pb613?88$Qq6UVc|rf-2cJs;d~IT zQX^EGwHX52or7KhpCnPpoux(iGx}6Mw(mPb7hU}ETuMae2k(#B;0o$WFC*b z_knw*=@palvM6S65#4U8aX>j(`XON%nI+TjNVqmI+51sZ8Q^t&1+5EQw``Xg7#@** zm!+B>SS7NOm3=)yE;+sU$;xPv_38J6l9LN{4EVrrJK6%XPxu~^g0=JIud;emlBKxT z@7kFAH%Mh}JmqzL(pUGjfsD=@Q_ZTl)dIS7b10&-b>v(R0^k+%al-TRV)+;J{kwWb z&XKA{FS$b=YBq^69b`4?9FPLR|E|G% z^=wp{-RCS#x9YPh(>3`#O8}wZW)K9k0XB$tmg6ScI|;1G#cu%c?}o%J`)}B#+tMmp zGOpv*IJjzQ78&OhcXjoMO2pK_jNe)Wp^2V+N8gXBJ{UrRor$F3Z$In+t!ED8A_zl? zokN{TX&+4W310rk>tb%4uXYo!ZC$eB?4LGoQH>tjwdK<15g=`yx!W%8Bm4Nza@WV? z7uw_?^;6{``~B$Bo=Y7_UdzRCnAukDdP02eP)f*J2~>)mRs^tleqVa=!l&2!6X{lN_cynpcJ;pVZiMEMX zkwwQ)6uqMK7LV1=a+nGE55U#isoxHz;p_KaaN?%NbPlY1HBV+c@0aff$Lyso))rhtKjicbT~B7wnt`ybj8$ zS~C4|d5fp;P-uaR|5W)3hyjP`63R(ehLqf}*@aC{+&BZqkG(J)Gl^gF4AV>Q5R$nr zN%+Q)smN{%`MMwHzZae{iE_mU9l>krAB~JET%&xGK-#uizSXY&k|M9p$m*3eJ}wL@ z>jH}=O|QIC09$W0d$uNozHy3z%n>b+;~q{6{B%hl4y5J^x-G6w^=h-kVCS^opG`3j z!b+lSN|bL$swr=oLmcj;H+(KqRzO;5U=*4I#9ukoYnGTaJ~G}QrSCjzfw@?iZ>*yoqifu2d9i?$OD1<2HU&IHhglNm)P{XeDj|Fb8-6+yEqiA0Uuj9)KW#Bmn>SDHK3p8zP&Sve&R* zCW!4wZ0`AsTm9+`Vb5@9-$^(M`13!nazYCzU>X~Bfq($^*79Ei{Qn?+`%|m2qMjc9 zR}e=~z)5B_G}X%VO0I2HtqMU!ie#b%-P6;B1<2`s|ML6cCCX*og&g&ix^+hW$L@_C z$Lp>;4$D~>Y}7}IjFCeJ({046o%$LRqC!+X;#eRxWOds&b6hq)#D}Y>N=_#bYQJU= zyfG{fTDdL9HS-Eo^XW=(U1O&$QNsJt#k6&)Q~g@$G5#rb7cLAs+1|Oc9bnBsfoQv8 z6-8w6pAJeV@6n?Yj80y9-WgNqkQaj{HcdkLSvKw;^#7BbTX&Q`{T-13o?Kv>$@&%#PqQW}|D2G>dgm zxSM&oEhDC(ujw_)d-(vah2FOIsaZ3?a} zM%$A^FFJXU6PmP+99cLVr%5*Ddp+&Lf)2Xm)(nQCVYnI)NS%EkLwK{iSCA!fnJ8qi ztxsOfN3{VEGYwB4AXpi`kTbe)n5G-SA^J&68zm9K8cNJ;_|+Emv)at`DCFxJO!A$CcCIWVRpQe~zs9O>*N zqLF9iC%pb4@*E6Rlls;EH2>rlD%$?{Zh^U2U)gp6r+WHO`tu`{^Jb@TP2*_1$V&3X zs!{O-t`xnLPh;(dO{-$mA2@sUL<{E)RPQ^|XstC)8z+I|gmPf`z#w7BaZ3gB<;2d{ qh}`iLOB=POEd0es4Upp%<7MM{+BX-=_24)_2#a`~|CG^RANt?1+J=V! literal 0 HcmV?d00001 diff --git a/tests/ApplePayJS.Tests/localhost-dev.pfx b/tests/ApplePayJS.Tests/localhost-dev.pfx new file mode 100644 index 0000000000000000000000000000000000000000..c30b0ab537d213339599ad25809f18e392e31f51 GIT binary patch literal 4037 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 literal 0 HcmV?d00001 diff --git a/tests/ApplePayJS.Tests/testsettings.json b/tests/ApplePayJS.Tests/testsettings.json new file mode 100644 index 00000000..c4ee5e9b --- /dev/null +++ b/tests/ApplePayJS.Tests/testsettings.json @@ -0,0 +1,17 @@ +{ + "ApplePay": { + "DefaultLanguage": "en-GB", + "StoreName": "Test Store", + "UseCertificateStore": false, + "MerchantCertificateFileName": "applepay-dev.pfx", + "MerchantCertificatePassword": "Pa55w0rd!", + "UsePolyfill": true + }, + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft": "Warning", + "System": "Warning" + } + } +} diff --git a/tests/ApplePayJS.Tests/xunit.runner.json b/tests/ApplePayJS.Tests/xunit.runner.json new file mode 100644 index 00000000..1d280220 --- /dev/null +++ b/tests/ApplePayJS.Tests/xunit.runner.json @@ -0,0 +1,3 @@ +{ + "methodDisplay": "method" +} From 2497f29b7110eaef0517b465c3a4c610d84e1f38 Mon Sep 17 00:00:00 2001 From: martincostello Date: Mon, 16 Sep 2019 19:07:30 +0100 Subject: [PATCH 08/12] Update to ASP.NET Core 3.0 RC1 Update to release candidate 1 of ASP.NET Core 3.0. --- global.json | 2 +- tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index 79a76ed5..c33f6a5e 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.0.100-preview9-014004" + "version": "3.0.100-rc1-014190" } } diff --git a/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj b/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj index 94f6d0a3..2c003896 100644 --- a/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj +++ b/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj @@ -10,7 +10,7 @@ - + From 8bd24297d8ed34544168dc6357af363a9e7bf089 Mon Sep 17 00:00:00 2001 From: martincostello Date: Mon, 16 Sep 2019 19:13:33 +0100 Subject: [PATCH 09/12] Install .NET Core 2.2 SDK Install the .NET Core 2.2 SDK as a workaround for `dotnet bundle` until it supports running on .NET Core 3.0. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 397cb1f7..ff33f7bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ sudo: required dist: xenial +dotnet: 2.2 language: csharp mono: none From 21460a3b266538a6fb5e1b7d30ff95c6d912a951 Mon Sep 17 00:00:00 2001 From: martincostello Date: Mon, 23 Sep 2019 21:57:45 +0100 Subject: [PATCH 10/12] Update to ASP.NET Core 3.0 Update to the GA version of ASP.NET Core 3.0. --- global.json | 2 +- tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/global.json b/global.json index c33f6a5e..79422f0c 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.0.100-rc1-014190" + "version": "3.0.100" } } diff --git a/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj b/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj index 2c003896..c619c322 100644 --- a/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj +++ b/tests/ApplePayJS.Tests/ApplePayJS.Tests.csproj @@ -10,8 +10,8 @@ - - + + From 53529eae95129a12556e778613d494c183b62fd1 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sat, 5 Oct 2019 14:36:35 +0100 Subject: [PATCH 11/12] Install .NET Core 2.2 SDK for bundling Install the .NET Core 2.2 SDK until BundlerMinifier.Core supports .NET Core 3.0. --- .travis.yml | 1 - build.sh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ff33f7bd..397cb1f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ sudo: required dist: xenial -dotnet: 2.2 language: csharp mono: none diff --git a/build.sh b/build.sh index 8d05745d..32508e27 100755 --- a/build.sh +++ b/build.sh @@ -31,6 +31,7 @@ export PATH="$DOTNET_INSTALL_DIR:$PATH" dotnet_version=$(dotnet --version) if [ "$dotnet_version" != "$CLI_VERSION" ]; then + curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --version "2.2.402" --install-dir "$DOTNET_INSTALL_DIR" curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --version "$CLI_VERSION" --install-dir "$DOTNET_INSTALL_DIR" fi From 68574e75a7c64656094a63b2bab40e483b066aa4 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sat, 5 Oct 2019 14:48:58 +0100 Subject: [PATCH 12/12] Install Chrome for macOS Change Chrome installation to support macOS in Travis. --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 397cb1f7..c40737b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,13 +20,11 @@ addons: apt: packages: - gettext - - google-chrome-stable - libcurl4-openssl-dev - libicu-dev - libssl-dev - libunwind8 - sources: - - google-chrome + chrome: stable install: - npm install --global bower