From 7beb8926cf3e0e06a8ed363197c73d071c0eacce Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 4 Mar 2024 23:57:07 +1100 Subject: [PATCH 01/10] Dev tools scripts --- .codepipeline/docker/cmfive_dev_tools.sh | 15 ++++ .codepipeline/docker/install_dev_tools.sh | 83 +++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100755 .codepipeline/docker/cmfive_dev_tools.sh create mode 100755 .codepipeline/docker/install_dev_tools.sh diff --git a/.codepipeline/docker/cmfive_dev_tools.sh b/.codepipeline/docker/cmfive_dev_tools.sh new file mode 100755 index 0000000..293652d --- /dev/null +++ b/.codepipeline/docker/cmfive_dev_tools.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# To be run on the container, see install_dev_tools.sh +set -e + +echo "🏗️ Installing required system packages" +apk add --no-cache php81-dom php81-xmlwriter php81-tokenizer php81-ctype mysql-client mariadb-connector-c-dev bash + +echo "🔨 Installing phpunit v${PHPUNIT}" +cd /usr/local/bin && curl -L https://phar.phpunit.de/phpunit-${PHPUNIT}.phar -o phpunit && chmod +x phpunit && chmod 777 . + +echo "🔨 Installing codeception" +chown -R cmfive:cmfive /var/www/html/test +cd /var/www/html/test/ && sh ./.install/install.sh + +# NOTE: Playwright is not recommended to be installed here diff --git a/.codepipeline/docker/install_dev_tools.sh b/.codepipeline/docker/install_dev_tools.sh new file mode 100755 index 0000000..31324a3 --- /dev/null +++ b/.codepipeline/docker/install_dev_tools.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# Installs the dev tools to the desired cmfive container + +## USAGE: +# If you have docker compose running: +# ./install_dev_tools.sh +# Or specify container name: +# CONTAINER=cmfive_webapp_1 ./install_dev_tools.sh +# To skip playwright dependencies: +# SKIP_PLAYWRIGHT=true ./install_dev_tools.sh + +#Settings +PHPUNIT=10 + +# If CONTAINER is not defined, default to the container name of the webapp service in docker compose +if [ -z "$CONTAINER" ]; then + CONTAINER=$(docker compose ps -q webapp) + if [ -z "$CONTAINER" ]; then + echo "❌ Error: Could not find container name. Please specify the container name with CONTAINER=container_name" + exit 1 + fi + echo "💭 Using container from docker compose" +fi + +# Check if $CONTAINER is a valid container name or id +if ! docker inspect --type=container "$CONTAINER" >/dev/null 2>&1; then + echo "❌ Error: Invalid container name or id: $CONTAINER" + exit 1 +fi + +echo "" +echo "👷 -- Installing dev tools to container: $CONTAINER --" +echo "" + +# Copy cmfive_dev_tools +SCRIPT_DIR=$(dirname "$0") +docker cp "$SCRIPT_DIR/cmfive_dev_tools.sh" "$CONTAINER:/home/cmfive" +if [ $? -ne 0 ]; then + echo "❌ Error: Could not copy cmfive_dev_tools.sh to container" + exit 1 +fi + +# Run cmfive_dev_tools +docker exec $CONTAINER sh -c "PHPUNIT=${PHPUNIT} /home/cmfive/cmfive_dev_tools.sh" +if [ $? -ne 0 ]; then + echo "❌ Error: cmfive_dev_tools.sh failed" + exit 1 +fi + +echo "" +echo "👷 -- Installing host machine dev tools --" +echo "" + +# If SKIP_PLAYWRIGHT is true skip the rest of the script +if [ "$SKIP_PLAYWRIGHT" = true ]; then + echo "✔️ Dev tools installed successfully" + exit 0 +fi + +# --- Install Playwright dependencies --- +echo "🔨 Installing Playwright dependencies" + +# If not Debian or Ubuntu exit the script +if ! command -v apt-get &> /dev/null; then + echo "⚠️ WARNING: Playwright dependencies are only supported on Debian and Ubuntu" + echo "✔️ Dev tools installed successfully" + exit 0 +fi + +# Check if npm is installed on host machine +if ! command -v npm &> /dev/null; then + echo "⚠️ WARNING: npm is not installed on this machine. Please install npm and run 'npm install' in the test directory" + echo "✔️ Dev tools installed successfully" + exit 0 +fi + +yes | npx playwright install --with-deps +if [ $? -ne 0 ]; then + echo "❌ Error: Failed to install Playwright dependencies" + exit 1 +fi + +echo "✔️ Dev tools installed successfully" From c3a5e8d1abaeb3a2226b315aac2c0f3b78ed4ff9 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 4 Mar 2024 23:57:46 +1100 Subject: [PATCH 02/10] Refactor unit test file paths to include module directory --- cmfiveTests.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmfiveTests.php b/cmfiveTests.php index 7ac36fd..cd74fc7 100644 --- a/cmfiveTests.php +++ b/cmfiveTests.php @@ -690,8 +690,12 @@ function getTestsForModule($module) $details['actor'] = rtrim($file, ".php"); } if ($ext == UNIT_DIRECTORY) { - $modFile = $module . "_" . $file; + $modFile = $module . "/" . $file; $details['unit'] = $modFile; + //Create $module directory if it doesn't exist + if (!is_dir(ROOT_PATH . DS . $dest_paths[$ext] . DS . $module)) { + mkdir(ROOT_PATH . DS . $dest_paths[$ext] . DS . $module); + } } if ($ext == $findActor) { $details['actor'] = rtrim($file, ".php"); From 31c68913b4669dcb5947230b6c2182ad76a38e3f Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 5 Mar 2024 00:10:53 +1100 Subject: [PATCH 03/10] Add php version --- .codepipeline/docker/cmfive_dev_tools.sh | 2 +- .codepipeline/docker/install_dev_tools.sh | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.codepipeline/docker/cmfive_dev_tools.sh b/.codepipeline/docker/cmfive_dev_tools.sh index 293652d..24df7e7 100755 --- a/.codepipeline/docker/cmfive_dev_tools.sh +++ b/.codepipeline/docker/cmfive_dev_tools.sh @@ -3,7 +3,7 @@ set -e echo "🏗️ Installing required system packages" -apk add --no-cache php81-dom php81-xmlwriter php81-tokenizer php81-ctype mysql-client mariadb-connector-c-dev bash +apk add --no-cache php$PHPVERSION-dom php$PHPVERSION-xmlwriter php$PHPVERSION-tokenizer php$PHPVERSION-ctype mysql-client mariadb-connector-c-dev bash echo "🔨 Installing phpunit v${PHPUNIT}" cd /usr/local/bin && curl -L https://phar.phpunit.de/phpunit-${PHPUNIT}.phar -o phpunit && chmod +x phpunit && chmod 777 . diff --git a/.codepipeline/docker/install_dev_tools.sh b/.codepipeline/docker/install_dev_tools.sh index 31324a3..fd32f28 100755 --- a/.codepipeline/docker/install_dev_tools.sh +++ b/.codepipeline/docker/install_dev_tools.sh @@ -10,6 +10,7 @@ # SKIP_PLAYWRIGHT=true ./install_dev_tools.sh #Settings +PHPVERSION=81 PHPUNIT=10 # If CONTAINER is not defined, default to the container name of the webapp service in docker compose @@ -41,7 +42,7 @@ if [ $? -ne 0 ]; then fi # Run cmfive_dev_tools -docker exec $CONTAINER sh -c "PHPUNIT=${PHPUNIT} /home/cmfive/cmfive_dev_tools.sh" +docker exec $CONTAINER sh -c "PHPUNIT=${PHPUNIT} PHPVERSION=${PHPVERSION} /home/cmfive/cmfive_dev_tools.sh" if [ $? -ne 0 ]; then echo "❌ Error: cmfive_dev_tools.sh failed" exit 1 From 07333cb0412790771b4775fef2036e0266b6c2b7 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 5 Mar 2024 09:40:11 +1100 Subject: [PATCH 04/10] Copy test dir --- .codepipeline/docker/install_dev_tools.sh | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.codepipeline/docker/install_dev_tools.sh b/.codepipeline/docker/install_dev_tools.sh index fd32f28..b1cb5aa 100755 --- a/.codepipeline/docker/install_dev_tools.sh +++ b/.codepipeline/docker/install_dev_tools.sh @@ -29,6 +29,35 @@ if ! docker inspect --type=container "$CONTAINER" >/dev/null 2>&1; then exit 1 fi +# Tell user if test dir already exists in container +if docker exec $CONTAINER test -d /var/www/html/test/.install; then + echo "💭 Test directory exists in the container" +else + # Find test dir + TEST_DIR="" + if test -d "./test"; then + TEST_DIR="./test" + elif test -d "../test"; then + TEST_DIR="../test" + elif test -d "../../test"; then + TEST_DIR="../../test" + fi + # If test dir is found and the container doesnt have an existing test dir, copy it + if [ -n "$TEST_DIR" ] ; then + echo "💭 Using test directory: $TEST_DIR" + echo "📦 Copying test directory to container" + docker cp "$TEST_DIR" "$CONTAINER:/var/www/html" + if [ $? -ne 0 ]; then + echo "❌ Error: Could not copy test directory to container" + exit 1 + fi + else + # If test dir is not found, exit the script + echo "❌ Error: Could not find test directory" + exit 1 + fi +fi + echo "" echo "👷 -- Installing dev tools to container: $CONTAINER --" echo "" From 98bf4d727f560e7c904406976373d924dfd7e71c Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 5 Mar 2024 15:06:05 +1100 Subject: [PATCH 05/10] Remove selenium and codeception --- .codepipeline/docker/cmfive_dev_tools.sh | 4 -- .codepipeline/docker/config.default.php | 44 ------------------- .../test_agent/configs/test_agent-config.php | 37 ---------------- Testing.Dockerfile | 27 ++++++++++++ docker-compose.yml | 15 ------- 5 files changed, 27 insertions(+), 100 deletions(-) create mode 100644 Testing.Dockerfile diff --git a/.codepipeline/docker/cmfive_dev_tools.sh b/.codepipeline/docker/cmfive_dev_tools.sh index 24df7e7..61bba19 100755 --- a/.codepipeline/docker/cmfive_dev_tools.sh +++ b/.codepipeline/docker/cmfive_dev_tools.sh @@ -8,8 +8,4 @@ apk add --no-cache php$PHPVERSION-dom php$PHPVERSION-xmlwriter php$PHPVERSION-to echo "🔨 Installing phpunit v${PHPUNIT}" cd /usr/local/bin && curl -L https://phar.phpunit.de/phpunit-${PHPUNIT}.phar -o phpunit && chmod +x phpunit && chmod 777 . -echo "🔨 Installing codeception" -chown -R cmfive:cmfive /var/www/html/test -cd /var/www/html/test/ && sh ./.install/install.sh - # NOTE: Playwright is not recommended to be installed here diff --git a/.codepipeline/docker/config.default.php b/.codepipeline/docker/config.default.php index 01185c0..c8a4e62 100644 --- a/.codepipeline/docker/config.default.php +++ b/.codepipeline/docker/config.default.php @@ -59,50 +59,6 @@ Config::set("system.environment", "development"); Config::set("core_template.foundation.reveal.animation", "none"); Config::set("core_template.foundation.reveal.animation_speed", 0); -//========== must be "ENABLED" to run ========================== -//========== "config" will pass through to CmfiveSite helper === -Config::set('system.environment', "development"); -Config::set( - "tests", - [ - "testrunner" => "ENABLED", - "config" => '', - "yaml" => - [ - "- WebDriver:" => - [ - "url" => "http://webapp:3000", - "browser" => "chrome", - "wait" => "8", - "host" => "seleniumDrv", - "port" => "4444", - "capabilities" => - [ - "acceptInsecureCerts" => true, - "goog:chromeOptions" => [ - "w3c" => "false", - "args" => '[' - .'"--headless=new","--disable-gpu",' - .'"-proxy-bypass-list=*","--proxy-server=direct://","--dns-prefetch-disable",' - .'"--disk-cache-size=0","–-media-cache-size=0",' - .'"--window-size=1920,1200","--disable-remote-fonts",' - .'"--ignore-certificate-errors","--disable-extensions","--no-sandbox",' - // .'"--enable-logging=/var/customlog/ch.log","--v=1' - .'"--disable-dev-shm-usage"' - .']' - ] - ] - ], - "- Db:" => - [ - "dsn" => "mysql:host=mysqldb:3306;dbname=cmfive", - "user" => "cmfive", - "password" => "cmfive", - ], - "- Asserts:" => "", - ] - ] -); //========= Anonymous Access ================================ // bypass authentication if sent from the following IP addresses diff --git a/.codepipeline/test_agent/configs/test_agent-config.php b/.codepipeline/test_agent/configs/test_agent-config.php index d73aec8..884bb1a 100644 --- a/.codepipeline/test_agent/configs/test_agent-config.php +++ b/.codepipeline/test_agent/configs/test_agent-config.php @@ -60,43 +60,6 @@ Config::set("system.environment", "development"); Config::set("core_template.foundation.reveal.animation", "none"); Config::set("core_template.foundation.reveal.animation_speed", 0); -//========== must be "ENABLED" to run ========================== -Config::set( - "tests", - [ - "testrunner" => "", - "config" => '', - "yaml" => - [ - "- WebDriver:" => - [ - "url" => "http://webapp:3000", - "browser" => "chrome", - "wait" => "60", - "host" => "seleniumDrv", - "port" => "4444", - "capabilities" => - [ - "acceptInsecureCerts" => true, - "goog:chromeOptions" => [ - "w3c" => "false", - "args" => '["--headless","--disable-gpu","--window-size=1920,1200","--ignore-certificate-errors","--disable-extensions","--no-sandbox","--disable-dev-shm-usage"]' - ] - ] - ], - "- Db:" => - [ - "dsn" => (getenv('DB') ?: 'mysql') - . ":host=" . (getenv('DB_HOST') ?: 'localhost') - . ":" . (getenv('DB_PORT') ?: '') - . ";dbname=" . (getenv('DB_DATABASE') ?: ''), - "user" => (getenv('DB_USERNAME') ?: ''), - "password" => (getenv('DB_PASSWORD') ?: ''), - ], - "- Asserts:" => "", - ] - ] -); //========= Anonymous Access ================================ // bypass authentication if sent from the following IP addresses diff --git a/Testing.Dockerfile b/Testing.Dockerfile new file mode 100644 index 0000000..17f9589 --- /dev/null +++ b/Testing.Dockerfile @@ -0,0 +1,27 @@ +# Change this to a PR build if you need to (eg ghcr.io/2pisoftware/cmfive:pr-117) +FROM ghcr.io/2pisoftware/cmfive:develop + +# Change this to a different branch or comment out to use the one built in to the image +ENV CMFIVE_CORE_BRANCH=develop + +# Install required packages for testing +USER root +RUN apk add --no-cache php81-dom php81-xmlwriter php81-tokenizer php81-ctype mysql-client mariadb-connector-c-dev bash + +# Copy test dir +ADD test/ /var/www/html/test/ + +# Install phpunit +ENV PHPUNIT=8 +RUN cd /usr/local/bin && curl -L https://phar.phpunit.de/phpunit-${PHPUNIT}.phar -o phpunit && chmod +x phpunit && chmod 777 . + +# Install codeception +RUN chown -R cmfive:cmfive /var/www/html/test +USER cmfive +RUN ls -la /var/www/html/test +RUN cd /var/www/html/test/ && sh ./.install/install.sh + +# Install NodeJS and Playwright +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash &&\ + nvm install 18 **\ + npx playwright install --with-deps \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 18b8ad7..048b8f1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,8 +37,6 @@ services: - ENVIRONMENT=development volumes: - ./:/var/www/html:rw - - ./test/Codeception/tests/boilerplate:/var/www/html/test/Codeception/tests/boilerplate - - ./test/Codeception/tests/_output:/var/www/html/test/Codeception/tests/_output ports: - "3000:80" - "3443:443" @@ -74,19 +72,6 @@ services: webapp: condition: service_healthy - seleniumsrv: - image: selenium/standalone-chrome:111.0 - container_name: seleniumDrv - hostname: seleniumDrv - ports: - - "4444:4444" - environment: - - TZ=Australia/Sydney - - START_XVFB=false - shm_size: '4gb' - networks: - - default - volumes: dbdata: driver: local From fa7ba8a7731dacaa5946595365cab0a1a7de43c3 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 5 Mar 2024 15:11:25 +1100 Subject: [PATCH 06/10] Remove codeception files --- test/.install/install.sh | 26 -- test/Codeception/.gitignore | 19 -- test/Codeception/readme.txt | 48 ---- test/Codeception/tests/_data/.gitkeep | 0 .../tests/boilerplate/CmfiveUI.php | 178 ------------- .../boilerplate/acceptance/BoilerCest.php | 18 -- .../boilerplate/acceptance/HelperCest.php | 28 -- .../acceptance/helpers/CmfiveSite.php | 243 ------------------ 8 files changed, 560 deletions(-) delete mode 100755 test/.install/install.sh delete mode 100644 test/Codeception/.gitignore delete mode 100644 test/Codeception/readme.txt delete mode 100644 test/Codeception/tests/_data/.gitkeep delete mode 100755 test/Codeception/tests/boilerplate/CmfiveUI.php delete mode 100755 test/Codeception/tests/boilerplate/acceptance/BoilerCest.php delete mode 100755 test/Codeception/tests/boilerplate/acceptance/HelperCest.php delete mode 100755 test/Codeception/tests/boilerplate/acceptance/helpers/CmfiveSite.php diff --git a/test/.install/install.sh b/test/.install/install.sh deleted file mode 100755 index fe3d6a0..0000000 --- a/test/.install/install.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -#setup for Codeception: - -SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -cd "${SCRIPTPATH}/../Codeception" - -export COMPOSER_ALLOW_SUPERUSER=1 ; -curl -sS https://getcomposer.org/installer | php -- \ - --filename=composer \ - --install-dir=. ; - -./composer -q require codeception/codeception:5.0.10 --dev ; -./composer config minimum-stability dev - -./composer require -W --no-update codeception/module-asserts:3.0.0 \ -codeception/module-db:3.1.0 \ -codeception/module-webdriver:4.0.0 \ -codeception/module-phpbrowser:3.0.0 - -./composer update --prefer-source --no-interaction --no-progress --optimize-autoloader --ansi; - -php vendor/bin/codecept bootstrap; - -chmod -R 777 tests/* ; -# mkdir tests/acceptance; diff --git a/test/Codeception/.gitignore b/test/Codeception/.gitignore deleted file mode 100644 index 33b3362..0000000 --- a/test/Codeception/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ - -!.gitignore - -/tests/_support/ -/tests/_output/ -/tests/acceptance - -/tests/acceptance.suite.yml -/tests/acceptance.suite.dist.yml - -codeception.yml - - -### Composer ### -composer.phar -composer.lock -/vendor/ - - diff --git a/test/Codeception/readme.txt b/test/Codeception/readme.txt deleted file mode 100644 index b24e9eb..0000000 --- a/test/Codeception/readme.txt +++ /dev/null @@ -1,48 +0,0 @@ - -* Check 'acceptance.suite.dist.yml' is prototyped in cmfive config.php, for your servers: -``` -class_name: CmfiveUI - -modules: - enabled: - - WebDriver: - url: http://cmfive.local - browser: chrome - wait: 60 - port: 4444 - -``` -1) replace 'http://cmfive.local' with the url of your site to be tested (including protocol) -2) replace the port with appropriate Webdriver, see 'tests\services': - --------------------------------------------------- - Follow Installation Instructions - --> https://codeception.com/docs/modules/WebDriver#Selenium - --> https://codeception.com/docs/modules/WebDriver#ChromeDriver - Enable RunProcess extension to start/stop Selenium automatically (optional). - -Check versions in tests/services: -Launch ChromeDriver = defaults to 9515 -Launch Selenium JAR = defaults to 4444 (Selenium can find/launch ChromeDriver automatically if they are in same folder) - --------------------------------------------------- - -# Writing Tests -Tests go in: - /system/modules/[module] (to test core modules&models) - /system/tests/workflows (to test highly compound workflows from actions, eg:Selenium tests) - /modules/[module] (to test eg:CRM modules&models) - boilerplate/test/Codeception/tests/boilerplate (to test "bare metal" cm5) - -# Running Tests -see --> https://codeception.com/docs/reference/Commands - -Running is generally automated by cmfive-boilerplate\cmfiveTests.php -See: cmfive-boilerplate\test\Guide.txt - -# Configuration - -Config is generally automated by cmfive-boilerplate\cmfiveTests.php - -codeception has a hierarchical configuration system. - - suite.yml -> suite.dist.yml -> codeception.yml -> codeception.dist.yml -dist configuration files are committed to git and contain generic common configuration. non dist configuration files are not committed to git and contain configuration specific to a developer's setup diff --git a/test/Codeception/tests/_data/.gitkeep b/test/Codeception/tests/_data/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/Codeception/tests/boilerplate/CmfiveUI.php b/test/Codeception/tests/boilerplate/CmfiveUI.php deleted file mode 100755 index 1763293..0000000 --- a/test/Codeception/tests/boilerplate/CmfiveUI.php +++ /dev/null @@ -1,178 +0,0 @@ - $fieldValue) { - $fieldNameParts = explode(':', $fieldName); - if ($fieldNameParts[0] == 'check' && count($fieldNameParts) > 1) { - if ($fieldValue) { - $this->checkOption('#' . $fieldNameParts[1]); - } else { - $this->uncheckOption('#' . $fieldNameParts[1]); - } - } elseif (($fieldNameParts[0] == 'select' || $fieldNameParts[0] == 'radio') && count($fieldNameParts) > 1) { - $this->wait(1); - $this->waitForElement('#' . $fieldNameParts[1], 2); - $this->wait(1); - $this->waitForElement('#' . $fieldNameParts[1], 2); - //$this->click("//select[@id='{$fieldNameParts[1]}']"); - $this->selectOption('#' . $fieldNameParts[1], $fieldValue); - // add a moment for response scripts to kick - $this->wait(1); - } elseif ($fieldNameParts[0] == 'date' && count($fieldNameParts) > 1) { - $this->fillDatePicker($fieldNameParts[1], $fieldValue); - } elseif ($fieldNameParts[0] == 'datetime' && count($fieldNameParts) > 1) { - $this->fillDateTimePicker($fieldNameParts[1], $fieldValue); - } elseif ($fieldNameParts[0] == 'time' && count($fieldNameParts) > 1) { - $this->fillTimePicker($fieldNameParts[1], $fieldValue); - } elseif ($fieldNameParts[0] == 'rte' && count($fieldNameParts) > 1) { - $this->fillCkEditorById($fieldNameParts[1], $fieldValue); - } elseif ($fieldNameParts[0] == 'autocomplete' && count($fieldNameParts) > 1) { - $this->fillAutocomplete($fieldNameParts[1], $fieldValue); - } elseif ($fieldNameParts[0] == 'vModelAutocomplete' && count($fieldNameParts) > 1) { - $this->wait(1); - $this->waitForElement("(//div[@id = '".$fieldNameParts[1]."'])/input", 2); - $this->fillField("(//div[@id = '".$fieldNameParts[1]."'])/input", $fieldValue); - } else { - $this->fillField('#' . $fieldName, $fieldValue); - } - } - } - } - - public function findTableRowMatching($columnNumber, $matchValue) - { - if ($this->isUsingBootstrap5($this)) { - $rows = $this->grabMultiple('.table-responsive ul li:nth-child(' . $columnNumber . ')'); - if (count($rows) == 0) { - $rows = $this->grabMultiple(".table-responsive table tbody tr td:nth-child(" . $columnNumber . ")"); - } - if (count($rows) == 0) { - $rows = $this->grabMultiple(".tablesorter tbody tr td:nth-child(" . $columnNumber . ")"); - } - if (is_array($rows)) { - foreach ($rows as $k => $v) { - if (trim($v) == trim($matchValue)) { - return $k + 1; - } - } - } - return false; - } else { - $rows = $this->grabMultiple('.tablesorter tbody tr td:nth-child(' . $columnNumber . ')'); - if (count($rows) == 0) { // but what if it was a resized non-sorting table?? - $rows = $this->grabMultiple("//table/tbody/tr/td[" . $columnNumber . "]"); - } - if (is_array($rows)) { - foreach ($rows as $k => $v) { - if (trim($v) == trim($matchValue)) { - return $k + 1; - } - } - } - return false; - } - } - -/******************************************************* - * http://stackoverflow.com/questions/29168107/how-to-fill-a-rich-text-editor-field-for-a-codeception-acceptance-test - *******************************************************/ - public function fillCkEditorById($element_id, $content) - { - $this->fillRteEditor(\Facebook\WebDriver\WebDriverBy::cssSelector( - '#cke_' . $element_id . ' .cke_wysiwyg_frame' - ), $content); - } - - public function fillCkEditorByName($element_name, $content) - { - $this->fillRteEditor(\Facebook\WebDriver\WebDriverBy::cssSelector( - 'textarea[name="' . $element_name . '"] + .cke .cke_wysiwyg_frame' - ), $content); - } - - public function fillRteEditor($selector, $content) - { - $this->executeInSelenium( - function (\Facebook\WebDriver\Remote\RemoteWebDriver $webDriver) use ($selector, $content) { - $webDriver->wait(3); - $webDriver->switchTo()->frame( - $webDriver->findElement($selector) - ); - - $webDriver->executeScript( - 'arguments[0].innerHTML = "' . addslashes($content) . '"', - [$webDriver->findElement(\Facebook\WebDriver\WebDriverBy::tagName('body'))] - ); - - $webDriver->switchTo()->defaultContent(); - } - ); - } - - public function fillDatePicker($field, $date) - { - $dateFormatted = date('d/m/Y H:i', $date); - $finalDateFormatted = date('d/m/Y', $date); - $this->executeJS('$("#' . $field . '").datepicker("setDate","' . $dateFormatted . '");'); - $this->wait(1); - $this->seeInField('#' . $field, $finalDateFormatted); - } - - public function fillDateTimePicker($field, $date) - { - $dateFormatted = date('d/m/Y H:i', $date); - $finalDateTimeFormatted = date('d/m/Y h:i a', $date); - $this->executeJS('$("#' . $field . '").datepicker("setDate","' . $dateFormatted . '");'); - $this->wait(1); - $this->seeInField('#' . $field, $finalDateTimeFormatted); - } - - public function fillTimePicker($field, $date) - { - $dateFormatted = date('d/m/Y H:i', $date); - $finalTimeFormatted = date('h:i a', $date); - $this->executeJS('$("#' . $field . '").datepicker("setDate","' . $dateFormatted . '");'); - $this->wait(1); - $this->seeInField('#' . $field, $finalTimeFormatted); - } - - public function fillAutocomplete($field, $value) - { - $this->executeJS("$('#acp_{$field}').autocomplete('search', '{$value}')"); - // pause & believe the UI entry exists - $this->waitForText($value); - //$this->click($value, '.ui-menu-item'); - // this way is more resilient regards 'focus' & timing? - $this->click("//li[contains(@class,'ui-menu-item')]/a[contains(text(),'{$value}')]"); - } -} diff --git a/test/Codeception/tests/boilerplate/acceptance/BoilerCest.php b/test/Codeception/tests/boilerplate/acceptance/BoilerCest.php deleted file mode 100755 index 8f08f96..0000000 --- a/test/Codeception/tests/boilerplate/acceptance/BoilerCest.php +++ /dev/null @@ -1,18 +0,0 @@ -loginAsAdmin($I); - } -} diff --git a/test/Codeception/tests/boilerplate/acceptance/HelperCest.php b/test/Codeception/tests/boilerplate/acceptance/HelperCest.php deleted file mode 100755 index 1a847d5..0000000 --- a/test/Codeception/tests/boilerplate/acceptance/HelperCest.php +++ /dev/null @@ -1,28 +0,0 @@ -getCodeceptionModuleList(); - echo "\n --- Helper Functions ---\n"; - foreach ($active as $module) { - $class = new ReflectionClass($module); - $methods = $class->getMethods(); - foreach($methods as $method) { - if(strpos($method->class, "Helper") !== false ) { - echo $method->class."::".$method->name."\n"; - //" --> ".$method->getDocComment()."\n"; - } - } - } - echo "\n"; - } -} diff --git a/test/Codeception/tests/boilerplate/acceptance/helpers/CmfiveSite.php b/test/Codeception/tests/boilerplate/acceptance/helpers/CmfiveSite.php deleted file mode 100755 index fce530c..0000000 --- a/test/Codeception/tests/boilerplate/acceptance/helpers/CmfiveSite.php +++ /dev/null @@ -1,243 +0,0 @@ -getTestDB(); - $this->runMigrations(); - } - - private function _useCmFiveSetup($param) - { - $rootDIR = $this->config['boilerplatePath'] . DIRECTORY_SEPARATOR; - $Mcommand = "cd " . $rootDIR . " && php " . $rootDIR - . $this->config['setupCommand'] . " " . $param; - echo "Running: " . $param . "\n"; - $exit = shell_exec($Mcommand); - echo $exit . "\n"; - return $exit; - } - - private function _useCmFiveDB($param) - { - $rootDIR = $this->config['boilerplatePath'] . DIRECTORY_SEPARATOR; - $Mcommand = "cd " . $rootDIR . " && php " . $rootDIR - . $this->config['DBCommand'] . " " . $param; - echo "DB task: " . $param . "\n"; - $exit = shell_exec($Mcommand); - echo $exit. "\n"; - return $exit; - } - - public function runMigrations() - { - $this->_useCmFiveSetup("install migrations"); - } - - /** Seed database with expected admin user profile */ - public function createTestAdminUser() - { - $adminAccount = - " " . $this->config['testAdminUsername'] . - " " . $this->config['testAdminPassword'] . - " " . $this->config['testAdminEmail'] . - " " . $this->config['testAdminFirstname'] . - " " . $this->config['testAdminLastname']; - $this->_useCmFiveSetup("seed admin " . $adminAccount); - } - - public function _wipeTestDB() - { - $this->_useCmFiveDB("purge"); - } - - public function getTestDB() - { - $this->assertNotContains("WARNING", [$this->_useCmFiveDB("test")]); - } - - public function putTestDB() - { - $this->_useCmFiveDB("sample"); - } - - - public function login($I, $username, $password) - { - $I->amOnPage('/auth/login'); - - // skip form filling if already logged in - if (strpos('/auth/login', $I->grabFromCurrentUrl()) !== false) { - $I->waitForElement('#login'); - $I->fillField('login', $username); - $I->fillField('password', $password); - $I->click('Login'); - } - } - - public function loginAsAdmin($I) - { - $this->login($I, $this->config['testAdminUsername'], $this->config['testAdminPassword']); - } - - - public function getUA_TestConfig() - { - return empty($this->config['UA_TestConfig']) ? [] : json_decode($this->config['UA_TestConfig'], true); - } - - public function getAdminUserName() - { - return $this->config['testAdminUsername']; - } - public function getAdminPassword() - { - return $this->config['testAdminPassword']; - } - public function getAdminFirstName() - { - return $this->config['testAdminFirstname']; - } - public function getAdminLastName() - { - return $this->config['testAdminLastname']; - } - - public function getDB_Settings() - { - $DB_set = []; - foreach ($this->config as $key => $value) { - if (substr($key, 0, 3) == "DB_") { - $DB_set[$key] = $value; - } - } - return $DB_set; - } - - public function getInstallPath() - { - return $this->config['boilerplatePath']; - } - - public function logout($I) - { - $I->amOnPage('/auth/logout'); - } - - public function isUsingBootstrap5($I) - { - try { - $I->seeElement('html.theme'); - return true; - } catch (\Exception $e) { - return false; - } - } - - public function clickCmfiveNavbar($I, $category, $link) - { - if ($this->isUsingBootstrap5($I)) { - // $I->waitForElement(".navbar-nav .nav-item .nav-link", 2); - // $I->click("#topnav_" . str_replace(" ", "_", strtolower($category)) . "_dropdown_link"); // ".navbar-nav .nav-item a.nav-link"); - - $I->waitForElementClickable(".//a[@id='topnav_" . str_replace(" ", "_", strtolower($category)) . "_dropdown_link']",2); - $I->click(".//a[@id='topnav_" . str_replace(" ", "_", strtolower($category)) . "_dropdown_link']"); - $I->click($link, "#topnav_" . str_replace(" ", "_", strtolower($category)) . "_dropdown_link + .dropdown-menu"); - $I->wait(1); - } else { - //$category, "section.top-bar-section ul.left" - $I->waitForElement("//section[@class='top-bar-section']/ul[@class='left']/li/a[contains(text(),'{$category}')]", 2); - $I->click("//section[@class='top-bar-section']/ul[@class='left']/li/a[contains(text(),'{$category}')]"); - // New designs now emerging on whole module (not just specific actions) - // So we should check if first step navbar click flipped us into BootStrap: - if ($this->isUsingBootstrap5($I)) { - $I->clickCmfiveNavbar($I, $category, $link); - return; - } - $I->moveMouseOver(['css' => '#topnav_' . strtolower($category)]); - $I->waitForText($link); - $I->click($link, '#topnav_' . strtolower($category)); - $I->wait(1); - } - } - - public function waitForBackendToRefresh($I) - { - $I->waitForElementNotVisible('.loading_overlay', 14); - } - - public function skipConfirmation($I) - { - // disable dialog - $I->executeJS('window.confirm = function(){return true;}'); - } - - - public function canUseCmfiveModule($module) - { - - $modules = $this->config['cmfiveModuleList']; - if (strpos($modules, ":" . $module . ":")) { - return true; - } - return false; - } - - public function getCodeceptionModuleList() - { - return $this->getModules(); - } - - public function getCmfiveModuleList() - { - return $this->config['cmfiveModuleList']; - } - - public function getPDOforCmfive() - { - return $this->getPDOConnection($this->getDB_Settings()); - } - - public function getPDOConnection($dbInfo) - { - // this gets us raw DB from cmfive config ... but only handles MYSQL! - $port = isset($dbInfo['DB_Port']) && !empty($dbInfo['DB_Port']) ? ";port=" . $dbInfo['DB_Port'] : ""; - $url = "{$dbInfo['DB_Driver']}:host={$dbInfo['DB_Hostname']};dbname={$dbInfo['DB_Database']}{$port}"; - return new \PDO( - $url, - $dbInfo['DB_Username'], - $dbInfo['DB_Password'], - array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'") - ); - } -} From 72266983723734774b26322782bc64115ffd9b3b Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 5 Mar 2024 15:34:13 +1100 Subject: [PATCH 07/10] Delete Testing.Dockerfile --- Testing.Dockerfile | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 Testing.Dockerfile diff --git a/Testing.Dockerfile b/Testing.Dockerfile deleted file mode 100644 index 17f9589..0000000 --- a/Testing.Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# Change this to a PR build if you need to (eg ghcr.io/2pisoftware/cmfive:pr-117) -FROM ghcr.io/2pisoftware/cmfive:develop - -# Change this to a different branch or comment out to use the one built in to the image -ENV CMFIVE_CORE_BRANCH=develop - -# Install required packages for testing -USER root -RUN apk add --no-cache php81-dom php81-xmlwriter php81-tokenizer php81-ctype mysql-client mariadb-connector-c-dev bash - -# Copy test dir -ADD test/ /var/www/html/test/ - -# Install phpunit -ENV PHPUNIT=8 -RUN cd /usr/local/bin && curl -L https://phar.phpunit.de/phpunit-${PHPUNIT}.phar -o phpunit && chmod +x phpunit && chmod 777 . - -# Install codeception -RUN chown -R cmfive:cmfive /var/www/html/test -USER cmfive -RUN ls -la /var/www/html/test -RUN cd /var/www/html/test/ && sh ./.install/install.sh - -# Install NodeJS and Playwright -RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash &&\ - nvm install 18 **\ - npx playwright install --with-deps \ No newline at end of file From abecfdb21b90c9897ddfafcd85ec29acb1b45764 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 5 Mar 2024 21:45:56 +1100 Subject: [PATCH 08/10] Remove selenium link on webapp --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 048b8f1..776b98b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -46,7 +46,6 @@ services: working_dir: /var/www/html links: - mysqldb - - seleniumsrv depends_on: mysqldb: condition: service_healthy From 7d8752a651b83ea8d41b2e31b2d80f0deb637e61 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 5 Mar 2024 22:29:29 +1100 Subject: [PATCH 09/10] Change test folder check --- .codepipeline/docker/install_dev_tools.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.codepipeline/docker/install_dev_tools.sh b/.codepipeline/docker/install_dev_tools.sh index b1cb5aa..5e8fe1b 100755 --- a/.codepipeline/docker/install_dev_tools.sh +++ b/.codepipeline/docker/install_dev_tools.sh @@ -29,8 +29,8 @@ if ! docker inspect --type=container "$CONTAINER" >/dev/null 2>&1; then exit 1 fi -# Tell user if test dir already exists in container -if docker exec $CONTAINER test -d /var/www/html/test/.install; then +# Tell user if test dir already exists in container (and has greater than 0 files) +if docker exec $CONTAINER sh -c 'test -d "/var/www/html/test" && test "$(ls -A /var/www/html/test | wc -l)" -gt 0'; then echo "💭 Test directory exists in the container" else # Find test dir From cdf3d5f8d18d330548bce76cdcb608cc36ddd3f4 Mon Sep 17 00:00:00 2001 From: DerekCrannaford <43056286+DerekCrannaford@users.noreply.github.com> Date: Thu, 14 Mar 2024 01:34:51 +0000 Subject: [PATCH 10/10] Strip back testrunner for unit tests only, 1st cut --- cmfiveTests.php | 328 +++++------------------------------------------- 1 file changed, 33 insertions(+), 295 deletions(-) diff --git a/cmfiveTests.php b/cmfiveTests.php index cd74fc7..9b00917 100644 --- a/cmfiveTests.php +++ b/cmfiveTests.php @@ -1,8 +1,6 @@ #!/bin/php 'admin', @@ -45,18 +36,6 @@ $sharedParam['boilerplatePath'] = getcwd(); -// 'loaded' will come from cmfive config -$loadedParam = [ - 'DB_Hostname' => "database.hostname", - 'DB_Port' => "database.port", - 'DB_Username' => "database.username", - 'DB_Password' => "database.password", - 'DB_Database' => "database.database", - 'DB_Driver' => "database.driver", - 'UA_TestConfig' => "tests.config" -]; - -defined('DEBUG_RUN') || define('DEBUG_RUN', "run --steps --debug Acceptance"); defined('PHPUNIT_RUN') || define('PHPUNIT_RUN', ""); ini_set('display_errors', 1); @@ -71,15 +50,6 @@ genericRunner($argc, $argv); } else { offerMenuTests(); - $cmdMaker['test'][] = - [ - 'request' => "run", 'message' => "Launching TestRunner", 'function' => "genericRunner", 'args' => true - ]; - $cmdMaker['tests'][] = - [ - 'request' => "run", 'message' => "Launching TestRunner", 'function' => "genericRunner", 'args' => true, - 'hint' => "module_FileNameCest.php silent" - ]; $cmdMaker['tests'][] = [ 'request' => "unit", 'message' => "Launching UnitTest", 'function' => "genericRunner", 'args' => true, @@ -88,7 +58,7 @@ $cmdMaker['tests'][] = [ 'request' => "module", 'message' => "Launching Tests on Module", 'function' => "genericRunner", 'args' => true, - 'hint' => "moduleName silent" + 'hint' => "moduleName" ]; $cmdMaker['testDB'][] = [ @@ -114,10 +84,15 @@ function offerMenuTests() ]; $found = chaseModules("all"); - ksort($found["Tests"]); + + // we cared a lot about this for ordered module names on accpetance tests + // but more generally, it seems an oblique insistence to sort only some test catagories? + // if(!empty($found['UnitTests'])) { + // ksort($found["UnitTests"]); + // } foreach ($found as $capabilities => $capability) { - if ($capabilities == "Tests") { + if ($capabilities == "UnitTests") { foreach ($capability as $module => $resources) { $menuMaker[] = [ @@ -126,51 +101,15 @@ function offerMenuTests() } } } - $menuMaker[] = - [ - 'option' => "Run all acceptance tests", 'message' => "Launching TestRunner", 'function' => "testRunner", 'param' => null - ]; $menuMaker[] = [ 'option' => "Run all unit tests", 'message' => "Launching UnitTests", 'function' => "unitTestRunner", 'param' => "all" ]; } -function moduleRunner($runModule, $silent = false) +function moduleRunner($runModule) { unitRunner($runModule); - purgeTestCode(); - registerConfig(); - $found = chaseModules("all"); - registerHelpers($found); - - $module_found = false; - - foreach ($found as $capabilities => $capability) { - if ($capabilities !== "Tests") { - continue; - } - - foreach ($capability as $module => $resources) { - if ($module !== $runModule) { - continue; - } - - $module_found = true; - - foreach ($resources as $resource) { - $codeCeptCommand = DEBUG_RUN . " " . $resource; - $packBar = "\nO" . str_repeat("-", strlen($codeCeptCommand) + 2) . "O\n"; - echo $packBar . "| " . $codeCeptCommand . " |" . $packBar; - $silent = launchCodecept($codeCeptCommand, $silent); - } - } - } - - if (!$module_found) { - echo "Error: Unable to find $runModule module\n"; - exit(1); - } } @@ -187,6 +126,8 @@ function unitRunner($run_module) if ($module == $run_module || $run_module == "all") { foreach ($resources as $resource) { $file_name = PHPUNIT_RUN . " " . UNIT_DESTINATION . DS . $resource . " "; + $packBar = "\n*" . str_repeat("-", strlen($file_name) + 12) . "*\n"; + echo $packBar . "| " . "\e[31m" . $file_name . " \e[39m| \e[31mTESTING \e[39m|" . $packBar; $output = []; $status_code = 0; @@ -195,9 +136,7 @@ function unitRunner($run_module) // If we received a non-zero status code, the test failed. Print the output to console. if ($status_code !== 0) { - $file_name = PHPUNIT_RUN . " " . UNIT_DESTINATION . DS . $resource . " "; - $packBar = "\n*" . str_repeat("-", strlen($file_name) + 11) . "*\n"; - echo $packBar . "| " . "\e[31m" . $file_name . " \e[39m| \e[31mFAILED \e[39m|" . $packBar; + echo $packBar . "| " . "\e[31m" . $file_name . " \e[39m| \e[31mFAILED! \e[39m|" . $packBar; foreach ($output as $o) { echo "\e[31m$o\n\e[39m"; @@ -216,10 +155,7 @@ function infoRunner() { genericRunner(null, null); } -function testRunner() -{ - genericRunner(2, ["", "run"]); -} + function unitTestRunner() { genericRunner(2, ["", "unit"]); @@ -232,26 +168,14 @@ function DBRunner() function genericRunner($argc, $argv) { purgeTestCode(); - registerConfig(); $found = chaseModules("all"); - registerHelpers($found); reportModules($found); - echo "\n --- To launch: --- \ncmfiveTests [run] [module_testfile.php] [silent]"; - echo "\n --- Or: --- \ncmfiveTests [unit] [module]\n\n"; + echo "\n --- To launch: --- \ncmfiveTests module [module]\n\n"; - $codeCeptCommand = DEBUG_RUN; if ($argc > 1) { - $silent = in_array("silent", $argv); switch (strtolower($argv[1])) { - case "run": - if ($argc > 2) { - $codeCeptCommand .= " " . $argv[2]; - } - - launchCodecept($codeCeptCommand, $silent); - break; case "unit": $unitModule = ""; if ($argc > 2) { @@ -264,7 +188,7 @@ function genericRunner($argc, $argv) if ($argc > 2) { $module = $argv[2]; } - moduleRunner($module, $silent); + moduleRunner($module); break; case "clean": purgeTestCode(); @@ -309,15 +233,13 @@ function checkTestEnvironment() { if ( - Config::get("tests.yaml.- WebDriver:") - && Config::get("tests.yaml.- Db:") - && Config::get("database.backups.commandPath") + Config::get("database.backups.commandPath") && Config::get("database.backups.backupCommand") && Config::get("database.backups.restoreCommand") ) { - echo "Found: Codeception configuration\n"; + echo "Found: TestDB configuration\n"; } else { - echo "Useful Codeception configuration not found in config.php\n"; + echo "Useful TestRunner configuration not found in config.php\n"; return false; } @@ -364,41 +286,6 @@ function batchTestSetup() } -function launchCodecept($param, $silent = false) -{ - $OK = "NO"; - - if (!$silent) { - echo "\nWARNING - Running tests will invalidate your current database.\n"; - echo "(You can silence this warning for subsequent tests.)\n"; - $OK = getUserInput('Enter "OK" or "SILENCE" to continue: '); - } - - if ($OK == 'SILENCE') { - $silent = true; - } - if ($silent) { - $OK = "OK"; - } - - if ($OK == "OK") { - try { - $runner = "cd " . TEST_DIRECTORY . " && vendor" . DS . "bin" . DS . "codecept " . $param; - $output = []; - $return_code = 0; - exec($runner, $output, $return_code); - echo implode("\n", $output) . "\n"; - if ($return_code > 0) { - exit($return_code); - } - } catch (Exception $e) { - echo $e->getMessage(); - exit(1); - } - } - - return $silent; -} /** * Calls exec on the $file_name parameter, and passes the $output and $status_code @@ -421,16 +308,8 @@ function executeUnitTest(string $file_name, ?array &$output, string &$status_cod function purgeTestCode() { if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - exec('del ' . CEST_DESTINATION . DS . '*Cest.php'); - exec('del ' . STEP_DESTINATION . DS . '*.php'); - exec('del ' . HELP_DESTINATION . DS . '*.php'); - // exec('del ' . HELP_DESTINATION . DS . '..' . DS . '*.php'); exec('del ' . UNIT_DESTINATION . DS . '*.php'); } else { - exec('rm -f ' . CEST_DESTINATION . DS . '*Cest.php'); - exec('rm -f ' . STEP_DESTINATION . DS . '*.php'); - exec('rm -f ' . HELP_DESTINATION . DS . '*.php'); - // exec('rm -f ' . HELP_DESTINATION . DS . '..' . DS . '*.php'); exec('rm -f ' . UNIT_DESTINATION . DS . '*.php'); } } @@ -471,114 +350,6 @@ function reportModules($moduleCapabilities) echo "\n"; } - -function registerConfig() -{ - $destPath = BOILERPLATE_TEST_DIRECTORY . DS . "Acceptance.suite.dist.yml"; - $ConfigYML = fopen($destPath, "w"); - - if (!$ConfigYML) { - return; - } - - $codeceptionConfig = ["modules" => ["enabled" => Config::get("tests.yaml")]]; - if (!$codeceptionConfig) { - return; - } - $hdr = "# Codeception Test Suite Configuration\n#\n" . - "# Suite for acceptance tests.\n" . - "# Perform tests in browser using the WebDriver or PhpBrowser.\n" . - "# If you need both WebDriver and PHPBrowser tests - create a separate suite.\n\n" . - "class_name: CmfiveUI\n\n"; - - fwrite($ConfigYML, $hdr); - - - $setup = Yaml::dump($codeceptionConfig, 99); - $setup = str_replace("'[", "[", $setup); - $setup = str_replace("]'", "]", $setup); - $setup = str_replace("'-", "-", $setup); - $setup = str_replace(":':", ":", $setup); - fwrite($ConfigYML, $setup); - // echo "Configured as:\n".$setup."\n"; - fclose($ConfigYML); -} - - -function registerHelpers($moduleCapabilities) -{ - // Helpers can know where module path is, - // hence could feed test data (CSV,SQL etc) - // $sharedParam & registerBoilerplateParametersmake it work - - $destPath = BOILERPLATE_TEST_DIRECTORY . DS . "Acceptance.suite.yml"; - $HelperYML = fopen($destPath, "w"); - - if (!$HelperYML) { - return; - } - - $hdr = "actor: CmfiveUI\n" - . "gherkin:\n" - . " contexts:\n" - . " default:\n" - . " - \Tests\Support\AcceptanceTester\n" - . " - \Tests\Support\CmfiveUI\n" - . "modules:\n" - . " enabled:\n"; - - fwrite($HelperYML, $hdr); - - foreach ($moduleCapabilities as $capabilities => $capability) { - if ($capabilities == "Helpers") { - foreach ($capability as $handler => $resources) { - foreach ($resources as $resource) { - fwrite($HelperYML, " - Tests\\Support\\Helper\\" . $resource . ":\n"); - // per notes above, can insert required values here... - $from = $moduleCapabilities['Paths'][$handler][0]; - $from = substr($from, 0, strpos($from, "acceptance")) . "acceptance" . DS; - fwrite($HelperYML, " " - . "basePath: {$from}\n"); - if ($handler == SHARED_SOURCE) { - registerBoilerplateParameters($HelperYML); - } - fwrite($HelperYML, "\n"); - } - } - } - }; - - fclose($HelperYML); -} - - -function registerBoilerplateParameters($spoolTo) -{ - global $sharedParam; - global $loadedParam; - - foreach ($sharedParam as $key => $value) { - fwrite($spoolTo, " " - . "{$key}: '{$value}'\n"); - } - foreach ($loadedParam as $key => $conf) { - //should be isarray vs string on 'config' then encode as req'd - $configTyped = Config::get($conf); - if (is_array($configTyped)) { - $configTyped = json_encode($configTyped); - } - if (is_string($configTyped)) { - fwrite($spoolTo, " " - . "{$key}: '" . $configTyped . "'\n"); - } - if (!isset($configTyped)) { - fwrite($spoolTo, " " - . "{$key}: ''\n"); - } - } -} - - function chaseModules($module_name) { global $sharedParam; @@ -608,21 +379,10 @@ function chaseModules($module_name) try { copy($file['source'], $file['dest']); - if (isset($file['helper'])) { - $moduleCapabilities['Helpers'][$module][] = $file['helper']; - } - - // these should be individually runnable (returned as list from here!) - if (isset($file['cest'])) { - $moduleCapabilities['Tests'][$module][] = $file['cest']; - } if (isset($file['unit'])) { $moduleCapabilities['UnitTests'][$module][] = $file['unit']; } - if (isset($file['actor'])) { - $moduleCapabilities['Actors'][$module][] = $file['actor']; - } $moduleCapabilities['Paths'][$module][] = $from; } catch (Exception $e) { echo $e->getMessage(); @@ -646,21 +406,11 @@ function getTestsForModule($module) $workflow_path = WORKFLOWS_TEST_DIRECTORY . DS . $module; $test_paths = [$module_path, $system_module_path, $boiler_path, $workflow_path]; - $extended_paths = [CEST_DIRECTORY, STEP_DIRECTORY, HELP_DIRECTORY, UNIT_DIRECTORY]; + $extended_paths = [UNIT_DIRECTORY]; $dest_paths = [ - CEST_DIRECTORY => CEST_DESTINATION, - STEP_DIRECTORY => STEP_DESTINATION, - HELP_DIRECTORY => HELP_DESTINATION, UNIT_DIRECTORY => UNIT_DESTINATION ]; - $findActor = ""; - if ($module == SHARED_SOURCE) { - $findActor = CEST_DIRECTORY . DS . ".."; - $extended_paths[] = $findActor; - $dest_paths[$findActor] = HELP_DESTINATION . DS . ".."; - } - if (empty($availableTests[$module])) { $availableTests[$module] = []; } @@ -678,17 +428,6 @@ function getTestsForModule($module) $modFile = $file; $details = []; - if ($ext == HELP_DIRECTORY) { - $details['helper'] = rtrim($file, ".php"); - } - if ($ext == CEST_DIRECTORY) { - $modFile = $module . "_" . $file; - $details['cest'] = $modFile; - } - if ($ext == STEP_DIRECTORY) { - $modFile = $module . "_" . $file; - $details['actor'] = rtrim($file, ".php"); - } if ($ext == UNIT_DIRECTORY) { $modFile = $module . "/" . $file; $details['unit'] = $modFile; @@ -697,9 +436,7 @@ function getTestsForModule($module) mkdir(ROOT_PATH . DS . $dest_paths[$ext] . DS . $module); } } - if ($ext == $findActor) { - $details['actor'] = rtrim($file, ".php"); - } + $details['source'] = $full_path . DS . $file; $details['dest'] = ROOT_PATH . DS . $dest_paths[$ext] . DS . $modFile; @@ -712,15 +449,16 @@ function getTestsForModule($module) return $availableTests; } -function getUserInput($prompt = "Command: ") -{ - $command = ''; - if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - echo $prompt; - $command = stream_get_line(STDIN, 1024, PHP_EOL); - } else { - $command = readline($prompt); - } - - return $command; -} +// // unused now, no silent option! +// function getUserInput($prompt = "Command: ") +// { +// $command = ''; +// if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { +// echo $prompt; +// $command = stream_get_line(STDIN, 1024, PHP_EOL); +// } else { +// $command = readline($prompt); +// } + +// return $command; +// }