forgejo/tests/e2e/user-settings.test.e2e.ts
Ryan Lerch 626ff29545 feat: Add support for administrators to set email visibility on user accounts (#9668)
feat: Add support for administrators to set email visibility on user accounts
This feature allows administrators to control user email privacy settings
through both the API and web interface.

**note: This was originally part of #9594 but is now split out into it's own PR**

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9668): <!--number 9668 --><!--line 0 --><!--description QWRkIHN1cHBvcnQgZm9yIGFkbWluaXN0cmF0b3JzIHRvIHNldCBlbWFpbCB2aXNpYmlsaXR5IG9uIHVzZXIgYWNjb3VudHM=-->Add support for administrators to set email visibility on user accounts<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9668
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Ryan Lerch <rlerch@redhat.com>
Co-committed-by: Ryan Lerch <rlerch@redhat.com>
2025-10-15 03:21:15 +02:00

147 lines
6.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @watch start
// templates/user/settings/**.tmpl
// web_src/css/{form,user}.css
// @watch end
import {expect} from '@playwright/test';
import {test, login_user, login} from './utils_e2e.ts';
import {screenshot} from './shared/screenshots.ts';
import {validate_form} from './shared/forms.ts';
test.beforeAll(async ({browser}, workerInfo) => {
await login_user(browser, workerInfo, 'user2');
});
test('User: Profile settings', async ({browser}, workerInfo) => {
const page = await login({browser}, workerInfo);
await page.goto('/user/settings');
await page.getByLabel('Full name').fill('SecondUser');
const pronounsInput = page.locator('input[list="pronouns"]');
await expect(pronounsInput).toHaveAttribute('placeholder', 'Unspecified');
await pronounsInput.click();
const pronounsList = page.locator('datalist#pronouns');
const pronounsOptions = pronounsList.locator('option');
const pronounsValues = await pronounsOptions.evaluateAll((opts) => opts.map((opt: HTMLOptionElement) => opt.value));
expect(pronounsValues).toEqual(['he/him', 'she/her', 'they/them', 'it/its', 'any pronouns']);
await pronounsInput.fill('she/her');
await page.getByPlaceholder('Tell others a little bit').fill('I am a playwright test running for several seconds.');
await page.getByPlaceholder('Tell others a little bit').press('Tab');
await page.getByLabel('Website').fill('https://forgejo.org');
await page.getByPlaceholder('Share your approximate').fill('on a computer chip');
await page.getByLabel('User visibility').click();
await page.getByLabel('Visible only to signed-in').click();
await page.getByLabel('Hide email address Email address will').uncheck();
await page.getByLabel('Hide activity from profile').check();
await validate_form({page}, 'fieldset');
await screenshot(page);
await page.getByRole('button', {name: 'Update profile'}).click();
await expect(page.getByText('Your profile has been updated.')).toBeVisible();
await page.getByRole('link', {name: 'public activity'}).click();
await expect(page.getByText('Your activity is only visible')).toBeVisible();
await screenshot(page);
await page.goto('/user2');
await expect(page.getByText('SecondUser')).toBeVisible();
await expect(page.getByText('on a computer chip')).toBeVisible();
await expect(page.locator('li').filter({hasText: 'user2@example.com'})).toBeVisible();
await expect(page.locator('li').filter({hasText: 'https://forgejo.org'})).toBeVisible();
await expect(page.getByText('I am a playwright test')).toBeVisible();
await screenshot(page);
await page.goto('/user/settings');
await page.locator('input[list="pronouns"]').fill('rob/ot');
await page.getByLabel('User visibility').click();
await page.getByLabel('Visible to everyone').click();
await page.getByLabel('Hide email address Email address will').check();
await page.getByLabel('Hide activity from profile').uncheck();
await expect(page.getByText('Your profile has been updated.')).toBeHidden();
await validate_form({page}, 'fieldset');
await screenshot(page);
await page.getByRole('button', {name: 'Update profile'}).click();
await expect(page.getByText('Your profile has been updated.')).toBeVisible();
await page.goto('/user2');
await expect(page.getByText('SecondUser')).toBeVisible();
await expect(page.locator('li').filter({hasText: 'user2@example.com'})).toBeHidden();
await page.goto('/user2?tab=activity');
await expect(page.getByText('Your activity is visible to everyone')).toBeVisible();
});
test('User: Storage overview', async ({browser}, workerInfo) => {
const page = await login({browser}, workerInfo);
await page.goto('/user/settings/storage_overview');
await page.waitForLoadState();
await page.getByLabel('Git LFS 8 KiB').nth(1).hover({position: {x: 250, y: 2}});
await expect(page.getByText('Git LFS 8 KiB')).toBeVisible();
// Show/hide legend by clicking on the bar
await expect(page.locator('.stats ul').nth(1)).toBeHidden();
await expect(page.getByText('Git LFS 8 KiB').nth(1)).toBeHidden();
await page.locator('.stats summary').nth(1).click();
await expect(page.locator('.stats ul').nth(1)).toBeVisible();
await expect(page.getByText('Git LFS 8 KiB').nth(1)).toBeVisible();
await screenshot(page);
await page.locator('.stats summary').nth(1).click();
await expect(page.locator('.stats ul').nth(1)).toBeHidden();
await expect(page.getByText('Git LFS 8 KiB').nth(1)).toBeHidden();
await screenshot(page);
});
test('User: Canceling adding SSH key clears inputs', async ({browser}, workerInfo) => {
const page = await login({browser}, workerInfo);
await page.goto('/user/settings/keys');
await page.locator('#add-ssh-button').click();
await page.getByLabel('Key name').fill('MyAwesomeKey');
await page.locator('#ssh-key-content').fill('Wront key material');
await page.getByRole('button', {name: 'Cancel'}).click();
await page.locator('#add-ssh-button').click();
const keyName = page.getByLabel('Key name');
await expect(keyName).toHaveValue('');
const content = page.locator('#ssh-key-content');
await expect(content).toHaveValue('');
});
test('User: Canceling adding GPG key clears input', async ({browser}, workerInfo) => {
const page = await login({browser}, workerInfo);
await page.goto('/user/settings/keys');
await page.locator('.show-panel[data-panel="#add-gpg-key-panel"]').click();
const gpgKeyContent = page.locator('#gpg-key-content');
await gpgKeyContent.fill('Wront key material');
await page.locator('.hide-panel[data-panel="#add-gpg-key-panel"]').click();
await expect(gpgKeyContent).toHaveValue('');
});
test('User: Add access token', async ({browser}, workerInfo) => {
const page = await login({browser}, workerInfo);
await page.goto('/user/settings/applications');
await page.locator('#scoped-access-submit').click();
await page.locator('#name:invalid').isVisible();
await page.locator('details.optional.field').click();
await page.selectOption('#access-token-scope-activitypub', 'read:activitypub');
await page.locator('#scoped-access-submit').click();
await page.locator('#name:invalid').isVisible();
await expect(page.locator('#access-token-scope-activitypub')).toHaveValue('read:activitypub');
const tokenName = globalThis.crypto.randomUUID();
await page.locator('#name').fill(tokenName);
await page.locator('#scoped-access-submit').click();
await page.getByText(tokenName).isVisible();
});