Commit 00d95c74 authored by catch's avatar catch
Browse files

Issue #3116856 by alexpott, Mile23: Workaround PHPUnit 8 warnings

parent e79723c3
......@@ -9,6 +9,7 @@
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutChangesToGlobalState="true"
failOnWarning="true"
printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter"
cacheResult="false">
<php>
......
......@@ -7,6 +7,7 @@
use Behat\Mink\Mink;
use Behat\Mink\Session;
use Drupal\Component\FileSystem\FileSystem as DrupalFilesystem;
use Drupal\Tests\Traits\PHPUnit8Warnings;
use PHPUnit\Framework\TestCase;
use Symfony\Component\BrowserKit\Client as SymfonyClient;
use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
......@@ -52,6 +53,7 @@
abstract class BuildTestBase extends TestCase {
use ExternalCommandRequirementsTrait;
use PHPUnit8Warnings;
/**
* The working directory where this test will manipulate files.
......
......@@ -21,6 +21,7 @@
use Drupal\Tests\ConfigTestTrait;
use Drupal\Tests\RandomGeneratorTrait;
use Drupal\Tests\TestRequirementsTrait;
use Drupal\Tests\Traits\PHPUnit8Warnings;
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
use PHPUnit\Framework\Exception;
use PHPUnit\Framework\TestCase;
......@@ -80,6 +81,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
use RandomGeneratorTrait;
use ConfigTestTrait;
use TestRequirementsTrait;
use PHPUnit8Warnings;
/**
* {@inheritdoc}
......
......@@ -16,6 +16,7 @@
use Drupal\Tests\block\Traits\BlockCreationTrait;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\Tests\Traits\PHPUnit8Warnings;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
use GuzzleHttp\Cookie\CookieJar;
......@@ -63,6 +64,7 @@ abstract class BrowserTestBase extends TestCase {
createUser as drupalCreateUser;
}
use XdebugRequestTrait;
use PHPUnit8Warnings;
/**
* The database prefix of this test run.
......
......@@ -561,7 +561,7 @@ public function testAnnotationWithVarTypeError($attribute,$type,$value,$given)
$parser->parse($docblock, $context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
$this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
}
}
......@@ -580,7 +580,7 @@ public function testAnnotationWithVarTypeArrayError($attribute,$type,$value,$giv
$parser->parse($docblock, $context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
$this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
}
}
......@@ -616,7 +616,7 @@ public function testAnnotationWithAttributesError($attribute,$type,$value,$given
$parser->parse($docblock, $context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
$this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
}
}
......@@ -635,7 +635,7 @@ public function testAnnotationWithAttributesWithVarTypeArrayError($attribute,$ty
$parser->parse($docblock, $context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
$this->assertStringContainsString("[Type Error] Attribute \"$attribute\" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
}
}
......@@ -660,7 +660,7 @@ public function testAnnotationWithRequiredAttributes()
$result = $parser->parse($docblock,$context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
$this->assertStringContainsString('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
}
$docblock = '@Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes(annot = @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation)';
......@@ -668,7 +668,7 @@ public function testAnnotationWithRequiredAttributes()
$result = $parser->parse($docblock,$context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
$this->assertStringContainsString('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
}
}
......@@ -694,7 +694,7 @@ public function testAnnotationWithRequiredAttributesWithoutContructor()
$result = $parser->parse($docblock,$context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
$this->assertStringContainsString('Attribute "annot" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
}
$docblock = '@Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor(annot = @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationTargetAnnotation)';
......@@ -702,7 +702,7 @@ public function testAnnotationWithRequiredAttributesWithoutContructor()
$result = $parser->parse($docblock,$context);
$this->fail();
} catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
$this->assertContains('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
$this->assertStringContainsString('Attribute "value" of @Drupal\Tests\Component\Annotation\Doctrine\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
}
}
......@@ -1145,7 +1145,7 @@ public function testCastInt()
$result = $parser->parse("@Name(foo=1234)");
$annot = $result[0];
$this->assertInternalType('int', $annot->foo);
$this->assertIsInt($annot->foo);
}
/**
......@@ -1157,7 +1157,7 @@ public function testCastNegativeInt()
$result = $parser->parse("@Name(foo=-1234)");
$annot = $result[0];
$this->assertInternalType('int', $annot->foo);
$this->assertIsInt($annot->foo);
}
/**
......@@ -1169,7 +1169,7 @@ public function testCastFloat()
$result = $parser->parse("@Name(foo=1234.345)");
$annot = $result[0];
$this->assertInternalType('float', $annot->foo);
$this->assertIsFloat($annot->foo);
}
/**
......@@ -1181,11 +1181,11 @@ public function testCastNegativeFloat()
$result = $parser->parse("@Name(foo=-1234.345)");
$annot = $result[0];
$this->assertInternalType('float', $annot->foo);
$this->assertIsFloat($annot->foo);
$result = $parser->parse("@Marker(-1234.345)");
$annot = $result[0];
$this->assertInternalType('float', $annot->value);
$this->assertIsFloat($annot->value);
}
public function testReservedKeywordsInAnnotations()
......
......@@ -24,7 +24,7 @@ public function testWriteHtaccessPrivate() {
$this->assertFileExists($htaccess_file);
$this->assertEquals('0444', substr(sprintf('%o', fileperms($htaccess_file)), -4));
$htaccess_contents = file_get_contents($htaccess_file);
$this->assertContains("Require all denied", $htaccess_contents);
$this->assertStringContainsString("Require all denied", $htaccess_contents);
}
/**
......@@ -37,7 +37,7 @@ public function testWriteHtaccessPublic() {
$this->assertFileExists($htaccess_file);
$this->assertEquals('0444', substr(sprintf('%o', fileperms($htaccess_file)), -4));
$htaccess_contents = file_get_contents($htaccess_file);
$this->assertNotContains("Require all denied", $htaccess_contents);
$this->assertStringNotContainsString("Require all denied", $htaccess_contents);
}
/**
......@@ -49,8 +49,8 @@ public function testWriteHtaccessForceOverwrite() {
file_put_contents($htaccess_file, "foo");
$this->assertTrue(FileSecurity::writeHtaccess(vfsStream::url('root'), TRUE, TRUE));
$htaccess_contents = file_get_contents($htaccess_file);
$this->assertContains("Require all denied", $htaccess_contents);
$this->assertNotContains("foo", $htaccess_contents);
$this->assertStringContainsString("Require all denied", $htaccess_contents);
$this->assertStringNotContainsString("foo", $htaccess_contents);
}
/**
......@@ -82,7 +82,7 @@ public function testWriteWebConfigForceOverwrite() {
$this->assertTrue(FileSecurity::writeWebConfig(vfsStream::url('root'), TRUE));
$this->assertFileExists($web_config_file);
$this->assertEquals('0444', substr(sprintf('%o', fileperms($web_config_file)), -4));
$this->assertNotContains("foo", $web_config_file);
$this->assertStringNotContainsString("foo", $web_config_file);
}
/**
......
......@@ -2,10 +2,13 @@
namespace Drupal\Tests\Composer\Plugin\Scaffold;
use Drupal\Tests\Traits\PHPUnit8Warnings;
/**
* Convenience class for creating fixtures.
*/
trait AssertUtilsTrait {
use PHPUnit8Warnings;
/**
* Asserts that a given file exists and is/is not a symlink.
......
......@@ -5,6 +5,7 @@
use Drupal\Composer\Plugin\Scaffold\Operations\AppendOp;
use Drupal\Composer\Plugin\Scaffold\ScaffoldOptions;
use Drupal\Tests\Composer\Plugin\Scaffold\Fixtures;
use Drupal\Tests\Traits\PHPUnit8Warnings;
use PHPUnit\Framework\TestCase;
/**
......@@ -13,6 +14,7 @@
* @group Scaffold
*/
class AppendOpTest extends TestCase {
use PHPUnit8Warnings;
/**
* @covers ::process
......
......@@ -5,6 +5,7 @@
use Drupal\Composer\Plugin\Scaffold\Operations\ReplaceOp;
use Drupal\Composer\Plugin\Scaffold\ScaffoldOptions;
use Drupal\Tests\Composer\Plugin\Scaffold\Fixtures;
use Drupal\Tests\Traits\PHPUnit8Warnings;
use PHPUnit\Framework\TestCase;
/**
......@@ -13,6 +14,7 @@
* @group Scaffold
*/
class ReplaceOpTest extends TestCase {
use PHPUnit8Warnings;
/**
* @covers ::process
......
......@@ -5,6 +5,7 @@
use Drupal\Composer\Plugin\Scaffold\Operations\SkipOp;
use Drupal\Composer\Plugin\Scaffold\ScaffoldOptions;
use Drupal\Tests\Composer\Plugin\Scaffold\Fixtures;
use Drupal\Tests\Traits\PHPUnit8Warnings;
use PHPUnit\Framework\TestCase;
/**
......@@ -13,6 +14,7 @@
* @group Scaffold
*/
class SkipOpTest extends TestCase {
use PHPUnit8Warnings;
/**
* @covers ::process
......
......@@ -77,10 +77,8 @@ public function testRootMergeConfig() {
$plugin_config = $ref_plugin_config->invoke($config);
$this->assertArraySubset([
'isa/string' => ['test_dir'],
'an/array' => ['test_dir', 'doc_dir'],
], $plugin_config);
$this->assertSame(['test_dir'], $plugin_config['isa/string']);
$this->assertSame(['test_dir', 'doc_dir'], $plugin_config['an/array']);
}
/**
......
......@@ -114,12 +114,12 @@ public function testQuickStartCommand() {
sleep(1);
}
// The progress bar uses STDERR to write messages.
$this->assertContains('Congratulations, you installed Drupal!', $process->getErrorOutput());
$this->assertStringContainsString('Congratulations, you installed Drupal!', $process->getErrorOutput());
$this->assertNotFalse($port, "Web server running on port $port");
// Give the server a couple of seconds to be ready.
sleep(2);
$this->assertContains("127.0.0.1:$port/user/reset/1/", $process->getOutput());
$this->assertStringContainsString("127.0.0.1:$port/user/reset/1/", $process->getOutput());
// Generate a cookie so we can make a request against the installed site.
define('DRUPAL_TEST_IN_CHILD_SITE', FALSE);
......@@ -130,7 +130,7 @@ public function testQuickStartCommand() {
$response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
$content = (string) $response->getBody();
$this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
$this->assertStringContainsString('Test site ' . $this->testDb->getDatabasePrefix(), $content);
// Stop the web server.
$process->stop();
......@@ -162,9 +162,9 @@ public function testPhpRequirement() {
}
$error_output = $process->getErrorOutput();
$this->assertContains('Your PHP installation is too old.', $error_output);
$this->assertContains('Drupal requires at least PHP', $error_output);
$this->assertContains(DRUPAL_MINIMUM_SUPPORTED_PHP, $error_output);
$this->assertStringContainsString('Your PHP installation is too old.', $error_output);
$this->assertStringContainsString('Drupal requires at least PHP', $error_output);
$this->assertStringContainsString(DRUPAL_MINIMUM_SUPPORTED_PHP, $error_output);
// Stop the web server.
$process->stop();
......@@ -191,7 +191,7 @@ public function testQuickStartInstallAndServerCommands() {
$install_process->setTimeout(500);
$result = $install_process->run();
// The progress bar uses STDERR to write messages.
$this->assertContains('Congratulations, you installed Drupal!', $install_process->getErrorOutput());
$this->assertStringContainsString('Congratulations, you installed Drupal!', $install_process->getErrorOutput());
$this->assertSame(0, $result);
// Run the PHP built-in webserver.
......@@ -215,7 +215,7 @@ public function testQuickStartInstallAndServerCommands() {
sleep(1);
}
$this->assertEquals('', $server_process->getErrorOutput());
$this->assertContains("127.0.0.1:$port/user/reset/1/", $server_process->getOutput());
$this->assertStringContainsString("127.0.0.1:$port/user/reset/1/", $server_process->getOutput());
$this->assertNotFalse($port, "Web server running on port $port");
// Give the server a couple of seconds to be ready.
......@@ -230,7 +230,7 @@ public function testQuickStartInstallAndServerCommands() {
$response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
$content = (string) $response->getBody();
$this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
$this->assertStringContainsString('Test site ' . $this->testDb->getDatabasePrefix(), $content);
// Try to re-install over the top of an existing site.
$install_command = [
......@@ -244,13 +244,13 @@ public function testQuickStartInstallAndServerCommands() {
$install_process->inheritEnvironmentVariables();
$install_process->setTimeout(500);
$result = $install_process->run();
$this->assertContains('Drupal is already installed.', $install_process->getOutput());
$this->assertStringContainsString('Drupal is already installed.', $install_process->getOutput());
$this->assertSame(0, $result);
// Ensure the site name has not changed.
$response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
$content = (string) $response->getBody();
$this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
$this->assertStringContainsString('Test site ' . $this->testDb->getDatabasePrefix(), $content);
// Stop the web server.
$server_process->stop();
......@@ -272,7 +272,7 @@ public function testQuickStartCommandProfileValidation() {
$process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$process->inheritEnvironmentVariables();
$process->run();
$this->assertContains('\'umami\' is not a valid install profile. Did you mean \'demo_umami\'?', $process->getErrorOutput());
$this->assertStringContainsString('\'umami\' is not a valid install profile. Did you mean \'demo_umami\'?', $process->getErrorOutput());
}
/**
......@@ -288,7 +288,7 @@ public function testServerWithNoInstall() {
$server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$server_process->inheritEnvironmentVariables();
$server_process->run();
$this->assertContains('No installation found. Use the \'install\' command.', $server_process->getErrorOutput());
$this->assertStringContainsString('No installation found. Use the \'install\' command.', $server_process->getErrorOutput());
}
/**
......
......@@ -114,6 +114,7 @@ public static function isDeprecationSkipped($message) {
'%The "[^"]+" class extends "Symfony\\\\Component\\\\EventDispatcher\\\\Event" that is deprecated since Symfony 4\.3, use "Symfony\\\\Contracts\\\\EventDispatcher\\\\Event" instead\.$%',
'%The "Symfony\\\\Component\\\\Validator\\\\Context\\\\ExecutionContextInterface::.*\(\)" method is considered internal Used by the validator engine. Should not be called by user\s\*\s*code\. It may change without further notice\. You should not extend it from "[^"]+".%',
'%The ".*" service relies on the deprecated "Symfony\\\\Component\\\\Debug\\\\BufferingLogger" class\. It should either be deprecated or its implementation upgraded\.%',
'%The "PHPUnit\\\\Framework\\\\TestCase::addWarning\(\)" method is considered internal%',
];
return (bool) preg_filter($dynamic_skipped_deprecations, '$0', $message);
}
......
<?php
namespace Drupal\Tests\Traits;
/**
* Used to ignore warnings being added by PHPUnit 8.
*
* This trait exists to allow Drupal 8 tests using PHPUnit 7 and Drupal 9 tests
* using PHPUnit 8 to happily co-exist. Once Drupal 8 and Drupal 9 are not so
* closely aligned these will be fixed in core and the warnings will be emitted
* from the test runner.
*
* @todo https://www.drupal.org/project/drupal/issues/3110543 Remove the ignored
* warnings to support PHPUnit 9.
*
* @internal
*/
trait PHPUnit8Warnings {
/**
* The list of warnings to ignore.
*
* @var string[]
*/
private static $ignoredWarnings = [
'Using assertContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringContainsString() or assertStringContainsStringIgnoringCase() instead.',
'Using assertNotContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringNotContainsString() or assertStringNotContainsStringIgnoringCase() instead.',
'assertArraySubset() is deprecated and will be removed in PHPUnit 9.',
'assertInternalType() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertIsArray(), assertIsBool(), assertIsFloat(), assertIsInt(), assertIsNumeric(), assertIsObject(), assertIsResource(), assertIsString(), assertIsScalar(), assertIsCallable(), or assertIsIterable() instead.',
'readAttribute() is deprecated and will be removed in PHPUnit 9.',
'getObjectAttribute() is deprecated and will be removed in PHPUnit 9.',
'The optional $canonicalize parameter of assertEquals() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertEqualsCanonicalizing() instead.',
'assertAttributeEquals() is deprecated and will be removed in PHPUnit 9.',
'assertAttributeSame() is deprecated and will be removed in PHPUnit 9.',
'assertAttributeInstanceOf() is deprecated and will be removed in PHPUnit 9.',
'assertAttributeEmpty() is deprecated and will be removed in PHPUnit 9.',
'The optional $ignoreCase parameter of assertContains() is deprecated and will be removed in PHPUnit 9.',
'The optional $ignoreCase parameter of assertNotContains() is deprecated and will be removed in PHPUnit 9.',
];
/**
* Ignores specific PHPUnit 8 warnings.
*
* @see \PHPUnit\Framework\TestCase::addWarning()
*
* @internal
*/
public function addWarning(string $warning): void {
if (in_array($warning, self::$ignoredWarnings, TRUE)) {
return;
}
parent::addWarning($warning);
}
}
......@@ -9,6 +9,7 @@
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
use Drupal\Tests\Traits\PHPUnit8Warnings;
use PHPUnit\Framework\TestCase;
/**
......@@ -17,6 +18,7 @@
* @ingroup testing
*/
abstract class UnitTestCase extends TestCase {
use PHPUnit8Warnings;
/**
* The random generator.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment