Template
1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo synced 2024-11-22 09:54:24 +01:00

Compare commits

...

17 commits

Author SHA1 Message Date
James Hatfield 735c2c8ada feat: add setting to block disposable emails
- Add a new setting `EMAIL_DOMAIN_BLOCK_DISPOSABLE` that will append a list of
  domains that are known for being used by temporary or disposable email
  services.

- Add a utility to automatically download and format the list of domains from
  the disposable-email-domains project on github.

  (https://github.com/disposable-email-domains/disposable-email-domains)
  license: CC0 1.0 Universal (CC0 1.0) [Public Domain]

  from README:
  """
  This repo contains a list of disposable and temporary email address domains often used to register dummy users in order to spam or abuse some services.

  We cannot guarantee all of these can still be considered disposable but we do basic checking so chances are they were disposable at one point in time.
  """
2024-11-14 21:30:14 -06:00
Earl Warren ef9a0c8d3d Merge pull request 'Update module code.forgejo.org/forgejo/act to v1.22.0 (forgejo)' (#5949) from renovate/forgejo-code.forgejo.org-forgejo-act-1.x into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5949
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-11-14 23:28:23 +00:00
Otto d1ad4dd561 Merge pull request 'Highlight user mention in comments and commit messages' (#5899) from 0ko/forgejo:mention-highlight into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5899
Reviewed-by: Otto <otto@codeberg.org>
2024-11-14 17:46:03 +00:00
Otto b92863b024 Merge pull request 'ci: use tmpfs for service storage' (#5958) from viceice/ci/use-tmpfs into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5958
Reviewed-by: Otto <otto@codeberg.org>
2024-11-14 17:44:22 +00:00
Michael Kriese 91fda7ee81 Merge pull request 'test: use sqlite in-memory db for integration' (#5956) from viceice/test/integration/use-sqlite-in-memory-db into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5956
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>
2024-11-14 17:14:39 +00:00
Michael Kriese 8a4407ef72
ci: use tmpfs for service storage 2024-11-14 17:27:48 +01:00
Michael Kriese a8beeff422 Merge pull request 'ci: disable mysql binlog' (#5957) from viceice/ci/mysql/no-bin-log into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5957
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2024-11-14 16:26:48 +00:00
Michael Kriese eda83cc7ed
ci: disable mysql binlog 2024-11-14 16:39:34 +01:00
Michael Kriese aea3c7d6e8
test: use memory for integration and journal for migration 2024-11-14 15:38:06 +01:00
Michael Kriese 24028747d3
test: use sqlite in-memory db for integration 2024-11-14 15:38:06 +01:00
Michael Kriese 5bd682b59d Merge pull request 'test: add trailing newline to testlogger.go:recordError message' (#5955) from viceice/test/add-newline-to-record-error-msg into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5955
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2024-11-14 14:20:42 +00:00
Michael Kriese 969027e3f2
test: add trailing newline to testlogger.go:recordError message 2024-11-14 14:38:47 +01:00
Otto Richter 019e38a746 chore(ci): Upload screenshots on test failure 2024-11-14 14:12:31 +01:00
Otto Richter 1f7a648057 tests(e2e): mention highlights in commit messages 2024-11-14 14:12:23 +01:00
Otto Richter c17b4bdaeb tests(e2e): Separate accessibility and form checks
- automatically test for light and dark themes
2024-11-14 14:08:12 +01:00
0ko 634519e891 feat(ui): highlight user mention in comments and commit messages 2024-11-14 14:08:12 +01:00
Renovate Bot 8206d509fc Update module code.forgejo.org/forgejo/act to v1.22.0 2024-11-14 02:03:09 +00:00
17 changed files with 4198 additions and 42 deletions

View file

@ -57,13 +57,14 @@ jobs:
services:
elasticsearch:
image: docker.io/bitnami/elasticsearch:7
options: --tmpfs /bitnami/elasticsearch/data
env:
discovery.type: single-node
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
minio:
image: docker.io/bitnami/minio:2024.8.17
options: >-
--hostname gitea.minio
--hostname gitea.minio --tmpfs /bitnami/minio/data
env:
MINIO_DOMAIN: minio
MINIO_ROOT_USER: 123456
@ -121,6 +122,13 @@ jobs:
USE_REPO_TEST_DIR: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
CHANGED_FILES: ${{steps.changed-files.outputs.all_changed_files}}
- name: Upload screenshots on failure
if: failure()
uses: https://code.forgejo.org/forgejo/upload-artifact@v4
with:
name: screenshots.zip
path: /workspace/forgejo/forgejo/tests/e2e/test-artifacts/*/*.png
retention-days: 3
test-remote-cacher:
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
@ -132,16 +140,16 @@ jobs:
cacher:
# redis
- image: docker.io/bitnami/redis:7.2
port: 6379
options: --tmpfs /bitnami/redis/data
# redict
- image: registry.redict.io/redict:7.3.0-scratch
port: 6379
options: --tmpfs /data
# valkey
- image: docker.io/bitnami/valkey:7.2
port: 6379
options: --tmpfs /bitnami/redis/data
# garnet
- image: ghcr.io/microsoft/garnet-alpine:1.0.14
port: 6379
options: --tmpfs /data
services:
cacher:
image: ${{ matrix.cacher.image }}
@ -176,7 +184,8 @@ jobs:
#
# See also https://codeberg.org/forgejo/forgejo/issues/976
#
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000 --disable-log-bin
options: --tmpfs /bitnami/mysql/data
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
@ -202,6 +211,7 @@ jobs:
env:
MINIO_ROOT_USER: 123456
MINIO_ROOT_PASSWORD: 12345678
options: --tmpfs /bitnami/minio/data
ldap:
image: docker.io/gitea/test-openldap:latest
pgsql:
@ -209,6 +219,7 @@ jobs:
env:
POSTGRES_DB: test
POSTGRES_PASSWORD: postgres
options: --tmpfs /var/lib/postgresql/data
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env

View file

@ -0,0 +1,109 @@
// Copyright 2024 James Hatfield
// SPDX-License-Identifier: MIT
//go:build ignore
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"go/format"
"io"
"log"
"net/http"
"os"
"strings"
)
const disposableEmailListURL string = "https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/%s/disposable_email_blocklist.conf"
var (
gitRef *string = flag.String("r", "master", "Git reference of the domain list version")
outPat *string = flag.String("o", "modules/setting/disposable_email_domain_data.go", "Output path")
)
func main() {
flag.Parse()
// generate the source code (array of domains)
res, err := generate()
if err != nil {
log.Fatalf("Generation Error: %v", err)
}
// write result to a file
err = os.WriteFile(*outPat, res, 0o644)
if err != nil {
log.Fatalf("File Write Error: %v", err)
}
}
func generate() ([]byte, error) {
var err error
var url string = fmt.Sprintf(disposableEmailListURL, *gitRef)
// download the domain list
res, err := http.Get(url)
if err != nil {
return nil, err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
// go through all entries (1 domain per line)
scanner := bufio.NewScanner(bytes.NewReader(body))
var arrDomains []string
for scanner.Scan() {
line := scanner.Text()
arrDomains = append(arrDomains, line)
}
// build the string in a readable way
var sb strings.Builder
_, err = sb.WriteString("[]string{\n")
if err != nil {
return nil, err
}
for _, item := range arrDomains {
_, err = sb.WriteString(fmt.Sprintf("\t%q,\n", item))
if err != nil {
return nil, err
}
}
_, err = sb.WriteString("}")
if err != nil {
return nil, err
}
// insert the values into file
final := fmt.Sprintf(hdr, url, sb.String())
return format.Source([]byte(final))
}
const hdr = `
// Copyright 2024 James Hatfield
// SPDX-License-Identifier: MIT
//
// Code generated by build/generate-disposable-email.go. DO NOT EDIT
// Sourced from %s
package setting
import "sync"
var DisposableEmailDomains = sync.OnceValue(func() []string {
return %s
})
`

2
go.mod
View file

@ -293,7 +293,7 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.21.5
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.22.0
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1

4
go.sum
View file

@ -4,8 +4,8 @@ code.forgejo.org/f3/gof3/v3 v3.7.0 h1:ZfuCP8CGm8ZJbWmL+V0pUu3E0X4FCAA7GfRDy/y5/K
code.forgejo.org/f3/gof3/v3 v3.7.0/go.mod h1:oNhOeqD4DZYjVcNjQXIOdDX9b/1tqxi9ITLS8H9/Csw=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
code.forgejo.org/forgejo/act v1.21.5 h1:rWI+bhClocogdNwjRrM836rZYY7JBcHY3VUAwkYqEtw=
code.forgejo.org/forgejo/act v1.21.5/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM=
code.forgejo.org/forgejo/act v1.22.0 h1:NbUf0+vQ48+ddwe4zVkINqnxKYl/to+NUvW7iisPA60=
code.forgejo.org/forgejo/act v1.22.0/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM=
code.forgejo.org/forgejo/archiver/v3 v3.5.1 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEjb3jaYYtmSE=
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@ package setting
import (
"regexp"
"slices"
"strings"
"time"
@ -37,6 +38,7 @@ var Service = struct {
RegisterManualConfirm bool
EmailDomainAllowList []glob.Glob
EmailDomainBlockList []glob.Glob
EmailDomainBlockDisposable bool
DisableRegistration bool
AllowOnlyInternalRegistration bool
AllowOnlyExternalRegistration bool
@ -156,6 +158,22 @@ func loadServiceFrom(rootCfg ConfigProvider) {
}
Service.EmailDomainAllowList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_WHITELIST", "EMAIL_DOMAIN_ALLOWLIST")
Service.EmailDomainBlockList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_BLOCKLIST")
Service.EmailDomainBlockDisposable = sec.Key("EMAIL_DOMAIN_BLOCK_DISPOSABLE").MustBool(false)
if Service.EmailDomainBlockDisposable {
toAdd := make([]glob.Glob, 0, len(DisposableEmailDomains()))
for _, domain := range DisposableEmailDomains() {
domain = strings.ToLower(domain)
// Only add domains that aren't blocked yet.
if !slices.ContainsFunc(Service.EmailDomainBlockList, func(g glob.Glob) bool { return g.Match(domain) }) {
if g, err := glob.Compile(domain); err != nil {
log.Error("Error in disposable domain %s: %v", domain, err)
} else {
toAdd = append(toAdd, g)
}
}
}
Service.EmailDomainBlockList = append(Service.EmailDomainBlockList, toAdd...)
}
Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true)
Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()

View file

@ -4,6 +4,7 @@
package setting
import (
"strings"
"testing"
"code.gitea.io/gitea/modules/structs"
@ -13,6 +14,15 @@ import (
"github.com/stretchr/testify/require"
)
func match(globs []glob.Glob, s string) bool {
for _, g := range globs {
if g.Match(s) {
return true
}
}
return false
}
func TestLoadServices(t *testing.T) {
oldService := Service
defer func() {
@ -28,15 +38,6 @@ EMAIL_DOMAIN_BLOCKLIST = d3, *.b
require.NoError(t, err)
loadServiceFrom(cfg)
match := func(globs []glob.Glob, s string) bool {
for _, g := range globs {
if g.Match(s) {
return true
}
}
return false
}
assert.True(t, match(Service.EmailDomainAllowList, "d1"))
assert.True(t, match(Service.EmailDomainAllowList, "foo.w"))
assert.True(t, match(Service.EmailDomainAllowList, "d2"))
@ -48,6 +49,97 @@ EMAIL_DOMAIN_BLOCKLIST = d3, *.b
assert.False(t, match(Service.EmailDomainBlockList, "d1"))
}
func TestLoadServiceBlockDisposable(t *testing.T) {
oldService := Service
defer func() {
Service = oldService
}()
cfg, err := NewConfigProviderFromData(`
[service]
EMAIL_DOMAIN_BLOCK_DISPOSABLE = true
`)
require.NoError(t, err)
loadServiceFrom(cfg)
for _, domain := range DisposableEmailDomains() {
require.True(t, match(Service.EmailDomainBlockList, domain))
}
require.Len(t, Service.EmailDomainBlockList, len(DisposableEmailDomains()))
knownGood := [...]string{
"aol.com",
"gmx.com",
"mail.com",
"zoho.com",
"proton.me",
"gmail.com",
"yahoo.com",
"icloud.com",
"outlook.com",
"protonmail.com",
}
for _, domain := range knownGood {
require.False(t, match(Service.EmailDomainBlockList, domain))
}
}
func TestLoadServiceBlockDisposableWithExistingGlobs(t *testing.T) {
oldService := Service
defer func() {
Service = oldService
}()
cfg, err := NewConfigProviderFromData(`
[service]
EMAIL_DOMAIN_BLOCKLIST = *.ru,*.org
EMAIL_DOMAIN_BLOCK_DISPOSABLE = true
`)
require.NoError(t, err)
loadServiceFrom(cfg)
for _, domain := range DisposableEmailDomains() {
require.True(t, match(Service.EmailDomainBlockList, domain))
}
redundant := 0
for _, val := range DisposableEmailDomains() {
if strings.HasSuffix(val, ".ru") || strings.HasSuffix(val, ".org") {
redundant++
}
}
expected := len(DisposableEmailDomains()) - redundant + 2
require.Len(t, Service.EmailDomainBlockList, expected)
}
func TestLoadServiceBlockDisposableWithComplementGlobs(t *testing.T) {
oldService := Service
defer func() {
Service = oldService
}()
cfg, err := NewConfigProviderFromData(`
[service]
EMAIL_DOMAIN_BLOCKLIST = *.random
EMAIL_DOMAIN_BLOCK_DISPOSABLE = true
`)
require.NoError(t, err)
loadServiceFrom(cfg)
for _, domain := range DisposableEmailDomains() {
require.True(t, match(Service.EmailDomainBlockList, domain))
}
expected := len(DisposableEmailDomains()) + 1
require.Len(t, Service.EmailDomainBlockList, expected)
}
func TestLoadServiceVisibilityModes(t *testing.T) {
oldService := Service
defer func() {

View file

@ -486,7 +486,7 @@ func PrintCurrentTest(t testing.TB, skip ...int) func() {
if err := WriterCloser.popT(); err != nil {
// disable test failure for now (too flacky)
_, _ = fmt.Fprintf(os.Stdout, "testlogger.go:recordError() FATAL ERROR: log.Error has been called: %v", err)
_, _ = fmt.Fprintf(os.Stdout, "testlogger.go:recordError() FATAL ERROR: log.Error has been called: %v\n", err)
// t.Errorf("testlogger.go:recordError() FATAL ERROR: log.Error has been called: %v", err)
}
}

View file

@ -26,6 +26,7 @@
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; }
</style>
</noscript>
{{template "shared/user/mention_highlight" .}}
{{template "base/head_opengraph" .}}
{{template "base/head_style" .}}
{{template "custom/header" .}}

View file

@ -0,0 +1,14 @@
{{if .IsSigned}}
<style>
.comment,
.commit-summary,
.commit-body {
.mention[href="{{AppSubUrl}}/{{.SignedUser.Name}}" i] {
background-color: var(--color-primary-alpha-30);
color: var(--color-primary-dark-2);
border-radius: 5px;
padding: 1px 4px;
}
}
</style>
{{end}}

View file

@ -5,7 +5,6 @@ package e2e
import (
"fmt"
"strconv"
"strings"
"testing"
"time"
@ -23,14 +22,31 @@ import (
// first entry represents filename
// the following entries define the full file content over time
type FileChanges [][]string
type FileChanges struct {
Filename string
CommitMsg string
Versions []string
}
// put your Git repo declarations in here
// feel free to amend the helper function below or use the raw variant directly
func DeclareGitRepos(t *testing.T) func() {
cleanupFunctions := []func(){
newRepo(t, 2, "diff-test", FileChanges{
{"testfile", "hello", "hallo", "hola", "native", "ubuntu-latest", "- runs-on: ubuntu-latest", "- runs-on: debian-latest"},
newRepo(t, 2, "diff-test", []FileChanges{{
Filename: "testfile",
Versions: []string{"hello", "hallo", "hola", "native", "ubuntu-latest", "- runs-on: ubuntu-latest", "- runs-on: debian-latest"},
}}),
newRepo(t, 2, "mentions-highlighted", []FileChanges{
{
Filename: "history1.md",
Versions: []string{""},
CommitMsg: "A commit message which mentions @user2 in the title\nand has some additional text which mentions @user1",
},
{
Filename: "history2.md",
Versions: []string{""},
CommitMsg: "Another commit which mentions @user1 in the title\nand @user2 in the text",
},
}),
// add your repo declarations here
}
@ -42,7 +58,7 @@ func DeclareGitRepos(t *testing.T) func() {
}
}
func newRepo(t *testing.T, userID int64, repoName string, fileChanges FileChanges) func() {
func newRepo(t *testing.T, userID int64, repoName string, fileChanges []FileChanges) func() {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
somerepo, _, cleanupFunc := tests.CreateDeclarativeRepo(t, user, repoName,
[]unit_model.Type{unit_model.TypeCode, unit_model.TypeIssues}, nil,
@ -50,19 +66,25 @@ func newRepo(t *testing.T, userID int64, repoName string, fileChanges FileChange
)
for _, file := range fileChanges {
changeLen := len(file)
for i := 1; i < changeLen; i++ {
operation := "create"
if i != 1 {
operation = "update"
for i, version := range file.Versions {
operation := "update"
if i == 0 {
operation = "create"
}
// default to unique commit messages
commitMsg := file.CommitMsg
if commitMsg == "" {
commitMsg = fmt.Sprintf("Patch: %s-%d", file.Filename, i+1)
}
resp, err := files_service.ChangeRepoFiles(git.DefaultContext, somerepo, user, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{{
Operation: operation,
TreePath: file[0],
ContentReader: strings.NewReader(file[i]),
TreePath: file.Filename,
ContentReader: strings.NewReader(version),
}},
Message: fmt.Sprintf("Patch: %s-%s", file[0], strconv.Itoa(i)),
Message: commitMsg,
OldBranch: "main",
NewBranch: "main",
Author: &files_service.IdentityOptions{

View file

@ -5,7 +5,12 @@
// @watch end
import {expect} from '@playwright/test';
import {test} from './utils_e2e.ts';
import {test, login_user, login} from './utils_e2e.ts';
import {accessibilityCheck} from './shared/accessibility.ts';
test.beforeAll(async ({browser}, workerInfo) => {
await login_user(browser, workerInfo, 'user2');
});
async function assertSelectedLines(page, nums) {
const pageAssertions = async () => {
@ -75,3 +80,19 @@ test('Readable diff', async ({page}, workerInfo) => {
}
}
});
test('Username highlighted in commits', async ({browser}, workerInfo) => {
const page = await login({browser}, workerInfo);
await page.goto('/user2/mentions-highlighted/commits/branch/main');
// check first commit
await page.getByRole('link', {name: 'A commit message which'}).click();
await expect(page.getByRole('link', {name: '@user2'})).toHaveCSS('background-color', /(.*)/);
await expect(page.getByRole('link', {name: '@user1'})).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
await accessibilityCheck({page}, ['.commit-header'], [], []);
// check second commit
await page.goto('/user2/mentions-highlighted/commits/branch/main');
await page.locator('tbody').getByRole('link', {name: 'Another commit which mentions'}).click();
await expect(page.getByRole('link', {name: '@user2'})).toHaveCSS('background-color', /(.*)/);
await expect(page.getByRole('link', {name: '@user1'})).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
await accessibilityCheck({page}, ['.commit-header'], [], []);
});

View file

@ -0,0 +1,35 @@
import {expect, type Page} from '@playwright/test';
import {AxeBuilder} from '@axe-core/playwright';
export async function accessibilityCheck({page}: {page: Page}, includes: string[], excludes: string[], disabledRules: string[]) {
// contrast of inline links is still a global issue in Forgejo
disabledRules += 'link-in-text-block';
let accessibilityScanner = await new AxeBuilder({page})
.disableRules(disabledRules);
// passing the whole array seems to be not supported,
// iterating has the nice side-effectof skipping this if the array is empty
for (const incl of includes) {
// passing the whole array seems to be not supported
accessibilityScanner = accessibilityScanner.include(incl);
}
for (const excl of excludes) {
accessibilityScanner = accessibilityScanner.exclude(excl);
}
// scan the page both in dark and light theme
let accessibilityScanResults = await accessibilityScanner.analyze();
expect(accessibilityScanResults.violations).toEqual([]);
await page.emulateMedia({colorScheme: 'dark'});
// in https://codeberg.org/forgejo/forgejo/pulls/5899 there have been
// some weird failures related to contrast scanning,
// reporting for colours that haven't been used and no trace in the
// screenshots.
// Since this was only happening with some browsers and not always,
// my bet is on a transition effect on dark/light mode switch.
// Waiting a little seems to work around this.
await page.waitForTimeout(100); // eslint-disable-line playwright/no-wait-for-timeout
accessibilityScanResults = await accessibilityScanner.analyze();
expect(accessibilityScanResults.violations).toEqual([]);
await page.emulateMedia({colorScheme: 'light'});
}

View file

@ -1,17 +1,14 @@
import {expect, type Page} from '@playwright/test';
import {AxeBuilder} from '@axe-core/playwright';
import {accessibilityCheck} from './accessibility.ts';
export async function validate_form({page}: {page: Page}, scope: 'form' | 'fieldset' = 'form') {
const accessibilityScanResults = await new AxeBuilder({page})
// disable checking for link style - should be fixed, but not now
.disableRules('link-in-text-block')
.include(scope)
const excludedElements = [
// exclude automated tooltips from accessibility scan, remove when fixed
.exclude('span[data-tooltip-content')
'span[data-tooltip-content',
// exclude weird non-semantic HTML disabled content
.exclude('.disabled')
.analyze();
expect(accessibilityScanResults.violations).toEqual([]);
'.disabled',
];
await accessibilityCheck({page}, [scope], excludedElements, []);
// assert CSS properties that needed to be overriden for forms (ensure they remain active)
const boxes = page.getByRole('checkbox').or(page.getByRole('radio'));

View file

@ -0,0 +1,21 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package integration
import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHeadMentionCSS(t *testing.T) {
userSession := loginUser(t, "user2")
resp := userSession.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK)
assert.Contains(t, resp.Body.String(), `.mention[href="/user2" i]`)
guestSession := emptyTestSession(t)
resp = guestSession.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK)
assert.NotContains(t, resp.Body.String(), `.mention[href="`)
}

View file

@ -5,6 +5,7 @@ RUN_MODE = prod
[database]
DB_TYPE = sqlite3
PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/gitea.db
SQLITE_JOURNAL_MODE = MEMORY
[indexer]
REPO_INDEXER_ENABLED = true

View file

@ -175,6 +175,9 @@ func InitTest(requireGitea bool) {
log.Fatal("db.Exec: CREATE SCHEMA: %v", err)
}
}
case setting.Database.Type.IsSQLite3():
setting.Database.Path = ":memory:"
}
routers.InitWebInstalled(graceful.GetManager().HammerContext())