diff --git a/.env.example b/.env.example index dce068f091..091cd76d47 100644 --- a/.env.example +++ b/.env.example @@ -85,3 +85,6 @@ DEV_API_CONFIG= # [Dev Mode] Path to directory with flash packages for Mudita Harmony DEV_FLASH_PACKAGE_PATH= + +# Token for using dev server for Kompakt OS update info +KOMPAKT_OS_UPDATE_DEV_TOKEN= diff --git a/.github/workflows/e2e-development.yml b/.github/workflows/e2e-development.yml index acf6663cf8..4ca8a1bed5 100644 --- a/.github/workflows/e2e-development.yml +++ b/.github/workflows/e2e-development.yml @@ -47,6 +47,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -78,6 +79,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env diff --git a/.github/workflows/e2e-feature-branch.yml b/.github/workflows/e2e-feature-branch.yml index ae9ba3fa0e..eadbf00446 100644 --- a/.github/workflows/e2e-feature-branch.yml +++ b/.github/workflows/e2e-feature-branch.yml @@ -4,7 +4,6 @@ on: pull_request: types: - opened - - synchronize - ready_for_review - reopened workflow_dispatch: @@ -13,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [Windows, Linux] + os: [Windows, Linux, macOS] if: startsWith(github.head_ref || github.ref, 'CP-') environment: development steps: @@ -23,6 +22,46 @@ jobs: uses: actions/setup-node@v4 with: node-version: 18.16.1 + - name: Find open port for ChromeBrowser on Linux/Mac + if: matrix.os != 'Windows' + id: find-port-unix + run: | + START_PORT=30000 + END_PORT=40000 + PORT=$START_PORT + RUNNER_OS="${{ matrix.os }}" + while [ $PORT -le $END_PORT ]; do + if [[ "$RUNNER_OS" == "Linux" ]]; then + nc -z 127.0.0.1 $PORT 2>/dev/null || break + elif [[ "$RUNNER_OS" == "macOS" ]]; then + nc -z -w1 127.0.0.1 $PORT 2>/dev/null || break + fi + PORT=$((PORT+1)) + done + if [ $PORT -gt $END_PORT ]; then + echo "No available port found in the range $START_PORT-$END_PORT" >&2 + exit 1 + fi + echo "CHROME_OPEN_PORT=$PORT" >> $GITHUB_ENV + - name: Find open port for ChromeBrowser on Windows + if: matrix.os == 'Windows' + id: find-port-windows + run: | + $startPort = 30000 + $endPort = 40000 + $port = $startPort + while ($port -le $endPort) { + $isUsed = (Test-NetConnection -ComputerName 127.0.0.1 -Port $port).TcpTestSucceeded + if (-not $isUsed) { + break + } + $port++ + } + if ($port -gt $endPort) { + Write-Error "No available port found in the range $startPort-$endPort" + exit 1 + } + echo "CHROME_OPEN_PORT=$port" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 - name: Setup environment variables for Linux if: matrix.os == 'Linux' env: @@ -51,6 +90,40 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} + NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} + run: | + printenv > .env + - name: Setup Env for Mac + if: matrix.os == 'macOS' + env: + E2ECI: "true" + TEST_GITHUB_TOKEN: ${{ secrets.MC_GITHUB_ACCESS_TOKEN }} + TEST_BINARY_PATH: "../mudita-center/release/mac/Mudita Center.app/Contents/MacOS/Mudita Center" + PHRASE_API_KEY: ${{ secrets.PHRASE_API_KEY }} + PHRASE_API_URL: ${{ secrets.PHRASE_API_URL }} + PHRASE_API_KEY_DEV: ${{ secrets.PHRASE_API_KEY_DEV }} + MUDITA_CENTER_SERVER_URL: ${{ secrets.MUDITA_CENTER_SERVER_URL }} + MUDITA_CENTER_SERVER_V2_URL: ${{ secrets.MUDITA_CENTER_SERVER_V2_URL }} + ROLLBAR_TOKEN: ${{ secrets.ROLLBAR_TOKEN }} + RELEASES_REPOSITORY_NAME: ${{ secrets.RELEASES_REPOSITORY_NAME }} + PRERELEASES_ENABLED: ${{ secrets.PRERELEASES_ENABLED }} + GITHUB_ACCESS_TOKEN: ${{ secrets.MC_GITHUB_ACCESS_TOKEN }} + LOGIN_MICROSOFT_ONLINE_CLIENT_ID: ${{ secrets.LOGIN_MICROSOFT_ONLINE_CLIENT_ID }} + FONTS_DIRECTORY_URL: ${{ secrets.FONTS_DIRECTORY_URL }} + FRESHDESK_API_URL: ${{ secrets.FRESHDESK_API_URL }} + FRESHDESK_API_TOKEN: ${{ secrets.FRESHDESK_API_TOKEN }} + ANALYTICS_ENABLED: ${{ secrets.ANALYTICS_ENABLED }} + ANALYTICS_API_URL: ${{ secrets.ANALYTICS_API_URL }} + ANALYTICS_API_SITE_ID: ${{ secrets.ANALYTICS_API_SITE_ID }} + FEATURE_TOGGLE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_ENVIRONMENT }} + STATIC_CONFIGURATION_FILE_PATH: ${{ secrets.STATIC_CONFIGURATION_FILE_PATH }} + DEV_REDUX_LOGGER_ENABLED: ${{ secrets.DEV_REDUX_LOGGER_ENABLED }} + DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} + FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} + MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} + NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -82,13 +155,14 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env - name: Setup dependencies run: npm run setup - - name: Build App for Linux - if: matrix.os == 'Linux' + - name: Build App for Linux/Mac + if: matrix.os != 'Windows' run: | export NODE_OPTIONS="--max-old-space-size=4096" npm run app:dist @@ -109,3 +183,7 @@ jobs: run: | cd apps/mudita-center-e2e npm run e2e:test:cicd:standalone + - name: Run E2E tests headless on Mac + if: matrix.os == 'macOS' + run: | + npm run e2e:test:standalone diff --git a/.github/workflows/e2e-mock-development.yml b/.github/workflows/e2e-mock-development.yml index 269e46a1f0..db4d880686 100644 --- a/.github/workflows/e2e-mock-development.yml +++ b/.github/workflows/e2e-mock-development.yml @@ -47,6 +47,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -78,6 +79,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env diff --git a/.github/workflows/e2e-mock-feature-branch.yml b/.github/workflows/e2e-mock-feature-branch.yml index 2fb79e3bb6..9105af8f8c 100644 --- a/.github/workflows/e2e-mock-feature-branch.yml +++ b/.github/workflows/e2e-mock-feature-branch.yml @@ -4,7 +4,6 @@ on: pull_request: types: - opened - - synchronize - ready_for_review - reopened workflow_dispatch: @@ -51,6 +50,8 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: "1" + NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -82,6 +83,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: "1" NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env diff --git a/.github/workflows/e2e-mock-pre-production.yml b/.github/workflows/e2e-mock-pre-production.yml index fc5797bbe1..e3c5818df2 100644 --- a/.github/workflows/e2e-mock-pre-production.yml +++ b/.github/workflows/e2e-mock-pre-production.yml @@ -48,6 +48,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -79,6 +80,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env diff --git a/.github/workflows/e2e-mock-production.yml b/.github/workflows/e2e-mock-production.yml index db29f9e251..a83ef0d803 100644 --- a/.github/workflows/e2e-mock-production.yml +++ b/.github/workflows/e2e-mock-production.yml @@ -48,6 +48,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -79,6 +80,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env diff --git a/.github/workflows/e2e-pre-production.yml b/.github/workflows/e2e-pre-production.yml index e6171412a7..0349d582c9 100644 --- a/.github/workflows/e2e-pre-production.yml +++ b/.github/workflows/e2e-pre-production.yml @@ -48,6 +48,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -79,6 +80,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env diff --git a/.github/workflows/e2e-production.yml b/.github/workflows/e2e-production.yml index 2d309399ed..feb0a447b9 100644 --- a/.github/workflows/e2e-production.yml +++ b/.github/workflows/e2e-production.yml @@ -48,6 +48,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup environment variables for Windows @@ -79,6 +80,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: ${{ secrets.MOCK_SERVICE_ENABLED }} NEW_HELP_ENABLED: ${{ secrets.NEW_HELP_ENABLED }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env diff --git a/.github/workflows/nexus-development.yml b/.github/workflows/nexus-development.yml index c8b65e20ee..c2e73224d9 100644 --- a/.github/workflows/nexus-development.yml +++ b/.github/workflows/nexus-development.yml @@ -45,6 +45,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" LOCALAPPDATA: "" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -74,6 +75,7 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup Env for Linux @@ -101,6 +103,7 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Changing app version in packages.json for Linux diff --git a/.github/workflows/nexus-feature-branch.yml b/.github/workflows/nexus-feature-branch.yml index a808ea400a..b7866a6f0c 100644 --- a/.github/workflows/nexus-feature-branch.yml +++ b/.github/workflows/nexus-feature-branch.yml @@ -4,7 +4,6 @@ on: pull_request: types: - opened - - synchronize - ready_for_review - reopened workflow_dispatch: @@ -50,6 +49,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" LOCALAPPDATA: "" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -79,7 +79,7 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" - SKIP_MAC_NOTARIZE_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup Env for Linux @@ -107,29 +107,30 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Changing app version in packages.json for Linux if: matrix.os == 'Linux' run: | export APP_VERSION=`cat apps/mudita-center/package.json | jq -r .version` - export SOURCE_BRANCH=${{ github.ref_name }} - export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.ref_name }}" + export SOURCE_BRANCH=${{ github.head_ref }} + export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.head_ref }}" export "BUILD_VERSION=-dev.${{ github.run_number }}" sed -i "s/\"version\": \".*\",/\"version\": \"$APP_VERSION$BUILD_VERSION\",/" apps/mudita-center/package.json - name: Changing app version in packages.json for Mac if: matrix.os == 'macOS' run: | export APP_VERSION=`cat apps/mudita-center/package.json | jq -r .version` - export SOURCE_BRANCH=${{ github.ref_name }} - export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.ref_name }}" + export SOURCE_BRANCH=${{ github.head_ref }} + export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.head_ref }}" export "BUILD_VERSION=-dev.${{ github.run_number }}" sed -i '' "s/\"version\": \".*\",/\"version\": \"$APP_VERSION$BUILD_VERSION\",/" apps/mudita-center/package.json - name: Changing app version in packages.json for Windows if: matrix.os == 'Windows' run: | - $SOURCE_BRANCH = "${{ github.ref_name }}" - $ENVIRONMENT_CATALOG_NAME = "feature-branch/${{ github.ref_name }}" + $SOURCE_BRANCH = "${{ github.head_ref }}" + $ENVIRONMENT_CATALOG_NAME = "feature-branch/${{ github.head_ref }}" $BUILD_VERSION = "-dev.${{ github.run_number }}" $APP_VERSION = (Get-Content -Path "apps/mudita-center/version") + $BUILD_VERSION (Get-Content -Path 'apps/mudita-center/package.json') | ForEach-Object { @@ -160,8 +161,8 @@ jobs: run: | jq -r -j .version apps/mudita-center/package.json > apps/mudita-center/version $APP_VERSION = Get-Content -Path "apps/mudita-center/version" - $SOURCE_BRANCH = "${{ github.ref_name }}" - $ENVIRONMENT_CATALOG_NAME = "feature-branch/${{ github.ref_name }}" + $SOURCE_BRANCH = "${{ github.head_ref }}" + $ENVIRONMENT_CATALOG_NAME = "feature-branch/${{ github.head_ref }}" $NEXUS_USERNAME = "$env:NEXUS_USERNAME" $NEXUS_PASSWORD = ConvertTo-SecureString "$env:NEXUS_PASSWORD" -AsPlainText -Force $AUTH = New-Object System.Management.Automation.PSCredential ($NEXUS_USERNAME, $NEXUS_PASSWORD) @@ -177,8 +178,8 @@ jobs: NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} run: | export APP_VERSION=`cat apps/mudita-center/package.json | jq -r .version` - export SOURCE_BRANCH=${{ github.ref_name }} - export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.ref_name }}" + export SOURCE_BRANCH=${{ github.head_ref }} + export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.head_ref }}" cp ./apps/mudita-center/release/builder-debug.yml ./apps/mudita-center/release/builder-debug-linux.yml curl -u $NEXUS_USERNAME:$NEXUS_PASSWORD --upload-file ./apps/mudita-center/release/Mudita-Center.AppImage https://nexus.mudita.com/repository/mudita-center/releases/$ENVIRONMENT_CATALOG_NAME/$APP_VERSION/Mudita-Center.AppImage curl -u $NEXUS_USERNAME:$NEXUS_PASSWORD --upload-file ./apps/mudita-center/release/latest-linux.yml https://nexus.mudita.com/repository/mudita-center/releases/$ENVIRONMENT_CATALOG_NAME/$APP_VERSION/latest-linux.yml @@ -190,8 +191,8 @@ jobs: NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} run: | export APP_VERSION=`cat apps/mudita-center/package.json | jq -r .version` - export SOURCE_BRANCH=${{ github.ref_name }} - export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.ref_name }}" + export SOURCE_BRANCH=${{ github.head_ref }} + export "ENVIRONMENT_CATALOG_NAME=feature-branch/${{ github.head_ref }}" cp ./apps/mudita-center/release/builder-debug.yml ./apps/mudita-center/release/builder-debug-mac.yml curl -u $NEXUS_USERNAME:$NEXUS_PASSWORD --upload-file ./apps/mudita-center/release/Mudita-Center.dmg https://nexus.mudita.com/repository/mudita-center/releases/$ENVIRONMENT_CATALOG_NAME/$APP_VERSION/Mudita-Center.dmg curl -u $NEXUS_USERNAME:$NEXUS_PASSWORD --upload-file ./apps/mudita-center/release/Mudita-Center.zip https://nexus.mudita.com/repository/mudita-center/releases/$ENVIRONMENT_CATALOG_NAME/$APP_VERSION/Mudita-Center.zip diff --git a/.github/workflows/nexus-mass-update.yml b/.github/workflows/nexus-mass-update.yml index cabf05a579..52a5f4d5e3 100644 --- a/.github/workflows/nexus-mass-update.yml +++ b/.github/workflows/nexus-mass-update.yml @@ -46,6 +46,7 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} LOCALAPPDATA: "" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -74,6 +75,7 @@ jobs: DEV_REDUX_LOGGER_ENABLED: ${{ secrets.DEV_REDUX_LOGGER_ENABLED }} DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup Env for Linux diff --git a/.github/workflows/nexus-mock-development.yml b/.github/workflows/nexus-mock-development.yml index 565a390c84..de380db5c5 100644 --- a/.github/workflows/nexus-mock-development.yml +++ b/.github/workflows/nexus-mock-development.yml @@ -46,6 +46,7 @@ jobs: DEV_TOOLS_SHORTCUT_ENABLED: "1" LOCALAPPDATA: "" MOCK_SERVICE_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -76,6 +77,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" MOCK_SERVICE_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup Env for Linux @@ -104,6 +106,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} MOCK_SERVICE_ENABLED: "1" DEV_TOOLS_SHORTCUT_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Changing app version in packages.json for Linux diff --git a/.github/workflows/nexus-mock-pre-production.yml b/.github/workflows/nexus-mock-pre-production.yml index 102f2bdef5..fc017b7f26 100644 --- a/.github/workflows/nexus-mock-pre-production.yml +++ b/.github/workflows/nexus-mock-pre-production.yml @@ -48,6 +48,7 @@ jobs: DEV_TOOLS_SHORTCUT_ENABLED: "1" LOCALAPPDATA: "" MOCK_SERVICE_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -78,6 +79,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" MOCK_SERVICE_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Changing app version in packages.json for Linux diff --git a/.github/workflows/nexus-mock-production.yml b/.github/workflows/nexus-mock-production.yml index 2b7ab34ae1..d373c207fe 100644 --- a/.github/workflows/nexus-mock-production.yml +++ b/.github/workflows/nexus-mock-production.yml @@ -48,6 +48,7 @@ jobs: DEV_TOOLS_SHORTCUT_ENABLED: "1" LOCALAPPDATA: "" MOCK_SERVICE_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -78,6 +79,7 @@ jobs: FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} DEV_TOOLS_SHORTCUT_ENABLED: "1" MOCK_SERVICE_ENABLED: "1" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Changing app version in packages.json for Linux diff --git a/.github/workflows/nexus-pre-production-latest.yml b/.github/workflows/nexus-pre-production-latest.yml index 88cd85d837..a25c137e6e 100644 --- a/.github/workflows/nexus-pre-production-latest.yml +++ b/.github/workflows/nexus-pre-production-latest.yml @@ -47,6 +47,7 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} LOCALAPPDATA: "" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -75,6 +76,7 @@ jobs: DEV_REDUX_LOGGER_ENABLED: ${{ secrets.DEV_REDUX_LOGGER_ENABLED }} DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup Env for Linux @@ -101,6 +103,7 @@ jobs: DEV_REDUX_LOGGER_ENABLED: ${{ secrets.DEV_REDUX_LOGGER_ENABLED }} DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Changing app version in packages.json for Linux & Standard Update diff --git a/.github/workflows/nexus-pre-production.yml b/.github/workflows/nexus-pre-production.yml index b8ab37b59c..fe7cf79da2 100644 --- a/.github/workflows/nexus-pre-production.yml +++ b/.github/workflows/nexus-pre-production.yml @@ -46,6 +46,7 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} LOCALAPPDATA: "" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -74,6 +75,7 @@ jobs: DEV_REDUX_LOGGER_ENABLED: ${{ secrets.DEV_REDUX_LOGGER_ENABLED }} DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup depedencies diff --git a/.github/workflows/nexus-production-with-os-rc.yml b/.github/workflows/nexus-production-with-os-rc.yml index 16881e260b..24b43f3ea2 100644 --- a/.github/workflows/nexus-production-with-os-rc.yml +++ b/.github/workflows/nexus-production-with-os-rc.yml @@ -46,6 +46,7 @@ jobs: DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} LOCALAPPDATA: "" + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} shell: cmd run: | SET > .env @@ -74,6 +75,7 @@ jobs: DEV_REDUX_LOGGER_ENABLED: ${{ secrets.DEV_REDUX_LOGGER_ENABLED }} DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Setup Env for Linux @@ -100,6 +102,7 @@ jobs: DEV_REDUX_LOGGER_ENABLED: ${{ secrets.DEV_REDUX_LOGGER_ENABLED }} DEV_DEVICE_LOGGER_ENABLED: ${{ secrets.DEV_DEVICE_LOGGER_ENABLED }} FEATURE_TOGGLE_RELEASE_ENVIRONMENT: ${{ secrets.FEATURE_TOGGLE_RELEASE_ENVIRONMENT }} + KOMPAKT_OS_UPDATE_DEV_TOKEN: ${{ secrets.KOMPAKT_OS_UPDATE_DEV_TOKEN }} run: | printenv > .env - name: Changing app version in packages.json for Linux diff --git a/apps/mudita-center-e2e/src/helpers/entity-fixtures.ts b/apps/mudita-center-e2e/src/helpers/entity-fixtures.ts new file mode 100644 index 0000000000..78178e6ec8 --- /dev/null +++ b/apps/mudita-center-e2e/src/helpers/entity-fixtures.ts @@ -0,0 +1,998 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +import { EntityData } from "device/models" + +export const contactEntities: EntityData[] = [ + { + entityType: "contacts", + contactId: "425", + searchName: "Dr. Anna Nowak Jr.", + sortField: "NowakAnna", + firstName: "Anna", + lastName: "Nowak", + namePrefix: "Dr.", + middleName: "Maria", + nameSuffix: "Jr.", + phoneNumbers: [ + { + id: "2981", + phoneNumber: "+48123456789", + phoneType: "MOBILE", + }, + ], + emailAddresses: [ + { + id: "2982", + emailAddress: "anna.nowak@example.com", + emailType: "WORK", + }, + ], + company: "ABC Corp.", + department: "HR", + workTitle: "Manager", + address: { + streetAddress: "Main Street 12", + city: "Warsaw", + country: "Poland", + type: "WORK", + }, + website: "https://example.com", + notes: "VIP client", + starred: false, + displayName1: "Dr.", + displayName2: "Anna", + displayName3: "Nowak", + displayName4: "Jr.", + }, + { + entityType: "contacts", + contactId: "426", + searchName: "Ms. Emily Clark", + sortField: "ClarkEmily", + firstName: "Emily", + lastName: "Clark", + namePrefix: "Ms.", + middleName: "Rose", + phoneNumbers: [ + { + id: "2989", + phoneNumber: "+12123456789", + phoneType: "WORK", + }, + ], + emailAddresses: [ + { + id: "2990", + emailAddress: "emily.clark@startup.com", + emailType: "WORK", + }, + ], + company: "Innovatech", + department: "Marketing", + workTitle: "Marketing Director", + address: { + streetAddress: "456 Innovation Ave", + city: "San Francisco", + country: "USA", + type: "WORK", + }, + website: "https://emilyclark.me", + notes: "Lead of the marketing strategy team.", + starred: false, + displayName1: "Ms.", + displayName2: "Emily", + displayName3: "Clark", + }, + { + entityType: "contacts", + contactId: "427", + searchName: "Dr. Michael Johnson PhD", + sortField: "JohnsonMichael", + firstName: "Michael", + lastName: "Johnson", + namePrefix: "Dr.", + middleName: "David", + nameSuffix: "PhD", + phoneNumbers: [ + { + id: "2997", + phoneNumber: "+49876543210", + phoneType: "MOBILE", + }, + { + id: "2998", + phoneNumber: "+49871234567", + phoneType: "HOME", + }, + ], + emailAddresses: [ + { + id: "2999", + emailAddress: "michael.j@researchlab.com", + emailType: "WORK", + }, + ], + company: "Research Labs", + department: "R&D", + workTitle: "Chief Scientist", + address: { + streetAddress: "789 Science Blvd", + city: "Berlin", + country: "Germany", + type: "WORK", + }, + website: "https://michaeljohnsonphd.com", + notes: "Collaborating on AI research projects.", + starred: false, + displayName1: "Dr.", + displayName2: "Michael", + displayName3: "Johnson", + displayName4: "PhD", + }, + { + entityType: "contacts", + contactId: "428", + searchName: + "Long Display Name (last name is long) Anna Maria Katarzyna Nowak-Wielka-Zabłocka-Długosz-Ostrowska-Mickiewicz-Piękna-Sobieska-Kowalewska-Jagiellońska-Słowacka-Krzyżanowska-Kordecka-Kościuszkowska", + sortField: + "Anna Maria Katarzyna Nowak-Wielka-Zabłocka-Długosz-Ostrowska-Mickiewicz-Piękna-Sobieska-Kowalewska-Jagiellońska-Słowacka-Krzyżanowska-Kordecka-KościuszkowskaLong Display Name (last name is long)", + firstName: "Long Display Name (last name is long)", + lastName: + "Anna Maria Katarzyna Nowak-Wielka-Zabłocka-Długosz-Ostrowska-Mickiewicz-Piękna-Sobieska-Kowalewska-Jagiellońska-Słowacka-Krzyżanowska-Kordecka-Kościuszkowska", + phoneNumbers: [ + { + id: "3006", + phoneNumber: "+48123456786", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "Long Display Name (last name is long)", + displayName3: + "Anna Maria Katarzyna Nowak-Wielka-Zabłocka-Długosz-Ostrowska-Mickiewicz-Piękna-Sobieska-Kowalewska-Jagiellońska-Słowacka-Krzyżanowska-Kordecka-Kościuszkowska", + }, + { + entityType: "contacts", + contactId: "429", + searchName: + "Aleksandra-Marianna-Katarzyna-Magdalena-Joanna-Weronika-Zofia-Karolina-Małgorzata-Anastazja Long Display Name (first name is long)", + sortField: + "Long Display Name (first name is long)Aleksandra-Marianna-Katarzyna-Magdalena-Joanna-Weronika-Zofia-Karolina-Małgorzata-Anastazja", + firstName: + "Aleksandra-Marianna-Katarzyna-Magdalena-Joanna-Weronika-Zofia-Karolina-Małgorzata-Anastazja", + lastName: "Long Display Name (first name is long)", + phoneNumbers: [ + { + id: "3013", + phoneNumber: "+48234567890", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: + "Aleksandra-Marianna-Katarzyna-Magdalena-Joanna-Weronika-Zofia-Karolina-Małgorzata-Anastazja", + displayName3: "Long Display Name (first name is long)", + }, + { + entityType: "contacts", + contactId: "430", + searchName: + "Special Character (last name with special characters) !@#$%^&*()-=+[]{}|;:',.<>?/`~", + sortField: + "!@#$%^&*()-=+[]{}|;:',.<>?/`~Special Character (last name with special characters)", + firstName: "Special Character (last name with special characters)", + lastName: "!@#$%^&*()-=+[]{}|;:',.<>?/`~", + phoneNumbers: [ + { + id: "3020", + phoneNumber: "+49123454789", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "Special Character (last name with special characters)", + displayName3: "!@#$%^&*()-=+[]{}|;:',.<>?/`~", + }, + { + entityType: "contacts", + contactId: "431", + searchName: "### Special Character (first name with special characters)", + sortField: "Special Character (first name with special characters)###", + firstName: "###", + lastName: "Special Character (first name with special characters)", + phoneNumbers: [ + { + id: "3027", + phoneNumber: "+49123426789", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "###", + displayName3: "Special Character (first name with special characters)", + }, + { + entityType: "contacts", + contactId: "432", + searchName: "Plus (last name with plus) +", + sortField: "+Plus (last name with plus)", + firstName: "Plus (last name with plus)", + lastName: "+", + phoneNumbers: [ + { + id: "3034", + phoneNumber: "+49123156789", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "Plus (last name with plus)", + displayName3: "+", + }, + { + entityType: "contacts", + contactId: "433", + searchName: "+ Plus (first name with plus)", + sortField: "Plus (first name with plus)+", + firstName: "+", + lastName: "Plus (first name with plus)", + phoneNumbers: [ + { + id: "3041", + phoneNumber: "+49123156789", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "+", + displayName3: "Plus (first name with plus)", + }, + { + entityType: "contacts", + contactId: "434", + searchName: "Marek Marmarecki", + sortField: "MarmareckiMarek", + firstName: "Marek", + lastName: "Marmarecki", + phoneNumbers: [ + { + id: "3048", + phoneNumber: "500500500", + phoneType: "MOBILE", + }, + { + id: "3049", + phoneNumber: "500500600", + phoneType: "WORK", + }, + ], + starred: false, + displayName2: "Marek", + displayName3: "Marmarecki", + }, + { + entityType: "contacts", + contactId: "435", + searchName: "Numer (last name is numeric) 12345", + sortField: "12345Numer (last name is numeric)", + firstName: "Numer (last name is numeric)", + lastName: "12345", + phoneNumbers: [ + { + id: "3056", + phoneNumber: "+48901234567", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "Numer (last name is numeric)", + displayName3: "12345", + }, + { + entityType: "contacts", + contactId: "436", + searchName: "Prof. PhD. (prefix & suffix only)", + sortField: "Prof.", + namePrefix: "Prof.", + nameSuffix: "PhD. (prefix & suffix only)", + phoneNumbers: [ + { + id: "3063", + phoneNumber: "+48345678901", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName1: "Prof.", + displayName4: "PhD. (prefix & suffix only)", + }, + { + entityType: "contacts", + contactId: "437", + searchName: "Jan (only middle name)", + sortField: "Jan (only middle name)", + middleName: "Jan (only middle name)", + starred: false, + displayName3: "Jan (only middle name)", + }, + { + entityType: "contacts", + contactId: "438", + searchName: "%%%% (only middle name)", + sortField: "%%%% (only middle name)", + middleName: "%%%% (only middle name)", + starred: false, + displayName3: "%%%% (only middle name)", + }, + { + entityType: "contacts", + contactId: "439", + searchName: "490123456789", + sortField: "490123456789", + phoneNumbers: [ + { + id: "3082", + phoneNumber: "490123456789", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName3: "490123456789", + }, + { + entityType: "contacts", + contactId: "440", + searchName: "911234567890", + sortField: "911234567890", + phoneNumbers: [ + { + id: "3089", + phoneNumber: "911234567890", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName3: "911234567890", + }, + { + entityType: "contacts", + contactId: "441", + searchName: "8612345678901", + sortField: "8612345678901", + phoneNumbers: [ + { + id: "3096", + phoneNumber: "8612345678901", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName3: "8612345678901", + }, + { + entityType: "contacts", + contactId: "442", + searchName: "+48345678902", + sortField: "+48345678902", + phoneNumbers: [ + { + id: "3103", + phoneNumber: "+48345678902", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName3: "+48345678902", + }, + { + entityType: "contacts", + contactId: "443", + searchName: "+48345678902", + sortField: "+48345678902", + phoneNumbers: [ + { + id: "3110", + phoneNumber: "+48345678902", + phoneType: "MOBILE", + }, + { + id: "3111", + phoneNumber: "+48445678903", + phoneType: "HOME", + }, + ], + starred: false, + displayName3: "+48345678902", + }, + { + entityType: "contacts", + contactId: "444", + searchName: "+48345678902", + sortField: "+48345678902", + phoneNumbers: [ + { + id: "3118", + phoneNumber: "+48345678902", + phoneType: "MOBILE", + }, + { + id: "3119", + phoneNumber: "+48445678903", + phoneType: "HOME", + }, + { + id: "3120", + phoneNumber: "+48555678904", + phoneType: "WORK", + }, + ], + starred: false, + displayName3: "+48345678902", + }, + { + entityType: "contacts", + contactId: "445", + searchName: "+48345678902", + sortField: "+48345678902", + phoneNumbers: [ + { + id: "3127", + phoneNumber: "+48345678902", + phoneType: "MOBILE", + }, + { + id: "3128", + phoneNumber: "+48445678903", + phoneType: "HOME", + }, + { + id: "3130", + phoneNumber: "+48665678905", + phoneType: "OTHER", + }, + { + id: "3129", + phoneNumber: "+48555678904", + phoneType: "WORK", + }, + ], + starred: false, + displayName3: "+48345678902", + }, + { + entityType: "contacts", + contactId: "446", + searchName: "+48555678904", + sortField: "+48555678904", + phoneNumbers: [ + { + id: "3138", + phoneNumber: "+48665678905", + phoneType: "OTHER", + }, + { + id: "3137", + phoneNumber: "+48555678904", + phoneType: "WORK", + }, + ], + starred: false, + displayName3: "+48555678904", + }, + { + entityType: "contacts", + contactId: "447", + searchName: "Anna (Germany-style)", + sortField: "Anna (Germany-style)", + firstName: "Anna (Germany-style)", + phoneNumbers: [ + { + id: "3145", + phoneNumber: "48123456789", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "Anna (Germany-style)", + }, + { + entityType: "contacts", + contactId: "448", + searchName: "Carlos (Brazil-style)", + sortField: "Carlos (Brazil-style)", + firstName: "Carlos (Brazil-style)", + phoneNumbers: [ + { + id: "3152", + phoneNumber: "551112345678", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "Carlos (Brazil-style)", + }, + { + entityType: "contacts", + contactId: "449", + searchName: "Yuki (Japan-style)", + sortField: "Yuki (Japan-style)", + firstName: "Yuki (Japan-style)", + phoneNumbers: [ + { + id: "3159", + phoneNumber: "81312345678", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "Yuki (Japan-style)", + }, + { + entityType: "contacts", + contactId: "450", + searchName: "Liam (Ireland & Australia)", + sortField: "Liam (Ireland & Australia)", + firstName: "Liam (Ireland & Australia)", + phoneNumbers: [ + { + id: "3166", + phoneNumber: "1512345678", + phoneType: "MOBILE", + }, + { + id: "3167", + phoneNumber: "611234567890123", + phoneType: "WORK", + }, + ], + starred: false, + displayName2: "Liam (Ireland & Australia)", + }, + { + entityType: "contacts", + contactId: "451", + searchName: "Amina (Morocco & USA)", + sortField: "Amina (Morocco & USA)", + firstName: "Amina (Morocco & USA)", + phoneNumbers: [ + { + id: "3175", + phoneNumber: "14155552671", + phoneType: "MOBILE", + }, + { + id: "3174", + phoneNumber: "201234567", + phoneType: "HOME", + }, + ], + starred: false, + displayName2: "Amina (Morocco & USA)", + }, + { + entityType: "contacts", + contactId: "452", + searchName: "home@email.com", + sortField: "home@email.com", + emailAddresses: [ + { + id: "3182", + emailAddress: "home@email.com", + emailType: "HOME", + }, + ], + starred: false, + displayName3: "home@email.com", + }, + { + entityType: "contacts", + contactId: "453", + searchName: "home@email.com", + sortField: "home@email.com", + emailAddresses: [ + { + id: "3189", + emailAddress: "home@email.com", + emailType: "HOME", + }, + { + id: "3190", + emailAddress: "work@email.com", + emailType: "WORK", + }, + ], + starred: false, + displayName3: "home@email.com", + }, + { + entityType: "contacts", + contactId: "454", + searchName: "home@email.com", + sortField: "home@email.com", + emailAddresses: [ + { + id: "3197", + emailAddress: "home@email.com", + emailType: "HOME", + }, + { + id: "3198", + emailAddress: "work@email.com", + emailType: "WORK", + }, + { + id: "3199", + emailAddress: "other@email.com", + emailType: "OTHER", + }, + ], + starred: false, + displayName3: "home@email.com", + }, + { + entityType: "contacts", + contactId: "455", + searchName: "home@email.com", + sortField: "home@email.com", + emailAddresses: [ + { + id: "3206", + emailAddress: "home@email.com", + emailType: "HOME", + }, + { + id: "3207", + emailAddress: "work@email.com", + emailType: "WORK", + }, + { + id: "3208", + emailAddress: "other@email.com", + emailType: "OTHER", + }, + { + id: "3209", + emailAddress: "unknown@email.com", + emailType: "OTHER", + }, + ], + starred: false, + displayName3: "home@email.com", + }, + { + entityType: "contacts", + contactId: "456", + searchName: "work@email.com", + sortField: "work@email.com", + emailAddresses: [ + { + id: "3216", + emailAddress: "work@email.com", + emailType: "WORK", + }, + { + id: "3217", + emailAddress: "other@email.com", + emailType: "OTHER", + }, + ], + starred: false, + displayName3: "work@email.com", + }, + { + entityType: "contacts", + contactId: "457", + searchName: "Bobby (nickname only)", + sortField: "Bobby (nickname only)", + nickName: "Bobby (nickname only)", + starred: false, + displayName3: "Bobby (nickname only)", + }, + { + entityType: "contacts", + contactId: "458", + searchName: "Innovative Technologies (company)", + sortField: "Innovative Technologies (company)", + company: "Innovative Technologies (company)", + starred: false, + displayName3: "Innovative Technologies (company)", + }, + { + entityType: "contacts", + contactId: "459", + searchName: "Human Resources (department)", + sortField: "Human Resources (department)", + department: "Human Resources (department)", + starred: false, + displayName3: "Human Resources (department)", + }, + { + entityType: "contacts", + contactId: "460", + searchName: "Chief Marketing Officer (job title)", + sortField: "Chief Marketing Officer (job title)", + workTitle: "Chief Marketing Officer (job title)", + starred: false, + displayName3: "Chief Marketing Officer (job title)", + }, + { + entityType: "contacts", + contactId: "461", + searchName: "Innovative Technologies (company & department)", + sortField: "Innovative Technologies (company & department)", + company: "Innovative Technologies (company & department)", + department: "Human Resources", + starred: false, + displayName3: "Innovative Technologies (company & department)", + }, + { + entityType: "contacts", + contactId: "462", + searchName: "Innovative Technologies (company & job title)", + sortField: "Innovative Technologies (company & job title)", + company: "Innovative Technologies (company & job title)", + workTitle: "Chief Marketing Officer", + starred: false, + displayName3: "Innovative Technologies (company & job title)", + }, + { + entityType: "contacts", + contactId: "463", + searchName: "Human Resources (department & job title)", + sortField: "Human Resources (department & job title)", + department: "Human Resources (department & job title)", + workTitle: "Chief Marketing Officer", + starred: false, + displayName3: "Human Resources (department & job title)", + }, + { + entityType: "contacts", + contactId: "464", + searchName: "Innovative Technologies (company, department & job title)", + sortField: "Innovative Technologies (company, department & job title)", + company: "Innovative Technologies (company, department & job title)", + department: "Human Resources", + workTitle: "Chief Marketing Officer", + starred: false, + displayName3: "Innovative Technologies (company, department & job title)", + }, + { + entityType: "contacts", + contactId: "465", + searchName: "Street 7 (full address), 10115, Berlin", + sortField: "Street 7 (full address), Berlin, 10115", + address: { + streetAddress: "Street 7 (full address)", + city: "Berlin", + zipCode: "10115", + type: "HOME", + }, + starred: false, + displayName3: "Street 7 (full address), 10115, Berlin", + }, + { + entityType: "contacts", + contactId: "466", + searchName: "Jane Smith", + sortField: "SmithJane", + firstName: "Jane", + lastName: "Smith", + address: { + streetAddress: "Street 5 (only street address)", + type: "HOME", + }, + starred: false, + displayName2: "Jane", + displayName3: "Smith", + }, + { + entityType: "contacts", + contactId: "467", + searchName: "Adam Johnson", + sortField: "JohnsonAdam", + firstName: "Adam", + lastName: "Johnson", + address: { + city: "Krakow", + type: "HOME", + }, + starred: false, + displayName2: "Adam", + displayName3: "Johnson", + }, + { + entityType: "contacts", + contactId: "468", + searchName: "Emily Davis", + sortField: "DavisEmily", + firstName: "Emily", + lastName: "Davis", + address: { + zipCode: "00-002", + type: "HOME", + }, + starred: false, + displayName2: "Emily", + displayName3: "Davis", + }, + { + entityType: "contacts", + contactId: "469", + searchName: "Michael Brown", + sortField: "BrownMichael", + firstName: "Michael", + lastName: "Brown", + address: { + streetAddress: "Street 9", + zipCode: "00-003", + type: "HOME", + }, + starred: false, + displayName2: "Michael", + displayName3: "Brown", + }, + { + entityType: "contacts", + contactId: "470", + searchName: "Michael Brown", + sortField: "BrownMichael", + firstName: "Michael", + lastName: "Brown", + address: { + state: "California", + country: "USA", + type: "HOME", + }, + starred: false, + displayName2: "Michael", + displayName3: "Brown", + }, + { + entityType: "contacts", + contactId: "471", + searchName: "sip:jan.nowak@siponly.com", + sortField: "sip:jan.nowak@siponly.com", + sip: "sip:jan.nowak@siponly.com", + starred: false, + displayName3: "sip:jan.nowak@siponly.com", + }, + { + entityType: "contacts", + contactId: "472", + searchName: "https://websiteonly.com", + sortField: "https://websiteonly.com", + website: "https://websiteonly.com", + starred: false, + displayName3: "https://websiteonly.com", + }, + { + entityType: "contacts", + contactId: "473", + searchName: "This is a test note. (only notes)", + sortField: "This is a test note. (only notes)", + notes: "This is a test note. (only notes)", + starred: false, + displayName3: "This is a test note. (only notes)", + }, + { + entityType: "contacts", + contactId: "474", + searchName: "🌞 Clark", + sortField: "Clark🌞", + firstName: "🌞", + lastName: "Clark", + phoneNumbers: [ + { + id: "3327", + phoneNumber: "+12123456789", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "🌞", + displayName3: "Clark", + }, + { + entityType: "contacts", + contactId: "475", + searchName: "John 🍀", + sortField: "🍀John", + firstName: "John", + lastName: "🍀", + phoneNumbers: [ + { + id: "3334", + phoneNumber: "+441234567890", + phoneType: "MOBILE", + }, + ], + starred: false, + displayName2: "John", + displayName3: "🍀", + }, + { + entityType: "contacts", + contactId: "476", + searchName: "+49876543210", + sortField: "+49876543210", + phoneNumbers: [ + { + id: "3341", + phoneNumber: "+49876543210", + phoneType: "MOBILE", + }, + ], + nickName: "🐶🐱", + starred: false, + displayName3: "+49876543210", + }, + { + entityType: "contacts", + contactId: "477", + searchName: "+48123456789", + sortField: "+48123456789", + phoneNumbers: [ + { + id: "3348", + phoneNumber: "+48123456789", + phoneType: "MOBILE", + }, + ], + company: "🚀💼", + starred: false, + displayName3: "+48123456789", + }, + { + entityType: "contacts", + contactId: "478", + searchName: "+48223456789", + sortField: "+48223456789", + phoneNumbers: [ + { + id: "3355", + phoneNumber: "+48223456789", + phoneType: "WORK", + }, + ], + notes: "💡🚨", + starred: false, + displayName3: "+48223456789", + }, +] + +export const selectedContactsEntities: EntityData[] = [ + contactEntities[0], // Dr. Anna Nowak Jr. – spełnia wymagania a (First name and Last name + Phone) + contactEntities[2], // Dr. Michael Johnson PhD – spełnia wymagania c (Suffix, First name and Last name + Phone) + contactEntities[3], // Long Display Name (last name is long) – spełnia wymagania e (Last name only + Phone) + contactEntities[9], // Plus (last name with plus) – nietypowy przypadek nazwiska z symbolem "+" + contactEntities[10], // Marek Marmarecki – spełnia wymagania g (Contact with two phone numbers) + contactEntities[19], // +48345678902 – spełnia wymagania f (Phone only) + contactEntities[31], // Anna (Germany-style) – różnicujący przypadek z imieniem i numerem + contactEntities[33], // Carlos (Brazil-style) – różnicujący przypadek regionalny + contactEntities[44], // 🌞 Clark – różnicujący przypadek z emoji w imieniu + contactEntities[45], // John 🍀 – różnicujący przypadek z emoji w nazwisku + contactEntities[46], // 🐶🐱 (nickname) – różnicujący przypadek z emoji w pseudonimie + contactEntities[53], // 💡🚨 (notes) – różnicujący przypadek z emoji w notatkach + contactEntities[7], // Special Character (last name with special characters) – różnicujący przypadek z nietypowym nazwiskiem + contactEntities[13], // Numer (last name is numeric) – różnicujący przypadek z liczbami w nazwisku + contactEntities[19], // +48345678902 – sam numer, spełnia wymaganie f + contactEntities[47], // Liam (Ireland & Australia) – kontakt z numerami z różnych regionów + contactEntities[48], // Amina (Morocco & USA) – różnorodność regionalna i wiele numerów +] + +export const audioFileEntities: EntityData[] = [ + { + id: "457", + filePath: "/storage/emulated/0/test.mp3", + fileName: "test.mp3", + extension: "mp3", + fileSize: 1048576000, + fileType: "AUDIO", + mimeType: "audio/mpeg", + isInternal: true, + entityType: "audioFiles", + }, +] diff --git a/apps/mudita-center-e2e/src/helpers/index.ts b/apps/mudita-center-e2e/src/helpers/index.ts index 62a4e2bea6..be5360b462 100644 --- a/apps/mudita-center-e2e/src/helpers/index.ts +++ b/apps/mudita-center-e2e/src/helpers/index.ts @@ -3,5 +3,6 @@ * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md */ +export * from "./mock-entity-download-process.helper" export * from "./sleep.helper" export * from "./testid.helper" diff --git a/apps/mudita-center-e2e/src/helpers/mock-entity-download-process.helper.ts b/apps/mudita-center-e2e/src/helpers/mock-entity-download-process.helper.ts new file mode 100644 index 0000000000..576cd50635 --- /dev/null +++ b/apps/mudita-center-e2e/src/helpers/mock-entity-download-process.helper.ts @@ -0,0 +1,90 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +import { E2EMockClient } from "../../../../libs/e2e-mock/client/src/lib/e2e-mock-client" +import { generateUniqueNumber } from "./utils/generate-unique-number-id.helper" +import { generateBase64Info } from "./utils/generate-base-64-info.helper" + +interface mockEntityDownloadProcessOptions { + path: string + entityType: string + data: Record[] +} + +export const mockEntityDownloadProcess = ({ + path, + entityType, + data, +}: mockEntityDownloadProcessOptions) => { + const { base64, sizeInBytes, crc32Hex } = generateBase64Info({ data }) + const totalEntities = data.length + const transferId = generateUniqueNumber() + + E2EMockClient.mockResponse({ + path, + body: { totalEntities, uniqueKey: "1733750368390" }, + match: { + expected: { + entityType: entityType, + }, + }, + endpoint: "ENTITIES_METADATA", + method: "GET", + status: 200, + }) + + E2EMockClient.mockResponse({ + path, + body: { + filePath: `../${entityType}_entities.json`, + progress: 100, + }, + match: { + expected: { + entityType: entityType, + responseType: "file", + }, + }, + endpoint: "ENTITIES_DATA", + method: "GET", + status: 200, + }) + + E2EMockClient.mockResponse({ + path, + body: { + transferId, + chunkSize: sizeInBytes, + fileSize: sizeInBytes, + crc32: crc32Hex, + }, + match: { + expected: { + filePath: `../${entityType}_entities.json`, + }, + }, + endpoint: "PRE_FILE_TRANSFER", + method: "GET", + status: 200, + }) + + E2EMockClient.mockResponse({ + path, + body: { + transferId, + chunkNumber: 1, + data: base64, + }, + match: { + expected: { + transferId, + chunkNumber: 1, + }, + }, + endpoint: "FILE_TRANSFER", + method: "GET", + status: 200, + }) +} diff --git a/apps/mudita-center-e2e/src/helpers/utils/generate-base-64-info.helper.ts b/apps/mudita-center-e2e/src/helpers/utils/generate-base-64-info.helper.ts new file mode 100644 index 0000000000..7a9422f825 --- /dev/null +++ b/apps/mudita-center-e2e/src/helpers/utils/generate-base-64-info.helper.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +import crc32 from "crc-32" + +export function generateBase64Info(obj: Record) { + const jsonString = JSON.stringify(obj) + const data = Buffer.from(jsonString, "utf8").toString() + const base64String = Buffer.from(data).toString("base64") + const sizeInBytes = Buffer.byteLength(data, "utf8") + const crc32Hex = (crc32.buf(Buffer.from(base64String, "utf8")) >>> 0) + .toString(16) + .padStart(8, "0") + + return { + base64: base64String, + sizeInBytes: sizeInBytes, + crc32Hex: crc32Hex, + } +} diff --git a/apps/mudita-center-e2e/src/helpers/utils/generate-unique-number-id.helper.ts b/apps/mudita-center-e2e/src/helpers/utils/generate-unique-number-id.helper.ts new file mode 100644 index 0000000000..0c7b745c13 --- /dev/null +++ b/apps/mudita-center-e2e/src/helpers/utils/generate-unique-number-id.helper.ts @@ -0,0 +1,7 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +export const generateUniqueNumber = () => + Date.now() + Math.floor(Math.random() * 1000) diff --git a/apps/mudita-center-e2e/src/specs/overview/e2e-mock-lock-sample.e2e.ts b/apps/mudita-center-e2e/src/specs/overview/e2e-mock-lock-sample.e2e.ts index a0f36b50b5..ae5b5b1cb7 100644 --- a/apps/mudita-center-e2e/src/specs/overview/e2e-mock-lock-sample.e2e.ts +++ b/apps/mudita-center-e2e/src/specs/overview/e2e-mock-lock-sample.e2e.ts @@ -1,11 +1,14 @@ -// import { DEFAULT_RESPONSES } from "Libs/e2e-mock/responses/src/lib/default-responses" import { E2EMockClient } from "../../../../../libs/e2e-mock/client/src" +import { DEFAULT_RESPONSES } from "../../../../../libs/e2e-mock/responses/src" +import { mockEntityDownloadProcess } from "../../helpers/mock-entity-download-process.helper" import { - DEFAULT_RESPONSES, - outboxReloadOverview, - overviewDataWithoutBadge, -} from "../../../../../libs/e2e-mock/responses/src" -// import { outboxReloadOverview } from "Libs/e2e-mock/responses/src" + audioFileEntities, + selectedContactsEntities, +} from "../../helpers/entity-fixtures" + +function getBodyAsRecord(body: unknown): Record { + return body ? (body as Record) : {} +} describe("E2E mock lock sample", () => { before(async () => { @@ -66,34 +69,111 @@ describe("E2E mock lock sample", () => { E2EMockClient.mockResponse({ path: "path-1", - body: DEFAULT_RESPONSES.FEATURE_DATA?.GET?.body as Record, + body: getBodyAsRecord( + DEFAULT_RESPONSES.API_CONFIGURATION?.GET?.[0]?.body + ), + endpoint: "API_CONFIGURATION", + method: "GET", + status: 200, + }) + + await browser.pause(2000) + + E2EMockClient.mockResponse({ + path: "path-1", + body: getBodyAsRecord(DEFAULT_RESPONSES.FEATURE_DATA?.GET?.[0]?.body), + match: { + expected: { + feature: "mc-overview", + lang: "en-US", + }, + }, endpoint: "FEATURE_DATA", method: "GET", status: 200, }) - // await browser.pause(2000) E2EMockClient.mockResponse({ path: "path-1", - body: DEFAULT_RESPONSES.FEATURE_CONFIGURATION?.GET?.body as Record< - string, - any - >, + body: getBodyAsRecord(DEFAULT_RESPONSES.FEATURE_DATA?.GET?.[1]?.body), + match: { + expected: { + feature: "fileManager", + lang: "en-US", + }, + }, + endpoint: "FEATURE_DATA", + method: "GET", + status: 200, + }) + + await browser.pause(2000) + + E2EMockClient.mockResponse({ + path: "path-1", + body: getBodyAsRecord( + DEFAULT_RESPONSES.FEATURE_CONFIGURATION?.GET?.[0]?.body + ), + match: { + expected: { + feature: "contacts", + lang: "en-US", + }, + }, + endpoint: "FEATURE_CONFIGURATION", + method: "GET", + status: 200, + }) + E2EMockClient.mockResponse({ + path: "path-1", + body: getBodyAsRecord( + DEFAULT_RESPONSES.FEATURE_CONFIGURATION?.GET?.[1]?.body + ), + match: { + expected: { + feature: "mc-overview", + lang: "en-US", + }, + }, + endpoint: "FEATURE_CONFIGURATION", + method: "GET", + status: 200, + }) + E2EMockClient.mockResponse({ + path: "path-1", + body: getBodyAsRecord( + DEFAULT_RESPONSES.FEATURE_CONFIGURATION?.GET?.[2]?.body + ), + match: { + expected: { + feature: "fileManager", + lang: "en-US", + }, + }, endpoint: "FEATURE_CONFIGURATION", method: "GET", status: 200, }) E2EMockClient.mockResponse({ path: "path-1", - body: DEFAULT_RESPONSES.MENU_CONFIGURATION?.GET?.body as Record< - string, - any - >, + body: getBodyAsRecord( + DEFAULT_RESPONSES.MENU_CONFIGURATION?.GET?.[0]?.body + ), endpoint: "MENU_CONFIGURATION", method: "GET", status: 200, }) + E2EMockClient.mockResponse({ + path: "path-1", + body: getBodyAsRecord( + DEFAULT_RESPONSES.ENTITIES_METADATA?.GET?.[0]?.body + ), + endpoint: "ENTITIES_METADATA", + method: "GET", + status: 200, + }) + E2EMockClient.mockResponse({ path: "path-1", body: { @@ -105,6 +185,39 @@ describe("E2E mock lock sample", () => { status: 200, }) + E2EMockClient.mockResponse({ + path: "path-1", + body: getBodyAsRecord( + DEFAULT_RESPONSES.ENTITIES_CONFIGURATION?.GET?.[0]?.body + ), + match: { expected: { entityType: "contacts" } }, + endpoint: "ENTITIES_CONFIGURATION", + method: "GET", + status: 200, + }) + + E2EMockClient.mockResponse({ + path: "path-1", + body: getBodyAsRecord( + DEFAULT_RESPONSES.ENTITIES_CONFIGURATION?.GET?.[1]?.body + ), + match: { expected: { entityType: "audioFiles" } }, + endpoint: "ENTITIES_CONFIGURATION", + method: "GET", + status: 200, + }) + + mockEntityDownloadProcess({ + path: "path-1", + data: selectedContactsEntities, + entityType: "contacts", + }) + mockEntityDownloadProcess({ + path: "path-1", + data: audioFileEntities, + entityType: "audioFiles", + }) + await browser.pause(10000) }) }) diff --git a/libs/device/models/src/lib/api-config/api-config.test.ts b/libs/device/models/src/lib/api-config/api-config.test.ts index 68ea8bfb0f..80cbcb17f9 100644 --- a/libs/device/models/src/lib/api-config/api-config.test.ts +++ b/libs/device/models/src/lib/api-config/api-config.test.ts @@ -7,6 +7,7 @@ import { ApiConfig, ApiConfigValidator } from "./api-config" const minimumApiConfig: ApiConfig = { apiVersion: "1.0.0", + osVersion: "0.0.46 MuditaOS K", features: ["mc-overview"], productId: "productId", vendorId: "vendorId", diff --git a/libs/device/models/src/lib/api-config/api-config.ts b/libs/device/models/src/lib/api-config/api-config.ts index 95f134ee64..0c5b349fa3 100644 --- a/libs/device/models/src/lib/api-config/api-config.ts +++ b/libs/device/models/src/lib/api-config/api-config.ts @@ -11,6 +11,7 @@ export type MCLang = z.infer export const ApiConfigValidator = z.object({ apiVersion: z.string(), + osVersion: z.string(), lang: MCLangValidator.optional(), variant: z.string().optional(), productId: z.string(), @@ -18,6 +19,12 @@ export const ApiConfigValidator = z.object({ serialNumber: z.string().optional(), features: z.array(z.string()).min(1), entityTypes: z.array(z.string()).min(1).optional(), + otaApiConfig: z + .object({ + otaApiKey: z.string(), + osVersionTimestamp: z.number(), + }) + .optional(), }) export type ApiConfig = z.infer diff --git a/libs/e2e-mock/responses/src/lib/api-config-responses.ts b/libs/e2e-mock/responses/src/lib/api-config-responses.ts index db4e4c5f75..dd7fad2fd6 100644 --- a/libs/e2e-mock/responses/src/lib/api-config-responses.ts +++ b/libs/e2e-mock/responses/src/lib/api-config-responses.ts @@ -7,6 +7,7 @@ import { ApiConfig } from "device/models" export const apiConfigWithContacts: ApiConfig = { apiVersion: "1.0.0", + osVersion: "0.0.46 MuditaOS K", lang: "en-US", variant: "black", features: ["mc-overview", "contacts"], diff --git a/libs/e2e-mock/responses/src/lib/default-responses.ts b/libs/e2e-mock/responses/src/lib/default-responses.ts index e9b4fe9db8..956cd0856a 100644 --- a/libs/e2e-mock/responses/src/lib/default-responses.ts +++ b/libs/e2e-mock/responses/src/lib/default-responses.ts @@ -6,7 +6,15 @@ import { ApiResponse } from "Core/device/types/mudita-os" import { MatchConfig } from "Libs/e2e-mock/server/src" import { APIEndpointType, APIMethodsType } from "device/models" - +import { + entitiesConfiguration, + entitiesConfigurationAudioFiles, +} from "./entities-configuration-responses" +import { + featureConfigurationContacts, + featureConfigurationFileManager, + featureConfigurationOverview, +} from "./feature-configuration-responses" //import from "Core/device" breaks usage in e2e enum ResponseStatus { Ok = 200, @@ -45,166 +53,281 @@ export type MocksArrayResponsesMap = Partial< Record > -export const DEFAULT_RESPONSES: MockResponsesMap = { +export const DEFAULT_RESPONSES: MocksArrayResponsesMap = { API_CONFIGURATION: { - GET: { - status: ResponseStatus.Ok, - body: { - apiVersion: "1.0.0", - lang: "en-US", - variant: "black", - features: ["mc-overview"], - productId: "2006", - vendorId: "0e8d", - serialNumber: "0123456789ABCDEF", - }, - }, + GET: [ + { + status: ResponseStatus.Ok, + body: { + apiVersion: "1.0.0", + osVersion: "0.0.46 MuditaOS K", + lang: "en-US", + variant: "black", + features: ["mc-overview", "contacts", "fileManager"], + entityTypes: ["contacts", "audioFiles"], + productId: "2006", + vendorId: "0e8d", + serialNumber: "0123456789ABCDEF", + otaApiConfig: { + otaApiKey: "864055030180383", + osVersionTimestamp: 1733752055000, + }, + }, + }, + ], }, MENU_CONFIGURATION: { - GET: { - status: ResponseStatus.Ok, - body: { - title: "Kompakt", - menuItems: [ - { - feature: "mc-overview", - displayName: "Overview", - icon: "overview", - }, - ], + GET: [ + { + status: ResponseStatus.Ok, + body: { + title: "Kompakt", + menuItems: [ + { + feature: "mc-overview", + displayName: "Overview", + icon: "overview", + }, + { + feature: "contacts", + displayName: "Contacts", + icon: "contacts-book", + }, + { + feature: "fileManager", + displayName: "Manage Files", + icon: "file-manager", + }, + ], + }, }, - }, + ], }, OUTBOX: { - GET: { - status: ResponseStatus.Ok, - body: { features: [], data: [] }, - }, + GET: [ + { + status: ResponseStatus.Ok, + body: { features: [], data: [] }, + }, + ], }, - FEATURE_DATA: { - GET: { - status: ResponseStatus.Ok, - body: { - summary: { - about: { - serialNumber: { text: "0123456789ABCDEF" }, - imei1: { text: "864055030138811" }, - imei2: { text: "864055030138829" }, - sar: { - text: "### SAR\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed aliquet ligula, viverra feugiat massa. In hac habitasse platea dictumst.\n\n1. Interdum et malesuada fames ac ante ipsum primis in faucibus.\n2. Suspendisse consectetur, nibh non consequat hendrerit, nibh felis commodo lacus, id auctor ante purus vitae justo.\n3. Cras purus neque, pharetra vitae nulla ac, mollis facilisis felis. Sed sit amet ex diam.\n\n> Sed accumsan sem nec iaculis euismod.", - }, + FEATURE_CONFIGURATION: { + GET: [ + { + status: ResponseStatus.Ok, + body: featureConfigurationContacts, + match: { + expected: { + feature: "contacts", + lang: "en-US", }, }, - sections: { - battery: { icon: "battery-charging-5", text: "100%", subText: "" }, - update: { text: "ANDROID 12", version: "0.3.0" }, - status: { badgeText: "Offline+" }, - "airplane-mode": { icon: "airplane-mode", text: "Airplane mode" }, + }, + { + status: ResponseStatus.Ok, + body: featureConfigurationOverview, + match: { + expected: { + feature: "mc-overview", + lang: "en-US", + }, }, }, - }, + { + status: ResponseStatus.Ok, + body: featureConfigurationFileManager, + match: { + expected: { + feature: "fileManager", + lang: "en-US", + }, + }, + }, + ], }, - FEATURE_CONFIGURATION: { - GET: { - status: ResponseStatus.Ok, - body: { - title: "Overview", - summary: { - show: true, - showImg: true, - imgVariant: "black", - showSerialNumber: true, - serialNumberLabel: "Serial number", - showAbout: true, - aboutTitle: "About your device", - aboutIcon: "device", - aboutSubtitle: "Device details", - aboutFields: [ - { - dataKey: "serialNumber", - type: "detail-list-text", - title: "Serial number", - }, - { - dataKey: "imei1", - type: "detail-list-text", - title: "IMEI (sim slot 1)", - }, - { - dataKey: "imei2", - type: "detail-list-text", - title: "IMEI (sim slot 2)", + FEATURE_DATA: { + GET: [ + { + status: ResponseStatus.Ok, + body: { + summary: { + about: { + serialNumber: { text: "0123456789ABCDEF" }, + imei1: { text: "864055030138811" }, + imei2: { text: "864055030138829" }, + sar: { + text: "### SAR\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed aliquet ligula, viverra feugiat massa. In hac habitasse platea dictumst.\n\n1. Interdum et malesuada fames ac ante ipsum primis in faucibus.\n2. Suspendisse consectetur, nibh non consequat hendrerit, nibh felis commodo lacus, id auctor ante purus vitae justo.\n3. Cras purus neque, pharetra vitae nulla ac, mollis facilisis felis. Sed sit amet ex diam.\n\n> Sed accumsan sem nec iaculis euismod.", + }, }, + }, + sections: { + battery: { icon: "battery-charging-5", text: "100%", subText: "" }, + update: { text: "ANDROID 12", version: "0.3.0" }, + status: { badgeText: "Offline+" }, + "airplane-mode": { icon: "airplane-mode", text: "Airplane mode" }, + }, + }, + match: { expected: { feature: "mc-overview", lang: "en-US" } }, + }, + { + status: ResponseStatus.Ok, + body: { + storageInformation: [ { - dataKey: "sar", - type: "detail-list-modal", - title: "SAR", - buttonText: "Check SAR information", + storageType: "INTERNAL", + totalSpaceBytes: 32000000000, + usedSpaceBytes: 9576652800, + totalSpaceString: "32 GB", + usedSpaceString: "9.6 GB", + categoriesSpaceInformation: { + imageFiles: { + storageCategory: "imageFiles", + spaceUsedBytes: 90085267, + spaceUsedString: "90.1 MB", + }, + audioFiles: { + storageCategory: "audioFiles", + spaceUsedBytes: 1048576000, + spaceUsedString: "1 GB", + }, + ebookFiles: { + storageCategory: "ebookFiles", + spaceUsedBytes: 0, + spaceUsedString: "0 B", + }, + otherFiles: { + storageCategory: "otherFiles", + spaceUsedBytes: 8437991533, + spaceUsedString: "8.4 GB", + }, + }, }, ], }, - sections: [ - { - title: "Status", - type: "tile-list", - dataKey: "status", - fields: [ - { dataKey: "battery", type: "icon-text" }, - { dataKey: "airplane-mode", type: "icon-text" }, - ], + match: { expected: { feature: "fileManager", lang: "en-US" } }, + }, + ], + }, + ENTITIES_CONFIGURATION: { + GET: [ + { + status: ResponseStatus.Ok, + body: entitiesConfiguration, + match: { expected: { entityType: "contacts" } }, + }, + { + status: ResponseStatus.Ok, + body: entitiesConfigurationAudioFiles, + match: { expected: { entityType: "audioFiles" } }, + }, + ], + }, + ENTITIES_METADATA: { + GET: [ + { + status: ResponseStatus.Ok, + body: { totalEntities: 1, uniqueKey: "1733750368393" }, + match: { expected: { entityType: "contacts" } }, + }, + { + status: ResponseStatus.Ok, + body: { totalEntities: 1, uniqueKey: "1733750368394" }, + match: { expected: { entityType: "audioFiles" } }, + }, + ], + }, + ENTITIES_DATA: { + GET: [ + { + status: ResponseStatus.Ok, + body: { + filePath: "../contact_entities.json", + progress: 100, + }, + match: { + expected: { + entityType: "contacts", + responseType: "file", }, - { - dataKey: "update", - type: "mc-overview-update", - title: "Android OS", - currentVersionKey: "version", - showBadge: false, - versionLabel: "Current version:", + }, + }, + { + status: ResponseStatus.Ok, + body: { + filePath: "../audioFiles_entities.json", + progress: 100, + }, + match: { + expected: { + entityType: "audioFiles", + responseType: "file", }, - { - dataKey: "backup", - type: "mc-overview-backup", - title: "Backup", - backupFeatures: [ - { label: "Contact list", key: "CONTACT_LIST" }, - { label: "Call log", key: "CALL_LOG" }, - { label: "Messages", key: "MESSAGES" }, - { label: "Notes", key: "NOTES" }, - { label: "Calendar events", key: "CALENDAR_EVENTS" }, - { - label: "OS version & OS settings", - key: "OS_VERSION_AND_SETTINGS", - }, - { label: "App settings: Phone, Messages", key: "APP_SETTINGS" }, - ], - restoreFeatures: [ - { - label: "Contact list", - feature: "CONTACT_LIST", - keys: ["CONTACT_LIST"], - }, - { label: "Call log", feature: "CALL_LOG", keys: ["CALL_LOG"] }, - { label: "Messages", feature: "MESSAGES", keys: ["MESSAGES"] }, - { label: "Notes", feature: "NOTES", keys: ["NOTES"] }, - { - label: "Calendar events", - feature: "CALENDAR_EVENTS", - keys: ["CALENDAR_EVENTS"], - }, - { - label: "OS version & OS settings", - feature: "OS_VERSION_AND_SETTINGS", - keys: ["OS_VERSION_AND_SETTINGS"], - }, - { - label: "App settings: Phone, Messages", - feature: "APP_SETTINGS", - keys: ["APP_SETTINGS"], - }, - ], + }, + }, + ], + }, + PRE_FILE_TRANSFER: { + GET: [ + { + status: ResponseStatus.Ok, + body: { + transferId: 48647, + chunkSize: 6574, + fileSize: 6574, + crc32: "f8748c26", + }, + match: { + expected: { + filePath: "../contact_entities.json", + }, + }, + }, + { + status: ResponseStatus.Ok, + body: { + transferId: 1734669809788, + chunkSize: 214, + fileSize: 214, + crc32: "217b0c15", + }, + match: { + expected: { + filePath: "../audioFiles_entities.json", + }, + }, + }, + ], + }, + FILE_TRANSFER: { + GET: [ + { + status: ResponseStatus.Ok, + body: { + transferId: 48647, + chunkNumber: 1, + data: "eyJkYXRhIjpbeyJjb250YWN0SWQiOiI0MjUiLCJlbnRpdHlUeXBlIjoiY29udGFjdHMiLCJzZWFyY2hOYW1lIjoiRHIuIEFubmEgTm93YWsgSnIuIiwic29ydEZpZWxkIjoiTm93YWtBbm5hIiwiZmlyc3ROYW1lIjoiQW5uYSIsImxhc3ROYW1lIjoiTm93YWsiLCJuYW1lUHJlZml4IjoiRHIuIiwibWlkZGxlTmFtZSI6Ik1hcmlhIiwibmFtZVN1ZmZpeCI6IkpyLiIsInBob25lTnVtYmVycyI6W3siaWQiOiIyOTgxIiwicGhvbmVOdW1iZXIiOiIrNDgxMjM0NTY3ODkiLCJwaG9uZVR5cGUiOiJNT0JJTEUifV0sImVtYWlsQWRkcmVzc2VzIjpbeyJpZCI6IjI5ODIiLCJlbWFpbEFkZHJlc3MiOiJhbm5hLm5vd2FrQGV4YW1wbGUuY29tIiwiZW1haWxUeXBlIjoiV09SSyJ9XSwiY29tcGFueSI6IkFCQyBDb3JwLiIsImRlcGFydG1lbnQiOiJIUiIsIndvcmtUaXRsZSI6Ik1hbmFnZXIiLCJhZGRyZXNzIjp7InN0cmVldEFkZHJlc3MiOiJNYWluIFN0cmVldCAxMiIsImNpdHkiOiJXYXJzYXciLCJjb3VudHJ5IjoiUG9sYW5kIiwidHlwZSI6IldPUksifSwid2Vic2l0ZSI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJub3RlcyI6IlZJUCBjbGllbnQiLCJzdGFycmVkIjpmYWxzZSwiZGlzcGxheU5hbWUxIjoiRHIuIiwiZGlzcGxheU5hbWUyIjoiQW5uYSIsImRpc3BsYXlOYW1lMyI6Ik5vd2FrIiwiZGlzcGxheU5hbWU0IjoiSnIuIn0seyJjb250YWN0SWQiOiI0MjciLCJlbnRpdHlUeXBlIjoiY29udGFjdHMiLCJzZWFyY2hOYW1lIjoiRHIuIE1pY2hhZWwgSm9obnNvbiBQaEQiLCJzb3J0RmllbGQiOiJKb2huc29uTWljaGFlbCIsImZpcnN0TmFtZSI6Ik1pY2hhZWwiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJuYW1lUHJlZml4IjoiRHIuIiwibWlkZGxlTmFtZSI6IkRhdmlkIiwibmFtZVN1ZmZpeCI6IlBoRCIsInBob25lTnVtYmVycyI6W3siaWQiOiIyOTk3IiwicGhvbmVOdW1iZXIiOiIrNDk4NzY1NDMyMTAiLCJwaG9uZVR5cGUiOiJNT0JJTEUifSx7ImlkIjoiMjk5OCIsInBob25lTnVtYmVyIjoiKzQ5ODcxMjM0NTY3IiwicGhvbmVUeXBlIjoiSE9NRSJ9XSwiZW1haWxBZGRyZXNzZXMiOlt7ImlkIjoiMjk5OSIsImVtYWlsQWRkcmVzcyI6Im1pY2hhZWwuakByZXNlYXJjaGxhYi5jb20iLCJlbWFpbFR5cGUiOiJXT1JLIn1dLCJjb21wYW55IjoiUmVzZWFyY2ggTGFicyIsImRlcGFydG1lbnQiOiJSJkQiLCJ3b3JrVGl0bGUiOiJDaGllZiBTY2llbnRpc3QiLCJhZGRyZXNzIjp7InN0cmVldEFkZHJlc3MiOiI3ODkgU2NpZW5jZSBCbHZkIiwiY2l0eSI6IkJlcmxpbiIsImNvdW50cnkiOiJHZXJtYW55IiwidHlwZSI6IldPUksifSwid2Vic2l0ZSI6Imh0dHBzOi8vbWljaGFlbGpvaG5zb25waGQuY29tIiwibm90ZXMiOiJDb2xsYWJvcmF0aW5nIG9uIEFJIHJlc2VhcmNoIHByb2plY3RzLiIsInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTEiOiJEci4iLCJkaXNwbGF5TmFtZTIiOiJNaWNoYWVsIiwiZGlzcGxheU5hbWUzIjoiSm9obnNvbiIsImRpc3BsYXlOYW1lNCI6IlBoRCJ9LHsiY29udGFjdElkIjoiNDI4IiwiZW50aXR5VHlwZSI6ImNvbnRhY3RzIiwic2VhcmNoTmFtZSI6IkxvbmcgRGlzcGxheSBOYW1lIChsYXN0IG5hbWUgaXMgbG9uZykgQW5uYSBNYXJpYSBLYXRhcnp5bmEgTm93YWstV2llbGthLVphYsWCb2NrYS1ExYJ1Z29zei1Pc3Ryb3dza2EtTWlja2lld2ljei1QacSZa25hLVNvYmllc2thLUtvd2FsZXdza2EtSmFnaWVsbG/FhHNrYS1TxYJvd2Fja2EtS3J6ecW8YW5vd3NrYS1Lb3JkZWNrYS1Lb8WbY2l1c3prb3dza2EiLCJzb3J0RmllbGQiOiJBbm5hIE1hcmlhIEthdGFyenluYSBOb3dhay1XaWVsa2EtWmFixYJvY2thLUTFgnVnb3N6LU9zdHJvd3NrYS1NaWNraWV3aWN6LVBpxJlrbmEtU29iaWVza2EtS293YWxld3NrYS1KYWdpZWxsb8WEc2thLVPFgm93YWNrYS1Lcnp5xbxhbm93c2thLUtvcmRlY2thLUtvxZtjaXVzemtvd3NrYUxvbmcgRGlzcGxheSBOYW1lIChsYXN0IG5hbWUgaXMgbG9uZykiLCJmaXJzdE5hbWUiOiJMb25nIERpc3BsYXkgTmFtZSAobGFzdCBuYW1lIGlzIGxvbmcpIiwibGFzdE5hbWUiOiJBbm5hIE1hcmlhIEthdGFyenluYSBOb3dhay1XaWVsa2EtWmFixYJvY2thLUTFgnVnb3N6LU9zdHJvd3NrYS1NaWNraWV3aWN6LVBpxJlrbmEtU29iaWVza2EtS293YWxld3NrYS1KYWdpZWxsb8WEc2thLVPFgm93YWNrYS1Lcnp5xbxhbm93c2thLUtvcmRlY2thLUtvxZtjaXVzemtvd3NrYSIsInBob25lTnVtYmVycyI6W3siaWQiOiIzMDA2IiwicGhvbmVOdW1iZXIiOiIrNDgxMjM0NTY3ODYiLCJwaG9uZVR5cGUiOiJNT0JJTEUifV0sInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTIiOiJMb25nIERpc3BsYXkgTmFtZSAobGFzdCBuYW1lIGlzIGxvbmcpIiwiZGlzcGxheU5hbWUzIjoiQW5uYSBNYXJpYSBLYXRhcnp5bmEgTm93YWstV2llbGthLVphYsWCb2NrYS1ExYJ1Z29zei1Pc3Ryb3dza2EtTWlja2lld2ljei1QacSZa25hLVNvYmllc2thLUtvd2FsZXdza2EtSmFnaWVsbG/FhHNrYS1TxYJvd2Fja2EtS3J6ecW8YW5vd3NrYS1Lb3JkZWNrYS1Lb8WbY2l1c3prb3dza2EifSx7ImNvbnRhY3RJZCI6IjQzNCIsImVudGl0eVR5cGUiOiJjb250YWN0cyIsInNlYXJjaE5hbWUiOiJNYXJlayBNYXJtYXJlY2tpIiwic29ydEZpZWxkIjoiTWFybWFyZWNraU1hcmVrIiwiZmlyc3ROYW1lIjoiTWFyZWsiLCJsYXN0TmFtZSI6Ik1hcm1hcmVja2kiLCJwaG9uZU51bWJlcnMiOlt7ImlkIjoiMzA0OCIsInBob25lTnVtYmVyIjoiNTAwNTAwNTAwIiwicGhvbmVUeXBlIjoiTU9CSUxFIn0seyJpZCI6IjMwNDkiLCJwaG9uZU51bWJlciI6IjUwMDUwMDYwMCIsInBob25lVHlwZSI6IldPUksifV0sInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTIiOiJNYXJlayIsImRpc3BsYXlOYW1lMyI6Ik1hcm1hcmVja2kifSx7ImNvbnRhY3RJZCI6IjQzNSIsImVudGl0eVR5cGUiOiJjb250YWN0cyIsInNlYXJjaE5hbWUiOiJOdW1lciAobGFzdCBuYW1lIGlzIG51bWVyaWMpIDEyMzQ1Iiwic29ydEZpZWxkIjoiMTIzNDVOdW1lciAobGFzdCBuYW1lIGlzIG51bWVyaWMpIiwiZmlyc3ROYW1lIjoiTnVtZXIgKGxhc3QgbmFtZSBpcyBudW1lcmljKSIsImxhc3ROYW1lIjoiMTIzNDUiLCJwaG9uZU51bWJlcnMiOlt7ImlkIjoiMzA1NiIsInBob25lTnVtYmVyIjoiKzQ4OTAxMjM0NTY3IiwicGhvbmVUeXBlIjoiTU9CSUxFIn1dLCJzdGFycmVkIjpmYWxzZSwiZGlzcGxheU5hbWUyIjoiTnVtZXIgKGxhc3QgbmFtZSBpcyBudW1lcmljKSIsImRpc3BsYXlOYW1lMyI6IjEyMzQ1In0seyJjb250YWN0SWQiOiI0NDQiLCJlbnRpdHlUeXBlIjoiY29udGFjdHMiLCJzZWFyY2hOYW1lIjoiKzQ4MzQ1Njc4OTAyIiwic29ydEZpZWxkIjoiKzQ4MzQ1Njc4OTAyIiwicGhvbmVOdW1iZXJzIjpbeyJpZCI6IjMxMTgiLCJwaG9uZU51bWJlciI6Iis0ODM0NTY3ODkwMiIsInBob25lVHlwZSI6Ik1PQklMRSJ9LHsiaWQiOiIzMTE5IiwicGhvbmVOdW1iZXIiOiIrNDg0NDU2Nzg5MDMiLCJwaG9uZVR5cGUiOiJIT01FIn0seyJpZCI6IjMxMjAiLCJwaG9uZU51bWJlciI6Iis0ODU1NTY3ODkwNCIsInBob25lVHlwZSI6IldPUksifV0sInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTMiOiIrNDgzNDU2Nzg5MDIifSx7ImNvbnRhY3RJZCI6IjQ1NiIsImVudGl0eVR5cGUiOiJjb250YWN0cyIsInNlYXJjaE5hbWUiOiJ3b3JrQGVtYWlsLmNvbSIsInNvcnRGaWVsZCI6IndvcmtAZW1haWwuY29tIiwiZW1haWxBZGRyZXNzZXMiOlt7ImlkIjoiMzIxNiIsImVtYWlsQWRkcmVzcyI6IndvcmtAZW1haWwuY29tIiwiZW1haWxUeXBlIjoiV09SSyJ9LHsiaWQiOiIzMjE3IiwiZW1haWxBZGRyZXNzIjoib3RoZXJAZW1haWwuY29tIiwiZW1haWxUeXBlIjoiT1RIRVIifV0sInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTMiOiJ3b3JrQGVtYWlsLmNvbSJ9LHsiY29udGFjdElkIjoiNDU4IiwiZW50aXR5VHlwZSI6ImNvbnRhY3RzIiwic2VhcmNoTmFtZSI6Iklubm92YXRpdmUgVGVjaG5vbG9naWVzIChjb21wYW55KSIsInNvcnRGaWVsZCI6Iklubm92YXRpdmUgVGVjaG5vbG9naWVzIChjb21wYW55KSIsImNvbXBhbnkiOiJJbm5vdmF0aXZlIFRlY2hub2xvZ2llcyAoY29tcGFueSkiLCJzdGFycmVkIjpmYWxzZSwiZGlzcGxheU5hbWUzIjoiSW5ub3ZhdGl2ZSBUZWNobm9sb2dpZXMgKGNvbXBhbnkpIn0seyJjb250YWN0SWQiOiI0NjkiLCJlbnRpdHlUeXBlIjoiY29udGFjdHMiLCJzZWFyY2hOYW1lIjoiTWljaGFlbCBCcm93biIsInNvcnRGaWVsZCI6IkJyb3duTWljaGFlbCIsImZpcnN0TmFtZSI6Ik1pY2hhZWwiLCJsYXN0TmFtZSI6IkJyb3duIiwiYWRkcmVzcyI6eyJzdHJlZXRBZGRyZXNzIjoiU3RyZWV0IDkiLCJ6aXBDb2RlIjoiMDAtMDAzIiwidHlwZSI6IkhPTUUifSwic3RhcnJlZCI6ZmFsc2UsImRpc3BsYXlOYW1lMiI6Ik1pY2hhZWwiLCJkaXNwbGF5TmFtZTMiOiJCcm93biJ9LHsiY29udGFjdElkIjoiNDcwIiwiZW50aXR5VHlwZSI6ImNvbnRhY3RzIiwic2VhcmNoTmFtZSI6Ik1pY2hhZWwgQnJvd24iLCJzb3J0RmllbGQiOiJCcm93bk1pY2hhZWwiLCJmaXJzdE5hbWUiOiJNaWNoYWVsIiwibGFzdE5hbWUiOiJCcm93biIsImFkZHJlc3MiOnsic3RhdGUiOiJDYWxpZm9ybmlhIiwiY291bnRyeSI6IlVTQSIsInR5cGUiOiJIT01FIn0sInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTIiOiJNaWNoYWVsIiwiZGlzcGxheU5hbWUzIjoiQnJvd24ifSx7ImNvbnRhY3RJZCI6IjQ3MSIsImVudGl0eVR5cGUiOiJjb250YWN0cyIsInNlYXJjaE5hbWUiOiJzaXA6amFuLm5vd2FrQHNpcG9ubHkuY29tIiwic29ydEZpZWxkIjoic2lwOmphbi5ub3dha0BzaXBvbmx5LmNvbSIsInNpcCI6InNpcDpqYW4ubm93YWtAc2lwb25seS5jb20iLCJzdGFycmVkIjpmYWxzZSwiZGlzcGxheU5hbWUzIjoic2lwOmphbi5ub3dha0BzaXBvbmx5LmNvbSJ9LHsiY29udGFjdElkIjoiNDc4IiwiZW50aXR5VHlwZSI6ImNvbnRhY3RzIiwic2VhcmNoTmFtZSI6Iis0ODIyMzQ1Njc4OSIsInNvcnRGaWVsZCI6Iis0ODIyMzQ1Njc4OSIsInBob25lTnVtYmVycyI6W3siaWQiOiIzMzU1IiwicGhvbmVOdW1iZXIiOiIrNDgyMjM0NTY3ODkiLCJwaG9uZVR5cGUiOiJXT1JLIn1dLCJub3RlcyI6IvCfkqHwn5qoIiwic3RhcnJlZCI6ZmFsc2UsImRpc3BsYXlOYW1lMyI6Iis0ODIyMzQ1Njc4OSJ9LHsiY29udGFjdElkIjoiNDMyIiwiZW50aXR5VHlwZSI6ImNvbnRhY3RzIiwic2VhcmNoTmFtZSI6IlBsdXMgKGxhc3QgbmFtZSB3aXRoIHBsdXMpICsiLCJzb3J0RmllbGQiOiIrUGx1cyAobGFzdCBuYW1lIHdpdGggcGx1cykiLCJmaXJzdE5hbWUiOiJQbHVzIChsYXN0IG5hbWUgd2l0aCBwbHVzKSIsImxhc3ROYW1lIjoiKyIsInBob25lTnVtYmVycyI6W3siaWQiOiIzMDM0IiwicGhvbmVOdW1iZXIiOiIrNDkxMjMxNTY3ODkiLCJwaG9uZVR5cGUiOiJNT0JJTEUifV0sInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTIiOiJQbHVzIChsYXN0IG5hbWUgd2l0aCBwbHVzKSIsImRpc3BsYXlOYW1lMyI6IisifSx7ImNvbnRhY3RJZCI6IjQzOCIsImVudGl0eVR5cGUiOiJjb250YWN0cyIsInNlYXJjaE5hbWUiOiIlJSUlIChvbmx5IG1pZGRsZSBuYW1lKSIsInNvcnRGaWVsZCI6IiUlJSUgKG9ubHkgbWlkZGxlIG5hbWUpIiwibWlkZGxlTmFtZSI6IiUlJSUgKG9ubHkgbWlkZGxlIG5hbWUpIiwic3RhcnJlZCI6ZmFsc2UsImRpc3BsYXlOYW1lMyI6IiUlJSUgKG9ubHkgbWlkZGxlIG5hbWUpIn0seyJjb250YWN0SWQiOiI0NDQiLCJlbnRpdHlUeXBlIjoiY29udGFjdHMiLCJzZWFyY2hOYW1lIjoiKzQ4MzQ1Njc4OTAyIiwic29ydEZpZWxkIjoiKzQ4MzQ1Njc4OTAyIiwicGhvbmVOdW1iZXJzIjpbeyJpZCI6IjMxMTgiLCJwaG9uZU51bWJlciI6Iis0ODM0NTY3ODkwMiIsInBob25lVHlwZSI6Ik1PQklMRSJ9LHsiaWQiOiIzMTE5IiwicGhvbmVOdW1iZXIiOiIrNDg0NDU2Nzg5MDMiLCJwaG9uZVR5cGUiOiJIT01FIn0seyJpZCI6IjMxMjAiLCJwaG9uZU51bWJlciI6Iis0ODU1NTY3ODkwNCIsInBob25lVHlwZSI6IldPUksifV0sInN0YXJyZWQiOmZhbHNlLCJkaXNwbGF5TmFtZTMiOiIrNDgzNDU2Nzg5MDIifSx7ImNvbnRhY3RJZCI6IjQ3MiIsImVudGl0eVR5cGUiOiJjb250YWN0cyIsInNlYXJjaE5hbWUiOiJodHRwczovL3dlYnNpdGVvbmx5LmNvbSIsInNvcnRGaWVsZCI6Imh0dHBzOi8vd2Vic2l0ZW9ubHkuY29tIiwid2Vic2l0ZSI6Imh0dHBzOi8vd2Vic2l0ZW9ubHkuY29tIiwic3RhcnJlZCI6ZmFsc2UsImRpc3BsYXlOYW1lMyI6Imh0dHBzOi8vd2Vic2l0ZW9ubHkuY29tIn0seyJjb250YWN0SWQiOiI0NzMiLCJlbnRpdHlUeXBlIjoiY29udGFjdHMiLCJzZWFyY2hOYW1lIjoiVGhpcyBpcyBhIHRlc3Qgbm90ZS4gKG9ubHkgbm90ZXMpIiwic29ydEZpZWxkIjoiVGhpcyBpcyBhIHRlc3Qgbm90ZS4gKG9ubHkgbm90ZXMpIiwibm90ZXMiOiJUaGlzIGlzIGEgdGVzdCBub3RlLiAob25seSBub3RlcykiLCJzdGFycmVkIjpmYWxzZSwiZGlzcGxheU5hbWUzIjoiVGhpcyBpcyBhIHRlc3Qgbm90ZS4gKG9ubHkgbm90ZXMpIn1dfQ==", + }, + match: { + expected: { + transferId: 48647, + chunkNumber: 1 }, - ], + }, + }, + { + status: ResponseStatus.Ok, + body: { + transferId: 1734669809788, + chunkNumber: 1, + data: "eyJkYXRhIjpbeyJlbnRpdHlUeXBlIjoiYXVkaW9GaWxlcyIsImlkIjoiNDU3IiwiZmlsZVBhdGgiOiIvc3RvcmFnZS9lbXVsYXRlZC8wL3Rlc3QubXAzIiwiZmlsZU5hbWUiOiJ0ZXN0Lm1wMyIsImV4dGVuc2lvbiI6Im1wMyIsImZpbGVTaXplIjoxMDQ4NTc2MDAwLCJmaWxlVHlwZSI6IkFVRElPIiwibWltZVR5cGUiOiJhdWRpby9tcGVnIiwiaXNJbnRlcm5hbCI6dHJ1ZX1dfQ==", + }, + match: { + expected: { + transferId: 1734669809788, + chunkNumber: 1 + }, + }, }, - }, + ], }, } diff --git a/libs/e2e-mock/responses/src/lib/entities-configuration-responses.ts b/libs/e2e-mock/responses/src/lib/entities-configuration-responses.ts new file mode 100644 index 0000000000..18618c2645 --- /dev/null +++ b/libs/e2e-mock/responses/src/lib/entities-configuration-responses.ts @@ -0,0 +1,452 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +export const entitiesConfigurationAudioFiles = { + globalValidators: { requiredFieldsCombinations: [] }, + fields: { + id: { type: "id" }, + filePath: { type: "string", validators: [{ required: true }] }, + fileName: { type: "string", validators: [{ required: true }] }, + extension: { type: "string", validators: [{ required: true }] }, + fileSize: { type: "number", validators: [{ required: true }] }, + fileType: { type: "string", validators: [{ required: true }] }, + mimeType: { type: "string", validators: [{ required: true }] }, + isInternal: { type: "boolean" }, + entityType: { type: "string", validators: [{ required: true }] }, + }, +} + +export const entitiesConfiguration = { + globalValidators: { + requiredFieldsCombinations: [ + { + fields: ["phoneNumbers"], + countLogic: "lt", + fieldsCount: 3, + error: "A maximum of two phone numbers can be provided.", + }, + ], + }, + fields: { + contactId: { + type: "id", + }, + firstName: { + type: "string", + validators: [ + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "First name must start with printable character", + }, + ], + }, + lastName: { + type: "string", + validators: [ + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Last name must start with printable character", + }, + ], + }, + namePrefix: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Prefix must start with printable character", + }, + ], + }, + middleName: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Middle name must start with printable character", + }, + ], + }, + nameSuffix: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Suffix must start with printable character", + }, + ], + }, + phoneNumbers: { + type: "array", + items: { + type: "object", + fields: { + id: { + type: "id", + }, + phoneNumber: { + type: "string", + validators: [ + { + required: true, + }, + { + pattern: + "/^(\\+?\\d{1,3}[-.\\s]?)?(\\(?\\d{1,4}\\)?[-.\\s]?)?\\d{1,4}[-.\\s]?\\d{1,4}[-.\\s]?\\d{1,9}$/", + negatePattern: false, + error: "Invalid phone number format", + }, + ], + }, + phoneType: { + type: "string", + validators: [ + { + required: true, + }, + { + pattern: "/^(MOBILE|HOME|WORK|OTHER|UNKNOWN$/i", + negatePattern: false, + error: "Invalid phone type", + }, + ], + }, + }, + validators: [ + { + unique: true, + error: "Given phone object is not unique inside the array", + }, + { + pattern: + '/^\\{"id":"[^"]+","phoneNumber":"[^"]+","phoneType":"[^"]+"\\}$/', + negatePattern: false, + error: "Phone data is invalid", + }, + ], + }, + validators: [ + { + required: false, + }, + ], + }, + emailAddresses: { + type: "array", + items: { + type: "object", + fields: { + id: { + type: "id", + }, + emailAddress: { + type: "string", + validators: [ + { + required: true, + }, + { + pattern: "/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/", + negatePattern: false, + error: "Invalid email address", + }, + ], + }, + emailType: { + type: "string", + validators: [ + { + required: true, + }, + { + pattern: "/^(HOME|WORK|OTHER|UNKNOWN$/i", + negatePattern: false, + error: "Invalid email address type", + }, + ], + }, + }, + validators: [ + { + unique: true, + error: "Given email object is not unique inside the array", + }, + { + pattern: + '/^\\{"id":"[^"]+","emailAddress":"[^"]+","emailType":"[^"]+"\\}$/', + negatePattern: false, + error: "Email data is invalid", + }, + ], + }, + validators: [ + { + required: false, + }, + ], + }, + nickName: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Nickname must start with printable character", + }, + ], + }, + company: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Company name must start with printable character", + }, + ], + }, + department: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Department name must start with printable character", + }, + ], + }, + workTitle: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Work title must start with printable character", + }, + ], + }, + address: { + type: "array", + items: { + type: "object", + fields: { + streetAddress: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Street address must start with printable character", + }, + ], + }, + secondStreetAddress: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Street address must start with printable character", + }, + ], + }, + poBox: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "POBox must start with printable character", + }, + ], + }, + city: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "City name must start with printable character", + }, + ], + }, + state: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "State must start with printable character", + }, + ], + }, + country: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Country must start with printable character", + }, + ], + }, + zipCode: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Zip code must start with printable character", + }, + ], + }, + type: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^(HOME|WORK|OTHER|UNKNOWN$/i", + negatePattern: false, + error: "Invalid address type", + }, + ], + }, + }, + }, + validators: [ + { + required: false, + }, + ], + }, + website: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: + "/^(https?=\\/\\/)?([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}(\\/[^\\s]*)?$/i\n", + negatePattern: false, + error: "Invalid website URL", + }, + ], + }, + notes: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^$/", + negatePattern: true, + }, + ], + }, + starred: { + type: "boolean", + validators: [ + { + required: false, + }, + { + pattern: "/^TRUE|FALSE$/i", + negatePattern: false, + }, + ], + }, + entityType: { + type: "string", + validators: [ + { + required: true, + }, + ], + defaultValue: "contacts", + }, + sip: { + type: "string", + validators: [ + { + required: false, + }, + { + pattern: "/^[^\\s].*/", + negatePattern: false, + error: "Sip must start with printable character", + }, + ], + }, + searchName: { + type: "string", + }, + displayName1: { + type: "string", + }, + displayName2: { + type: "string", + }, + displayName3: { + type: "string", + }, + displayName4: { + type: "string", + }, + sortField: { + type: "string", + }, + }, +} diff --git a/libs/e2e-mock/responses/src/lib/feature-configuration-responses.ts b/libs/e2e-mock/responses/src/lib/feature-configuration-responses.ts new file mode 100644 index 0000000000..af59e2decf --- /dev/null +++ b/libs/e2e-mock/responses/src/lib/feature-configuration-responses.ts @@ -0,0 +1,122 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +export const featureConfigurationFileManager = { + main: { + screenTitle: "Manage Files", + component: "mc-file-manager-view", + config: { entityTypes: ["audioFiles"] }, + }, +} + +export const featureConfigurationContacts = { + main: { + component: "mc-contacts-view", + config: { + entityTypes: ["contacts"], + }, + // @ts-ignore + screenTitle: "Contacts", + }, +} + +export const featureConfigurationOverview = { + title: "Overview", + summary: { + show: true, + showImg: true, + imgVariant: "black", + showSerialNumber: true, + serialNumberLabel: "Serial number", + showAbout: true, + aboutTitle: "About your device", + aboutIcon: "device", + aboutSubtitle: "Device details", + aboutFields: [ + { + dataKey: "serialNumber", + type: "detail-list-text", + title: "Serial number", + }, + { + dataKey: "imei1", + type: "detail-list-text", + title: "IMEI (sim slot 1)", + }, + { + dataKey: "imei2", + type: "detail-list-text", + title: "IMEI (sim slot 2)", + }, + { + dataKey: "sar", + type: "detail-list-modal", + title: "SAR", + buttonText: "Check SAR information", + }, + ], + }, + sections: [ + { + title: "Status", + type: "tile-list", + dataKey: "status", + fields: [ + { dataKey: "battery", type: "icon-text" }, + { dataKey: "airplane-mode", type: "icon-text" }, + ], + }, + { + dataKey: "update", + type: "mc-overview-update", + title: "Android OS", + currentVersionKey: "version", + showBadge: false, + versionLabel: "Current version:", + }, + { + dataKey: "backup", + type: "mc-overview-backup", + title: "Backup", + backupFeatures: [ + { label: "Contact list", key: "CONTACT_LIST" }, + { label: "Call log", key: "CALL_LOG" }, + { label: "Messages", key: "MESSAGES" }, + { label: "Notes", key: "NOTES" }, + { label: "Calendar events", key: "CALENDAR_EVENTS" }, + { + label: "OS version & OS settings", + key: "OS_VERSION_AND_SETTINGS", + }, + { label: "App settings: Phone, Messages", key: "APP_SETTINGS" }, + ], + restoreFeatures: [ + { + label: "Contact list", + feature: "CONTACT_LIST", + keys: ["CONTACT_LIST"], + }, + { label: "Call log", feature: "CALL_LOG", keys: ["CALL_LOG"] }, + { label: "Messages", feature: "MESSAGES", keys: ["MESSAGES"] }, + { label: "Notes", feature: "NOTES", keys: ["NOTES"] }, + { + label: "Calendar events", + feature: "CALENDAR_EVENTS", + keys: ["CALENDAR_EVENTS"], + }, + { + label: "OS version & OS settings", + feature: "OS_VERSION_AND_SETTINGS", + keys: ["OS_VERSION_AND_SETTINGS"], + }, + { + label: "App settings: Phone, Messages", + feature: "APP_SETTINGS", + keys: ["APP_SETTINGS"], + }, + ], + }, + ], +} diff --git a/libs/e2e-mock/server/src/lib/mock-descriptor/mock-descriptor.test.ts b/libs/e2e-mock/server/src/lib/mock-descriptor/mock-descriptor.test.ts new file mode 100644 index 0000000000..d2c7a270a7 --- /dev/null +++ b/libs/e2e-mock/server/src/lib/mock-descriptor/mock-descriptor.test.ts @@ -0,0 +1,246 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +import { DEFAULT_RESPONSES } from "e2e-mock-responses" +import { APIEndpoints } from "device/models" +import { mockDescriptor, getMockedDevices } from "./mock-descriptor" +import { AddKompaktResponse } from "./mock-descriptor-validators" + +const path = "/dev/ttyUSB0" +const endpoint = APIEndpoints[0] +const method = "GET" + +describe("MockDescriptor", () => { + beforeEach(() => { + mockDescriptor["_devices"] = [] + mockDescriptor["_mockResponsesPerDevice"] = {} + mockDescriptor["_mockResponsesPerDeviceOnce"] = {} + }) + + describe("addKompakt", () => { + test("adds a new kompakt device", () => { + const devicePath = "/dev/ttyUSB0" + const serialNumber = "123456" + mockDescriptor.addKompakt({ path: devicePath, serialNumber }) + + const devices = getMockedDevices() + expect(devices).toHaveLength(1) + expect(devices[0]).toMatchObject({ + path, + serialNumber, + manufacturer: "Mudita", + }) + }) + + test("does not add a duplicate device", () => { + const device = { path: "/dev/ttyUSB0", serialNumber: "123456" } + mockDescriptor.addKompakt(device) + mockDescriptor.addKompakt(device) + + const devices = getMockedDevices() + expect(devices).toHaveLength(1) + }) + }) + + describe("removeDevice", () => { + test("removes a device by path", () => { + const device = { path: "/dev/ttyUSB0", serialNumber: "123456" } + mockDescriptor.addKompakt(device) + + mockDescriptor.removeDevice("/dev/ttyUSB0") + const devices = getMockedDevices() + expect(devices).toHaveLength(0) + }) + }) + + describe("addResponse and getResponse", () => { + test("adds and retrieves a response for a device", () => { + const response: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { key: "value" }, + } + mockDescriptor.addResponse(response) + + const result = mockDescriptor.getResponse(path, endpoint, method, {}) + expect(result).toEqual({ status: 200, body: { key: "value" } }) + }) + + test("adds and retrieves a response with matching data", () => { + const response: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { key: "value" }, + match: { expected: { key: "value" } }, + } + mockDescriptor.addResponse(response) + + const result = mockDescriptor.getResponse(path, endpoint, method, { + key: "value", + }) + expect(result).toEqual({ status: 200, body: { key: "value" } }) + }) + + test("adds a new response and filters out previous one without match", () => { + const firstResponse: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { key: "firstValue" }, + match: undefined, + } + mockDescriptor.addResponse(firstResponse) + + const secondResponse: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { key: "secondValue" }, + match: { expected: { key: "secondValue" } }, + } + mockDescriptor.addResponse(secondResponse) + + const result = mockDescriptor.getResponse(path, endpoint, method, { + key: "secondValue", + }) + expect(result).toEqual({ status: 200, body: { key: "secondValue" } }) + }) + + test("does not retrieve a response if match does not pass", () => { + const response: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { key: "value" }, + match: { expected: { key: "notValue" } }, + } + mockDescriptor.addResponse(response) + + const result = mockDescriptor.getResponse(path, endpoint, method, { + key: "otherValue", + }) + expect(result).toEqual(DEFAULT_RESPONSES[endpoint]?.[method]?.[0]) + }) + + test("includes the response without match if it's the last one added", () => { + const firstResponse: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { key: "firstValue" }, + match: undefined, + } + mockDescriptor.addResponse(firstResponse) + + const secondResponse: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { key: "secondValue" }, + match: undefined, + } + mockDescriptor.addResponse(secondResponse) + + const result = mockDescriptor.getResponse(path, endpoint, method, { + key: "secondValue", + }) + expect(result).toEqual({ status: 200, body: { key: "secondValue" } }) + }) + + test("returns default response if no custom response exists", () => { + const result = mockDescriptor.getResponse(path, endpoint, method, {}) + expect(result).toEqual(DEFAULT_RESPONSES[endpoint]?.[method]?.[0]) + }) + }) + + describe("ddResponseOnce and getResponse", () => { + test("adds and retrieves a one-time response with matching data", () => { + const response: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { once: true, key: "value" }, + match: { expected: { key: "value" } }, + } + mockDescriptor.addResponseOnce(response) + + const firstResult = mockDescriptor.getResponse(path, endpoint, method, { + key: "value", + }) + expect(firstResult).toEqual({ + status: 200, + body: { once: true, key: "value" }, + }) + + const secondResult = mockDescriptor.getResponse(path, endpoint, method, { + key: "value", + }) + expect(secondResult).toEqual(DEFAULT_RESPONSES[endpoint]?.[method]?.[0]) + }) + + test("does not retrieve a one-time response if match does not pass", () => { + const response: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { once: true, key: "value" }, + match: { expected: { key: "notValue" } }, + } + mockDescriptor.addResponseOnce(response) + + const result = mockDescriptor.getResponse(path, endpoint, method, { + key: "otherValue", + }) + expect(result).toEqual(DEFAULT_RESPONSES[endpoint]?.[method]?.[0]) + }) + }) + + describe("addResponseOnce", () => { + test("adds a one-time response and removes it after retrieval", () => { + const response: AddKompaktResponse = { + path, + endpoint, + method, + status: 200, + body: { once: true }, + } + mockDescriptor.addResponseOnce(response) + + const firstResult = mockDescriptor.getResponse(path, endpoint, method, {}) + expect(firstResult).toEqual({ status: 200, body: { once: true } }) + + const secondResult = mockDescriptor.getResponse( + path, + endpoint, + method, + {} + ) + expect(secondResult).toEqual(DEFAULT_RESPONSES[endpoint]?.[method]?.[0]) + }) + }) + + describe("getResponse fallback to default", () => { + test("returns default response if no per-device response exists", () => { + const result = mockDescriptor.getResponse( + "non-existing-path", + endpoint, + method, + {} + ) + expect(result).toEqual(DEFAULT_RESPONSES[endpoint]?.[method]?.[0]) + }) + }) +}) diff --git a/libs/e2e-mock/server/src/lib/mock-descriptor/mock-descriptor.ts b/libs/e2e-mock/server/src/lib/mock-descriptor/mock-descriptor.ts index 9c376ea158..4dbe5c3e18 100644 --- a/libs/e2e-mock/server/src/lib/mock-descriptor/mock-descriptor.ts +++ b/libs/e2e-mock/server/src/lib/mock-descriptor/mock-descriptor.ts @@ -3,7 +3,7 @@ * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md */ -import { findIndex, pullAt, find, merge } from "lodash" +import { find, findIndex, merge, pullAt } from "lodash" import { PortInfo } from "serialport" import { AddKompakt, @@ -11,8 +11,8 @@ import { RestoreDefaultResponses, } from "./mock-descriptor-validators" import { - ApiResponseWithConfig, ApiResponsesWithConfigArray, + ApiResponseWithConfig, DEFAULT_RESPONSES, MocksArrayResponsesMap, } from "e2e-mock-responses" @@ -66,7 +66,7 @@ class MockDescriptor { this._mockResponsesPerDevice[path]?.[endpoint]?.[method] ?? [] const filteredResponses = currentResponses.filter((item) => { - if (match?.options?.id === item.match?.options?.id) { + if (item.match === undefined) { return false } return true @@ -120,7 +120,7 @@ class MockDescriptor { this._mockResponsesPerDevice[path]?.[endpoint]?.[method] ?? [] const filteredResponses = currentResponses.filter((item) => { - if (match?.options?.id === item.match?.options?.id) { + if (item.match === undefined) { return false } return true @@ -205,9 +205,11 @@ class MockDescriptor { method, responses: perDeviceOnceResponses, }) - return merge( - foundResponse.response, - this.fillEndpointSpecificFields(endpoint, method, body) + return this.mapResponseWithoutMatch( + merge( + foundResponse.response, + this.fillEndpointSpecificFields(endpoint, method, body) + ) ) } } @@ -241,15 +243,32 @@ class MockDescriptor { const foundResponse = this.findResponse(perDeviceResponses, body) if (foundResponse) { - return merge( - foundResponse.response, - this.fillEndpointSpecificFields(endpoint, method, body) + return this.mapResponseWithoutMatch( + merge( + foundResponse.response, + this.fillEndpointSpecificFields(endpoint, method, body) + ) ) } } return undefined } + private getDefaultResponse( + endpoint: APIEndpointType, + method: APIMethodsType, + body: Record | undefined + ): ApiResponse | undefined { + const perDeviceResponses = DEFAULT_RESPONSES[endpoint]?.[method] + if (perDeviceResponses !== undefined) { + const foundResponse = this.findResponse(perDeviceResponses, body) + if (foundResponse) { + return this.mapResponseWithoutMatch(foundResponse.response) + } + } + return undefined + } + public getResponse( path: string, endpoint: APIEndpointType, @@ -271,11 +290,17 @@ class MockDescriptor { return response } - const defaultResponse: ApiResponse | undefined = - DEFAULT_RESPONSES[endpoint]?.[method] + const defaultResponse = this.getDefaultResponse(endpoint, method, body) return defaultResponse } + + private mapResponseWithoutMatch({ + match, + ...response + }: ApiResponseWithConfig): ApiResponse { + return response + } } export const mockDescriptor = new MockDescriptor() diff --git a/libs/e2e-test-ids/src/e2e-test-ids.ts b/libs/e2e-test-ids/src/e2e-test-ids.ts index fd55e24944..f9948c5b9d 100644 --- a/libs/e2e-test-ids/src/e2e-test-ids.ts +++ b/libs/e2e-test-ids/src/e2e-test-ids.ts @@ -14,6 +14,32 @@ export enum InteractiveTextInputTestIds { ErrorText = "interactive-text-input-error-text", } +export enum TypographyTestIds { + H1 = "ui-typography-h1", + H2 = "ui-typography-h2", + H3 = "ui-typography-h3", + H4 = "ui-typography-h4", + H5 = "ui-typography-h5", + P1 = "ui-typography-p1", + P2 = "ui-typography-p2", + P3 = "ui-typography-p3", + P4 = "ui-typography-p4", + P5 = "ui-typography-p5", +} + +export enum CheckboxTestIds { + Checkbox = "ui-checkbox", +} + +export enum TableTestIds { + Table = "ui-table", + TableRow = "ui-table-row", + TableHeaderRow = "ui-table-header-row", + TablePlaceholderRow = "ui-table-place-holder-row", + TableCell = "ui-table-cell", + TableHeaderCell = "ui-table-header-cell", +} + export enum PredefinedBackupPasswordTestIds { Title = "predefined-backup-password-title", Description = "predefined-backup-password-description", diff --git a/libs/generic-view/ui/src/lib/interactive/form/input/checkbox-input.tsx b/libs/generic-view/ui/src/lib/interactive/form/input/checkbox-input.tsx index 72b1df1f3a..f8e7c03849 100644 --- a/libs/generic-view/ui/src/lib/interactive/form/input/checkbox-input.tsx +++ b/libs/generic-view/ui/src/lib/interactive/form/input/checkbox-input.tsx @@ -4,10 +4,11 @@ */ import React, { useCallback, useEffect, useId, useMemo, useRef } from "react" -import { APIFC, IconType, useViewFormContext } from "generic-view/utils" import styled from "styled-components" -import { Icon } from "../../../icon/icon" +import { CheckboxTestIds } from "e2e-test-ids" +import { APIFC, IconType, useViewFormContext } from "generic-view/utils" import { FormCheckboxInputConfig } from "generic-view/models" +import { Icon } from "../../../icon/icon" interface Config extends FormCheckboxInputConfig { onToggle?: (checked: boolean) => void @@ -110,6 +111,7 @@ export const CheckboxInput: APIFC = ({ > = ({ config, data, ...props }) => { + const deviceConfiguration = useSelector(selectActiveDeviceConfiguration) + const [availableUpdateName, setAvailableUpdateName] = useState() + const updateAvailable = availableUpdateName !== undefined + const { osVersionTimestamp, otaApiKey } = + deviceConfiguration?.apiConfig?.otaApiConfig || {} + + useEffect(() => { + void (async () => { + if (!serverUrl) { + return + } + try { + const devTokenParam = devToken ? `&devToken=${devToken}` : "" + const { data } = await axios.get<{ + available: boolean + versionName?: string + }>( + `${serverUrl}/kompakt-os-update-availability?imei=${otaApiKey}&version=${osVersionTimestamp}${devTokenParam}` + ) + if (data && data.available && data.versionName) { + setAvailableUpdateName(data.versionName) + } + } catch (error) { + logger.error( + `Error while checking Kompakt OS update availability for ${otaApiKey}, version ${osVersionTimestamp}.`, + error + ) + } + })() + }, [osVersionTimestamp, otaApiKey]) + return ( {config?.versionLabel && ( @@ -41,19 +79,17 @@ export const OverviewOsVersion: APIFC< {data?.text && ( {data?.text} )} - {data?.update?.available && ( + {updateAvailable && ( {intl.formatMessage(messages.updateTag, { - version: data?.update.updateText, + version: availableUpdateName, })} )} - {config?.showBadge && !data?.update?.available && ( - {data?.badgeText} - )} - {data?.update?.available && ( + {config?.showBadge && !updateAvailable && {data?.badgeText}} + {updateAvailable && ( - {data.update.actionLabel ?? + {data?.update?.actionLabel ?? intl.formatMessage(messages.updateActionLabel)} )} diff --git a/libs/generic-view/ui/src/lib/table/table-cell.tsx b/libs/generic-view/ui/src/lib/table/table-cell.tsx index 6d2ac8d7e7..466f28ab71 100644 --- a/libs/generic-view/ui/src/lib/table/table-cell.tsx +++ b/libs/generic-view/ui/src/lib/table/table-cell.tsx @@ -7,6 +7,7 @@ import React, { useMemo } from "react" import { APIFC } from "generic-view/utils" import { TableCellConfig } from "generic-view/models" import styled from "styled-components" +import { TableTestIds } from "e2e-test-ids" export const TableCell: APIFC = ({ children, @@ -20,6 +21,7 @@ export const TableCell: APIFC = ({ () => { return ( export const TableHeaderCell: APIFC = (props) => ( - + ) diff --git a/libs/generic-view/ui/src/lib/table/table.tsx b/libs/generic-view/ui/src/lib/table/table.tsx index 61b994c6af..21e37d917a 100644 --- a/libs/generic-view/ui/src/lib/table/table.tsx +++ b/libs/generic-view/ui/src/lib/table/table.tsx @@ -15,6 +15,7 @@ import React, { } from "react" import styled from "styled-components" import { difference, intersection } from "lodash" +import { TableTestIds } from "e2e-test-ids" import { APIFC, useViewFormContext } from "generic-view/utils" import { TableConfig, @@ -139,8 +140,8 @@ export const Table: APIFC & { (id: string) => { const isActive = activeRowId === id return ( - - + +
@@ -188,7 +189,7 @@ export const Table: APIFC & { const isActive = activeRowId === id return ( - + {renderChildren(id)} ) @@ -205,9 +206,9 @@ export const Table: APIFC & { return useMemo( () => ( - + - {renderHeaderChildren()} + {renderHeaderChildren()} {data?.map((id, index) => renderRow(id, index))} diff --git a/libs/generic-view/ui/src/lib/texts/headers.tsx b/libs/generic-view/ui/src/lib/texts/headers.tsx index aeb5b5d254..99a1670ab1 100644 --- a/libs/generic-view/ui/src/lib/texts/headers.tsx +++ b/libs/generic-view/ui/src/lib/texts/headers.tsx @@ -4,10 +4,11 @@ */ import React from "react" -import { APIFC } from "generic-view/utils" +import { isEmpty } from "lodash" import styled, { css } from "styled-components" +import { TypographyTestIds } from "e2e-test-ids" +import { APIFC } from "generic-view/utils" import { HeaderConfig, UnboldValidator } from "generic-view/models" -import { isEmpty } from "lodash" import { CommonTextProps, commonTextStyles } from "./common-text-styles" interface HeaderProps extends CommonTextProps { @@ -37,6 +38,7 @@ export const Header3: APIFC = ({ }) => { return (

= ({ }) => { return (

= ({ }) => { return (

= ({ return ( {isEmpty(children) ? transformedText : children} @@ -80,11 +82,12 @@ export const Paragraph2: APIFC = ({ return ( {isEmpty(children) ? transformedText : children} @@ -120,11 +123,12 @@ export const Paragraph3: APIFC = ({ return ( {isEmpty(children) ? transformedText : children} @@ -160,11 +164,12 @@ export const Paragraph4: APIFC = ({ return ( {isEmpty(children) ? transformedText : children} @@ -200,11 +205,12 @@ export const Paragraph5: APIFC = ({ return ( {isEmpty(children) ? transformedText : children} diff --git a/scripts/notarize.js b/scripts/notarize.js index 4019115f9d..fde3bf8e10 100644 --- a/scripts/notarize.js +++ b/scripts/notarize.js @@ -10,10 +10,7 @@ require("dotenv").config({ module.exports = async function (context) { const { electronPlatformName, appOutDir } = context - if ( - electronPlatformName !== "darwin" || - process.env.SKIP_MAC_NOTARIZE_ENABLED === "1" - ) { + if (electronPlatformName !== "darwin") { return }