diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 00000000..bc3d2998 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,29 @@ +name: Playwright Tests + +on: + repository_dispatch: + types: [playwright] + # schedule: + # - cron: '30 6 * * 1-5' + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Build + run: dotnet build src/UDS.Net.Web.MVC.Services.Test + + - name: Install Playwright + run: pwsh src/UDS.Net.Web.MVC.Services.Test/bin/Debug/net8.0/playwright.ps1 install --with-deps + + - name: Run tests + run: dotnet test src/UDS.Net.Web.MVC.Services.Test --no-build --verbosity normal \ No newline at end of file diff --git a/.gitignore b/.gitignore index d22f91a0..3b2a736a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .DS_Store appsettings.Development.json +[Pp]laywright/.auth # User-specific files *.rsuser diff --git a/README.md b/README.md index c8c5018b..b76ea81b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ The software is implemented with several .NET tools and includes a development c Thank you for interest in contributing to our project! There are many ways you can help: * Submit bugs and feature requests [here](Discussions) * Submit a fix by forking and submitting a PR Request [here](CONTRIBUTING.md) +* This solution includes automated tooling for linting, unit testing, and end-to-end testing. Powershell is required. Read more in our [wiki](https://github.com/UK-SBCoA/uniform-data-set-dotnet/wiki) ## Security [Security reports](SECURITY.md) diff --git a/src/UDS.Net.Web.MVC.Services.Test/HomepageTests.cs b/src/UDS.Net.Web.MVC.Services.Test/HomepageTests.cs new file mode 100644 index 00000000..5eaf6682 --- /dev/null +++ b/src/UDS.Net.Web.MVC.Services.Test/HomepageTests.cs @@ -0,0 +1,25 @@ +using Microsoft.Playwright; +using Microsoft.Playwright.MSTest; + +namespace UDS.Net.Web.MVC.Services.Test; + +[TestClass] +public class HomepageTests : PageTest +{ + [TestMethod] + public async Task HomepageHasNavigationToParticipations() + { + await Page.GotoAsync("/"); + + //var participation = Page.GetByRole(AriaRole.Link, new() { Name = "Participation" }); + + //await Expect(participation).ToHaveAttributeAsync("href", "/Participations"); + + //var createButton = Page.GetByRole(AriaRole.Link, new() { Name = "New participation" }); + + //await Expect(createButton).ToHaveAttributeAsync("href", "/Participations/Create"); + + //await participation.ClickAsync(); + } +} + diff --git a/src/UDS.Net.Web.MVC.Services.Test/Startup.cs b/src/UDS.Net.Web.MVC.Services.Test/Startup.cs new file mode 100644 index 00000000..2bf010d0 --- /dev/null +++ b/src/UDS.Net.Web.MVC.Services.Test/Startup.cs @@ -0,0 +1,27 @@ +using System; +using Microsoft.Playwright; +using Microsoft.Playwright.MSTest; + +namespace UDS.Net.Web.MVC.Services.Test +{ + public class Startup : PageTest + { + [TestInitialize] + public async Task TestInitialize() + { + await Page.GotoAsync("Identity/Account/Login?ReturnUrl=%2F"); + + var loginButton = Page.GetByRole(AriaRole.Link, new() { Name = "Login" }); + + if (loginButton != null) + { + + } + else + { + // already authenticated + } + } + } +} + diff --git a/src/UDS.Net.Web.MVC.Services.Test/UDS.Net.Web.MVC.Services.Test.csproj b/src/UDS.Net.Web.MVC.Services.Test/UDS.Net.Web.MVC.Services.Test.csproj new file mode 100644 index 00000000..9e1e2627 --- /dev/null +++ b/src/UDS.Net.Web.MVC.Services.Test/UDS.Net.Web.MVC.Services.Test.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + diff --git a/src/UDS.Net.Web.MVC.Services.Test/UnitTest1.cs b/src/UDS.Net.Web.MVC.Services.Test/UnitTest1.cs new file mode 100644 index 00000000..72a8323f --- /dev/null +++ b/src/UDS.Net.Web.MVC.Services.Test/UnitTest1.cs @@ -0,0 +1,29 @@ +using Microsoft.Playwright; +using Microsoft.Playwright.MSTest; + +namespace UDS.Net.Web.MVC.Services.Test; + +[TestClass] +public class ParticipationTests : PageTest +{ + [TestMethod] + public async Task ParticipationHasCreateButton() + { + await Page.GotoAsync("https://localhost:4811/Participations"); + + //var createButton = Page.GetByRole(AriaRole.Link, new() { Name = "New participation" }); + + //await Expect(createButton).ToHaveAttributeAsync("href", "/Create"); + + //createButton.ClickAsync(); + //await page.GetByLabel("NACC IdParticipation.LegacyId").ClickAsync(); + //await page.GetByLabel("NACC IdParticipation.LegacyId").FillAsync("2000"); + //await page.GetByRole(AriaRole.Button, new() { Name = "Save" }).ClickAsync(); + //await page.GetByLabel("NACC IdParticipation.LegacyId").ClickAsync(); + //await page.GetByLabel("NACC IdParticipation.LegacyId").FillAsync("2001"); + //await page.GetByRole(AriaRole.Button, new() { Name = "Save" }).ClickAsync(); + //await page.GetByLabel("NACC IdParticipation.LegacyId").ClickAsync(); + //await page.GetByLabel("NACC IdParticipation.LegacyId").FillAsync("5000"); + //await page.GetByRole(AriaRole.Button, new() { Name = "Save" }).ClickAsync(); + } +} diff --git a/src/UDS.Net.Web.MVC.Services.Test/appsettings.DEFAULT.json b/src/UDS.Net.Web.MVC.Services.Test/appsettings.DEFAULT.json new file mode 100644 index 00000000..593bede0 --- /dev/null +++ b/src/UDS.Net.Web.MVC.Services.Test/appsettings.DEFAULT.json @@ -0,0 +1,3 @@ +{ + "TestUrl": "https://localhost:4811" +} \ No newline at end of file diff --git a/src/UDS.Net.Web.MVC.Services.Test/appsettings.json b/src/UDS.Net.Web.MVC.Services.Test/appsettings.json new file mode 100644 index 00000000..19e338aa --- /dev/null +++ b/src/UDS.Net.Web.MVC.Services.Test/appsettings.json @@ -0,0 +1,3 @@ +{ + "TestUrl": "https://demo-uds.coa.uky.edu" +} \ No newline at end of file diff --git a/src/UDS.Net.sln b/src/UDS.Net.sln index eda02dfe..b284311f 100644 --- a/src/UDS.Net.sln +++ b/src/UDS.Net.sln @@ -9,13 +9,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDS.Net.Forms", "UDS.Net.Fo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDS.Net.Services", "UDS.Net.Services\UDS.Net.Services.csproj", "{BD35F74B-9134-46F3-850D-7DF05F7397E4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UDS.Net.Forms.Tests", "UDS.Net.Forms.Tests\UDS.Net.Forms.Tests.csproj", "{7A359BF3-B7F2-4962-A948-DAB0A996DA0F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDS.Net.Forms.Tests", "UDS.Net.Forms.Tests\UDS.Net.Forms.Tests.csproj", "{7A359BF3-B7F2-4962-A948-DAB0A996DA0F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDS.Net.Web.MVC.Services", "UDS.Net.Web.MVC.Services\UDS.Net.Web.MVC.Services.csproj", "{10B4A194-D9E4-491B-AF11-FF14F6108F5F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UDS.Net.Services.Test", "UDS.Net.Services.Test\UDS.Net.Services.Test.csproj", "{395296FB-4036-4FC9-A8DC-A50F96D35623}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDS.Net.Services.Test", "UDS.Net.Services.Test\UDS.Net.Services.Test.csproj", "{395296FB-4036-4FC9-A8DC-A50F96D35623}" EndProject -Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "docker-compose", "docker-compose.dcproj", "{C44B743C-B76C-41C1-BBB2-97AAC6B988BE}" +Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "docker-compose", "docker-compose.dcproj", "{EF687CA4-D15B-4E2F-97BA-64AAB218E395}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDS.Net.Web.MVC.Services.Test", "UDS.Net.Web.MVC.Services.Test\UDS.Net.Web.MVC.Services.Test.csproj", "{7879003A-AF57-4662-A66B-6A33FA09325C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -47,10 +49,14 @@ Global {395296FB-4036-4FC9-A8DC-A50F96D35623}.Debug|Any CPU.Build.0 = Debug|Any CPU {395296FB-4036-4FC9-A8DC-A50F96D35623}.Release|Any CPU.ActiveCfg = Release|Any CPU {395296FB-4036-4FC9-A8DC-A50F96D35623}.Release|Any CPU.Build.0 = Release|Any CPU - {C44B743C-B76C-41C1-BBB2-97AAC6B988BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C44B743C-B76C-41C1-BBB2-97AAC6B988BE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C44B743C-B76C-41C1-BBB2-97AAC6B988BE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C44B743C-B76C-41C1-BBB2-97AAC6B988BE}.Release|Any CPU.Build.0 = Release|Any CPU + {EF687CA4-D15B-4E2F-97BA-64AAB218E395}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF687CA4-D15B-4E2F-97BA-64AAB218E395}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF687CA4-D15B-4E2F-97BA-64AAB218E395}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF687CA4-D15B-4E2F-97BA-64AAB218E395}.Release|Any CPU.Build.0 = Release|Any CPU + {7879003A-AF57-4662-A66B-6A33FA09325C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7879003A-AF57-4662-A66B-6A33FA09325C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7879003A-AF57-4662-A66B-6A33FA09325C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7879003A-AF57-4662-A66B-6A33FA09325C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE