1
0
mirror of https://git.cloudron.io/cloudron/gitea-app synced 2026-05-01 06:53:37 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Girish Ramakrishnan 433327e0d6 test: drop redundant scrollIntoView usage
Remove explicit scrollIntoView calls in Charlie-based test flows now that interactions auto-scroll elements.

Made-with: Cursor
2026-04-21 12:39:12 +02:00
5 changed files with 107 additions and 53 deletions
-2
View File
@@ -1,4 +1,2 @@
node_modules/ node_modules/
test/test-results.xml
test/screenshots/
-14
View File
@@ -1994,17 +1994,3 @@
* Automatic generation of release notes ([#35977](https://github.com/go-gitea/gitea/issues/35977)) * Automatic generation of release notes ([#35977](https://github.com/go-gitea/gitea/issues/35977))
* Add button to re-run failed jobs in Actions ([#36924](https://github.com/go-gitea/gitea/issues/36924)) * Add button to re-run failed jobs in Actions ([#36924](https://github.com/go-gitea/gitea/issues/36924))
[1.38.1]
* Update gitea to 1.26.1
* [Full Changelog](https://github.com/go-gitea/gitea/releases/tag/v1.26.1)
* Add event.schedule context for schedule actions task ([#37320](https://github.com/go-gitea/gitea/issues/37320)) ([#37348](https://github.com/go-gitea/gitea/issues/37348))
* Fix an issue where changing an organization's visibility caused problems when users had forked its repositories. ([#37324](https://github.com/go-gitea/gitea/issues/37324)) ([#37344](https://github.com/go-gitea/gitea/issues/37344))
* Use modern "git update-index --cacheinfo" syntax to support more file names ([#37338](https://github.com/go-gitea/gitea/issues/37338)) ([#37343](https://github.com/go-gitea/gitea/issues/37343))
* Fix URL related escaping for oauth2 ([#37334](https://github.com/go-gitea/gitea/issues/37334)) ([#37340](https://github.com/go-gitea/gitea/issues/37340))
* When the requested arch rpm is missing fall back to noarch ([#37236](https://github.com/go-gitea/gitea/issues/37236)) ([#37339](https://github.com/go-gitea/gitea/issues/37339))
* Fix actions concurrency groups cross-branch leak ([#37311](https://github.com/go-gitea/gitea/issues/37311)) ([#37331](https://github.com/go-gitea/gitea/issues/37331))
* Fix bug when accessing user badges ([#37321](https://github.com/go-gitea/gitea/issues/37321)) ([#37329](https://github.com/go-gitea/gitea/issues/37329))
* Fix container auth for public instance ([#37290](https://github.com/go-gitea/gitea/issues/37290)) ([#37294](https://github.com/go-gitea/gitea/issues/37294))
* Fix Mermaid diagrams failing when node labels contain line breaks ([#37296](https://github.com/go-gitea/gitea/issues/37296)) ([#37299](https://github.com/go-gitea/gitea/issues/37299))
* Fix: dump with default zip type produces uncompressed zip ([#37401](https://github.com/go-gitea/gitea/issues/37401)) [#37402](https://github.com/go-gitea/gitea/issues/37402)
+2 -2
View File
@@ -4,8 +4,8 @@
"author": "Gitea developers", "author": "Gitea developers",
"description": "file://DESCRIPTION.md", "description": "file://DESCRIPTION.md",
"tagline": "A painless self-hosted Git Service", "tagline": "A painless self-hosted Git Service",
"version": "1.38.1", "version": "1.38.0",
"upstreamVersion": "1.26.1", "upstreamVersion": "1.26.0",
"healthCheckPath": "/explore", "healthCheckPath": "/explore",
"httpPort": 3000, "httpPort": 3000,
"memoryLimit": 536870912, "memoryLimit": 536870912,
+1 -1
View File
@@ -18,7 +18,7 @@ WORKDIR /home/git
ENV GNUPGHOME="/app/data/gnupg" ENV GNUPGHOME="/app/data/gnupg"
# renovate: datasource=github-releases depName=go-gitea/gitea versioning=semver extractVersion=^v(?<version>.+)$ # renovate: datasource=github-releases depName=go-gitea/gitea versioning=semver extractVersion=^v(?<version>.+)$
ARG GITEA_VERSION=1.26.1 ARG GITEA_VERSION=1.26.0
RUN mkdir -p /home/git/gitea && \ RUN mkdir -p /home/git/gitea && \
curl -L https://github.com/go-gitea/gitea/releases/download/v${GITEA_VERSION}/gitea-${GITEA_VERSION}-linux-amd64 -o /home/git/gitea/gitea \ curl -L https://github.com/go-gitea/gitea/releases/download/v${GITEA_VERSION}/gitea-${GITEA_VERSION}-linux-amd64 -o /home/git/gitea/gitea \
Regular → Executable
+104 -34
View File
@@ -4,7 +4,24 @@ import assert from 'node:assert/strict';
import { execSync } from 'node:child_process'; import { execSync } from 'node:child_process';
import fs from 'node:fs'; import fs from 'node:fs';
import path from 'node:path'; import path from 'node:path';
import { app, clearCache, click, cloudronCli, goto, loginOIDC, sendKeys, setupBrowser, takeScreenshot, teardownBrowser, username, waitFor, waitForUrl, press } from '@cloudron/charlie'; import superagent from '@cloudron/superagent';
import {
app,
clearCache,
click,
cloudronCli,
executeScript,
goto,
loginOIDC,
sendKeys,
setInputFiles,
setupBrowser,
takeScreenshot,
teardownBrowser,
username,
waitForElement,
waitForPath
} from '@cloudron/charlie';
/* global it, describe, before, after, afterEach */ /* global it, describe, before, after, afterEach */
@@ -21,15 +38,35 @@ describe('Application life cycle test', function () {
}); });
afterEach(async function () { afterEach(async function () {
await takeScreenshot(this.currentTest); await takeScreenshot(this.currentTest.title);
}); });
async function setAvatar() {
await goto(`https://${app.fqdn}/user/settings`, '//label[contains(text(), "Use Custom Avatar")]');
await click('//label[contains(text(), "Use Custom Avatar")]');
await setInputFiles('//input[@type="file" and @name="avatar"]', path.resolve(import.meta.dirname, '../logo.png'));
await click('//button[contains(text(), "Update Avatar")]');
await waitForElement('//p[contains(text(),"Your avatar has been updated.")]');
}
async function checkAvatar() {
await goto(`https://${app.fqdn}/${username}`, '//div[@id="profile-avatar"]/a/img');
const avatarSrc = await executeScript(() => {
const el = document.querySelector('#profile-avatar a img');
return el ? el.getAttribute('src') : null;
});
assert.ok(avatarSrc);
const avatarUrl = new URL(avatarSrc, `https://${app.fqdn}`).href;
const response = await superagent.get(avatarUrl);
assert.strictEqual(response.status, 200);
}
async function login(user, passwd) { async function login(user, passwd) {
await goto(`https://${app.fqdn}/user/login`, 'label=Username or Email Address'); await goto(`https://${app.fqdn}/user/login`, '#user_name');
await sendKeys('label=Username or Email Address', user); await sendKeys('#user_name', user);
await sendKeys('label=Password', passwd); await sendKeys('#password', passwd);
await click('Sign In', { role: 'button' }); // there is a sign in link at the top await click('//form[@action="/user/login"]//button');
await waitFor('Milestones'); await waitForElement('//nav//img[contains(@class, "avatar")]');
} }
async function adminLogin() { async function adminLogin() {
@@ -38,33 +75,43 @@ describe('Application life cycle test', function () {
async function loginGiteaOIDC() { async function loginGiteaOIDC() {
await clearCache(); await clearCache();
await goto(`https://${app.fqdn}/user/login`, /Sign in with/); await goto(`https://${app.fqdn}/user/login`, '//a[@href="/user/oauth2/cloudron"]');
await click(/Sign in with/); await click('//a[@href="/user/oauth2/cloudron"]');
await loginOIDC('Milestones'); await loginOIDC('//nav//img[contains(@class, "avatar")]');
}
async function loginGiteaOIDCOld() {
await clearCache();
await goto(`https://${app.fqdn}/user/login`, '//a[contains(@class, "openidConnect")]');
await click('//a[contains(@class, "openidConnect") and contains(., "Sign in with cloudron")]');
await loginOIDC('//nav//img[contains(@class, "avatar")]');
} }
async function logout() { async function logout() {
await clearCache(); await goto(`https://${app.fqdn}`, '//nav//img[contains(@class, "avatar")]');
await click('//nav//img[contains(@class, "avatar")]');
await waitForElement('//a[@href="/user/logout"]');
await click('//a[@href="/user/logout"]');
} }
async function addPublicKey() { async function addPublicKey() {
const keyPath = path.join(import.meta.dirname, 'id_ed25519'); const keyPath = path.join(import.meta.dirname, 'id_ed25519');
fs.chmodSync(keyPath, 0o600); fs.chmodSync(keyPath, 0o600);
await goto(`https://${app.fqdn}/user/settings/keys`, 'css=#add-ssh-button'); await goto(`https://${app.fqdn}/user/settings/keys`, '#add-ssh-button');
await click('css=#add-ssh-button'); // there are two Add key buttons await click('#add-ssh-button');
await sendKeys('label=Content', fs.readFileSync(`${import.meta.dirname}/id_ed25519.pub`, 'utf8').trim()); // there are two Content labels await sendKeys('#ssh-key-title', 'testkey');
await sendKeys('label=Key Name', 'testkey'); await sendKeys('#ssh-key-content', fs.readFileSync(`${import.meta.dirname}/id_ed25519.pub`, 'utf8').trim());
await press('label=Key Name', 'Enter'); await click('//form//button[contains(text(),"Add Key")]');
await waitFor(/has been added/); await waitForElement('//p[contains(text(), "has been added.")]');
} }
async function createRepo() { async function createRepo() {
await goto(`https://${app.fqdn}/repo/create`, 'label=Repository Name'); await goto(`https://${app.fqdn}/repo/create`, '#repo_name');
await sendKeys('label=Repository Name', reponame); await sendKeys('#repo_name', reponame);
await click(/Initialize Repository/); await click('#auto-init');
await click('Create Repository'); await click('//button[contains(text(), "Create Repository")]');
await waitForUrl(`https://${app.fqdn}/${username}/${reponame}`); await waitForPath(`/${username}/${reponame}`);
} }
function cloneRepo() { function cloneRepo() {
@@ -96,6 +143,8 @@ describe('Application life cycle test', function () {
it('can logout', logout); it('can logout', logout);
it('can login', loginGiteaOIDC); it('can login', loginGiteaOIDC);
it('can set avatar', setAvatar);
it('can get avatar', checkAvatar);
it('can add public key', addPublicKey); it('can add public key', addPublicKey);
@@ -105,29 +154,41 @@ describe('Application life cycle test', function () {
it('can add and push a file', pushFile); it('can add and push a file', pushFile);
it('can restart app', cloudronCli.restart); it('can restart app', function () {
cloudronCli.restart();
});
it('can clone the url', cloneRepo); it('can clone the url', cloneRepo);
it('file exists in repo', fileExists); it('file exists in repo', fileExists);
it('backup app', cloudronCli.createBackup); it('backup app', async function () {
it('restore app', cloudronCli.restoreFromLatestBackup); await cloudronCli.createBackup();
});
it('restore app', async function () {
await cloudronCli.restoreFromLatestBackup();
});
it('can login', loginGiteaOIDC); it('can login', loginGiteaOIDC);
it('can get avatar', checkAvatar);
it('can clone the url', cloneRepo); it('can clone the url', cloneRepo);
it('file exists in repo', function () { it('file exists in repo', function () {
assert.strictEqual(fs.existsSync(`${repodir}/newfile`), true); assert.strictEqual(fs.existsSync(`${repodir}/newfile`), true);
}); });
it('move to different location', cloudronCli.changeLocation); it('move to different location', async function () {
await cloudronCli.changeLocation();
});
it('can login', loginGiteaOIDC); it('can login', loginGiteaOIDC);
it('can get avatar', checkAvatar);
it('can clone the url', cloneRepo); it('can clone the url', cloneRepo);
it('file exists in repo', function () { it('file exists in repo', function () {
assert.strictEqual(fs.existsSync(`${repodir}/newfile`), true); assert.strictEqual(fs.existsSync(`${repodir}/newfile`), true);
}); });
it('uninstall app', cloudronCli.uninstall); it('uninstall app', async function () {
await cloudronCli.uninstall();
});
it('install app (no sso)', function () { it('install app (no sso)', function () {
cloudronCli.install({ noSso: true, tcpPortFlags: INSTALL_TCP_FLAGS }); cloudronCli.install({ noSso: true, tcpPortFlags: INSTALL_TCP_FLAGS });
@@ -136,26 +197,35 @@ describe('Application life cycle test', function () {
it('can admin login (no sso)', adminLogin); it('can admin login (no sso)', adminLogin);
it('can logout', logout); it('can logout', logout);
it('uninstall app (no sso)', cloudronCli.uninstall); it('uninstall app (no sso)', async function () {
await cloudronCli.uninstall();
it('can install app for update', async function () {
await cloudronCli.appstoreInstall({ tcpPortFlags: INSTALL_TCP_FLAGS });
}); });
it('can login', loginGiteaOIDC); it('can install app', function () {
cloudronCli.appstoreInstall({ tcpPortFlags: INSTALL_TCP_FLAGS });
});
it('can login', loginGiteaOIDCOld);
it('can set avatar', setAvatar);
it('can get avatar', checkAvatar);
it('can add public key', addPublicKey); it('can add public key', addPublicKey);
it('can create repo', createRepo); it('can create repo', createRepo);
it('can clone the url', cloneRepo); it('can clone the url', cloneRepo);
it('can add and push a file', pushFile); it('can add and push a file', pushFile);
it('can update', cloudronCli.update); it('can update', async function () {
await cloudronCli.update();
});
it('can admin login', adminLogin); it('can admin login', adminLogin);
it('can logout', logout); it('can logout', logout);
it('can login', loginGiteaOIDC); it('can login', loginGiteaOIDC);
it('can get avatar', checkAvatar);
it('can clone the url', cloneRepo); it('can clone the url', cloneRepo);
it('file exists in cloned repo', fileExists); it('file exists in cloned repo', fileExists);
it('uninstall app', cloudronCli.uninstall); it('uninstall app', async function () {
await cloudronCli.uninstall();
});
}); });