diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml new file mode 100644 index 00000000..8b9dd472 --- /dev/null +++ b/.github/workflows/e2e.yaml @@ -0,0 +1,235 @@ +name: e2e + +on: + push: + branches: + - master + - citest + +env: + APP_NAME: memories + PHP_CLI_SERVER_WORKERS: 8 + +jobs: + vue: + runs-on: ubuntu-latest + steps: + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - name: Checkout the app + uses: actions/checkout@v3 + + - name: Build vue app + run: | + make dev-setup + make build-js-production + zip -r vue.zip js/ + + - uses: actions/upload-artifact@v2 + with: + name: vue.zip + path: vue.zip + + mysql: + runs-on: ubuntu-latest + needs: vue + + strategy: + # do not stop on another job's failure + fail-fast: false + matrix: + php-versions: ['7.4', '8.1'] + server-versions: ['v24.0.4'] + + services: + mysql: + image: mariadb:10.5 + ports: + - 4444:3306/tcp + env: + MYSQL_ROOT_PASSWORD: rootpassword + options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5 + + steps: + - name: Checkout server + uses: actions/checkout@v3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout the app + uses: actions/checkout@v3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - uses: actions/download-artifact@v2 + with: + name: vue.zip + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit + extensions: mbstring, iconv, fileinfo, intl, mysql, pdo_mysql + coverage: none + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + php occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password + git clone --depth 1 --branch ${{ matrix.server-versions }} https://github.com/nextcloud/viewer apps/viewer + + - name: Run tests + run: | + ./apps/memories/ci-test.sh + + - uses: actions/upload-artifact@v3 + if: always() + with: + name: report-mysql-${{ matrix.php-versions }}-${{ matrix.server-versions }} + path: apps/${{ env.APP_NAME }}/playwright-report + + + pgsql: + runs-on: ubuntu-latest + needs: vue + + strategy: + # do not stop on another job's failure + fail-fast: false + matrix: + php-versions: ['7.4'] + server-versions: ['v24.0.4'] + + services: + mysql: + image: postgres + ports: + - 4444:5432/tcp + env: + POSTGRES_PASSWORD: rootpassword + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Checkout server + uses: actions/checkout@v3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout the app + uses: actions/checkout@v3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - uses: actions/download-artifact@v2 + with: + name: vue.zip + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit + extensions: mbstring, iconv, fileinfo, intl, mysql, pdo_mysql + coverage: none + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + php occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=postgres --database-pass=rootpassword --admin-user admin --admin-pass password + git clone --depth 1 --branch ${{ matrix.server-versions }} https://github.com/nextcloud/viewer apps/viewer + + - name: Run tests + run: | + ./apps/memories/ci-test.sh + + - uses: actions/upload-artifact@v3 + if: always() + with: + name: report-pgsql-${{ matrix.php-versions }}-${{ matrix.server-versions }} + path: apps/${{ env.APP_NAME }}/playwright-report + + sqlite: + runs-on: ubuntu-latest + needs: vue + + strategy: + # do not stop on another job's failure + fail-fast: false + matrix: + php-versions: ['7.4'] + server-versions: ['v24.0.4'] + + steps: + - name: Checkout server + uses: actions/checkout@v3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout the app + uses: actions/checkout@v3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - uses: actions/download-artifact@v2 + with: + name: vue.zip + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit + extensions: mbstring, iconv, fileinfo, intl, mysql, pdo_mysql + coverage: none + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + php occ maintenance:install --verbose --admin-user admin --admin-pass password + git clone --depth 1 --branch ${{ matrix.server-versions }} https://github.com/nextcloud/viewer apps/viewer + + - name: Run tests + run: | + ./apps/memories/ci-test.sh + + - uses: actions/upload-artifact@v3 + if: always() + with: + name: report-sqlite-${{ matrix.php-versions }}-${{ matrix.server-versions }} + path: apps/${{ env.APP_NAME }}/playwright-report + diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0a70da58..60946f63 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,4 +1,4 @@ -name: Release +name: release on: release: diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 5547cf4d..00000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,74 +0,0 @@ -name: Tests - -env: - APP_NAME: memories - -jobs: - phpunit-mysql: - runs-on: ubuntu-latest - - strategy: - # do not stop on another job's failure - fail-fast: false - matrix: - php-versions: ['7.4', '8.1'] - server-versions: ['v24.0.4'] - - services: - mysql: - image: mariadb:10.5 - ports: - - 4444:3306/tcp - env: - MYSQL_ROOT_PASSWORD: rootpassword - options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5 - - steps: - - name: Enable ONLY_FULL_GROUP_BY MySQL option - run: | - echo "SET GLOBAL sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword - echo "SELECT @@sql_mode;" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword - - - name: Checkout server - uses: actions/checkout@v3 - with: - submodules: true - repository: nextcloud/server - ref: ${{ matrix.server-versions }} - - - name: Checkout the app - uses: actions/checkout@v3 - with: - path: apps/${{ env.APP_NAME }} - - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: 18.x - - - name: Build Vue - run: | - working-directory: apps/${{ env.APP_NAME }} - make dev-setup - make build-js-production - - - name: Set up php ${{ matrix.php-versions }} - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - tools: phpunit - extensions: mbstring, iconv, fileinfo, intl, mysql, pdo_mysql - coverage: none - - - name: Set up PHPUnit - working-directory: apps/${{ env.APP_NAME }} - run: composer i - - - name: Set up Nextcloud - env: - DB_PORT: 4444 - run: | - mkdir data - ./occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password - ./occ app:enable --force ${{ env.APP_NAME }} - php -S localhost:8080 & diff --git a/ci-test.sh b/ci-test.sh new file mode 100755 index 00000000..f65ba2ab --- /dev/null +++ b/ci-test.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Build vue +cd apps/memories +npm i +cp ../../vue.zip . +unzip vue.zip +cd ../.. + +# Speed up loads +php occ app:disable comments +php occ app:disable contactsinteraction: +php occ app:disable dashboard +php occ app:disable weather_status +php occ app:disable user_status +php occ app:disable updatenotification +php occ app:disable systemtags +php occ app:disable files_sharing + +# Enable apps +php occ app:enable --force viewer +php occ app:enable --force memories + +set -e + +# Set debug mode and start dev server +php occ config:system:set --type bool --value true debug +php -S localhost:8080 & + +# Get test photo files +cd data/admin/files +wget https://github.com/pulsejet/memories-test/raw/main/Files.zip +unzip Files.zip +cd ../../.. + +# Index +sudo apt-get install libimage-exiftool-perl -y +php occ files:scan --all +php occ memories:index + +# Run e2e tests +cd apps/memories +sudo npx playwright install-deps chromium +npm run e2e +cd ../.. diff --git a/e2e/folders.spec.ts b/e2e/folders.spec.ts index 38a347d2..c8171ba5 100644 --- a/e2e/folders.spec.ts +++ b/e2e/folders.spec.ts @@ -5,12 +5,12 @@ test.beforeEach(login('/folders')); test.describe('Open', () => { test('Look for Folders', async ({ page }) => { - expect(await page.locator('.big-icon > .icon-folder').count(), 'Number of folders').toBeGreaterThan(3); + expect(await page.locator('.big-icon > .icon-folder').count(), 'Number of folders').toBe(2); }); test('Open folder', async ({ page }) => { await page.locator('text=Local').click(); - await expect(page).toHaveURL(/http:\/\/localhost:8080\/apps\/memories\/folders\/\.*/); - await page.waitForSelector('img[src^="/core/preview"]'); + await expect(page).toHaveURL(/\/apps\/memories\/folders\/[0-9]*/); + await page.waitForSelector('img[src*="core/preview"]'); }); }); \ No newline at end of file diff --git a/e2e/login.ts b/e2e/login.ts index d850b3ac..952447dc 100644 --- a/e2e/login.ts +++ b/e2e/login.ts @@ -3,14 +3,14 @@ import { expect, PlaywrightTestArgs } from '@playwright/test'; export function login(route: string) { return async ({ page }: PlaywrightTestArgs) => { await page.setViewportSize({ width: 800, height: 600 }) - await page.goto('http://localhost:8080/apps/memories' + route) + await page.goto('http://localhost:8080/index.php/apps/memories' + route) await page.locator('[placeholder="Username or email"]').click(); await page.locator('[placeholder="Username or email"]').fill('admin'); await page.locator('[placeholder="Username or email"]').press('Tab'); - await page.locator('[placeholder="Password"]').fill('admin'); + await page.locator('[placeholder="Password"]').fill('password'); await page.locator('input:has-text("Log in")').click(); - await expect(page).toHaveURL('http://localhost:8080/apps/memories' + route); - await page.waitForSelector('img[src^="/core/preview"]'); + await expect(page).toHaveURL('http://localhost:8080/index.php/apps/memories' + route); + await page.waitForSelector('img[src*="core/preview"]'); } } \ No newline at end of file diff --git a/e2e/timeline.spec.ts b/e2e/timeline.spec.ts index 05b47db1..925d645e 100644 --- a/e2e/timeline.spec.ts +++ b/e2e/timeline.spec.ts @@ -5,7 +5,7 @@ test.beforeEach(login('/')); test.describe('Open', () => { test('Look for Images', async ({ page }) => { - expect(await page.locator('img[src^="/core/preview"]').count(), 'Number of previews').toBeGreaterThan(4); + expect(await page.locator('img[src*="core/preview"]').count(), 'Number of previews').toBeGreaterThan(4); await page.waitForTimeout(1000); }); @@ -16,8 +16,8 @@ test.describe('Open', () => { }); test('Select two images and delete', async ({ page }) => { - const i1 = "div:nth-child(3) > .photo-row > div:nth-child(2) > .p-outer"; - const i2 = "div:nth-child(3) > .photo-row > div:nth-child(3) > .p-outer"; + const i1 = "div:nth-child(2) > .photo-row > div:nth-child(1) > .p-outer"; + const i2 = "div:nth-child(2) > .photo-row > div:nth-child(2) > .p-outer"; const src1 = await page.locator(`${i1} > .img-outer > img`).first().getAttribute('src'); const src2 = await page.locator(`${i2} > .img-outer > img`).first().getAttribute('src'); @@ -36,7 +36,7 @@ test.describe('Open', () => { // refresh page await page.reload(); - await page.waitForSelector('img[src^="/core/preview"]'); + await page.waitForSelector('img[src*="core/preview"]'); expect(await page.locator(`img[src="${src1}"]`).count()).toBe(0); expect(await page.locator(`img[src="${src2}"]`).count()).toBe(0); }); diff --git a/package.json b/package.json index 15cfd626..258f7748 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "build": "NODE_ENV=production webpack --progress --config webpack.js", "dev": "NODE_ENV=development webpack --progress --config webpack.js", "watch": "NODE_ENV=development webpack --progress --watch --config webpack.js", + "e2e": "playwright test", "lint": "eslint --ext .js,.vue src", "lint:fix": "eslint --ext .js,.vue src --fix", "stylelint": "stylelint src", diff --git a/playwright.config.ts b/playwright.config.ts index 8fe811c8..b0049b57 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -13,33 +13,33 @@ import { devices } from '@playwright/test'; const config: PlaywrightTestConfig = { testDir: './e2e', /* Maximum time one test can run for. */ - timeout: 30 * 1000, + timeout: 600 * 1000, expect: { /** * Maximum time expect() should wait for the condition to be met. * For example in `await expect(locator).toHaveText();` */ - timeout: 5000 + timeout: 30000 }, /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, + retries: process.env.CI ? 0 : 0, + reporter: 'html', /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, + actionTimeout: 30000, /* Base URL to use in actions like `await page.goto('/')`. */ // baseURL: 'http://localhost:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', + screenshot: 'on', }, /* Configure projects for major browsers */