name: Test
on:
  push:
    paths-ignore:
      - 'docs/**'
      - '**.md'
      - 'radicale/web/README.md'
      - 'radicale/web/internal_data/css/icons/credits.md'
      - 'Dockerfile'
      - 'Dockerfile.dev'
      - 'config'
      - 'rights'
      - 'contrib/**'
      - 'compose.yaml'
      - 'setup.py.legacy'
      - '.github/workflows/docker-publish.yml'
  pull_request:
    paths-ignore:
      - 'docs/**'
      - '**.md'
      - 'radicale/web/README.md'
      - 'radicale/web/internal_data/css/icons/credits.md'
      - 'Dockerfile'
      - 'Dockerfile.dev'
      - 'config'
      - 'rights'
      - 'contrib/**'
      - 'compose.yaml'
      - 'setup.py.legacy'
      - '.github/workflows/docker-publish.yml'

jobs:

  test-ubuntu-python-newest:
    name: Test Python:newest Ubuntu:latest
    needs: lint
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ['3.14']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with newest Python on latest Ubuntu
        run: tox -c pyproject.toml -e py

  test-ubuntu-python-newest-with-passlib:
    name: Test passlib Python:newest Ubuntu:latest
    needs: [lint, test-ubuntu-python-newest]
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ['3.14']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Switch back to passlib
        run: sed -i 's|libpass[^"]*|passlib|' pyproject.toml
      - name: Test with newest Python on latest Ubuntu using passlib
        run: tox -c pyproject.toml -e py

  test-ubuntu-python-newest-with-vfat:
    name: Test VFAT Python:newest Ubuntu:latest
    needs: [lint, test-ubuntu-python-newest]
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ['3.14']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with newest Python on latest Ubuntu using VFAT
        run: tox -c pyproject.toml -e py_filesystem_vfat

  test-ubuntu-python-newest-with-vfat-utf8:
    name: Test VFAT UTF-8 Python:newest Ubuntu:latest
    needs: [lint, test-ubuntu-python-newest, test-ubuntu-python-newest-with-vfat]
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ['3.14']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with newest Python on latest Ubuntu using VFAT UTF-8
        run: tox -c pyproject.toml -e py_filesystem_vfat_utf8

  test-ubuntu-python-newest-with-ntfs:
    name: Test NTFS Python:newest Ubuntu:latest
    needs: [lint, test-ubuntu-python-newest]
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ['3.14']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with newest Python on latest Ubuntu using NTFS
        run: tox -c pyproject.toml -e py_filesystem_ntfs

  test-python-32bit:
    name: Test 32-bit Python:3.11 Ubuntu:latest
    needs: [lint, test-ubuntu-python-newest, integ-test, test-ubuntu-python-newest-with-passlib]
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ['3.11']
    runs-on: ${{ matrix.os }}
    container:
      image: i386/python:${{ matrix.python-version }}
      volumes:
        - /home/runner/work/_temp:/__e/node24
    steps:
      - name: Update system
        run: |
          apt-get update
      - name: Fix checkout and upload-artifact
        run: |
          apt-get install -y nodejs npm
          mkdir -p /__e/node24/bin
          ln -sf $(which node) /__e/node24/bin/node
          ln -sf $(which npm) /__e/node24/bin/npm
          ln -sf $(which npx) /__e/node24/bin/npx
      - name: Install git
        run: |
          apt-get install -y git
      - uses: actions/checkout@v5
      - name: Install Python dependencies
        run: |
          apt-get install -y tox rust-all cargo
      - name: Activate Python virtual environment
        run: |
          python3 -m venv venv
          . venv/bin/activate
          pip install --upgrade pip
      - name: Test with 32-bit Python on latest Ubuntu
        run: |
          . venv/bin/activate
          tox -c /__w/Radicale/Radicale/pyproject.toml -e py

  test-ubuntu-python-oldest:
    name: Test Python:oldest Ubuntu:latest
    needs: [lint, test-ubuntu-python-newest, test-python-32bit]
    strategy:
      matrix:
        os: [ubuntu-latest]
        python-version: ['3.9']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with oldest Python on Ubuntu
        run: tox -c pyproject.toml -e py

  test-otheros-python-newest:
    name: Test MacOS/Windows:latest Python:newest
    needs: [lint, test-ubuntu-python-newest, test-ubuntu-python-newest-with-ntfs, test-ubuntu-python-newest-with-vfat, test-ubuntu-python-newest-with-vfat-utf8]
    strategy:
      matrix:
        os: [macos-latest, windows-latest]
        python-version: ['3.14']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with latest Python on other OS
        run: tox -c pyproject.toml -e py

  test-otheros-python-oldest:
    name: Test MacOS/Windows:latest Python:oldest
    needs: [lint, test-ubuntu-python-oldest, test-otheros-python-newest]
    strategy:
      matrix:
        os: [macos-latest, windows-latest]
        python-version: ['3.9']
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with oldest Python on other OS
        run: tox -c pyproject.toml -e py

  test-python-versions:
    name: Test Ubuntu/MacOS/Windows:latest Python:Matrix
    needs: [lint, test-otheros-python-oldest, test-otheros-python-newest, test-ubuntu-python-oldest, test-ubuntu-python-newest]
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ['3.10', '3.11', '3.12', '3.13', 'pypy-3.9', 'pypy-3.10', 'pypy-3.11']
        exclude:
          - os: windows-latest
            python-version: 'pypy-3.9'
          - os: windows-latest
            python-version: 'pypy-3.10'
          - os: windows-latest
            python-version: 'pypy-3.11'
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Test dependencies
        run: pip install tox
      - name: Test with older Python
        run: tox -c pyproject.toml -e py

  coveralls-test:
    name: Coveralls:Test
    needs: [test-ubuntu-python-newest, test-python-32bit]
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: '3.14'
      - name: Install Test dependencies
        run: pip install tox
      - name: Test
        run: tox -c pyproject.toml -e py
      - name: Install Coveralls
        if: github.event_name == 'push'
        run: pip install coveralls
      - name: Upload coverage to Coveralls
        if: github.event_name == 'push'
        env:
          COVERALLS_PARALLEL: true
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: coveralls --service=github

  coveralls-finish:
    name: Coveralls:Finish
    needs: coveralls-test
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-python@v6
        with:
          python-version: 3.x
      - name: Install Coveralls
        run: pip install coveralls
      - name: Finish Coveralls parallel builds
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: coveralls --service=github --finish

  js-test:
    name: JS Type Check
    runs-on: ubuntu-latest
    needs: [test-ubuntu-python-newest]
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with:
          node-version: 24
      - name: JS Type Check
        run: |
          npx -y -p typescript@7.0.2 tsc -p radicale/web/jsconfig.json

  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: '3.14'
      - name: Install tox
        run: pip install tox
      - name: Lint
        run: tox -c pyproject.toml -e flake8,mypy,isort

  htmlvalidator:
    name: HTML Validator
    runs-on: ubuntu-latest
    needs: test-ubuntu-python-newest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: '3.14'
      - uses: Cyb3r-Jak3/html5validator-action@v7.2.0
        with:
          root: 'radicale/web/internal_data/'
          css: true

  integ-test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    needs: [test-ubuntu-python-newest, htmlvalidator, js-test]
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v6
        with:
          python-version: '3.14'
      - name: Install uv
        run: pip install uv
      - name: Install Playwright Browsers
        run: uv run --extra dev playwright install --with-deps
      - name: Run Integration Tests
        run: uv run --extra dev pytest integ_tests/ -v
