diff --git a/.github/workflows/dotnetCi.yml b/.github/workflows/dotnetCi.yml index 947f768e..0bfb8788 100644 --- a/.github/workflows/dotnetCi.yml +++ b/.github/workflows/dotnetCi.yml @@ -23,7 +23,7 @@ jobs: build_test_and_pack: name: Build, test & package - runs-on: ubuntu-slim + runs-on: ubuntu-24.04 timeout-minutes: 30 env: @@ -40,7 +40,7 @@ jobs: BranchParam: ${{ github.event_name == 'pull_request' && 'sonar.pullrequest.branch' || 'sonar.branch.name' }} PullRequestParam: ${{ github.event_name == 'pull_request' && format('/d:sonar.pullrequest.key={0}', github.event.number) || '' }} DISPLAY: :99 - + steps: - name: Checkout uses: actions/checkout@v4 @@ -68,10 +68,11 @@ jobs: with: java-version: 21 distribution: 'zulu' - - name: Install GUI packages so Chrome may run - run: | - sudo apt-get update - sudo apt install -y xorg xvfb gtk2-engines-pixbuf dbus-x11 xfonts-base xfonts-100dpi xfonts-75dpi xfonts-cyrillic xfonts-scalable psmisc + # See https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md + - name: Disable AppArmor restrictions so Chrome may run + run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns + - name: Start an Xvfb display so Chrome may run + run: Xvfb -ac $DISPLAY -screen 0 1280x1024x16 & # Environment setup pre-build @@ -79,8 +80,6 @@ jobs: run: | mkdir ~/.cache/selenium cp Tools/se-config.toml ~/.cache/selenium - - name: Start an Xvfb display so Chrome may run - run: Xvfb -ac $DISPLAY -screen 0 1280x1024x16 & - name: Restore .NET packages run: dotnet restore - name: Restore Node modules @@ -100,13 +99,13 @@ jobs: /d:sonar.host.url=${{ env.SonarCloudUrl }} /d:sonar.token=${{ env.SonarCloudSecretKey }} /d:${{ env.BranchParam }}=${{ env.BranchName }} ${{ env.PullRequestParam }} - /d:sonar.javascript.lcov.reportPaths=CSF.Screenplay.JsonToHtmlReport.Template/src/TestResults/lcov.info + /d:sonar.javascript.lcov.reportPaths=$PWD/CSF.Screenplay.JsonToHtmlReport.Template/src/TestResults/lcov.info /s:$PWD/.sonarqube-analysisproperties.xml - name: Build the solution run: dotnet build -c ${{ env.Configuration }} --no-incremental - name: Run .NET tests with coverage id: dotnet_tests - continue-on-error: true + shell: bash {0} run: | for proj in Tests/*.Tests do @@ -114,20 +113,24 @@ jobs: projName=${projNameArray[1]} assemblyPath=$proj/bin/$Configuration/$Tfm/$projName.dll coverlet "$assemblyPath" --target "dotnet" --targetargs "test $proj -c $Configuration --no-build --logger:nunit --test-adapter-path:." -f=opencover -o="TestResults/$projName.opencover.xml" - if [ $? -ne 0 ] + exitCode=$? + if [ $exitCode -ne 0 ] then - echo "failures=true" >> $GITHUB_OUTPUT + echo "One or more tests have failed; this build should eventually fail" + echo "failures=true" >> "$GITHUB_OUTPUT" fi done - name: Run JavaScript tests with coverage id: js_tests - continue-on-error: true + shell: bash {0} run: | cd CSF.Screenplay.JsonToHtmlReport.Template/src npm test - if [ $? -ne 0 ] + exitCode=$? + if [ $exitCode -ne 0 ] then - echo "failures=true" >> $GITHUB_OUTPUT + echo "One or more tests have failed; this build should eventually fail" + echo "failures=true" >> "$GITHUB_OUTPUT" fi cd ../.. @@ -139,11 +142,23 @@ jobs: - name: Gracefully stop Xvfb run: killall Xvfb continue-on-error: true - - name: Upload test results artifacts + - name: Upload .NET test results artifacts uses: actions/upload-artifact@v4 with: name: NUnit test results path: Tests/*.Tests/**/TestResults.xml + # This step won't produce any artifacts if the verbose factory isn't + # selected via appsettings.json in CSF.Screenplay.Selenium.Tests, but that's OK + - name: Upload verbose webdriver log artifacts + uses: actions/upload-artifact@v4 + with: + name: Verbose webdriver logs + path: '**/chrome-verbose-log.txt' + - name: Upload JS test results artifacts + uses: actions/upload-artifact@v4 + with: + name: Jest test results + path: CSF.Screenplay.JsonToHtmlReport.Template/src/TestResults/**/* - name: Upload Screenplay JSON report artifact uses: actions/upload-artifact@v4 with: @@ -164,7 +179,7 @@ jobs: name: Screenplay HTML reports path: Tests/**/ScreenplayReport.html - name: Fail the build if any test failures - if: ${{ steps.dotnet_tests.outputs.failures == 'true' || steps.js_tests.outputs.failures == 'true' }} + if: steps.dotnet_tests.outputs.failures == 'true' || steps.js_tests.outputs.failures == 'true' run: | echo "Failing the build due to test failures" exit 1 diff --git a/CSF.Screenplay.Docs/docfx.json b/CSF.Screenplay.Docs/docfx.json index c356164d..0c6b88cf 100644 --- a/CSF.Screenplay.Docs/docfx.json +++ b/CSF.Screenplay.Docs/docfx.json @@ -11,7 +11,8 @@ "**/obj/**", "Tests/**", "Old/**", - "CSF.Screenplay.JsonToHtmlReport.Template/**" + "CSF.Screenplay.JsonToHtmlReport.Template/**", + "CSF.Screenplay.SpecFlow/**" ] } ], diff --git a/Tests/CSF.Screenplay.Selenium.Tests/VerboseChromeDriverFactory.cs b/Tests/CSF.Screenplay.Selenium.Tests/VerboseChromeDriverFactory.cs new file mode 100644 index 00000000..adf5ab3c --- /dev/null +++ b/Tests/CSF.Screenplay.Selenium.Tests/VerboseChromeDriverFactory.cs @@ -0,0 +1,30 @@ +using System; +using CSF.Extensions.WebDriver.Factories; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; + +namespace CSF.Screenplay.Selenium; + +/// +/// An implementation of which writes verbose logs to a file. +/// +/// +/// +/// This driver factory is unused most of the time, but it's helpful if you're trying to diagnose problems with ChromeDriver, +/// say in a CI build that's been failing. Select this factory by changing the appsettings.json file and you'll get +/// log files. +/// +/// +public class VerboseChromeDriverFactory : ICreatesWebDriverFromOptions +{ + public WebDriverAndOptions GetWebDriver(WebDriverCreationOptions options, Action? supplementaryConfiguration = null) + { + var chromeOptions = (ChromeOptions) options.OptionsFactory(); + var service = ChromeDriverService.CreateDefaultService(); + service.EnableVerboseLogging = true; + service.LogPath = "chrome-verbose-log.txt"; + var driver = new ChromeDriver(service, chromeOptions); + + return new(driver, chromeOptions); + } +} \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Selenium.Tests/appsettings.json b/Tests/CSF.Screenplay.Selenium.Tests/appsettings.json index e0e48d58..2e931337 100644 --- a/Tests/CSF.Screenplay.Selenium.Tests/appsettings.json +++ b/Tests/CSF.Screenplay.Selenium.Tests/appsettings.json @@ -3,6 +3,10 @@ "DriverConfigurations": { "DefaultChrome": { "DriverType": "ChromeDriver" + }, + "VerboseChrome": { + "DriverType": "ChromeDriver", + "DriverFactoryType": "CSF.Screenplay.Selenium.VerboseChromeDriverFactory, CSF.Screenplay.Selenium.Tests" } }, "SelectedConfiguration": "DefaultChrome" diff --git a/Tools/se-config.toml b/Tools/se-config.toml index 6a3f8c5c..8c787990 100644 --- a/Tools/se-config.toml +++ b/Tools/se-config.toml @@ -8,5 +8,4 @@ # already installed. browser = "chrome" -force-browser-download = true browser-version = "stable" \ No newline at end of file