name: Testing

on:
  workflow_dispatch:
  push:
    branches:
      - "main"
      - "rc"
      - "hotfix-rc-*"
  pull_request:
    types: [opened, synchronize]

jobs:

  testing:
    name: Run tests
    runs-on: ubuntu-22.04
    permissions:
      checks: write
      contents: read
      pull-requests: write

    steps:
      - name: Check out repo
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Get Node Version
        id: retrieve-node-version
        run: |
          NODE_NVMRC=$(cat .nvmrc)
          NODE_VERSION=${NODE_NVMRC/v/''}
          echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT

      - name: Set up Node
        uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
        with:
          cache: 'npm'
          cache-dependency-path: '**/package-lock.json'
          node-version: ${{ steps.retrieve-node-version.outputs.node_version }}

      - name: Print environment
        run: |
          node --version
          npm --version

      - name: Install Node dependencies
        run: npm ci

      # We use isolatedModules: true which disables typechecking in tests
      # Tests in apps/ are typechecked when their app is built, so we just do it here for libs/
      # See https://bitwarden.atlassian.net/browse/EC-497
      - name: Run typechecking
        run: npm run test:types

      - name: Run tests
        # maxWorkers is a workaround for a memory leak that crashes tests in CI:
        # https://github.com/facebook/jest/issues/9430#issuecomment-1149882002
        run: npm test -- --coverage --maxWorkers=3

      - name: Report test results
        uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 # v1.9.1
        if: ${{ github.event.pull_request.head.repo.full_name == github.repository && !cancelled() }}
        with:
          name: Test Results
          path: "junit.xml"
          reporter: jest-junit
          fail-on-error: true

      - name: Upload coverage to codecov.io
        uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2

      - name: Upload results to codecov.io
        uses: codecov/test-results-action@4e79e65778be1cecd5df25e14af1eafb6df80ea9 # v1.0.2
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

  rust:
    name: Run Rust tests on ${{ matrix.os }}
    runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
    permissions:
      contents: read

    strategy:
      matrix:
        os:
          - ubuntu-22.04
          - macos-14
          - windows-2022

    steps:
      - name: Check Rust version
        run: rustup --version

      - name: Install gnome-keyring
        if: ${{ matrix.os=='ubuntu-22.04' }}
        run: |
          sudo apt-get update
          sudo apt-get install -y gnome-keyring dbus-x11

      - name: Check out repo
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Build
        working-directory: ./apps/desktop/desktop_native
        run: cargo build

      - name: Test Ubuntu
        if: ${{ matrix.os=='ubuntu-22.04' }}
        working-directory: ./apps/desktop/desktop_native
        run: |
          eval "$(dbus-launch --sh-syntax)"
          mkdir -p ~/.cache
          mkdir -p ~/.local/share/keyrings
          eval "$(printf '\n' | gnome-keyring-daemon --unlock)"
          eval "$(printf '\n' | /usr/bin/gnome-keyring-daemon --start)"
          cargo test -- --test-threads=1

      - name: Test macOS
        if: ${{ matrix.os=='macos-14' }}
        working-directory: ./apps/desktop/desktop_native
        run: cargo test -- --test-threads=1

      - name: Test Windows
        if: ${{ matrix.os=='windows-2022'}}
        working-directory: ./apps/desktop/desktop_native/core
        run: cargo test -- --test-threads=1

  rust-coverage:
    name: Rust Coverage
    runs-on: macos-14
    steps:
      - name: Checkout
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Install rust
        uses: dtolnay/rust-toolchain@c5a29ddb4d9d194e7c84ec8c3fba61b1c31fee8c # stable
        with:
          toolchain: stable
          components: llvm-tools

      - name: Cache cargo registry
        uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5
        with:
          workspaces: "apps/desktop/desktop_native -> target"

      - name: Install cargo-llvm-cov
        run: cargo install cargo-llvm-cov --version 0.6.16

      - name: Generate coverage
        working-directory: ./apps/desktop/desktop_native
        run: cargo llvm-cov --all-features --lcov --output-path lcov.info --workspace --no-cfg-coverage

      - name: Upload to codecov.io
        uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
        with:
          files: ./apps/desktop/desktop_native/lcov.info
