From 7fc85adf616469d5f53c5653d01644e56cefc612 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 11:39:22 -0400 Subject: [PATCH 01/95] Use `kebab` style arg Related: https://github.com/pypa/gh-action-pypi-publish/pull/125 --- .github/workflows/pytest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 50e80b837..ec1961032 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -186,7 +186,7 @@ jobs: with: user: __token__ password: ${{ secrets.PYPI_TEST_API_TOKEN }} - repository_url: https://test.pypi.org/legacy/ + repository-url: https://test.pypi.org/legacy/ ## prod deploy ---- - name: "Deploy to PyPI" From 63923bf4b29a98477e021683875ea5f39024d2e0 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 11:41:22 -0400 Subject: [PATCH 02/95] Move playwright tests from `pytest.yaml` to `end-to-end.yaml` --- .github/workflows/end-to-end.yaml | 117 ++++++++++++++++++++++++++++++ .github/workflows/pytest.yaml | 109 ---------------------------- 2 files changed, 117 insertions(+), 109 deletions(-) create mode 100644 .github/workflows/end-to-end.yaml diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml new file mode 100644 index 000000000..b1996e20c --- /dev/null +++ b/.github/workflows/end-to-end.yaml @@ -0,0 +1,117 @@ +name: End-to-End Tests + +on: + push: + branches: ["main", "rc-*"] + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + schedule: + - cron: "0 8 * * *" + workflow_dispatch: + +jobs: + playwright-shiny: + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] + os: [ubuntu-latest] + fail-fast: false + + steps: + - uses: actions/checkout@v4 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup + with: + python-version: ${{ matrix.python-version }} + + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + all-browsers: ${{ startsWith(github.head_ref, 'playwright') }} + - name: Display browser + shell: bash + run: echo '${{ steps.browsers.outputs.browsers }}' + - name: Run End-to-End tests + timeout-minutes: 20 + run: | + make playwright-shiny SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: "playright-shiny-${{ matrix.os }}-${{ matrix.python-version }}-results" + path: test-results/ + retention-days: 5 + + playwright-examples: + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] + os: [ubuntu-latest] + fail-fast: false + + steps: + - uses: actions/checkout@v4 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup + with: + python-version: ${{ matrix.python-version }} + + - name: Install node.js + uses: actions/setup-node@v4 + with: + node-version: "18" + cache: npm + cache-dependency-path: examples/brownian/shinymediapipe/package-lock.json + - name: Install node.js package + working-directory: examples/brownian/shinymediapipe + run: | + npm ci + + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + all-browsers: ${{ startsWith(github.head_ref, 'playwright') }} + - name: Run example app tests + timeout-minutes: 20 + run: | + make playwright-examples SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: "playright-examples-${{ matrix.os }}-${{ matrix.python-version }}-results" + path: test-results/ + retention-days: 5 + + playwright-deploys-precheck: + runs-on: ${{ matrix.os }} + strategy: + matrix: + # Matches deploy server python version + python-version: ["3.10"] + os: [ubuntu-latest] + fail-fast: false + + steps: + - uses: actions/checkout@v4 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup + with: + python-version: ${{ matrix.python-version }} + + - name: Test that deployable example apps work + timeout-minutes: 5 # ~10s locally + env: + DEPLOY_APPS: "false" + run: | + make playwright-deploys SUB_FILE=". -vv" + + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: "playright-examples-${{ matrix.os }}-${{ matrix.python-version }}-results" + path: test-results/ + retention-days: 5 diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index ec1961032..9298d5c58 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -49,115 +49,6 @@ jobs: run: | make check-format - playwright-shiny: - runs-on: ${{ matrix.os }} - if: github.event_name != 'release' - strategy: - matrix: - python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] - os: [ubuntu-latest] - fail-fast: false - - steps: - - uses: actions/checkout@v4 - - name: Setup py-shiny - uses: ./.github/py-shiny/setup - with: - python-version: ${{ matrix.python-version }} - - - name: Determine browsers for testing - uses: ./.github/py-shiny/pytest-browsers - id: browsers - with: - all-browsers: ${{ startsWith(github.head_ref, 'playwright') }} - - name: Display browser - shell: bash - run: echo '${{ steps.browsers.outputs.browsers }}' - - name: Run End-to-End tests - timeout-minutes: 20 - run: | - make playwright-shiny SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: "playright-shiny-${{ matrix.os }}-${{ matrix.python-version }}-results" - path: test-results/ - retention-days: 5 - - playwright-examples: - runs-on: ${{ matrix.os }} - if: github.event_name != 'release' - strategy: - matrix: - python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] - os: [ubuntu-latest] - fail-fast: false - - steps: - - uses: actions/checkout@v4 - - name: Setup py-shiny - uses: ./.github/py-shiny/setup - with: - python-version: ${{ matrix.python-version }} - - - name: Install node.js - uses: actions/setup-node@v4 - with: - node-version: "18" - cache: npm - cache-dependency-path: examples/brownian/shinymediapipe/package-lock.json - - name: Install node.js package - working-directory: examples/brownian/shinymediapipe - run: | - npm ci - - - name: Determine browsers for testing - uses: ./.github/py-shiny/pytest-browsers - id: browsers - with: - all-browsers: ${{ startsWith(github.head_ref, 'playwright') }} - - name: Run example app tests - timeout-minutes: 20 - run: | - make playwright-examples SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: "playright-examples-${{ matrix.os }}-${{ matrix.python-version }}-results" - path: test-results/ - retention-days: 5 - - playwright-deploys-precheck: - if: github.event_name != 'release' - runs-on: ${{ matrix.os }} - strategy: - matrix: - # Matches deploy server python version - python-version: ["3.10"] - os: [ubuntu-latest] - fail-fast: false - - steps: - - uses: actions/checkout@v4 - - name: Setup py-shiny - uses: ./.github/py-shiny/setup - with: - python-version: ${{ matrix.python-version }} - - - name: Test that deployable example apps work - timeout-minutes: 5 # ~10s locally - env: - DEPLOY_APPS: "false" - run: | - make playwright-deploys SUB_FILE=". -vv" - - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: "playright-examples-${{ matrix.os }}-${{ matrix.python-version }}-results" - path: test-results/ - retention-days: 5 - pypi: name: "Deploy to PyPI" runs-on: ubuntu-latest From 3d8ef6e9ab8e4a25a36efe75ea1ca57059227c76 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 14:28:20 -0400 Subject: [PATCH 03/95] Reduce jobs created if status is draft. Test full --- .github/py-shiny/pytest-browsers/action.yaml | 15 +++++ .github/workflows/end-to-end.yaml | 59 +++++++++++++++++--- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/.github/py-shiny/pytest-browsers/action.yaml b/.github/py-shiny/pytest-browsers/action.yaml index b9f470277..8c4d3034f 100644 --- a/.github/py-shiny/pytest-browsers/action.yaml +++ b/.github/py-shiny/pytest-browsers/action.yaml @@ -1,6 +1,10 @@ name: 'Custom merge queue browsers' description: 'Trim down pytest browsers for any github event other than merge_group.' inputs: + browser: + description: 'Browser to use for testing' + required: false + default: '' all-browsers: description: 'Force all pytest browsers to used when testing' required: false @@ -16,6 +20,17 @@ runs: shell: bash id: browsers run: | + if [ "${{ inputs.browser }}" != "" ]; then + BROWSER="${{ inputs.browser }}" + if [ "$BROWSER" == "chromium" ] || [ "$BROWSER" == "firefox" ] || [ "$BROWSER" == "webkit" ]; then + echo "Using custom browser $BROWSER !" + echo 'browsers=PYTEST_BROWSERS="--browser $BROWSER"' >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "Unknown browser: $BROWSER" + exit 1 + fi + if [ "${{ inputs.all-browsers }}" == "true" ]; then echo "Using all browsers!" exit 0 diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index b1996e20c..fe551db88 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -10,12 +10,44 @@ on: workflow_dispatch: jobs: + setup: + runs-on: ubuntu-latest + outputs: + is-draft: ${{ steps.is-draft.outputs.value }} + python-versions: ${{ steps.python-versions.outputs.values }} + browsers: ${{ steps.browsers.outputs.values }} + steps: + - name: Is Draft + id: is-draft + run: | + echo 'value=${{ github.event.pull_request.draft }}' > $GITHUB_OUTPUT + + - name: Python versions + id: python-versions + run: | + if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then + echo 'values=["3.12", "3.11", "3.10", "3.9", "3.8"]' > $GITHUB_OUTPUT + else + echo 'values=["3.12", "3.8"]' > $GITHUB_OUTPUT + fi + + - name: Browsers + id: browsers + run: | + if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then + echo 'values=["chromium", "firefox", "webkit"]' > $GITHUB_OUTPUT + else + echo 'values=["chromium"]' > $GITHUB_OUTPUT + fi + playwright-shiny: runs-on: ${{ matrix.os }} + needs: [setup] strategy: matrix: - python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] os: [ubuntu-latest] + python-version: ${{ fromJson(needs.setup.outputs.python-versions) }} + browser: ${{ fromJson(needs.setup.outputs.browsers) }} fail-fast: false steps: @@ -29,7 +61,9 @@ jobs: uses: ./.github/py-shiny/pytest-browsers id: browsers with: - all-browsers: ${{ startsWith(github.head_ref, 'playwright') }} + browser: ${{ matrix.browser }} + + # TODO-barret remove - name: Display browser shell: bash run: echo '${{ steps.browsers.outputs.browsers }}' @@ -46,10 +80,12 @@ jobs: playwright-examples: runs-on: ${{ matrix.os }} + needs: [setup] strategy: matrix: - python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] os: [ubuntu-latest] + python-version: ${{ fromJson(needs.setup.outputs.python-versions) }} + browser: ${{ fromJson(needs.setup.outputs.browsers) }} fail-fast: false steps: @@ -58,6 +94,11 @@ jobs: uses: ./.github/py-shiny/setup with: python-version: ${{ matrix.python-version }} + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + browser: ${{ matrix.browser }} - name: Install node.js uses: actions/setup-node@v4 @@ -70,11 +111,6 @@ jobs: run: | npm ci - - name: Determine browsers for testing - uses: ./.github/py-shiny/pytest-browsers - id: browsers - with: - all-browsers: ${{ startsWith(github.head_ref, 'playwright') }} - name: Run example app tests timeout-minutes: 20 run: | @@ -88,11 +124,13 @@ jobs: playwright-deploys-precheck: runs-on: ${{ matrix.os }} + needs: [setup] strategy: matrix: # Matches deploy server python version python-version: ["3.10"] os: [ubuntu-latest] + browser: ${{ fromJson(needs.setup.outputs.browsers) }} fail-fast: false steps: @@ -101,6 +139,11 @@ jobs: uses: ./.github/py-shiny/setup with: python-version: ${{ matrix.python-version }} + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + all-browsers: ${{ ! needs.setup.outputs.is-draft }} - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally From 4a6281f57e3cdb211ffa38144f67865173a46de4 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 14:29:20 -0400 Subject: [PATCH 04/95] Update end-to-end.yaml --- .github/workflows/end-to-end.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index fe551db88..84d08aed7 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -67,6 +67,7 @@ jobs: - name: Display browser shell: bash run: echo '${{ steps.browsers.outputs.browsers }}' + - name: Run End-to-End tests timeout-minutes: 20 run: | From a2e1a710cc920f036c2ca62170ee12f0ddc41c2d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 14:45:49 -0400 Subject: [PATCH 05/95] bash quote typo --- .github/py-shiny/pytest-browsers/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/py-shiny/pytest-browsers/action.yaml b/.github/py-shiny/pytest-browsers/action.yaml index 8c4d3034f..69f6b56ce 100644 --- a/.github/py-shiny/pytest-browsers/action.yaml +++ b/.github/py-shiny/pytest-browsers/action.yaml @@ -24,7 +24,7 @@ runs: BROWSER="${{ inputs.browser }}" if [ "$BROWSER" == "chromium" ] || [ "$BROWSER" == "firefox" ] || [ "$BROWSER" == "webkit" ]; then echo "Using custom browser $BROWSER !" - echo 'browsers=PYTEST_BROWSERS="--browser $BROWSER"' >> "$GITHUB_OUTPUT" + echo "browsers=PYTEST_BROWSERS=\"--browser $BROWSER\"" >> "$GITHUB_OUTPUT" exit 0 fi echo "Unknown browser: $BROWSER" From e32b840a62805b9870459a918c7cba549a45d44a Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 14:46:04 -0400 Subject: [PATCH 06/95] Actually test on os value --- .github/workflows/pytest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 9298d5c58..fdb7e6bfb 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -13,7 +13,7 @@ on: jobs: check: - runs-on: ubuntu-latest + runs-on: matrix.os strategy: matrix: # "3.10" must be a string; otherwise it is interpreted as 3.1. From 5260d98bca4938a7d5ad813f449dc9215da7b67e Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 14:46:21 -0400 Subject: [PATCH 07/95] Add os value support --- .github/workflows/end-to-end.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 84d08aed7..8be309fd7 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -14,6 +14,7 @@ jobs: runs-on: ubuntu-latest outputs: is-draft: ${{ steps.is-draft.outputs.value }} + os-versions: ${{ steps.os-versions.outputs.values }} python-versions: ${{ steps.python-versions.outputs.values }} browsers: ${{ steps.browsers.outputs.values }} steps: @@ -22,6 +23,15 @@ jobs: run: | echo 'value=${{ github.event.pull_request.draft }}' > $GITHUB_OUTPUT + - name: OS versions + id: os-versions + run: | + if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then + echo 'values=["ubuntu-latest", "windows-latest", "macOS-latest"]' > $GITHUB_OUTPUT + else + echo 'values=["ubuntu-latest"]' > $GITHUB_OUTPUT + fi + - name: Python versions id: python-versions run: | From 2dde152e284b933d17167e4f5d19982d64aeb955 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 14:47:44 -0400 Subject: [PATCH 08/95] debug if inline if values are converted to boolean or the value is kept --- .github/workflows/end-to-end.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 8be309fd7..353884180 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -58,6 +58,7 @@ jobs: os: [ubuntu-latest] python-version: ${{ fromJson(needs.setup.outputs.python-versions) }} browser: ${{ fromJson(needs.setup.outputs.browsers) }} + barret: ${{ (needs.setup.outputs.is-draft || fromJson('[1,2]')) || fromJson('[3,4]') }} fail-fast: false steps: From 0ba8293b3da4e6f8355d3429ebc34a1fc9eabee7 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:05:13 -0400 Subject: [PATCH 09/95] Try using exclusion approach to avoid needing config pre-job Related: https://stackoverflow.com/a/73822998/591574 --- .github/workflows/end-to-end.yaml | 132 ++++++++++++++++-------------- 1 file changed, 71 insertions(+), 61 deletions(-) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 353884180..70b6b3ac5 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -10,55 +10,61 @@ on: workflow_dispatch: jobs: - setup: + # config: + # runs-on: ubuntu-latest + # outputs: + # is-draft: ${{ steps.is-draft.outputs.value }} + # os-versions: ${{ steps.os-versions.outputs.values }} + # python-versions: ${{ steps.python-versions.outputs.values }} + # browsers: ${{ steps.browsers.outputs.values }} + # steps: + # - name: Is Draft + # id: is-draft + # run: | + # echo 'value=${{ github.event.pull_request.draft }}' > $GITHUB_OUTPUT + + # - name: OS versions + # id: os-versions + # run: | + # if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then + # echo 'values=["ubuntu-latest", "windows-latest", "macOS-latest"]' > $GITHUB_OUTPUT + # else + # echo 'values=["ubuntu-latest"]' > $GITHUB_OUTPUT + # fi + + # - name: Python versions + # id: python-versions + # run: | + # if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then + # echo 'values=["3.12", "3.11", "3.10", "3.9", "3.8"]' > $GITHUB_OUTPUT + # else + # echo 'values=["3.12", "3.8"]' > $GITHUB_OUTPUT + # fi + + # - name: Browsers + # id: browsers + # run: | + # if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then + # echo 'values=["chromium", "firefox", "webkit"]' > $GITHUB_OUTPUT + # else + # echo 'values=["chromium"]' > $GITHUB_OUTPUT + # fi + + e2e-shiny: runs-on: ubuntu-latest - outputs: - is-draft: ${{ steps.is-draft.outputs.value }} - os-versions: ${{ steps.os-versions.outputs.values }} - python-versions: ${{ steps.python-versions.outputs.values }} - browsers: ${{ steps.browsers.outputs.values }} - steps: - - name: Is Draft - id: is-draft - run: | - echo 'value=${{ github.event.pull_request.draft }}' > $GITHUB_OUTPUT - - - name: OS versions - id: os-versions - run: | - if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then - echo 'values=["ubuntu-latest", "windows-latest", "macOS-latest"]' > $GITHUB_OUTPUT - else - echo 'values=["ubuntu-latest"]' > $GITHUB_OUTPUT - fi - - - name: Python versions - id: python-versions - run: | - if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then - echo 'values=["3.12", "3.11", "3.10", "3.9", "3.8"]' > $GITHUB_OUTPUT - else - echo 'values=["3.12", "3.8"]' > $GITHUB_OUTPUT - fi - - - name: Browsers - id: browsers - run: | - if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then - echo 'values=["chromium", "firefox", "webkit"]' > $GITHUB_OUTPUT - else - echo 'values=["chromium"]' > $GITHUB_OUTPUT - fi - - playwright-shiny: - runs-on: ${{ matrix.os }} - needs: [setup] + # needs: [config] strategy: matrix: - os: [ubuntu-latest] - python-version: ${{ fromJson(needs.setup.outputs.python-versions) }} - browser: ${{ fromJson(needs.setup.outputs.browsers) }} - barret: ${{ (needs.setup.outputs.is-draft || fromJson('[1,2]')) || fromJson('[3,4]') }} + # python-version: ${{ fromJson(needs.config.outputs.python-versions) }} + # browser: ${{ fromJson(needs.config.outputs.browsers) }} + python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] + browser: ["chromium", "firefox", "webkit"] + exclude: + - python-version: ${{ github.event.pull_request.draft && '3.11' }} + - python-version: ${{ github.event.pull_request.draft && '3.10' }} + - python-version: ${{ github.event.pull_request.draft && '3.9' }} + - browser: ${{ github.event.pull_request.draft && 'firefox' }} + - browser: ${{ github.event.pull_request.draft && 'webkit' }} fail-fast: false steps: @@ -86,18 +92,25 @@ jobs: - uses: actions/upload-artifact@v4 if: failure() with: - name: "playright-shiny-${{ matrix.os }}-${{ matrix.python-version }}-results" + name: "playright-shiny-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" path: test-results/ retention-days: 5 - playwright-examples: - runs-on: ${{ matrix.os }} - needs: [setup] + e2e-examples: + runs-on: ubuntu-latest + # needs: [config] strategy: matrix: - os: [ubuntu-latest] - python-version: ${{ fromJson(needs.setup.outputs.python-versions) }} - browser: ${{ fromJson(needs.setup.outputs.browsers) }} + # python-version: ${{ fromJson(needs.config.outputs.python-versions) }} + # browser: ${{ fromJson(needs.config.outputs.browsers) }} + python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] + browser: ["chromium", "firefox", "webkit"] + exclude: + - python-version: ${{ github.event.pull_request.draft && '3.11' }} + - python-version: ${{ github.event.pull_request.draft && '3.10' }} + - python-version: ${{ github.event.pull_request.draft && '3.9' }} + - browser: ${{ github.event.pull_request.draft && 'firefox' }} + - browser: ${{ github.event.pull_request.draft && 'webkit' }} fail-fast: false steps: @@ -130,19 +143,16 @@ jobs: - uses: actions/upload-artifact@v4 if: failure() with: - name: "playright-examples-${{ matrix.os }}-${{ matrix.python-version }}-results" + name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" path: test-results/ retention-days: 5 - playwright-deploys-precheck: - runs-on: ${{ matrix.os }} - needs: [setup] + e2e-deploys-precheck: + runs-on: ubuntu-latest strategy: matrix: # Matches deploy server python version python-version: ["3.10"] - os: [ubuntu-latest] - browser: ${{ fromJson(needs.setup.outputs.browsers) }} fail-fast: false steps: @@ -155,7 +165,7 @@ jobs: uses: ./.github/py-shiny/pytest-browsers id: browsers with: - all-browsers: ${{ ! needs.setup.outputs.is-draft }} + all-browsers: ${{ ! github.event.pull_request.draft }} - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally @@ -167,6 +177,6 @@ jobs: - uses: actions/upload-artifact@v4 if: failure() with: - name: "playright-examples-${{ matrix.os }}-${{ matrix.python-version }}-results" + name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-results" path: test-results/ retention-days: 5 From 6aea30d4e5a1b9c1e23c49d2364b2e6365e92116 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:10:35 -0400 Subject: [PATCH 10/95] Update end-to-end.yaml --- .github/workflows/end-to-end.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 70b6b3ac5..2151141bc 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -50,7 +50,7 @@ jobs: # echo 'values=["chromium"]' > $GITHUB_OUTPUT # fi - e2e-shiny: + playwright-shiny: runs-on: ubuntu-latest # needs: [config] strategy: @@ -96,7 +96,7 @@ jobs: path: test-results/ retention-days: 5 - e2e-examples: + playwright-examples: runs-on: ubuntu-latest # needs: [config] strategy: @@ -147,7 +147,7 @@ jobs: path: test-results/ retention-days: 5 - e2e-deploys-precheck: + playwright-deploys-precheck: runs-on: ubuntu-latest strategy: matrix: From 39512c8047145fe41e4e341331dfd0195b92ac57 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:11:12 -0400 Subject: [PATCH 11/95] Exclude macos and windows and py 3.9, 3.10, 3.11 on draft --- .github/workflows/pytest.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index fdb7e6bfb..74e85c7dc 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -19,6 +19,13 @@ jobs: # "3.10" must be a string; otherwise it is interpreted as 3.1. python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] os: [ubuntu-latest, windows-latest, macOS-latest] + exclude: + - python-version: ${{ github.event.pull_request.draft && '3.11' }} + - python-version: ${{ github.event.pull_request.draft && '3.10' }} + - python-version: ${{ github.event.pull_request.draft && '3.9' }} + - os: ${{ github.event.pull_request.draft && 'windows-latest' }} + - os: ${{ github.event.pull_request.draft && 'macOS-latest' }} + fail-fast: false steps: From 82964778834bad42c0f4f5420825baa0d97dd58d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:20:31 -0400 Subject: [PATCH 12/95] Update pytest.yaml --- .github/workflows/pytest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 74e85c7dc..e76cf1afb 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -13,7 +13,7 @@ on: jobs: check: - runs-on: matrix.os + runs-on: ${{ matrix.os }} strategy: matrix: # "3.10" must be a string; otherwise it is interpreted as 3.1. From a86e385734f509a79f7b03d504e73589857cc4ce Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:26:56 -0400 Subject: [PATCH 13/95] Try installing packags via `uv` and not `pip` --- .github/py-shiny/setup/action.yaml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 0b507a22f..7c438de1d 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -21,29 +21,34 @@ runs: shell: bash run: python -m pip install --upgrade pip + - name: Install `uv` + shell: bash + run: | + pip install uv + - name: Pip list shell: bash run: | - pip list + uv pip list - name: Install dependencies shell: bash run: | - pip install https://github.com/rstudio/py-htmltools/tarball/main + uv pip install https://github.com/rstudio/py-htmltools/tarball/main make install-deps - name: Install shell: bash run: | - make install + uv pip install -e ".[dev,test]" - name: Install backports.tarfile if: ${{ startsWith(inputs.python-version, '3.8') }} shell: bash run: | - pip install backports.tarfile + uv pip install backports.tarfile - name: Pip list shell: bash run: | - pip list + uv pip list From 2ad4c03ba1529b3328a2fa7297717a83623e34f0 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:35:54 -0400 Subject: [PATCH 14/95] Add a virtual environment and enable it before calling `make` commands --- .github/py-shiny/setup/action.yaml | 9 ++++++++- .github/workflows/deploy-tests.yaml | 2 ++ .github/workflows/end-to-end.yaml | 2 ++ .github/workflows/pytest.yaml | 4 ++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 7c438de1d..54d302c8d 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -26,6 +26,11 @@ runs: run: | pip install uv + - name: Create virtual environment + shell: bash + run: | + uv venv + - name: Pip list shell: bash run: | @@ -35,12 +40,14 @@ runs: shell: bash run: | uv pip install https://github.com/rstudio/py-htmltools/tarball/main + source .venv/bin/activate make install-deps - name: Install shell: bash run: | - uv pip install -e ".[dev,test]" + source .venv/bin/activate + make install - name: Install backports.tarfile if: ${{ startsWith(inputs.python-version, '3.8') }} diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 5a68555a8..7ca8240a4 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -30,6 +30,7 @@ jobs: env: DEPLOY_APPS: "false" run: | + source .venv/bin/activate make playwright-deploys SUB_FILE=". -vv" - name: Deploy apps and run tests (on `push` or `deploy**` branches) @@ -44,6 +45,7 @@ jobs: # Given we are waiting for external servers to finish, # we can have many local processes waiting for deployment to finish run: | + source .venv/bin/activate make playwright-deploys SUB_FILE=". -vv --numprocesses 12" - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 2151141bc..1761f5024 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -88,6 +88,7 @@ jobs: - name: Run End-to-End tests timeout-minutes: 20 run: | + source .venv/bin/activate make playwright-shiny SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() @@ -139,6 +140,7 @@ jobs: - name: Run example app tests timeout-minutes: 20 run: | + source .venv/bin/activate make playwright-examples SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index e76cf1afb..70d5819de 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -39,21 +39,25 @@ jobs: - name: Run unit tests if: steps.install.outcome == 'success' && (success() || failure()) run: | + source .venv/bin/activate make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) run: | + source .venv/bin/activate make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) run: | + source .venv/bin/activate make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) run: | + source .venv/bin/activate make check-format pypi: From 51181289c2d2f4c3874cc8af0d28277926aa2410 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:36:00 -0400 Subject: [PATCH 15/95] Update end-to-end.yaml --- .github/workflows/end-to-end.yaml | 51 ------------------------------- 1 file changed, 51 deletions(-) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 1761f5024..c89c09cc7 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -10,53 +10,10 @@ on: workflow_dispatch: jobs: - # config: - # runs-on: ubuntu-latest - # outputs: - # is-draft: ${{ steps.is-draft.outputs.value }} - # os-versions: ${{ steps.os-versions.outputs.values }} - # python-versions: ${{ steps.python-versions.outputs.values }} - # browsers: ${{ steps.browsers.outputs.values }} - # steps: - # - name: Is Draft - # id: is-draft - # run: | - # echo 'value=${{ github.event.pull_request.draft }}' > $GITHUB_OUTPUT - - # - name: OS versions - # id: os-versions - # run: | - # if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then - # echo 'values=["ubuntu-latest", "windows-latest", "macOS-latest"]' > $GITHUB_OUTPUT - # else - # echo 'values=["ubuntu-latest"]' > $GITHUB_OUTPUT - # fi - - # - name: Python versions - # id: python-versions - # run: | - # if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then - # echo 'values=["3.12", "3.11", "3.10", "3.9", "3.8"]' > $GITHUB_OUTPUT - # else - # echo 'values=["3.12", "3.8"]' > $GITHUB_OUTPUT - # fi - - # - name: Browsers - # id: browsers - # run: | - # if [[ ${{ steps.is-draft.outputs.value }} == "true" ]]; then - # echo 'values=["chromium", "firefox", "webkit"]' > $GITHUB_OUTPUT - # else - # echo 'values=["chromium"]' > $GITHUB_OUTPUT - # fi - playwright-shiny: runs-on: ubuntu-latest - # needs: [config] strategy: matrix: - # python-version: ${{ fromJson(needs.config.outputs.python-versions) }} - # browser: ${{ fromJson(needs.config.outputs.browsers) }} python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] browser: ["chromium", "firefox", "webkit"] exclude: @@ -80,11 +37,6 @@ jobs: with: browser: ${{ matrix.browser }} - # TODO-barret remove - - name: Display browser - shell: bash - run: echo '${{ steps.browsers.outputs.browsers }}' - - name: Run End-to-End tests timeout-minutes: 20 run: | @@ -99,11 +51,8 @@ jobs: playwright-examples: runs-on: ubuntu-latest - # needs: [config] strategy: matrix: - # python-version: ${{ fromJson(needs.config.outputs.python-versions) }} - # browser: ${{ fromJson(needs.config.outputs.browsers) }} python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] browser: ["chromium", "firefox", "webkit"] exclude: From f3dfadf3891c45c0d7dba873f05d74779f9d64c9 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:38:06 -0400 Subject: [PATCH 16/95] Update action.yaml --- .github/py-shiny/setup/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 54d302c8d..168bf0ef5 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -39,7 +39,7 @@ runs: - name: Install dependencies shell: bash run: | - uv pip install https://github.com/rstudio/py-htmltools/tarball/main + uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" source .venv/bin/activate make install-deps From 617c229399361a29a897a4dabe7a1496044f6e15 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:46:57 -0400 Subject: [PATCH 17/95] Call `make` commands directly --- .github/py-shiny/setup/action.yaml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 168bf0ef5..b823af99c 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -43,11 +43,29 @@ runs: source .venv/bin/activate make install-deps + - name: Pip list + shell: bash + run: | + uv pip list + - name: Install shell: bash run: | + # make install + source .venv/bin/activate - make install + + make clean + + # make dist + uv pip install setuptools + python setup.py sdist + python setup.py bdist_wheel + ls -l dist + + # make install + uv pip uninstall -y shiny + uv pip install dist/shiny*.whl - name: Install backports.tarfile if: ${{ startsWith(inputs.python-version, '3.8') }} From 5afc91e069e999f7be13902d1307b357cedefbde Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:49:24 -0400 Subject: [PATCH 18/95] Update action.yaml --- .github/py-shiny/setup/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index b823af99c..d55ca1bd1 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -64,7 +64,7 @@ runs: ls -l dist # make install - uv pip uninstall -y shiny + uv pip uninstall shiny uv pip install dist/shiny*.whl - name: Install backports.tarfile From 4be84fb8a8de69159446aa2614e9abf3c177f9d9 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 15:58:26 -0400 Subject: [PATCH 19/95] Try activating and calling make --- .github/py-shiny/setup/action.yaml | 3 ++- .github/workflows/pytest.yaml | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index d55ca1bd1..a4fb09c35 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -41,7 +41,8 @@ runs: run: | uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" source .venv/bin/activate - make install-deps + # make install-deps + uv pip install -e ".[dev,test]" - name: Pip list shell: bash diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 70d5819de..ef95c311b 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -39,26 +39,26 @@ jobs: - name: Run unit tests if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate - make check-tests + source .venv/bin/activate && \ + make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate - make check-types + source .venv/bin/activate && \ + make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate - make check-lint + source .venv/bin/activate && \ + make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate - make check-format + source .venv/bin/activate && \ + make check-format pypi: name: "Deploy to PyPI" From daddcfe7995258767433af3cca3a6f2cf6d7ef74 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:01:16 -0400 Subject: [PATCH 20/95] Update action.yaml --- .github/py-shiny/setup/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index a4fb09c35..12519a9f1 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -56,7 +56,7 @@ runs: source .venv/bin/activate - make clean + # make clean # make dist uv pip install setuptools From af6af507566bc0a40e847d1acfc7bc24cb9d25ae Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:21:34 -0400 Subject: [PATCH 21/95] Update action.yaml --- .github/py-shiny/setup/action.yaml | 37 +++++++++++------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 12519a9f1..91df7033e 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -31,42 +31,33 @@ runs: run: | uv venv - - name: Pip list - shell: bash - run: | - uv pip list - - name: Install dependencies shell: bash run: | uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" - source .venv/bin/activate - # make install-deps - uv pip install -e ".[dev,test]" - - name: Pip list - shell: bash - run: | - uv pip list + source .venv/bin/activate && \ + make install-deps - name: Install shell: bash run: | - # make install + source .venv/bin/activate && \ + make install - source .venv/bin/activate + # source .venv/bin/activate - # make clean + # # make clean - # make dist - uv pip install setuptools - python setup.py sdist - python setup.py bdist_wheel - ls -l dist + # # make dist + # uv pip install setuptools + # python setup.py sdist + # python setup.py bdist_wheel + # ls -l dist - # make install - uv pip uninstall shiny - uv pip install dist/shiny*.whl + # # make install + # uv pip uninstall shiny + # uv pip install dist/shiny*.whl - name: Install backports.tarfile if: ${{ startsWith(inputs.python-version, '3.8') }} From bf36cd3e7f80c614d6bf5876213727c409df5b33 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:25:10 -0400 Subject: [PATCH 22/95] Update action.yaml --- .github/py-shiny/setup/action.yaml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 91df7033e..d55af5edb 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -29,35 +29,35 @@ runs: - name: Create virtual environment shell: bash run: | - uv venv + uv venv venv - name: Install dependencies shell: bash run: | uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" - source .venv/bin/activate && \ + source venv/bin/activate && \ make install-deps - name: Install shell: bash run: | - source .venv/bin/activate && \ - make install + # source venv/bin/activate && \ + # make install - # source .venv/bin/activate + source venv/bin/activate - # # make clean + # make clean - # # make dist - # uv pip install setuptools - # python setup.py sdist - # python setup.py bdist_wheel - # ls -l dist + # make dist + uv pip install setuptools + python setup.py sdist + python setup.py bdist_wheel + ls -l dist - # # make install - # uv pip uninstall shiny - # uv pip install dist/shiny*.whl + # make install + uv pip uninstall shiny + uv pip install dist/shiny*.whl - name: Install backports.tarfile if: ${{ startsWith(inputs.python-version, '3.8') }} From b4f72a6089f7badaa1e6da7359a99a3663f42827 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:25:53 -0400 Subject: [PATCH 23/95] Use `venv` folder for docs --- .github/workflows/build-docs.yaml | 18 ++++++++---------- .github/workflows/deploy-tests.yaml | 8 ++++---- .github/workflows/end-to-end.yaml | 8 ++++---- .github/workflows/pytest.yaml | 8 ++++---- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index f0b3c670d..9a344d71c 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -18,14 +18,11 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup with: python-version: ${{ matrix.python-version }} - - name: Upgrade pip - run: python -m pip install --upgrade pip - # ===================================================== # API docs # ===================================================== @@ -36,14 +33,15 @@ jobs: - name: Install dependencies run: | - cd docs - make ../venv - make deps + . venv/bin/activate && \ + uv pip install -e ".[dev,test,doc]" \ + "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ + "shinylive @ git+https://github.com/posit-dev/py-shinylive.git" - name: Run quartodoc run: | - cd docs - make quartodoc + . venv/bin/activate && \ + make docs-quartodoc # ===================================================== # Shinylive diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 7ca8240a4..99515e305 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -30,8 +30,8 @@ jobs: env: DEPLOY_APPS: "false" run: | - source .venv/bin/activate - make playwright-deploys SUB_FILE=". -vv" + source venv/bin/activate && \ + make playwright-deploys SUB_FILE=". -vv" - name: Deploy apps and run tests (on `push` or `deploy**` branches) env: @@ -45,8 +45,8 @@ jobs: # Given we are waiting for external servers to finish, # we can have many local processes waiting for deployment to finish run: | - source .venv/bin/activate - make playwright-deploys SUB_FILE=". -vv --numprocesses 12" + source venv/bin/activate && \ + make playwright-deploys SUB_FILE=". -vv --numprocesses 12" - uses: actions/upload-artifact@v4 if: failure() diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index c89c09cc7..a48df4883 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -40,8 +40,8 @@ jobs: - name: Run End-to-End tests timeout-minutes: 20 run: | - source .venv/bin/activate - make playwright-shiny SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} + source venv/bin/activate && \ + make playwright-shiny SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: @@ -89,8 +89,8 @@ jobs: - name: Run example app tests timeout-minutes: 20 run: | - source .venv/bin/activate - make playwright-examples SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} + source venv/bin/activate && \ + make playwright-examples SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index ef95c311b..25476bceb 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -39,25 +39,25 @@ jobs: - name: Run unit tests if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate && \ + source venv/bin/activate && \ make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate && \ + source venv/bin/activate && \ make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate && \ + source venv/bin/activate && \ make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) run: | - source .venv/bin/activate && \ + source venv/bin/activate && \ make check-format pypi: From 5a709aeed9df8b75260db2a2ab507b5ddf4b4563 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:28:20 -0400 Subject: [PATCH 24/95] Update action.yaml --- .github/py-shiny/setup/action.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index d55af5edb..1071f5937 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -34,9 +34,8 @@ runs: - name: Install dependencies shell: bash run: | - uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" - - source venv/bin/activate && \ + . venv/bin/activate && \ + uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" && \ make install-deps - name: Install @@ -45,7 +44,7 @@ runs: # source venv/bin/activate && \ # make install - source venv/bin/activate + . venv/bin/activate # make clean @@ -63,9 +62,11 @@ runs: if: ${{ startsWith(inputs.python-version, '3.8') }} shell: bash run: | - uv pip install backports.tarfile + . venv/bin/activate && \ + uv pip install backports.tarfile - name: Pip list shell: bash run: | - uv pip list + . venv/bin/activate && \ + uv pip list From 731fd7249530eef6d0f8d64abb18b455742ac861 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:36:54 -0400 Subject: [PATCH 25/95] Update action.yaml --- .github/py-shiny/setup/action.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 1071f5937..5cf03261c 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -34,9 +34,11 @@ runs: - name: Install dependencies shell: bash run: | + # make install-deps . venv/bin/activate && \ uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" && \ - make install-deps + uv pip install -e ".[dev,test]" + - name: Install shell: bash From b452d4775865f9bc4ea982b4a7afb085f51ce1ba Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:47:35 -0400 Subject: [PATCH 26/95] Use `. venv/bin/activate` syntax --- .github/py-shiny/setup/action.yaml | 4 ++-- .github/workflows/deploy-tests.yaml | 4 ++-- .github/workflows/end-to-end.yaml | 4 ++-- .github/workflows/pytest.yaml | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 5cf03261c..4b8ec56d3 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -19,7 +19,8 @@ runs: - name: Upgrade pip shell: bash - run: python -m pip install --upgrade pip + run: | + python -m pip install --upgrade pip - name: Install `uv` shell: bash @@ -39,7 +40,6 @@ runs: uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" && \ uv pip install -e ".[dev,test]" - - name: Install shell: bash run: | diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 99515e305..9255666ab 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -30,7 +30,7 @@ jobs: env: DEPLOY_APPS: "false" run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make playwright-deploys SUB_FILE=". -vv" - name: Deploy apps and run tests (on `push` or `deploy**` branches) @@ -45,7 +45,7 @@ jobs: # Given we are waiting for external servers to finish, # we can have many local processes waiting for deployment to finish run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make playwright-deploys SUB_FILE=". -vv --numprocesses 12" - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index a48df4883..799d96bc7 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -40,7 +40,7 @@ jobs: - name: Run End-to-End tests timeout-minutes: 20 run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make playwright-shiny SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() @@ -89,7 +89,7 @@ jobs: - name: Run example app tests timeout-minutes: 20 run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make playwright-examples SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 25476bceb..e6223c7ae 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -39,25 +39,25 @@ jobs: - name: Run unit tests if: steps.install.outcome == 'success' && (success() || failure()) run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) run: | - source venv/bin/activate && \ + . venv/bin/activate && \ make check-format pypi: From 1caa908d44db93265b0e3e84ff62c971dff44cff Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:48:04 -0400 Subject: [PATCH 27/95] Do not require make playwright-deploys to install rsconnect --- .github/workflows/deploy-tests.yaml | 5 +++++ .github/workflows/end-to-end.yaml | 8 +++++++- Makefile | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 9255666ab..04783906c 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -25,6 +25,11 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Install rsconnect + run: | + . venv/bin/activate && \ + uv pip install "rsconnect @ git+https://github.com/rstudio/rsconnect-python.git" + - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally env: diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 799d96bc7..11f7a3fe2 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -118,12 +118,18 @@ jobs: with: all-browsers: ${{ ! github.event.pull_request.draft }} + - name: Install rsconnect + run: | + . venv/bin/activate && \ + uv pip install "rsconnect @ git+https://github.com/rstudio/rsconnect-python.git" + - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally env: DEPLOY_APPS: "false" run: | - make playwright-deploys SUB_FILE=". -vv" + . venv/bin/activate && \ + make playwright-deploys SUB_FILE=". -vv" - uses: actions/upload-artifact@v4 if: failure() diff --git a/Makefile b/Makefile index 0dfc9f9c0..01e1d1d88 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,7 @@ playwright-shiny: FORCE $(MAKE) playwright TEST_FILE="tests/playwright/shiny/$(SUB_FILE)" # end-to-end tests on deployed apps with playwright; (SUB_FILE="" within tests/playwright/deploys/) -playwright-deploys: install-rsconnect +playwright-deploys: FORCE $(MAKE) playwright TEST_FILE="tests/playwright/deploys/$(SUB_FILE)" PYTEST_BROWSERS="$(PYTEST_DEPLOYS_BROWSERS)" # end-to-end tests on all py-shiny examples with playwright; (SUB_FILE="" within tests/playwright/examples/) From 74ae8ad1753ba272d78d0b2dc0de203aa527e4b0 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:49:39 -0400 Subject: [PATCH 28/95] `rsconnect_python` not `rsconnect` --- .github/workflows/deploy-tests.yaml | 2 +- .github/workflows/end-to-end.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 04783906c..e0f69ad9c 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -28,7 +28,7 @@ jobs: - name: Install rsconnect run: | . venv/bin/activate && \ - uv pip install "rsconnect @ git+https://github.com/rstudio/rsconnect-python.git" + uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 11f7a3fe2..5968cb0fb 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -121,7 +121,7 @@ jobs: - name: Install rsconnect run: | . venv/bin/activate && \ - uv pip install "rsconnect @ git+https://github.com/rstudio/rsconnect-python.git" + uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally From 09ef1efe2e963019820da809a49ce5282269a6a2 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 16:55:21 -0400 Subject: [PATCH 29/95] Try with 4 processes --- .github/workflows/end-to-end.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index 5968cb0fb..e316a9716 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -41,7 +41,7 @@ jobs: timeout-minutes: 20 run: | . venv/bin/activate && \ - make playwright-shiny SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} + make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: @@ -90,7 +90,7 @@ jobs: timeout-minutes: 20 run: | . venv/bin/activate && \ - make playwright-examples SUB_FILE=". -vv" ${{ steps.browsers.outputs.browsers }} + make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: From 1bf23b3ece57aa036eb606aee98631d0f80504c9 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:02:22 -0400 Subject: [PATCH 30/95] Update end-to-end.yaml --- .github/workflows/end-to-end.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/end-to-end.yaml index e316a9716..658ff4d32 100644 --- a/.github/workflows/end-to-end.yaml +++ b/.github/workflows/end-to-end.yaml @@ -1,4 +1,4 @@ -name: End-to-End Tests +name: Playwright on: push: @@ -10,7 +10,7 @@ on: workflow_dispatch: jobs: - playwright-shiny: + shiny: runs-on: ubuntu-latest strategy: matrix: @@ -49,7 +49,7 @@ jobs: path: test-results/ retention-days: 5 - playwright-examples: + examples: runs-on: ubuntu-latest strategy: matrix: @@ -98,7 +98,7 @@ jobs: path: test-results/ retention-days: 5 - playwright-deploys-precheck: + deploys-precheck: runs-on: ubuntu-latest strategy: matrix: From 98a4359925ae4ff0055f0d4059610faab61535a0 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:05:22 -0400 Subject: [PATCH 31/95] Update playwright.yaml --- .github/workflows/{end-to-end.yaml => playwright.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{end-to-end.yaml => playwright.yaml} (100%) diff --git a/.github/workflows/end-to-end.yaml b/.github/workflows/playwright.yaml similarity index 100% rename from .github/workflows/end-to-end.yaml rename to .github/workflows/playwright.yaml From a011eab41ec5547f3e5763ae1c4a70ad27d6e864 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:05:34 -0400 Subject: [PATCH 32/95] Add types for pull request --- .github/workflows/pytest.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index e6223c7ae..1de2d9502 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -5,6 +5,7 @@ on: push: branches: ["main", "rc-*"] pull_request: + types: [opened, synchronize, reopened, ready_for_review] merge_group: release: types: [published] From 807792af82714fb256385c01789c6e9a6106701d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:07:46 -0400 Subject: [PATCH 33/95] Move playwright tests back into `pytest.yaml` --- .github/workflows/playwright.yaml | 139 ------------------------------ .github/workflows/pytest.yaml | 128 +++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 139 deletions(-) delete mode 100644 .github/workflows/playwright.yaml diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml deleted file mode 100644 index 658ff4d32..000000000 --- a/.github/workflows/playwright.yaml +++ /dev/null @@ -1,139 +0,0 @@ -name: Playwright - -on: - push: - branches: ["main", "rc-*"] - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - schedule: - - cron: "0 8 * * *" - workflow_dispatch: - -jobs: - shiny: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] - browser: ["chromium", "firefox", "webkit"] - exclude: - - python-version: ${{ github.event.pull_request.draft && '3.11' }} - - python-version: ${{ github.event.pull_request.draft && '3.10' }} - - python-version: ${{ github.event.pull_request.draft && '3.9' }} - - browser: ${{ github.event.pull_request.draft && 'firefox' }} - - browser: ${{ github.event.pull_request.draft && 'webkit' }} - fail-fast: false - - steps: - - uses: actions/checkout@v4 - - name: Setup py-shiny - uses: ./.github/py-shiny/setup - with: - python-version: ${{ matrix.python-version }} - - - name: Determine browsers for testing - uses: ./.github/py-shiny/pytest-browsers - id: browsers - with: - browser: ${{ matrix.browser }} - - - name: Run End-to-End tests - timeout-minutes: 20 - run: | - . venv/bin/activate && \ - make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: "playright-shiny-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" - path: test-results/ - retention-days: 5 - - examples: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] - browser: ["chromium", "firefox", "webkit"] - exclude: - - python-version: ${{ github.event.pull_request.draft && '3.11' }} - - python-version: ${{ github.event.pull_request.draft && '3.10' }} - - python-version: ${{ github.event.pull_request.draft && '3.9' }} - - browser: ${{ github.event.pull_request.draft && 'firefox' }} - - browser: ${{ github.event.pull_request.draft && 'webkit' }} - fail-fast: false - - steps: - - uses: actions/checkout@v4 - - name: Setup py-shiny - uses: ./.github/py-shiny/setup - with: - python-version: ${{ matrix.python-version }} - - name: Determine browsers for testing - uses: ./.github/py-shiny/pytest-browsers - id: browsers - with: - browser: ${{ matrix.browser }} - - - name: Install node.js - uses: actions/setup-node@v4 - with: - node-version: "18" - cache: npm - cache-dependency-path: examples/brownian/shinymediapipe/package-lock.json - - name: Install node.js package - working-directory: examples/brownian/shinymediapipe - run: | - npm ci - - - name: Run example app tests - timeout-minutes: 20 - run: | - . venv/bin/activate && \ - make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" - path: test-results/ - retention-days: 5 - - deploys-precheck: - runs-on: ubuntu-latest - strategy: - matrix: - # Matches deploy server python version - python-version: ["3.10"] - fail-fast: false - - steps: - - uses: actions/checkout@v4 - - name: Setup py-shiny - uses: ./.github/py-shiny/setup - with: - python-version: ${{ matrix.python-version }} - - name: Determine browsers for testing - uses: ./.github/py-shiny/pytest-browsers - id: browsers - with: - all-browsers: ${{ ! github.event.pull_request.draft }} - - - name: Install rsconnect - run: | - . venv/bin/activate && \ - uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - - - name: Test that deployable example apps work - timeout-minutes: 5 # ~10s locally - env: - DEPLOY_APPS: "false" - run: | - . venv/bin/activate && \ - make playwright-deploys SUB_FILE=". -vv" - - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-results" - path: test-results/ - retention-days: 5 diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 1de2d9502..8b2243c78 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -98,3 +98,131 @@ jobs: with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} + + playwright-shiny: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] + browser: ["chromium", "firefox", "webkit"] + exclude: + - python-version: ${{ github.event.pull_request.draft && '3.11' }} + - python-version: ${{ github.event.pull_request.draft && '3.10' }} + - python-version: ${{ github.event.pull_request.draft && '3.9' }} + - browser: ${{ github.event.pull_request.draft && 'firefox' }} + - browser: ${{ github.event.pull_request.draft && 'webkit' }} + fail-fast: false + + steps: + - uses: actions/checkout@v4 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup + with: + python-version: ${{ matrix.python-version }} + + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + browser: ${{ matrix.browser }} + + - name: Run End-to-End tests + timeout-minutes: 20 + run: | + . venv/bin/activate && \ + make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: "playright-shiny-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" + path: test-results/ + retention-days: 5 + + playwright-examples: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] + browser: ["chromium", "firefox", "webkit"] + exclude: + - python-version: ${{ github.event.pull_request.draft && '3.11' }} + - python-version: ${{ github.event.pull_request.draft && '3.10' }} + - python-version: ${{ github.event.pull_request.draft && '3.9' }} + - browser: ${{ github.event.pull_request.draft && 'firefox' }} + - browser: ${{ github.event.pull_request.draft && 'webkit' }} + fail-fast: false + + steps: + - uses: actions/checkout@v4 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup + with: + python-version: ${{ matrix.python-version }} + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + browser: ${{ matrix.browser }} + + - name: Install node.js + uses: actions/setup-node@v4 + with: + node-version: "18" + cache: npm + cache-dependency-path: examples/brownian/shinymediapipe/package-lock.json + - name: Install node.js package + working-directory: examples/brownian/shinymediapipe + run: | + npm ci + + - name: Run example app tests + timeout-minutes: 20 + run: | + . venv/bin/activate && \ + make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" + path: test-results/ + retention-days: 5 + + playwright-deploys-precheck: + runs-on: ubuntu-latest + strategy: + matrix: + # Matches deploy server python version + python-version: ["3.10"] + fail-fast: false + + steps: + - uses: actions/checkout@v4 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup + with: + python-version: ${{ matrix.python-version }} + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + all-browsers: ${{ ! github.event.pull_request.draft }} + + - name: Install rsconnect + run: | + . venv/bin/activate && \ + uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" + + - name: Test that deployable example apps work + timeout-minutes: 5 # ~10s locally + env: + DEPLOY_APPS: "false" + run: | + . venv/bin/activate && \ + make playwright-deploys SUB_FILE=". -vv" + + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-results" + path: test-results/ + retention-days: 5 From 4da66ba19b839ab42fca25d4ca9b2c9442811570 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:08:44 -0400 Subject: [PATCH 34/95] Do not run playwright on release --- .github/workflows/pytest.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 8b2243c78..09f09d646 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -100,6 +100,7 @@ jobs: password: ${{ secrets.PYPI_API_TOKEN }} playwright-shiny: + if: github.event_name != 'release' runs-on: ubuntu-latest strategy: matrix: @@ -139,6 +140,7 @@ jobs: retention-days: 5 playwright-examples: + if: github.event_name != 'release' runs-on: ubuntu-latest strategy: matrix: @@ -188,6 +190,7 @@ jobs: retention-days: 5 playwright-deploys-precheck: + if: github.event_name != 'release' runs-on: ubuntu-latest strategy: matrix: From 00d65f27af0439ac091ebc08b6fc0fbd66dfb723 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:14:31 -0400 Subject: [PATCH 35/95] Test using bash shell (windows) --- .github/workflows/pytest.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 09f09d646..f4646ffa0 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -39,24 +39,28 @@ jobs: - name: Run unit tests if: steps.install.outcome == 'success' && (success() || failure()) + shell: bash run: | . venv/bin/activate && \ make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) + shell: bash run: | . venv/bin/activate && \ make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) + shell: bash run: | . venv/bin/activate && \ make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) + shell: bash run: | . venv/bin/activate && \ make check-format From 94c6dbce02b87052c66e3514a9c2e1ef5d763e1c Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:27:49 -0400 Subject: [PATCH 36/95] Use windows friendly commands --- .github/py-shiny/setup/action.yaml | 25 ++++++++------- .github/workflows/build-docs.yaml | 18 +++++++---- .github/workflows/deploy-tests.yaml | 18 +++++++---- .github/workflows/pytest.yaml | 48 +++++++++++++++++++---------- 4 files changed, 70 insertions(+), 39 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 4b8ec56d3..b14f9509e 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -36,17 +36,16 @@ runs: shell: bash run: | # make install-deps - . venv/bin/activate && \ - uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" && \ - uv pip install -e ".[dev,test]" + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" + uv pip install -e ".[dev,test]" - name: Install shell: bash run: | - # source venv/bin/activate && \ - # make install - - . venv/bin/activate + # make install + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi # make clean @@ -64,11 +63,15 @@ runs: if: ${{ startsWith(inputs.python-version, '3.8') }} shell: bash run: | - . venv/bin/activate && \ - uv pip install backports.tarfile + # pip install backports.tarfile + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + uv pip install backports.tarfile - name: Pip list shell: bash run: | - . venv/bin/activate && \ - uv pip list + # pip list + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + uv pip list diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 9a344d71c..23665efae 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -33,15 +33,19 @@ jobs: - name: Install dependencies run: | - . venv/bin/activate && \ - uv pip install -e ".[dev,test,doc]" \ - "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ + # install docs dependencies + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + uv pip install -e ".[dev,test,doc]" + uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ "shinylive @ git+https://github.com/posit-dev/py-shinylive.git" - name: Run quartodoc run: | - . venv/bin/activate && \ - make docs-quartodoc + # make docs-quartodoc + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make docs-quartodoc # ===================================================== # Shinylive @@ -71,7 +75,9 @@ jobs: - name: Use local build of shinylive for building docs if: github.ref == 'refs/heads/main' run: | - . venv/bin/activate + # shinylive assets install-from-local ./build + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + cd shinylive-repo shinylive assets install-from-local ./build diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index e0f69ad9c..90672742e 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -27,16 +27,20 @@ jobs: - name: Install rsconnect run: | - . venv/bin/activate && \ - uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" + # pip install rsconnect + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally env: DEPLOY_APPS: "false" run: | - . venv/bin/activate && \ - make playwright-deploys SUB_FILE=". -vv" + # make playwright-deploys + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make playwright-deploys SUB_FILE=". -vv" - name: Deploy apps and run tests (on `push` or `deploy**` branches) env: @@ -50,8 +54,10 @@ jobs: # Given we are waiting for external servers to finish, # we can have many local processes waiting for deployment to finish run: | - . venv/bin/activate && \ - make playwright-deploys SUB_FILE=". -vv --numprocesses 12" + # make playwright-deploys + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make playwright-deploys SUB_FILE=". -vv --numprocesses 12" - uses: actions/upload-artifact@v4 if: failure() diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index f4646ffa0..b0ef9122c 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -41,29 +41,37 @@ jobs: if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - . venv/bin/activate && \ - make check-tests + # make check-tests + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - . venv/bin/activate && \ - make check-types + # make check-types + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - . venv/bin/activate && \ - make check-lint + # make check-lint + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - . venv/bin/activate && \ - make check-format + # make check-format + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make check-format pypi: name: "Deploy to PyPI" @@ -134,8 +142,10 @@ jobs: - name: Run End-to-End tests timeout-minutes: 20 run: | - . venv/bin/activate && \ - make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + # make playwright-shiny + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: @@ -184,8 +194,10 @@ jobs: - name: Run example app tests timeout-minutes: 20 run: | - . venv/bin/activate && \ - make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + # make playwright-examples + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: @@ -216,16 +228,20 @@ jobs: - name: Install rsconnect run: | - . venv/bin/activate && \ - uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" + # pip install rsconnect + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally env: DEPLOY_APPS: "false" run: | - . venv/bin/activate && \ - make playwright-deploys SUB_FILE=". -vv" + # make playwright-deploys + if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + + make playwright-deploys SUB_FILE=". -vv" - uses: actions/upload-artifact@v4 if: failure() From 06cbb1bef45df5a17c8908795028a6375acb398e Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 22 Jul 2024 17:30:35 -0400 Subject: [PATCH 37/95] Updated inline if syntax --- .github/py-shiny/setup/action.yaml | 8 ++++---- .github/workflows/build-docs.yaml | 6 +++--- .github/workflows/deploy-tests.yaml | 6 +++--- .github/workflows/pytest.yaml | 16 ++++++++-------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index b14f9509e..f0bd9ef6d 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -36,7 +36,7 @@ runs: shell: bash run: | # make install-deps - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" uv pip install -e ".[dev,test]" @@ -45,7 +45,7 @@ runs: shell: bash run: | # make install - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi # make clean @@ -64,7 +64,7 @@ runs: shell: bash run: | # pip install backports.tarfile - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi uv pip install backports.tarfile @@ -72,6 +72,6 @@ runs: shell: bash run: | # pip list - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi uv pip list diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 23665efae..ba906d45b 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -34,7 +34,7 @@ jobs: - name: Install dependencies run: | # install docs dependencies - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi uv pip install -e ".[dev,test,doc]" uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ @@ -43,7 +43,7 @@ jobs: - name: Run quartodoc run: | # make docs-quartodoc - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make docs-quartodoc @@ -76,7 +76,7 @@ jobs: if: github.ref == 'refs/heads/main' run: | # shinylive assets install-from-local ./build - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi cd shinylive-repo shinylive assets install-from-local ./build diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 90672742e..54ad785ff 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -28,7 +28,7 @@ jobs: - name: Install rsconnect run: | # pip install rsconnect - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" @@ -38,7 +38,7 @@ jobs: DEPLOY_APPS: "false" run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv" @@ -55,7 +55,7 @@ jobs: # we can have many local processes waiting for deployment to finish run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv --numprocesses 12" diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index b0ef9122c..792671ea7 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -42,7 +42,7 @@ jobs: shell: bash run: | # make check-tests - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make check-tests @@ -51,7 +51,7 @@ jobs: shell: bash run: | # make check-types - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make check-types @@ -60,7 +60,7 @@ jobs: shell: bash run: | # make check-lint - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make check-lint @@ -69,7 +69,7 @@ jobs: shell: bash run: | # make check-format - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make check-format @@ -143,7 +143,7 @@ jobs: timeout-minutes: 20 run: | # make playwright-shiny - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 @@ -195,7 +195,7 @@ jobs: timeout-minutes: 20 run: | # make playwright-examples - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 @@ -229,7 +229,7 @@ jobs: - name: Install rsconnect run: | # pip install rsconnect - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" @@ -239,7 +239,7 @@ jobs: DEPLOY_APPS: "false" run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then; venv\Scripts\activate; else; . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv" From 467391920e08668feaaac12f18589e426c9c07bc Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 08:45:26 -0400 Subject: [PATCH 38/95] Windows path update --- .github/py-shiny/setup/action.yaml | 8 ++++---- .github/workflows/build-docs.yaml | 6 +++--- .github/workflows/deploy-tests.yaml | 6 +++--- .github/workflows/pytest.yaml | 16 ++++++++-------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index f0bd9ef6d..4a473c642 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -36,7 +36,7 @@ runs: shell: bash run: | # make install-deps - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" uv pip install -e ".[dev,test]" @@ -45,7 +45,7 @@ runs: shell: bash run: | # make install - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi # make clean @@ -64,7 +64,7 @@ runs: shell: bash run: | # pip install backports.tarfile - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install backports.tarfile @@ -72,6 +72,6 @@ runs: shell: bash run: | # pip list - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip list diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index ba906d45b..a6aab0fa0 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -34,7 +34,7 @@ jobs: - name: Install dependencies run: | # install docs dependencies - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install -e ".[dev,test,doc]" uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ @@ -43,7 +43,7 @@ jobs: - name: Run quartodoc run: | # make docs-quartodoc - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make docs-quartodoc @@ -76,7 +76,7 @@ jobs: if: github.ref == 'refs/heads/main' run: | # shinylive assets install-from-local ./build - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi cd shinylive-repo shinylive assets install-from-local ./build diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 54ad785ff..fab97368f 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -28,7 +28,7 @@ jobs: - name: Install rsconnect run: | # pip install rsconnect - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" @@ -38,7 +38,7 @@ jobs: DEPLOY_APPS: "false" run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv" @@ -55,7 +55,7 @@ jobs: # we can have many local processes waiting for deployment to finish run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv --numprocesses 12" diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 792671ea7..31666e015 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -42,7 +42,7 @@ jobs: shell: bash run: | # make check-tests - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-tests @@ -51,7 +51,7 @@ jobs: shell: bash run: | # make check-types - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-types @@ -60,7 +60,7 @@ jobs: shell: bash run: | # make check-lint - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-lint @@ -69,7 +69,7 @@ jobs: shell: bash run: | # make check-format - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-format @@ -143,7 +143,7 @@ jobs: timeout-minutes: 20 run: | # make playwright-shiny - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 @@ -195,7 +195,7 @@ jobs: timeout-minutes: 20 run: | # make playwright-examples - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 @@ -229,7 +229,7 @@ jobs: - name: Install rsconnect run: | # pip install rsconnect - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" @@ -239,7 +239,7 @@ jobs: DEPLOY_APPS: "false" run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then venv\Scripts\activate; else . venv/bin/activate; fi + if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv" From c71e159337ad81a302b7cdb028b27f181b263e79 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 09:00:23 -0400 Subject: [PATCH 39/95] Allow uv to use the system Python by default --- .github/py-shiny/setup/action.yaml | 18 ++++++++++++------ .github/workflows/build-docs.yaml | 6 +++--- .github/workflows/deploy-tests.yaml | 6 +++--- .github/workflows/pytest.yaml | 16 ++++++++-------- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 4a473c642..474a8dc20 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -27,16 +27,22 @@ runs: run: | pip install uv - - name: Create virtual environment + # https://github.com/astral-sh/uv/blob/main/docs/guides/integration/github.md#using-uv-pip + - name: Allow uv to use the system Python by default shell: bash run: | - uv venv venv + echo "UV_SYSTEM_PYTHON=1" >> $GITHUB_ENV + + # - name: Create virtual environment + # shell: bash + # run: | + # uv venv venv - name: Install dependencies shell: bash run: | # make install-deps - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" uv pip install -e ".[dev,test]" @@ -45,7 +51,7 @@ runs: shell: bash run: | # make install - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi # make clean @@ -64,7 +70,7 @@ runs: shell: bash run: | # pip install backports.tarfile - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install backports.tarfile @@ -72,6 +78,6 @@ runs: shell: bash run: | # pip list - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip list diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index a6aab0fa0..d800230ed 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -34,7 +34,7 @@ jobs: - name: Install dependencies run: | # install docs dependencies - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install -e ".[dev,test,doc]" uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ @@ -43,7 +43,7 @@ jobs: - name: Run quartodoc run: | # make docs-quartodoc - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make docs-quartodoc @@ -76,7 +76,7 @@ jobs: if: github.ref == 'refs/heads/main' run: | # shinylive assets install-from-local ./build - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi cd shinylive-repo shinylive assets install-from-local ./build diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index fab97368f..4367d37f0 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -28,7 +28,7 @@ jobs: - name: Install rsconnect run: | # pip install rsconnect - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" @@ -38,7 +38,7 @@ jobs: DEPLOY_APPS: "false" run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv" @@ -55,7 +55,7 @@ jobs: # we can have many local processes waiting for deployment to finish run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv --numprocesses 12" diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 31666e015..fb492e2c7 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -42,7 +42,7 @@ jobs: shell: bash run: | # make check-tests - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-tests @@ -51,7 +51,7 @@ jobs: shell: bash run: | # make check-types - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-types @@ -60,7 +60,7 @@ jobs: shell: bash run: | # make check-lint - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-lint @@ -69,7 +69,7 @@ jobs: shell: bash run: | # make check-format - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make check-format @@ -143,7 +143,7 @@ jobs: timeout-minutes: 20 run: | # make playwright-shiny - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 @@ -195,7 +195,7 @@ jobs: timeout-minutes: 20 run: | # make playwright-examples - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 @@ -229,7 +229,7 @@ jobs: - name: Install rsconnect run: | # pip install rsconnect - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" @@ -239,7 +239,7 @@ jobs: DEPLOY_APPS: "false" run: | # make playwright-deploys - if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi + # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi make playwright-deploys SUB_FILE=". -vv" From 20e1086e63eaa5be2aad67987c2d5a685da4e588 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 09:38:17 -0400 Subject: [PATCH 40/95] Clean up --- .github/py-shiny/setup/action.yaml | 9 --------- .github/workflows/build-docs.yaml | 11 +---------- .github/workflows/deploy-tests.yaml | 9 --------- .github/workflows/pytest.yaml | 24 ------------------------ 4 files changed, 1 insertion(+), 52 deletions(-) diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 474a8dc20..9f73baf99 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -42,8 +42,6 @@ runs: shell: bash run: | # make install-deps - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" uv pip install -e ".[dev,test]" @@ -51,7 +49,6 @@ runs: shell: bash run: | # make install - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi # make clean @@ -69,15 +66,9 @@ runs: if: ${{ startsWith(inputs.python-version, '3.8') }} shell: bash run: | - # pip install backports.tarfile - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - uv pip install backports.tarfile - name: Pip list shell: bash run: | - # pip list - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - uv pip list diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index d800230ed..cb6b6d9d8 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -34,17 +34,12 @@ jobs: - name: Install dependencies run: | # install docs dependencies - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - uv pip install -e ".[dev,test,doc]" uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ "shinylive @ git+https://github.com/posit-dev/py-shinylive.git" - name: Run quartodoc run: | - # make docs-quartodoc - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make docs-quartodoc # ===================================================== @@ -75,11 +70,7 @@ jobs: - name: Use local build of shinylive for building docs if: github.ref == 'refs/heads/main' run: | - # shinylive assets install-from-local ./build - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - - cd shinylive-repo - shinylive assets install-from-local ./build + cd shinylive-repo && shinylive assets install-from-local ./build # ===================================================== # Build site diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 4367d37f0..10932fa11 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -27,9 +27,6 @@ jobs: - name: Install rsconnect run: | - # pip install rsconnect - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - name: Test that deployable example apps work @@ -37,9 +34,6 @@ jobs: env: DEPLOY_APPS: "false" run: | - # make playwright-deploys - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make playwright-deploys SUB_FILE=". -vv" - name: Deploy apps and run tests (on `push` or `deploy**` branches) @@ -54,9 +48,6 @@ jobs: # Given we are waiting for external servers to finish, # we can have many local processes waiting for deployment to finish run: | - # make playwright-deploys - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make playwright-deploys SUB_FILE=". -vv --numprocesses 12" - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index fb492e2c7..1d74f369d 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -41,36 +41,24 @@ jobs: if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - # make check-tests - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - # make check-types - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - # make check-lint - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) shell: bash run: | - # make check-format - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make check-format pypi: @@ -142,9 +130,6 @@ jobs: - name: Run End-to-End tests timeout-minutes: 20 run: | - # make playwright-shiny - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() @@ -194,9 +179,6 @@ jobs: - name: Run example app tests timeout-minutes: 20 run: | - # make playwright-examples - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() @@ -228,9 +210,6 @@ jobs: - name: Install rsconnect run: | - # pip install rsconnect - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - name: Test that deployable example apps work @@ -238,9 +217,6 @@ jobs: env: DEPLOY_APPS: "false" run: | - # make playwright-deploys - # if [ "${{ runner.os }}" == "Windows" ]; then venv/Scripts/activate; else . venv/bin/activate; fi - make playwright-deploys SUB_FILE=". -vv" - uses: actions/upload-artifact@v4 From 02b9c24e8a9cf2df3c5a8a2fa4561d6d4089f140 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 09:40:08 -0400 Subject: [PATCH 41/95] Skip tests that fail on windows due to temp file ownership issues --- tests/playwright/utils/deploy_utils.py | 9 +++++++++ tests/pytest/test_express_ui.py | 2 ++ tests/pytest/test_theme.py | 3 +++ 3 files changed, 14 insertions(+) diff --git a/tests/playwright/utils/deploy_utils.py b/tests/playwright/utils/deploy_utils.py index 38f40b1a3..aecd38e07 100644 --- a/tests/playwright/utils/deploy_utils.py +++ b/tests/playwright/utils/deploy_utils.py @@ -40,6 +40,15 @@ CallableT = TypeVar("CallableT", bound=Callable[..., Any]) +def skip_on_windows(fn: CallableT) -> CallableT: + fn = pytest.mark.skipif( + sys.platform.startswith("win"), + reason="Does not run on windows", + )(fn) + + return fn + + def skip_if_not_chrome(fn: CallableT) -> CallableT: # # Keeping commented to allow for easier local debugging # import platform diff --git a/tests/pytest/test_express_ui.py b/tests/pytest/test_express_ui.py index 90b36c360..83c82a92b 100644 --- a/tests/pytest/test_express_ui.py +++ b/tests/pytest/test_express_ui.py @@ -9,6 +9,7 @@ from shiny.express import output_args from shiny.express import ui as xui from shiny.express._run import run_express +from tests.playwright.utils.deploy_utils import skip_on_windows def test_express_ui_is_complete(): @@ -100,6 +101,7 @@ def display_hook_spy(_: object) -> Any: sys.displayhook = old_displayhook +@skip_on_windows def test_recall_context_manager(): # A Shiny Express app that uses a RecallContextManager (ui.card_header()) without # `with`. It is used within another RecallContextManager (ui.card()), but that one diff --git a/tests/pytest/test_theme.py b/tests/pytest/test_theme.py index 826e1280e..1f2ad0271 100644 --- a/tests/pytest/test_theme.py +++ b/tests/pytest/test_theme.py @@ -20,6 +20,7 @@ shiny_theme_presets, shiny_theme_presets_bundled, ) +from tests.playwright.utils.deploy_utils import skip_on_windows def test_theme_stores_values_correctly(): @@ -78,6 +79,7 @@ def test_theme_preset_must_be_valid(): Theme("not_a_valid_preset") # type: ignore +@skip_on_windows @pytest.mark.parametrize("preset", shiny_theme_presets) def test_theme_css_compiles_and_is_cached(preset: ShinyThemePreset): theme = Theme(preset) @@ -156,6 +158,7 @@ def _page_sidebar(*args, **kwargs) -> Tag: # type: ignore return page_sidebar(sidebar("Sidebar"), *args, **kwargs) # type: ignore +@skip_on_windows @pytest.mark.parametrize( "page_fn", [ From fd6e280036037d33b5313935f75e6c71a4436fa9 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 09:46:35 -0400 Subject: [PATCH 42/95] Relocate `skip_on_windows` --- tests/playwright/utils/deploy_utils.py | 9 --------- tests/pytest/_utils.py | 17 +++++++++++++++++ tests/pytest/test_express_ui.py | 2 +- tests/pytest/test_theme.py | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 tests/pytest/_utils.py diff --git a/tests/playwright/utils/deploy_utils.py b/tests/playwright/utils/deploy_utils.py index aecd38e07..38f40b1a3 100644 --- a/tests/playwright/utils/deploy_utils.py +++ b/tests/playwright/utils/deploy_utils.py @@ -40,15 +40,6 @@ CallableT = TypeVar("CallableT", bound=Callable[..., Any]) -def skip_on_windows(fn: CallableT) -> CallableT: - fn = pytest.mark.skipif( - sys.platform.startswith("win"), - reason="Does not run on windows", - )(fn) - - return fn - - def skip_if_not_chrome(fn: CallableT) -> CallableT: # # Keeping commented to allow for easier local debugging # import platform diff --git a/tests/pytest/_utils.py b/tests/pytest/_utils.py new file mode 100644 index 000000000..a36b04069 --- /dev/null +++ b/tests/pytest/_utils.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +import sys +from typing import Any, Callable, TypeVar + +import pytest + +CallableT = TypeVar("CallableT", bound=Callable[..., Any]) + + +def skip_on_windows(fn: CallableT) -> CallableT: + fn = pytest.mark.skipif( + sys.platform.startswith("win"), + reason="Does not run on windows", + )(fn) + + return fn diff --git a/tests/pytest/test_express_ui.py b/tests/pytest/test_express_ui.py index 83c82a92b..27a19aa93 100644 --- a/tests/pytest/test_express_ui.py +++ b/tests/pytest/test_express_ui.py @@ -4,12 +4,12 @@ from typing import Any import pytest +from _utils import skip_on_windows from shiny import render, ui from shiny.express import output_args from shiny.express import ui as xui from shiny.express._run import run_express -from tests.playwright.utils.deploy_utils import skip_on_windows def test_express_ui_is_complete(): diff --git a/tests/pytest/test_theme.py b/tests/pytest/test_theme.py index 1f2ad0271..c3c506c94 100644 --- a/tests/pytest/test_theme.py +++ b/tests/pytest/test_theme.py @@ -1,6 +1,7 @@ from typing import Callable, Optional import pytest +from _utils import skip_on_windows from htmltools import Tag from shiny import App @@ -20,7 +21,6 @@ shiny_theme_presets, shiny_theme_presets_bundled, ) -from tests.playwright.utils.deploy_utils import skip_on_windows def test_theme_stores_values_correctly(): From ca0ce73a661e5fe956c0d81fc079d65b5a407d54 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 09:48:58 -0400 Subject: [PATCH 43/95] Remove unnecessary rsconnect install --- .github/workflows/pytest.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 1d74f369d..29039ee3f 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -208,10 +208,6 @@ jobs: with: all-browsers: ${{ ! github.event.pull_request.draft }} - - name: Install rsconnect - run: | - uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" - - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally env: From a36cfdb30479a2a7a0904044584230b3a2bc5292 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 09:50:46 -0400 Subject: [PATCH 44/95] Work here? --- tests/pytest/test_express_ui.py | 2 +- tests/pytest/test_theme.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/pytest/test_express_ui.py b/tests/pytest/test_express_ui.py index 27a19aa93..347f39942 100644 --- a/tests/pytest/test_express_ui.py +++ b/tests/pytest/test_express_ui.py @@ -4,7 +4,7 @@ from typing import Any import pytest -from _utils import skip_on_windows +from ._utils import skip_on_windows from shiny import render, ui from shiny.express import output_args diff --git a/tests/pytest/test_theme.py b/tests/pytest/test_theme.py index c3c506c94..1bfc42b87 100644 --- a/tests/pytest/test_theme.py +++ b/tests/pytest/test_theme.py @@ -1,7 +1,6 @@ from typing import Callable, Optional import pytest -from _utils import skip_on_windows from htmltools import Tag from shiny import App @@ -22,6 +21,8 @@ shiny_theme_presets_bundled, ) +from ._utils import skip_on_windows + def test_theme_stores_values_correctly(): theme = ( From 1c4ade19ceeda84f9a5be4ba03dd9d6c10b26905 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 10:06:34 -0400 Subject: [PATCH 45/95] isort --- tests/pytest/test_express_ui.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/pytest/test_express_ui.py b/tests/pytest/test_express_ui.py index 347f39942..c758e2e09 100644 --- a/tests/pytest/test_express_ui.py +++ b/tests/pytest/test_express_ui.py @@ -4,13 +4,14 @@ from typing import Any import pytest -from ._utils import skip_on_windows from shiny import render, ui from shiny.express import output_args from shiny.express import ui as xui from shiny.express._run import run_express +from ._utils import skip_on_windows + def test_express_ui_is_complete(): """ From bac659a584f208ed6cf9998af8cd57c4757adf0c Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 12:19:53 -0400 Subject: [PATCH 46/95] Move commands into make files; Remove remaining merge queue commands --- .github/py-shiny/pytest-browsers/action.yaml | 4 +- .github/py-shiny/setup/action.yaml | 29 +----- .github/workflows/build-docs.yaml | 8 +- .github/workflows/deploy-tests.yaml | 2 +- .github/workflows/pytest.yaml | 1 - .github/workflows/verify-js-built.yaml | 1 - Makefile | 34 +++++++- docs/Makefile | 92 ++++++++------------ 8 files changed, 73 insertions(+), 98 deletions(-) diff --git a/.github/py-shiny/pytest-browsers/action.yaml b/.github/py-shiny/pytest-browsers/action.yaml index 69f6b56ce..4d3eaa393 100644 --- a/.github/py-shiny/pytest-browsers/action.yaml +++ b/.github/py-shiny/pytest-browsers/action.yaml @@ -1,5 +1,5 @@ -name: 'Custom merge queue browsers' -description: 'Trim down pytest browsers for any github event other than merge_group.' +name: 'Trim down pytest browsers' +description: 'Trim down pytest browsers so the browser tabs are not shut down between tests, speeding up testing.' inputs: browser: description: 'Browser to use for testing' diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index 9f73baf99..dfa398f9f 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -12,12 +12,8 @@ runs: uses: actions/setup-python@v5 with: python-version: ${{ inputs.python-version }} - # # Caching with pip only saves ~15 seconds. Not work risks of confusion. - # cache: 'pip' - # cache-dependency-path: | - # setup.cfg - - name: Upgrade pip + - name: Upgrade `pip` shell: bash run: | python -m pip install --upgrade pip @@ -33,34 +29,15 @@ runs: run: | echo "UV_SYSTEM_PYTHON=1" >> $GITHUB_ENV - # - name: Create virtual environment - # shell: bash - # run: | - # uv venv venv - - name: Install dependencies shell: bash run: | - # make install-deps - uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" - uv pip install -e ".[dev,test]" + make ci-install-deps - name: Install shell: bash run: | - # make install - - # make clean - - # make dist - uv pip install setuptools - python setup.py sdist - python setup.py bdist_wheel - ls -l dist - - # make install - uv pip uninstall shiny - uv pip install dist/shiny*.whl + make ci-install-wheel - name: Install backports.tarfile if: ${{ startsWith(inputs.python-version, '3.8') }} diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index cb6b6d9d8..6a45560cc 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -5,7 +5,6 @@ on: push: branches: ["main"] pull_request: - merge_group: jobs: build-docs: @@ -33,10 +32,7 @@ jobs: - name: Install dependencies run: | - # install docs dependencies - uv pip install -e ".[dev,test,doc]" - uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ - "shinylive @ git+https://github.com/posit-dev/py-shinylive.git" + make ci-install-docs - name: Run quartodoc run: | @@ -77,7 +73,7 @@ jobs: # ===================================================== - name: Build site - if: ${{ github.ref == 'refs/heads/main' || github.event_name == 'merge_group' || startsWith(github.head_ref, 'docs') }} + if: ${{ github.ref == 'refs/heads/main' || (!github.event.pull_request.draft) || startsWith(github.head_ref, 'docs') }} run: | cd docs make site diff --git a/.github/workflows/deploy-tests.yaml b/.github/workflows/deploy-tests.yaml index 10932fa11..d0e17f727 100644 --- a/.github/workflows/deploy-tests.yaml +++ b/.github/workflows/deploy-tests.yaml @@ -27,7 +27,7 @@ jobs: - name: Install rsconnect run: | - uv pip install "rsconnect_python @ git+https://github.com/rstudio/rsconnect-python.git" + make ci-install-rsconnect - name: Test that deployable example apps work timeout-minutes: 5 # ~10s locally diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 29039ee3f..6f0205d99 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -6,7 +6,6 @@ on: branches: ["main", "rc-*"] pull_request: types: [opened, synchronize, reopened, ready_for_review] - merge_group: release: types: [published] schedule: diff --git a/.github/workflows/verify-js-built.yaml b/.github/workflows/verify-js-built.yaml index d38cd1a7d..02127f3b0 100644 --- a/.github/workflows/verify-js-built.yaml +++ b/.github/workflows/verify-js-built.yaml @@ -4,7 +4,6 @@ on: push: branches: ["main", "rc-*"] pull_request: - merge_group: jobs: verify_js_built: diff --git a/Makefile b/Makefile index 01e1d1d88..25d391826 100644 --- a/Makefile +++ b/Makefile @@ -26,10 +26,10 @@ for line in sys.stdin: endef export PRINT_HELP_PYSCRIPT -BROWSER := python -c "$$BROWSER_PYSCRIPT" +BROWSER := python3 -c "$$BROWSER_PYSCRIPT" help: FORCE - @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts @@ -98,7 +98,7 @@ check-pyright: pyright-typings pyright check-pytest: FORCE @echo "-------- Running tests with pytest ----------" - python3 tests/pytest/asyncio_prevent.py + python tests/pytest/asyncio_prevent.py pytest # Check types with pyright @@ -192,6 +192,13 @@ dist: clean ## builds source and wheel package python3 setup.py sdist python3 setup.py bdist_wheel ls -l dist +ci-dist: FORCE + $(MAKE) clean + pip install setuptools + python setup.py sdist + python setup.py bdist_wheel + ls -l dist + ## install the package to the active Python's site-packages # Note that instead of --force-reinstall, we uninstall and then install, because @@ -200,9 +207,30 @@ dist: clean ## builds source and wheel package install: dist pip uninstall -y shiny python3 -m pip install dist/shiny*.whl +ci-install-wheel: FORCE + $(MAKE) ci-dist + # make install + uv pip uninstall shiny + uv pip install dist/shiny*.whl install-deps: FORCE ## install dependencies pip install -e ".[dev,test]" --upgrade +ci-install-deps: FORCE + uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" + uv pip install -e ".[dev,test]" + +install-docs: FORCE + pip install -e ".[dev,test,doc]" + pip install https://github.com/posit-dev/py-htmltools/tarball/main + pip install https://github.com/posit-dev/py-shinylive/tarball/main +ci-install-docs: FORCE + uv pip install -e ".[dev,test,doc]" + uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git" \ + "shinylive @ git+https://github.com/posit-dev/py-shinylive.git" + +ci-install-rsconnect: FORCE + uv pip install "rsconnect-python @ git+https://github.com/rstudio/rsconnect-python.git" + # ## If caching is ever used, we could run: # install-deps: FORCE ## install latest dependencies diff --git a/docs/Makefile b/docs/Makefile index 84a47d432..a7a9c0547 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,4 +1,7 @@ -.PHONY: help Makefile +# Using `FORCE` as prerequisite to _force_ the target to always run; https://www.gnu.org/software/make/manual/make.html#index-FORCE +FORCE: ; + +.PHONY: Makefile .DEFAULT_GOAL := help define BROWSER_PYSCRIPT @@ -21,86 +24,59 @@ for line in sys.stdin: endef export PRINT_HELP_PYSCRIPT -BROWSER := python -c "$$BROWSER_PYSCRIPT" - -# Use venv from parent -VENV = ../venv -PYBIN = $(VENV)/bin - -# Any targets that depend on $(VENV) or $(PYBIN) will cause the venv to be -# created. To use the venv, python scripts should run with the prefix $(PYBIN), -# as in `$(PYBIN)/pip`. -$(VENV): - python3 -m venv $(VENV) - -$(PYBIN): $(VENV) - - -help: - @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) - -dev-htmltools: $(PYBIN) ## Install development version of htmltools - $(PYBIN)/pip install https://github.com/posit-dev/py-htmltools/tarball/main +BROWSER := python3 -c "$$BROWSER_PYSCRIPT" -dev-shinylive: $(PYBIN) ## Install development version of shinylive - $(PYBIN)/pip install https://github.com/posit-dev/py-shinylive/tarball/main +help: FORCE + @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) -deps: $(PYBIN) dev-htmltools dev-shinylive ## Install build dependencies - $(PYBIN)/pip install pip --upgrade - $(PYBIN)/pip install ..[doc] +deps: FORCE ## Install build dependencies + cd .. && $(MAKE) install- -quartodoc: quartodoc_build_core quartodoc_build_express quartodoc_build_test quartodoc_post ## Build quartodocs for express and core +quartodoc: quartodoc_build_core quartodoc_build_express quartodoc_build_test quartodoc_post ## Build quartodocs for express, core, and testing ## Build interlinks for API docs -quartodoc_interlinks: $(PYBIN) - . $(PYBIN)/activate \ - && quartodoc interlinks +quartodoc_interlinks: FORCE + quartodoc interlinks ## Build core API docs -quartodoc_build_core: $(PYBIN) quartodoc_interlinks +quartodoc_build_core: quartodoc_interlinks FORCE $(eval export SHINY_ADD_EXAMPLES=true) $(eval export IN_QUARTODOC=true) $(eval export SHINY_MODE=core) - . $(PYBIN)/activate \ - && echo "::group::quartodoc build core docs" \ - && quartodoc build --config _quartodoc-core.yml --verbose \ - && mv objects.json _objects_core.json \ - && echo "::endgroup::" + @echo "::group::quartodoc build core docs" + quartodoc build --config _quartodoc-core.yml --verbose \ + && mv objects.json _objects_core.json + @echo "::endgroup::" ## Build express API docs -quartodoc_build_express: $(PYBIN) quartodoc_interlinks +quartodoc_build_express: quartodoc_interlinks FORCE $(eval export SHINY_ADD_EXAMPLES=true) $(eval export IN_QUARTODOC=true) $(eval export SHINY_MODE=express) - . $(PYBIN)/activate \ - && echo "::group::quartodoc build express docs" \ - && quartodoc build --config _quartodoc-express.yml --verbose \ - && mv objects.json _objects_express.json \ - && echo "::endgroup::" + @echo "::group::quartodoc build express docs" + quartodoc build --config _quartodoc-express.yml --verbose \ + && mv objects.json _objects_express.json + @echo "::endgroup::" ## Build test API docs -quartodoc_build_test: $(PYBIN) quartodoc_interlinks +quartodoc_build_test: quartodoc_interlinks FORCE $(eval export SHINY_ADD_EXAMPLES=true) $(eval export IN_QUARTODOC=true) $(eval export SHINY_MODE=express) - . $(PYBIN)/activate \ - && echo "::group::quartodoc build testing docs" \ - && quartodoc build --config _quartodoc-testing.yml --verbose \ - && mv objects.json _objects_test.json \ - && echo "::endgroup::" + @echo "::group::quartodoc build testing docs" + quartodoc build --config _quartodoc-testing.yml --verbose \ + && mv objects.json _objects_test.json + @echo "::endgroup::" ## Clean up after quartodoc build -quartodoc_post: $(PYBIN) - . $(PYBIN)/activate \ - && python _combine_objects_json.py +quartodoc_post: FORCE + python _combine_objects_json.py -site: ## Build website - . $(PYBIN)/activate \ - && quarto render +site: FORCE ## Build website (quarto render) + quarto render -serve: ## Build website and serve - . $(PYBIN)/activate \ - && quarto preview --port 8080 +serve: FORCE ## Build website and serve (quarto preview) + && quarto preview --port 8080 -clean: ## Clean build artifacts +clean: FORCE ## Clean build artifacts rm -rf _inv api _site .quarto From 419a3ebcf231dbc56f023f0df2e94fe0aeca925a Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 12:59:17 -0400 Subject: [PATCH 47/95] Update Makefile --- Makefile | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 25d391826..be22a2342 100644 --- a/Makefile +++ b/Makefile @@ -188,11 +188,6 @@ release: dist ## package and upload a release twine upload dist/* dist: clean ## builds source and wheel package - pip install setuptools - python3 setup.py sdist - python3 setup.py bdist_wheel - ls -l dist -ci-dist: FORCE $(MAKE) clean pip install setuptools python setup.py sdist @@ -206,9 +201,9 @@ ci-dist: FORCE # deps wouldn't be installed the first time. install: dist pip uninstall -y shiny - python3 -m pip install dist/shiny*.whl + python -m pip install dist/shiny*.whl ci-install-wheel: FORCE - $(MAKE) ci-dist + $(MAKE) dist # make install uv pip uninstall shiny uv pip install dist/shiny*.whl From 36c41a8b2e2430c15637266331ad40f88bb9b31f Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 12:59:50 -0400 Subject: [PATCH 48/95] ci: Adjust pytest verbosity output levels (#1553) --- .github/workflows/pytest.yaml | 6 +++--- pytest.ini | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 6f0205d99..1ea839768 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -129,7 +129,7 @@ jobs: - name: Run End-to-End tests timeout-minutes: 20 run: | - make playwright-shiny SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + make playwright-shiny SUB_FILE=". --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: @@ -178,7 +178,7 @@ jobs: - name: Run example app tests timeout-minutes: 20 run: | - make playwright-examples SUB_FILE=". -vv --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + make playwright-examples SUB_FILE=". --numprocesses 4" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: @@ -212,7 +212,7 @@ jobs: env: DEPLOY_APPS: "false" run: | - make playwright-deploys SUB_FILE=". -vv" + make playwright-deploys - uses: actions/upload-artifact@v4 if: failure() diff --git a/pytest.ini b/pytest.ini index 1c02d79f4..936ed0305 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,3 +3,4 @@ asyncio_mode=strict testpaths=tests/pytest/ ; Note: Browsers are set within `./Makefile` addopts = --strict-markers --durations=6 --durations-min=5.0 --numprocesses auto --tracing=retain-on-failure --video=retain-on-failure +verbosity_test_cases=2 From 9431b949439c2a767b1a8b292493886c74c720f4 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 14:08:39 -0400 Subject: [PATCH 49/95] Try using temp dir for better windows support --- tests/pytest/test_express_ui.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/pytest/test_express_ui.py b/tests/pytest/test_express_ui.py index c758e2e09..aa052aaec 100644 --- a/tests/pytest/test_express_ui.py +++ b/tests/pytest/test_express_ui.py @@ -10,8 +10,6 @@ from shiny.express import ui as xui from shiny.express._run import run_express -from ._utils import skip_on_windows - def test_express_ui_is_complete(): """ @@ -102,7 +100,6 @@ def display_hook_spy(_: object) -> Any: sys.displayhook = old_displayhook -@skip_on_windows def test_recall_context_manager(): # A Shiny Express app that uses a RecallContextManager (ui.card_header()) without # `with`. It is used within another RecallContextManager (ui.card()), but that one @@ -125,9 +122,9 @@ def test_recall_context_manager(): ) ) - with tempfile.NamedTemporaryFile(mode="w+t") as temp_file: - temp_file.write(card_app_express_text) - temp_file.flush() + with tempfile.TemporaryDirectory() as temp_dir: + temp_file = Path(temp_dir, "temp.file") + temp_file.write_text(card_app_express_text) res = run_express(Path(temp_file.name)).tagify() assert str(res) == str(card_app_core) From b8eac1ea589e53bc8f7d9970c575210ec12dca18 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 16:20:47 -0400 Subject: [PATCH 50/95] Update test_express_ui.py --- tests/pytest/test_express_ui.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/pytest/test_express_ui.py b/tests/pytest/test_express_ui.py index aa052aaec..b53477cc9 100644 --- a/tests/pytest/test_express_ui.py +++ b/tests/pytest/test_express_ui.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys import tempfile from pathlib import Path @@ -125,6 +127,6 @@ def test_recall_context_manager(): with tempfile.TemporaryDirectory() as temp_dir: temp_file = Path(temp_dir, "temp.file") temp_file.write_text(card_app_express_text) - res = run_express(Path(temp_file.name)).tagify() + res = run_express(temp_file).tagify() assert str(res) == str(card_app_core) From 10f4ebe7a2d5e5eb10fec184832d956ee12c5cde Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 16:26:35 -0400 Subject: [PATCH 51/95] Add test to discourage usage of `tempfile.NamedTemporaryFile()` --- tests/pytest/test_named_temporary_file.py | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/pytest/test_named_temporary_file.py diff --git a/tests/pytest/test_named_temporary_file.py b/tests/pytest/test_named_temporary_file.py new file mode 100644 index 000000000..3622983e8 --- /dev/null +++ b/tests/pytest/test_named_temporary_file.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +import glob +from pathlib import Path +from typing import Dict, Set + +# File names that contain `tempfile.NamedTemporaryFile` but are known to be correct. +# The key is the file name, the value is a set of lines stripped that contain `NamedTemporaryFile(` that are known to be correct. +# This file (test_named_temporary_file.py) is automatically excluded. +known_entries: Dict[str, Set[str]] = { + "tests/pytest/test_poll.py": { + "tmpfile = tempfile.NamedTemporaryFile(delete=False)", + "tmpfile1 = tempfile.NamedTemporaryFile(delete=False)", + } +} + +# Trim all line values of `known_entries` +for k, v in known_entries.items(): + known_entries[k] = {x.strip() for x in v} + + +def test_named_temporary_file_is_not_used(): + """ + Windows does not work well with tempfile.NamedTemporaryFile. + + * https://github.com/python/cpython/issues/58451 + * https://github.com/appveyor/ci/issues/2547 + * https://github.com/marickmanrho/pip-audit/commit/086ea4d684b41b795d9505b51ce7d079c990dca6 + * https://github.com/IdentityPython/pysaml2/pull/665/files + * https://github.com/aws-cloudformation/cloudformation-cli/pull/924/files + + Fair fix: + * Use a temp dir and create the file in the temp dir. On exit, the dir will be deleted. + * https://stackoverflow.com/a/77536782/591574 + Possible future fix: + * https://github.com/marickmanrho/pip-audit/commit/086ea4d684b41b795d9505b51ce7d079c990dca6 + """ + + root_here = Path(__file__).parent.parent.parent + + dir_content = [ + *glob.glob("shiny/**/*.py", root_dir=root_here, recursive=True), + *glob.glob("tests/**/*.py", root_dir=root_here, recursive=True), + ] + + search_string = "NamedTemporaryFile(" + + bad_entries: list[tuple[str, int, str]] = [] + + # For every python file... + for p in dir_content: + path = Path(root_here, p) + # Skip if dir + if path.is_dir(): + continue + + # Skip this file + if path.name in {"test_named_temporary_file.py"}: + continue + + with open(path, "r") as f: + # Read file contents + txt = f.read() + + # Skip if search string is not in file + if search_string not in txt: + continue + + # Split file contents by line + lines = txt.split("\n") + known_lines = known_entries.get(str(p), set()) + + # If the search string is in the line + # and the line is not in the known lines, + # add it to the bad entries + for i, line in enumerate(lines): + line = line.strip() + if search_string in line and (line not in known_lines): + bad_entries.append((p, i + 1, line)) + + assert ( + len(bad_entries) == 0 + ), f"Unexpected files containing `TemporaryDirectory`: {str(bad_entries)}" From dd2593e186eac3946c1a180212c94b35e75bacc7 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 16:27:05 -0400 Subject: [PATCH 52/95] Allow for windows testing to possibly produce errors --- tests/pytest/test_theme.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/pytest/test_theme.py b/tests/pytest/test_theme.py index 1bfc42b87..2d053ab68 100644 --- a/tests/pytest/test_theme.py +++ b/tests/pytest/test_theme.py @@ -21,7 +21,7 @@ shiny_theme_presets_bundled, ) -from ._utils import skip_on_windows +# from ._utils import skip_on_windows def test_theme_stores_values_correctly(): @@ -80,7 +80,7 @@ def test_theme_preset_must_be_valid(): Theme("not_a_valid_preset") # type: ignore -@skip_on_windows +# @skip_on_windows @pytest.mark.parametrize("preset", shiny_theme_presets) def test_theme_css_compiles_and_is_cached(preset: ShinyThemePreset): theme = Theme(preset) @@ -159,7 +159,7 @@ def _page_sidebar(*args, **kwargs) -> Tag: # type: ignore return page_sidebar(sidebar("Sidebar"), *args, **kwargs) # type: ignore -@skip_on_windows +# @skip_on_windows @pytest.mark.parametrize( "page_fn", [ From 493a64703e449b3deba8aedd06b38042c4e40384 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 16:27:51 -0400 Subject: [PATCH 53/95] Update test_named_temporary_file.py --- tests/pytest/test_named_temporary_file.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/pytest/test_named_temporary_file.py b/tests/pytest/test_named_temporary_file.py index 3622983e8..3f9fdc94e 100644 --- a/tests/pytest/test_named_temporary_file.py +++ b/tests/pytest/test_named_temporary_file.py @@ -33,7 +33,8 @@ def test_named_temporary_file_is_not_used(): * Use a temp dir and create the file in the temp dir. On exit, the dir will be deleted. * https://stackoverflow.com/a/77536782/591574 Possible future fix: - * https://github.com/marickmanrho/pip-audit/commit/086ea4d684b41b795d9505b51ce7d079c990dca6 + * Related Issue: https://github.com/pypa/pip-audit/issues/646 + * Their fix: https://github.com/marickmanrho/pip-audit/commit/086ea4d684b41b795d9505b51ce7d079c990dca6#diff-a182a096790cc91a1771db39e19b337dec83c579775e46a45956a463b903b616 """ root_here = Path(__file__).parent.parent.parent From 4f4f5f61839ed30d825d81025aeee3bcf113bca9 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 16:49:02 -0400 Subject: [PATCH 54/95] Use windows friendly back arrow --- shiny/_template_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shiny/_template_utils.py b/shiny/_template_utils.py index c870cd353..a974b8147 100644 --- a/shiny/_template_utils.py +++ b/shiny/_template_utils.py @@ -33,7 +33,8 @@ ) # Prebuild some common choices cancel_choice: Choice = Choice(title=[("class:secondary", "[Cancel]")], value="cancel") -back_choice: Choice = Choice(title=[("class:secondary", "← Back")], value="back") +# Use windows friendly unicode value for back arrow +back_choice: Choice = Choice(title=[("class:secondary", "\u2190 Back")], value="back") def choice_from_dict(choice_dict: dict[str, str]) -> list[Choice]: From 49863791b88a6776ee7dec49bd13e67eea499d46 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 23 Jul 2024 16:50:33 -0400 Subject: [PATCH 55/95] Revert "Allow for windows testing to possibly produce errors" This reverts commit dd2593e186eac3946c1a180212c94b35e75bacc7. --- tests/pytest/test_theme.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/pytest/test_theme.py b/tests/pytest/test_theme.py index 2d053ab68..1bfc42b87 100644 --- a/tests/pytest/test_theme.py +++ b/tests/pytest/test_theme.py @@ -21,7 +21,7 @@ shiny_theme_presets_bundled, ) -# from ._utils import skip_on_windows +from ._utils import skip_on_windows def test_theme_stores_values_correctly(): @@ -80,7 +80,7 @@ def test_theme_preset_must_be_valid(): Theme("not_a_valid_preset") # type: ignore -# @skip_on_windows +@skip_on_windows @pytest.mark.parametrize("preset", shiny_theme_presets) def test_theme_css_compiles_and_is_cached(preset: ShinyThemePreset): theme = Theme(preset) @@ -159,7 +159,7 @@ def _page_sidebar(*args, **kwargs) -> Tag: # type: ignore return page_sidebar(sidebar("Sidebar"), *args, **kwargs) # type: ignore -# @skip_on_windows +@skip_on_windows @pytest.mark.parametrize( "page_fn", [ From 8fac2e5fd86e735396a0a3752254968c5c4d6638 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 10:30:50 -0400 Subject: [PATCH 56/95] Assert all lines are seen and files are processed --- tests/pytest/test_named_temporary_file.py | 32 ++++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/tests/pytest/test_named_temporary_file.py b/tests/pytest/test_named_temporary_file.py index 3f9fdc94e..83f264e30 100644 --- a/tests/pytest/test_named_temporary_file.py +++ b/tests/pytest/test_named_temporary_file.py @@ -38,19 +38,21 @@ def test_named_temporary_file_is_not_used(): """ root_here = Path(__file__).parent.parent.parent + shiny_files = glob.glob(str(root_here / "shiny" / "**" / "*.py"), recursive=True) + tests_files = glob.glob(str(root_here / "tests" / "**" / "*.py"), recursive=True) - dir_content = [ - *glob.glob("shiny/**/*.py", root_dir=root_here, recursive=True), - *glob.glob("tests/**/*.py", root_dir=root_here, recursive=True), - ] + assert len(shiny_files) > 0 + assert len(tests_files) > 0 + + all_files = [*shiny_files, *tests_files] search_string = "NamedTemporaryFile(" - bad_entries: list[tuple[str, int, str]] = [] + bad_entries: list[tuple[Path, int, str]] = [] # For every python file... - for p in dir_content: - path = Path(root_here, p) + for path in all_files: + path = Path(path) # Skip if dir if path.is_dir(): continue @@ -69,15 +71,25 @@ def test_named_temporary_file_is_not_used(): # Split file contents by line lines = txt.split("\n") - known_lines = known_entries.get(str(p), set()) + rel_path = path.relative_to(root_here) + known_lines = known_entries.get(str(rel_path), set()) + seen_lines: set[str] = set() # If the search string is in the line # and the line is not in the known lines, # add it to the bad entries for i, line in enumerate(lines): line = line.strip() - if search_string in line and (line not in known_lines): - bad_entries.append((p, i + 1, line)) + if search_string in line: + seen_lines.add(line) + if line not in known_lines: + bad_entries.append((rel_path, i + 1, line)) + + if (len(known_lines) > 0) and (len(seen_lines) != len(known_lines)): + raise ValueError( + f"Lines not found in {rel_path}: {known_lines - seen_lines}" + "\nPlease remove them from the known_entries dictionary." + ) assert ( len(bad_entries) == 0 From a3c8a6e059e5fcda30967a3f6ea16d9d8c0a6ad1 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 11:01:00 -0400 Subject: [PATCH 57/95] Update test_named_temporary_file.py --- tests/pytest/test_named_temporary_file.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/pytest/test_named_temporary_file.py b/tests/pytest/test_named_temporary_file.py index 83f264e30..a96d2432c 100644 --- a/tests/pytest/test_named_temporary_file.py +++ b/tests/pytest/test_named_temporary_file.py @@ -4,6 +4,8 @@ from pathlib import Path from typing import Dict, Set +from tests.pytest._utils import skip_on_windows + # File names that contain `tempfile.NamedTemporaryFile` but are known to be correct. # The key is the file name, the value is a set of lines stripped that contain `NamedTemporaryFile(` that are known to be correct. # This file (test_named_temporary_file.py) is automatically excluded. @@ -19,6 +21,7 @@ known_entries[k] = {x.strip() for x in v} +@skip_on_windows def test_named_temporary_file_is_not_used(): """ Windows does not work well with tempfile.NamedTemporaryFile. From d9c86a0341ff77e58ffa8f8d103b339efeaafe25 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 11:04:24 -0400 Subject: [PATCH 58/95] Discard changes to shiny/_template_utils.py --- shiny/_template_utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shiny/_template_utils.py b/shiny/_template_utils.py index a974b8147..c870cd353 100644 --- a/shiny/_template_utils.py +++ b/shiny/_template_utils.py @@ -33,8 +33,7 @@ ) # Prebuild some common choices cancel_choice: Choice = Choice(title=[("class:secondary", "[Cancel]")], value="cancel") -# Use windows friendly unicode value for back arrow -back_choice: Choice = Choice(title=[("class:secondary", "\u2190 Back")], value="back") +back_choice: Choice = Choice(title=[("class:secondary", "← Back")], value="back") def choice_from_dict(choice_dict: dict[str, str]) -> list[Choice]: From 11a9ff442942f1c0cfb30037334849f4b668abe6 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 11:36:31 -0400 Subject: [PATCH 59/95] Apply suggestions from code review Co-authored-by: Winston Chang --- Makefile | 8 +++----- docs/Makefile | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index be22a2342..9a70a41bd 100644 --- a/Makefile +++ b/Makefile @@ -26,10 +26,10 @@ for line in sys.stdin: endef export PRINT_HELP_PYSCRIPT -BROWSER := python3 -c "$$BROWSER_PYSCRIPT" +BROWSER := python -c "$$BROWSER_PYSCRIPT" help: FORCE - @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts @@ -188,7 +188,6 @@ release: dist ## package and upload a release twine upload dist/* dist: clean ## builds source and wheel package - $(MAKE) clean pip install setuptools python setup.py sdist python setup.py bdist_wheel @@ -202,8 +201,7 @@ dist: clean ## builds source and wheel package install: dist pip uninstall -y shiny python -m pip install dist/shiny*.whl -ci-install-wheel: FORCE - $(MAKE) dist +ci-install-wheel: FORCE dist # make install uv pip uninstall shiny uv pip install dist/shiny*.whl diff --git a/docs/Makefile b/docs/Makefile index a7a9c0547..c863dccf0 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -24,13 +24,13 @@ for line in sys.stdin: endef export PRINT_HELP_PYSCRIPT -BROWSER := python3 -c "$$BROWSER_PYSCRIPT" +BROWSER := python -c "$$BROWSER_PYSCRIPT" help: FORCE - @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) deps: FORCE ## Install build dependencies - cd .. && $(MAKE) install- + cd .. && $(MAKE) install-docs quartodoc: quartodoc_build_core quartodoc_build_express quartodoc_build_test quartodoc_post ## Build quartodocs for express, core, and testing @@ -76,7 +76,7 @@ site: FORCE ## Build website (quarto render) quarto render serve: FORCE ## Build website and serve (quarto preview) - && quarto preview --port 8080 + quarto preview --port 8080 clean: FORCE ## Clean build artifacts rm -rf _inv api _site .quarto From 1eeb7ff55a27e3c6c4efba95a7c07fd9e147e9f5 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 11:38:06 -0400 Subject: [PATCH 60/95] Update Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9a70a41bd..ecabe5f9f 100644 --- a/Makefile +++ b/Makefile @@ -201,8 +201,8 @@ dist: clean ## builds source and wheel package install: dist pip uninstall -y shiny python -m pip install dist/shiny*.whl -ci-install-wheel: FORCE dist - # make install +ci-install-wheel: dist FORCE + # `uv` version of `make install` uv pip uninstall shiny uv pip install dist/shiny*.whl From 8607638b905f9c3fe52df0533ce55ce43fa8c79d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 11:45:38 -0400 Subject: [PATCH 61/95] Do not build site except for `main` or branches that start with `docs-` --- .github/workflows/build-docs.yaml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 6a45560cc..7b98723c4 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -1,9 +1,13 @@ name: Build API docs and Shinylive for GitHub Pages +# Allow for `main` branch to build full website and deploy +# Allow branches that start with `docs-` to build full website, but not deploy +# Allow for PRs to build quartodoc only. (No shinylive, no site build, no deploy) + on: workflow_dispatch: push: - branches: ["main"] + branches: ["main", "docs-**"] pull_request: jobs: @@ -42,7 +46,7 @@ jobs: # Shinylive # ===================================================== - name: Check out shinylive - if: github.ref == 'refs/heads/main' + if: github.event_name != 'pull_request' uses: actions/checkout@v4 with: repository: rstudio/shinylive @@ -50,7 +54,7 @@ jobs: path: shinylive-repo - name: Update shinylive's copy of shiny and htmltools - if: github.ref == 'refs/heads/main' + if: github.event_name != 'pull_request' run: | cd shinylive-repo make submodules @@ -58,13 +62,13 @@ jobs: make submodules-pull-htmltools - name: Build shinylive - if: github.ref == 'refs/heads/main' + if: github.event_name != 'pull_request' run: | cd shinylive-repo make all - name: Use local build of shinylive for building docs - if: github.ref == 'refs/heads/main' + if: github.event_name != 'pull_request' run: | cd shinylive-repo && shinylive assets install-from-local ./build @@ -73,7 +77,7 @@ jobs: # ===================================================== - name: Build site - if: ${{ github.ref == 'refs/heads/main' || (!github.event.pull_request.draft) || startsWith(github.head_ref, 'docs') }} + if: github.event_name != 'pull_request' run: | cd docs make site From c2174fcb7cafb825bd70792b2115e4ae4301649a Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 13:35:34 -0400 Subject: [PATCH 62/95] Add skip to failing test (unknown reasons) --- .../chat/append_user_msg/test_chat_append_user_msg.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py index 1d4e614e6..3dae48166 100644 --- a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py +++ b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py @@ -5,6 +5,10 @@ def test_validate_chat_append_user_message(page: Page, local_app: ShinyAppProc) -> None: + import pytest + + pytest.skip("Fails. Needs investigation.") + page.goto(local_app.url) chat = controller.Chat(page, "chat") From d7a00ac8f0db396e03ca25de44d8692e28688fcc Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 13:48:37 -0400 Subject: [PATCH 63/95] Disable webkit on python 3.8, 3.9 --- .github/workflows/pytest.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 1ea839768..26b98dc8b 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -111,6 +111,12 @@ jobs: - python-version: ${{ github.event.pull_request.draft && '3.9' }} - browser: ${{ github.event.pull_request.draft && 'firefox' }} - browser: ${{ github.event.pull_request.draft && 'webkit' }} + # There are many unexplained tests that fail on webkit w/ python 3.8, 3.9 + # Given the more recent versions of python work, we will exclude this combination + - browser: "webkit" + python-version: "3.8" + - browser: "webkit" + python-version: "3.9" fail-fast: false steps: From 74d9f185a0308f30bc72175a9311a50944706751 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 13:50:34 -0400 Subject: [PATCH 64/95] Add skip to another failing test (unknown reasons) --- .../playwright/shiny/components/chat/basic/test_chat_basic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py index 2d1c3b147..f53ed3067 100644 --- a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py +++ b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py @@ -5,6 +5,10 @@ def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: + import pytest + + pytest.skip("Fails. Needs investigation.") + page.goto(local_app.url) chat = controller.Chat(page, "chat") From 0372f979556903953dfa4877fe2bfbcd55d45cac Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 14:03:53 -0400 Subject: [PATCH 65/95] Add skip to another failing test (unknown reasons) --- .../shiny/components/chat/stream/test_chat_stream.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py index e40868948..83e248a59 100644 --- a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py +++ b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py @@ -7,6 +7,9 @@ def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: + import pytest + + pytest.skip("Fails. Needs investigation.") page.goto(local_app.url) chat = controller.Chat(page, "chat") From 923115ca8d26510e921b270ebac35d6387c215a4 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 14:31:06 -0400 Subject: [PATCH 66/95] Reenable tests --- .../chat/append_user_msg/test_chat_append_user_msg.py | 4 ++-- .../playwright/shiny/components/chat/basic/test_chat_basic.py | 4 ++-- .../shiny/components/chat/stream/test_chat_stream.py | 4 ++-- .../shiny/components/chat/transform/test_chat_transform.py | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py index 3dae48166..7655f4f58 100644 --- a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py +++ b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py @@ -5,9 +5,9 @@ def test_validate_chat_append_user_message(page: Page, local_app: ShinyAppProc) -> None: - import pytest + # import pytest - pytest.skip("Fails. Needs investigation.") + # pytest.skip("Fails. Needs investigation.") page.goto(local_app.url) diff --git a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py index f53ed3067..e97d3e264 100644 --- a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py +++ b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py @@ -5,9 +5,9 @@ def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: - import pytest + # import pytest - pytest.skip("Fails. Needs investigation.") + # pytest.skip("Fails. Needs investigation.") page.goto(local_app.url) diff --git a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py index 83e248a59..a45875a41 100644 --- a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py +++ b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py @@ -7,9 +7,9 @@ def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: - import pytest + # import pytest - pytest.skip("Fails. Needs investigation.") + # pytest.skip("Fails. Needs investigation.") page.goto(local_app.url) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py index bce40b89a..23fd412b8 100644 --- a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py +++ b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py @@ -5,6 +5,9 @@ def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: + # import pytest + + # pytest.skip("Fails. Needs investigation.") page.goto(local_app.url) chat = controller.Chat(page, "chat") From 8a50dc384d939f9d1195d84124258ad0db5d43ce Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 14:31:36 -0400 Subject: [PATCH 67/95] Capture all console messages and display them on failed test --- tests/playwright/conftest.py | 58 +++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index efe5b5516..5779ca692 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -4,10 +4,18 @@ from __future__ import annotations from pathlib import PurePath +from typing import Generator import pytest -from playwright.sync_api import BrowserContext, Page +from playwright.sync_api import ( + BrowserContext, + ConsoleMessage, + JSHandle, + Page, + SourceLocation, +) +from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName from shiny.pytest import create_app_fixture @@ -40,11 +48,21 @@ def session_page(browser: BrowserContext) -> Page: return browser.new_page() +class ConsoleMessageInfo(TypedDict): + type: str + text: str + location: SourceLocation + args: list[JSHandle] + + @pytest.fixture(scope="function") # By going to `about:blank`, we _reset_ the page to a known state before each test. # It is not perfect, but it is faster than making a new page for each test. # This must be done before each test -def page(session_page: Page) -> Page: +def page( + request: pytest.FixtureRequest, + session_page: Page, +) -> Generator[Page, None, None]: """ Reset the given page to a known state before each test. @@ -53,12 +71,44 @@ def page(session_page: Page) -> Page: The default viewport size is set to 1920 x 1080 (1080p) for each test function. Parameters: - session_page (Page): The page to reset. + session_page (Page): The page to reset before each test. """ session_page.goto("about:blank") # Reset screen size to 1080p session_page.set_viewport_size({"width": 1920, "height": 1080}) - return session_page + + console_msgs: list[ConsoleMessageInfo] = [] + + def on_console_msg(msg: ConsoleMessage) -> None: + # Do not report missing favicon errors + if msg.location["url"].endswith("favicon.ico"): + return + if msg.type == "warning" and msg.text.startswith("DEPRECATED:"): + return + # console_msgs.append(msg.text) + console_msgs.append( + { + "type": msg.type, + "text": msg.text, + "location": msg.location, + "args": msg.args, + } + ) + + session_page.on("console", on_console_msg) + + yield session_page + + session_page.remove_listener("console", on_console_msg) + + if request.session.testsfailed: + if len(console_msgs) > 0: + print("+++++++++ Browser console log ++++++++") + for msg in console_msgs: + print(msg) + print("+++++++++ / Browser console log ++++++++") + else: + print("No browser console messages captured.") def create_example_fixture( From 681ef405e9896f553bf356408c6546b26bc63fcf Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 15:07:39 -0400 Subject: [PATCH 68/95] Add a screenshot for failed tests; Set output dir to `test-results` --- pytest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 936ed0305..6e026f30f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,5 +2,5 @@ asyncio_mode=strict testpaths=tests/pytest/ ; Note: Browsers are set within `./Makefile` -addopts = --strict-markers --durations=6 --durations-min=5.0 --numprocesses auto --tracing=retain-on-failure --video=retain-on-failure +addopts = --strict-markers --durations=6 --durations-min=5.0 --numprocesses auto --tracing=retain-on-failure --video=retain-on-failure --screenshot=only-on-failure --full-page-screenshot --output="test-results" verbosity_test_cases=2 From 8ea81d919d6219974d3922cb1a140e8e85ad3ccf Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 15:09:14 -0400 Subject: [PATCH 69/95] Disable sneaky page meant for speedup and use playwright page for video debugging --- tests/playwright/conftest.py | 180 ++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 89 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 5779ca692..9d276aa45 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -4,21 +4,23 @@ from __future__ import annotations from pathlib import PurePath -from typing import Generator - -import pytest -from playwright.sync_api import ( - BrowserContext, - ConsoleMessage, - JSHandle, - Page, - SourceLocation, -) -from shiny._typing_extensions import TypedDict +# from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName from shiny.pytest import create_app_fixture +# from typing import Generator + +# import pytest +# from playwright.sync_api import ( +# BrowserContext, +# ConsoleMessage, +# JSHandle, +# Page, +# SourceLocation, +# ) + + __all__ = ( "create_doc_example_fixture", "create_example_fixture", @@ -31,84 +33,84 @@ here_root = here.parent.parent -# Make a single page fixture that can be used by all tests -@pytest.fixture(scope="session") -# By using a single page, the browser is only launched once and all tests run in the same tab / page. -def session_page(browser: BrowserContext) -> Page: - """ - Create a new page within the given browser context. - - Parameters: - browser (BrowserContext): The browser context in which to create the new page. - - Returns: - Page: The newly created page. - - """ - return browser.new_page() - - -class ConsoleMessageInfo(TypedDict): - type: str - text: str - location: SourceLocation - args: list[JSHandle] - - -@pytest.fixture(scope="function") -# By going to `about:blank`, we _reset_ the page to a known state before each test. -# It is not perfect, but it is faster than making a new page for each test. -# This must be done before each test -def page( - request: pytest.FixtureRequest, - session_page: Page, -) -> Generator[Page, None, None]: - """ - Reset the given page to a known state before each test. - - The page is built on the session_page, which is maintained over the full session. - The page will visit "about:blank" to reset between apps. - The default viewport size is set to 1920 x 1080 (1080p) for each test function. - - Parameters: - session_page (Page): The page to reset before each test. - """ - session_page.goto("about:blank") - # Reset screen size to 1080p - session_page.set_viewport_size({"width": 1920, "height": 1080}) - - console_msgs: list[ConsoleMessageInfo] = [] - - def on_console_msg(msg: ConsoleMessage) -> None: - # Do not report missing favicon errors - if msg.location["url"].endswith("favicon.ico"): - return - if msg.type == "warning" and msg.text.startswith("DEPRECATED:"): - return - # console_msgs.append(msg.text) - console_msgs.append( - { - "type": msg.type, - "text": msg.text, - "location": msg.location, - "args": msg.args, - } - ) - - session_page.on("console", on_console_msg) - - yield session_page - - session_page.remove_listener("console", on_console_msg) - - if request.session.testsfailed: - if len(console_msgs) > 0: - print("+++++++++ Browser console log ++++++++") - for msg in console_msgs: - print(msg) - print("+++++++++ / Browser console log ++++++++") - else: - print("No browser console messages captured.") +# # Make a single page fixture that can be used by all tests +# @pytest.fixture(scope="session") +# # By using a single page, the browser is only launched once and all tests run in the same tab / page. +# def session_page(browser: BrowserContext) -> Page: +# """ +# Create a new page within the given browser context. + +# Parameters: +# browser (BrowserContext): The browser context in which to create the new page. + +# Returns: +# Page: The newly created page. + +# """ +# return browser.new_page() + + +# class ConsoleMessageInfo(TypedDict): +# type: str +# text: str +# location: SourceLocation +# args: list[JSHandle] + + +# @pytest.fixture(scope="function") +# # By going to `about:blank`, we _reset_ the page to a known state before each test. +# # It is not perfect, but it is faster than making a new page for each test. +# # This must be done before each test +# def page( +# request: pytest.FixtureRequest, +# session_page: Page, +# ) -> Generator[Page, None, None]: +# """ +# Reset the given page to a known state before each test. + +# The page is built on the session_page, which is maintained over the full session. +# The page will visit "about:blank" to reset between apps. +# The default viewport size is set to 1920 x 1080 (1080p) for each test function. + +# Parameters: +# session_page (Page): The page to reset before each test. +# """ +# session_page.goto("about:blank") +# # Reset screen size to 1080p +# session_page.set_viewport_size({"width": 1920, "height": 1080}) + +# console_msgs: list[ConsoleMessageInfo] = [] + +# def on_console_msg(msg: ConsoleMessage) -> None: +# # Do not report missing favicon errors +# if msg.location["url"].endswith("favicon.ico"): +# return +# if msg.type == "warning" and msg.text.startswith("DEPRECATED:"): +# return +# # console_msgs.append(msg.text) +# console_msgs.append( +# { +# "type": msg.type, +# "text": msg.text, +# "location": msg.location, +# "args": msg.args, +# } +# ) + +# session_page.on("console", on_console_msg) + +# yield session_page + +# session_page.remove_listener("console", on_console_msg) + +# if request.session.testsfailed: +# if len(console_msgs) > 0: +# print("+++++++++ Browser console log ++++++++") +# for msg in console_msgs: +# print(msg) +# print("+++++++++ / Browser console log ++++++++") +# else: +# print("No browser console messages captured.") def create_example_fixture( From bb73e50049b3a8c9cd68d839f10bfb29e419acb0 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 15:22:23 -0400 Subject: [PATCH 70/95] Use `page_chat` to slow down default wait time across board --- tests/playwright/conftest.py | 10 ++++++++++ .../chat/append_user_msg/test_chat_append_user_msg.py | 9 ++++----- .../shiny/components/chat/basic/test_chat_basic.py | 7 ++----- .../shiny/components/chat/errors/test_chat_errors.py | 3 ++- .../shiny/components/chat/stream/test_chat_stream.py | 6 ++---- .../components/chat/transform/test_chat_transform.py | 6 ++---- .../test_chat_transform_assistant.py | 5 ++++- 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 9d276aa45..5452b7f7b 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -149,3 +149,13 @@ def create_doc_example_express_fixture( ): """Used to create app fixtures from ``app-express.py`` example apps in py-shiny/shiny/api-examples""" return create_doc_example_fixture(example_name, "app-express.py", scope) + + +import pytest +from playwright.sync_api import Page + + +@pytest.fixture(scope="function") +def page_chat(page: Page) -> Page: + page.set_default_timeout(30 * 1000) + return page diff --git a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py index 7655f4f58..e4968668d 100644 --- a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py +++ b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py @@ -4,11 +4,10 @@ from shiny.run import ShinyAppProc -def test_validate_chat_append_user_message(page: Page, local_app: ShinyAppProc) -> None: - # import pytest - - # pytest.skip("Fails. Needs investigation.") - +def test_validate_chat_append_user_message( + page_chat: Page, local_app: ShinyAppProc +) -> None: + page = page_chat page.goto(local_app.url) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py index e97d3e264..1f3b51cb6 100644 --- a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py +++ b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py @@ -4,11 +4,8 @@ from shiny.run import ShinyAppProc -def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: - # import pytest - - # pytest.skip("Fails. Needs investigation.") - +def test_validate_chat_basic(page_chat: Page, local_app: ShinyAppProc) -> None: + page = page_chat page.goto(local_app.url) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py index c0401f88d..a78c23398 100644 --- a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py +++ b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py @@ -4,7 +4,8 @@ from shiny.run import ShinyAppProc -def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: +def test_validate_chat_basic(page_chat: Page, local_app: ShinyAppProc) -> None: + page = page_chat page.goto(local_app.url) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py index a45875a41..5f015808c 100644 --- a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py +++ b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py @@ -6,10 +6,8 @@ from shiny.run import ShinyAppProc -def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: - # import pytest - - # pytest.skip("Fails. Needs investigation.") +def test_validate_chat(page_chat: Page, local_app: ShinyAppProc) -> None: + page = page_chat page.goto(local_app.url) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py index 23fd412b8..305fba93a 100644 --- a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py +++ b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py @@ -4,10 +4,8 @@ from shiny.run import ShinyAppProc -def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: - # import pytest - - # pytest.skip("Fails. Needs investigation.") +def test_validate_chat_transform(page_chat: Page, local_app: ShinyAppProc) -> None: + page = page_chat page.goto(local_app.url) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py index 0f16784af..28b1ce36e 100644 --- a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py +++ b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py @@ -5,7 +5,10 @@ from shiny.run import ShinyAppProc -def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) -> None: +def test_validate_chat_transform_assistant( + page_chat: Page, local_app: ShinyAppProc +) -> None: + page = page_chat page.goto(local_app.url) chat = controller.Chat(page, "chat") From 43b4a27690a8394ab6a01f5c2cca636a4828057b Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 15:30:56 -0400 Subject: [PATCH 71/95] Update test_chat_append_user_msg.py --- .../chat/append_user_msg/test_chat_append_user_msg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py index e4968668d..d50289ccd 100644 --- a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py +++ b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py @@ -14,7 +14,7 @@ def test_validate_chat_append_user_message( # Verify starting state expect(chat.loc).to_be_visible() - chat.expect_latest_message("A user message") + chat.expect_latest_message("A user message", timeout=30 * 1000) # Verify that the message state is as expected message_state = controller.OutputCode(page, "message_state") From df2a0cbe3b5bcb5f4d5d3da19854e67ef4b8cef1 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 16:12:27 -0400 Subject: [PATCH 72/95] Add a `wait_for_idle_app()` at beginning of each chat test --- tests/playwright/conftest.py | 34 ++++++++++++++----- .../test_chat_append_user_msg.py | 9 +++-- .../components/chat/basic/test_chat_basic.py | 5 +-- .../chat/errors/test_chat_errors.py | 5 +-- .../chat/stream/test_chat_stream.py | 5 +-- .../chat/transform/test_chat_transform.py | 5 +-- .../test_chat_transform_assistant.py | 7 ++-- 7 files changed, 44 insertions(+), 26 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 5452b7f7b..7e47e29f5 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -1,10 +1,13 @@ # This file is necessary for pytest to find relative module files # such as examples/example_apps.py - from __future__ import annotations from pathlib import PurePath +from playwright.sync_api import Page + +from shiny.playwright.expect import expect_not_to_have_class + # from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName from shiny.pytest import create_app_fixture @@ -151,11 +154,24 @@ def create_doc_example_express_fixture( return create_doc_example_fixture(example_name, "app-express.py", scope) -import pytest -from playwright.sync_api import Page - - -@pytest.fixture(scope="function") -def page_chat(page: Page) -> Page: - page.set_default_timeout(30 * 1000) - return page +def wait_for_idle_app( + page: Page, + *, + timeout: int = 30 * 1000, +) -> None: + """ + Wait for the app to not be busy (even if for a moment). + + Parameters + ---------- + page + The page to wait for. + timeout + The maximum time to wait for the app's `html` element to not have the `shiny-busy` class. + """ + + expect_not_to_have_class( + page.locator("html"), + "shiny-busy", + timeout=timeout, + ) diff --git a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py index d50289ccd..65742be54 100644 --- a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py +++ b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py @@ -1,20 +1,19 @@ +from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller from shiny.run import ShinyAppProc -def test_validate_chat_append_user_message( - page_chat: Page, local_app: ShinyAppProc -) -> None: - page = page_chat +def test_validate_chat_append_user_message(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) + wait_for_idle_app(page) chat = controller.Chat(page, "chat") # Verify starting state expect(chat.loc).to_be_visible() - chat.expect_latest_message("A user message", timeout=30 * 1000) + chat.expect_latest_message("A user message") # Verify that the message state is as expected message_state = controller.OutputCode(page, "message_state") diff --git a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py index 1f3b51cb6..e7b52eeb5 100644 --- a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py +++ b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py @@ -1,12 +1,13 @@ +from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller from shiny.run import ShinyAppProc -def test_validate_chat_basic(page_chat: Page, local_app: ShinyAppProc) -> None: - page = page_chat +def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) + wait_for_idle_app(page) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py index a78c23398..e0bbbe1c9 100644 --- a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py +++ b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py @@ -1,12 +1,13 @@ +from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller from shiny.run import ShinyAppProc -def test_validate_chat_basic(page_chat: Page, local_app: ShinyAppProc) -> None: - page = page_chat +def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) + wait_for_idle_app(page) chat = controller.Chat(page, "chat") expect(chat.loc).to_be_visible() diff --git a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py index 5f015808c..9bc841183 100644 --- a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py +++ b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py @@ -1,14 +1,15 @@ import re +from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller from shiny.run import ShinyAppProc -def test_validate_chat(page_chat: Page, local_app: ShinyAppProc) -> None: - page = page_chat +def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) + wait_for_idle_app(page) chat = controller.Chat(page, "chat") message_state = controller.OutputCode(page, "message_state") diff --git a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py index 305fba93a..3465f4f86 100644 --- a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py +++ b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py @@ -1,12 +1,13 @@ +from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller from shiny.run import ShinyAppProc -def test_validate_chat_transform(page_chat: Page, local_app: ShinyAppProc) -> None: - page = page_chat +def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) + wait_for_idle_app(page) chat = controller.Chat(page, "chat") diff --git a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py index 28b1ce36e..611867744 100644 --- a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py +++ b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py @@ -1,3 +1,4 @@ +from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny import ui @@ -5,11 +6,9 @@ from shiny.run import ShinyAppProc -def test_validate_chat_transform_assistant( - page_chat: Page, local_app: ShinyAppProc -) -> None: - page = page_chat +def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) + wait_for_idle_app(page) chat = controller.Chat(page, "chat") From baf093a039a31e406794af95d55c68711832ff98 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 16:35:28 -0400 Subject: [PATCH 73/95] Try waiting for shiny elements to have been bound before waiting for non-busy --- tests/playwright/conftest.py | 6 +++++- tests/playwright/shiny/components/chat/errors/app.py | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 7e47e29f5..62a397363 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -4,7 +4,7 @@ from pathlib import PurePath -from playwright.sync_api import Page +from playwright.sync_api import Page, expect from shiny.playwright.expect import expect_not_to_have_class @@ -170,6 +170,10 @@ def wait_for_idle_app( The maximum time to wait for the app's `html` element to not have the `shiny-busy` class. """ + # Wait for page to exist + expect(page.locator(".shiny-bound-output")).not_to_have_count(0, timeout=timeout) + + # Wait for the app to not be busy expect_not_to_have_class( page.locator("html"), "shiny-busy", diff --git a/tests/playwright/shiny/components/chat/errors/app.py b/tests/playwright/shiny/components/chat/errors/app.py index bc699ba6c..7d11dd189 100644 --- a/tests/playwright/shiny/components/chat/errors/app.py +++ b/tests/playwright/shiny/components/chat/errors/app.py @@ -1,4 +1,4 @@ -from shiny.express import ui +from shiny.express import render, ui # Set some Shiny page options ui.page_opts(title="Hello Chat") @@ -11,3 +11,9 @@ @chat.on_user_submit async def _(): raise Exception("boom!") + + +# Placeholder to help determine when shiny has loaded via `.shiny-bound-output` being present +@render.ui +def _(): + return "" From 17fcb22035cc27d85453063180caa43ef5b64aae Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 24 Jul 2024 16:44:45 -0400 Subject: [PATCH 74/95] Rather than a function, just set the timeout variable directly --- tests/playwright/conftest.py | 31 ------------------- .../test_chat_append_user_msg.py | 4 +-- .../components/chat/basic/test_chat_basic.py | 4 +-- .../chat/errors/test_chat_errors.py | 4 +-- .../chat/stream/test_chat_stream.py | 4 +-- .../chat/transform/test_chat_transform.py | 7 +++-- .../test_chat_transform_assistant.py | 4 +-- 7 files changed, 9 insertions(+), 49 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 62a397363..117467d02 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -4,10 +4,6 @@ from pathlib import PurePath -from playwright.sync_api import Page, expect - -from shiny.playwright.expect import expect_not_to_have_class - # from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName from shiny.pytest import create_app_fixture @@ -152,30 +148,3 @@ def create_doc_example_express_fixture( ): """Used to create app fixtures from ``app-express.py`` example apps in py-shiny/shiny/api-examples""" return create_doc_example_fixture(example_name, "app-express.py", scope) - - -def wait_for_idle_app( - page: Page, - *, - timeout: int = 30 * 1000, -) -> None: - """ - Wait for the app to not be busy (even if for a moment). - - Parameters - ---------- - page - The page to wait for. - timeout - The maximum time to wait for the app's `html` element to not have the `shiny-busy` class. - """ - - # Wait for page to exist - expect(page.locator(".shiny-bound-output")).not_to_have_count(0, timeout=timeout) - - # Wait for the app to not be busy - expect_not_to_have_class( - page.locator("html"), - "shiny-busy", - timeout=timeout, - ) diff --git a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py index 65742be54..40e236c90 100644 --- a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py +++ b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py @@ -1,4 +1,3 @@ -from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller @@ -7,13 +6,12 @@ def test_validate_chat_append_user_message(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) - wait_for_idle_app(page) chat = controller.Chat(page, "chat") # Verify starting state expect(chat.loc).to_be_visible() - chat.expect_latest_message("A user message") + chat.expect_latest_message("A user message", timeout=30 * 1000) # Verify that the message state is as expected message_state = controller.OutputCode(page, "message_state") diff --git a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py index e7b52eeb5..36e84e853 100644 --- a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py +++ b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py @@ -1,4 +1,3 @@ -from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller @@ -7,14 +6,13 @@ def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) - wait_for_idle_app(page) chat = controller.Chat(page, "chat") # Verify starting state expect(chat.loc).to_be_visible() initial_message = "Hello! How can I help you today?" - chat.expect_latest_message(initial_message) + chat.expect_latest_message(initial_message, timeout=30 * 1000) # Verify user input is empty and input button / enter is disabled chat.expect_user_input("") diff --git a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py index e0bbbe1c9..7027e01c5 100644 --- a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py +++ b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py @@ -1,4 +1,3 @@ -from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller @@ -7,14 +6,13 @@ def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) - wait_for_idle_app(page) chat = controller.Chat(page, "chat") expect(chat.loc).to_be_visible() chat.set_user_input("Hello!") chat.send_user_input() - chat.expect_latest_message("Hello!") + chat.expect_latest_message("Hello!", timeout=30 * 1000) error_loc = page.locator(".shiny-notification-error") expect(error_loc).to_be_visible() diff --git a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py index 9bc841183..8fb751082 100644 --- a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py +++ b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py @@ -1,6 +1,5 @@ import re -from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller @@ -9,7 +8,6 @@ def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) - wait_for_idle_app(page) chat = controller.Chat(page, "chat") message_state = controller.OutputCode(page, "message_state") @@ -25,7 +23,7 @@ def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: "FIFTH FIFTH FIFTH", ] # Allow for any whitespace between messages - chat.expect_messages(re.compile(r"\s*".join(messages))) + chat.expect_messages(re.compile(r"\s*".join(messages)), timeout=30 * 1000) message_state_expected = tuple( [{"content": message, "role": "assistant"} for message in messages] diff --git a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py index 3465f4f86..1787ef6b1 100644 --- a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py +++ b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py @@ -1,4 +1,3 @@ -from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny.playwright import controller @@ -7,7 +6,6 @@ def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) - wait_for_idle_app(page) chat = controller.Chat(page, "chat") @@ -17,7 +15,10 @@ def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: user_msg = "hello" chat.set_user_input(user_msg) chat.send_user_input() - chat.expect_latest_message(f"Transformed input: {user_msg.upper()}") + chat.expect_latest_message( + f"Transformed input: {user_msg.upper()}", + timeout=30 * 1000, + ) user_msg2 = "return None" chat.set_user_input(user_msg2) diff --git a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py index 611867744..75b3c5f78 100644 --- a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py +++ b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py @@ -1,4 +1,3 @@ -from conftest import wait_for_idle_app from playwright.sync_api import Page, expect from shiny import ui @@ -8,7 +7,6 @@ def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) - wait_for_idle_app(page) chat = controller.Chat(page, "chat") @@ -19,7 +17,7 @@ def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) chat.set_user_input(user_msg) chat.send_user_input() code = chat.loc_latest_message.locator("code") - expect(code).to_have_text("hello") + expect(code).to_have_text("hello", timeout=30 * 1000) user_msg2 = "return HTML" chat.set_user_input(user_msg2) From a73a00e87387d54e1dd8ebcf9228bd5f5b144ab0 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 14:40:06 -0400 Subject: [PATCH 75/95] Allow slower execution time; Do not use 4 processes --- .github/workflows/pytest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 26b98dc8b..893c8c791 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -133,9 +133,9 @@ jobs: browser: ${{ matrix.browser }} - name: Run End-to-End tests - timeout-minutes: 20 + timeout-minutes: 60 run: | - make playwright-shiny SUB_FILE=". --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + make playwright-shiny SUB_FILE="." ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() with: From 1f436cc39cb684ac99678624d207e392150ff548 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 15:07:22 -0400 Subject: [PATCH 76/95] Disable playwright-diagnostics for webkit as it's VERY slow Related https://github.com/microsoft/playwright/issues/18119 --- .github/py-shiny/pytest-browsers/action.yaml | 26 +++++++++++++++++++- .github/workflows/pytest.yaml | 16 ++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/.github/py-shiny/pytest-browsers/action.yaml b/.github/py-shiny/pytest-browsers/action.yaml index 4d3eaa393..6e1b61807 100644 --- a/.github/py-shiny/pytest-browsers/action.yaml +++ b/.github/py-shiny/pytest-browsers/action.yaml @@ -2,17 +2,27 @@ name: 'Trim down pytest browsers' description: 'Trim down pytest browsers so the browser tabs are not shut down between tests, speeding up testing.' inputs: browser: - description: 'Browser to use for testing' + description: 'Browser to use for testing. Currently supports `chromium`, `firefox`, and `webkit`.' required: false default: '' all-browsers: description: 'Force all pytest browsers to used when testing' required: false default: 'false' + disable-playwright-diagnostics: + description: 'Disable playwright diagnostics.' + required: false + default: 'true' outputs: browsers: description: 'pytest browsers to use' value: ${{ steps.browsers.outputs.browsers }} + has-playwright-diagnostics: + description: 'Whether playwright diagnostics have been enabled' + value: ${{ steps.browsers.outputs.has-playwright-diagnostics }} + playwright-diagnostic-args: + description: 'Args to supply to `make playwright` like commands.' + value: ${{ steps.browsers.outputs.playwright-diagnostic-args }} runs: using: "composite" steps: @@ -20,8 +30,22 @@ runs: shell: bash id: browsers run: | + # Use temp output variable to set default behavior + + echo 'has-playwright-diagnostics=true' >> "$GITHUB_OUTPUT" + echo 'playwright-diagnostic-args="' >> "$GITHUB_OUTPUT" + if [ "${{ inputs.browser }}" != "" ]; then BROWSER="${{ inputs.browser }}" + + if [ "${{ inputs.disable-playwright-diagnostics }}" == "true" ]; then + echo "Disabling playwright diagnostics!" + echo 'has-playwright-diagnostics=false' >> "$GITHUB_OUTPUT" + echo 'playwright-diagnostic-args="--tracing off --video off --screenshot off' >> "$GITHUB_OUTPUT" + else + echo "Using webkit diagnostics!" + fi + if [ "$BROWSER" == "chromium" ] || [ "$BROWSER" == "firefox" ] || [ "$BROWSER" == "webkit" ]; then echo "Using custom browser $BROWSER !" echo "browsers=PYTEST_BROWSERS=\"--browser $BROWSER\"" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 893c8c791..2f12063db 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -131,13 +131,16 @@ jobs: id: browsers with: browser: ${{ matrix.browser }} + # If anything other than `true`, it will heavily reduce webkit performance + # Related: https://github.com/microsoft/playwright/issues/18119 + disable-playwright-diagnostics: ${{ matrix.browser == 'webkit' }} - name: Run End-to-End tests timeout-minutes: 60 run: | - make playwright-shiny SUB_FILE="." ${{ steps.browsers.outputs.browsers }} + make playwright-shiny SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 - if: failure() + if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: name: "playright-shiny-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" path: test-results/ @@ -169,6 +172,9 @@ jobs: id: browsers with: browser: ${{ matrix.browser }} + # If anything other than `true`, it will heavily reduce webkit performance + # Related: https://github.com/microsoft/playwright/issues/18119 + disable-playwright-diagnostics: ${{ matrix.browser == 'webkit' }} - name: Install node.js uses: actions/setup-node@v4 @@ -182,11 +188,11 @@ jobs: npm ci - name: Run example app tests - timeout-minutes: 20 + timeout-minutes: 60 run: | - make playwright-examples SUB_FILE=". --numprocesses 4" ${{ steps.browsers.outputs.browsers }} + make playwright-examples SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 - if: failure() + if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" path: test-results/ From 1dfc3086d80d47fe9ab3f0a536164202b8593b64 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 15:12:49 -0400 Subject: [PATCH 77/95] Update action.yaml --- .github/py-shiny/pytest-browsers/action.yaml | 23 ++++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/py-shiny/pytest-browsers/action.yaml b/.github/py-shiny/pytest-browsers/action.yaml index 6e1b61807..8ada3ee55 100644 --- a/.github/py-shiny/pytest-browsers/action.yaml +++ b/.github/py-shiny/pytest-browsers/action.yaml @@ -10,7 +10,7 @@ inputs: required: false default: 'false' disable-playwright-diagnostics: - description: 'Disable playwright diagnostics.' + description: 'Disable playwright diagnostics: tracing, video, screenshot' required: false default: 'true' outputs: @@ -30,22 +30,21 @@ runs: shell: bash id: browsers run: | - # Use temp output variable to set default behavior + # Determine which browsers to use - echo 'has-playwright-diagnostics=true' >> "$GITHUB_OUTPUT" - echo 'playwright-diagnostic-args="' >> "$GITHUB_OUTPUT" + if [ "${{ inputs.disable-playwright-diagnostics }}" == "true" ]; then + echo "Disabling playwright diagnostics!" + echo 'has-playwright-diagnostics=false' >> "$GITHUB_OUTPUT" + echo 'playwright-diagnostic-args=--tracing off --video off --screenshot off' >> "$GITHUB_OUTPUT" + else + echo "Using playwright diagnostics!" + echo 'has-playwright-diagnostics=true' >> "$GITHUB_OUTPUT" + echo 'playwright-diagnostic-args=' >> "$GITHUB_OUTPUT" + fi if [ "${{ inputs.browser }}" != "" ]; then BROWSER="${{ inputs.browser }}" - if [ "${{ inputs.disable-playwright-diagnostics }}" == "true" ]; then - echo "Disabling playwright diagnostics!" - echo 'has-playwright-diagnostics=false' >> "$GITHUB_OUTPUT" - echo 'playwright-diagnostic-args="--tracing off --video off --screenshot off' >> "$GITHUB_OUTPUT" - else - echo "Using webkit diagnostics!" - fi - if [ "$BROWSER" == "chromium" ] || [ "$BROWSER" == "firefox" ] || [ "$BROWSER" == "webkit" ]; then echo "Using custom browser $BROWSER !" echo "browsers=PYTEST_BROWSERS=\"--browser $BROWSER\"" >> "$GITHUB_OUTPUT" From 8738c851e76a12824ce5072d516da4c285e179d2 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 15:32:24 -0400 Subject: [PATCH 78/95] Wait for chat apps to perform initial load before attempting to type --- tests/playwright/shiny/components/chat/errors/app.py | 10 ++++++---- .../shiny/components/chat/errors/test_chat_errors.py | 9 +++++++-- .../shiny/components/chat/stream/test_chat_stream.py | 5 ++++- .../components/chat/transform/test_chat_transform.py | 7 +++++-- .../test_chat_transform_assistant.py | 7 +++++-- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/tests/playwright/shiny/components/chat/errors/app.py b/tests/playwright/shiny/components/chat/errors/app.py index 7d11dd189..6a9920fb8 100644 --- a/tests/playwright/shiny/components/chat/errors/app.py +++ b/tests/playwright/shiny/components/chat/errors/app.py @@ -13,7 +13,9 @@ async def _(): raise Exception("boom!") -# Placeholder to help determine when shiny has loaded via `.shiny-bound-output` being present -@render.ui -def _(): - return "" +"Message state:" + + +@render.code +def message_state(): + return str(chat.messages()) diff --git a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py index 7027e01c5..263b2622f 100644 --- a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py +++ b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py @@ -4,12 +4,17 @@ from shiny.run import ShinyAppProc -def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: +def test_validate_chat_basic_error(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) chat = controller.Chat(page, "chat") - expect(chat.loc).to_be_visible() + controller.OutputCode(page, "message_state").expect.not_to_have_text( + "", + timeout=30 * 1000, + ) + + expect(chat.loc).to_be_visible() chat.set_user_input("Hello!") chat.send_user_input() chat.expect_latest_message("Hello!", timeout=30 * 1000) diff --git a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py index 8fb751082..04889b7ce 100644 --- a/tests/playwright/shiny/components/chat/stream/test_chat_stream.py +++ b/tests/playwright/shiny/components/chat/stream/test_chat_stream.py @@ -12,6 +12,9 @@ def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: chat = controller.Chat(page, "chat") message_state = controller.OutputCode(page, "message_state") + # Wait for app to load + message_state.expect.not_to_have_text("", timeout=30 * 1000) + expect(chat.loc).to_be_visible() expect(chat.loc_input_button).to_be_disabled() @@ -23,7 +26,7 @@ def test_validate_chat(page: Page, local_app: ShinyAppProc) -> None: "FIFTH FIFTH FIFTH", ] # Allow for any whitespace between messages - chat.expect_messages(re.compile(r"\s*".join(messages)), timeout=30 * 1000) + chat.expect_messages(re.compile(r"\s*".join(messages))) message_state_expected = tuple( [{"content": message, "role": "assistant"} for message in messages] diff --git a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py index 1787ef6b1..f482ff124 100644 --- a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py +++ b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py @@ -8,6 +8,11 @@ def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: page.goto(local_app.url) chat = controller.Chat(page, "chat") + message_state = controller.OutputCode(page, "message_state") + message_state2 = controller.OutputCode(page, "message_state2") + + # Wait for app to load + message_state.expect_value("()", timeout=30 * 1000) expect(chat.loc).to_be_visible() expect(chat.loc_input_button).to_be_disabled() @@ -30,7 +35,6 @@ def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: chat.send_user_input() chat.expect_latest_message("Custom message") - message_state = controller.OutputCode(page, "message_state") message_state_expected = tuple( [ {"content": user_msg.upper(), "role": "user"}, @@ -42,7 +46,6 @@ def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: ) message_state.expect_value(str(message_state_expected)) - message_state2 = controller.OutputCode(page, "message_state2") message_state_expected2 = tuple( [ {"content": user_msg, "role": "user"}, diff --git a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py index 75b3c5f78..35d838660 100644 --- a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py +++ b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py @@ -9,6 +9,11 @@ def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) page.goto(local_app.url) chat = controller.Chat(page, "chat") + message_state = controller.OutputCode(page, "message_state") + message_state2 = controller.OutputCode(page, "message_state2") + + # Wait for app to load + message_state.expect_value("()", timeout=30 * 1000) expect(chat.loc).to_be_visible() expect(chat.loc_input_button).to_be_disabled() @@ -25,7 +30,6 @@ def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) bold = chat.loc_latest_message.locator("b") expect(bold).to_have_text("Transformed response") - message_state = controller.OutputCode(page, "message_state") message_state_expected = tuple( [ {"content": "hello", "role": "user"}, @@ -36,7 +40,6 @@ def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) ) message_state.expect_value(str(message_state_expected)) - message_state2 = controller.OutputCode(page, "message_state2") message_state_expected2 = tuple( [ {"content": "hello", "role": "user"}, From e9e691707958b8675379da9c9d169eee414229f9 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 15:41:58 -0400 Subject: [PATCH 79/95] Add reruns for failed tests on CI --- .github/workflows/pytest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 2f12063db..089239b11 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -138,7 +138,7 @@ jobs: - name: Run End-to-End tests timeout-minutes: 60 run: | - make playwright-shiny SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} + make playwright-shiny SUB_FILE=". --numprocesses 4 --reruns 3 --reruns-delay 1 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: @@ -190,7 +190,7 @@ jobs: - name: Run example app tests timeout-minutes: 60 run: | - make playwright-examples SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} + make playwright-examples SUB_FILE=". --numprocesses 4 --reruns 3 --reruns-delay 1 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: From 727d86b7b4a9423b46234413d7fe7f6d3d4225d2 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 15:56:42 -0400 Subject: [PATCH 80/95] Add back page size reset and console monitoring --- tests/playwright/conftest.py | 165 ++++++++++++++++------------------- 1 file changed, 74 insertions(+), 91 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 117467d02..6e6d49167 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -3,23 +3,21 @@ from __future__ import annotations from pathlib import PurePath +from typing import Generator + +import pytest +from playwright.sync_api import ( + BrowserContext, + ConsoleMessage, + JSHandle, + Page, + SourceLocation, +) -# from shiny._typing_extensions import TypedDict +from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName from shiny.pytest import create_app_fixture -# from typing import Generator - -# import pytest -# from playwright.sync_api import ( -# BrowserContext, -# ConsoleMessage, -# JSHandle, -# Page, -# SourceLocation, -# ) - - __all__ = ( "create_doc_example_fixture", "create_example_fixture", @@ -32,84 +30,69 @@ here_root = here.parent.parent -# # Make a single page fixture that can be used by all tests -# @pytest.fixture(scope="session") -# # By using a single page, the browser is only launched once and all tests run in the same tab / page. -# def session_page(browser: BrowserContext) -> Page: -# """ -# Create a new page within the given browser context. - -# Parameters: -# browser (BrowserContext): The browser context in which to create the new page. - -# Returns: -# Page: The newly created page. - -# """ -# return browser.new_page() - - -# class ConsoleMessageInfo(TypedDict): -# type: str -# text: str -# location: SourceLocation -# args: list[JSHandle] - - -# @pytest.fixture(scope="function") -# # By going to `about:blank`, we _reset_ the page to a known state before each test. -# # It is not perfect, but it is faster than making a new page for each test. -# # This must be done before each test -# def page( -# request: pytest.FixtureRequest, -# session_page: Page, -# ) -> Generator[Page, None, None]: -# """ -# Reset the given page to a known state before each test. - -# The page is built on the session_page, which is maintained over the full session. -# The page will visit "about:blank" to reset between apps. -# The default viewport size is set to 1920 x 1080 (1080p) for each test function. - -# Parameters: -# session_page (Page): The page to reset before each test. -# """ -# session_page.goto("about:blank") -# # Reset screen size to 1080p -# session_page.set_viewport_size({"width": 1920, "height": 1080}) - -# console_msgs: list[ConsoleMessageInfo] = [] - -# def on_console_msg(msg: ConsoleMessage) -> None: -# # Do not report missing favicon errors -# if msg.location["url"].endswith("favicon.ico"): -# return -# if msg.type == "warning" and msg.text.startswith("DEPRECATED:"): -# return -# # console_msgs.append(msg.text) -# console_msgs.append( -# { -# "type": msg.type, -# "text": msg.text, -# "location": msg.location, -# "args": msg.args, -# } -# ) - -# session_page.on("console", on_console_msg) - -# yield session_page - -# session_page.remove_listener("console", on_console_msg) - -# if request.session.testsfailed: -# if len(console_msgs) > 0: -# print("+++++++++ Browser console log ++++++++") -# for msg in console_msgs: -# print(msg) -# print("+++++++++ / Browser console log ++++++++") -# else: -# print("No browser console messages captured.") +class ConsoleMessageInfo(TypedDict): + type: str + text: str + location: SourceLocation + args: list[JSHandle] + + +@pytest.fixture +def page( + request: pytest.FixtureRequest, + browser: BrowserContext, +) -> Generator[Page, None, None]: + """ + Create a new page. + + Enhancements + * Set the size of the page to 1920 x 1080 (1080p) for each test. + * Add a console listener to the browser context and create a new page. + + Parameters: + browser (BrowserContext): The browser context in which to create the new page. + + Returns: + Page: The newly created page. + + """ + page = browser.new_page() + + # Reset screen size to 1080p + page.set_viewport_size({"width": 1920, "height": 1080}) + + console_msgs: list[ConsoleMessageInfo] = [] + + def on_console_msg(msg: ConsoleMessage) -> None: + # Do not report missing favicon errors + if msg.location["url"].endswith("favicon.ico"): + return + if msg.type == "warning" and msg.text.startswith("DEPRECATED:"): + return + # console_msgs.append(msg.text) + console_msgs.append( + { + "type": msg.type, + "text": msg.text, + "location": msg.location, + "args": msg.args, + } + ) + + page.on("console", on_console_msg) + + yield page + + page.remove_listener("console", on_console_msg) + + if request.session.testsfailed: + if len(console_msgs) > 0: + print("+++++++++ Browser console log ++++++++") + for msg in console_msgs: + print(msg) + print("+++++++++ / Browser console log ++++++++") + else: + print("(No browser console messages captured.)") def create_example_fixture( From 2be323939c39155d6eb98d349f5ab6b025383e60 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 16:11:55 -0400 Subject: [PATCH 81/95] Trying to keep memory usage down. Do not keep args --- tests/playwright/conftest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 6e6d49167..0f3abc0fd 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -34,7 +34,6 @@ class ConsoleMessageInfo(TypedDict): type: str text: str location: SourceLocation - args: list[JSHandle] @pytest.fixture @@ -75,7 +74,6 @@ def on_console_msg(msg: ConsoleMessage) -> None: "type": msg.type, "text": msg.text, "location": msg.location, - "args": msg.args, } ) From 8924acd74f74c4396477c4339e024eb5d26525e6 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 16:15:42 -0400 Subject: [PATCH 82/95] lint --- tests/playwright/conftest.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 0f3abc0fd..5aa7e276d 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -6,13 +6,7 @@ from typing import Generator import pytest -from playwright.sync_api import ( - BrowserContext, - ConsoleMessage, - JSHandle, - Page, - SourceLocation, -) +from playwright.sync_api import BrowserContext, ConsoleMessage, Page, SourceLocation from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName From 679ad95214ed681c01e640b5b57926d9228f0fac Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 16:26:11 -0400 Subject: [PATCH 83/95] Do not record on firefox --- .github/workflows/pytest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 089239b11..a2c3296a3 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -133,7 +133,7 @@ jobs: browser: ${{ matrix.browser }} # If anything other than `true`, it will heavily reduce webkit performance # Related: https://github.com/microsoft/playwright/issues/18119 - disable-playwright-diagnostics: ${{ matrix.browser == 'webkit' }} + disable-playwright-diagnostics: ${{ matrix.browser == 'webkit' || matrix.browser == 'firefox' }} - name: Run End-to-End tests timeout-minutes: 60 @@ -174,7 +174,7 @@ jobs: browser: ${{ matrix.browser }} # If anything other than `true`, it will heavily reduce webkit performance # Related: https://github.com/microsoft/playwright/issues/18119 - disable-playwright-diagnostics: ${{ matrix.browser == 'webkit' }} + disable-playwright-diagnostics: ${{ matrix.browser == 'webkit' || matrix.browser == 'firefox' }} - name: Install node.js uses: actions/setup-node@v4 From 7eabc3b02520a5963c95a58da2b08196143dd034 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 16:26:40 -0400 Subject: [PATCH 84/95] Only record console messages on chromium --- tests/playwright/conftest.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 5aa7e276d..97c0f16cf 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -34,6 +34,7 @@ class ConsoleMessageInfo(TypedDict): def page( request: pytest.FixtureRequest, browser: BrowserContext, + is_chromium: bool, ) -> Generator[Page, None, None]: """ Create a new page. @@ -71,11 +72,15 @@ def on_console_msg(msg: ConsoleMessage) -> None: } ) - page.on("console", on_console_msg) + # Only record console messages in Chromium + # GHA is running out of memory + if is_chromium: + page.on("console", on_console_msg) yield page - page.remove_listener("console", on_console_msg) + if is_chromium: + page.remove_listener("console", on_console_msg) if request.session.testsfailed: if len(console_msgs) > 0: From 6c1e9b57b7578c460357ab5a3fd7d90839b54082 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 16:34:05 -0400 Subject: [PATCH 85/95] Update pytest.yaml --- .github/workflows/pytest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index a2c3296a3..e8168cc40 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -138,7 +138,7 @@ jobs: - name: Run End-to-End tests timeout-minutes: 60 run: | - make playwright-shiny SUB_FILE=". --numprocesses 4 --reruns 3 --reruns-delay 1 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} + make playwright-shiny SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: @@ -190,7 +190,7 @@ jobs: - name: Run example app tests timeout-minutes: 60 run: | - make playwright-examples SUB_FILE=". --numprocesses 4 --reruns 3 --reruns-delay 1 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} + make playwright-examples SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: From f29deb02801f10c73347b104a3f0938369891abf Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 16:46:27 -0400 Subject: [PATCH 86/95] Try older versions of ubuntu --- .github/workflows/pytest.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index e8168cc40..e3209bf02 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -18,7 +18,7 @@ jobs: matrix: # "3.10" must be a string; otherwise it is interpreted as 3.1. python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-20.04, windows-latest, macOS-latest] exclude: - python-version: ${{ github.event.pull_request.draft && '3.11' }} - python-version: ${{ github.event.pull_request.draft && '3.10' }} @@ -148,7 +148,7 @@ jobs: playwright-examples: if: github.event_name != 'release' - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: matrix: python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] @@ -200,7 +200,7 @@ jobs: playwright-deploys-precheck: if: github.event_name != 'release' - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: matrix: # Matches deploy server python version From ebaa5e139745daba4336746b9398c8453b5e8928 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 16:48:53 -0400 Subject: [PATCH 87/95] Rearrange diagnostic arg locations to avoid needing to override values --- .github/py-shiny/pytest-browsers/action.yaml | 2 +- pytest.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/py-shiny/pytest-browsers/action.yaml b/.github/py-shiny/pytest-browsers/action.yaml index 8ada3ee55..67a3843cf 100644 --- a/.github/py-shiny/pytest-browsers/action.yaml +++ b/.github/py-shiny/pytest-browsers/action.yaml @@ -39,7 +39,7 @@ runs: else echo "Using playwright diagnostics!" echo 'has-playwright-diagnostics=true' >> "$GITHUB_OUTPUT" - echo 'playwright-diagnostic-args=' >> "$GITHUB_OUTPUT" + echo 'playwright-diagnostic-args=--tracing=retain-on-failure --video=retain-on-failure --screenshot=only-on-failure --full-page-screenshot --output=test-results' >> "$GITHUB_OUTPUT" fi if [ "${{ inputs.browser }}" != "" ]; then diff --git a/pytest.ini b/pytest.ini index 6e026f30f..267fc8c6c 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,5 +2,5 @@ asyncio_mode=strict testpaths=tests/pytest/ ; Note: Browsers are set within `./Makefile` -addopts = --strict-markers --durations=6 --durations-min=5.0 --numprocesses auto --tracing=retain-on-failure --video=retain-on-failure --screenshot=only-on-failure --full-page-screenshot --output="test-results" +addopts = --strict-markers --durations=6 --durations-min=5.0 --numprocesses auto verbosity_test_cases=2 From 2efa0b29df3d686a2cd9a27093746c06d85d64ed Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 17:02:23 -0400 Subject: [PATCH 88/95] Try not using custom page object --- tests/playwright/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 97c0f16cf..e3126c936 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -31,7 +31,7 @@ class ConsoleMessageInfo(TypedDict): @pytest.fixture -def page( +def page_old( request: pytest.FixtureRequest, browser: BrowserContext, is_chromium: bool, From 1d9e1e2fccf60d56856efd97d6c8f434481af6b0 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 17:09:17 -0400 Subject: [PATCH 89/95] Revert ubuntu change --- .github/workflows/pytest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index e3209bf02..c6ea87818 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -18,7 +18,7 @@ jobs: matrix: # "3.10" must be a string; otherwise it is interpreted as 3.1. python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] - os: [ubuntu-20.04, windows-latest, macOS-latest] + os: [ubuntu-latest, windows-latest, macOS-latest] exclude: - python-version: ${{ github.event.pull_request.draft && '3.11' }} - python-version: ${{ github.event.pull_request.draft && '3.10' }} @@ -200,7 +200,7 @@ jobs: playwright-deploys-precheck: if: github.event_name != 'release' - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: matrix: # Matches deploy server python version From 43947aeeec3a15a6b4da646f2406c06790bfd589 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 17:17:25 -0400 Subject: [PATCH 90/95] Update pytest.yaml --- .github/workflows/pytest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index c6ea87818..bdce63805 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -138,7 +138,7 @@ jobs: - name: Run End-to-End tests timeout-minutes: 60 run: | - make playwright-shiny SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} + make playwright-shiny SUB_FILE=". --numprocesses 3 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: @@ -190,7 +190,7 @@ jobs: - name: Run example app tests timeout-minutes: 60 run: | - make playwright-examples SUB_FILE=". --numprocesses 4 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} + make playwright-examples SUB_FILE=". --numprocesses 3 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} - uses: actions/upload-artifact@v4 if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: From 1d5a5c652c9e54acf1634a0732e6fdcf38ef9f71 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 17:31:44 -0400 Subject: [PATCH 91/95] Remove custom page object with browser console message tracking --- tests/playwright/conftest.py | 62 ------------------------------------ 1 file changed, 62 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index e3126c936..6a0d3fcdf 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -30,68 +30,6 @@ class ConsoleMessageInfo(TypedDict): location: SourceLocation -@pytest.fixture -def page_old( - request: pytest.FixtureRequest, - browser: BrowserContext, - is_chromium: bool, -) -> Generator[Page, None, None]: - """ - Create a new page. - - Enhancements - * Set the size of the page to 1920 x 1080 (1080p) for each test. - * Add a console listener to the browser context and create a new page. - - Parameters: - browser (BrowserContext): The browser context in which to create the new page. - - Returns: - Page: The newly created page. - - """ - page = browser.new_page() - - # Reset screen size to 1080p - page.set_viewport_size({"width": 1920, "height": 1080}) - - console_msgs: list[ConsoleMessageInfo] = [] - - def on_console_msg(msg: ConsoleMessage) -> None: - # Do not report missing favicon errors - if msg.location["url"].endswith("favicon.ico"): - return - if msg.type == "warning" and msg.text.startswith("DEPRECATED:"): - return - # console_msgs.append(msg.text) - console_msgs.append( - { - "type": msg.type, - "text": msg.text, - "location": msg.location, - } - ) - - # Only record console messages in Chromium - # GHA is running out of memory - if is_chromium: - page.on("console", on_console_msg) - - yield page - - if is_chromium: - page.remove_listener("console", on_console_msg) - - if request.session.testsfailed: - if len(console_msgs) > 0: - print("+++++++++ Browser console log ++++++++") - for msg in console_msgs: - print(msg) - print("+++++++++ / Browser console log ++++++++") - else: - print("(No browser console messages captured.)") - - def create_example_fixture( example_name: str, example_file: str = "app.py", From 11ce472edad5fe5b2095328d7a54490e272126af Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 17:33:51 -0400 Subject: [PATCH 92/95] lints --- tests/playwright/conftest.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 6a0d3fcdf..0f0dac392 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -3,10 +3,8 @@ from __future__ import annotations from pathlib import PurePath -from typing import Generator -import pytest -from playwright.sync_api import BrowserContext, ConsoleMessage, Page, SourceLocation +from playwright.sync_api import SourceLocation from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName From ba436a31ab2054e2f092a2d8fd96fa8920bd8719 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Thu, 25 Jul 2024 17:39:14 -0400 Subject: [PATCH 93/95] More timeouts settings --- .../chat/append_user_msg/test_chat_append_user_msg.py | 2 +- tests/playwright/shiny/components/chat/basic/test_chat_basic.py | 2 +- .../playwright/shiny/components/chat/errors/test_chat_errors.py | 2 +- .../shiny/components/chat/transform/test_chat_transform.py | 2 +- .../chat/transform_assistant/test_chat_transform_assistant.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py index 40e236c90..c42c5a214 100644 --- a/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py +++ b/tests/playwright/shiny/components/chat/append_user_msg/test_chat_append_user_msg.py @@ -10,7 +10,7 @@ def test_validate_chat_append_user_message(page: Page, local_app: ShinyAppProc) chat = controller.Chat(page, "chat") # Verify starting state - expect(chat.loc).to_be_visible() + expect(chat.loc).to_be_visible(timeout=30 * 1000) chat.expect_latest_message("A user message", timeout=30 * 1000) # Verify that the message state is as expected diff --git a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py index 36e84e853..82e1bcf42 100644 --- a/tests/playwright/shiny/components/chat/basic/test_chat_basic.py +++ b/tests/playwright/shiny/components/chat/basic/test_chat_basic.py @@ -10,7 +10,7 @@ def test_validate_chat_basic(page: Page, local_app: ShinyAppProc) -> None: chat = controller.Chat(page, "chat") # Verify starting state - expect(chat.loc).to_be_visible() + expect(chat.loc).to_be_visible(timeout=30 * 1000) initial_message = "Hello! How can I help you today?" chat.expect_latest_message(initial_message, timeout=30 * 1000) diff --git a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py index 263b2622f..c38bbd5c4 100644 --- a/tests/playwright/shiny/components/chat/errors/test_chat_errors.py +++ b/tests/playwright/shiny/components/chat/errors/test_chat_errors.py @@ -14,7 +14,7 @@ def test_validate_chat_basic_error(page: Page, local_app: ShinyAppProc) -> None: timeout=30 * 1000, ) - expect(chat.loc).to_be_visible() + expect(chat.loc).to_be_visible(timeout=30 * 1000) chat.set_user_input("Hello!") chat.send_user_input() chat.expect_latest_message("Hello!", timeout=30 * 1000) diff --git a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py index f482ff124..4b06be4e9 100644 --- a/tests/playwright/shiny/components/chat/transform/test_chat_transform.py +++ b/tests/playwright/shiny/components/chat/transform/test_chat_transform.py @@ -14,7 +14,7 @@ def test_validate_chat_transform(page: Page, local_app: ShinyAppProc) -> None: # Wait for app to load message_state.expect_value("()", timeout=30 * 1000) - expect(chat.loc).to_be_visible() + expect(chat.loc).to_be_visible(timeout=30 * 1000) expect(chat.loc_input_button).to_be_disabled() user_msg = "hello" diff --git a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py index 35d838660..7246a08e3 100644 --- a/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py +++ b/tests/playwright/shiny/components/chat/transform_assistant/test_chat_transform_assistant.py @@ -15,7 +15,7 @@ def test_validate_chat_transform_assistant(page: Page, local_app: ShinyAppProc) # Wait for app to load message_state.expect_value("()", timeout=30 * 1000) - expect(chat.loc).to_be_visible() + expect(chat.loc).to_be_visible(timeout=30 * 1000) expect(chat.loc_input_button).to_be_disabled() user_msg = "hello" From 5bb15771d5679eae9052e6af47d0fba68d5cbafb Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Fri, 26 Jul 2024 08:53:19 -0400 Subject: [PATCH 94/95] Remove unnecessary `shell: bash` --- .github/workflows/pytest.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index bdce63805..43e5338d0 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -38,25 +38,21 @@ jobs: - name: Run unit tests if: steps.install.outcome == 'success' && (success() || failure()) - shell: bash run: | make check-tests - name: Type check if: steps.install.outcome == 'success' && (success() || failure()) - shell: bash run: | make check-types - name: Lint code if: steps.install.outcome == 'success' && (success() || failure()) - shell: bash run: | make check-lint - name: Verify code formatting if: steps.install.outcome == 'success' && (success() || failure()) - shell: bash run: | make check-format From 1e08f8f9a45a9a8e823288aa0ee28e9f2b070ec4 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Fri, 26 Jul 2024 08:53:26 -0400 Subject: [PATCH 95/95] Clean up file --- tests/playwright/conftest.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 0f0dac392..886c69dca 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -4,9 +4,6 @@ from pathlib import PurePath -from playwright.sync_api import SourceLocation - -from shiny._typing_extensions import TypedDict from shiny.pytest import ScopeName as ScopeName from shiny.pytest import create_app_fixture @@ -22,12 +19,6 @@ here_root = here.parent.parent -class ConsoleMessageInfo(TypedDict): - type: str - text: str - location: SourceLocation - - def create_example_fixture( example_name: str, example_file: str = "app.py",