Compare commits

..

1 commit

Author SHA1 Message Date
dependabot[bot]
0e3b023910
Bump symfony/cache from 4.3.3 to 4.4.1
Bumps [symfony/cache](https://github.com/symfony/cache) from 4.3.3 to 4.4.1.
- [Release notes](https://github.com/symfony/cache/releases)
- [Changelog](https://github.com/symfony/cache/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/cache/compare/v4.3.3...v4.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-03 00:09:18 +00:00
35 changed files with 9613 additions and 1 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/web
/vendor
/app

47
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,47 @@
stages:
- setup
- test
setup:composer:
image: composer:latest
stage: setup
script:
- mkdir -p .composer/cache
- COMPOSER_CACHE_DIR=.composer/cache composer install --no-progress --no-ansi --no-interaction -o
cache:
key: composer-cache
paths:
- .composer/cache
artifacts:
expire_in: 30 mins
paths:
- app
- web
- vendor
test:acceptance:
image: php:7.2-alpine
stage: test
services:
- mysql:5.7
- mailhog/mailhog:v1.0.0
- selenium/standalone-chrome
variables:
MYSQL_ROOT_PASSWORD: "dev"
MYSQL_DATABASE: "dev"
MYSQL_USER: "dev"
MYSQL_PASSWORD: "dev"
before_script:
- docker-php-ext-install pdo pdo_mysql mysqli
- export LOCAL_IP=$(ip a | grep inet | sed -n 2p | xargs | cut -d" " -f2 | cut -d"/" -f1)
- export TESTING_DOMAIN="$LOCAL_IP:8080"
- export TYPO3_CONTEXT=Testing/Acceptance
- php -S "$TESTING_DOMAIN" -t web &> php.log.txt &
script:
- ./vendor/bin/codecept run --env=gitlab-ci
artifacts:
when: on_failure
expire_in: 10 mins
paths:
- tests/_output/
- php.log.txt

View file

@ -3,4 +3,39 @@ Workshop GitLab Acceptance Testing
This repository provides material for GitLab Acceptance testing.
Superseded by https://gitea.daniel-siepmann.de/danielsiepmann/acceptance-testing-with-php-codeception
Install
-------
#. Run ``composer install``
#. Setup database ``own_workshopgitlabacceptance_testing``
#. Setup Mailhog.
Execute
-------
#. Start selenium
E.g.::
ChromeDriver=~/Applications/chromedriver-76 java -Djava.awt.headless=true -jar ~/Applications/selenium-server-standalone-3.141.59.jar
#. Start mailhog
#. Start php server::
TYPO3_CONTEXT=Testing/Acceptance php -S 127.0.0.1:8080 -t web
#. Execute tests::
./vendor/bin/codecept run --env local
TODO
----
* Add css / js for testing
* Use docker registry for finished container with php support for mysql
* Add db tests as examples to cest

View file

@ -0,0 +1,52 @@
<?php
if (getenv('TYPO3_ADDITIONAL_CONFIGURATION')) {
require_once getenv('TYPO3_ADDITIONAL_CONFIGURATION');
}
$appContext = \TYPO3\CMS\Core\Utility\GeneralUtility::getApplicationContext();
if ((string) $appContext === 'Testing/Acceptance') {
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule(
$GLOBALS['TYPO3_CONF_VARS'],
[
'SYS' => [
'trustedHostsPattern' => 'localhost:8080',
],
'MAIL' => [
'transport' => 'smtp',
'transport_smtp_server' => '127.0.0.1:1025',
],
'DB' => [
'Connections' => [
'Default' => [
'dbname' => 'own_workshopgitlabacceptance_testing',
],
],
],
]
);
}
if ((string) $appContext === 'Testing/Acceptance' && getenv('CI') === 'true') {
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule(
$GLOBALS['TYPO3_CONF_VARS'],
[
'SYS' => [
'trustedHostsPattern' => getenv('TESTING_DOMAIN'),
],
'MAIL' => [
'transport' => 'smtp',
'transport_smtp_server' => 'mailhog__mailhog:1025',
],
'DB' => [
'Connections' => [
'Default' => [
'dbname' => 'dev',
'password' => 'dev',
'user' => 'dev',
'host' => 'mysql',
],
],
],
]
);
}

View file

@ -0,0 +1,95 @@
<?php
return [
'BE' => [
'debug' => true,
'explicitADmode' => 'explicitAllow',
'installToolPassword' => '$argon2i$v=19$m=65536,t=16,p=2$UzAyaTZoVEpFMmV2M1piSQ$TywI+4PRhqx2ggtTrV+R7BNrb0oheW6tr/SThHr6HgM',
'loginSecurityLevel' => 'normal',
'passwordHashing' => [
'className' => 'TYPO3\\CMS\\Core\\Crypto\\PasswordHashing\\Argon2iPasswordHash',
'options' => [],
],
],
'DB' => [
'Connections' => [
'Default' => [
'charset' => 'utf8mb4',
'dbname' => 'own_workshopgitlabacceptance',
'driver' => 'mysqli',
'host' => '127.0.0.1',
'password' => 'dev',
'port' => 3306,
'tableoptions' => [
'charset' => 'utf8mb4',
'collate' => 'utf8mb4_unicode_ci',
],
'unix_socket' => '/var/run/mysqld/mysqld.sock',
'user' => 'dev',
],
],
],
'EXT' => [
'extConf' => [
'backend' => 'a:6:{s:9:"loginLogo";s:0:"";s:19:"loginHighlightColor";s:0:"";s:20:"loginBackgroundImage";s:0:"";s:13:"loginFootnote";s:0:"";s:11:"backendLogo";s:0:"";s:14:"backendFavicon";s:0:"";}',
'extensionmanager' => 'a:2:{s:21:"automaticInstallation";s:1:"1";s:11:"offlineMode";s:1:"0";}',
'scheduler' => 'a:2:{s:11:"maxLifetime";s:4:"1440";s:15:"showSampleTasks";s:1:"1";}',
],
],
'EXTENSIONS' => [
'backend' => [
'backendFavicon' => '',
'backendLogo' => '',
'loginBackgroundImage' => '',
'loginFootnote' => '',
'loginHighlightColor' => '',
'loginLogo' => '',
],
'extensionmanager' => [
'automaticInstallation' => '1',
'offlineMode' => '0',
],
'scheduler' => [
'maxLifetime' => '1440',
'showSampleTasks' => '1',
],
],
'FE' => [
'debug' => true,
'loginSecurityLevel' => 'normal',
'passwordHashing' => [
'className' => 'TYPO3\\CMS\\Core\\Crypto\\PasswordHashing\\Argon2iPasswordHash',
'options' => [],
],
],
'GFX' => [
'processor' => 'ImageMagick',
'processor_allowTemporaryMasksAsPng' => false,
'processor_colorspace' => 'sRGB',
'processor_effects' => true,
'processor_enabled' => true,
'processor_path' => '/usr/bin/',
'processor_path_lzw' => '/usr/bin/',
],
'MAIL' => [
'transport' => 'sendmail',
'transport_sendmail_command' => '/usr/sbin/sendmail -t -i ',
'transport_smtp_encrypt' => '',
'transport_smtp_password' => '',
'transport_smtp_server' => '',
'transport_smtp_username' => '',
],
'SYS' => [
'devIPmask' => '*',
'displayErrors' => 1,
'encryptionKey' => 'fc4441867ae5c425bd55676e01d6d14fd2ae17ed8fd5682b495e74518eda4d437c0c48917772dc848fff31f5cea3c3eb',
'exceptionalErrors' => 12290,
'features' => [
'unifiedPageTranslationHandling' => true,
],
'sitename' => 'New TYPO3 Console site',
'systemLogLevel' => 0,
'systemMaintainers' => [
1,
],
],
];

View file

@ -0,0 +1,40 @@
rootPageId: 1
base: /
languages:
-
title: English
enabled: true
languageId: '0'
base: /
typo3Language: default
locale: en_US.UTF-8
iso-639-1: en
navigationTitle: English
hreflang: en-us
direction: ltr
flag: us
errorHandling: {}
routes: {}
baseVariants: {}
# routeEnhancers:
# ExamplePlugin:
# type: Extbase
# extension: ExampleExtension
# plugin: Address
# defaultController: 'Address::index'
# routes:
# -
# routePath: '/edit/{address}'
# _controller: 'Address::edit'
# _arguments:
# 'address': 'address'
# -
# routePath: '/update'
# _controller: 'Address::update'
# aspects:
# address:
# type: PersistedAliasMapper
# tableName: 'tx_exampleextension_domain_model_address'
# routeFieldName: 'slug'
# routeValuePrefix: '/'

35
codeception.yml Normal file
View file

@ -0,0 +1,35 @@
suites:
acceptance:
actor: AcceptanceTester
path: .
modules:
enabled:
- WebDriver:
url: https://workshop-gitlab-acceptance.own.localhost/
browser: chrome
- Db:
dump: tests/_data/typo3.sql
populate: true
cleanup: true
- MailHog:
url: http://127.0.0.1
port: 8025
deleteEmailsAfterScenario: true
- \Helper\Acceptance
step_decorators:
- Codeception\Step\ConditionalAssertion
- Codeception\Step\TryTo
- Codeception\Step\Retry
extensions:
enabled: [Codeception\Extension\RunFailed]
params:
- env
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs

51
composer.json Normal file
View file

@ -0,0 +1,51 @@
{
"repositories": [
{
"type": "path",
"url": "localPackages/*"
},
{
"type": "composer",
"url": "https://composer.typo3.org/"
}
],
"name": "website/typo3-extension-workshop",
"description": "Example TYPO3 installation for Acceptance Testing",
"license": "GPL-2.0-or-later",
"require": {
"helhum/typo3-console": "^5.5.5",
"helhum/typo3-secure-web": "^0.2.7",
"typo3-console/composer-auto-commands": "^0.2.0",
"typo3/cms-core": "^9.5.0",
"typo3/cms-about": "*",
"typo3/cms-belog": "*",
"typo3/cms-beuser": "*",
"typo3/cms-fluid-styled-content": "*",
"typo3/cms-info": "*",
"typo3/cms-info-pagetsconfig": "*",
"typo3/cms-rte-ckeditor": "*",
"typo3/cms-setup": "*",
"typo3/cms-t3editor": "*",
"typo3/cms-tstemplate": "*",
"workshop/example-extension": "@dev"
},
"require-dev": {
"typo3/cms-lowlevel": "*",
"codeception/codeception": "^3.1.0",
"ericmartel/codeception-email-mailhog": "^1.0"
},
"config": {
"platform": {
"php": "7.2"
}
},
"extra": {
"typo3/cms": {
"app-dir": "app",
"root-dir": "app",
"web-dir": "web"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

6612
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
<?php
namespace Workshop\ExampleExtension\Controller;
/*
* Copyright (C) 2018 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use Workshop\ExampleExtension\Domain\Model\Address;
use Workshop\ExampleExtension\Domain\Repository\AddressRepository;
class AddressController extends ActionController
{
/**
* @var AddressRepository
*/
protected $addressRepository;
public function __construct(AddressRepository $addressRepository)
{
$this->addressRepository = $addressRepository;
}
public function indexAction()
{
$this->view->assign('addresses', $this->addressRepository->findAll());
}
/**
* @ignorevalidation $address
*/
public function editAction(Address $address)
{
$this->view->assign('address', $address);
}
public function updateAction(Address $address)
{
$this->addressRepository->update($address);
$this->signalSlotDispatcher->dispatch(__CLASS__, 'addressUpdated', [
$address,
$this,
]);
$this->redirect('index');
}
}

View file

@ -0,0 +1,58 @@
<?php
namespace Workshop\ExampleExtension\Domain\Event;
/*
* Copyright (C) 2019 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use Workshop\ExampleExtension\Controller\AddressController;
use Workshop\ExampleExtension\Domain\Model\Address as AddressModel;
class Address
{
public function updated(AddressModel $address, AddressController $controller)
{
$this->sendUpdateEMail($address);
$this->addUpdateFlashMessage($address, $controller);
}
private function sendUpdateEmail(AddressModel $address)
{
$mail = GeneralUtility::makeInstance(MailMessage::class);
$mail->setSubject('Address ' . $address->getCompanyName() . ' was updated');
$mail->setTo(array('coding@daniel-siepmann.de'));
$mail->setBody('The address ' . $address->getCompanyName() . ' was successfully updated.');
$mail->send();
}
private function addUpdateFlashMessage(AddressModel $address, AddressController $controller)
{
$controller->addFlashMessage(
LocalizationUtility::translate('flashSuccess', 'ExampleExtension', [
'companyName' => $address->getCompanyName(),
'street' => $address->getStreet(),
]),
'Update successfully'
);
}
}

View file

@ -0,0 +1,119 @@
<?php
namespace Workshop\ExampleExtension\Domain\Model;
/*
* Copyright (C) 2018 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class Address extends AbstractEntity
{
/**
* @var string
* @validate NotEmpty
*/
protected $companyName;
/**
* @var string
*/
protected $street;
/**
* @var string
*/
protected $houseNumber;
/**
* @var string
* @validate RegularExpression(regularExpression = '/^[0-9]{5}$/')
*/
protected $zip;
/**
* @var string
*/
protected $city;
/**
* @var string
*/
protected $country;
public function setCompanyName(string $companyName)
{
$this->companyName = $companyName;
}
public function getCompanyName(): string
{
return $this->companyName;
}
public function setStreet(string $street)
{
$this->street = $street;
}
public function getStreet(): string
{
return $this->street;
}
public function setHouseNumber(string $houseNumber)
{
$this->houseNumber = $houseNumber;
}
public function getHouseNumber(): string
{
return $this->houseNumber;
}
public function setZip(string $zip)
{
$this->zip = $zip;
}
public function getZip(): string
{
return $this->zip;
}
public function setCity(string $city)
{
$this->city = $city;
}
public function getCity(): string
{
return $this->city;
}
public function setCountry(string $country)
{
$this->country = $country;
}
public function getCountry(): string
{
return $this->country;
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace Workshop\ExampleExtension\Domain\Repository;
/*
* Copyright (C) 2018 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use TYPO3\CMS\Extbase\Persistence\Repository;
class AddressRepository extends Repository
{
}

View file

@ -0,0 +1,40 @@
<?php
(function ($extensionKey, $tableName) {
$langPath = 'LLL:EXT:' . $extensionKey . '/Resources/Private/Language/locallang.xlf:' . $tableName . '.';
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
'Workshop.ExampleExtension',
'Address',
'Address Plugin',
'content-store'
);
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule(
$GLOBALS['TCA'][$tableName],
[
'ctrl' => [
'typeicon_classes' => [
'exampleextension_address' => 'content-store',
],
],
'types' => [
'exampleextension_address' => [
'showitem' => implode(',', [
// phpcs:disable Generic.Files.LineLength.TooLong
// Keep original code from ext:frontend
'--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general',
'--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.general;general',
'--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.headers;headers',
'pages;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:pages.ALT.list_formlabel',
'recursive,',
'--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access',
'--palette--;;hidden',
'--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.access;access',
// phpcs:enable
]),
],
],
]
);
})('example_extension', 'tt_content');

View file

@ -0,0 +1,115 @@
<?php
return (function (
$extensionKey = 'example_extension',
$tableName = 'tx_workshopexampleextension_domain_model_address'
) {
$extensionLanguagePrefix = 'LLL:EXT:example_extension/Resources/Private/Language/locallang_tca.xlf:';
$coreLanguagePrefix = 'LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:';
return [
'ctrl' => [
'label' => 'company_name',
'iconfile' => 'EXT:core/Resources/Public/Icons/T3Icons/content/content-store.svg',
'default_sortby' => 'company_name',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => $extensionLanguagePrefix . 'address',
'delete' => 'deleted',
'enablecolumns' => [
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime'
],
'searchFields' => 'company_name, street, city'
],
'interface' => [
'showRecordFieldList' => 'company_name, street, house_number, zip, city, country, slug'
],
'palettes' => [
'address' => [
'showitem' => implode(',', [
'street, house_number',
'--linebreak--',
'zip, city',
'--linebreak--',
'country',
]),
],
],
'types' => [
'0' => [
'showitem' => implode(',', [
'--div--;' . $coreLanguagePrefix . 'general',
'company_name;;address',
'slug',
]),
],
],
'columns' => [
'company_name' => [
'label' => $extensionLanguagePrefix . 'company_name',
'config' => [
'type' => 'input',
'max' => 255,
'eval' => 'trim,required',
],
],
'street' => [
'label' => $extensionLanguagePrefix . 'street',
'config' => [
'type' => 'input',
'max' => 255,
'eval' => 'trim,required',
],
],
'house_number' => [
'label' => $extensionLanguagePrefix . 'house_number',
'config' => [
'type' => 'input',
'size' => 10,
'max' => 255,
'eval' => 'trim,required',
],
],
'zip' => [
'label' => $extensionLanguagePrefix . 'zip',
'config' => [
'type' => 'input',
'size' => 10,
'max' => 255,
'eval' => 'trim,required',
],
],
'city' => [
'label' => $extensionLanguagePrefix . 'city',
'config' => [
'type' => 'input',
'max' => 255,
'eval' => 'trim,required',
],
],
'country' => [
'label' => $extensionLanguagePrefix . 'country',
'config' => [
'type' => 'input',
'max' => 255,
'eval' => 'trim,required',
],
],
'slug' => [
'label' => $extensionLanguagePrefix . 'slug',
'config' => [
'type' => 'slug',
'generatorOptions' => [
'fields' => ['company_name'],
'prefixParentPageSlug' => true,
],
'fallbackCharacter' => '-',
'eval' => 'uniqueInSite',
],
],
],
];
})();

View file

@ -0,0 +1,3 @@
config {
contentObjectExceptionHandler = 0
}

View file

@ -0,0 +1 @@
@import 'EXT:fluid_styled_content/Configuration/TypoScript/setup.typoscript'

View file

@ -0,0 +1,4 @@
page = PAGE
page {
10 < styles.content.get
}

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="messages" date="2018-10-01T11:16:33Z" product-name="CodeExamples">
<header/>
<body>
<!-- Form Labels -->
<trans-unit id="labels.companyName" xml:space="preserve">
<source>Company name</source>
</trans-unit>
<trans-unit id="labels.street" xml:space="preserve">
<source>Street</source>
</trans-unit>
<trans-unit id="labels.houseNumber" xml:space="preserve">
<source>House number</source>
</trans-unit>
<trans-unit id="labels.zip" xml:space="preserve">
<source>Zip</source>
</trans-unit>
<trans-unit id="labels.city" xml:space="preserve">
<source>City</source>
</trans-unit>
<trans-unit id="labels.country" xml:space="preserve">
<source>Country</source>
</trans-unit>
<!-- Form Validation -->
<trans-unit id="error.address.companyName.1221560718" xml:space="preserve">
<source>Please provide a company name.</source>
</trans-unit>
<trans-unit id="error.address.zip.1221565130" xml:space="preserve">
<source>Please provide a valid ZIP consisting of 5 digits.</source>
</trans-unit>
<trans-unit id="flashSuccess" xml:space="preserve">
<source>Update des Datensatzes %1$s war Erfolgreich.</source>
</trans-unit>
</body>
</file>
</xliff>

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="messages" date="2018-09-05T08:51:01Z" product-name="CodeExamples">
<header/>
<body>
<trans-unit id="address" xml:space="preserve">
<source>Address</source>
</trans-unit>
<trans-unit id="company_name" xml:space="preserve">
<source>Company name</source>
</trans-unit>
<trans-unit id="street" xml:space="preserve">
<source>Street</source>
</trans-unit>
<trans-unit id="house_number" xml:space="preserve">
<source>House number</source>
</trans-unit>
<trans-unit id="zip" xml:space="preserve">
<source>Zip</source>
</trans-unit>
<trans-unit id="city" xml:space="preserve">
<source>City</source>
</trans-unit>
<trans-unit id="country" xml:space="preserve">
<source>Country</source>
</trans-unit>
</body>
</file>
</xliff>

View file

@ -0,0 +1,41 @@
<h3>Editing: {address.companyName}</h3>
<f:form action="update" object="{address}" name="address">
<f:for each="{
0: 'companyName',
1: 'street',
2: 'houseNumber',
3: 'zip',
4: 'city',
5: 'country'
}" as="propertyName">
{f:render(section: 'Field', arguments: {
propertyName: propertyName
})}
</f:for>
<br>
<f:form.submit value="Update" />
</f:form>
<f:section name="Field">
<p>
<label for="{propertyName}">{f:translate(id: 'labels.{propertyName}')}</label>
<br>
<f:form.textfield property="{propertyName}" id="{propertyName}" />
{f:render(section: 'FieldErrors', arguments: {
propertyPath: 'address.{propertyName}'
})}
<br>
</p>
</f:section>
<f:section name="FieldErrors">
<f:form.validationResults for="{propertyPath}">
<f:for each="{validationResults.flattenedErrors}" as="errors">
<f:for each="{errors}" as="error">
{f:translate(id: 'error.{propertyPath}.{error.code}', default: error.code)}
</f:for>
</f:for>
</f:form.validationResults>
</f:section>

View file

@ -0,0 +1,11 @@
<f:flashMessages />
<f:for each="{addresses}" as="address">
<h3>{address.companyName}</h3>
<address>
{address.street} {address.houseNumber}
{address.zip} {address.city}
{address.country}
</address>
<f:link.action action="edit" arguments="{address: address}">Edit</f:link.action>
</f:for>

View file

@ -0,0 +1,21 @@
{
"name": "workshop/example-extension",
"description": "Example for TYPO3 Extension Workshop.",
"type": "typo3-cms-extension",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Daniel Siepmann",
"email": "coding@daniel-siepmann.de"
}
],
"autoload": {
"psr-4": {
"Workshop\\ExampleExtension\\": "Classes"
}
},
"require": {
"php": ">=7.2.0",
"typo3/cms-core": "*"
}
}

View file

@ -0,0 +1,23 @@
<?php
$EM_CONF['example_extension'] = [
'title' => 'Example extension',
'description' => 'Example for TYPO3 Extension Workshop.',
'category' => 'example',
'version' => '1.0.0',
'state' => 'stable',
'author' => 'Daniel Siepmann',
'author_email' => 'coding@daniel-siepmann.de',
'author_company' => 'Codappix',
'constraints' => [
'depends' => [
'php' => '7.2.0-7.2.999',
'typo3' => '8.7.0-9.5.999',
],
],
'autoload' => [
'psr-4' => [
'Workshop\\ExampleExtension\\' => 'Classes',
]
],
];

View file

@ -0,0 +1,51 @@
<?php
(function () {
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Workshop.ExampleExtension',
'Address',
[
'Address' => 'index, edit, update'
],
[
'Address' => 'update'
],
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup(trim('
@import "EXT:example_extension/Configuration/TypoScript/*.typoscript"
'));
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig('
mod {
wizards {
newContentElement {
wizardItems {
common {
show = *
elements {
exampleElement {
iconIdentifier = content-store
title = Example title
description = Example Description
tt_content_defValues {
CType = list
list_type = exampleextension_pluginkey
}
}
}
}
}
}
}
}
');
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class)->connect(
\Workshop\ExampleExtension\Controller\AddressController::class,
'addressUpdated',
\Workshop\ExampleExtension\Domain\Event\Address::class,
'updated'
);
})();

View file

@ -0,0 +1,9 @@
CREATE TABLE tx_exampleextension_domain_model_address (
company_name varchar(255) DEFAULT '' NOT NULL,
street varchar(255) DEFAULT '' NOT NULL,
house_number varchar(255) DEFAULT '' NOT NULL,
zip varchar(255) DEFAULT '' NOT NULL,
city varchar(255) DEFAULT '' NOT NULL,
country varchar(255) DEFAULT '' NOT NULL,
slug varchar(2048),
);

66
tests/AddressCest.php Normal file
View file

@ -0,0 +1,66 @@
<?php
class AddressCest
{
public function listsExistingRecords(AcceptanceTester $I)
{
$I->amOnPage('/plugin');
$I->see('Codappix GmbH');
}
/**
* @depends listsExistingRecords
*/
public function canEditRecord(AcceptanceTester $I)
{
$I->amOnPage('/plugin');
$I->see('Edit');
$I->click('Edit');
$I->see('Editing: Codappix GmbH');
$I->fillField(['id' => 'companyName'], 'TYPO3 Camp Rhein Ruhr');
$I->click('Update');
$I->amOnPage('/plugin');
$I->see('TYPO3 Camp Rhein Ruhr');
}
/**
* @depends canEditRecord
*/
public function sendsMailOnUpdate(AcceptanceTester $I)
{
$I->amOnPage('/plugin');
$I->see('Edit');
$I->click('Edit');
$I->see('Editing: Codappix GmbH');
$I->fillField(['id' => 'companyName'], 'TYPO3 Camp Rhein Ruhr');
$I->click('Update');
$I->fetchEmails();
$I->haveUnreadEmails();
$I->openNextUnreadEmail();
$I->dontHaveUnreadEmails();
$I->seeInOpenedEmailSubject('Address TYPO3 Camp Rhein Ruhr was updated');
$I->seeInOpenedEmailBody('The address TYPO3 Camp Rhein Ruhr was successfully updated.');
$I->seeInOpenedEmailRecipients('coding@daniel-siepmann.de');
}
/**
* @depends listsExistingRecords
*/
public function zipValidatesAgainst5Digits(AcceptanceTester $I)
{
$I->amOnPage('/plugin');
$I->see('Edit');
$I->click('Edit');
$I->see('Editing: Codappix GmbH');
$I->fillField(['id' => 'zip'], '123');
$I->click('Update');
$I->see('Please provide a valid ZIP consisting of 5 digits.');
}
}

0
tests/_data/.gitkeep Normal file
View file

1855
tests/_data/typo3.sql Normal file

File diff suppressed because one or more lines are too long

12
tests/_envs/gitlab-ci.yml Normal file
View file

@ -0,0 +1,12 @@
modules:
config:
WebDriver:
url: http://%TESTING_DOMAIN%/
host: selenium__standalone-chrome
Db:
dsn: 'mysql:host=mysql;dbname=dev'
user: 'dev'
password: 'dev'
MailHog:
url: http://mailhog__mailhog
port: 8025

11
tests/_envs/local.yml Normal file
View file

@ -0,0 +1,11 @@
modules:
config:
WebDriver:
url: http://localhost:8080/
Db:
dsn: 'mysql:host=localhost;dbname=own_workshopgitlabacceptance_testing'
user: 'dev'
password: 'dev'
MailHog:
url: http://127.0.0.1
port: 8025

2
tests/_output/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -0,0 +1,26 @@
<?php
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void pause()
*
* @SuppressWarnings(PHPMD)
*/
class AcceptanceTester extends \Codeception\Actor
{
use _generated\AcceptanceTesterActions;
/**
* Define custom actions here
*/
}

View file

@ -0,0 +1,10 @@
<?php
namespace Helper;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class Acceptance extends \Codeception\Module
{
}

2
tests/_support/_generated/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore