jojo/tests/e2e/org-members.test.e2e.ts
Antonin Delpeuch 5c13563682 feat: "Add member" button in org members list (#11848)
Fixes #1529.

This adds an "Add member" button to the list of members of an organization, offering a more intuitive way to add a user to an organization (instead of going through the list of teams).
This follows the design proposed in #1529. This PR can already be reviewed as such, but I plan to work on follow-up improvements:
- adding a confirmation dialog when adding the new member to the "Owners" team, since they get absolute rights on the org
- adding a text input to filter the list of teams, making it easier to select the desired teams when there are many of them
- potentially, improving the team creation link so that it brings the user back to the modal dialog once the team is created (but I'm not sure there's a ton of value behind this added complexity, since currently, creating a team will lead the user to the team page, which is a good place to add the member to the team)

This new way of adding members does not support issuing email invites, since we decided in #9884 that the invite feature hasn't got good enough of a UX to advertise it yet. Following [this discussion](https://codeberg.org/forgejo/discussions/issues/441), I am planning to work on enabling invites everywhere (potentially even making it the default).

## Checklist

### Tests for Go changes

- 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 ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [x] 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 plan to update https://docs.codeberg.org/collaborating/create-organization/#people once we are ready to take final screenshots of the feature.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

### Screenshots

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

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/11848): <!--number 11848 --><!--line 0 --><!--description IkFkZCBtZW1iZXIiIGJ1dHRvbiBpbiBvcmcgbWVtYmVycyBsaXN0-->"Add member" button in org members list<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11848
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Antonin Delpeuch <antonin@delpeuch.eu>
Co-committed-by: Antonin Delpeuch <antonin@delpeuch.eu>
2026-03-31 02:56:12 +02:00

77 lines
2.5 KiB
TypeScript

// Copyright 2026 The Forgejo Authors
// SPDX-License-Identifier: GPL-3.0-or-later
// @watch start
// web_src/css/org.css
// templates/org/member/members.tmpl
// @watch end
import {expect} from '@playwright/test';
import {test} from './utils_e2e.ts';
test.use({user: 'user2'});
test('Toggle visibility', async ({page}) => {
page.goto('/org/org3/members');
// Button "Make hidden" for user2's row
const hideUser2 = page.locator('.link-action[data-url="/org/org3/members/action/private?uid=2"]');
// Button "Make visible" for user2's row
const showUser2 = page.locator('.link-action[data-url="/org/org3/members/action/public?uid=2"]');
await expect(hideUser2).toBeVisible();
await expect(showUser2).toBeHidden();
await hideUser2.click();
// Button action was flipped
await expect(hideUser2).toBeHidden();
await expect(showUser2).toBeVisible();
// Revert for repeatability
await showUser2.click();
});
test('Leave org', async ({page}) => {
page.goto('/org/org3/members');
// Button "Leave" for user2's row
const leaveButton = page.locator('.delete-button[data-url="/org/org3/members/action/leave"]');
// Click the button
await leaveButton.click();
// A confirmation modal will appear
await expect(page.locator('.modal#leave-organization')).toBeVisible();
// Proceed leaving the org
await page.locator('.modal#leave-organization .actions button.ok').click();
// Getting error is enough to know that the correct request went though
await expect(page.locator('.flash-error').getByText('You cannot remove the last user from the "owners" team.')).toBeVisible();
});
test('Add a new member to the org', async ({page}) => {
page.goto('/org/org3/members');
// Click the "Add member" button
const newMemberButton = page.locator('#add-org-member-button');
await newMemberButton.click();
// A modal dialog appears
await expect(page.locator('#add-member-modal')).toBeVisible();
// Fill in the name of the user to add
await page.locator('#search-user-box input').fill('user5');
// Pick the auto-complete suggestion
await page.locator('#search-user-box .results a.result').click();
// Choose some teams
await page.locator('#add-member-team_2').click();
await page.locator('#add-member-team_12').click();
// Click the button
await page.locator('#add-member-modal .actions button.ok').click();
// Getting error is enough to know that the correct request went though
await expect(page.locator('.organization.members .list a').getByText('user5 (User Five)')).toBeVisible();
});