jojo/tests/forgery/user.go
oliverpool 88ba174119 tests: better factory with forgery package (#11356)
### Context

Following the feedback in forgejo/discussions#170 (and my ambitious attempt in forgejo/forgejo#10985), it appears that having an easy-to-use factory package would greatly help get rid of the global fixtures.

I think that the global fixtures are quite harmful (recent example: https://codeberg.org/forgejo/forgejo/pulls/9906#issuecomment-10826066):
- hard to write (contributor must know where to add them)
- hard to change (may break some unrelated tests)
- hard to review (not located near the test code)
- they require the tests to execute sequentially

### Proposed way forward

The `forgery` package (the name represents faking/crafting and sounds good with Forgejo) is meant to replace global yaml fixtures with local go factories. The forgery can currently:
- create users
- create repos
- create organisations

This allowed me to drop `CreateDeclarativeRepoWithOptions` (and deprecate `CreateDeclarativeRepo`).

I think that further changes should be delayed to other PRs (I have a local branch to create `Project`)

### 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

- [ ] 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.
- [x] 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.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11356
Reviewed-by: limiting-factor <limiting-factor@noreply.codeberg.org>
2026-05-12 20:57:02 +02:00

66 lines
1.5 KiB
Go

// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgery
import (
"math/rand/v2"
"regexp"
"strconv"
"testing"
org_model "forgejo.org/models/organization"
user_model "forgejo.org/models/user"
"github.com/stretchr/testify/require"
)
var nameCleaner = regexp.MustCompile(`[^a-zA-Z0-9-]+`) // exclude "_", to prevent multiple consecutive dashes
// uniqueSafeName replaces specials chars with _ and appends a random hex suffix
func uniqueSafeName(testName string) string {
return nameCleaner.ReplaceAllLiteralString(testName, "_") + "-" + strconv.FormatUint(uint64(rand.Uint32()), 16)
}
type CreateUserOptions struct {
IsAdmin bool
}
const userPassword = "password"
func CreateUser(t testing.TB, opts *CreateUserOptions) *user_model.User {
t.Helper()
if opts == nil {
opts = &CreateUserOptions{}
}
u := &user_model.User{}
name := "user-" + uniqueSafeName(t.Name())
u.Name = name
u.Email = name + "@test.forgejo.org"
u.Passwd = userPassword
u.IsAdmin = opts.IsAdmin
err := user_model.CreateUser(t.Context(), u)
require.NoError(t, err)
return u
}
func CreateOrganisation(t testing.TB, owner *user_model.User) *org_model.Organization {
t.Helper()
if owner == nil {
owner = CreateUser(t, nil) // if specific options are needed, create the owner manually
}
o := &org_model.Organization{}
name := "org-" + uniqueSafeName(t.Name())
o.Name = name
err := org_model.CreateOrganization(t.Context(), o, owner)
require.NoError(t, err)
return o
}