Skip to content

Commit 184b978

Browse files
authored
Merge pull request #11046 from nextcloud/add/e2e-test
test(e2e): add test for basic functionality of mail app
2 parents 5a057c5 + b37dabc commit 184b978

File tree

7 files changed

+264
-1
lines changed

7 files changed

+264
-1
lines changed

.github/workflows/test.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,95 @@ jobs:
227227
env:
228228
CI: true
229229

230+
matrix:
231+
runs-on: ubuntu-latest-low
232+
outputs:
233+
matrix: ${{ steps.versions.outputs.sparse-matrix }}
234+
steps:
235+
- name: Checkout app
236+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
237+
- name: Get version matrix
238+
id: versions
239+
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
240+
with:
241+
matrix: '{"node-versions": ["20"]}'
242+
243+
frontend-e2e-tests:
244+
runs-on: ubuntu-latest
245+
name: Front-end E2E tests
246+
needs: matrix
247+
strategy:
248+
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
249+
steps:
250+
- name: Set up Nextcloud env
251+
uses: ChristophWurst/setup-nextcloud@fc0790385c175d97e88a7cb0933490de6e990374 # v0.3.2
252+
with:
253+
nextcloud-version: ${{ matrix.server-versions }}
254+
php-version: ${{ matrix.php-versions }}
255+
node-version: ${{ matrix.node-versions }}
256+
install: true
257+
- name: Configure Nextcloud for testing
258+
run: |
259+
php -f nextcloud/occ config:system:set debug --type=bool --value=true
260+
php -f nextcloud/occ config:system:set overwriteprotocol --value=https
261+
php -f nextcloud/occ config:system:set overwritehost --value=localhost
262+
php -f nextcloud/occ config:system:set overwrite.cli.url --value=https://localhost
263+
php -f nextcloud/occ config:system:set app.mail.debug --type=bool --value=true
264+
php -f nextcloud/occ config:system:set app.mail.verify-tls-peer --type=bool --value=false
265+
- name: Check out the app
266+
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
267+
with:
268+
path: nextcloud/apps/mail
269+
- name: Install php dependencies
270+
working-directory: nextcloud/apps/mail
271+
run: composer install
272+
- name: Install the app
273+
run: php -f nextcloud/occ app:enable mail
274+
- name: Set up node ${{ matrix.node-version }}
275+
uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3
276+
with:
277+
node-version: ${{ matrix.node-versions }}
278+
- name: Install npm dependencies
279+
working-directory: nextcloud/apps/mail
280+
run: npm ci
281+
- name: Build frontend
282+
working-directory: nextcloud/apps/mail
283+
run: npm run build
284+
- name: Install stunnel (tiny https proxy)
285+
run: sudo apt-get install -y stunnel
286+
- name: Start php server and https proxy
287+
working-directory: nextcloud
288+
run: |
289+
openssl req -new -x509 -days 365 -nodes -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=localhost" -out stunnel.pem -keyout stunnel.pem
290+
php -S 127.0.0.1:8080 &
291+
sudo stunnel3 -p stunnel.pem -d 443 -r 8080
292+
- name: Test https access
293+
run: curl --insecure -Li https://localhost
294+
- name: Install Playwright browsers
295+
working-directory: nextcloud/apps/mail
296+
run: npx playwright install --with-deps chromium
297+
- name: Run Playwright tests
298+
working-directory: nextcloud/apps/mail
299+
run: DEBUG=pw:api npx playwright test
300+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
301+
if: always()
302+
with:
303+
name: playwright-report-${{ github.event.number }}-nc${{ matrix.server-versions }}-php${{ matrix.php-versions }}-node${{ matrix.node-versions }}
304+
path: nextcloud/apps/mail/playwright-report/
305+
retention-days: 14
306+
- name: Print server logs
307+
if: always()
308+
run: cat nextcloud/data/nextcloud.log*
309+
env:
310+
CI: true
311+
230312
summary:
231313
runs-on: ubuntu-latest-low
232314
needs:
233315
- unit-tests
234316
- integration-tests
235317
- frontend-unit-test
318+
- frontend-e2e-tests
236319

237320
if: always()
238321

@@ -245,3 +328,5 @@ jobs:
245328
run: if ${{ needs.integration-tests.result != 'success' && needs.integration-tests.result != 'skipped' }}; then exit 1; fi
246329
- name: Frontend unit test status
247330
run: if ${{ needs.frontend-unit-test.result != 'success' && needs.frontend-unit-test.result != 'skipped' }}; then exit 1; fi
331+
- name: Frontend E2E test status
332+
run: if ${{ needs.frontend-e2e-tests.result != 'success' && needs.frontend-e2e-tests.result != 'skipped' }}; then exit 1; fi

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,8 @@ tests/.phpunit.result.cache
4545

4646
# PhpStorm
4747
.idea
48+
49+
# Playwright
50+
/playwright
51+
/playwright-report
52+
/test-results

package-lock.json

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
"lint": "eslint --ext .js,.vue --ignore-pattern tests src",
1313
"lint:fix": "eslint --ext .js,.vue --ignore-pattern tests src --fix",
1414
"test:unit": "jest src/tests/unit",
15-
"test:unit:watch": "jest --watch src/tests/unit"
15+
"test:unit:watch": "jest --watch src/tests/unit",
16+
"test:e2e": "playwright test",
17+
"test:e2e:ui": "playwright test --ui"
1618
},
1719
"dependencies": {
1820
"@ckeditor/ckeditor5-alignment": "44.3.0",
@@ -107,6 +109,7 @@
107109
"@nextcloud/browserslist-config": "^3.0.1",
108110
"@nextcloud/eslint-config": "^8.4.2",
109111
"@nextcloud/eslint-plugin": "^2.2.1",
112+
"@playwright/test": "^1.52.0",
110113
"@types/jest": "^29.5.14",
111114
"@vue/test-utils": "^1.3.6",
112115
"@vue/vue2-jest": "^29.2.6",

playwright.config.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
const { defineConfig, devices } = require('@playwright/test')
7+
const path = require('path')
8+
9+
/**
10+
* @see https://playwright.dev/docs/test-configuration
11+
*/
12+
export default defineConfig({
13+
testDir: './src/tests/e2e',
14+
fullyParallel: false,
15+
forbidOnly: !!process.env.CI,
16+
retries: process.env.CI ? 2 : 0,
17+
workers: 1,
18+
reporter: [
19+
['list'],
20+
['html'],
21+
],
22+
use: {
23+
baseURL: 'https://localhost',
24+
trace: 'on-first-retry',
25+
},
26+
projects: [
27+
{
28+
name: 'chromium',
29+
testMatch: '**/*.spec.js',
30+
use: {
31+
...devices['Desktop Chrome'],
32+
ignoreHTTPSErrors: true,
33+
},
34+
},
35+
],
36+
})

src/tests/e2e/login.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
/**
7+
* Log in as the admin user.
8+
* This method is best used in a beforeEach hook.
9+
*
10+
* @param {import("@playwright/test").Page} page The page object to use
11+
* @return {Promise<void>}
12+
*/
13+
export async function login(page) {
14+
await page.goto('./index.php/login')
15+
await page.locator('#user').fill('admin')
16+
await page.locator('#password').fill('admin')
17+
await page.locator('#password').press('Enter')
18+
19+
// Wait for login to finish
20+
await page.waitForURL('**/apps/**')
21+
}

src/tests/e2e/mail-e2e.spec.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { test, expect } from '@playwright/test'
7+
import { login } from './login.js'
8+
9+
test.beforeEach(async ({ page }) => {
10+
await login(page)
11+
})
12+
13+
test('render setup page', async ({ page }) => {
14+
await page.goto('./index.php/apps/mail')
15+
16+
await expect(page.getByText('Connect your mail account')).toBeVisible();
17+
await expect(page.locator('#account-form')).toBeVisible();
18+
})
19+
20+
// we might need these in the future
21+
22+
/*
23+
test('open Mail app and load inbox', async ({ page }) => {
24+
await page.goto('./index.php/apps/mail')
25+
26+
// Assert that the mail interface is rendered
27+
await expect(page.getByRole('complementary', { name: 'New message' }).first()).toBeVisible()
28+
await expect(page.getByRole('link', { name: 'Priority inbox' })).toBeVisible()
29+
await expect(page.getByRole('link', { name: 'All inboxes' })).toBeVisible()
30+
})
31+
32+
test('compose and send an email', async ({ page }) => {
33+
await page.goto('./index.php/apps/mail')
34+
35+
// Open compose modal
36+
await page.getByRole('complementary', { name: 'New message' }).first().click()
37+
38+
// Fill in email fields
39+
await page.getByRole('combobox', { name: 'Select recipient' }).fill('test@example.com')
40+
await page.getByRole('textbox', { name: 'Subject' }).fill('Test Subject')
41+
await page.getByRole('textbox', { name: 'Rich Text Editor' }).fill('This is a test message.')
42+
43+
// Click send
44+
await page.getByRole('button', { name: 'Send' }).click()
45+
46+
// Assert that a confirmation or notification appears
47+
await expect(page.getByText('Message sent')).toBeVisible()
48+
})
49+
*/

0 commit comments

Comments
 (0)