#!/usr/bin/env node import assert from 'node:assert/strict'; import { execSync } from 'node:child_process'; import fs from 'node:fs'; import path from 'node:path'; import { app, clearCache, click, cloudronCli, goto, loginOIDC, sendKeys, setupBrowser, takeScreenshot, teardownBrowser, username, waitFor, waitForUrl, press } from '@cloudron/charlie'; /* global it, describe, before, after, afterEach */ const SSH_PORT = 29420; const INSTALL_TCP_FLAGS = { SSH_PORT }; const repodir = '/tmp/testrepo'; const reponame = 'testrepo'; describe('Application life cycle test', function () { before(setupBrowser); after(async function () { await teardownBrowser(); fs.rmSync(repodir, { recursive: true, force: true }); }); afterEach(async function () { await takeScreenshot(this.currentTest); }); async function login(user, passwd) { await goto(`https://${app.fqdn}/user/login`, 'label=Username or Email Address'); await sendKeys('label=Username or Email Address', user); await sendKeys('label=Password', passwd); await click('Sign In', { role: 'button' }); // there is a sign in link at the top await waitFor('Milestones'); } async function adminLogin() { await login('root', 'changeme'); } async function loginGiteaOIDC() { await clearCache(); await goto(`https://${app.fqdn}/user/login`, /Sign in with/); await click(/Sign in with/); await loginOIDC('Milestones'); } async function logout() { await clearCache(); } async function addPublicKey() { const keyPath = path.join(import.meta.dirname, 'id_ed25519'); fs.chmodSync(keyPath, 0o600); await goto(`https://${app.fqdn}/user/settings/keys`, 'css=#add-ssh-button'); await click('css=#add-ssh-button'); // there are two Add key buttons await sendKeys('label=Content', fs.readFileSync(`${import.meta.dirname}/id_ed25519.pub`, 'utf8').trim()); // there are two Content labels await sendKeys('label=Key Name', 'testkey'); await press('label=Key Name', 'Enter'); await waitFor(/has been added/); } async function createRepo() { await goto(`https://${app.fqdn}/repo/create`, 'label=Repository Name'); await sendKeys('label=Repository Name', reponame); await click(/Initialize Repository/); await click('Create Repository'); await waitForUrl(`https://${app.fqdn}/${username}/${reponame}`); } function cloneRepo() { fs.rmSync(repodir, { recursive: true, force: true }); const env = Object.create(process.env); env.GIT_SSH = path.join(import.meta.dirname, 'git_ssh_wrapper.sh'); execSync(`git clone ssh://git@${app.fqdn}:${SSH_PORT}/${username}/${reponame}.git ${repodir}`, { env }); } function pushFile() { const env = Object.create(process.env); env.GIT_SSH = path.join(import.meta.dirname, 'git_ssh_wrapper.sh'); execSync( `touch newfile && git add newfile && git commit -a -mx && git push ssh://git@${app.fqdn}:${SSH_PORT}/${username}/${reponame} main`, { env, cwd: repodir } ); fs.rmSync(repodir, { recursive: true, force: true }); } function fileExists() { assert.strictEqual(fs.existsSync(`${repodir}/newfile`), true); } it('install app', function () { cloudronCli.install({ tcpPortFlags: INSTALL_TCP_FLAGS }); }); it('can admin login', adminLogin); it('can logout', logout); it('can login', loginGiteaOIDC); it('can add public key', addPublicKey); it('can create repo', createRepo); it('can clone the url', cloneRepo); it('can add and push a file', pushFile); it('can restart app', cloudronCli.restart); it('can clone the url', cloneRepo); it('file exists in repo', fileExists); it('backup app', cloudronCli.createBackup); it('restore app', cloudronCli.restoreFromLatestBackup); it('can login', loginGiteaOIDC); it('can clone the url', cloneRepo); it('file exists in repo', function () { assert.strictEqual(fs.existsSync(`${repodir}/newfile`), true); }); it('move to different location', cloudronCli.changeLocation); it('can login', loginGiteaOIDC); it('can clone the url', cloneRepo); it('file exists in repo', function () { assert.strictEqual(fs.existsSync(`${repodir}/newfile`), true); }); it('uninstall app', cloudronCli.uninstall); it('install app (no sso)', function () { cloudronCli.install({ noSso: true, tcpPortFlags: INSTALL_TCP_FLAGS }); }); it('can admin login (no sso)', adminLogin); it('can logout', logout); it('uninstall app (no sso)', cloudronCli.uninstall); it('can install app from appstore', async function () { await cloudronCli.appstoreInstall({ tcpPortFlags: INSTALL_TCP_FLAGS }); }); it('can login', loginGiteaOIDC); it('can add public key', addPublicKey); it('can create repo', createRepo); it('can clone the url', cloneRepo); it('can add and push a file', pushFile); it('can update', cloudronCli.update); it('can admin login', adminLogin); it('can logout', logout); it('can login', loginGiteaOIDC); it('can clone the url', cloneRepo); it('file exists in cloned repo', fileExists); it('uninstall app', cloudronCli.uninstall); });