mirror of
https://github.com/saccas/mjml-typo3.git
synced 2024-11-22 10:36:10 +01:00
[TASK] Update MJML and clean up parts of the extension for new release (#31)
Use one functional test to ensure everything works, no unit tests with heavy mocking. Update mjml to fix security issues and allow new options. Provide GitHub Actions. This is a public extension with free minutes which should ensure that existing setup still works.
This commit is contained in:
parent
8fa50c3089
commit
c45dee45b0
17 changed files with 1145 additions and 1253 deletions
100
.github/workflows/ci.yaml
vendored
Normal file
100
.github/workflows/ci.yaml
vendored
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-composer:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 8.1
|
||||||
|
coverage: none
|
||||||
|
tools: composer:v2
|
||||||
|
env:
|
||||||
|
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Validate composer.json
|
||||||
|
run: composer validate
|
||||||
|
|
||||||
|
php-linting:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php-version:
|
||||||
|
- 8.1
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: "${{ matrix.php-version }}"
|
||||||
|
coverage: none
|
||||||
|
tools: composer:v2
|
||||||
|
env:
|
||||||
|
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: PHP lint
|
||||||
|
run: "find *.php Classes Configuration Tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l"
|
||||||
|
|
||||||
|
coding-guideline:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: "8.1"
|
||||||
|
coverage: none
|
||||||
|
tools: composer:v2
|
||||||
|
env:
|
||||||
|
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
|
- name: Coding Guideline
|
||||||
|
run: ./vendor/bin/phpcs
|
||||||
|
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- php-version: '8.1'
|
||||||
|
typo3-version: '^11.5'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install NodeJS
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
|
||||||
|
- name: Install PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: "${{ matrix.php-version }}"
|
||||||
|
coverage: none
|
||||||
|
tools: composer:v2
|
||||||
|
env:
|
||||||
|
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install PHP dependencies with expected TYPO3 version
|
||||||
|
run: composer require --prefer-dist --no-progress "typo3/cms-core:${{ matrix.typo3-version }}" "typo3/cms-form:${{ matrix.typo3-version }}"
|
||||||
|
|
||||||
|
- name: Install npm dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: PHPUnit Tests
|
||||||
|
run: ./vendor/bin/phpunit --testdox
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -15,3 +15,4 @@ bower_components
|
||||||
composer.lock
|
composer.lock
|
||||||
web
|
web
|
||||||
vendor
|
vendor
|
||||||
|
var/
|
||||||
|
|
|
@ -8,9 +8,17 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||||
|
|
||||||
class Command implements RendererInterface
|
class Command implements RendererInterface
|
||||||
{
|
{
|
||||||
|
private ExtensionConfiguration $extensionConfiguration;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
ExtensionConfiguration $extensionConfiguration
|
||||||
|
) {
|
||||||
|
$this->extensionConfiguration = $extensionConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
public function getHtmlFromMjml($mjml): string
|
public function getHtmlFromMjml($mjml): string
|
||||||
{
|
{
|
||||||
$conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('mjml');
|
$conf = $this->extensionConfiguration->get('mjml');
|
||||||
|
|
||||||
$temporaryMjmlFileWithPath = GeneralUtility::tempnam('mjml_', '.mjml');
|
$temporaryMjmlFileWithPath = GeneralUtility::tempnam('mjml_', '.mjml');
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Saccas\Mjml\View;
|
namespace Saccas\Mjml\View;
|
||||||
|
|
||||||
use Saccas\Mjml\Domain\Renderer\RendererInterface;
|
use Saccas\Mjml\Domain\Renderer\RendererInterface;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
||||||
use TYPO3\CMS\Fluid\View\StandaloneView;
|
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
class MjmlBasedView extends StandaloneView
|
class MjmlBasedView extends StandaloneView
|
||||||
{
|
{
|
||||||
protected ?RendererInterface $renderer = null;
|
protected RendererInterface $renderer;
|
||||||
|
|
||||||
public function __construct(ContentObjectRenderer $contentObject = null, RendererInterface $renderer = null)
|
public function __construct(
|
||||||
{
|
ContentObjectRenderer $contentObject,
|
||||||
|
RendererInterface $renderer
|
||||||
|
) {
|
||||||
parent::__construct($contentObject);
|
parent::__construct($contentObject);
|
||||||
|
|
||||||
$this->renderer = $renderer;
|
$this->renderer = $renderer;
|
||||||
if ($this->renderer === null) {
|
|
||||||
$this->renderer = GeneralUtility::makeInstance(RendererInterface::class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render($actionName = null): string
|
public function render($actionName = null): string
|
||||||
|
|
0
Configuration/Services.yaml
Executable file → Normal file
0
Configuration/Services.yaml
Executable file → Normal file
1
Tests/Functional/Fixtures/Expected.html
Normal file
1
Tests/Functional/Fixtures/Expected.html
Normal file
File diff suppressed because one or more lines are too long
39
Tests/Functional/RendersMjmlTemplateTest.php
Normal file
39
Tests/Functional/RendersMjmlTemplateTest.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Saccas\Mjml\Tests\Functional;
|
||||||
|
|
||||||
|
use Saccas\Mjml\View\MjmlBasedView;
|
||||||
|
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
|
||||||
|
|
||||||
|
class RendersMjmlTemplateTest extends FunctionalTestCase
|
||||||
|
{
|
||||||
|
protected $testExtensionsToLoad = [
|
||||||
|
'typo3conf/ext/mjml',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $configurationToUseInTestInstance = [
|
||||||
|
'EXTENSIONS' => [
|
||||||
|
'mjml' => [
|
||||||
|
'nodeBinaryPath' => 'node',
|
||||||
|
'mjmlBinaryPath' => './node_modules/mjml/bin/',
|
||||||
|
'mjmlBinary' => 'mjml',
|
||||||
|
'mjmlParams' => '-s --noStdoutFileComment',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function returnsHtmlResult(): void
|
||||||
|
{
|
||||||
|
$subject = $this->get(MjmlBasedView::class);
|
||||||
|
$subject->setTemplateSource(file_get_contents(__DIR__ . '/Fixtures/Input.mjml'));
|
||||||
|
|
||||||
|
$result = $subject->render();
|
||||||
|
|
||||||
|
self::assertStringEqualsFile(__DIR__ . '/Fixtures/Expected.html', $result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace Saccas\Mjml\Tests\Unit;
|
|
||||||
|
|
||||||
use TYPO3\CMS\Core\Cache\Backend\NullBackend;
|
|
||||||
use TYPO3\CMS\Core\Cache\CacheManager;
|
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
||||||
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
|
|
||||||
|
|
||||||
abstract class AbstractUnitTestCase extends UnitTestCase
|
|
||||||
{
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
GeneralUtility::makeInstance(CacheManager::class)
|
|
||||||
->setCacheConfigurations([
|
|
||||||
'extbase_object' => [
|
|
||||||
'backend' => NullBackend::class,
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace Saccas\Mjml\Tests\Functional\Domain\Renderer;
|
|
||||||
|
|
||||||
use Saccas\Mjml\Domain\Renderer\Command;
|
|
||||||
use Saccas\Mjml\Tests\Unit\AbstractUnitTestCase;
|
|
||||||
use TYPO3\CMS\Core\Package\Package;
|
|
||||||
use TYPO3\CMS\Core\Package\PackageManager;
|
|
||||||
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
|
||||||
|
|
||||||
class CommandTest extends AbstractUnitTestCase
|
|
||||||
{
|
|
||||||
protected ObjectManager $objectManager;
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function htmlIsReturnedForMjml(): void
|
|
||||||
{
|
|
||||||
// Mock extension to be active, to enable path fetching to call node binary.
|
|
||||||
$packageMock = $this->getMockBuilder(Package::class)
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$packageMock->expects($this->any())
|
|
||||||
->method('getPackagePath')
|
|
||||||
->willReturn(dirname(__FILE__, 5) . '/');
|
|
||||||
$packageManagerMock = $this->getMockBuilder(PackageManager::class)->getMock();
|
|
||||||
$packageManagerMock->expects($this->any())
|
|
||||||
->method('isPackageActive')
|
|
||||||
->with('mjml')
|
|
||||||
->willReturn(true);
|
|
||||||
$packageManagerMock->expects($this->any())
|
|
||||||
->method('getPackage')
|
|
||||||
->with('mjml')
|
|
||||||
->willReturn($packageMock);
|
|
||||||
ExtensionManagementUtility::setPackageManager($packageManagerMock);
|
|
||||||
|
|
||||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['mjml'] = serialize([
|
|
||||||
'nodeBinaryPath' => 'node',
|
|
||||||
'mjmlBinaryPath' => 'node_modules/mjml/bin/',
|
|
||||||
'mjmlBinary' => 'mjml',
|
|
||||||
'mjmlParams' => '-s --config.beautify true --config.minify true',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$subject = $this->objectManager->get(Command::class);
|
|
||||||
$mjml = file_get_contents(__DIR__ . '/CommandTestFixture/Basic.mjml');
|
|
||||||
$html = $subject->getHtmlFromMjml($mjml);
|
|
||||||
|
|
||||||
// remove comment rendered by the outputToConsole https://github.com/mjmlio/mjml/blob/50b08513b7a651c234829abfde254f106a62c859/packages/mjml-cli/src/commands/outputToConsole.js#L4
|
|
||||||
$html = preg_replace('/<!-- FILE: (.*)-->/Uis', '', $html);
|
|
||||||
|
|
||||||
$this->assertStringEqualsFile(
|
|
||||||
__DIR__ . '/CommandTestFixture/Expected.html',
|
|
||||||
$html,
|
|
||||||
'Command renderer did not return expected HTML.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
|
@ -1,53 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace Saccas\Mjml\Tests\Unit\View;
|
|
||||||
|
|
||||||
use Saccas\Mjml\Domain\Renderer\RendererInterface;
|
|
||||||
use Saccas\Mjml\Tests\Unit\AbstractUnitTestCase;
|
|
||||||
use Saccas\Mjml\View\MjmlBasedView;
|
|
||||||
|
|
||||||
class MjmlBasedViewTest extends AbstractUnitTestCase
|
|
||||||
{
|
|
||||||
public const EXAMPLE_MJML_TEMPLATE = '<mjml>
|
|
||||||
<mj-body>
|
|
||||||
<mj-section>
|
|
||||||
<mj-column>
|
|
||||||
<mj-image src="/assets/img/easy-and-quick.png" width="112px" />
|
|
||||||
<mj-text font-size="20px" color="#595959" align="center">Easy and Quick</mj-text>
|
|
||||||
</mj-column>
|
|
||||||
<mj-column>
|
|
||||||
<mj-image src="/assets/img/responsive.png" width="135px" />
|
|
||||||
<mj-text font-size="20px" color="#595959" align="center">Responsive</mj-text>
|
|
||||||
</mj-column>
|
|
||||||
</mj-section>
|
|
||||||
<mj-section>
|
|
||||||
<mj-column>
|
|
||||||
<mj-button background-color="#F45E43" font-size="15px">Discover</mj-button>
|
|
||||||
</mj-column>
|
|
||||||
</mj-section>
|
|
||||||
</mj-body>
|
|
||||||
</mjml>
|
|
||||||
';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function viewCallsRendererAndReturnsRenderedHtml(): void
|
|
||||||
{
|
|
||||||
$expectedHtml = '<h1>Simple HTML</h1>';
|
|
||||||
$rendererMock = $this->getMockBuilder(RendererInterface::class)->getMock();
|
|
||||||
$rendererMock->expects($this->once())
|
|
||||||
->method('getHtmlFromMjml')
|
|
||||||
->with(static::EXAMPLE_MJML_TEMPLATE)
|
|
||||||
->willReturn($expectedHtml);
|
|
||||||
|
|
||||||
$subject = new MjmlBasedView(null, $rendererMock);
|
|
||||||
$subject->setTemplateSource(static::EXAMPLE_MJML_TEMPLATE);
|
|
||||||
$result = $subject->render();
|
|
||||||
|
|
||||||
$this->assertSame(
|
|
||||||
$expectedHtml,
|
|
||||||
$result,
|
|
||||||
'Rendering of view did not return expected HTML.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,13 +15,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4 || ^8.0 || ^8.1",
|
"php": "^8.1",
|
||||||
"typo3/cms-core": "^9.5.0 || ^10.4.10 || ^11.5",
|
"typo3/cms-core": "^11.5",
|
||||||
"typo3/cms-form": "^9.5.0 || ^10.4.10 || ^11.5"
|
"typo3/cms-form": "^11.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"squizlabs/php_codesniffer": "^3.2.0",
|
"squizlabs/php_codesniffer": "^3.2.0",
|
||||||
"typo3/testing-framework": "^1.2.2 || ^6.16"
|
"typo3/testing-framework": "^6.16"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": [
|
"lint": [
|
||||||
|
@ -47,5 +47,11 @@
|
||||||
"cms-package-dir": "{$vendor-dir}/typo3/cms",
|
"cms-package-dir": "{$vendor-dir}/typo3/cms",
|
||||||
"web-dir": "web"
|
"web-dir": "web"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"typo3/class-alias-loader": true,
|
||||||
|
"typo3/cms-composer-installers": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,4 @@ mjmlBinaryPath = ./node_modules/mjml/bin/
|
||||||
mjmlBinary = mjml
|
mjmlBinary = mjml
|
||||||
|
|
||||||
# cat=mjml/Binary/4000; type=string; label=mjml params : -s --config.beautify true --config.minify true
|
# cat=mjml/Binary/4000; type=string; label=mjml params : -s --config.beautify true --config.minify true
|
||||||
mjmlParams = -s --config.beautify true --config.minify true
|
mjmlParams = -s --config.beautify true --config.minify true --noStdoutFileComment
|
||||||
|
|
2046
package-lock.json
generated
2046
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "mjml-typo3",
|
"name": "mjml-typo3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mjml": "^4.6.2"
|
"mjml": "^4.13.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<phpunit
|
<?xml version="1.0"?>
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
||||||
backupGlobals="false"
|
backupGlobals="false"
|
||||||
backupStaticAttributes="false"
|
backupStaticAttributes="false"
|
||||||
bootstrap="./vendor/typo3/testing-framework/Resources/Core/Build/UnitTestsBootstrap.php"
|
bootstrap="vendor/typo3/testing-framework/Resources/Core/Build/FunctionalTestsBootstrap.php"
|
||||||
|
|
||||||
colors="true"
|
colors="true"
|
||||||
convertErrorsToExceptions="false"
|
convertErrorsToExceptions="false"
|
||||||
convertWarningsToExceptions="false"
|
convertWarningsToExceptions="false"
|
||||||
|
@ -12,17 +13,21 @@
|
||||||
stopOnFailure="false"
|
stopOnFailure="false"
|
||||||
stopOnIncomplete="false"
|
stopOnIncomplete="false"
|
||||||
stopOnSkipped="false"
|
stopOnSkipped="false"
|
||||||
verbose="false">
|
verbose="false"
|
||||||
|
>
|
||||||
|
<coverage>
|
||||||
|
<include>
|
||||||
|
<directory suffix=".php">./Classes</directory>
|
||||||
|
</include>
|
||||||
|
</coverage>
|
||||||
|
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="unit-tests">
|
<testsuite name="functional-tests">
|
||||||
<directory>./Tests/Unit</directory>
|
<directory>./Tests/Functional</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
|
||||||
<filter>
|
<php>
|
||||||
<whitelist>
|
<env name="typo3DatabaseDriver" value="pdo_sqlite"/>
|
||||||
<directory suffix=".php">./Classes</directory>
|
</php>
|
||||||
</whitelist>
|
|
||||||
</filter>
|
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
|
Loading…
Reference in a new issue