From 89cee6707407e87ef3f5e041dcfc97de009bc6d0 Mon Sep 17 00:00:00 2001 From: Alexander Walther Date: Mon, 8 Jul 2024 13:06:24 +0200 Subject: [PATCH] e2e test files --- .github/workflows/e2e.yml | 84 ++++++++++ nightwatch.conf.js | 82 ++++++++++ tests/e2e/maintenance.js | 326 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 492 insertions(+) create mode 100644 .github/workflows/e2e.yml create mode 100644 nightwatch.conf.js create mode 100644 tests/e2e/maintenance.js diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000..0d23a59 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,84 @@ +name: e2e tests + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + +permissions: + contents: read + +jobs: + e2e: + + runs-on: ubuntu-latest + permissions: + contents: write # for Git to git apply + + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: gd, intl, pdo_mysql + coverage: none # disable xdebug, pcov + + # credits https://blog.markvincze.com/download-artifacts-from-a-latest-github-release-in-sh-and-powershell/ + - name: Download latest REDAXO release + run: | + LATEST_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/redaxo/redaxo/releases/latest) + REDAXO_VERSION=$(echo $LATEST_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') + echo "Downloaded REDAXO $REDAXO_VERSION" + curl -Ls -o redaxo.zip https://github.com/redaxo/redaxo/releases/download/$REDAXO_VERSION/redaxo_$REDAXO_VERSION.zip + unzip -oq redaxo.zip -d redaxo_cms + rm redaxo.zip + + - name: Init database + run: | + sudo /etc/init.d/mysql start + mysql -uroot -h127.0.0.1 -proot -e 'create database redaxo5;' + + - name: Setup REDAXO + run: | + php redaxo_cms/redaxo/bin/console setup:run -n --lang=de_de --agree-license --db-host=127.0.0.1 --db-name=redaxo5 --db-password=root --db-createdb=no --db-setup=normal --admin-username=admin --admin-password=adminpassword --error-email=test@redaxo.invalid --ansi + php redaxo_cms/redaxo/bin/console config:set --type boolean debug.enabled true + php redaxo_cms/redaxo/bin/console config:set --type boolean debug.throw_always_exception true + + - name: Create user, update config + run: | + php redaxo_cms/redaxo/bin/console user:create nightwatch_username nightwatch_password --admin --ansi + php redaxo_cms/redaxo/bin/console config:set error_email 'test@redaxo.invalid' --ansi + php redaxo_cms/redaxo/bin/console config:set server 'http://localhost:8000/' --ansi + + # copy Addon files, ignore some directories... + # install phpmailer + # install the addon + # if the addon name does not match the repository name, ${{ github.event.repository.name }} must be replaced with the addon name + - name: Copy and install Addons + run: | + rsync -av --exclude='vendor' --exclude='.github' --exclude='.git' --exclude='redaxo_cms' './' 'redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }}' + redaxo_cms/redaxo/bin/console package:install '${{ github.event.repository.name }}' + + - name: Setup nodejs + uses: actions/setup-node@v3 + with: + node-version: "16.x" + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Setup Webserver and install node modules + working-directory: redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }} + run: | + php -S 127.0.0.1:8000 -t ../../../../ & + npm install + sudo apt-get install xvfb + + - name: Run e2e tests + working-directory: redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }} +# continue-on-error: true + run: | + export LAUNCH_URL='http://localhost:8000/'; + xvfb-run npm test diff --git a/nightwatch.conf.js b/nightwatch.conf.js new file mode 100644 index 0000000..9788896 --- /dev/null +++ b/nightwatch.conf.js @@ -0,0 +1,82 @@ +// Refer to the online docs for more details: +// https://nightwatchjs.org/gettingstarted/configuration/ +// + +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: ['tests/e2e'], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + // page_objects_path: ['test/e2e/page-objects'], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + // custom_commands_path: ['test/e2e/custom-commands'], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + // custom_assertions_path: ['test/e2e/custom-assertions'], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + // plugins: [], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html + globals_path: '', + + webdriver: {}, + + test_settings: { + default: { + disable_error_log: false, + launch_url: '${LAUNCH_URL}', + + screenshots: { + enabled: false, + on_failure: false, + path: "./screens" + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + }, + + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + } +}; diff --git a/tests/e2e/maintenance.js b/tests/e2e/maintenance.js new file mode 100644 index 0000000..b10bcdd --- /dev/null +++ b/tests/e2e/maintenance.js @@ -0,0 +1,326 @@ +const got = require('got'); + +describe('maintenance addon testing', () => { + /** + * login + */ + function login(browser) { + /** + * navigate to the login screen + */ + browser.navigateTo('/redaxo/index.php'); + browser.pause(250); + + /** + * check if the login input is present + * add username + */ + browser.assert.elementPresent('input[id=rex-id-login-user]'); + browser.sendKeys('input[id=rex-id-login-user]', 'nightwatch_username'); + browser.pause(250); + + /** + * check if the password input is present + * add password + */ + browser.assert.elementPresent('input[id=rex-id-login-password]'); + browser.sendKeys('input[id=rex-id-login-password]', ['nightwatch_password', browser.Keys.ENTER]); + browser.pause(250); + } + + /** + * logout + */ + function logout(browser) { + browser.pause(200); + browser.click('.navbar-nav a.rex-logout'); + } + + beforeEach(browser => { + login(browser); + + /** + * check if we are logged in to the backend + */ + browser.assert.urlContains('/redaxo/index.php?page=structure'); + + /** + * Add a start article if empty... + */ + browser.getText('css selector', 'section.rex-page-section:last-of-type table tbody tr:last-of-type td:nth-of-type(3)', function (result) { + if (result.value === '') { + browser.navigateTo('/redaxo/index.php?page=structure&category_id=0&article_id=0&clang=1&function=add_art&artstart=0'); + browser.sendKeys('input[name=article-name]', ['nightwatch_test_start_article', browser.Keys.ENTER]); + browser.waitForElementPresent('#rex-message-container .alert.alert-success'); + } + }); + }); + + function activateMaintenance(browser) { + /** + * navigate to the settings page + * activate maintenance + */ + browser.navigateTo('/redaxo/index.php?page=maintenance/frontend'); + browser.click('.rex-page-main button[data-id="deakt-front"]'); + browser.click('.rex-page-main #bs-select-1-1'); + } + + it('maintenance url secret - 503', function (browser) { + activateMaintenance(browser); + + /** + * set secret + */ + browser.updateValue('input#rex-maintenance-secret-secret-we-got-a-secret', 'nightwatch_secret'); + + /** + * set 503 response code + */ + browser.click('.rex-page-main button[data-id="responsecode"]'); + browser.click('.rex-page-main #bs-select-3-0'); + + browser.click('#rex-maintenance-save'); + + /** + * logout + */ + logout(browser); + + /** + * navigate to the frontend + */ + browser.navigateTo(this.settings.launchUrl); + + /** + * test if maintenance is active + */ + browser.assert.elementPresent('.maintenance-container', 'maintenance-container should exist'); + browser.assert.textContains('.maintenance-error-title', 'Maintenance', 'maintenance-error-title should contain "Maintenance"'); + browser.assert.textContains('.maintenance-error-message', 'This website is temporarily unavailable', 'maintenance-error-message should contain "This website is temporarily unavailable"'); + browser.perform(async () => { + try { + const response = await got(browser.launchUrl, { followRedirect: false }); + browser.assert.equal(response.statusCode, 503, 'Status code should be 503'); + } catch (error) { + browser.assert.equal(error.response.statusCode, 503, 'Status code should be 503'); + } + return true; + }); + + /** + * test maintenance secret + */ + browser.navigateTo('/?secret=nightwatch_secret'); + browser.perform(async () => { + try { + const response = await got(browser.launchUrl + '?secret=nightwatch_secret', { followRedirect: false }); + browser.assert.equal(response.statusCode, 200, 'Status code should be 200'); + } catch (error) { + browser.assert.equal(error.response.statusCode, 200, 'Status code should be 200'); + } + return true; + }); + browser.assert.not.elementPresent('.maintenance-container', 'maintenance-container should not exist'); + }) + + it('maintenance url secret - 403', function (browser) { + activateMaintenance(browser); + + /** + * set secret + */ + browser.updateValue('input#rex-maintenance-secret-secret-we-got-a-secret', 'nightwatch_secret'); + + /** + * set 403 response code + */ + browser.click('.rex-page-main button[data-id="responsecode"]'); + browser.click('.rex-page-main #bs-select-3-1'); + + browser.click('#rex-maintenance-save'); + + /** + * logout + */ + logout(browser); + + /** + * navigate to the frontend + */ + browser.navigateTo(this.settings.launchUrl); + + /** + * test if maintenance is active + */ + browser.assert.elementPresent('.maintenance-container', 'maintenance-container should exist'); + browser.assert.textContains('.maintenance-error-title', 'Maintenance', 'maintenance-error-title should contain "Maintenance"'); + browser.assert.textContains('.maintenance-error-message', 'This website is temporarily unavailable', 'maintenance-error-message should contain "This website is temporarily unavailable"'); + browser.perform(async () => { + try { + const response = await got(browser.launchUrl, { followRedirect: false }); + browser.assert.equal(response.statusCode, 403, 'Status code should be 403'); + } catch (error) { + browser.assert.equal(error.response.statusCode, 403, 'Status code should be 403'); + } + return true; + }); + + /** + * test maintenance secret + */ + browser.navigateTo('/?secret=nightwatch_secret'); + browser.perform(async () => { + try { + const response = await got(browser.launchUrl + '?secret=nightwatch_secret', { followRedirect: false }); + browser.assert.equal(response.statusCode, 200, 'Status code should be 200'); + } catch (error) { + browser.assert.equal(error.response.statusCode, 200, 'Status code should be 200'); + } + return true; + }); + browser.assert.not.elementPresent('.maintenance-container', 'maintenance-container should not exist'); + }) + + it('maintenance password - 503', function (browser) { + /** + * navigate to the settings page + * activate maintenance + */ + activateMaintenance(browser); + + /** + * set secret + */ + browser.updateValue('input#rex-maintenance-secret-secret-we-got-a-secret', 'nightwatch_secret'); + + /** + * set 503 response code + */ + browser.click('.rex-page-main button[data-id="responsecode"]'); + browser.click('.rex-page-main #bs-select-3-0'); + + /** + * activate password + */ + browser.click('.rex-page-main button[data-id="type"]'); + browser.click('.rex-page-main #bs-select-2-1'); + browser.click('#rex-maintenance-save'); + + /** + * logout + */ + logout(browser); + + /** + * navigate to the frontend + */ + browser.navigateTo(this.settings.launchUrl); + + // /** + // * test if maintenance is active + // */ + browser.assert.elementPresent('.maintenance-pw-input', 'maintenance-pw-input should exist'); + browser.perform(async () => { + try { + const response = await got(browser.launchUrl, { followRedirect: false }); + browser.assert.equal(response.statusCode, 503, 'Status code should be 503'); + } catch (error) { + browser.assert.equal(error.response.statusCode, 503, 'Status code should be 503'); + } + return true; + }); + browser.updateValue('.maintenance-pw-input', 'nightwatch_secret'); + browser.sendKeys('.maintenance-pw-input', [browser.Keys.ENTER]); + browser.assert.not.elementPresent('.maintenance-pw-input', 'maintenance-pw-input should not exist'); + }) + + it('maintenance password - 403', function (browser) { + /** + * navigate to the settings page + * activate maintenance + */ + activateMaintenance(browser); + + /** + * set secret + */ + browser.updateValue('input#rex-maintenance-secret-secret-we-got-a-secret', 'nightwatch_secret'); + + /** + * set 403 response code + */ + browser.click('.rex-page-main button[data-id="responsecode"]'); + browser.click('.rex-page-main #bs-select-3-1'); + + /** + * activate password + */ + browser.click('.rex-page-main button[data-id="type"]'); + browser.click('.rex-page-main #bs-select-2-1'); + browser.click('#rex-maintenance-save'); + + /** + * logout + */ + logout(browser); + + /** + * navigate to the frontend + */ + browser.navigateTo(this.settings.launchUrl); + + // /** + // * test if maintenance is active + // */ + browser.assert.elementPresent('.maintenance-pw-input', 'maintenance-pw-input should exist'); + browser.perform(async () => { + try { + const response = await got(browser.launchUrl, { followRedirect: false }); + browser.assert.equal(response.statusCode, 403, 'Status code should be 403'); + } catch (error) { + browser.assert.equal(error.response.statusCode, 403, 'Status code should be 403'); + } + return true; + }); + browser.updateValue('.maintenance-pw-input', 'nightwatch_secret'); + browser.sendKeys('.maintenance-pw-input', [browser.Keys.ENTER]); + browser.assert.not.elementPresent('.maintenance-pw-input', 'maintenance-pw-input should not exist'); + }) + + /** + * reset maintenance settings + */ + afterEach(browser => { + /** + * login + */ + login(browser); + + browser.pause(200); + + /** + * reset settings + */ + browser.navigateTo('/redaxo/index.php?page=maintenance/frontend'); + browser.pause(200); + browser.updateValue('input#rex-maintenance-secret-secret-we-got-a-secret', ''); + browser.sendKeys('input#rex-maintenance-secret-secret-we-got-a-secret', [browser.Keys.ENTER]); + browser.pause(250); + browser.click('.rex-page-main button.dropdown-toggle'); + browser.pause(250); + browser.click('.rex-page-main #bs-select-1-0'); + browser.pause(250); + browser.click('#rex-maintenance-save'); + browser.pause(250); + + logout(browser); + browser.end(); + }); + + /** + * close the browser + */ + after(browser => { + }); +});