[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:
Daniel Siepmann 2022-09-15 15:58:08 +02:00 committed by GitHub
parent 8fa50c3089
commit c45dee45b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 1145 additions and 1253 deletions

100
.github/workflows/ci.yaml vendored Normal file
View 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
View file

@ -15,3 +15,4 @@ bower_components
composer.lock
web
vendor
var/

View file

@ -8,9 +8,17 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
class Command implements RendererInterface
{
private ExtensionConfiguration $extensionConfiguration;
public function __construct(
ExtensionConfiguration $extensionConfiguration
) {
$this->extensionConfiguration = $extensionConfiguration;
}
public function getHtmlFromMjml($mjml): string
{
$conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('mjml');
$conf = $this->extensionConfiguration->get('mjml');
$temporaryMjmlFileWithPath = GeneralUtility::tempnam('mjml_', '.mjml');

View file

@ -1,23 +1,24 @@
<?php
declare(strict_types=1);
namespace Saccas\Mjml\View;
use Saccas\Mjml\Domain\Renderer\RendererInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
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);
$this->renderer = $renderer;
if ($this->renderer === null) {
$this->renderer = GeneralUtility::makeInstance(RendererInterface::class);
}
}
public function render($actionName = null): string

0
Configuration/Services.yaml Executable file → Normal file
View file

File diff suppressed because one or more lines are too long

View 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);
}
}

View file

@ -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,
],
]);
}
}

View file

@ -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

View file

@ -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.'
);
}
}

View file

@ -15,13 +15,13 @@
}
},
"require": {
"php": "^7.4 || ^8.0 || ^8.1",
"typo3/cms-core": "^9.5.0 || ^10.4.10 || ^11.5",
"typo3/cms-form": "^9.5.0 || ^10.4.10 || ^11.5"
"php": "^8.1",
"typo3/cms-core": "^11.5",
"typo3/cms-form": "^11.5"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.2.0",
"typo3/testing-framework": "^1.2.2 || ^6.16"
"typo3/testing-framework": "^6.16"
},
"scripts": {
"lint": [
@ -47,5 +47,11 @@
"cms-package-dir": "{$vendor-dir}/typo3/cms",
"web-dir": "web"
}
},
"config": {
"allow-plugins": {
"typo3/class-alias-loader": true,
"typo3/cms-composer-installers": true
}
}
}

View file

@ -8,4 +8,4 @@ mjmlBinaryPath = ./node_modules/mjml/bin/
mjmlBinary = mjml
# 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

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "mjml-typo3",
"dependencies": {
"mjml": "^4.6.2"
"mjml": "^4.13.0"
}
}

View file

@ -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"
backupStaticAttributes="false"
bootstrap="./vendor/typo3/testing-framework/Resources/Core/Build/UnitTestsBootstrap.php"
bootstrap="vendor/typo3/testing-framework/Resources/Core/Build/FunctionalTestsBootstrap.php"
colors="true"
convertErrorsToExceptions="false"
convertWarningsToExceptions="false"
@ -12,17 +13,21 @@
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
verbose="false">
verbose="false"
>
<coverage>
<include>
<directory suffix=".php">./Classes</directory>
</include>
</coverage>
<testsuites>
<testsuite name="unit-tests">
<directory>./Tests/Unit</directory>
<testsuite name="functional-tests">
<directory>./Tests/Functional</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">./Classes</directory>
</whitelist>
</filter>
<php>
<env name="typo3DatabaseDriver" value="pdo_sqlite"/>
</php>
</phpunit>