diff --git a/composer.json b/composer.json index a79cf4cb0cdefb7e5ba4f768e04c8420ea9f2d8a..faa78c64dd0da7adcab2ca1b722f6bbe02165264 100644 --- a/composer.json +++ b/composer.json @@ -146,7 +146,7 @@ "drupal/module_filter": "3.2", "drupal/multiple_fields_remove_button": "^1.0@alpha", "drupal/pantheon_advanced_page_cache": "1.2", - "drupal/paragraphs": "1.12", + "drupal/paragraphs": "1.15", "drupal/pathauto": "1.11", "drupal/queue_mail": "^1.4", "drupal/realname": "^2.0@beta", diff --git a/composer.lock b/composer.lock index af6ea3061902fcb188d0d1a189fad51600ef4857..c1ba16def06574db6fa54f086dd875d61b37f5aa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "00b3339b124e176f69a985ebf27eaa8c", + "content-hash": "66825c008c7e0270cc8e1f922cb9b8d6", "packages": [ { "name": "alchemy/zippy", @@ -6194,33 +6194,32 @@ }, { "name": "drupal/paragraphs", - "version": "1.12.0", + "version": "1.15.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/paragraphs.git", - "reference": "8.x-1.12" + "reference": "8.x-1.15" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/paragraphs-8.x-1.12.zip", - "reference": "8.x-1.12", - "shasum": "3b67d8af1160af42d93a4610be1e02869e428965" + "url": "https://ftp.drupal.org/files/projects/paragraphs-8.x-1.15.zip", + "reference": "8.x-1.15", + "shasum": "2ed2d3199553010fa1c500181bbebe676e9e60c1" }, "require": { - "drupal/core": "^8.8 || ^9", + "drupal/core": "^9.3 || ^10", "drupal/entity_reference_revisions": "~1.3" }, "require-dev": { - "drupal/block_field": "~1.0", - "drupal/ctools": "3.x-dev", - "drupal/diff": "~1.0", + "drupal/block_field": "1.x-dev", + "drupal/diff": "1.x-dev", "drupal/entity_browser": "2.x-dev", "drupal/entity_usage": "2.x-dev", "drupal/field_group": "3.x-dev", - "drupal/inline_entity_form": "~1.0", + "drupal/inline_entity_form": "1.x-dev", "drupal/paragraphs-paragraphs_library": "*", - "drupal/replicate": "~1.0", - "drupal/search_api": "~1.0", + "drupal/replicate": "1.x-dev", + "drupal/search_api": "1.x-dev", "drupal/search_api_db": "*" }, "suggest": { @@ -6229,8 +6228,8 @@ "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.12", - "datestamp": "1590140081", + "version": "8.x-1.15", + "datestamp": "1661440897", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -13181,16 +13180,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v4.4.44", + "version": "v4.4.49", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471" + "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/25502a57182ba1e15da0afd64c975cae4d0a1471", - "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9065fe97dbd38a897e95ea254eb5ddfe1310f734", + "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734", "shasum": "" }, "require": { @@ -13247,7 +13246,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v4.4.44" + "source": "https://github.com/symfony/dependency-injection/tree/v4.4.49" }, "funding": [ { @@ -13263,7 +13262,7 @@ "type": "tidelift" } ], - "time": "2022-07-20T09:59:04+00:00" + "time": "2022-11-16T16:18:09+00:00" }, { "name": "symfony/deprecation-contracts", @@ -15041,16 +15040,16 @@ }, { "name": "symfony/psr-http-message-bridge", - "version": "v2.1.3", + "version": "v2.1.4", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840" + "reference": "a125b93ef378c492e274f217874906fb9babdebb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/d444f85dddf65c7e57c58d8e5b3a4dbb593b1840", - "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/a125b93ef378c492e274f217874906fb9babdebb", + "reference": "a125b93ef378c492e274f217874906fb9babdebb", "shasum": "" }, "require": { @@ -15109,7 +15108,7 @@ ], "support": { "issues": "https://github.com/symfony/psr-http-message-bridge/issues", - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.3" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.4" }, "funding": [ { @@ -15125,7 +15124,7 @@ "type": "tidelift" } ], - "time": "2022-09-05T10:34:54+00:00" + "time": "2022-11-28T22:46:34+00:00" }, { "name": "symfony/routing", diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index f5e38062421407fdffa9af75b8a1c35634088bc0..ae4eebf790f4460d2960be43944f303e98c4d5d3 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -6412,34 +6412,33 @@ }, { "name": "drupal/paragraphs", - "version": "1.12.0", - "version_normalized": "1.12.0.0", + "version": "1.15.0", + "version_normalized": "1.15.0.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/paragraphs.git", - "reference": "8.x-1.12" + "reference": "8.x-1.15" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/paragraphs-8.x-1.12.zip", - "reference": "8.x-1.12", - "shasum": "3b67d8af1160af42d93a4610be1e02869e428965" + "url": "https://ftp.drupal.org/files/projects/paragraphs-8.x-1.15.zip", + "reference": "8.x-1.15", + "shasum": "2ed2d3199553010fa1c500181bbebe676e9e60c1" }, "require": { - "drupal/core": "^8.8 || ^9", + "drupal/core": "^9.3 || ^10", "drupal/entity_reference_revisions": "~1.3" }, "require-dev": { - "drupal/block_field": "~1.0", - "drupal/ctools": "3.x-dev", - "drupal/diff": "~1.0", + "drupal/block_field": "1.x-dev", + "drupal/diff": "1.x-dev", "drupal/entity_browser": "2.x-dev", "drupal/entity_usage": "2.x-dev", "drupal/field_group": "3.x-dev", - "drupal/inline_entity_form": "~1.0", + "drupal/inline_entity_form": "1.x-dev", "drupal/paragraphs-paragraphs_library": "*", - "drupal/replicate": "~1.0", - "drupal/search_api": "~1.0", + "drupal/replicate": "1.x-dev", + "drupal/search_api": "1.x-dev", "drupal/search_api_db": "*" }, "suggest": { @@ -6448,8 +6447,8 @@ "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.12", - "datestamp": "1590140081", + "version": "8.x-1.15", + "datestamp": "1661440897", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -6470,10 +6469,6 @@ "name": "Frans", "homepage": "https://www.drupal.org/user/514222" }, - { - "name": "Primsi", - "homepage": "https://www.drupal.org/user/282629" - }, { "name": "jeroen.b", "homepage": "https://www.drupal.org/user/1853532" @@ -6485,6 +6480,10 @@ { "name": "miro_dietiker", "homepage": "https://www.drupal.org/user/227761" + }, + { + "name": "Primsi", + "homepage": "https://www.drupal.org/user/282629" } ], "description": "Enables the creation of Paragraphs entities.", @@ -13698,17 +13697,17 @@ }, { "name": "symfony/dependency-injection", - "version": "v4.4.44", - "version_normalized": "4.4.44.0", + "version": "v4.4.49", + "version_normalized": "4.4.49.0", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471" + "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/25502a57182ba1e15da0afd64c975cae4d0a1471", - "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9065fe97dbd38a897e95ea254eb5ddfe1310f734", + "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734", "shasum": "" }, "require": { @@ -13739,7 +13738,7 @@ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", "symfony/yaml": "" }, - "time": "2022-07-20T09:59:04+00:00", + "time": "2022-11-16T16:18:09+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -13767,7 +13766,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v4.4.44" + "source": "https://github.com/symfony/dependency-injection/tree/v4.4.49" }, "funding": [ { @@ -15627,17 +15626,17 @@ }, { "name": "symfony/psr-http-message-bridge", - "version": "v2.1.3", - "version_normalized": "2.1.3.0", + "version": "v2.1.4", + "version_normalized": "2.1.4.0", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840" + "reference": "a125b93ef378c492e274f217874906fb9babdebb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/d444f85dddf65c7e57c58d8e5b3a4dbb593b1840", - "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/a125b93ef378c492e274f217874906fb9babdebb", + "reference": "a125b93ef378c492e274f217874906fb9babdebb", "shasum": "" }, "require": { @@ -15658,7 +15657,7 @@ "suggest": { "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" }, - "time": "2022-09-05T10:34:54+00:00", + "time": "2022-11-28T22:46:34+00:00", "type": "symfony-bridge", "extra": { "branch-alias": { @@ -15698,7 +15697,7 @@ ], "support": { "issues": "https://github.com/symfony/psr-http-message-bridge/issues", - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.3" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.4" }, "funding": [ { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 1299061afa43b57da0ff0cf677599a7e21c19ec6..40b2bf6daf5841149126ec149a88a4504b9bcb2f 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'osu-asc-webservices/d8-upstream', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'ba6af3568d179c683bcb49150597c4f6eb32e14e', + 'reference' => '7b38d41b8b6ae95e9b0320d434f2220a4367f2d9', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -1064,9 +1064,9 @@ 'dev_requirement' => false, ), 'drupal/paragraphs' => array( - 'pretty_version' => '1.12.0', - 'version' => '1.12.0.0', - 'reference' => '8.x-1.12', + 'pretty_version' => '1.15.0', + 'version' => '1.15.0.0', + 'reference' => '8.x-1.15', 'type' => 'drupal-module', 'install_path' => __DIR__ . '/../../web/modules/paragraphs', 'aliases' => array(), @@ -1594,7 +1594,7 @@ 'osu-asc-webservices/d8-upstream' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'ba6af3568d179c683bcb49150597c4f6eb32e14e', + 'reference' => '7b38d41b8b6ae95e9b0320d434f2220a4367f2d9', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -2190,9 +2190,9 @@ 'dev_requirement' => false, ), 'symfony/dependency-injection' => array( - 'pretty_version' => 'v4.4.44', - 'version' => '4.4.44.0', - 'reference' => '25502a57182ba1e15da0afd64c975cae4d0a1471', + 'pretty_version' => 'v4.4.49', + 'version' => '4.4.49.0', + 'reference' => '9065fe97dbd38a897e95ea254eb5ddfe1310f734', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), @@ -2403,9 +2403,9 @@ 'dev_requirement' => false, ), 'symfony/psr-http-message-bridge' => array( - 'pretty_version' => 'v2.1.3', - 'version' => '2.1.3.0', - 'reference' => 'd444f85dddf65c7e57c58d8e5b3a4dbb593b1840', + 'pretty_version' => 'v2.1.4', + 'version' => '2.1.4.0', + 'reference' => 'a125b93ef378c492e274f217874906fb9babdebb', 'type' => 'symfony-bridge', 'install_path' => __DIR__ . '/../symfony/psr-http-message-bridge', 'aliases' => array(), diff --git a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php index 3b8086d0931e6c38844e07a886d1c6fb73bf39ef..185a097ebe20bb2b66a4a1ceca23ac0be34efedc 100644 --- a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php +++ b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php @@ -42,7 +42,7 @@ public function process(ContainerBuilder $container) $tagsToKeep = $container->hasParameter('container.behavior_describing_tags') ? $container->getParameter('container.behavior_describing_tags') - : ['container.do_not_inline', 'container.service_locator', 'container.service_subscriber']; + : ['container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'container.service_subscriber.locator']; foreach ($definitions as [$id, $definition]) { $decoratedService = $definition->getDecoratedService(); diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php index 5fdbe5686dbfa81017a0f4101e9592f568df5c81..72b093043bf15cff415a6e315b55f0539f01f011 100644 --- a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php +++ b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php @@ -39,6 +39,10 @@ protected function processValue($value, $isRoot = false) return self::register($this->container, $value->getValues()); } + if ($value instanceof Definition) { + $value->setBindings(parent::processValue($value->getBindings())); + } + if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) { return parent::processValue($value, $isRoot); } diff --git a/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php b/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php index 61650df9f680570a249f08b924ec2b8991104871..b1b6f9ae260ff021af0cce236efb03c57e31b81c 100644 --- a/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php +++ b/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php @@ -142,7 +142,7 @@ public function createResponse(Response $symfonyResponse) $stream->write($buffer); return ''; - }); + }, 1); $symfonyResponse->sendContent(); ob_end_clean(); diff --git a/web/modules/paragraphs/README.txt b/web/modules/paragraphs/README.txt index c4e36a8079fc052d9bda1fa07e6bbdc5773c7b59..e2eff04187f8d226966ec948da83dd41d99590f9 100644 --- a/web/modules/paragraphs/README.txt +++ b/web/modules/paragraphs/README.txt @@ -18,18 +18,19 @@ WIDGETS Paragraphs currently provides two different widgets that can be used. - * Classic: a stable UI with limited features that will not be changed or - updated. + * Legacy (formerly Classic): a stable UI with limited features that will not be + changed or updated. - * Experimental: This widget provides additional features like duplicating - paragraphs and a drag & drop mode (see below) as well a improved user - experience. It is just as well tested as the classic UI but major changes - between versions are to be expected. + * Stable (formerly Experimental): This widget provides additional features like + duplicating paragraphs and a drag & drop mode (see below) as well a improved + user experience. It is now the default and recommended widget, but changes + between versions are to be expected and customizations might need to be + updated. Drag & drop ------------- -The experimental widget offers a separate mode that allows to re-sort paragraphs +The stable widget offers a separate mode that allows to re-sort paragraphs not just within the same level but it is also possible to change the hierarchy and move paragraphs including their children around and into other paragraphs. diff --git a/web/modules/paragraphs/composer.json b/web/modules/paragraphs/composer.json index c65f9072b65d912026e9a8afe6071ae53b66aba0..6bf7b1847acf3d016cba6dc0135e22bb6475b412 100644 --- a/web/modules/paragraphs/composer.json +++ b/web/modules/paragraphs/composer.json @@ -10,14 +10,13 @@ "drupal/entity_browser": "Recommended for an improved user experience when using the Paragraphs library module" }, "require-dev": { - "drupal/diff": "~1.0", - "drupal/replicate": "~1.0", - "drupal/inline_entity_form": "~1.0", + "drupal/diff": "1.x-dev", + "drupal/replicate": "1.x-dev", + "drupal/inline_entity_form": "1.x-dev", "drupal/field_group": "3.x-dev", - "drupal/block_field": "~1.0", - "drupal/ctools": "3.x-dev", + "drupal/block_field": "1.x-dev", "drupal/entity_browser": "2.x-dev", "drupal/entity_usage": "2.x-dev", - "drupal/search_api": "~1.0" + "drupal/search_api": "1.x-dev" } } diff --git a/web/modules/paragraphs/css/README.md b/web/modules/paragraphs/css/README.md index a5da7f76832dbabc26540d9f3294cfb34652d3c5..88748a206f7ba0913e08b281b58156b882550fc3 100644 --- a/web/modules/paragraphs/css/README.md +++ b/web/modules/paragraphs/css/README.md @@ -5,10 +5,10 @@ development. For the people that wants to contribute to paragraphs CSS code you have two options: 1. If you want to propose CSS improvement but do not want to use our Gulp/SASS - toolchain then just change compiled CSS and create a issue with a patch from - it. When patch is accepted we will then transfer your changes to SASS and + toolchain then just change the compiled CSS and create an issue with a patch from + it. When the patch is accepted we will then transfer your changes to SASS and recompile CSS files. -2. Instead of manually changing CSS files, recommended way is to reuse our +2. Instead of manually changing CSS files, the recommended way is to reuse our Gulp/SASS process and do changes in appropriate SASS files and then recompile it to CSS. @@ -16,13 +16,13 @@ have two options: ## Preparing your development environment for Gulp/SASS toolchain If you want to do __step 2.__ but do not have needed Gulp/SASS experience do not -worry, process is not that difficult and is explained in next steps: +worry, the process is not that difficult and is explained in next steps: - First thing you need to have is nodejs server on your machine. Please check - https://nodejs.org/en/download/package-manager/ and follow steps of nodejs + https://nodejs.org/en/download/package-manager/ and follow the steps of nodejs server installation for your operating system. -- Then change directory to paragraphs CSS folder +- Then change the directory to paragraphs CSS folder `$ cd paragraphs/css` @@ -37,35 +37,35 @@ worry, process is not that difficult and is explained in next steps: - You are now able to compile paragraphs CSS from our SASS source files. In the same folder execute - `$ gulp` + `$ npx gulp` -If you did not get any error your local machine is now ready and with last +If you did not get any errors your local machine is now ready and with last command you already compiled paragraphs SASS files to CSS. -For closer look at our Gulp configuration and tasks check +For a closer look at our Gulp configuration and tasks check paragraphs/css/gulpfile.js. ## Doing changes in CSS over SASS -Now you are ready to do necessary changes to paragraphs CSS. First locate the -CSS selector rule you want to change in CSS and then locate this rule in -appropriate SASS file. Do the change in SASS file, save it and just execute -again `$ gulp` from your console. +Now you are ready to do the necessary changes to paragraphs CSS. First locate the +CSS selector rule you want to change in CSS and then locate this rule in the +appropriate SASS file. Do the change in the SASS file, save it and just execute +again `$ npx gulp` from your console. -When you are satisfied with result in CSS files, create Drupal paragraphs issue -and a patch in standard way. +When you are satisfied with the result in CSS files, create a Drupal paragraphs +issue and a patch in standard way. ## Making sure that your changes are aligned with CSS code standards -If you are getting warning when executing `$ gulp` that are coming from +If you are getting any warnings when executing `$ npx gulp` that are coming from stylelint do not worry. -This warnings are coming from stylelint postcss plugin which is doing statical +These warnings are coming from stylelint postcss plugin which is doing statical checking of generated CSS files and this simply means that generated CSS code is not compatible with paragraphs CSS coding standards. -Generally before accepting SASS/CSS change you need to be sure that all warnings +Generally before accepting any SASS/CSS changes you need to be sure that all warnings are fixed. But in some cases warnings can not be avoided, in that case please use turning rules off from SASS like explained in https://github.com/stylelint/stylelint/blob/master/docs/user-guide/configuration.md#turning-rules-off-from-within-your-css. Note that you can use also `//` @@ -73,11 +73,11 @@ comment syntax instead of `/* ... */` You can also just run gulp sass lint task: -`$ gulp sass:lint` +`$ npx gulp sass:lint` ## Resources -SASS is a very powerful tool and its always good option to know your tools +SASS is a very powerful tool and its always a good option to know your tools better. Please check http://sass-lang.com/guide for more information on SASS syntax and it features. diff --git a/web/modules/paragraphs/css/gulp-tasks.js b/web/modules/paragraphs/css/gulp-tasks.js index 05245943e612e8c674c74ab61c52a7a1978b3d02..76b50e00c737aec0afcbd19bf1114344c1b9ff31 100644 --- a/web/modules/paragraphs/css/gulp-tasks.js +++ b/web/modules/paragraphs/css/gulp-tasks.js @@ -18,7 +18,7 @@ module.exports = function(gulp, plugins, options) { // Defining gulp tasks. gulp.task('sass', function() { - return gulp.src(options.scssSrc + '/*.scss') + return gulp.src(options.scssSrc + '*.scss') .pipe(plugins.sass({ outputStyle: 'expanded', includePaths: options.sassIncludePaths @@ -28,10 +28,10 @@ module.exports = function(gulp, plugins, options) { }); gulp.task('sass:lint', function () { - return gulp.src(options.scssSrc + '/*.scss') + return gulp.src(options.scssSrc + '*.scss') .pipe(plugins.postcss(options.processors, {syntax: plugins.syntax_scss})) }); // Default task to run everything in correct order. - gulp.task('default', ['sass:lint', 'sass']); + gulp.task('default', gulp.series(gulp.parallel('sass:lint', 'sass'))); }; diff --git a/web/modules/paragraphs/css/package-lock.json b/web/modules/paragraphs/css/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..73778a6b1a2fdc7a0882319ada2617f1345ce621 --- /dev/null +++ b/web/modules/paragraphs/css/package-lock.json @@ -0,0 +1,7185 @@ +{ + "name": "paragraphs", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.0.tgz", + "integrity": "sha512-eyoaac3btgU8eJlvh01En8OCKzRqlLe2G5jDsCr3RiE2uLGMEEB1aaGwVVpwR8M95956tGH6R+9edC++OvzaVw==", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", + "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==", + "dev": true, + "requires": { + "browserslist": "^2.11.3", + "caniuse-lite": "^1.0.30000805", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.17", + "postcss-value-parser": "^3.2.3" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "dev": true + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000792", + "electron-to-chromium": "^1.3.30" + } + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001090", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001090.tgz", + "integrity": "sha512-QzPRKDCyp7RhjczTPZaqK3CjPA5Ht2UnXhZhCI4f7QiB5JK6KEuZBxIzyWnB3wO4hgAj4GMRxAhuiacfw0Psjg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "ccount": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz", + "integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz", + "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-regexp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz", + "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==", + "dev": true, + "requires": { + "is-regexp": "^1.0.0", + "is-supported-regexp-flag": "^1.0.0" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", + "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.4.3", + "minimist": "^1.2.0", + "object-assign": "^4.1.0", + "os-homedir": "^1.0.1", + "parse-json": "^2.2.0", + "require-from-string": "^1.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "electron-to-chromium": { + "version": "1.3.483", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.483.tgz", + "integrity": "sha512-+05RF8S9rk8S0G8eBCqBRBaRq7+UN3lDs2DAvnG8SBSgQO3hjy0+qt4CmRk5eiuGbTcaicgXfPmBi31a+BD3lg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + }, + "dependencies": { + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + } + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "execall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", + "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", + "dev": true, + "requires": { + "clone-regexp": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", + "dev": true + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "gonzales-pe": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", + "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + } + }, + "yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } + }, + "gulp-load-plugins": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-load-plugins/-/gulp-load-plugins-1.6.0.tgz", + "integrity": "sha512-HlCODki0WHJvQIgAsJYOTkyo0c7TsDCetvfhrdGz9JYPL6A4mFRMGmKfoi6JmXjA/vvzg+fkT91c9FBh7rnkyg==", + "dev": true, + "requires": { + "array-unique": "^0.2.1", + "fancy-log": "^1.2.0", + "findup-sync": "^3.0.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "micromatch": "^3.1.10", + "resolve": "^1.1.7" + }, + "dependencies": { + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + } + } + }, + "gulp-postcss": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-7.0.1.tgz", + "integrity": "sha1-Pxw22xGXFAw5nCUt3/M5EpY445U=", + "dev": true, + "requires": { + "fancy-log": "^1.3.2", + "plugin-error": "^0.1.2", + "postcss": "^6.0.0", + "postcss-load-config": "^1.2.0", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "gulp-sass": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-3.2.1.tgz", + "integrity": "sha512-UATbRpSDsyXCnpYSPBUEvdvtSEzksJs7/oQ0CujIpzKqKrO6vlnYwhX2UTsGrf4rNLwqlSSaM271It0uHYvJ3Q==", + "dev": true, + "requires": { + "gulp-util": "^3.0", + "lodash.clonedeep": "^4.3.2", + "node-sass": "^4.8.3", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", + "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-supported-regexp-flag": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz", + "integrity": "sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-base64": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.2.tgz", + "integrity": "sha512-1hgLrLIrmCgZG+ID3VoLNLOSwjGnoZa8tyrUdEteMeIzsT6PH7PMLyUvbDwzNE56P3PNxyvuIOx4Uh2E5rzQIw==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "known-css-properties": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.5.0.tgz", + "integrity": "sha512-LOS0CoS8zcZnB1EjLw4LLqDXw8nvt3AGH5dXLQP3D9O1nLLA+9GC5GnPl5mmF+JiQAtSX4VyZC7KvEtcA4kUtA==", + "dev": true + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "longest-streak": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", + "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true + }, + "markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true + }, + "mdast-util-compact": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz", + "integrity": "sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg==", + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "node-sass": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", + "dev": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash": "^4.17.15", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.13.2", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "2.2.5", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-selector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", + "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", + "dev": true + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + } + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "postcss-bem-linter": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/postcss-bem-linter/-/postcss-bem-linter-2.7.1.tgz", + "integrity": "sha512-ZrioXOS7tDQRynp5KoMgcukRerPWitTpkAE37XWmQNuNO8R4vYAh/f4/I7+5MwwfzTY6X6oy3Ab3iaSMNMF6vg==", + "dev": true, + "requires": { + "minimatch": "^3.0.3", + "postcss": "^5.0.0", + "postcss-resolve-nested-selector": "^0.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "postcss-html": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.12.0.tgz", + "integrity": "sha512-KxKUpj7AY7nlCbLcTOYxdfJnGE7QFAfU2n95ADj1Q90RM/pOLdz8k3n4avOyRFs7MDQHcRzJQWM1dehCwJxisQ==", + "dev": true, + "requires": { + "htmlparser2": "^3.9.2", + "remark": "^8.0.0", + "unist-util-find-all-after": "^1.0.1" + } + }, + "postcss-less": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-1.1.5.tgz", + "integrity": "sha512-QQIiIqgEjNnquc0d4b6HDOSFZxbFQoy4MPpli2lSLpKhMyBkKwwca2HFqu4xzxlKID/F2fxSOowwtKpgczhF7A==", + "dev": true, + "requires": { + "postcss": "^5.2.16" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "postcss-load-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", + "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", + "dev": true, + "requires": { + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0", + "postcss-load-options": "^1.2.0", + "postcss-load-plugins": "^2.3.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "postcss-load-options": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", + "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", + "dev": true, + "requires": { + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "postcss-load-plugins": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", + "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", + "dev": true, + "requires": { + "cosmiconfig": "^2.1.1", + "object-assign": "^4.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-reporter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", + "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "lodash": "^4.17.4", + "log-symbols": "^2.0.0", + "postcss": "^6.0.8" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", + "dev": true + }, + "postcss-safe-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz", + "integrity": "sha1-t1Pv9sfArqXoN1++TN6L+QY/8UI=", + "dev": true, + "requires": { + "postcss": "^6.0.6" + } + }, + "postcss-sass": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.2.0.tgz", + "integrity": "sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg==", + "dev": true, + "requires": { + "gonzales-pe": "^4.0.3", + "postcss": "^6.0.6" + } + }, + "postcss-scss": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-1.0.6.tgz", + "integrity": "sha512-4EFYGHcEw+H3E06PT/pQQri06u/1VIIPjeJQaM8skB80vZuXMhp4cSNV5azmdNkontnOID/XYWEvEEELLFB1ww==", + "dev": true, + "requires": { + "postcss": "^6.0.23" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-sorting": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-3.1.0.tgz", + "integrity": "sha512-YCPTcJwGIInF1LpMD1lIYvMHTGUL4s97o/OraA6eKvoauhhk6vjwOWDDjm6uRKqug/kyDPMKEzmYZ6FtW6RDgw==", + "dev": true, + "requires": { + "lodash": "^4.17.4", + "postcss": "^6.0.13" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "remark": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-8.0.0.tgz", + "integrity": "sha512-K0PTsaZvJlXTl9DN6qYlvjTkqSZBFELhROZMrblm2rB+085flN84nz4g/BscKRMqDvhzlK1oQ/xnWQumdeNZYw==", + "dev": true, + "requires": { + "remark-parse": "^4.0.0", + "remark-stringify": "^4.0.0", + "unified": "^6.0.0" + } + }, + "remark-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-4.0.0.tgz", + "integrity": "sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw==", + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "remark-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-4.0.0.tgz", + "integrity": "sha512-xLuyKTnuQer3ke9hkU38SUYLiTmS078QOnoFavztmbt/pAJtNSkNtFgR0U//uCcmG0qnyxao+PDuatQav46F1w==", + "dev": true, + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass-graph": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "specificity": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", + "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringify-entities": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", + "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "dev": true, + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", + "dev": true + }, + "stylelint": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-8.4.0.tgz", + "integrity": "sha512-56hPH5mTFnk8LzlEuTWq0epa34fHuS54UFYQidBOFt563RJBNi1nz1F2HK2MoT1X1waq47milvRsRahFCCJs/Q==", + "dev": true, + "requires": { + "autoprefixer": "^7.1.2", + "balanced-match": "^1.0.0", + "chalk": "^2.0.1", + "cosmiconfig": "^3.1.0", + "debug": "^3.0.0", + "execall": "^1.0.0", + "file-entry-cache": "^2.0.0", + "get-stdin": "^5.0.1", + "globby": "^7.0.0", + "globjoin": "^0.1.4", + "html-tags": "^2.0.0", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "known-css-properties": "^0.5.0", + "lodash": "^4.17.4", + "log-symbols": "^2.0.0", + "mathml-tag-names": "^2.0.1", + "meow": "^4.0.0", + "micromatch": "^2.3.11", + "normalize-selector": "^0.2.0", + "pify": "^3.0.0", + "postcss": "^6.0.6", + "postcss-html": "^0.12.0", + "postcss-less": "^1.1.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-reporter": "^5.0.0", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^3.0.1", + "postcss-sass": "^0.2.0", + "postcss-scss": "^1.0.2", + "postcss-selector-parser": "^3.1.0", + "postcss-value-parser": "^3.3.0", + "resolve-from": "^4.0.0", + "specificity": "^0.3.1", + "string-width": "^2.1.0", + "style-search": "^0.1.0", + "sugarss": "^1.0.0", + "svg-tags": "^1.0.0", + "table": "^4.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "cosmiconfig": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-3.1.0.tgz", + "integrity": "sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^3.0.0", + "require-from-string": "^2.0.1" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-3.0.0.tgz", + "integrity": "sha1-+m9HsY4jgm6tMvJj50TQ4ehH+xM=", + "dev": true, + "requires": { + "error-ex": "^1.3.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, + "stylelint-config-recommended": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-1.0.0.tgz", + "integrity": "sha512-wp50rY5A6MWndIIkKNNzJv/S58lTvqQEriS7CXTBN1SwtoY/YjHhCLIOkjundLnUWMvJJska6GnciLbs76UQrA==", + "dev": true + }, + "stylelint-config-standard": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-17.0.0.tgz", + "integrity": "sha512-G8jMZ0KsaVH7leur9XLZVhwOBHZ2vdbuJV8Bgy0ta7/PpBhEHo6fjVDaNchyCGXB5sRcWVq6O9rEU/MvY9cQDQ==", + "dev": true, + "requires": { + "stylelint-config-recommended": "^1.0.0" + } + }, + "stylelint-order": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-0.6.0.tgz", + "integrity": "sha1-ciIr4MZNh4Ky/CN9DZrJdAOflos=", + "dev": true, + "requires": { + "lodash": "^4.17.4", + "postcss": "^6.0.7", + "postcss-sorting": "^3.0.1", + "stylelint": "^8.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } + } + }, + "stylelint-scss": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-2.5.0.tgz", + "integrity": "sha512-+joZpza5nQxAyGwzRMancFEl0EH9+1Vy88YzBghRMS0wHulzDPE9fEkBi6ZOlz+I3tYIBI4x9NbqO5/LkbeE3Q==", + "dev": true, + "requires": { + "lodash": "^4.17.4", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^3.1.1", + "postcss-value-parser": "^3.3.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } + } + }, + "stylelint-selector-bem-pattern": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stylelint-selector-bem-pattern/-/stylelint-selector-bem-pattern-1.1.1.tgz", + "integrity": "sha512-PGCjc5yc/tg12ZTKavWHO8a/snpgLdHb8CAJG/MGug0qA7Z6deBNT4FViAVRTGTrQT7+CseJ5MTOqhM/kNmOcQ==", + "dev": true, + "requires": { + "lodash": ">=3.10.0", + "postcss": ">=5.0.19", + "postcss-bem-linter": "^2.1.0", + "stylelint": ">=3.0.2" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } + } + }, + "sugarss": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-1.0.1.tgz", + "integrity": "sha512-3qgLZytikQQEVn1/FrhY7B68gPUUGY3R1Q1vTiD5xT+Ti1DP/8iZuwFet9ONs5+bmL8pZoDQ6JrQHVgrNlK6mA==", + "dev": true, + "requires": { + "postcss": "^6.0.14" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, + "table": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "^6.0.1", + "ajv-keywords": "^3.0.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "dev": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", + "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==", + "dev": true + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "requires": { + "glob": "^7.1.2" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "unist-util-find-all-after": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-1.0.5.tgz", + "integrity": "sha512-lWgIc3rrTMTlK1Y0hEuL+k+ApzFk78h+lsaa2gHf63Gp5Ww+mt11huDniuaoq1H+XMK2lIIjjPkncxXcDp3QDw==", + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } + }, + "unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true + }, + "unist-util-remove-position": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", + "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", + "dev": true + }, + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true, + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } + } + }, + "vfile-location": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", + "dev": true + }, + "vfile-message": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", + "dev": true, + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + } + } +} diff --git a/web/modules/paragraphs/css/package.json b/web/modules/paragraphs/css/package.json index 5a426d2c911f6b704321e2d00b6b39826f4d44cc..827ed7460a24069a53b3bbb3f436f9dc8124aca5 100644 --- a/web/modules/paragraphs/css/package.json +++ b/web/modules/paragraphs/css/package.json @@ -6,7 +6,7 @@ "license": "GPL-2.0", "devDependencies": { "autoprefixer": "^7.1.3", - "gulp": "^3.9.1", + "gulp": "^4.0.0", "gulp-load-plugins": "^1.5.0", "gulp-postcss": "^7.0.0", "gulp-sass": "^3.1.0", diff --git a/web/modules/paragraphs/css/paragraphs.modal.css b/web/modules/paragraphs/css/paragraphs.modal.css index 299c77aa764b6885e815af2f4bf0baa46e8b04ed..a48f555e3552e825e2691e69390b673497560fe1 100644 --- a/web/modules/paragraphs/css/paragraphs.modal.css +++ b/web/modules/paragraphs/css/paragraphs.modal.css @@ -4,7 +4,7 @@ ul.paragraphs-add-dialog-list { list-style-type: none; } -ul.paragraphs-add-dialog-list input.field-add-more-submit { +ul.paragraphs-add-dialog-list .button.button--small { background-repeat: no-repeat; background-position: 10px; background-size: auto calc(100% - 10px); diff --git a/web/modules/paragraphs/css/paragraphs.modal.scss b/web/modules/paragraphs/css/paragraphs.modal.scss index 96631e5ea694e11de6ee58840bd7f7ba1542ebb7..fc817341c0b80b37130f015458e4f36866566cb3 100644 --- a/web/modules/paragraphs/css/paragraphs.modal.scss +++ b/web/modules/paragraphs/css/paragraphs.modal.scss @@ -3,7 +3,7 @@ ul.paragraphs-add-dialog-list { padding: 0; list-style-type: none; - input.field-add-more-submit { + .button.button--small { background-repeat: no-repeat; background-position: 10px; background-size: auto calc(100% - 10px); diff --git a/web/modules/paragraphs/css/paragraphs.seven.css b/web/modules/paragraphs/css/paragraphs.seven.css new file mode 100644 index 0000000000000000000000000000000000000000..1224e5296cf256615a924df8f0246ae22eada4cc --- /dev/null +++ b/web/modules/paragraphs/css/paragraphs.seven.css @@ -0,0 +1,4 @@ +.no-touchevents .button.button--small { + padding: 4px 1.5em; + font-size: 0.875rem; +} diff --git a/web/modules/paragraphs/css/paragraphs.seven.scss b/web/modules/paragraphs/css/paragraphs.seven.scss new file mode 100644 index 0000000000000000000000000000000000000000..6cd7934f29b88159b5dbacd25ce1ff55edd76b38 --- /dev/null +++ b/web/modules/paragraphs/css/paragraphs.seven.scss @@ -0,0 +1,9 @@ +// We added button-small class for the Claro theme UX definitions. +// We therefore need to reset small button styles for the Seven theme. +.no-touchevents { + // Need to be more specific in order to override Seven's definition. + .button.button--small { + padding: 4px 1.5em; + font-size: 0.875rem; + } +} diff --git a/web/modules/paragraphs/css/paragraphs.widget.css b/web/modules/paragraphs/css/paragraphs.widget.css index a2616b936cc87d4b6bc0af813aef1661e0b2527d..5d115b3eb3f2d85163326e4569cd4e601031c7be 100644 --- a/web/modules/paragraphs/css/paragraphs.widget.css +++ b/web/modules/paragraphs/css/paragraphs.widget.css @@ -137,7 +137,7 @@ } } -.paragraphs-tabs-wrapper .paragraphs-tabs { +.paragraphs-tabs-wrapper .paragraphs-tabs-hide { display: none; } @@ -211,12 +211,15 @@ } .js .field--widget-paragraphs .field-multiple-drag { - vertical-align: top; + vertical-align: middle; + min-width: 40px; } .js .field--widget-paragraphs .draggable .tabledrag-handle { - min-width: 50px; margin-left: 0; + margin-top: 3px; + padding-right: .25em; + width: 23px; } .js .field--widget-paragraphs .draggable .tabledrag-handle:focus::before { @@ -224,8 +227,24 @@ margin-right: .1em; } +.js .field--widget-paragraphs .draggable .tabledrag-handle::after { + margin-left: 0; + padding: .5rem; +} + +.js .field--widget-paragraphs .draggable .tabledrag-handle:hover .handle { + -webkit-transform: scale(1.25); + transform: scale(1.25); +} + +.js .field--widget-paragraphs .tabledrag-changed { + text-decoration: none; +} + .js .field--widget-paragraphs .tabledrag-handle .handle { height: 22px; + margin-left: 0; + margin-right: 0; } .js .field--widget-paragraphs .delta-order { @@ -375,6 +394,11 @@ tr:hover .paragraphs-description::after { background: #057ec7 none; } +.paragraphs-dragdrop__item .paragraphs-summary-wrapper .paragraphs-description .paragraphs-content-wrapper, +.paragraphs-dragdrop__item .paragraphs-summary-wrapper .paragraphs-description .paragraphs-plugin-wrapper { + font-size: 81.3%; +} + .paragraph--view-mode--preview { padding-right: 1em; } diff --git a/web/modules/paragraphs/css/paragraphs.widget.scss b/web/modules/paragraphs/css/paragraphs.widget.scss index 3dedd0b9660b0b55fc5b793c0f6b2cc83180df5d..a14f7fa17216109a36a38fd88bd773eea5396afc 100644 --- a/web/modules/paragraphs/css/paragraphs.widget.scss +++ b/web/modules/paragraphs/css/paragraphs.widget.scss @@ -1,6 +1,6 @@ // // @file -// Experimental paragraphs widget CSS. +// Stable paragraphs widget CSS. // @import "variables"; @@ -58,7 +58,7 @@ .paragraphs-tabs-wrapper { - .paragraphs-tabs { + .paragraphs-tabs-hide { display: none; } } @@ -143,12 +143,15 @@ } .field-multiple-drag { - vertical-align: top; + vertical-align: middle; + min-width: 40px; } .draggable .tabledrag-handle { - min-width: 50px; margin-left: 0; + margin-top: 3px; + padding-right: .25em; + width: 23px; // Fix active focus. &:focus { @@ -157,10 +160,27 @@ margin-right: .1em; } } + + // Claro theme fix for the handle icon position. + &::after { + margin-left: 0; + padding: .5rem; + } + + // Scale the icon on hover. + &:hover .handle { + transform: scale(1.25); + } + } + + .tabledrag-changed { + text-decoration: none; } .tabledrag-handle .handle { height: 22px; + margin-left: 0; + margin-right: 0; } .delta-order { @@ -291,6 +311,17 @@ } } +.paragraphs-dragdrop__item { + .paragraphs-summary-wrapper { + .paragraphs-description { + .paragraphs-content-wrapper, + .paragraphs-plugin-wrapper { + font-size: 81.3%; + } + } + } +} + .paragraph--view-mode--preview { padding-right: 1em; } diff --git a/web/modules/paragraphs/js/paragraphs.actions.js b/web/modules/paragraphs/js/paragraphs.actions.js index 27e2d48f0d08be9c9c1a57cda8dae4bbacdc002d..90792cb0cfff5d338741c4813012726fa2e94e30 100644 --- a/web/modules/paragraphs/js/paragraphs.actions.js +++ b/web/modules/paragraphs/js/paragraphs.actions.js @@ -3,7 +3,7 @@ * Paragraphs actions JS code for paragraphs actions button. */ -(function ($, Drupal) { +(function ($, Drupal, once) { 'use strict'; @@ -17,7 +17,7 @@ */ Drupal.behaviors.paragraphsActions = { attach: function (context, settings) { - var $actionsElement = $(context).find('.paragraphs-dropdown').once('paragraphs-dropdown'); + var $actionsElement = $(once('paragraphs-dropdown', '.paragraphs-dropdown', context)); // Attach event handlers to toggle button. $actionsElement.each(function () { var $this = $(this); @@ -40,4 +40,4 @@ } }; -})(jQuery, Drupal); +})(jQuery, Drupal, once); diff --git a/web/modules/paragraphs/js/paragraphs.add_above_button.js b/web/modules/paragraphs/js/paragraphs.add_above_button.js index cc49ca15f8bc782ffa688426d53f288363d090b9..6f1e85987f7d8de35fd76ba7e86ebf5f941b6a99 100644 --- a/web/modules/paragraphs/js/paragraphs.add_above_button.js +++ b/web/modules/paragraphs/js/paragraphs.add_above_button.js @@ -3,7 +3,7 @@ * Paragraphs actions JS code for paragraphs actions button. */ -(function ($, Drupal) { +(function ($, Drupal, once) { 'use strict'; @@ -13,19 +13,35 @@ * @param event * Click event. */ - var clickHandler = function(event) { + var clickHandler = function (event) { event.preventDefault(); + // We need to stop event propagation in order to prevent triggering jQuery + // UI dialog.js mousedown method. This method order call is not predictable. + // When we are in dialog for editing reusable library (parent dialog) then + // for 'Add Paragraph' button it will be called before child dialog + // creation, but for 'Add above' button it will be called after child dialog + // creation and this will result in moving parent dialog in front of + // child dialog. + event.stopPropagation(); + var $button = $(this); - var $add_more_wrapper = $button.closest('table').siblings('.clearfix').find('.paragraphs-add-dialog'); // Find delta for row without interference of unrelated table rows. var $anchorRow = $button.closest('tr'); var delta = $anchorRow.parent().find('> .draggable').index($anchorRow); + // We need the siblings function to avoid finding the 'Add paragraph' button inside a container. + var $add_more_wrapper = $button.closest('.field-multiple-table').siblings('.clearfix,.form-actions').find('.paragraphs-add-wrapper'); // Set delta before opening of dialog. - $add_more_wrapper.parent().find('.paragraph-type-add-modal-delta').val(delta); + $add_more_wrapper.find('.paragraph-type-add-delta').val(delta); - Drupal.paragraphsAddModal.openDialog($add_more_wrapper, Drupal.t('Add above')); + // If the add mode is modal open the dialog, otherwise press the add button. + if ($add_more_wrapper.find('.paragraph-type-add-delta').hasClass('modal')) { + Drupal.paragraphsAddModal.openDialog($add_more_wrapper.find('.paragraphs-add-dialog'), Drupal.t('Add above')); + } + else { + $add_more_wrapper.find('.field-add-more-submit').trigger('mousedown'); + } }; /** @@ -35,18 +51,28 @@ */ Drupal.behaviors.paragraphsAddAboveButton = { attach: function (context, settings) { - $('.paragraphs-dropdown-actions', context).once('paragraphs-add-above-button').each(function () { + $(once('paragraphs-add-above-button', '.paragraphs-dropdown-actions', context)).each(function () { var $actions = $(this); if ($actions.closest('.paragraph-top').hasClass('add-above-on')) { - var $button = $('<input class="paragraphs-dropdown-action paragraphs-dropdown-action--add-above button js-form-submit form-submit" type="submit" value="' + Drupal.t('Add above') + '">'); - // "Mousedown" is used since the original actions created by paragraphs - // use the event "focusout" to hide the actions dropdown. - $button.on('mousedown', clickHandler); + var $add_above = false; + var $add_more_wrapper = $actions.closest('.field-multiple-table').siblings('.clearfix,.form-actions').find('.paragraphs-add-wrapper'); + // The Add Above button is added when the add mode is modal or when + // there is only one add button in the other add modes. + if ($add_more_wrapper.find('.paragraph-type-add-delta').hasClass('modal') || $add_more_wrapper.find('.field-add-more-submit').length === 1) { + $add_above = true; + } + // Prepend the Add above button only if there is only one button. + if ($add_above) { + var $button = $('<input class="paragraphs-dropdown-action paragraphs-dropdown-action--add-above button button--small js-form-submit form-submit" type="submit" onClick="return false;" value="' + Drupal.t('Add above') + '">'); + // "Mousedown" is used since the original actions created by + // paragraphs use the event "focusout" to hide the actions dropdown. + $button.on('mousedown', clickHandler); - $actions.prepend($button); + $actions.prepend($button); + } } }); } }; -})(jQuery, Drupal); +})(jQuery, Drupal, once); diff --git a/web/modules/paragraphs/js/paragraphs.admin.js b/web/modules/paragraphs/js/paragraphs.admin.js index f0696cb9529e51e87a547656ed5afe07fc8cce42..b7fb3e11a294ade860e105704aa3c575af6b02ab 100644 --- a/web/modules/paragraphs/js/paragraphs.admin.js +++ b/web/modules/paragraphs/js/paragraphs.admin.js @@ -1,4 +1,4 @@ -(function ($, Drupal) { +(function ($, Drupal, once) { 'use strict'; @@ -18,12 +18,14 @@ * Main paragraph region. */ var setUpTab = function ($parWidget, $parTabs, $parContent, $parBehavior, $mainRegion) { - var $tabContent = $parTabs.find('#content'); - var $tabBehavior = $parTabs.find('#behavior'); + var $tabContent = $parTabs.find('.paragraphs_content_tab'); + var $tabBehavior = $parTabs.find('.paragraphs_behavior_tab'); if ($tabBehavior.hasClass('is-active')) { $parWidget.removeClass('content-active').addClass('behavior-active'); $tabContent.removeClass('is-active'); + $tabContent.find('a').removeClass('is-active'); $tabBehavior.addClass('is-active'); + $tabBehavior.find('a').addClass('is-active'); } else { // Activate content tab visually if there is no previously @@ -31,12 +33,13 @@ if (!($mainRegion.hasClass('content-active')) && !($mainRegion.hasClass('behavior-active'))) { $tabContent.addClass('is-active'); + $tabContent.find('a').addClass('is-active'); $parWidget.addClass('content-active'); } - $parTabs.show(); + $parTabs.removeClass('paragraphs-tabs-hide'); if ($parBehavior.length === 0) { - $parTabs.hide(); + $parTabs.addClass('paragraphs-tabs-hide'); } } }; @@ -54,10 +57,12 @@ var $clickedTabParent = $clickedTab.parent(); $parTabs.find('li').removeClass('is-active'); + $parTabs.find('li').find('a').removeClass('is-active'); $clickedTabParent.addClass('is-active'); + $clickedTabParent.find('a').addClass('is-active'); $parWidget.removeClass('behavior-active content-active'); - if ($clickedTabParent.attr('id') === 'content') { + if ($clickedTabParent.hasClass('paragraphs_content_tab')) { $parWidget.addClass('content-active'); $parWidget.find('.paragraphs-add-wrapper').parent().removeClass('hidden'); } @@ -131,7 +136,7 @@ }); // Initialization. - $topLevelParWidgets.once('paragraphs-bodytabs').each(function() { + $(once('paragraphs-bodytabs', $topLevelParWidgets)).each(function() { var $parWidget = $(this); var $parTabs = $parWidget.find('.paragraphs-tabs'); @@ -185,5 +190,5 @@ } } }; -})(jQuery, Drupal); +})(jQuery, Drupal, once); diff --git a/web/modules/paragraphs/js/paragraphs.modal.js b/web/modules/paragraphs/js/paragraphs.modal.js index 16128f17aa688b95a0f4585b9e82f8e2999ca3f7..a8a7057aac95cc9a1b851c2ccd196dedd4622b56 100644 --- a/web/modules/paragraphs/js/paragraphs.modal.js +++ b/web/modules/paragraphs/js/paragraphs.modal.js @@ -3,7 +3,7 @@ * */ -(function ($, Drupal) { +(function ($, Drupal, once) { 'use strict'; @@ -14,7 +14,7 @@ */ Drupal.behaviors.paragraphsModalAdd = { attach: function (context) { - $('.paragraph-type-add-modal-button', context).once('add-click-handler').on('click', function (event) { + $(once('add-click-handler', '.paragraph-type-add-modal-button', context)).on('click', function (event) { var $button = $(this); Drupal.paragraphsAddModal.openDialog($button.parent().siblings('.paragraphs-add-dialog'), $button.val()); @@ -47,7 +47,7 @@ var $element = $(element); // Get the delta element before moving $element to dialog element. - var $modalDelta = $element.parent().find('.paragraph-type-add-modal-delta'); + var $modalDelta = $element.parent().find('.paragraph-type-add-delta'); // Deep clone with all attached events. We need to work on cloned element // and not directly on origin because Drupal dialog.ajax.js @@ -67,7 +67,7 @@ // Close the dialog after a button was clicked. // Use mousedown event, because we are using ajax in the modal add mode // which explicitly suppresses the click event. - $element.once().find('.field-add-more-submit').on('mousedown', function () { + $(once('paragraphs-add-more-submit-modal', $element.find('.field-add-more-submit'))).on('mousedown', function () { dialog.close(); }); @@ -86,4 +86,4 @@ } }); -})(jQuery, Drupal); +})(jQuery, Drupal, once); diff --git a/web/modules/paragraphs/migrations/d7_field_collection.yml b/web/modules/paragraphs/migrations/d7_field_collection.yml new file mode 100644 index 0000000000000000000000000000000000000000..a7077d36cf1e61de343333061e86d66e7c5eb8ec --- /dev/null +++ b/web/modules/paragraphs/migrations/d7_field_collection.yml @@ -0,0 +1,21 @@ +id: d7_field_collection +label: Field Collections +migration_tags: + - Drupal 7 + - Content + - Field Collection Content +deriver: Drupal\paragraphs\Plugin\migrate\D7FieldCollectionItemDeriver +source: + plugin: d7_field_collection_item +process: + type: bundle + # @todo Get the langcode from the parent entity. + # See https://drupal.org/i/3146632. + # langcode: langcode +destination: + plugin: entity_reference_revisions:paragraph +migration_dependencies: + required: + - d7_field_collection_type + optional: + - d7_field_instance diff --git a/web/modules/paragraphs/migrations/d7_field_collection_revisions.yml b/web/modules/paragraphs/migrations/d7_field_collection_revisions.yml new file mode 100644 index 0000000000000000000000000000000000000000..01ca0e3e82aad5934817bebe6c65522857f07967 --- /dev/null +++ b/web/modules/paragraphs/migrations/d7_field_collection_revisions.yml @@ -0,0 +1,30 @@ +id: d7_field_collection_revisions +label: Field Collection Revisions +migration_tags: + - Drupal 7 + - Content + - Field Collection Revisions Content +deriver: Drupal\paragraphs\Plugin\migrate\D7FieldCollectionItemDeriver +source: + plugin: d7_field_collection_item_revision +process: + id: + - + plugin: paragraphs_lookup + tags: + - Field Collection Content + source: item_id + - + plugin: extract + index: + - id + type: bundle + # @todo Get the langcode from the parent entity revision. + # See https://drupal.org/i/3146632. + # langcode: langcode +destination: + plugin: entity_reference_revisions:paragraph + new_revisions: TRUE +migration_dependencies: + required: + - d7_field_collection diff --git a/web/modules/paragraphs/migrations/d7_field_collection_type.yml b/web/modules/paragraphs/migrations/d7_field_collection_type.yml index 79227c3a2214ef807ccd3928c24128f053534182..b0cdcebcbad8fceab359d073183e4fe3b85438a0 100644 --- a/web/modules/paragraphs/migrations/d7_field_collection_type.yml +++ b/web/modules/paragraphs/migrations/d7_field_collection_type.yml @@ -2,6 +2,7 @@ id: d7_field_collection_type label: Paragraphs - Field Collection type configuration migration_tags: - Drupal 7 + - Configuration source: plugin: d7_field_collection_type add_description: true diff --git a/web/modules/paragraphs/migrations/d7_paragraphs.yml b/web/modules/paragraphs/migrations/d7_paragraphs.yml new file mode 100644 index 0000000000000000000000000000000000000000..89ab1664d8c481da9cbb050fd83fae321076d0b5 --- /dev/null +++ b/web/modules/paragraphs/migrations/d7_paragraphs.yml @@ -0,0 +1,21 @@ +id: d7_paragraphs +label: Paragraphs +migration_tags: + - Drupal 7 + - Content + - Paragraphs Content +deriver: Drupal\paragraphs\Plugin\migrate\D7ParagraphsItemDeriver +source: + plugin: d7_paragraphs_item +process: + type: bundle + # @todo Get the langcode from the parent entity. + # See https://drupal.org/i/3146632. + # langcode: langcode +destination: + plugin: entity_reference_revisions:paragraph +migration_dependencies: + required: + - d7_paragraphs_type + optional: + - d7_field_instance diff --git a/web/modules/paragraphs/migrations/d7_paragraphs_revisions.yml b/web/modules/paragraphs/migrations/d7_paragraphs_revisions.yml new file mode 100644 index 0000000000000000000000000000000000000000..676fa1c599c4ea50f7bcadcf690500591bcd609c --- /dev/null +++ b/web/modules/paragraphs/migrations/d7_paragraphs_revisions.yml @@ -0,0 +1,30 @@ +id: d7_paragraphs_revisions +label: Paragraphs Revisions +migration_tags: + - Drupal 7 + - Content + - Paragraphs Revisions Content +deriver: Drupal\paragraphs\Plugin\migrate\D7ParagraphsItemDeriver +source: + plugin: d7_paragraphs_item_revision +process: + id: + - + plugin: paragraphs_lookup + tags: + - Paragraphs Content + source: item_id + - + plugin: extract + index: + - id + type: bundle + # @todo Get the langcode from the parent entity revision. + # See https://drupal.org/i/3146632. + # langcode: langcode +destination: + plugin: entity_reference_revisions:paragraph + new_revisions: TRUE +migration_dependencies: + required: + - d7_paragraphs diff --git a/web/modules/paragraphs/migrations/d7_paragraphs_type.yml b/web/modules/paragraphs/migrations/d7_paragraphs_type.yml index ac38f5bf4908cf0e46b2594d10c15fc7650c8a8b..2d385f7dba254c11e89414239800cdbc5b476e7f 100644 --- a/web/modules/paragraphs/migrations/d7_paragraphs_type.yml +++ b/web/modules/paragraphs/migrations/d7_paragraphs_type.yml @@ -2,6 +2,7 @@ id: d7_paragraphs_type label: Paragraphs type configuration migration_tags: - Drupal 7 + - Configuration source: plugin: d7_paragraphs_type add_description: true diff --git a/web/modules/paragraphs/modules/paragraphs_demo/config/install/core.entity_form_display.node.paragraphed_content_demo.default.yml b/web/modules/paragraphs/modules/paragraphs_demo/config/install/core.entity_form_display.node.paragraphed_content_demo.default.yml index a415b8a8bbcf7a7d6e2070b88a8157f6662b5dfb..6086fb41e2aa69a00e1e37eddff91031f1f2d17a 100644 --- a/web/modules/paragraphs/modules/paragraphs_demo/config/install/core.entity_form_display.node.paragraphed_content_demo.default.yml +++ b/web/modules/paragraphs/modules/paragraphs_demo/config/install/core.entity_form_display.node.paragraphed_content_demo.default.yml @@ -40,11 +40,6 @@ content: weight: 2 settings: { } third_party_settings: { } - path: - type: path - weight: 30 - settings: { } - third_party_settings: { } promote: type: boolean_checkbox weight: 15 diff --git a/web/modules/paragraphs/modules/paragraphs_demo/paragraphs_demo.info.yml b/web/modules/paragraphs/modules/paragraphs_demo/paragraphs_demo.info.yml index 0a67b970e1a2297b1c559e1adde10f018997dfdb..d1e0859b28485fe6778ab15dbb2a92094fb35de4 100644 --- a/web/modules/paragraphs/modules/paragraphs_demo/paragraphs_demo.info.yml +++ b/web/modules/paragraphs/modules/paragraphs_demo/paragraphs_demo.info.yml @@ -1,5 +1,5 @@ description: 'Provides multilingual demo Paragraphs types.' -core_version_requirement: ^8.7.7 || ^9 +core_version_requirement: ^9.3 || ^10 dependencies: - paragraphs:paragraphs - drupal:field @@ -21,7 +21,7 @@ name: Paragraphs Demo package: Paragraphs type: module -# Information added by Drupal.org packaging script on 2020-05-21 -version: '8.x-1.12' +# Information added by Drupal.org packaging script on 2022-08-25 +version: '8.x-1.15' project: 'paragraphs' -datestamp: 1590061337 +datestamp: 1661440900 diff --git a/web/modules/paragraphs/modules/paragraphs_demo/tests/src/Functional/ParagraphsDemoTest.php b/web/modules/paragraphs/modules/paragraphs_demo/tests/src/Functional/ParagraphsDemoTest.php index 56ab0fb79351c0e214b2de5f1f045211dbf50f44..4f199f60822c9691a2d66223861b6028097e731e 100644 --- a/web/modules/paragraphs/modules/paragraphs_demo/tests/src/Functional/ParagraphsDemoTest.php +++ b/web/modules/paragraphs/modules/paragraphs_demo/tests/src/Functional/ParagraphsDemoTest.php @@ -19,7 +19,7 @@ class ParagraphsDemoTest extends BrowserTestBase { * * @var string[] */ - public static $modules = array( + protected static $modules = array( 'paragraphs_demo', 'block', ); @@ -32,11 +32,9 @@ class ParagraphsDemoTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); } /** @@ -81,9 +79,9 @@ public function testConfigurationsAndCreation() { // Set edit mode to open. $this->drupalGet('admin/structure/types/manage/paragraphed_content_demo/form-display'); - $this->drupalPostForm(NULL, [], "field_paragraphs_demo_settings_edit"); + $this->submitForm([], "field_paragraphs_demo_settings_edit"); $edit = ['fields[field_paragraphs_demo][settings_edit_form][settings][edit_mode]' => 'open']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check for all pre-configured paragraphs_types. $this->drupalGet('admin/structure/paragraphs_type'); @@ -144,7 +142,7 @@ public function testConfigurationsAndCreation() { $this->drupalGet('node/add/paragraphed_content_demo'); $this->assertSession()->responseContains('<h4 class="label">Paragraphs</h4>'); - $this->drupalPostForm(NULL, NULL, t('Add Text')); + $this->submitForm([], 'Add Text'); $this->assertSession()->responseNotContains('<strong data-drupal-selector="edit-field-paragraphs-demo-title">Paragraphs</strong>'); $this->assertSession()->responseContains('<h4 class="label">Paragraphs</h4>'); $edit = array( @@ -152,11 +150,11 @@ public function testConfigurationsAndCreation() { 'moderation_state[0][state]' => 'published', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Paragraph text', ); - $this->drupalPostForm(NULL, $edit, t('Add User')); + $this->submitForm($edit, 'Add User'); $edit = [ 'field_paragraphs_demo[1][subform][field_user_demo][0][target_id]' => $admin_user->label() . ' (' . $admin_user->id() . ')', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraphed article Paragraph title has been created.'); $this->assertSession()->pageTextContains('Paragraph title'); @@ -173,7 +171,7 @@ public function testConfigurationsAndCreation() { $this->assertSession()->responseNotContains('Welcome to the Paragraphs Demo module!'); // Check that the dropbutton of Nested Paragraph has the Duplicate function. - // For now, this indicates that it is using the EXPERIMENTAL widget. + // For now, this indicates that it is using the stable widget. $this->drupalGet('node/1/edit'); $this->assertSession()->buttonExists('field_paragraphs_demo_3_subform_field_paragraphs_demo_0_duplicate'); diff --git a/web/modules/paragraphs/modules/paragraphs_library/config/install/core.entity_view_display.paragraphs_library_item.paragraphs_library_item.summary.yml b/web/modules/paragraphs/modules/paragraphs_library/config/install/core.entity_view_display.paragraphs_library_item.paragraphs_library_item.summary.yml index 22f6fb5240df53afb2c628aab2704a3a2bb1c9d3..7325396cc4ccf3f59164bf68e5ce3a0a24f9097f 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/config/install/core.entity_view_display.paragraphs_library_item.paragraphs_library_item.summary.yml +++ b/web/modules/paragraphs/modules/paragraphs_library/config/install/core.entity_view_display.paragraphs_library_item.paragraphs_library_item.summary.yml @@ -21,7 +21,7 @@ content: third_party_settings: { } paragraphs: label: hidden - type: paragraph_summary + type: library_item_summary weight: 0 region: content settings: { } diff --git a/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.info.yml b/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.info.yml index f2372be3de8942c4aa38dd8fcc26ee32a510d693..0c206d263cd2700ee68ac076c33fc797f2f8cc53 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.info.yml +++ b/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.info.yml @@ -1,7 +1,7 @@ name: Paragraphs Library type: module description: 'Provides a library for reusing paragraphs.' -core_version_requirement: ^8.7.7 || ^9 +core_version_requirement: ^9.3 || ^10 package: Paragraphs configure: paragraphs_library_item.settings dependencies: @@ -11,7 +11,7 @@ dependencies: test_dependencies: - entity_browser:entity_browser -# Information added by Drupal.org packaging script on 2020-05-21 -version: '8.x-1.12' +# Information added by Drupal.org packaging script on 2022-08-25 +version: '8.x-1.15' project: 'paragraphs' -datestamp: 1590061337 +datestamp: 1661440900 diff --git a/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.module b/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.module index d2e4829de70d4ff3824b1d534654d110e1f41050..4a1f1a604df2cf709dd8ff4a7cc26cbacc8abf45 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.module +++ b/web/modules/paragraphs/modules/paragraphs_library/paragraphs_library.module @@ -139,7 +139,7 @@ function paragraphs_library_preprocess_paragraph(&$variables) { // Only replace the content if access is allowed to the library. Access // cacheability metadata is already returned by the original widget in case // access is not allowed. - if ($library_item->access('view')) { + if ($library_item->access('view') && isset($variables['elements']['field_reusable_paragraph'][0]['#view_mode'])) { $view_builder = \Drupal::entityTypeManager() ->getViewBuilder('paragraphs_library_item'); $library_item_render_array = $view_builder->view($library_item, $variables['elements']['field_reusable_paragraph'][0]['#view_mode']); diff --git a/web/modules/paragraphs/modules/paragraphs_library/src/Controller/LibraryItemController.php b/web/modules/paragraphs/modules/paragraphs_library/src/Controller/LibraryItemController.php index 138afb4810e1c2c341d3a59d4cd14c2a4b88f513..fde2eb0149988f1db3f608c0160d08bc4ef40058 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/src/Controller/LibraryItemController.php +++ b/web/modules/paragraphs/modules/paragraphs_library/src/Controller/LibraryItemController.php @@ -196,6 +196,7 @@ protected function getRevisionIds(LibraryItemInterface $library_item) { $result = $this->entityTypeManager->getStorage('paragraphs_library_item')->getQuery() ->allRevisions() ->condition('id', $library_item->id()) + ->accessCheck(TRUE) ->sort($library_item->getEntityType()->getKey('revision'), 'DESC') ->pager(50) ->execute(); diff --git a/web/modules/paragraphs/modules/paragraphs_library/src/Entity/LibraryItem.php b/web/modules/paragraphs/modules/paragraphs_library/src/Entity/LibraryItem.php index 3dfe46a230ec39c6c11e2f8c3c66400c1d1fc0cb..0b3cde3895531b1e0fb96128704a50632e3c5bb8 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/src/Entity/LibraryItem.php +++ b/web/modules/paragraphs/modules/paragraphs_library/src/Entity/LibraryItem.php @@ -267,6 +267,11 @@ public static function createFromParagraph(ParagraphInterface $paragraph) { 'langcode' => $paragraph->language()->getId(), ]); + // If the item has a moderation field, set it to published. + if ($library_item->hasField('moderation_state')) { + $library_item->set('moderation_state', 'published'); + } + // Build the label in each available translation and ensure the translations // exist. foreach ($duplicate_paragraph->getTranslationLanguages() as $langcode => $language) { diff --git a/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemForm.php b/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemForm.php index a2ed4c61247af8cc9de4f678da3d0d9582db9003..64dd676a6f6364727d97a883eae3f8ebc7b01c7f 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemForm.php +++ b/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemForm.php @@ -50,10 +50,10 @@ public function save(array $form, FormStateInterface $form_state) { parent::save($form, $form_state); $form_state->setRedirect('entity.paragraphs_library_item.collection'); if ($insert) { - $this->messenger->addMessage(t('Paragraph %label has been created.', ['%label' => $this->entity->label()])); + $this->messenger->addMessage($this->t('Paragraph %label has been created.', ['%label' => $this->entity->label()])); } else { - $this->messenger->addMessage(t('Paragraph %label has been updated.', ['%label' => $this->entity->label()])); + $this->messenger->addMessage($this->t('Paragraph %label has been updated.', ['%label' => $this->entity->label()])); } } diff --git a/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemRevisionRevertForm.php b/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemRevisionRevertForm.php index 3d2f3fb61e6961d301f4c250dddf6e162e60fef0..7bff0f850b3bd434b6c4fabe8f850415d9b43355 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemRevisionRevertForm.php +++ b/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemRevisionRevertForm.php @@ -102,7 +102,7 @@ public function getQuestion() { public function submitForm(array &$form, FormStateInterface $form_state) { $original_revision_timestamp = $this->revision->getChangedTime(); $this->revision = $this->prepareRevertedRevision($this->revision); - $this->revision->revision_log = t('Copy of the revision from %date.', [ + $this->revision->revision_log = $this->t('Copy of the revision from %date.', [ '%date' => $this->dateFormatter->format($original_revision_timestamp) ]); $this->revision->setChangedTime($this->time->getRequestTime()); diff --git a/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemSettingsForm.php b/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemSettingsForm.php index 718ae99f6bde311eed8d9840bba73af28ad61870..f59433bddb7dabe42e3b0806bac4aff8b5998e60 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemSettingsForm.php +++ b/web/modules/paragraphs/modules/paragraphs_library/src/Form/LibraryItemSettingsForm.php @@ -30,7 +30,7 @@ protected function getEditableConfigNames() { public function buildForm(array $form, FormStateInterface $form_state) { // This exists to make the field UI pages visible and must not be removed. $form['account'] = array( - '#markup' => '<p>' . t('There are no settings yet.') . '</p>', + '#markup' => '<p>' . $this->t('There are no settings yet.') . '</p>', ); return $form; diff --git a/web/modules/paragraphs/modules/paragraphs_library/src/Plugin/Field/FieldFormatter/LibraryItemSummaryFormatter.php b/web/modules/paragraphs/modules/paragraphs_library/src/Plugin/Field/FieldFormatter/LibraryItemSummaryFormatter.php new file mode 100644 index 0000000000000000000000000000000000000000..2fb4fcfc544a3fd7af08f239274768cf139598ea --- /dev/null +++ b/web/modules/paragraphs/modules/paragraphs_library/src/Plugin/Field/FieldFormatter/LibraryItemSummaryFormatter.php @@ -0,0 +1,48 @@ +<?php + +namespace Drupal\paragraphs_library\Plugin\Field\FieldFormatter; + +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\FieldItemListInterface; +use Drupal\paragraphs\Plugin\Field\FieldFormatter\ParagraphsSummaryFormatter; + +/** + * Plugin implementation of the 'paragraph_summary' formatter. + * + * @FieldFormatter( + * id = "library_item_summary", + * label = @Translation("Library item summary"), + * field_types = { + * "entity_reference_revisions" + * } + * ) + */ +class LibraryItemSummaryFormatter extends ParagraphsSummaryFormatter { + + /** + * {@inheritdoc} + */ + public function viewElements(FieldItemListInterface $items, $langcode) { + $elements = parent::viewElements($items, $langcode); + if (!$items->getEntity()->isPublished()) { + $published = [ + '#theme' => 'paragraphs_info_icon', + '#message' => $this->t('Unpublished'), + '#icon' => 'view', + ]; + $elements[0]['info'] += $published; + } + return $elements; + } + + /** + * {@inheritdoc} + */ + public static function isApplicable(FieldDefinitionInterface $field_definition) { + if ($field_definition->getTargetEntityTypeId() == 'paragraphs_library_item' && $field_definition->getName() == 'paragraphs') { + return TRUE; + } + return FALSE; + } + +} diff --git a/web/modules/paragraphs/modules/paragraphs_library/src/Routing/LibraryItemRouteProvider.php b/web/modules/paragraphs/modules/paragraphs_library/src/Routing/LibraryItemRouteProvider.php index d6c89d6a5bc6c4b5c15532120253b5c69e12f770..e55fe4b0881de5e20b98da619b2e065b0998cac1 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/src/Routing/LibraryItemRouteProvider.php +++ b/web/modules/paragraphs/modules/paragraphs_library/src/Routing/LibraryItemRouteProvider.php @@ -15,9 +15,14 @@ class LibraryItemRouteProvider extends DefaultHtmlRouteProvider { */ public function getRoutes(EntityTypeInterface $entity_type) { $route_collection = parent::getRoutes($entity_type); - // Display library items using default theme. if ($canonical_route = $route_collection->get("entity.{$entity_type->id()}.canonical")) { + // Display library items using default theme. $canonical_route->setOption('_admin_route', FALSE); + + // Restrict access based on permission. + $canonical_route->addRequirements([ + '_permission' => 'administer paragraphs library+create paragraph library item+edit paragraph library item', + ]); } return $route_collection; } diff --git a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/MultilingualBehaviorTest.php b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/MultilingualBehaviorTest.php index 94f7c1291bfabe6a644cf994def3110ea5ce858c..4af581cc7d72a62a53d3a927782ab86821985910 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/MultilingualBehaviorTest.php +++ b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/MultilingualBehaviorTest.php @@ -3,7 +3,7 @@ namespace Drupal\Tests\paragraphs_library\Functional; use Drupal\language\Entity\ConfigurableLanguage; -use Drupal\Tests\paragraphs\Functional\Experimental\ParagraphsExperimentalTestBase; +use Drupal\Tests\paragraphs\Functional\WidgetStable\ParagraphsTestBase; /** * Tests paragraphs library multilingual functionality. @@ -11,12 +11,12 @@ * @package Drupal\paragraphs_library\Tests * @group paragraphs_library */ -class MultilingualBehaviorTest extends ParagraphsExperimentalTestBase { +class MultilingualBehaviorTest extends ParagraphsTestBase { /** * {@inheritdoc} */ - public static $modules = [ + protected static $modules = [ 'language', 'content_translation', 'paragraphs_library', @@ -25,7 +25,7 @@ class MultilingualBehaviorTest extends ParagraphsExperimentalTestBase { /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->addParagraphedContentType('paragraphed_test'); @@ -49,7 +49,8 @@ public function setUp() { $edit = [ 'language_configuration[content_translation]' => TRUE, ]; - $this->drupalPostForm('admin/structure/types/manage/paragraphed_test', $edit, 'Save content type'); + $this->drupalGet('admin/structure/types/manage/paragraphed_test'); + $this->submitForm($edit, 'Save content type'); $this->fieldUIAddNewField('admin/structure/paragraphs_type/test_content', 'paragraphs_text', 'Test content', 'text_long', [], []); @@ -70,7 +71,8 @@ public function setUp() { 'settings[paragraph][test_content][fields][field_paragraphs_text]' => TRUE, 'settings[paragraphs_library_item][paragraphs_library_item][translatable]' => TRUE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, 'Save configuration'); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); } /** @@ -79,13 +81,13 @@ public function setUp() { public function testReuseTranslationForNestedParagraphFromLibrary() { // Add nested paragraph directly in library. $this->drupalGet('admin/content/paragraphs/add/default'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_0_subform_field_err_field_test_content_add_more'); + $this->submitForm([], 'paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'paragraphs_0_subform_field_err_field_test_content_add_more'); $edit = [ 'label[0][value]' => 'En label Test nested paragraph', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'En label Example text for test in nested paragraph.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph En label Test nested paragraph has been created.'); // Translate nested paragraphs library item. @@ -95,23 +97,24 @@ public function testReuseTranslationForNestedParagraphFromLibrary() { 'label[0][value]' => 'De label Test geschachtelten Absatz', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'De label Beispieltext fur den Test in geschachteltem Absatz.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Create test content. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_from_library_add_more'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'En label Test node nested', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 'En label Test nested paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Add translation for test node. $node = $this->drupalGetNodeByTitle('En label Test node nested'); $edit = [ 'title[0][value]' => 'De label Test geschachtelten Absatz', ]; - $this->drupalPostForm('de/node/' . $node->id() . '/translations/add/en/de', $edit, 'Save (this translation)'); + $this->drupalGet('de/node/' . $node->id() . '/translations/add/en/de'); + $this->submitForm($edit, 'Save (this translation)'); $this->drupalGet('node/' . $node->id()); $this->assertSession()->pageTextContains('En label Example text for test in nested paragraph.'); @@ -123,7 +126,8 @@ public function testReuseTranslationForNestedParagraphFromLibrary() { $edit = [ 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'De label Beispieltext fur den Test geander.', ]; - $this->drupalPostForm('de/admin/content/paragraphs/1/edit', $edit, 'Save'); + $this->drupalGet('de/admin/content/paragraphs/1/edit'); + $this->submitForm($edit, 'Save'); // Check updated content. $this->drupalGet('de/node/' . $node->id()); @@ -138,13 +142,13 @@ public function testMoveTranslatedNestedParagraphToLibrary() { // Add node with text paragraph. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_0_subform_field_err_field_test_content_add_more'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_err_field_test_content_add_more'); $edit = [ 'title[0][value]' => 'En label Test node nested', 'field_paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'En label Example text for test in nested paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Add translation for node. $node = $this->drupalGetNodeByTitle('En label Test node nested'); @@ -154,12 +158,12 @@ public function testMoveTranslatedNestedParagraphToLibrary() { 'title[0][value]' => 'Testknoten', 'field_paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'De label Beispieltext fur den Test in geschachteltem Absatz.', ]; - $this->drupalPostForm(NULL, $edit, 'Save (this translation)'); + $this->submitForm($edit, 'Save (this translation)'); // Convert translated paragraph to library. $this->drupalGet($node->toUrl('edit-form')); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_0_promote_to_library'); - $this->drupalPostForm(NULL, NULL, 'Save (this translation)'); + $this->submitForm([], 'field_paragraphs_0_promote_to_library'); + $this->submitForm([], 'Save (this translation)'); // Check translation. $this->drupalGet($node->toUrl()); @@ -173,6 +177,86 @@ public function testMoveTranslatedNestedParagraphToLibrary() { $this->assertSession()->pageTextContains('De label Beispieltext fur den Test in geschachteltem Absatz.'); } + /** + * Tests converting moderated translated nested paragraph into library. + */ + public function testMoveModeratedTranslatedNestedParagraphToLibrary() { + $this->container->get('module_installer')->install(['content_moderation']); + $this->createEditorialWorkflow('paragraphed_test'); + + $this->loginAsAdmin([ + 'access administration pages', + 'view any unpublished content', + 'view all revisions', + 'revert all revisions', + 'view latest version', + 'view any unpublished content', + 'use ' . $this->workflow->id() . ' transition create_new_draft', + 'use ' . $this->workflow->id() . ' transition publish', + 'use ' . $this->workflow->id() . ' transition archived_published', + 'use ' . $this->workflow->id() . ' transition archived_draft', + 'use ' . $this->workflow->id() . ' transition archive', + 'administer nodes', + 'bypass node access', + 'administer content translation', + 'translate any entity', + 'create content translations', + 'administer languages', + 'administer content types', + 'administer node form display', + 'edit any paragraphed_test content', + 'create paragraphed_test content', + 'edit behavior plugin settings', + 'administer paragraphs library', + 'administer workflows' + ]); + + $this->drupalGet('admin/config/workflow/workflows/manage/' . $this->workflow->id() . '/type/paragraphs_library_item'); + $edit = [ + 'bundles[paragraphs_library_item]' => 1, + ]; + $this->submitForm($edit, 'Save'); + + $this->enableConvertingParagraphsTypeToLibrary('nested_paragraph'); + + // Add node with text paragraph. + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_err_field_test_content_add_more'); + $edit = [ + 'title[0][value]' => 'En label Test node nested', + 'field_paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'En label Example text for test in nested paragraph', + 'moderation_state[0][state]' => 'published' + ]; + $this->submitForm($edit, 'Save'); + + // Add translation for node. + $node = $this->drupalGetNodeByTitle('En label Test node nested'); + $this->drupalGet('node/' . $node->id() . '/translations'); + $this->clickLink('Add'); + $edit = [ + 'title[0][value]' => 'Testknoten', + 'field_paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'De label Beispieltext fur den Test in geschachteltem Absatz.', + ]; + $this->submitForm($edit, 'Save (this translation)'); + + // Convert translated paragraph to library. + $this->drupalGet($node->toUrl('edit-form')); + $this->submitForm([], 'field_paragraphs_0_promote_to_library'); + $this->submitForm([], 'Save (this translation)'); + + // Visible to admins. + $this->drupalGet($node->toUrl()); + $this->assertSession()->pageTextContains('En label Example text for test in nested paragraph'); + $this->drupalGet('de/node/' . $node->id()); + $this->assertSession()->pageTextContains('De label Beispieltext fur den Test in geschachteltem Absatz.'); + + // And to anonymous users as well. + $this->drupalLogout(); + $this->drupalGet('de/node/' . $node->id()); + $this->assertSession()->pageTextContains('De label Beispieltext fur den Test in geschachteltem Absatz.'); + } + /** * Tests converting translated nested paragraph from library. */ @@ -181,13 +265,13 @@ public function testDetachTranslatedNestedParagraphItemFromLibrary() { // Add paragraph directly in library. $this->drupalGet('admin/content/paragraphs/add/default'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_0_subform_field_err_field_test_content_add_more'); + $this->submitForm([], 'paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'paragraphs_0_subform_field_err_field_test_content_add_more'); $edit = [ 'label[0][value]' => 'En label Test nested paragraph', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'En label Example text for test.' ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph En label Test nested paragraph has been created.'); // Translate nested paragraphs library item. @@ -197,23 +281,24 @@ public function testDetachTranslatedNestedParagraphItemFromLibrary() { 'label[0][value]' => 'De label Test geschachtelten Absatz', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'De label Beispieltext fur den Test in geschachteltem Absatz.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Create test content. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_from_library_add_more'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'En label Test node nested', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 'En label Test nested paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Add translation for test node. $node = $this->drupalGetNodeByTitle('En label Test node nested'); $edit = [ 'title[0][value]' => 'De label Testknoten', ]; - $this->drupalPostForm('de/node/' . $node->id() . '/translations/add/en/de', $edit, 'Save (this translation)'); + $this->drupalGet('de/node/' . $node->id() . '/translations/add/en/de'); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('De label Beispieltext fur den Test in geschachteltem Absatz.'); @@ -225,7 +310,7 @@ public function testDetachTranslatedNestedParagraphItemFromLibrary() { $this->drupalGet('node/' . $node->id()); $this->assertSession()->pageTextContains('En label Example text for test.'); $this->clickLink('Edit'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_0_unlink_from_library'); + $this->submitForm([], 'field_paragraphs_0_unlink_from_library'); $this->assertSession()->pageTextContains('En label Example text for test.'); } @@ -237,13 +322,13 @@ public function testDetachBeforeTranslation() { // Add paragraph directly in library. $this->drupalGet('admin/content/paragraphs/add/default'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_0_subform_field_err_field_test_content_add_more'); + $this->submitForm([], 'paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'paragraphs_0_subform_field_err_field_test_content_add_more'); $edit = [ 'label[0][value]' => 'En label Test nested paragraph', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'En label Example text for test.' ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph En label Test nested paragraph has been created.'); // Translate nested paragraphs library item. @@ -253,24 +338,25 @@ public function testDetachBeforeTranslation() { 'label[0][value]' => 'De label Test geschachtelten Absatz', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'De label Beispieltext fur den Test in geschachteltem Absatz.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Create test content. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_from_library_add_more'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'En label Test node nested', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 'En label Test nested paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_unlink_from_library'); + $this->submitForm($edit, 'field_paragraphs_0_unlink_from_library'); $edit = [ 'title[0][value]' => 'En label Test node nested', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Add translation for test node. $node = $this->drupalGetNodeByTitle('En label Test node nested'); - $this->drupalPostForm('de/node/' . $node->id() . '/translations/add/en/de', NULL, 'Save (this translation)'); + $this->drupalGet('de/node/' . $node->id() . '/translations/add/en/de'); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('De label Beispieltext fur den Test in geschachteltem Absatz.'); @@ -291,6 +377,7 @@ public function enableConvertingParagraphsTypeToLibrary($paragraphs_type) { $edit = [ 'allow_library_conversion' => 1, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraphs_type, $edit, 'Save'); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraphs_type); + $this->submitForm($edit, 'Save'); } } diff --git a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTest.php b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTest.php index 0f13b888e04abb7494002c84ba66969995891b81..da3e76016fde4cb0021d1bd240a40156a4808f07 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTest.php +++ b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTest.php @@ -8,6 +8,7 @@ use Drupal\Tests\BrowserTestBase; use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; +use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; /** * Tests the functionality of the Paragraphs Library. @@ -16,14 +17,14 @@ */ class ParagraphsLibraryItemTest extends BrowserTestBase { - use ParagraphsTestBaseTrait, FieldUiTestTrait; + use ParagraphsTestBaseTrait, FieldUiTestTrait, ParagraphsCoreVersionUiTestTrait; /** * Modules to be enabled. * * @var string[] */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_library', 'block', @@ -38,7 +39,7 @@ class ParagraphsLibraryItemTest extends BrowserTestBase { /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->addParagraphedContentType('paragraphed_test', 'field_paragraphs'); @@ -56,10 +57,7 @@ public function setUp() { ]); $this->drupalLogin($admin); - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); } /** @@ -80,7 +78,7 @@ public function testLibraryItemsAccessControl() { 'label[0][value]' => 'Library item', 'paragraphs[0][subform][field_text][0][value]' => 'Item content', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph Library item has been created'); // Assert a user has no access to the global library overview page. $this->assertSession()->statusCodeEquals(403); @@ -165,8 +163,8 @@ public function testNoConversionSideEffects() { // Convert the container to a library item. $this->drupalGet('/node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Promote to library'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Promote to library'); + $this->submitForm([], 'Save'); // Check that the child text paragraph is present in the node. $this->assertSession()->pageTextContains('Test text 1'); @@ -181,7 +179,7 @@ public function testNoConversionSideEffects() { $this->getSession()->getPage() ->findButton('paragraphs_0_subform_paragraphs_container_paragraphs_0_remove') ->press(); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); // Check that the child text paragraph is no longer present in the // library item or the node. @@ -205,9 +203,9 @@ public function testNoConversionSideEffects() { // Add a new text paragraph to the library item. $this->drupalGet('/admin/content/paragraphs/' . $library_item->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Add text'); + $this->submitForm([], 'Add text'); $this->getSession()->getPage()->fillField('field_text', 'Test text 2'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); // Check that the child text paragraph is present in the library item and // the node. @@ -219,11 +217,11 @@ public function testNoConversionSideEffects() { // Convert the library item in the node back to a container paragraph and // delete it. $this->drupalGet('/node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Unlink from library'); + $this->submitForm([], 'Unlink from library'); $this->getSession()->getPage() ->findButton('field_paragraphs_0_subform_paragraphs_container_paragraphs_0_remove') ->press(); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); // Check that the child text paragraph is no longer present in the node but // still present in the library item. @@ -275,7 +273,7 @@ public function testLibraryItemUsageTab() { 'label[0][value]' => 'Test usage nested paragraph', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'Example text for revision in nested paragraph.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $assert_session->pageTextContains('Paragraph Test usage nested paragraph has been created.'); // Create content with referenced paragraph. @@ -285,7 +283,7 @@ public function testLibraryItemUsageTab() { 'title[0][value]' => 'Test content', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 'Test usage nested paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('Test content'); // Check Usage tab. @@ -308,8 +306,8 @@ public function testLibraryItemUsageTab() { // Unlink library item and check usage tab. $node = $this->drupalGetNodeByTitle('Test content'); $this->drupalGet($node->toUrl('edit-form')); - $this->drupalPostForm(NULL, [], 'Unlink from library'); - $this->drupalPostForm(NULL, ['revision' => TRUE], 'Save'); + $this->submitForm([], 'Unlink from library'); + $this->submitForm(['revision' => TRUE], 'Save'); // Check Usage tab. $this->drupalGet('admin/content/paragraphs'); @@ -341,7 +339,7 @@ public function testLibraryItemDeleteWarningMessage() { 'label[0][value]' => 'Test usage warning message', 'paragraphs[0][subform][field_text][0][value]' => 'Example text.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $assert_session->pageTextContains('Paragraph Test usage warning message has been created.'); // Create content with referenced paragraph. @@ -351,7 +349,7 @@ public function testLibraryItemDeleteWarningMessage() { 'title[0][value]' => 'Test content', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 'Test usage warning message', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('Test content'); $library_item = $node->get('field_paragraphs')->entity->get('field_reusable_paragraph')->entity; diff --git a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTranslationTest.php b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTranslationTest.php index 3fd2014f97ca143b50da7861bd4b95f21f9e200f..af0af9224229c97dccf8c0b8b960acb8618f41b2 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTranslationTest.php +++ b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryItemTranslationTest.php @@ -2,12 +2,14 @@ namespace Drupal\Tests\paragraphs_library\Functional; +use Drupal\block\Entity\Block; use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\paragraphs\Entity\ParagraphsType; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\paragraphs\FunctionalJavascript\LoginAdminTrait; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; +use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; /** * Tests the multilingual functionality of the Paragraphs Library. @@ -19,13 +21,14 @@ class ParagraphsLibraryItemTranslationTest extends BrowserTestBase { use ParagraphsTestBaseTrait; use LoginAdminTrait; use FieldUiTestTrait; + use ParagraphsCoreVersionUiTestTrait; /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'views', 'paragraphs_library', 'link', @@ -44,14 +47,11 @@ class ParagraphsLibraryItemTranslationTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->addParagraphedContentType('paragraphed_test'); - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); // Add a second language (German) to the site. ConfigurableLanguage::createFromLangcode('de')->save(); @@ -92,14 +92,15 @@ public function testLibraryItemTranslation() { 'settings[paragraphs_library_item][paragraphs_library_item][translatable]' => TRUE, 'settings[node][paragraphed_test][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); $assert_session = $this->assertSession(); $page = $this->getSession()->getPage(); // Add a node and translate it. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'Add text'); + $this->submitForm([], 'Add text'); $assert_session->buttonExists('field_paragraphs_0_promote_to_library'); $assert_session->buttonExists('Promote to library'); @@ -107,7 +108,7 @@ public function testLibraryItemTranslation() { 'title[0][value]' => 'EN Title', 'field_paragraphs[0][subform][field_text][0][value]' => 'EN Library text', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $assert_session->pageTextContains('paragraphed_test EN Title has been created.'); $this->clickLink('Translate'); @@ -117,7 +118,7 @@ public function testLibraryItemTranslation() { 'title[0][value]' => 'DE Title', 'field_paragraphs[0][subform][field_text][0][value]' => 'DE Library text', ]; - $this->drupalPostForm(NULL, $edit, 'Save (this translation)'); + $this->submitForm($edit, 'Save (this translation)'); $assert_session->pageTextContains('paragraphed_test DE Title has been updated.'); // Convert the text to a library item and make sure it is displayed @@ -126,7 +127,7 @@ public function testLibraryItemTranslation() { $this->drupalGet('node/' . $node->id() . '/edit'); $page->pressButton('Promote to library'); $assert_session->fieldValueEquals('Reusable paragraph', 'text: EN Library text (1)'); - $this->drupalPostForm(NULL, NULL, 'Save'); + $this->submitForm([], 'Save'); $assert_session->pageTextContains('EN Title'); $assert_session->pageTextContains('EN Library text'); @@ -152,13 +153,13 @@ public function testLibraryItemTranslation() { // Add a node with a text paragraph. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'Add text'); + $this->submitForm([], 'Add text'); $edit = [ 'title[0][value]' => 'DE Llama Test', 'langcode[0][value]' => 'de', 'field_paragraphs[0][subform][field_text][0][value]' => 'DE Text Paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $assert_session->pageTextContains('paragraphed_test DE Llama Test has been created.'); // Translate the node to the default language. @@ -168,7 +169,7 @@ public function testLibraryItemTranslation() { 'title[0][value]' => 'EN Llama Test', 'field_paragraphs[0][subform][field_text][0][value]' => 'EN Library text', ]; - $this->drupalPostForm(NULL, $edit, 'Save (this translation)'); + $this->submitForm($edit, 'Save (this translation)'); $assert_session->pageTextContains('paragraphed_test EN Llama Test has been updated.'); // Assert the original node can promote paragraphs to the library. @@ -176,7 +177,7 @@ public function testLibraryItemTranslation() { $this->drupalGet('de/node/' . $node->id() . '/edit'); $page->pressButton('field_paragraphs_0_promote_to_library'); $assert_session->fieldValueEquals('Reusable paragraph', 'text: DE Text Paragraph (2)'); - $this->drupalPostForm(NULL, NULL, 'Save'); + $this->submitForm([], 'Save'); $assert_session->pageTextContains('paragraphed_test DE Llama Test has been updated.'); $this->drupalGet('node/' . $node->id() . '/edit'); $assert_session->pageTextContains('Reusable paragraph'); diff --git a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryTest.php b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryTest.php index d8970da2709dd684637b051dc4d5bbc7f0c0f098..aabcd51914c0ae5d339067d1e8250ced632a0292 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryTest.php +++ b/web/modules/paragraphs/modules/paragraphs_library/tests/src/Functional/ParagraphsLibraryTest.php @@ -3,21 +3,21 @@ namespace Drupal\Tests\paragraphs_library\Functional; use Drupal\Core\Url; -use Drupal\Tests\paragraphs\Functional\Experimental\ParagraphsExperimentalTestBase; +use Drupal\Tests\paragraphs\Functional\WidgetStable\ParagraphsTestBase; /** * Tests paragraphs library functionality. * * @group paragraphs_library */ -class ParagraphsLibraryTest extends ParagraphsExperimentalTestBase { +class ParagraphsLibraryTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'views', 'paragraphs_library', ]; @@ -25,7 +25,7 @@ class ParagraphsLibraryTest extends ParagraphsExperimentalTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->addParagraphedContentType('paragraphed_test'); } @@ -47,17 +47,21 @@ public function testLibraryItems() { // Add a new library item. $this->drupalGet('admin/content/paragraphs'); $this->clickLink('Add library item'); - $this->drupalPostForm(NULL, [], 'paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'paragraphs_text_paragraph_add_more'); $edit = [ 'label[0][value]' => 're usable paragraph label', 'paragraphs[0][subform][field_text][0][value]' => 're_usable_text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->clickLink('re usable paragraph label'); $this->assertSession()->responseContains('bartik/css/base/elements.css'); $this->clickLink('Edit'); $this->assertSession()->responseNotContains('class="messages messages--warning"'); - $items = \Drupal::entityQuery('paragraphs_library_item')->sort('id', 'DESC')->range(0, 1)->execute(); + $items = \Drupal::entityQuery('paragraphs_library_item') + ->accessCheck(TRUE) + ->sort('id', 'DESC') + ->range(0, 1) + ->execute(); $library_item_id = reset($items); // Assert local tasks and URLs. @@ -85,12 +89,13 @@ public function testLibraryItems() { $this->assertSession()->fieldExists('paragraphs[0][subform][field_text][0][value]'); // Create a node with the library paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_from_library_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'library_test', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 're usable paragraph label (1)' ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $library_items = \Drupal::entityTypeManager()->getStorage('paragraphs_library_item')->loadByProperties(['label' => 're usable paragraph label']); $this->drupalGet('admin/content/paragraphs/' . current($library_items)->id() . '/edit'); @@ -159,7 +164,7 @@ public function testLibraryItems() { $alternative_display->save(); $this->drupalGet('node/' . $node_one->id()); - $this->assertText('re_usable_text'); + $this->assertSession()->pageTextContains('re_usable_text'); /** @var \Drupal\Core\Entity\Entity\EntityViewDisplay $from_library_view_display */ $from_library_view_display = $display_storage->load('paragraph.from_library.default'); @@ -169,7 +174,7 @@ public function testLibraryItems() { $from_library_view_display->save(); $this->drupalGet('node/' . $node_one->id()); - $this->assertNoText('re_usable_text'); + $this->assertSession()->pageTextNotContains('re_usable_text'); $from_library_view_display = $display_storage->load('paragraph.from_library.default'); $field_reusable_paragraph_component = $from_library_view_display->getComponent('field_reusable_paragraph'); @@ -178,12 +183,13 @@ public function testLibraryItems() { $from_library_view_display->save(); // Create a new node with the library paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_from_library_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'library_test_new', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 're usable paragraph label (1)' ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Assert that the paragraph is shown correctly. $node_two = $this->getNodeByTitle('library_test_new'); $this->assertSession()->addressEquals('node/' . $node_two->id()); @@ -193,13 +199,13 @@ public function testLibraryItems() { $this->assertSession()->elementTextNotContains('css', '.paragraph--type--from-library', 'Paragraphs'); $this->drupalGet('node/' . $node_two->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_from_library_add_more'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'library_test_new', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 're usable paragraph label (1)', 'field_paragraphs[1][subform][field_reusable_paragraph][0][target_id]' => 're usable paragraph label (1)', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $reusable_paragraphs_text = $this->xpath('//div[contains(@class, "field--name-field-paragraphs")]/div[@class="field__items"]/div[1]//div[@class="field__item"]/p'); $this->assertEquals($reusable_paragraphs_text[0]->getText(), 're_usable_text'); @@ -220,7 +226,7 @@ public function testLibraryItems() { $edit = [ 'paragraphs[0][subform][field_text][0][value]' => 're_usable_text_new', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check in both nodes that the text is updated. Test as anonymous user, so // that the cache is populated. @@ -239,7 +245,7 @@ public function testLibraryItems() { $edit = [ 'status[value]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/' . $node_one->id()); $this->assertSession()->pageTextContains('re_usable_text_new'); @@ -254,7 +260,7 @@ public function testLibraryItems() { $edit = [ 'status[value]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/' . $node_one->id()); $this->assertSession()->pageTextContains('re_usable_text_new'); @@ -290,7 +296,7 @@ public function testLibraryItems() { $this->assertSession()->linkExists('Manage display'); // Assert that users can create fields to $this->clickLink('Manage fields'); - $this->clickLink(t('Add field')); + $this->clickLink('Add field'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextNotContains('plugin does not exist'); $this->drupalGet('admin/config/content'); @@ -315,31 +321,32 @@ public function testConvertLibraryItemIntoParagraph() { // Add a new library item. $this->drupalGet('admin/content/paragraphs'); $this->clickLink('Add library item'); - $this->drupalPostForm(NULL, [], 'paragraphs_text_add_more'); + $this->submitForm([], 'paragraphs_text_add_more'); $edit = [ 'label[0][value]' => 'reusable paragraph label', 'paragraphs[0][subform][field_text][0][value]' => 'reusable_text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph reusable paragraph label has been created.'); // Add created library item to a node. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_from_library_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'Node with converted library item', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 'reusable paragraph label', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Node with converted library item has been created.'); $this->assertSession()->pageTextContains('reusable_text'); // Convert library item to paragraph. $this->clickLink('Edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_unlink_from_library'); + $this->submitForm([], 'field_paragraphs_0_unlink_from_library'); $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_text][0][value]'); $this->assertSession()->fieldNotExists('field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]'); $this->assertSession()->pageTextContains('reusable_text'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('reusable_text'); } @@ -360,11 +367,12 @@ public function testConvertParagraphIntoLibrary() { static::fieldUIAddNewField('admin/structure/paragraphs_type/' . $paragraph_type, 'text', 'Text', 'text_long', [], []); $edit = ['allow_library_conversion' => 1]; - $this->drupalPostForm('admin/structure/paragraphs_type/text', $edit, 'Save'); + $this->drupalGet('admin/structure/paragraphs_type/text'); + $this->submitForm($edit, 'Save'); // Adding library item is available with the administer library permission. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'Add text'); + $this->submitForm([], 'Add text'); $this->assertSession()->buttonExists('field_paragraphs_0_promote_to_library'); $this->drupalGet('admin/content/paragraphs/add/default'); $this->assertSession()->statusCodeEquals(200); @@ -374,7 +382,7 @@ public function testConvertParagraphIntoLibrary() { $user_role = end($user_roles); user_role_revoke_permissions($user_role, ['administer paragraphs library']); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'Add text'); + $this->submitForm([], 'Add text'); $this->assertSession()->buttonNotExists('field_paragraphs_0_promote_to_library'); $this->drupalGet('admin/content/paragraphs/add/default'); $this->assertSession()->statusCodeEquals(403); @@ -383,19 +391,20 @@ public function testConvertParagraphIntoLibrary() { $edit = [ 'behavior_plugins[test_text_color][enabled]' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text', $edit, 'Save'); + $this->drupalGet('admin/structure/paragraphs_type/text'); + $this->submitForm($edit, 'Save'); // Assign "create paragraph library item" permission to a user. user_role_grant_permissions($user_role, ['create paragraph library item']); $this->drupalGet('admin/content/paragraphs/add/default'); $this->assertSession()->statusCodeEquals(200); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'Add text'); + $this->submitForm([], 'Add text'); $this->assertSession()->buttonExists('field_paragraphs_0_promote_to_library'); $this->assertSession()->responseContains('Promote to library'); $edit = [ 'field_paragraphs[0][subform][field_text][0][value]' => 'Random text for testing converting into library.', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_promote_to_library'); + $this->submitForm($edit, 'field_paragraphs_0_promote_to_library'); $this->assertSession()->pageTextContains('From library'); $this->assertSession()->pageTextContains('Reusable paragraph'); $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]'); @@ -404,21 +413,21 @@ public function testConvertParagraphIntoLibrary() { ]; $this->assertSession()->buttonNotExists('field_paragraphs_0_promote_to_library'); $this->assertSession()->buttonExists('field_paragraphs_0_unlink_from_library'); - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/1'); $this->assertSession()->pageTextContains('Random text for testing converting into library.'); // Create library item from existing paragraph item. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'Add text'); + $this->submitForm([], 'Add text'); $edit = [ 'title[0][value]' => 'NodeTitle', 'field_paragraphs[0][subform][field_text][0][value]' => 'Random text for testing converting into library.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $node = $this->getNodeByTitle('NodeTitle'); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_promote_to_library'); + $this->submitForm($edit, 'field_paragraphs_0_promote_to_library'); user_role_grant_permissions($user_role, ['administer paragraphs library']); $this->drupalGet('/admin/content/paragraphs'); $this->assertSession()->pageTextContains('Text'); @@ -426,7 +435,8 @@ public function testConvertParagraphIntoLibrary() { // Test disallow convesrion. $edit = ['allow_library_conversion' => FALSE]; - $this->drupalPostForm('admin/structure/paragraphs_type/text', $edit, 'Save'); + $this->drupalGet('admin/structure/paragraphs_type/text'); + $this->submitForm($edit, 'Save'); /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */ $config_factory = \Drupal::service('config.factory'); @@ -434,7 +444,7 @@ public function testConvertParagraphIntoLibrary() { $this->assertFalse(isset($third_party['paragraphs_library']['allow_library_conversion'])); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, 'Add text'); + $this->submitForm([], 'Add text'); $this->assertSession()->responseNotContains('Promote to library'); // Test that the checkbox is not visible on from_library. @@ -462,14 +472,15 @@ public function testLibraryItemParagraphsSummary() { $edit = [ 'fields[field_paragraphs][type]' => 'paragraphs', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->drupalPostForm('admin/content/paragraphs/add/default', [], 'paragraphs_nested_test_add_more'); - $this->drupalPostForm(NULL, [], 'paragraphs_0_subform_field_paragraphs_text_add_more'); + $this->submitForm($edit, 'Save'); + $this->drupalGet('admin/content/paragraphs/add/default'); + $this->submitForm([], 'paragraphs_nested_test_add_more'); + $this->submitForm([], 'paragraphs_0_subform_field_paragraphs_text_add_more'); $edit = [ 'label[0][value]' => 'Test nested', 'paragraphs[0][subform][field_paragraphs][0][subform][field_text][0][value]' => 'test text paragraph', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('test text paragraph'); // Assert that the user with the access content permission can see the @@ -504,26 +515,26 @@ public function testLibraryitemValidation() { $this->clickLink('Add library item'); // Check the label validation. - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Label field is required.'); $edit = [ 'label[0][value]' => 're usable paragraph label', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check the paragraph validation. $this->assertSession()->pageTextContains('Paragraphs field is required.'); - $this->drupalPostForm(NULL, [], 'paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'paragraphs_text_paragraph_add_more'); $edit['paragraphs[0][subform][field_text][0][value]'] = 're_usable_text'; // Check that the library item is created. - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph re usable paragraph label has been created.'); $this->clickLink('Edit'); $edit = [ 'paragraphs[0][subform][field_text][0][value]' => 'new text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph re usable paragraph label has been updated.'); } @@ -543,23 +554,23 @@ public function testLibraryReferencingParagraphValidation() { // Add a library item with paragraphs type "Text". $this->drupalGet('admin/content/paragraphs'); $this->clickLink('Add library item'); - $this->drupalPostForm(NULL, [], 'paragraphs_text_add_more'); + $this->submitForm([], 'paragraphs_text_add_more'); $edit = [ 'label[0][value]' => 'reusable paragraph label', 'paragraphs[0][subform][field_text][0][value]' => 'reusable_text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph reusable paragraph label has been created.'); // Create a node with a "From library" paragraph referencing the library // item. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_from_library_add_more'); + $this->submitForm([], 'field_paragraphs_from_library_add_more'); $edit = [ 'title[0][value]' => 'library_test', 'field_paragraphs[0][subform][field_reusable_paragraph][0][target_id]' => 'reusable paragraph label', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test library_test has been created.'); // Disallow the paragraphs type "Text" for the used content type. @@ -569,13 +580,13 @@ public function testLibraryReferencingParagraphValidation() { 'settings[handler_settings][target_bundles_drag_drop][from_library][enabled]' => 1, 'settings[handler_settings][target_bundles_drag_drop][text][enabled]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save settings')); + $this->submitForm($edit, 'Save settings'); $this->assertSession()->pageTextContains('Saved field_paragraphs configuration.'); // Check that the node now fails validation. $node = $this->getNodeByTitle('library_test'); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->addressEquals('node/' . $node->id() . '/edit'); $this->assertSession()->pageTextContains('The Reusable paragraph field cannot contain a text paragraph, because the parent field_paragraphs field disallows it.'); } @@ -603,13 +614,13 @@ public function testLibraryItemRevisions() { // Add nested paragraph directly in library. $this->drupalGet('admin/content/paragraphs/add/default'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'paragraphs_0_subform_field_err_field_test_content_add_more'); + $this->submitForm([], 'paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'paragraphs_0_subform_field_err_field_test_content_add_more'); $edit = [ 'label[0][value]' => 'Test revisions nested original', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'Example text for revision original.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph Test revisions nested original has been created.'); // Check revisions tab. @@ -624,7 +635,7 @@ public function testLibraryItemRevisions() { 'label[0][value]' => 'Test revisions nested first change', 'paragraphs[0][subform][field_err_field][0][subform][field_paragraphs_text][0][value]' => 'Example text for revision first change.', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Check previous revision. $storage = \Drupal::entityTypeManager()->getStorage('paragraphs_library_item'); @@ -642,14 +653,9 @@ public function testLibraryItemRevisions() { // Test reverting revision. $this->clickLink('Revert'); - $this->assertSession()->responseContains(t('Are you sure you want to revert revision from %revision-date?', [ - '%revision-date' => $date_formatter->format($revision->getChangedTime()) - ])); - $this->drupalPostForm(NULL, NULL, 'Revert'); - $this->assertSession()->responseContains(t('%title has been reverted to the revision from %revision-date.', [ - '%title' => 'Test revisions nested original', - '%revision-date' => $date_formatter->format($revision->getChangedTime()) - ])); + $this->assertSession()->responseContains('Are you sure you want to revert revision from ' . $date_formatter->format($revision->getChangedTime()) . '?'); + $this->submitForm([], 'Revert'); + $this->assertSession()->pageTextContains('Test revisions nested original has been reverted to the revision from ' . $date_formatter->format($revision->getChangedTime()) . '.'); // Check current revision. $current_revision = $storage->loadRevision(3); @@ -660,13 +666,9 @@ public function testLibraryItemRevisions() { // Test deleting revision. $revision_for_deleting = $storage->loadRevision(2); $this->clickLink('Delete'); - $this->assertSession()->responseContains(t('Are you sure you want to delete revision from %revision-date', [ - '%revision-date' => $date_formatter->format($revision_for_deleting->getChangedTime()) - ])); - $this->drupalPostForm(NULL, NULL, 'Delete'); - $this->assertSession()->responseContains(t('Revision from %revision-date has been deleted.', [ - '%revision-date' => $date_formatter->format($revision_for_deleting->getChangedTime()) - ])); + $this->assertSession()->responseContains('Are you sure you want to delete revision from ' . $date_formatter->format($revision_for_deleting->getChangedTime())); + $this->submitForm([], 'Delete'); + $this->assertSession()->pageTextContains('Revision from ' . $date_formatter->format($revision_for_deleting->getChangedTime()) .' has been deleted.'); } } diff --git a/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsContentModerationTest.php b/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsContentModerationTest.php index a8a2a6233ff1dae9e3773738b4c4c5a2174a1b48..9f951361999dfe791a6298d551614964a8d53552 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsContentModerationTest.php +++ b/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsContentModerationTest.php @@ -3,9 +3,11 @@ namespace Drupal\Tests\paragraphs_library\FunctionalJavascript; use Behat\Mink\Element\Element; -use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; +use Drupal\paragraphs\Entity\ParagraphsType; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; +use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; use Drupal\Tests\paragraphs\Traits\ParagraphsLastEntityQueryTrait; /** @@ -15,7 +17,7 @@ */ class ParagraphsContentModerationTest extends WebDriverTestBase { - use ParagraphsTestBaseTrait, FieldUiTestTrait, ParagraphsLastEntityQueryTrait; + use ParagraphsTestBaseTrait, FieldUiTestTrait, ParagraphsLastEntityQueryTrait, ParagraphsCoreVersionUiTestTrait; /** * A user with permission to bypass access content. @@ -58,9 +60,9 @@ class ParagraphsContentModerationTest extends WebDriverTestBase { /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); - $this->addParagraphedContentType('paragraphed_moderated_test', 'field_paragraphs', 'entity_reference_paragraphs'); + $this->addParagraphedContentType('paragraphed_moderated_test', 'field_paragraphs'); $this->addParagraphsType('text'); $this->addFieldtoParagraphType('text', 'field_text', 'text'); @@ -112,10 +114,7 @@ public function setUp() { 'view all revisions', ]); - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); $this->drupalLogin($this->adminUser); } @@ -260,10 +259,11 @@ public function testModeratedParagraphedContent() { $this->drupalGet("/node/{$host_node_id}/edit"); $page->fillField('title[0][value]', 'Host page 1 (rev 4)'); $page->fillField('field_paragraphs[1][subform][field_text][0][value]', 'Direct paragraph text 2 modified again'); + $row = $assert_session->elementExists('css', '#field-paragraphs-add-more-wrapper tr.draggable:nth-of-type(3)'); + $dropdown = $assert_session->elementExists('css', '.paragraphs-dropdown', $row); + $dropdown->click(); $paragraph3_remove_button = $assert_session->elementExists('css', 'input[name="field_paragraphs_2_remove"]'); $paragraph3_remove_button->press(); - $paragraph3_confirm_remove_button = $assert_session->waitForElement('css', 'input[name="field_paragraphs_2_confirm_remove"]'); - $paragraph3_confirm_remove_button->press(); $assert_session->assertWaitOnAjaxRequest(); $page->selectFieldOption('moderation_state[0][state]', 'draft'); $page->find('css', 'a[href="#edit-revision-information"]')->click(); @@ -406,11 +406,13 @@ public function testModeratedParagraphedContent() { $nodes = \Drupal::entityTypeManager()->getStorage('node')->getQuery() ->allRevisions() ->condition($host_node->getEntityType()->getKey('id'), $host_node->id()) + ->accessCheck(TRUE) ->execute(); $this->assertEquals(7, count($nodes)); $library_items = \Drupal::entityTypeManager()->getStorage('paragraphs_library_item')->getQuery() ->allRevisions() ->condition($library_item->getEntityType()->getKey('id'), $library_item->id()) + ->accessCheck(TRUE) ->execute(); $this->assertEquals(6, count($library_items)); @@ -421,6 +423,56 @@ public function testModeratedParagraphedContent() { $assert_session->pageTextContains('Content types'); $assert_session->elementNotExists('css', 'a[href$="' . $this->workflow->id() . '/type/paragraph"]'); $assert_session->elementExists('css', 'a[href$="' . $this->workflow->id() . '/type/node"]'); + + // Promote a library and assert that is published when created. + $paragraph_type = ParagraphsType::load('text'); + $paragraph_type->setThirdPartySetting('paragraphs_library', 'allow_library_conversion', TRUE); + $paragraph_type->save(); + $this->drupalGet('/node/add/paragraphed_moderated_test'); + $page->fillField('title[0][value]', 'Host page 1'); + $dropbutton_paragraphs = $assert_session->elementExists('css', '#field-paragraphs-add-more-wrapper .dropbutton-arrow'); + $dropbutton_paragraphs->click(); + $add_text_paragraph = $assert_session->elementExists('css', '#field-paragraphs-text-add-more'); + $add_text_paragraph->press(); + $textfield = $assert_session->waitForElement('css', 'input[name="field_paragraphs[0][subform][field_text][0][value]"]'); + $this->assertNotNull($textfield); + $page->fillField('field_paragraphs[0][subform][field_text][0][value]', 'Promoted library item'); + $first_row = $assert_session->elementExists('css', '#field-paragraphs-add-more-wrapper tr.draggable:nth-of-type(1)'); + $dropdown = $assert_session->elementExists('css', '.paragraphs-dropdown', $first_row); + $dropdown->click(); + $add_above_button = $assert_session->elementExists('css', 'input[name="field_paragraphs_0_promote_to_library"]', $first_row); + $add_above_button->click(); + $library_item = $this->getLastEntityOfType('paragraphs_library_item', TRUE); + $this->assertEquals('published', $library_item->moderation_state->value); + + // Assert the unpublished indicator for library items. + ParagraphsType::load('text')->setThirdPartySetting('paragraphs_library', 'allow_library_conversion', TRUE)->save(); + $this->drupalGet('node/add'); + $title = $assert_session->fieldExists('Title'); + $title->setValue('Paragraph test'); + $element = $page->find('xpath', '//*[contains(@class, "dropbutton-toggle")]'); + $element->click(); + $button = $page->findButton('Add text'); + $button->press(); + $assert_session->waitForElementVisible('css', '.ui-dialog'); + $page->fillField('field_paragraphs[0][subform][field_text][0][value]', 'This is a reusable text UPDATED.'); + $first_row = $assert_session->elementExists('css', '#field-paragraphs-add-more-wrapper tr.draggable:nth-of-type(1)'); + $dropdown = $assert_session->elementExists('css', '.paragraphs-dropdown', $first_row); + $dropdown->click(); + $page->pressButton('Promote to library'); + $assert_session->assertWaitOnAjaxRequest(); + // New library items are published by default. + $status_icon = $page->find('css', '.paragraph-formatter.paragraphs-icon-view'); + $this->assertNull($status_icon); + // Archive the library item and assert there is a unpublished icon. + $edit_button = $page->find('css', 'input[name^="field_reusable_paragraph_edit_button"]'); + $edit_button->press(); + $assert_session->waitForElementVisible('css', '.ui-dialog'); + $assert_session->elementExists('css', '.ui-dialog')->selectFieldOption('moderation_state[0][state]', 'archived'); + $page->find('css', '.ui-dialog-buttonset button:contains("Save")')->press(); + $assert_session->assertWaitOnAjaxRequest(); + $status_icon = $page->find('css', '.paragraphs-icon-view'); + $this->assertTrue($status_icon->isVisible()); } /** diff --git a/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsLibraryItemEntityBrowserTest.php b/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsLibraryItemEntityBrowserTest.php index 4090c498ab05902feef7de9f3636fb2c4ce67c13..5753d8ea098d6df651e82c2d943b8f1e557afd4b 100644 --- a/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsLibraryItemEntityBrowserTest.php +++ b/web/modules/paragraphs/modules/paragraphs_library/tests/src/FunctionalJavascript/ParagraphsLibraryItemEntityBrowserTest.php @@ -18,8 +18,7 @@ class ParagraphsLibraryItemEntityBrowserTest extends EntityBrowserWebDriverTestB /** * {@inheritdoc} */ - public static $modules = [ - 'ctools', + protected static $modules = [ 'views', 'block', 'node', @@ -65,7 +64,8 @@ public function testEntityBrowserWidget() { 'entity_types[paragraphs_library_item]' => TRUE, 'settings[paragraphs_library_item][paragraphs_library_item][translatable]' => TRUE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); $this->addParagraphsType('text'); $this->addFieldtoParagraphType('text', 'field_text', 'text'); @@ -105,7 +105,7 @@ public function testEntityBrowserWidget() { // processing in the iframe. sleep(1); $this->waitForAjaxToFinish(); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); // Check that the paragraph was correctly reused. $this->assertSession()->pageTextContains('reusable_text'); @@ -118,7 +118,7 @@ public function testEntityBrowserWidget() { 'label[0][value]' => 'DE Title', 'paragraphs[0][subform][field_text][0][value]' => 'DE Library text', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Paragraph DE Title has been updated.'); // Add a node with a paragraph from library. diff --git a/web/modules/paragraphs/modules/paragraphs_type_permissions/paragraphs_type_permissions.info.yml b/web/modules/paragraphs/modules/paragraphs_type_permissions/paragraphs_type_permissions.info.yml index 6c65ff200e3b1d8696e792beb6dbcc086e29fb7a..74e3a3c56fbda3273699a3570e9077bb5a5cedc3 100644 --- a/web/modules/paragraphs/modules/paragraphs_type_permissions/paragraphs_type_permissions.info.yml +++ b/web/modules/paragraphs/modules/paragraphs_type_permissions/paragraphs_type_permissions.info.yml @@ -1,13 +1,13 @@ name: Paragraphs Type Permissions type: module description: 'Allows users to configure permissions for individual Paragraphs types.' -core_version_requirement: ^8.7.7 || ^9 +core_version_requirement: ^9.3 || ^10 package: Paragraphs dependencies: - paragraphs:paragraphs -# Information added by Drupal.org packaging script on 2020-05-21 -version: '8.x-1.12' +# Information added by Drupal.org packaging script on 2022-08-25 +version: '8.x-1.15' project: 'paragraphs' -datestamp: 1590061337 +datestamp: 1661440900 diff --git a/web/modules/paragraphs/modules/paragraphs_type_permissions/tests/src/Functional/ParagraphsTypePermissionsTest.php b/web/modules/paragraphs/modules/paragraphs_type_permissions/tests/src/Functional/ParagraphsTypePermissionsTest.php index 223bf255f87e2ae3c627325fe022ea9b7699df3c..0dd14b350faef0f42726a0727a3687c7f19ff990 100644 --- a/web/modules/paragraphs/modules/paragraphs_type_permissions/tests/src/Functional/ParagraphsTypePermissionsTest.php +++ b/web/modules/paragraphs/modules/paragraphs_type_permissions/tests/src/Functional/ParagraphsTypePermissionsTest.php @@ -40,7 +40,7 @@ class ParagraphsTypePermissionsTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->drupalPlaceBlock('system_breadcrumb_block'); ConfigurableLanguage::create(['id' => 'de', 'label' => '1German'])->save(); @@ -83,7 +83,8 @@ protected function setUp() { 'settings[paragraph][text_image][fields][field_text_demo]' => TRUE, 'settings[node][paragraphed_content_demo][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); $display_options = [ 'type' => 'image', @@ -141,24 +142,24 @@ public function testAnonymousParagraphsTypePermissions() { // Create a node with some Paragraph types. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text_image')); - $this->drupalPostForm(NULL, NULL, t('Add images')); - $this->drupalPostForm(NULL, NULL, t('Add text')); + $this->submitForm([], 'Add text_image'); + $this->submitForm([], 'Add images'); + $this->submitForm([], 'Add text'); $image_text = $this->getTestFiles('image')[0]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_0_subform_field_image_demo_0]' => $image_text->uri, - ], t('Upload')); + ], 'Upload'); $images = $this->getTestFiles('image')[1]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_1_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $edit = [ 'title[0][value]' => 'paragraph node title', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Paragraph type Image + Text', 'field_paragraphs_demo[2][subform][field_text_demo][0][value]' => 'Paragraph type Text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Get the node to edit it later. $node = $this->drupalGetNodeByTitle($edit['title[0][value]']); @@ -195,9 +196,9 @@ public function testAnonymousParagraphsTypePermissions() { // Set edit mode to open. $this->drupalGet('admin/structure/types/manage/paragraphed_content_demo/form-display'); - $this->drupalPostForm(NULL, [], "field_paragraphs_demo_settings_edit"); + $this->submitForm([], "field_paragraphs_demo_settings_edit"); $edit = ['fields[field_paragraphs_demo][settings_edit_form][settings][edit_mode]' => 'open']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Unpublish the 'Image + Text' paragraph type. $this->drupalGet('node/' . $node->id() . '/edit'); @@ -205,7 +206,7 @@ public function testAnonymousParagraphsTypePermissions() { $edit = [ 'field_paragraphs_demo[0][subform][status][value]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check that 'Image + Text' paragraph is not shown anymore for admin user. $this->assertSession()->responseNotContains($image_text_tag); diff --git a/web/modules/paragraphs/paragraphs.info.yml b/web/modules/paragraphs/paragraphs.info.yml index f3c67844e9f057b588e12af65c65d80d6e148cbd..657d499f8df00233c45b5a6779a4504f350e1fc9 100644 --- a/web/modules/paragraphs/paragraphs.info.yml +++ b/web/modules/paragraphs/paragraphs.info.yml @@ -1,7 +1,7 @@ name: Paragraphs type: module description: 'Enables the creation of paragraphs entities.' -core_version_requirement: ^8.8 || ^9 +core_version_requirement: ^9.3 || ^10 package: Paragraphs configure: entity.paragraphs_type.collection @@ -16,7 +16,7 @@ test_dependencies: - field_group:field_group - block_field:block_field -# Information added by Drupal.org packaging script on 2020-05-21 -version: '8.x-1.12' +# Information added by Drupal.org packaging script on 2022-08-25 +version: '8.x-1.15' project: 'paragraphs' -datestamp: 1590061337 +datestamp: 1661440900 diff --git a/web/modules/paragraphs/paragraphs.libraries.yml b/web/modules/paragraphs/paragraphs.libraries.yml index e59af4435b50821ceaa4b3276ca8f9953a916ed2..c928e1076243973d6308b8c52dcce1d58a80810c 100644 --- a/web/modules/paragraphs/paragraphs.libraries.yml +++ b/web/modules/paragraphs/paragraphs.libraries.yml @@ -3,8 +3,7 @@ drupal.paragraphs.admin: - core/jquery - core/drupal - core/drupalSettings - - core/jquery.once - - core/jquery.form + - core/once - core/drupal.ajax - core/drupal.dropbutton css: @@ -16,8 +15,7 @@ drupal.paragraphs.widget: - core/jquery - core/drupal - core/drupalSettings - - core/jquery.once - - core/jquery.form + - core/once - core/drupal.ajax - core/drupal.dropbutton - paragraphs/drupal.paragraphs.summary @@ -35,9 +33,8 @@ drupal.paragraphs.add_above_button: js/paragraphs.add_above_button.js: {} dependencies: - core/drupalSettings - - core/jquery.once + - core/once - core/jquery - - core/jquery.form - core/drupal.ajax - core/drupal @@ -49,9 +46,8 @@ drupal.paragraphs.actions: js/paragraphs.actions.js: {} dependencies: - core/drupalSettings - - core/jquery.once + - core/once - core/jquery - - core/jquery.form - core/drupal.ajax - core/drupal @@ -70,7 +66,7 @@ drupal.paragraphs.modal: dependencies: - core/drupal.dialog - core/drupal.dialog.ajax - - core/jquery.once + - core/once paragraphs-dragdrop: css: @@ -94,3 +90,8 @@ drupal.paragraphs.unpublished: css: theme: css/paragraphs.unpublished.css: {} + +paragraphs.seven: + css: + theme: + css/paragraphs.seven.css: {} diff --git a/web/modules/paragraphs/paragraphs.module b/web/modules/paragraphs/paragraphs.module index 53f7d5f091d7665e54a295b81badc313f5deed29..a7fa93770bd6b012fa25f393cf7923087d4a0e38 100644 --- a/web/modules/paragraphs/paragraphs.module +++ b/web/modules/paragraphs/paragraphs.module @@ -5,15 +5,12 @@ * Contains paragraphs.module */ +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\field\FieldStorageConfigInterface; -use Drupal\field\Plugin\migrate\source\d7\Field; -use Drupal\field\Plugin\migrate\source\d7\FieldInstance; -use Drupal\field\Plugin\migrate\source\d7\ViewMode; -use Drupal\migrate_drupal\Plugin\migrate\FieldMigration; use Drupal\paragraphs\Entity\ParagraphsType; -use Drupal\paragraphs\Plugin\migrate\field\FieldCollection; +use Drupal\paragraphs\MigrationPluginsAlterer; use Drupal\Core\Render\Element; use Drupal\Core\Entity\EntityTypeInterface; @@ -103,7 +100,7 @@ function paragraphs_theme_suggestions_paragraph(array $variables) { /** * Implements hook_form_FORM_ID_alter(). */ -function paragraphs_form_entity_form_display_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { +function paragraphs_form_entity_form_display_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($form['#entity_type'], $form['#bundle']); // Loop over ERR field's display options with paragraph target type. foreach (array_keys($field_definitions) as $field_name) { @@ -120,7 +117,7 @@ function paragraphs_form_entity_form_display_edit_form_alter(&$form, \Drupal\Cor /** * Implements hook_form_FORM_ID_alter(). */ -function paragraphs_form_field_storage_config_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { +function paragraphs_form_field_storage_config_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { if ($form_state->getFormObject()->getEntity()->getType() == 'entity_reference') { // Entity Reference fields are no longer supported to reference Paragraphs. unset($form['settings']['target_type']['#options'][(string) t('Content')]['paragraph']); @@ -132,7 +129,7 @@ function paragraphs_form_field_storage_config_edit_form_alter(&$form, \Drupal\Co * * Indicate unsupported multilingual paragraphs field configuration. */ -function paragraphs_form_field_config_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { +function paragraphs_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { $field = $form_state->getFormObject()->getEntity(); if (!\Drupal::hasService('content_translation.manager')) { @@ -195,7 +192,7 @@ function paragraphs_module_implements_alter(&$implementations, $hook) { * Add a warning that paragraph fields can not be translated. * Switch to error if a paragraph field is marked as translatable. */ -function paragraphs_form_language_content_settings_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { +function paragraphs_form_language_content_settings_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Without it Paragraphs message are meaningless. if (!\Drupal::hasService('content_translation.manager')) { return; @@ -314,6 +311,10 @@ function template_preprocess_paragraphs_add_dialog(&$variables) { // $add variable for the add button. $variables['add'] = $variables['element'][$key]; } + elseif ($key == 'add_more_delta') { + // Add the delta to the add wrapper. + $variables['add'][$key] = $variables['element'][$key]; + } else { // Buttons for the paragraph types in the modal form. $variables['buttons'][$key] = $variables['element'][$key]; @@ -350,10 +351,10 @@ function template_preprocess_paragraphs_actions(&$variables) { * Implements hook_preprocess_HOOK() for field_multiple_value_form(). */ function paragraphs_preprocess_field_multiple_value_form(&$variables) { - if (!empty($variables['table']['#header']) && isset($variables['table']['#rows'])) { + if (!empty($variables['table']['#header']) && isset($variables['table']['#rows'][0])) { // Find paragraph_actions and move to header. // @see template_preprocess_field_multiple_value_form() - if (!empty($variables['table']['#rows'][0]['data'][1]['data']['#paragraphs_header'])) { + if (is_array($variables['table']['#rows'][0]['data'][1]) && !empty($variables['table']['#rows'][0]['data'][1]['data']['#paragraphs_header'])) { $variables['table']['#header'][0]['data'] = [ 'title' => $variables['table']['#header'][0]['data'], 'button' => $variables['table']['#rows'][0]['data'][1]['data'], @@ -383,9 +384,11 @@ function paragraphs_preprocess_field_multiple_value_form(&$variables) { foreach ($variables['table']['#rows'] as $key => $value) { $variables['table']['#rows'][$key]['data'][0]['class'][] = 'paragraph-bullet'; // Restore the removed weight and give access FALSE. - $variables['table']['#rows'][$key]['data'][1]['data']['_weight'] = $value['data'][2]['data']; - unset($variables['table']['#rows'][$key]['data'][2]); - $variables['table']['#rows'][$key]['data'][1]['data']['_weight']['#access'] = FALSE; + if (isset($value['data'][2])) { + $variables['table']['#rows'][$key]['data'][1]['data']['_weight'] = $value['data'][2]['data']; + unset($variables['table']['#rows'][$key]['data'][2]); + $variables['table']['#rows'][$key]['data'][1]['data']['_weight']['#access'] = FALSE; + } } } } @@ -398,38 +401,9 @@ function paragraphs_preprocess_field_multiple_value_form(&$variables) { * https://www.drupal.org/project/drupal/issues/2904765 is resolved */ function paragraphs_migration_plugins_alter(array &$migrations) { - /** @var \Drupal\migrate\Plugin\MigrationPluginManager $migration_plugin_manager */ - $migration_plugin_manager = \Drupal::service('plugin.manager.migration'); - /** @var \Drupal\migrate\Plugin\MigrateSourcePluginManager $source_plugin_manager */ - $source_plugin_manager = \Drupal::service('plugin.manager.migrate.source'); - - foreach ($migrations as &$migration) { - if (!empty($migration['source'])) { - $configuration = $migration['source']; - $migration_stub = $migration_plugin_manager->createStubMigration($migration); - $source = $source_plugin_manager->createInstance($migration['source']['plugin'], $configuration, $migration_stub); - if (is_a($migration['class'], FieldMigration::class, TRUE)) { - - // Field storage. - if (is_a($source, Field::class)) { - _paragraphs_migration_entity_type_adjust($migration); - } - - // Field instance. - if (is_a($source, FieldInstance::class)) { - _paragraphs_migration_entity_type_adjust($migration); - _paragraphs_migration_bundle_adjust($migration); - $migration['migration_dependencies']['optional']['d7_field_collection_type'] = 'd7_field_collection_type'; - $migration['migration_dependencies']['optional']['d7_paragraphs_type'] = 'd7_paragraphs_type'; - } - } - - // View Modes. - if (is_a($source, ViewMode::class)) { - _paragraphs_migration_entity_type_adjust($migration, 'targetEntityType'); - } - } - } + $migration_plugins_alterer = \Drupal::service('paragraphs.migration_plugins_alterer'); + assert($migration_plugins_alterer instanceof MigrationPluginsAlterer); + $migration_plugins_alterer->alterMigrationPlugins($migrations); } /** @@ -457,62 +431,33 @@ function paragraphs_entity_base_field_info_alter(&$fields, EntityTypeInterface $ * * @param array $migration * The migration configuration to process. + * + * @deprecated in paragraphs:8.x-1.13 and is removed from paragraphs:8.x-2.0. + * Use \Drupal\paragraphs\MigrationPluginsAlterer::paragraphsMigrationBundleAdjust(). + * @see https://www.drupal.org/project/paragraphs/issues/2911244 */ function _paragraphs_migration_bundle_adjust(array &$migration) { - - if (!isset($migration['process']['bundle'])) { - $migration['process']['bundle'] = []; - } - - $bundle_process = $migration['process']['bundle']; - - // Try to play nice with other modules altering this, and don't replace - // it outright unless it's unchanged. - if (array_key_exists('plugin', $bundle_process)) { - $bundle_process = [$bundle_process]; - } - $bundle_process['paragraphs'] = [ - 'plugin' => 'paragraphs_process_on_value', - 'source_value' => 'entity_type', - 'expected_value' => 'field_collection_item', - 'process' => [ - 'plugin' => 'substr', - 'start' => FieldCollection::FIELD_COLLECTION_PREFIX_LENGTH, - ], - ]; - $migration['process']['bundle'] = $bundle_process; + $migration_plugins_alterer = \Drupal::service('paragraphs.migration_plugins_alterer'); + assert($migration_plugins_alterer instanceof MigrationPluginsAlterer); + $migration_plugins_alterer->paragraphsMigrationBundleAdjust($migration); } /** * Map field_collection_item and 'paragraphs_item' fields to 'paragraph'. * * @param array $migration - * Thei migration to process. + * The migration to process. * @param string $destination * The process destination. + * + * @deprecated in paragraphs:8.x-1.13 and is removed from paragraphs:8.x-2.0. + * Use \Drupal\paragraphs\MigrationPluginsAlterer::paragraphsMigrationEntityTypeAdjust(). + * @see https://www.drupal.org/project/paragraphs/issues/2911244 */ function _paragraphs_migration_entity_type_adjust(array &$migration, $destination = 'entity_type') { - $entity_type_process = $migration['process'][$destination]; - - // Try to play with other modules altering this, and don't replace it - // outright unless it's unchanged. - if (!is_array($entity_type_process)) { - $entity_type_process = [ - [ - 'plugin' => 'get', - 'source' => 'entity_type', - ], - ]; - } - $entity_type_process['paragraphs'] = [ - 'plugin' => 'static_map', - 'map' => [ - 'field_collection_item' => 'paragraph', - 'paragraphs_item' => 'paragraph', - ], - 'bypass' => TRUE, - ]; - $migration['process'][$destination] = $entity_type_process; + $migration_plugins_alterer = \Drupal::service('paragraphs.migration_plugins_alterer'); + assert($migration_plugins_alterer instanceof MigrationPluginsAlterer); + $migration_plugins_alterer->paragraphsMigrationEntityTypeAdjust($migration, $destination); } /** diff --git a/web/modules/paragraphs/paragraphs.post_update.php b/web/modules/paragraphs/paragraphs.post_update.php index d76c3d2e8dd4c9247860b6f840f4ac0a895b65b8..e0ce29a102aa061c71a49ba401217840e515abe8 100644 --- a/web/modules/paragraphs/paragraphs.post_update.php +++ b/web/modules/paragraphs/paragraphs.post_update.php @@ -22,7 +22,7 @@ function paragraphs_post_update_set_paragraphs_parent_fields(&$sandbox) { // Don't execute the function if paragraphs_update_8003() was already executed // which used to do the same. - $module_schema = drupal_get_installed_schema_version('paragraphs'); + $module_schema = \Drupal::service('update.update_hook_registry')->getInstalledVersion('paragraphs'); // The state entry 'paragraphs_update_8003_placeholder' is used in order to // indicate that the placeholder paragraphs_update_8003() function has been diff --git a/web/modules/paragraphs/paragraphs.services.yml b/web/modules/paragraphs/paragraphs.services.yml index b8c96660c12d6edcde2efebe2a9720cc6cd71920..4410694c27f8ba9c80b8ffa9dcbce4c8fb2c399b 100644 --- a/web/modules/paragraphs/paragraphs.services.yml +++ b/web/modules/paragraphs/paragraphs.services.yml @@ -8,3 +8,4 @@ services: arguments: ['@cache.bootstrap', '@lock', '@entity_type.manager'] tags: - { name: needs_destruction } + diff --git a/web/modules/paragraphs/src/Entity/Paragraph.php b/web/modules/paragraphs/src/Entity/Paragraph.php index 07e86ab1398d5fa15620773b709ce779acc68be9..702b78d8e1f4e3863ce93fe1efe56136277fbb3c 100644 --- a/web/modules/paragraphs/src/Entity/Paragraph.php +++ b/web/modules/paragraphs/src/Entity/Paragraph.php @@ -14,6 +14,7 @@ use Drupal\Core\Field\EntityReferenceFieldItemListInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Render\Markup; +use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\TypedData\TranslatableInterface; use Drupal\field\Entity\FieldStorageConfig; use Drupal\entity_reference_revisions\EntityNeedsSaveTrait; @@ -83,7 +84,7 @@ * } * }, * "entity_form_display" = { - * "type" = "entity_reference_paragraphs" + * "type" = "paragraphs" * }, * "entity_view_display" = { * "type" = "entity_reference_revisions_entity_view" @@ -100,6 +101,7 @@ class Paragraph extends ContentEntityBase implements ParagraphInterface { use EntityNeedsSaveTrait; use EntityPublishedTrait; + use StringTranslationTrait; /** * The behavior plugin data for the paragraph entity. @@ -164,7 +166,7 @@ public function label() { } } else { - $label = t('Orphaned @type: @summary', ['@summary' => Unicode::truncate(strip_tags($this->getSummary()), 50, FALSE, TRUE), '@type' => $this->get('type')->entity->label()]); + $label = $this->t('Orphaned @type: @summary', ['@summary' => Unicode::truncate(strip_tags($this->getSummary()), 50, FALSE, TRUE), '@type' => $this->get('type')->entity->label()]); } return $label; } @@ -219,6 +221,8 @@ public function setAllBehaviorSettings(array $settings) { * {@inheritdoc} */ public function setBehaviorSettings($plugin_id, array $settings) { + // Get existing behaviors first. + $this->getAllBehaviorSettings(); // Set behavior settings fields. $this->unserializedBehaviorSettings[$plugin_id] = $settings; } @@ -736,7 +740,7 @@ public function getTextSummary($field_name, FieldDefinitionInterface $field_defi return ''; } - $text = $this->get($field_name)->value; + $text = $this->get($field_name)->value ?? ''; $summary = Unicode::truncate(trim(strip_tags($text)), 150); if (empty($summary)) { // Autoescape is applied to the summary when it is rendered with twig, diff --git a/web/modules/paragraphs/src/Entity/ParagraphsType.php b/web/modules/paragraphs/src/Entity/ParagraphsType.php index 9b815c09884fa1e570a3c34c8bb15eba41325c80..51ac1998ee79ad849c2352361c6306882d6a9d12 100644 --- a/web/modules/paragraphs/src/Entity/ParagraphsType.php +++ b/web/modules/paragraphs/src/Entity/ParagraphsType.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityWithPluginCollectionInterface; use Drupal\file\Entity\File; +use Drupal\file\FileInterface; use Drupal\paragraphs\ParagraphsBehaviorCollection; use Drupal\paragraphs\ParagraphsTypeInterface; use Drupal\Core\File\FileSystemInterface; @@ -118,7 +119,7 @@ protected function restoreDefaultIcon() { // Compose the default icon file destination. $icon_meta = stream_get_meta_data($icon_data); // File extension from MIME, only JPG/JPEG, PNG and SVG expected. - list(, $icon_file_ext) = explode('image/', $icon_meta['mediatype']); + [, $icon_file_ext] = explode('image/', $icon_meta['mediatype']); // SVG special case. if ($icon_file_ext == 'svg+xml') { $icon_file_ext = 'svg'; @@ -137,7 +138,7 @@ protected function restoreDefaultIcon() { 'uri' => $icon_file_uri, 'uid' => \Drupal::currentUser()->id(), 'uuid' => $this->icon_uuid, - 'status' => FILE_STATUS_PERMANENT, + 'status' => FileInterface::STATUS_PERMANENT, ]; // Delete existent icon file if it exists. @@ -159,9 +160,11 @@ protected function restoreDefaultIcon() { * {@inheritdoc} */ public function getIconFile() { - $icon = $this->getFileByUuid($this->icon_uuid) ?: $this->restoreDefaultIcon(); - if ($this->icon_uuid && $icon) { - return $icon; + if ($this->icon_uuid !== NULL) { + $icon = $this->getFileByUuid($this->icon_uuid) ?: $this->restoreDefaultIcon(); + if ($icon) { + return $icon; + } } return FALSE; @@ -182,7 +185,7 @@ public function getBehaviorPlugins() { */ public function getIconUrl() { if ($image = $this->getIconFile()) { - return file_create_url($image->getFileUri()); + return \Drupal::service('file_url_generator')->generateString($image->getFileUri()); } return FALSE; diff --git a/web/modules/paragraphs/src/Form/ParagraphsTypeDeleteConfirm.php b/web/modules/paragraphs/src/Form/ParagraphsTypeDeleteConfirm.php index ac6bb77c35ece0256caf9304cb7808c2078c7a9f..dc57041c28c1f6d964fd1c7da89baf633930de49 100644 --- a/web/modules/paragraphs/src/Form/ParagraphsTypeDeleteConfirm.php +++ b/web/modules/paragraphs/src/Form/ParagraphsTypeDeleteConfirm.php @@ -17,6 +17,7 @@ class ParagraphsTypeDeleteConfirm extends EntityDeleteForm { public function buildForm(array $form, FormStateInterface $form_state) { $num_paragraphs = $this->entityTypeManager->getStorage('paragraph')->getQuery() ->condition('type', $this->entity->id()) + ->accessCheck(FALSE) ->count() ->execute(); if ($num_paragraphs) { @@ -49,6 +50,7 @@ public function deleteExistingEntities(array $form, FormStateInterface $form_sta $storage = $this->entityTypeManager->getStorage('paragraph'); $ids = $storage->getQuery() ->condition('type', $this->entity->id()) + ->accessCheck(FALSE) ->execute(); if (!empty($ids)) { diff --git a/web/modules/paragraphs/src/Form/ParagraphsTypeForm.php b/web/modules/paragraphs/src/Form/ParagraphsTypeForm.php index 986533e5c0d44ef22b412835e09fe210424b26af..dee8c7a691d6cf19c7ff10180e0cb4b11267d2aa 100644 --- a/web/modules/paragraphs/src/Form/ParagraphsTypeForm.php +++ b/web/modules/paragraphs/src/Form/ParagraphsTypeForm.php @@ -69,7 +69,7 @@ public function form(array $form, FormStateInterface $form_state) { $paragraphs_type = $this->entity; if (!$paragraphs_type->isNew()) { - $form['#title'] = (t('Edit %title paragraph type', [ + $form['#title'] = ($this->t('Edit %title paragraph type', [ '%title' => $paragraphs_type->label(), ])); } @@ -107,17 +107,18 @@ public function form(array $form, FormStateInterface $form_state) { } $form['description'] = [ - '#title' => t('Description'), + '#title' => $this->t('Description'), '#type' => 'textarea', '#default_value' => $paragraphs_type->getDescription(), - '#description' => t('This text will be displayed on the <em>Add new paragraph</em> page.'), + '#description' => $this->t('This text will be displayed on the <em>Add new paragraph</em> page.'), ]; // Loop over the plugins that can be applied to this paragraph type. if ($behavior_plugin_definitions = $this->paragraphsBehaviorManager->getApplicableDefinitions($paragraphs_type)) { $form['message'] = [ '#type' => 'container', - '#markup' => $this->t('Behavior plugins are only supported by the EXPERIMENTAL paragraphs widget.', [], ['context' => 'paragraphs']), + '#markup' => $this->t('Behavior plugins are only supported by the stable paragraphs widget.', [], ['context' => + 'paragraphs']), '#attributes' => ['class' => ['messages', 'messages--warning']] ]; $form['behavior_plugins'] = [ diff --git a/web/modules/paragraphs/src/MigrationPluginsAlterer.php b/web/modules/paragraphs/src/MigrationPluginsAlterer.php new file mode 100644 index 0000000000000000000000000000000000000000..f749dde99d6ee1cfe815aa97466c69ec9041407c --- /dev/null +++ b/web/modules/paragraphs/src/MigrationPluginsAlterer.php @@ -0,0 +1,150 @@ +<?php + +namespace Drupal\paragraphs; + +use Drupal\Core\Logger\LoggerChannelFactoryInterface; +use Drupal\migrate\Plugin\MigrationDeriverTrait; +use Drupal\paragraphs\Plugin\migrate\field\FieldCollection; + +/** + * Class MigrationPluginsAlterer. + */ +final class MigrationPluginsAlterer { + + use MigrationDeriverTrait; + + /** + * Paragraphs' logger channel. + * + * @var \Drupal\Core\Logger\LoggerChannelInterface + */ + protected $loggerChannel; + + /** + * Constructs a MigratePluginAlterer object. + * + * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory + * The logger factory service. + */ + public function __construct(LoggerChannelFactoryInterface $logger_factory) { + $this->loggerChannel = $logger_factory->get('paragraphs'); + } + + /** + * Adds field collection and paragraph migration dependencies where needed. + * + * @param array[] $migrations + * An associative array of migrations keyed by migration ID, the same that + * is passed to hook_migration_plugins_alter() hooks. + */ + public function alterMigrationPlugins(array &$migrations) { + foreach ($migrations as &$migration) { + if (!isset($migration['process']) || !is_array($migration['process'])) { + continue; + } + + foreach (['entity_type', 'targetEntityType'] as $process_property) { + if (isset($migration['process'][$process_property])) { + $this->paragraphsMigrationEntityTypeAdjust($migration, $process_property); + $this->paragraphsMigrationBundleAdjust($migration); + $migration['migration_dependencies']['optional'][] = 'd7_field_collection_type'; + $migration['migration_dependencies']['optional'][] = 'd7_paragraphs_type'; + } + } + } + } + + /** + * Map field_collection_item and 'paragraphs_item' fields to 'paragraph'. + * + * @param array $migration + * Thei migration to process. + * @param string $process_property + * The process destination. + */ + public function paragraphsMigrationEntityTypeAdjust(array &$migration, $process_property) { + if (!$this->paragraphsMigrationPrepareProcess($migration['process'], $process_property)) { + return; + } + + $entity_type_process = &$migration['process'][$process_property]; + $entity_type_process[] = [ + 'plugin' => 'static_map', + 'map' => [ + 'field_collection_item' => 'paragraph', + 'paragraphs_item' => 'paragraph', + ], + 'bypass' => TRUE, + ]; + } + + /** + * Remove 'field_' prefix from field collection bundles. + * + * @param array $migration + * The migration configuration to process. + */ + public function paragraphsMigrationBundleAdjust(array &$migration) { + // @see https://www.drupal.org/project/drupal/releases/9.1.4 + // @see https://www.drupal.org/project/drupal/issues/2565931 + $key = version_compare(\Drupal::VERSION, '9.1.4', '<') + ? 'bundle' + : 'bundle_mapped'; + if (!$this->paragraphsMigrationPrepareProcess($migration['process'], $key)) { + return; + } + + $bundle_process = &$migration['process'][$key]; + $bundle_process[] = [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'entity_type', + 'expected_value' => 'field_collection_item', + 'process' => [ + 'plugin' => 'substr', + 'start' => FieldCollection::FIELD_COLLECTION_PREFIX_LENGTH, + ], + ]; + } + + /** + * Converts a migration process to array for adding another process elements. + * + * @param array $process + * The array of process definitions of a migration. + * @param string $property + * The property which process definition should me converted to an array of + * process definitions. + * + * @return bool + * TRUE when the action was successful, FALSE otherwise. + */ + public function paragraphsMigrationPrepareProcess(array &$process, $property): bool { + if (!isset($process[$property])) { + return FALSE; + } + + $process_element = &$process[$property]; + + // Try to play with other modules altering this, and don't replace it + // outright unless it's unchanged. + if (is_string($process_element)) { + $process_element = [ + [ + 'plugin' => 'get', + 'source' => $process_element, + ], + ]; + } + elseif (is_array($process_element) && array_key_exists('plugin', $process_element)) { + $process_element = [$process_element]; + } + + if (!is_array($process_element)) { + $this->loggerChannel->error('Unknown migration process element type: @type.', ['@type' => gettype($process_element)]); + return FALSE; + } + + return TRUE; + } + +} diff --git a/web/modules/paragraphs/src/ParagraphInterface.php b/web/modules/paragraphs/src/ParagraphInterface.php index 6d7969b34529c424031afe625d2143caa76eb4d0..4cd6f10e36f254627467717d81a16bef9d21ba0a 100644 --- a/web/modules/paragraphs/src/ParagraphInterface.php +++ b/web/modules/paragraphs/src/ParagraphInterface.php @@ -18,7 +18,7 @@ interface ParagraphInterface extends ContentEntityInterface, EntityOwnerInterfac * * Preserves language context with translated entities. * - * @return ContentEntityInterface + * @return \Drupal\Core\Entity\ContentEntityInterface|null * The parent entity. */ public function getParentEntity(); diff --git a/web/modules/paragraphs/src/ParagraphsBehaviorInterface.php b/web/modules/paragraphs/src/ParagraphsBehaviorInterface.php index e3ecb3b87aa5357e27c829e23db764e6360b6ef8..bf64a016f04ead0616b1654136bc21bd987689f2 100644 --- a/web/modules/paragraphs/src/ParagraphsBehaviorInterface.php +++ b/web/modules/paragraphs/src/ParagraphsBehaviorInterface.php @@ -95,9 +95,6 @@ public function preprocess(&$variables); * entity components. * @param string $view_mode * The view mode the entity is rendered in. - * - * @return array - * A render array provided by the plugin. */ public function view(array &$build, Paragraph $paragraph, EntityViewDisplayInterface $display, $view_mode); diff --git a/web/modules/paragraphs/src/ParagraphsServiceProvider.php b/web/modules/paragraphs/src/ParagraphsServiceProvider.php index db38ed640e2a00b759083894e22af9c9b6c74f6e..a0a78e0301959216151f6e49c68ca6d2f460b8a1 100644 --- a/web/modules/paragraphs/src/ParagraphsServiceProvider.php +++ b/web/modules/paragraphs/src/ParagraphsServiceProvider.php @@ -28,5 +28,13 @@ public function register(ContainerBuilder $container) { $service_definition->setPublic(TRUE); $container->setDefinition('replicate.event_subscriber.paragraphs', $service_definition); } + // Check for installed Migrate module. + if (isset($modules['migrate']) ) { + // Add a Migration plugins alterer service. + $service_definition = new Definition('Drupal\paragraphs\MigrationPluginsAlterer'); + $service_definition->addArgument(new Reference('logger.factory')); + $service_definition->setPublic(TRUE); + $container->setDefinition('paragraphs.migration_plugins_alterer', $service_definition); + } } } diff --git a/web/modules/paragraphs/src/ParagraphsTypeIconUuidLookup.php b/web/modules/paragraphs/src/ParagraphsTypeIconUuidLookup.php index 9786eb1023fa5a233b0b4b9ebcf9b49786e1480d..af3fde082fe18f1d14a38bd9812591e2f6428b4b 100644 --- a/web/modules/paragraphs/src/ParagraphsTypeIconUuidLookup.php +++ b/web/modules/paragraphs/src/ParagraphsTypeIconUuidLookup.php @@ -40,6 +40,7 @@ public function __construct(CacheBackendInterface $cache, LockBackendInterface $ protected function resolveCacheMiss($key) { $ids = $this->entityTypeManager->getStorage('file')->getQuery() ->condition('uuid', $key) + ->accessCheck(TRUE) ->execute(); // Only cache if there is a match, otherwise creating new entities would diff --git a/web/modules/paragraphs/src/ParagraphsTypeInterface.php b/web/modules/paragraphs/src/ParagraphsTypeInterface.php index 9cee2ee49692d13f050d8ba23508ee7d4079a2b4..c08b263846fb4d9b79bb9a4d019a05835fa37571 100644 --- a/web/modules/paragraphs/src/ParagraphsTypeInterface.php +++ b/web/modules/paragraphs/src/ParagraphsTypeInterface.php @@ -46,7 +46,7 @@ public function getEnabledBehaviorPlugins(); /** * Returns the icon file entity. * - * @return \Drupal\file\FileInterface|bool + * @return \Drupal\file\FileInterface|false * The icon's file entity or FALSE if icon does not exist. */ public function getIconFile(); @@ -54,7 +54,7 @@ public function getIconFile(); /** * Returns the icon's URL. * - * @return string|bool + * @return string|false * The icon's URL or FALSE if icon does not exits. */ public function getIconUrl(); diff --git a/web/modules/paragraphs/src/Plugin/EntityReferenceSelection/ParagraphSelection.php b/web/modules/paragraphs/src/Plugin/EntityReferenceSelection/ParagraphSelection.php index 1545d85cc54bbaffbda068961b42d8bbd3e5e913..5564a48803a97db0ccec169ac53cee6cdba9b4b1 100644 --- a/web/modules/paragraphs/src/Plugin/EntityReferenceSelection/ParagraphSelection.php +++ b/web/modules/paragraphs/src/Plugin/EntityReferenceSelection/ParagraphSelection.php @@ -250,7 +250,7 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') $entity_type = $this->entityTypeManager->getDefinition($target_type); $query = $this->entityTypeManager->getStorage($target_type)->getQuery(); - + $query->accessCheck(TRUE); // If 'target_bundles' is NULL, all bundles are referenceable, no further // conditions are needed. if (is_array($this->configuration['target_bundles'])) { diff --git a/web/modules/paragraphs/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php b/web/modules/paragraphs/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php index d90cb147c6cff9eee41227f56f57b33171ab2b25..aa2b7070c2c215733c5e465463d35af0b1fb2ba2 100644 --- a/web/modules/paragraphs/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php +++ b/web/modules/paragraphs/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php @@ -26,8 +26,8 @@ * * @FieldWidget( * id = "entity_reference_paragraphs", - * label = @Translation("Paragraphs Classic"), - * description = @Translation("A paragraphs inline form widget."), + * label = @Translation("Paragraphs Legacy"), + * description = @Translation("The legacy paragraphs inline form widget."), * field_types = { * "entity_reference_revisions" * } @@ -298,8 +298,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen if ($paragraphs_entity) { // Detect if we are translating. $this->initIsTranslating($form_state, $host); - $langcode = $form_state->get('langcode'); - + $langcode = $this->getCurrentLangcode($form_state, $items); if (!$this->isTranslating) { // Set the langcode if we are not translating. $langcode_key = $paragraphs_entity->getEntityType()->getKey('langcode'); @@ -929,6 +928,14 @@ public function formMultipleElements(FieldItemListInterface $items, array &$form $host = $items->getEntity(); $this->initIsTranslating($form_state, $host); + if (!$form_state->has('langcode')) { + // Entity forms usually have the langcode set, but it's not guaranteed. + // Any form object can embed entities with their field widgets. + // At this point, without knowing the langcode from the form state, + // it's not certain which language is chosen. Remember the host entity, + // to get the langcode at a stage when the chosen value is more certain. + $elements['#host'] = $host; + } if (($this->realItemCount < $cardinality || $cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) && !$form_state->isProgrammed() && !$this->isTranslating) { $elements['add_more'] = $this->buildAddActions(); @@ -1127,11 +1134,15 @@ protected function buildSelectAddMode() { * is only accessibly through the form state. * * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. * @param \Drupal\Core\Field\FieldItemListInterface $items + * The field item list. + * * @return string + * The language code. */ protected function getCurrentLangcode(FormStateInterface $form_state, FieldItemListInterface $items) { - return $form_state->get('langcode') ?: $items->getEntity()->language()->getId(); + return $form_state->has('langcode') ? $form_state->get('langcode') : $items->getEntity()->language()->getId(); } /** @@ -1291,7 +1302,7 @@ public function multipleElementValidate(array $elements, FormStateInterface $for $non_remove_mode_item_count = $widget_state['real_item_count'] - $remove_mode_item_count; if ($elements['#required'] && $non_remove_mode_item_count < 1) { - $form_state->setError($elements, t('@name field is required.', ['@name' => $this->fieldDefinition->getLabel()])); + $form_state->setError($elements, $this->t('@name field is required.', ['@name' => $this->fieldDefinition->getLabel()])); } static::setWidgetState($elements['#field_parents'], $field_name, $form_state, $widget_state); @@ -1318,14 +1329,20 @@ public function massageFormValues(array $values, array $form, FormStateInterface // A content entity form saves without any rebuild. It needs to set the // language to update it in case of language change. $langcode_key = $paragraphs_entity->getEntityType()->getKey('langcode'); - if ($paragraphs_entity->get($langcode_key)->value != $form_state->get('langcode')) { + $langcode = $form_state->get('langcode'); + if (!isset($langcode) && isset($element['#host'])) { + // Use the host entity as a last resort to determine the langcode. + // @see self::formMultipleElements + $langcode = $element['#host']->language()->getId(); + } + if ($paragraphs_entity->get($langcode_key)->value != $langcode) { // If a translation in the given language already exists, switch to // that. If there is none yet, update the language. - if ($paragraphs_entity->hasTranslation($form_state->get('langcode'))) { - $paragraphs_entity = $paragraphs_entity->getTranslation($form_state->get('langcode')); + if ($paragraphs_entity->hasTranslation($langcode)) { + $paragraphs_entity = $paragraphs_entity->getTranslation($langcode); } else { - $paragraphs_entity->set($langcode_key, $form_state->get('langcode')); + $paragraphs_entity->set($langcode_key, $langcode); } } @@ -1380,7 +1397,8 @@ protected function initIsTranslating(FormStateInterface $form_state, EntityInter // Adding a language through the ContentTranslationController. $this->isTranslating = TRUE; } - if ($host->hasTranslation($form_state->get('langcode')) && $host->getTranslation($form_state->get('langcode'))->get($default_langcode_key)->value == 0) { + $langcode = $form_state->get('langcode'); + if (isset($langcode) && $host->hasTranslation($langcode) && $host->getTranslation($langcode)->get($default_langcode_key)->value == 0) { // Editing a translation. $this->isTranslating = TRUE; } diff --git a/web/modules/paragraphs/src/Plugin/Field/FieldWidget/ParagraphsWidget.php b/web/modules/paragraphs/src/Plugin/Field/FieldWidget/ParagraphsWidget.php index 6625db3a0d47d3aae1f9c60d5d7ca5fd9d8cfe01..5e31eedd84a3fd93fee36b9be4af1fb4d9c35b86 100644 --- a/web/modules/paragraphs/src/Plugin/Field/FieldWidget/ParagraphsWidget.php +++ b/web/modules/paragraphs/src/Plugin/Field/FieldWidget/ParagraphsWidget.php @@ -27,8 +27,8 @@ * * @FieldWidget( * id = "paragraphs", - * label = @Translation("Paragraphs EXPERIMENTAL"), - * description = @Translation("An experimental paragraphs inline form widget."), + * label = @Translation("Paragraphs (stable)"), + * description = @Translation("The stable paragraphs inline form widget."), * field_types = { * "entity_reference_revisions" * } @@ -419,8 +419,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen if ($paragraphs_entity) { // Detect if we are translating. $this->initIsTranslating($form_state, $host); - $langcode = $form_state->get('langcode'); - + $langcode = $this->getCurrentLangcode($form_state, $items); if (!$this->isTranslating) { // Set the langcode if we are not translating. $langcode_key = $paragraphs_entity->getEntityType()->getKey('langcode'); @@ -950,6 +949,7 @@ protected function buildModalAddForm(array &$element) { '#name' => 'button_add_modal', '#attributes' => [ 'class' => [ + 'field-add-more-submit', 'paragraph-type-add-modal-button', 'js-show', 'button--small', @@ -957,19 +957,6 @@ protected function buildModalAddForm(array &$element) { ], ]; - // Hidden field provided by "Modal" mode. Field is provided for additional - // integrations, where also position of addition can be specified. It should - // be used by sub-modules or other paragraphs integration. CSS class is used - // to support easier element selecting in JavaScript. - $element['add_modal_form_area']['add_more_delta'] = [ - '#type' => 'hidden', - '#attributes' => [ - 'class' => [ - 'paragraph-type-add-modal-delta', - ], - ], - ]; - $element['#attached']['library'][] = 'paragraphs/drupal.paragraphs.modal'; if ($this->isFeatureEnabled('add_above')) { $element['#attached']['library'][] = 'paragraphs/drupal.paragraphs.add_above_button'; @@ -1062,7 +1049,7 @@ public function formMultipleElements(FieldItemListInterface $items, array &$form $is_multiple = $this->fieldDefinition->getFieldStorageDefinition()->isMultiple(); $field_title = $this->fieldDefinition->getLabel(); - $description = FieldFilteredMarkup::create(\Drupal::token()->replace($this->fieldDefinition->getDescription())); + $description = FieldFilteredMarkup::create(\Drupal::token()->replace($this->fieldDefinition->getDescription() ?? '')); $elements = array(); $tabs = ''; @@ -1074,7 +1061,7 @@ public function formMultipleElements(FieldItemListInterface $items, array &$form $field_prefix = strtr($this->fieldIdPrefix, '_', '-'); if (count($this->fieldParents) == 0) { if ($items->getEntity()->getEntityTypeId() != 'paragraph') { - $tabs = '<ul class="paragraphs-tabs tabs primary clearfix"><li id="content" class="tabs__tab"><a href="#' . $field_prefix . '-values">' . $this->t('Content', [], ['context' => 'paragraphs']) . '</a></li><li id="behavior" class="tabs__tab"><a href="#' . $field_prefix . '-values">' . $this->t('Behavior', [], ['context' => 'paragraphs']) . '</a></li></ul>'; + $tabs = '<ul class="paragraphs-tabs tabs primary tabs--secondary paragraphs-tabs-hide clearfix"><li class="tabs__tab paragraphs_content_tab"><a href="#' . $field_prefix . '-values" class="tabs__link">' . $this->t('Content', [], ['context' => 'paragraphs']) . '</a></li><li class="tabs__tab paragraphs_behavior_tab"><a href="#' . $field_prefix . '-values" class="tabs__link">' . $this->t('Behavior', [], ['context' => 'paragraphs']) . '</a></li></ul>'; } } if (count($this->fieldParents) > 0) { @@ -1183,6 +1170,14 @@ public function formMultipleElements(FieldItemListInterface $items, array &$form $host = $items->getEntity(); $this->initIsTranslating($form_state, $host); + if (!$form_state->has('langcode')) { + // Entity forms usually have the langcode set, but it's not guaranteed. + // Any form object can embed entities with their field widgets. + // At this point, without knowing the langcode from the form state, + // it's not certain which language is chosen. Remember the host entity, + // to get the langcode at a stage when the chosen value is more certain. + $elements['#host'] = $host; + } $header_actions = $this->buildHeaderActions($field_state, $form_state); if ($header_actions) { @@ -1200,12 +1195,30 @@ public function formMultipleElements(FieldItemListInterface $items, array &$form $elements['add_more'] = $this->buildAddActions(); // Add the class to hide the add actions in the Behavior perspective. $elements['add_more']['#attributes']['class'][] = 'paragraphs-add-wrapper'; + + // Hidden field is provided for additional integrations, where also + // position of addition can be specified. It should be used by sub-modules + // or other paragraphs integration. CSS class is used to support easier + // element selecting in JavaScript. + $elements['add_more']['add_more_delta'] = [ + '#type' => 'hidden', + '#attributes' => [ + 'class' => [ + 'paragraph-type-add-delta', + $this->getSetting('add_mode') + ], + ], + ]; } $elements['#allow_reference_changes'] = $this->allowReferenceChanges(); $elements['#paragraphs_widget'] = TRUE; $elements['#attached']['library'][] = 'paragraphs/drupal.paragraphs.widget'; + if (\Drupal::theme()->getActiveTheme()->getName() == 'seven') { + $elements['#attached']['library'][] = 'paragraphs/paragraphs.seven'; + } + return $elements; } @@ -1585,6 +1598,7 @@ protected function buildDropbutton(array $elements = []) { // Even though operations are run through the "links" element type, the // theme system will render any render array passed as a link "title". '#links' => $operations, + '#dropbutton_type' => 'small', ]; return $build + $elements; @@ -1607,7 +1621,7 @@ protected function buildButtonsAddMode() { '#type' => 'submit', '#name' => $this->fieldIdPrefix . '_' . $machine_name . '_add_more', '#value' => $add_mode == 'modal' ? $label : $this->t('Add @type', ['@type' => $label]), - '#attributes' => ['class' => ['field-add-more-submit']], + '#attributes' => ['class' => ['field-add-more-submit', 'button--small']], '#limit_validation_errors' => [array_merge($this->fieldParents, [$this->fieldDefinition->getName(), 'add_more'])], '#submit' => [[get_class($this), 'addMoreSubmit']], '#ajax' => [ @@ -1695,6 +1709,25 @@ protected function buildSelectAddMode() { return $add_more_elements; } + /** + * Gets current language code from the form state or item. + * + * Since the paragraph field is not set as translatable, the item language + * code is set to the source language. The intended translation language + * is only accessibly through the form state. + * + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. + * @param \Drupal\Core\Field\FieldItemListInterface $items + * The field item list. + * + * @return string + * The language code. + */ + protected function getCurrentLangcode(FormStateInterface $form_state, FieldItemListInterface $items) { + return $form_state->has('langcode') ? $form_state->get('langcode') : $items->getEntity()->language()->getId(); + } + /** * {@inheritdoc} */ @@ -1710,7 +1743,7 @@ public static function addMoreAjax(array $form, FormStateInterface $form_state) // Clear the Add more delta. NestedArray::setValue( $element, - ['add_more', 'add_modal_form_area', 'add_more_delta', '#value'], + ['add_more', 'add_more_delta', '#value'], '' ); @@ -1776,7 +1809,7 @@ protected static function prepareDeltaPosition(array &$widget_state, FormStateIn } // Add information into delta mapping for the new element. - $original_deltas_size = count($widget_state['original_deltas']); + $original_deltas_size = count($widget_state['original_deltas'] ?? []); $new_original_deltas[$new_delta] = $original_deltas_size; $user_input[$original_deltas_size]['_weight'] = $new_delta; @@ -1794,7 +1827,7 @@ public static function addMoreSubmit(array $form, FormStateInterface $form_state $field_path = array_merge($submit['element']['#field_parents'], [$submit['element']['#field_name']]); $add_more_delta = NestedArray::getValue( $submit['element'], - ['add_more', 'add_modal_form_area', 'add_more_delta', '#value'] + ['add_more', 'add_more_delta', '#value'] ); static::prepareDeltaPosition($submit['widget_state'], $form_state, $field_path, $add_more_delta); @@ -2207,7 +2240,7 @@ public function multipleElementValidate(array $elements, FormStateInterface $for $widget_state = static::getWidgetState($elements['#field_parents'], $field_name, $form_state); if ($elements['#required'] && $widget_state['real_item_count'] < 1) { - $form_state->setError($elements, t('@name field is required.', ['@name' => $this->fieldDefinition->getLabel()])); + $form_state->setError($elements, $this->t('@name field is required.', ['@name' => $this->fieldDefinition->getLabel()])); } static::setWidgetState($elements['#field_parents'], $field_name, $form_state, $widget_state); @@ -2236,7 +2269,7 @@ public function massageFormValues(array $values, array $form, FormStateInterface return $values; } - foreach ($values as $delta => &$item) { + foreach ($values as &$item) { if (isset($widget_state['paragraphs'][$item['_original_delta']]['entity']) && $widget_state['paragraphs'][$item['_original_delta']]['mode'] != 'remove') { /** @var \Drupal\paragraphs\ParagraphInterface $paragraphs_entity */ @@ -2250,14 +2283,20 @@ public function massageFormValues(array $values, array $form, FormStateInterface // A content entity form saves without any rebuild. It needs to set the // language to update it in case of language change. $langcode_key = $paragraphs_entity->getEntityType()->getKey('langcode'); - if ($paragraphs_entity->get($langcode_key)->value != $form_state->get('langcode')) { + $langcode = $form_state->get('langcode'); + if (!isset($langcode) && isset($element['#host'])) { + // Use the host entity as a last resort to determine the langcode. + // @see self::formMultipleElements + $langcode = $element['#host']->language()->getId(); + } + if ($paragraphs_entity->get($langcode_key)->value != $langcode) { // If a translation in the given language already exists, switch to // that. If there is none yet, update the language. - if ($paragraphs_entity->hasTranslation($form_state->get('langcode'))) { - $paragraphs_entity = $paragraphs_entity->getTranslation($form_state->get('langcode')); + if ($paragraphs_entity->hasTranslation($langcode)) { + $paragraphs_entity = $paragraphs_entity->getTranslation($langcode); } else { - $paragraphs_entity->set($langcode_key, $form_state->get('langcode')); + $paragraphs_entity->set($langcode_key, $langcode); } } if (isset($item['behavior_plugins'])) { @@ -2373,7 +2412,7 @@ protected function initIsTranslating(FormStateInterface $form_state, ContentEnti $this->isTranslating = TRUE; } $langcode = $form_state->get('langcode'); - if ($host->hasTranslation($langcode) && $host->getTranslation($langcode)->get($default_langcode_key)->value == 0) { + if (isset($langcode) && $host->hasTranslation($langcode) && $host->getTranslation($langcode)->get($default_langcode_key)->value == 0) { // Editing a translation. $this->isTranslating = TRUE; } diff --git a/web/modules/paragraphs/src/Plugin/migrate/D7FieldCollectionItemDeriver.php b/web/modules/paragraphs/src/Plugin/migrate/D7FieldCollectionItemDeriver.php new file mode 100644 index 0000000000000000000000000000000000000000..6ee8bc916a252f81d6514d6655d5ec5f69a46b67 --- /dev/null +++ b/web/modules/paragraphs/src/Plugin/migrate/D7FieldCollectionItemDeriver.php @@ -0,0 +1,105 @@ +<?php + +namespace Drupal\paragraphs\Plugin\migrate; + +use Drupal\Component\Plugin\Derivative\DeriverBase; +use Drupal\Core\Database\DatabaseExceptionWrapper; +use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\migrate\Exception\RequirementsException; +use Drupal\migrate\Plugin\MigrationDeriverTrait; +use Drupal\migrate_drupal\FieldDiscoveryInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Deriver for field collections. + */ +class D7FieldCollectionItemDeriver extends DeriverBase implements ContainerDeriverInterface { + + use MigrationDeriverTrait; + use StringTranslationTrait; + + /** + * The base plugin ID this derivative is for. + * + * @var string + */ + protected $basePluginId; + + /** + * The migration field discovery service. + * + * @var \Drupal\migrate_drupal\FieldDiscoveryInterface + */ + protected $fieldDiscovery; + + /** + * D7FieldCollectionItemDeriver constructor. + * + * @param string $base_plugin_id + * The base plugin ID for the plugin ID. + * @param \Drupal\migrate_drupal\FieldDiscoveryInterface $field_discovery + * The migration field discovery service. + */ + public function __construct($base_plugin_id, FieldDiscoveryInterface $field_discovery) { + $this->basePluginId = $base_plugin_id; + $this->fieldDiscovery = $field_discovery; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $base_plugin_id, + $container->get('migrate_drupal.field_discovery') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + $types = static::getSourcePlugin('d7_field_collection_type'); + + try { + $types->checkRequirements(); + } + catch (RequirementsException $e) { + return $this->derivatives; + } + + try { + foreach ($types as $row) { + /** @var \Drupal\migrate\Row $row */ + $values = $base_plugin_definition; + $fc_bundle = $row->getSourceProperty('field_name'); + $p_bundle = $row->getSourceProperty('bundle'); + $values['label'] = $this->t('@label (@type)', [ + '@label' => $values['label'], + '@type' => $row->getSourceProperty('name'), + ]); + $values['source']['field_name'] = $fc_bundle; + $values['destination']['default_bundle'] = $p_bundle; + + /** @var \Drupal\migrate\Plugin\Migration $migration */ + $migration = \Drupal::service('plugin.manager.migration') + ->createStubMigration($values); + $migration->setProcessOfProperty('parent_id', 'parent_id'); + $migration->setProcessOfProperty('parent_type', 'parent_type'); + $migration->setProcessOfProperty('parent_field_name', 'field_name'); + + $this->fieldDiscovery->addBundleFieldProcesses($migration, 'field_collection_item', $fc_bundle); + $this->derivatives[$p_bundle] = $migration->getPluginDefinition(); + } + } + catch (DatabaseExceptionWrapper $e) { + // Once we begin iterating the source plugin it is possible that the + // source tables will not exist. This can happen when the + // MigrationPluginManager gathers up the migration definitions but we do + // not actually have a Drupal 7 source database. + } + return $this->derivatives; + } + +} diff --git a/web/modules/paragraphs/src/Plugin/migrate/D7ParagraphsItemDeriver.php b/web/modules/paragraphs/src/Plugin/migrate/D7ParagraphsItemDeriver.php new file mode 100644 index 0000000000000000000000000000000000000000..1e8e46da98357c318f0af4f3f7c6a98100d5c68a --- /dev/null +++ b/web/modules/paragraphs/src/Plugin/migrate/D7ParagraphsItemDeriver.php @@ -0,0 +1,98 @@ +<?php + +namespace Drupal\paragraphs\Plugin\migrate; + +use Drupal\Component\Plugin\Derivative\DeriverBase; +use Drupal\Core\Database\DatabaseExceptionWrapper; +use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\migrate\Exception\RequirementsException; +use Drupal\migrate\Plugin\MigrationDeriverTrait; +use Drupal\migrate_drupal\FieldDiscoveryInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Deriver for Paragraph Items. + */ +class D7ParagraphsItemDeriver extends DeriverBase implements ContainerDeriverInterface { + + use MigrationDeriverTrait; + use StringTranslationTrait; + + /** + * The base plugin ID this derivative is for. + * + * @var string + */ + protected $basePluginId; + + /** + * The migration field discovery service. + * + * @var \Drupal\migrate_drupal\FieldDiscoveryInterface + */ + protected $fieldDiscovery; + + /** + * D7ParagraphsItemDeriver constructor. + * + * @param string $base_plugin_id + * The base plugin ID for the plugin ID. + * @param \Drupal\migrate_drupal\FieldDiscoveryInterface $field_discovery + * The migration field discovery service. + */ + public function __construct($base_plugin_id, FieldDiscoveryInterface $field_discovery) { + $this->basePluginId = $base_plugin_id; + $this->fieldDiscovery = $field_discovery; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $base_plugin_id, + $container->get('migrate_drupal.field_discovery') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + $types = static::getSourcePlugin('d7_paragraphs_type'); + try { + $types->checkRequirements(); + } + catch (RequirementsException $e) { + return $this->derivatives; + } + + try { + foreach ($types as $row) { + $values = $base_plugin_definition; + $bundle = $row->getSourceProperty('bundle'); + $values['label'] = $this->t('@label (@type)', [ + '@label' => $values['label'], + '@type' => $row->getSourceProperty('name'), + ]); + $values['source']['bundle'] = $bundle; + $values['destination']['default_bundle'] = $bundle; + + /** @var \Drupal\migrate\Plugin\Migration $migration */ + $migration = \Drupal::service('plugin.manager.migration') + ->createStubMigration($values); + $this->fieldDiscovery->addBundleFieldProcesses($migration, 'paragraphs_item', $bundle); + $this->derivatives[$bundle] = $migration->getPluginDefinition(); + } + } + catch (DatabaseExceptionWrapper $e) { + // Once we begin iterating the source plugin it is possible that the + // source tables will not exist. This can happen when the + // MigrationPluginManager gathers up the migration definitions but we do + // not actually have a Drupal 7 source database. + } + return $this->derivatives; + } + +} diff --git a/web/modules/paragraphs/src/Plugin/migrate/field/FieldCollection.php b/web/modules/paragraphs/src/Plugin/migrate/field/FieldCollection.php index 19d9a21e4d5a48d0467ae70233dbbccd03aad066..73d8b00617e4afabe4c5713da1299b62deba47f1 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/field/FieldCollection.php +++ b/web/modules/paragraphs/src/Plugin/migrate/field/FieldCollection.php @@ -8,9 +8,6 @@ /** * Field Plugin for field collection migrations. * - * @todo Implement ::defineValueProcessPipeline() - * @see https://www.drupal.org/project/paragraphs/issues/2911244 - * * @MigrateField( * id = "field_collection", * core = {7}, @@ -23,11 +20,64 @@ */ class FieldCollection extends FieldPluginBase { - /** + /* * Length of the 'field_' prefix that field collection prepends to bundles. */ const FIELD_COLLECTION_PREFIX_LENGTH = 6; + /** + * {@inheritdoc} + */ + public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) { + $process = [ + 'plugin' => 'sub_process', + 'source' => $field_name, + 'process' => [ + 'target_id' => [ + [ + 'plugin' => 'paragraphs_lookup', + 'tags' => 'Field Collection Content', + 'source' => 'value', + ], + [ + 'plugin' => 'extract', + 'index' => ['id'], + ], + ], + 'target_revision_id' => [ + [ + 'plugin' => 'paragraphs_lookup', + 'tags' => [ + 'Field Collection Revisions Content', + 'Field Collection Content', + ], + 'tag_ids' => [ + 'Field Collection Revisions Content' => ['revision_id'], + 'Field Collection Content' => ['value'], + ], + ], + [ + 'plugin' => 'extract', + 'index' => ['revision_id'], + ], + ], + ], + ]; + $migration->setProcessOfProperty($field_name, $process); + + // Add the respective field collection migration as a dependency. + $migration_dependency = 'd7_field_collection:' . substr($field_name, static::FIELD_COLLECTION_PREFIX_LENGTH); + $migration_rev_dependency = 'd7_field_collection_revisions:' . substr($field_name, static::FIELD_COLLECTION_PREFIX_LENGTH); + $dependencies = $migration->getMigrationDependencies() + ['required' => []]; + $dependencies['required'] = array_unique(array_merge(array_values($dependencies['required']), [$migration_dependency])); + $migration->set('migration_dependencies', $dependencies); + + if (strpos($migration->getDestinationPlugin()->getPluginId(), 'entity_revision:') === 0 || strpos($migration->getDestinationPlugin()->getPluginId(), 'entity_complete:') === 0) { + $dependencies['required'] = array_unique(array_merge(array_values($dependencies['required']), [$migration_rev_dependency])); + $migration->set('migration_dependencies', $dependencies); + } + } + /** * {@inheritdoc} */ @@ -42,7 +92,6 @@ public function alterFieldFormatterMigration(MigrationInterface $migration) { public function getFieldFormatterMap() { return [ 'field_collection_view' => 'entity_reference_revisions_entity_view', - // TODO: Change the autogenerated stub. ] + parent::getFieldFormatterMap(); } diff --git a/web/modules/paragraphs/src/Plugin/migrate/field/Paragraphs.php b/web/modules/paragraphs/src/Plugin/migrate/field/Paragraphs.php index bb3d82121c3aa5997054f577a664ce99d3db3949..6c42aa497c8e89b173662ae95b5d52acababe379 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/field/Paragraphs.php +++ b/web/modules/paragraphs/src/Plugin/migrate/field/Paragraphs.php @@ -8,9 +8,6 @@ /** * Field Plugin for paragraphs migrations. * - * @todo Implement ::defineValueProcessPipeline() - * @see https://www.drupal.org/project/paragraphs/issues/2911244 - * * @MigrateField( * id = "paragraphs", * core = {7}, @@ -23,6 +20,68 @@ */ class Paragraphs extends FieldPluginBase { + /** + * {@inheritdoc} + */ + public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) { + $process = [ + 'plugin' => 'sub_process', + 'source' => $field_name, + 'process' => [ + 'target_id' => [ + [ + 'plugin' => 'paragraphs_lookup', + 'tags' => 'Paragraphs Content', + 'source' => 'value', + ], + [ + 'plugin' => 'extract', + 'index' => ['id'], + ], + ], + 'target_revision_id' => [ + [ + 'plugin' => 'paragraphs_lookup', + 'tags' => [ + 'Paragraphs Revisions Content', + 'Paragraphs Content', + ], + 'tag_ids' => [ + 'Paragraphs Revisions Content' => ['revision_id'], + 'Paragraphs Content' => ['value'], + ], + // D8.4 Does not like an empty source value, Even when using ids. + 'source' => 'value', + ], + [ + 'plugin' => 'extract', + 'index' => ['revision_id'], + ], + ], + ], + ]; + $migration->setProcessOfProperty($field_name, $process); + + // Add paragraphs migration as a dependency (if this is not a paragraph + // migration). + // @todo: This is a great example why we should consider derive paragraph + // migrations based on parent entity type (and bundle). + if (!in_array('Paragraphs Content', $migration->getMigrationTags(), TRUE)) { + $dependencies = $migration->getMigrationDependencies() + ['required' => []]; + $dependencies['required'] = array_unique(array_merge(array_values($dependencies['required']), [ + 'd7_paragraphs', + ])); + $migration->set('migration_dependencies', $dependencies); + + if (strpos($migration->getDestinationPlugin()->getPluginId(), 'entity_revision:') === 0 || strpos($migration->getDestinationPlugin()->getPluginId(), 'entity_complete:') === 0) { + $dependencies['required'] = array_unique(array_merge(array_values($dependencies['required']), [ + 'd7_paragraphs_revisions', + ])); + $migration->set('migration_dependencies', $dependencies); + } + } + } + /** * {@inheritdoc} */ @@ -45,7 +104,6 @@ public function alterFieldFormatterMigration(MigrationInterface $migration) { public function getFieldFormatterMap() { return [ 'paragraphs_view' => 'entity_reference_revisions_entity_view', - // TODO: Change the autogenerated stub. ] + parent::getFieldFormatterMap(); } @@ -53,15 +111,15 @@ public function getFieldFormatterMap() { * {@inheritdoc} */ public function getFieldWidgetMap() { - return ['paragraphs_embed' => 'entity_reference_paragraphs'] - + parent::getFieldWidgetMap(); + return [ + 'paragraphs_embed' => 'entity_reference_paragraphs', + ] + parent::getFieldWidgetMap(); } /** * {@inheritdoc} */ public function alterFieldMigration(MigrationInterface $migration) { - $settings = [ 'paragraphs' => [ 'plugin' => 'paragraphs_field_settings', @@ -74,7 +132,6 @@ public function alterFieldMigration(MigrationInterface $migration) { * {@inheritdoc} */ public function alterFieldInstanceMigration(MigrationInterface $migration) { - $settings = [ 'paragraphs' => [ 'plugin' => 'paragraphs_field_instance_settings', diff --git a/web/modules/paragraphs/src/Plugin/migrate/process/FieldCollectionFieldInstanceSettings.php b/web/modules/paragraphs/src/Plugin/migrate/process/FieldCollectionFieldInstanceSettings.php index e552a6716cff78d60cb7f8a74da33f13234c5cfc..baf76bbaa6e5362bbb1b406fc1f3e2ed925b1e05 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/process/FieldCollectionFieldInstanceSettings.php +++ b/web/modules/paragraphs/src/Plugin/migrate/process/FieldCollectionFieldInstanceSettings.php @@ -26,7 +26,7 @@ public function transform($value, MigrateExecutableInterface $migrate_executable if ($type == 'field_collection') { $bundles = $this->entityTypeBundleInfo->getBundleInfo('paragraph'); - $target_bundle = $row->getSourceProperty('field_name'); + $target_bundle = $row->getSourceProperty('field_name') ?? ''; // Remove field_ prefix for new bundle. $target_bundle = substr($target_bundle, FieldCollection::FIELD_COLLECTION_PREFIX_LENGTH); diff --git a/web/modules/paragraphs/src/Plugin/migrate/process/ParagraphsLookup.php b/web/modules/paragraphs/src/Plugin/migrate/process/ParagraphsLookup.php new file mode 100644 index 0000000000000000000000000000000000000000..f9474810d8b5498aeb81259eae913478d94d1c41 --- /dev/null +++ b/web/modules/paragraphs/src/Plugin/migrate/process/ParagraphsLookup.php @@ -0,0 +1,235 @@ +<?php + +namespace Drupal\paragraphs\Plugin\migrate\process; + +use Drupal\Component\Plugin\Exception\PluginException; +use Drupal\migrate\MigrateException; +use Drupal\migrate\MigrateExecutableInterface; +use Drupal\migrate\MigrateLookupInterface; +use Drupal\migrate\MigrateStubInterface; +use Drupal\migrate\Plugin\migrate\process\MigrationLookup; +use Drupal\migrate\Plugin\MigrateIdMapInterface; +use Drupal\migrate\Plugin\MigratePluginManagerInterface; +use Drupal\migrate\Plugin\MigrationInterface; +use Drupal\migrate\Plugin\MigrationPluginManagerInterface; +use Drupal\migrate\Row; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Looks up the value of a paragraph property based on previous migrations. + * + * Compared to the MigrationLookup, this process plugin can accept two new + * configuration option: these are 'tags' and 'tag_ids'. + * Every other configuration options are inherited from MigrationLookup. If + * 'tags' has value, then the migration tag based lookup takes precedence over + * the migration plugin ID based property lookup. + * + * @todo Clean up, add test coverage and document how the two extra config + * option works in https://drupal.org/i/3146646. + * + * @MigrateProcessPlugin( + * id = "paragraphs_lookup" + * ) + */ +class ParagraphsLookup extends MigrationLookup { + + /** + * The migration plugin manager. + * + * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface + */ + protected $migrationPluginManager; + + /** + * The process plugin manager. + * + * @var \Drupal\migrate\Plugin\MigratePluginManager + */ + protected $processPluginManager; + + /** + * Constructs a MigrationLookup object. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\migrate\Plugin\MigrationInterface $migration + * The Migration the plugin is being used in. + * @param \Drupal\migrate\MigrateLookupInterface $migrate_lookup + * The migrate lookup service. + * @param \Drupal\migrate\MigrateStubInterface $migrate_stub + * The migrate stub service. + * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager + * The Migration Plugin Manager Interface. + * @param \Drupal\migrate\Plugin\MigratePluginManagerInterface $process_plugin_manager + * The process migration plugin manager. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, MigrateLookupInterface $migrate_lookup, MigrateStubInterface $migrate_stub, MigrationPluginManagerInterface $migration_plugin_manager, MigratePluginManagerInterface $process_plugin_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $migrate_lookup, $migrate_stub); + + $this->migrationPluginManager = $migration_plugin_manager; + $this->processPluginManager = $process_plugin_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $migration, + $container->get('migrate.lookup'), + $container->get('migrate.stub'), + $container->get('plugin.manager.migration'), + $container->get('plugin.manager.migrate.process') + ); + } + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + $source_id_values = []; + $destination_ids = NULL; + $migrations = []; + if (isset($this->configuration['tags'])) { + $tags = (array) $this->configuration['tags']; + foreach ($tags as $tag) { + /** @var \Drupal\migrate\Plugin\MigrationInterface[] $tag_migrations */ + $tag_migrations = $this->migrationPluginManager->createInstancesByTag($tag); + $migrations += $tag_migrations; + if (isset($this->configuration['tag_ids'][$tag])) { + $configuration = ['source' => $this->configuration['tag_ids'][$tag]]; + try { + $get_process_plugin = $this->processPluginManager + ->createInstance('get', $configuration, $this->migration); + } + catch (PluginException $e) { + continue; + } + $value = $get_process_plugin->transform(NULL, $migrate_executable, $row, $destination_property); + } + foreach ($tag_migrations as $migration_id => $migration) { + $source_id_values[$migration_id] = (array) $value; + $destination_ids = $this->lookupDestination($migration, $value); + if ($destination_ids) { + break 2; + } + } + } + } + elseif (!empty($this->configuration['migration'])) { + $destination_ids = parent::transform($value, $migrate_executable, $row, $destination_property); + $migration_ids = $this->configuration['migration']; + if (!is_array($migration_ids)) { + $migration_ids = (array) $migration_ids; + } + /** @var \Drupal\migrate\Plugin\MigrationInterface[] $migrations */ + $migrations = $this->migrationPluginManager->createInstances($migration_ids); + foreach ($migrations as $migration_id => $migration) { + if (isset($this->configuration['source_ids'][$migration_id])) { + $configuration = ['source' => $this->configuration['source_ids'][$migration_id]]; + $value = $this->processPluginManager + ->createInstance('get', $configuration, $this->migration) + ->transform(NULL, $migrate_executable, $row, $destination_property); + } + $source_id_values[$migration_id] = (array) $value; + $destination_ids = $this->lookupDestination($migration, $value); + if ($destination_ids) { + break; + } + } + } + else { + throw new MigrateException("Either Migration or Tags must be defined."); + } + + if (!$destination_ids && !empty($this->configuration['no_stub'])) { + return NULL; + } + + if (!$destination_ids) { + // If the lookup didn't succeed, figure out which migration will do the + // stubbing. + if (isset($this->configuration['stub_id'])) { + $migration = $this->migrationPluginManager->createInstance($this->configuration['stub_id']); + assert($migration instanceof MigrationInterface); + } + else { + $migration = reset($migrations); + } + $destination_plugin = $migration->getDestinationPlugin(TRUE); + // Only keep the process necessary to produce the destination ID. + $process = $migration->getProcess(); + + // We already have the source ID values but need to key them for the Row + // constructor. + $source_ids = $migration->getSourcePlugin()->getIds(); + $values = []; + foreach (array_keys($source_ids) as $index => $source_id) { + $values[$source_id] = $source_id_values[$migration->getPluginId()][$index]; + } + + // @todo use the migration.stub service. + $stub_row = new Row($values + $migration->getSourceConfiguration(), $source_ids, TRUE); + + // Do a normal migration with the stub row. + $migrate_executable->processRow($stub_row, $process); + $destination_ids = []; + $id_map = $migration->getIdMap(); + try { + $destination_ids = $destination_plugin->import($stub_row); + } + catch (\Exception $e) { + $id_map->saveMessage($stub_row->getSourceIdValues(), $e->getMessage()); + } + + if ($destination_ids) { + $id_map->saveIdMapping($stub_row, $destination_ids, MigrateIdMapInterface::STATUS_NEEDS_UPDATE); + } + } + if ($destination_ids) { + if (count($destination_ids) == 1) { + return reset($destination_ids); + } + else { + return $destination_ids; + } + } + + throw new MigrateException("Paragraphs lookup wasn't able to find the corresponding property for paragraph with source ID $value for the destination property $destination_property."); + } + + /** + * Look for destination records. + * + * @param \Drupal\migrate\Plugin\MigrationInterface $migration + * The migration that should be checked. + * @param string|string[] $value + * The source ID. + * + * @return array|false + * The array of the destination identifiers, or FALSE if destination cannot + * be determined. + * + * @throws \Drupal\migrate\MigrateException + * @throws \Drupal\migrate\MigrateSkipProcessException + */ + protected function lookupDestination(MigrationInterface $migration, $value) { + $value = (array) $value; + $this->skipInvalid($value); + + // Break out of the loop as soon as a destination ID is found. + if ($destination_ids = $migration->getIdMap()->lookupDestinationIds($value)) { + $destination_ids = array_combine(array_keys($migration->getDestinationPlugin()->getIds()), reset($destination_ids)); + return $destination_ids; + } + return FALSE; + } + +} diff --git a/web/modules/paragraphs/src/Plugin/migrate/process/ParagraphsProcessOnValue.php b/web/modules/paragraphs/src/Plugin/migrate/process/ParagraphsProcessOnValue.php index 2e3992651fea5d61ae7e0db2a7a0187f2d614be6..cc77f4a4d5e3368bda8e3500d0e64fc0053c3b69 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/process/ParagraphsProcessOnValue.php +++ b/web/modules/paragraphs/src/Plugin/migrate/process/ParagraphsProcessOnValue.php @@ -3,7 +3,6 @@ namespace Drupal\paragraphs\Plugin\migrate\process; use Drupal\migrate\MigrateExecutableInterface; -use Drupal\migrate\MigrateSkipRowException; use Drupal\migrate\Row; /** @@ -43,9 +42,14 @@ public function transform($value, MigrateExecutableInterface $migrate_executable throw new \InvalidArgumentException("Required argument 'process' not set or invalid for paragraphs_process_on_value plugin"); } $source_value = $row->getSourceProperty($this->configuration['source_value']); + if (is_null($source_value)) { - throw new MigrateSkipRowException('Argument source_value is not valid for ProcessOnValue plugin'); + // This is probably a migration that shouldn't be touched by Paragraphs. + // For example, throwing an exception here would prevent the migration of + // the comment field configurations. + return $value; } + if ($source_value === $this->configuration['expected_value']) { $process = $this->configuration['process']; diff --git a/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItem.php b/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItem.php index d96646be7b8c08c517901134a0a3ae92f02d58b5..50af07d341f432b404f25268e80fa08e1f58accf 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItem.php +++ b/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItem.php @@ -50,6 +50,9 @@ public function query() { // bundles retrieved. if ($this->configuration['field_name']) { $query->condition('f.field_name', $this->configuration['field_name']); + $query->addField('fc', 'entity_type', 'parent_type'); + $query->addField('fc', 'entity_id', 'parent_id'); + $query->innerJoin('field_revision_' . $this->configuration['field_name'], 'fc', 'fc.' . $this->configuration['field_name'] . '_value = f.item_id and fc.' . $this->configuration['field_name'] . '_revision_id = f.revision_id'); } return $query; } @@ -85,6 +88,8 @@ public function fields() { 'revision_id' => $this->t('The field_collection_item revision id'), 'bundle' => $this->t('The field_collection bundle'), 'field_name' => $this->t('The field_collection field_name'), + 'parent_type' => $this->t('The type of the parent entity'), + 'parent_id' => $this->t('The identifier of the parent entity'), ]; return $fields; @@ -94,14 +99,12 @@ public function fields() { * {@inheritdoc} */ public function getIds() { - $ids = [ + return [ 'item_id' => [ 'type' => 'integer', 'alias' => 'f', ], ]; - - return $ids; } } diff --git a/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItemRevision.php b/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItemRevision.php index d281f5c9eea133dff5ae5afec11a17a80640f99c..bbc21885054286e4e89e3a2a2186193a12700cb5 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItemRevision.php +++ b/web/modules/paragraphs/src/Plugin/migrate/source/d7/FieldCollectionItemRevision.php @@ -25,14 +25,12 @@ class FieldCollectionItemRevision extends FieldCollectionItem { * {@inheritdoc} */ public function getIds() { - $ids = [ + return [ 'revision_id' => [ 'type' => 'integer', 'alias' => 'fr', ], ]; - - return $ids; } } diff --git a/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItem.php b/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItem.php index 5bd1f6f93fe0b4d372cd71a9358445c23e9f8c00..ffacff662f1644a3c7e7ae04caee4f16ae61ed79 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItem.php +++ b/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItem.php @@ -2,6 +2,7 @@ namespace Drupal\paragraphs\Plugin\migrate\source\d7; +use Drupal\Core\Database\DatabaseExceptionWrapper; use Drupal\migrate\Row; /** @@ -20,9 +21,18 @@ class ParagraphsItem extends FieldableEntity { /** * Join string for getting current revisions. + * + * @var string */ const JOIN = "p.revision_id = pr.revision_id"; + /** + * The prefix of the field table that contains the entity properties. + * + * @var string + */ + const PARENT_FIELD_TABLE_PREFIX = 'field_data_'; + /** * {@inheritdoc} */ @@ -38,7 +48,8 @@ public function defaultConfiguration() { public function query() { $query = $this->select('paragraphs_item', 'p') ->fields('p', - ['item_id', + [ + 'item_id', 'bundle', 'field_name', 'archived', @@ -58,13 +69,47 @@ public function query() { * {@inheritdoc} */ public function prepareRow(Row $row) { + [ + 'item_id' => $paragraph_id, + 'revision_id' => $paragraph_revision_id, + 'field_name' => $paragraph_parent_field_name, + 'bundle' => $bundle, + ] = $row->getSource(); + + if (!$paragraph_parent_field_name || !is_string($paragraph_parent_field_name)) { + return FALSE; + } // Get Field API field values. - $item_id = $row->getSourceProperty('item_id'); - $revision_id = $row->getSourceProperty('revision_id'); + foreach (array_keys($this->getFields('paragraphs_item', $bundle)) as $field_name) { + $row->setSourceProperty($field_name, $this->getFieldValues('paragraphs_item', $field_name, $paragraph_id, $paragraph_revision_id)); + } + + // We have to find the corresponding parent entity (which might be an + // another paragraph). Active revision only. + try { + $parent_data_query = $this->getDatabase()->select(static::PARENT_FIELD_TABLE_PREFIX . $paragraph_parent_field_name, 'fd'); + $parent_data_query->addField('fd', 'entity_type', 'parent_type'); + $parent_data_query->addField('fd', 'entity_id', 'parent_id'); + $parent_data = $parent_data_query + ->condition("fd.{$paragraph_parent_field_name}_value", $paragraph_id) + ->condition("fd.{$paragraph_parent_field_name}_revision_id", $paragraph_revision_id) + ->execute()->fetchAssoc(); + } + catch (DatabaseExceptionWrapper $e) { + // The paragraphs field data|revision table is missing, we cannot get + // the parent entity identifiers. This is a corrupted database. + // @todo Shouldn't we have to throw an exception instead? + return FALSE; + } + + if (!is_iterable($parent_data)) { + // We cannot get the parent entity identifiers. + return FALSE; + } - foreach (array_keys($this->getFields('paragraphs_item', $row->getSourceProperty('bundle'))) as $field) { - $row->setSourceProperty($field, $this->getFieldValues('paragraphs_item', $field, $item_id, $revision_id)); + foreach ($parent_data as $property_name => $property_value) { + $row->setSourceProperty($property_name, $property_value); } return parent::prepareRow($row); @@ -88,14 +133,12 @@ public function fields() { * {@inheritdoc} */ public function getIds() { - $ids = [ + return [ 'item_id' => [ 'type' => 'integer', 'alias' => 'p', ], ]; - - return $ids; } } diff --git a/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItemRevision.php b/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItemRevision.php index b15610dfe3634e6f0d047ac7b3c081e864a4e885..4713188175620a034696d99f834d77565535319b 100644 --- a/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItemRevision.php +++ b/web/modules/paragraphs/src/Plugin/migrate/source/d7/ParagraphsItemRevision.php @@ -17,22 +17,25 @@ class ParagraphsItemRevision extends ParagraphsItem { /** - * Join string for getting all except the current revisions. + * {@inheritdoc} */ const JOIN = "p.item_id=pr.item_id AND p.revision_id <> pr.revision_id"; + /** + * {@inheritdoc} + */ + const PARENT_FIELD_TABLE_PREFIX = 'field_revision_'; + /** * {@inheritdoc} */ public function getIds() { - $ids = [ + return [ 'revision_id' => [ 'type' => 'integer', 'alias' => 'pr', ], ]; - - return $ids; } } diff --git a/web/modules/paragraphs/templates/paragraphs-dropbutton-wrapper.html.twig b/web/modules/paragraphs/templates/paragraphs-dropbutton-wrapper.html.twig index 38cff6739fe4e1eff630833fb1a3fda5be283a4a..d647095f973c487396fc5d3923e3a0b819605043 100644 --- a/web/modules/paragraphs/templates/paragraphs-dropbutton-wrapper.html.twig +++ b/web/modules/paragraphs/templates/paragraphs-dropbutton-wrapper.html.twig @@ -13,9 +13,9 @@ */ #} {% if children %} - {% spaceless %} + {% apply spaceless %} <div class="paragraphs-dropbutton-wrapper"> {{ children }} </div> - {% endspaceless %} + {% endapply %} {% endif %} diff --git a/web/modules/paragraphs/templates/paragraphs-summary.html.twig b/web/modules/paragraphs/templates/paragraphs-summary.html.twig index b7f9330bbb35cd94d4e1c6851c0a640a5dec15d7..883a48dbf47a6aadb55a36f3c404286bcd5eb7de 100644 --- a/web/modules/paragraphs/templates/paragraphs-summary.html.twig +++ b/web/modules/paragraphs/templates/paragraphs-summary.html.twig @@ -17,7 +17,7 @@ 'paragraphs-description', expanded ? 'paragraphs-expanded-description' : 'paragraphs-collapsed-description' ] %} -{% spaceless %} +{% apply spaceless %} {% if content is not empty or behaviors is not empty %} <div{{ attributes.addClass(classes) }}> {% if content is not empty %} @@ -42,4 +42,4 @@ {% endif %} </div> {% endif %} -{% endspaceless %} +{% endapply %} diff --git a/web/modules/paragraphs/tests/fixtures/sites/default/files/Babylon5.txt b/web/modules/paragraphs/tests/fixtures/sites/default/files/Babylon5.txt new file mode 100644 index 0000000000000000000000000000000000000000..6a7e452749cf08168239c3e267a7e1d07c49ddc0 --- /dev/null +++ b/web/modules/paragraphs/tests/fixtures/sites/default/files/Babylon5.txt @@ -0,0 +1 @@ +*** diff --git a/web/modules/paragraphs/tests/fixtures/sites/default/files/cube.jpeg b/web/modules/paragraphs/tests/fixtures/sites/default/files/cube.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..652a7db77d5e3489745effa930f1a41b2d1ba69f --- /dev/null +++ b/web/modules/paragraphs/tests/fixtures/sites/default/files/cube.jpeg @@ -0,0 +1 @@ +******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** \ No newline at end of file diff --git a/web/modules/paragraphs/tests/fixtures/sites/default/files/ds9.txt b/web/modules/paragraphs/tests/fixtures/sites/default/files/ds9.txt new file mode 100644 index 0000000000000000000000000000000000000000..b49b7f69a81c1caf9dd969eb9105813f0d544bbe --- /dev/null +++ b/web/modules/paragraphs/tests/fixtures/sites/default/files/ds9.txt @@ -0,0 +1,79 @@ + __ ___ ___ + ,' ,' | | `. `. + ,' ,' |===| `. `. + / // |___| \\ \ + / // |___| \\ \ + //// |___| \\\\ + / / || || \ \ + / / || || \ \ + /| | || || | |\ + || | | : o : | | || + | \| | .===. | |/ | + | |\ /| (___) |\ /| | + |__||.\ .-. // /,_._,\ \\ .-. /.||__| + |__||_.\ `-.\ //_ [:(|):] _\\ /.-' /._||__| + __/| ||___`._____ ___\\__/___/_ ||| _\___\__//___ _____.'___||_ |\__ +/___//__________/.-/_____________|.-.|_____________\-.\__________\\___\ +\___\\__\\\_____\`-\__\\\\__\____|_-_|____/_//_____/-'/__//______//__// + \|__||__..' // \ _ \__|||__/ _ / \\ `..__||__|/ + |__||_./ .-'/ \\ |(|)| // \`-. \..||__| + | || / `-' \\ \'/ // `-' \ || | + | |/ \| :(-): |/ \| | + | /| | : o : | |\ | + || | | |___| | | || + \| | || || | |/ + \ \ || || / / + \ \ ||___|| / / + \\\\ |___| //// + \ \\ |___| // / + \ \\ | | // / + `. `. |===| ,' ,' + `._`. |___| ,'_,' + + + _ _ + _____---' \_n_/ `---_____ + _ / ... ----------- ... \ _ + ( )-' . '::.\__ V __/.::' . `-( ) + _ .-' ':::. ____ \ / ____ .:::' `-. _ + ,-'.`' __.--' \ | | / `--.__ `'.`-. + / ''::.. \ || || / ..::'' \ + / ..... ,'\,' ||_|| `./`. ..... \ + / :::::' ,' | | `. '::::: \ + | '::: ,' | | `. :::' | + _/ :: / |___| \ :: \_ + (/ / ,-' `-. \ \) + _/ `. ,-' ooo oo `-. ,' \_ + | /`./ ,-'\ /`-. \.'\ | + | .: / / \ \_ __.---.__ _/ / \ \ :. | + .' :;: | _ / o \[ ' \ / ` ]/ \ _ | ::: `. + | ':: | ( `-. / | | \ ,-' ) | ::' | + |: ': | `-./ / ___ \ \,-' | :' :| +.':: ' | | / `-. .-' . `-. .-' \ o | | ' ::`. +| ::. | | o ,| `-. / \`_|_'/ \ .-' |. o | | .:: | + \ |_ |____| | ` / \ ' | |____| _| / + (| _] ]____[ |- ( (O) ) -| ]____[ [_ |) + /.: | | | | . \_ _/ . | | | | :.\ +| :' | | o `|-,-' \ /..|..\ / `-.-|' o | |. ': | +`. :: | | o \ .-' `-.___.-' `-. / o | | :: .' + | .:: | _.\ \| | | \/ /._ | ::. | + | ': | _.-' \ o \ | | / o / `-._ | :' | + `. __ |__.-'_ _.\ /[_.__ | | __._]\ o /._ _`-.__| __ .' + | \ \_.--''.' .-' \ / / `---' \ \ / `-. `.``--__/ / | + |_\ __ ,',-' `-./ o \,-' `-.`. __ /_| + \\ / .',' `-. oo .-. oo ,-' `.`. \ // + (\\ \ \ `-._| |_,-' / / //) + \\ ) \ (_) / ( // + / \/ `. ,' \/ \ + \ .::. `. ,' .::: / + \ ':::. `-./`. .'\.-' '''''' / + \ ''' /_ _ _\ ::.. / + `-.'::' `--.______| |______.--' ,-' + `-'`-._ .. .: .: _,-'`' + (_)-. ::. '':::: :::::: : ,-(_) + \_____ '' _ _ ' _____/ + ---._/ u \_.--- + +Used with permission from: +Orbital Space Station (Terok Nor - Deep Space 9) - Joe Reiss +https://startrekasciiart.blogspot.co.uk/2011/05/deep-space-nine.html diff --git a/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.info.yml b/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.info.yml index 575b23ffe89c0fe64404fbfb8082ee7b1547cc12..df33b7c071c7dcbb79e49f666177f928165f1f9a 100644 --- a/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.info.yml +++ b/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.info.yml @@ -1,14 +1,13 @@ name: Paragraphs test type: module description: Resources for Paragraphs tests -core_version_requirement: ^8.7.7 || ^9 hidden: true -package: Paragraphs +package: Testing dependencies: - paragraphs:paragraphs -# Information added by Drupal.org packaging script on 2020-05-21 -version: '8.x-1.12' +# Information added by Drupal.org packaging script on 2022-08-25 +version: '8.x-1.15' project: 'paragraphs' -datestamp: 1590061337 +datestamp: 1661440900 diff --git a/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.module b/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.module index c5c345eb6dd93377c49edebd6f3483b1eaae7534..38e1f8ec407491aef5f07f76db1484db83024808 100644 --- a/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.module +++ b/web/modules/paragraphs/tests/modules/paragraphs_test/paragraphs_test.module @@ -43,10 +43,10 @@ function paragraphs_test_paragraph_view(array &$build, ParagraphInterface $entit } /** - * Implements hook_field_widget_WIDGET_TYPE_form_alter(). + * Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter(). */ -function paragraphs_test_field_widget_entity_reference_paragraphs_form_alter(&$element, &$form_state, $context) { +function paragraphs_test_field_widget_single_element_entity_reference_paragraphs_form_alter(&$element, &$form_state, $context) { if ($element['#paragraph_type'] == 'altered_paragraph') { $element['subform']['field_text']['widget'][0]['#title'] = 'Altered title'; } -} \ No newline at end of file +} diff --git a/web/modules/paragraphs/tests/modules/paragraphs_test/src/Form/TestEmbeddedEntityForm.php b/web/modules/paragraphs/tests/modules/paragraphs_test/src/Form/TestEmbeddedEntityForm.php new file mode 100644 index 0000000000000000000000000000000000000000..ea47736bdced25687159188a78274495fb96d98a --- /dev/null +++ b/web/modules/paragraphs/tests/modules/paragraphs_test/src/Form/TestEmbeddedEntityForm.php @@ -0,0 +1,104 @@ +<?php + +namespace Drupal\paragraphs_test\Form; + +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Core\Form\FormInterface; +use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Form\SubformStateInterface; + +/** + * A class to build a form that embeds a content entity form. + * + * The logic of form processing is based on Layout Builder's InlineBlock + * form processing. + */ +class TestEmbeddedEntityForm implements FormInterface { + + /** + * The entity of the embedded form. + * + * @var \Drupal\Core\Entity\ContentEntityInterface + */ + protected $entity; + + /** + * TestEmbeddedEntityForm constructor. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The entity of the embedded form. + */ + public function __construct(ContentEntityInterface $entity) { + $this->entity = $entity; + } + + /** + * Get the entity of this form object. + * + * @return \Drupal\Core\Entity\ContentEntityInterface + * The entity. + */ + public function getEntity() { + return $this->entity; + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'test_embedded_entity_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + // Based on the logic of Layout Builder's InlineBlock form processing, + // the entity form is being inserted via process callback. + return [ + 'embedded_entity_form' => [ + '#type' => 'container', + '#process' => [[static::class, 'processEmbeddedEntityForm']], + '#entity' => $this->entity, + ], + ]; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) {} + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $embedded_form = $form['embedded_entity_form']; + $this->entity = $embedded_form['#entity']; + + $form_display = EntityFormDisplay::collectRenderDisplay($this->entity, 'default'); + $complete_form_state = $form_state instanceof SubformStateInterface ? $form_state->getCompleteFormState() : $form_state; + $form_display->extractFormValues($this->entity, $embedded_form, $complete_form_state); + $this->entity->save(); + } + + /** + * Process callback to embed an entity form. + * + * @param array $element + * The containing element. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. + * + * @return array + * The containing element, with the entity form inserted. + */ + public static function processEmbeddedEntityForm(array $element, FormStateInterface $form_state) { + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + $entity = $element['#entity']; + EntityFormDisplay::collectRenderDisplay($entity, 'default')->buildForm($entity, $element, $form_state); + return $element; + } + +} diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalReplicateEnableTest.php b/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalReplicateEnableTest.php deleted file mode 100644 index 775b3cc47a75ea9c8ee0142b3a19b0ac1c470ae8..0000000000000000000000000000000000000000 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalReplicateEnableTest.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Drupal\Tests\paragraphs\Functional\Experimental; - -/** - * Enables replicate module. - * - * @group paragraphs - */ - -class ParagraphsExperimentalReplicateEnableTest extends ParagraphsExperimentalDuplicateFeatureTest { - - public static $modules = [ - 'replicate', - ]; - -} diff --git a/web/modules/paragraphs/tests/src/Functional/Migrate/MigrateUiParagraphsTest.php b/web/modules/paragraphs/tests/src/Functional/Migrate/MigrateUiParagraphsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6f5e72c68a0db2638befa0245260096637134072 --- /dev/null +++ b/web/modules/paragraphs/tests/src/Functional/Migrate/MigrateUiParagraphsTest.php @@ -0,0 +1,51 @@ +<?php + +namespace Drupal\Tests\paragraphs\Functional\Migrate; + +use Drupal\Tests\paragraphs\Traits\ParagraphsNodeMigrationAssertionsTrait; + +/** + * Tests the migration of paragraph entities. + * + * @group paragraphs + * + * @group legacy + */ +class MigrateUiParagraphsTest extends MigrateUiParagraphsTestBase { + + use ParagraphsNodeMigrationAssertionsTrait; + + /** + * Tests the result of the paragraphs migration. + * + * @dataProvider providerParagraphsMigrate + */ + public function testParagraphsMigrate($node_migrate_type_classic) { + // Drupal 8.8.x only has 'classic' node migrations. + // @see https://www.drupal.org/node/3105503 + if (!$node_migrate_type_classic && version_compare(\Drupal::VERSION, '8.9', '<')) { + $this->pass("Drupal 8.8.x has only the 'classic' node migration."); + return; + } + $this->setClassicNodeMigration($node_migrate_type_classic); + $this->assertMigrateUpgradeViaUi(); + $this->assertParagraphsMigrationResults(); + $this->assertNode8Paragraphs(); + $this->assertNode9Paragraphs(); + $this->assertIcelandicNode9Paragraphs(); + } + + /** + * Provides data and expected results for testing paragraph migrations. + * + * @return bool[][] + * Classic node migration type. + */ + public function providerParagraphsMigrate() { + return [ + ['node_migrate_type_classic' => TRUE], + ['node_migrate_type_classic' => FALSE], + ]; + } + +} diff --git a/web/modules/paragraphs/tests/src/Functional/Migrate/MigrateUiParagraphsTestBase.php b/web/modules/paragraphs/tests/src/Functional/Migrate/MigrateUiParagraphsTestBase.php new file mode 100644 index 0000000000000000000000000000000000000000..fcd1867e8476fdde4e15150b1363664af44cc1d1 --- /dev/null +++ b/web/modules/paragraphs/tests/src/Functional/Migrate/MigrateUiParagraphsTestBase.php @@ -0,0 +1,569 @@ +<?php + +namespace Drupal\Tests\paragraphs\Functional\Migrate; + +use Behat\Mink\Exception\ExpectationException; +use Drupal\Component\Plugin\Exception\PluginNotFoundException; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Site\Settings; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\migrate\Plugin\MigrateIdMapInterface; +use Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeTestBase; + +/** + * Provides a base class for testing Paragraphs migration via the UI. + */ +abstract class MigrateUiParagraphsTestBase extends MigrateUpgradeTestBase { + + use StringTranslationTrait; + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'content_translation', + 'migrate_drupal_ui', + 'paragraphs', + 'telephone', + ]; + + /** + * {@inheritdoc} + */ + protected function getSourceBasePath() { + return \Drupal::service('extension.list.module')->getPath('paragraphs') . '/tests/fixtures'; + } + + /** + * {@inheritdoc} + */ + protected function getSourcePrivateFilesPath() { + return \Drupal::service('extension.list.module')->getPath('paragraphs') . '/tests/fixtures'; + } + + /** + * Gets the expected entity IDs and labels per entity type after migration. + * + * @return string|null[][] + * An array of expected entity labels keyed by IDs, grouped by entity type + * ID. For some of the entities, label can be NULL. + */ + protected function getExpectedEntities() { + $expected_entities = [ + 'entity_form_display' => [ + 'block_content.basic.default' => NULL, + 'comment.comment.default' => NULL, + 'comment.comment_forum.default' => NULL, + 'comment.comment_node_article.default' => NULL, + 'comment.comment_node_blog.default' => NULL, + 'comment.comment_node_book.default' => NULL, + 'comment.comment_node_page.default' => NULL, + 'comment.comment_node_paragraphs_test.default' => NULL, + 'comment.comment_node_test_content_type.default' => NULL, + 'node.article.default' => NULL, + 'node.blog.default' => NULL, + 'node.book.default' => NULL, + 'node.forum.default' => NULL, + 'node.page.default' => NULL, + 'node.paragraphs_test.default' => NULL, + 'node.test_content_type.default' => NULL, + 'paragraph.field_collection_test.default' => NULL, + 'paragraph.nested_fc_inner.default' => NULL, + 'paragraph.nested_fc_outer.default' => NULL, + 'paragraph.paragraph_bundle_one.default' => NULL, + 'paragraph.paragraph_bundle_two.default' => NULL, + 'taxonomy_term.test_vocabulary.default' => NULL, + 'user.user.default' => NULL, + ], + 'entity_form_mode' => [ + 'user.register' => 'Register', + ], + 'entity_view_display' => [ + 'block_content.basic.default' => NULL, + 'comment.comment.default' => NULL, + 'comment.comment_forum.default' => NULL, + 'comment.comment_node_article.default' => NULL, + 'comment.comment_node_blog.default' => NULL, + 'comment.comment_node_book.default' => NULL, + 'comment.comment_node_page.default' => NULL, + 'comment.comment_node_paragraphs_test.default' => NULL, + 'comment.comment_node_test_content_type.default' => NULL, + 'node.article.custom' => NULL, + 'node.article.default' => NULL, + 'node.article.rss' => NULL, + 'node.article.teaser' => NULL, + 'node.blog.default' => NULL, + 'node.blog.teaser' => NULL, + 'node.book.default' => NULL, + 'node.book.teaser' => NULL, + 'node.forum.default' => NULL, + 'node.forum.teaser' => NULL, + 'node.page.default' => NULL, + 'node.page.teaser' => NULL, + 'node.paragraphs_test.default' => NULL, + 'node.paragraphs_test.teaser' => NULL, + 'node.test_content_type.default' => NULL, + 'paragraph.field_collection_test.default' => NULL, + 'paragraph.nested_fc_inner.default' => NULL, + 'paragraph.nested_fc_outer.default' => NULL, + 'paragraph.paragraph_bundle_one.default' => NULL, + 'paragraph.paragraph_bundle_one.paragraphs_editor_preview' => NULL, + 'paragraph.paragraph_bundle_two.default' => NULL, + 'taxonomy_term.test_vocabulary.default' => NULL, + 'user.user.compact' => NULL, + 'user.user.default' => NULL, + ], + 'entity_view_mode' => [ + 'block_content.full' => 'Full', + 'comment.full' => 'Full', + 'node.custom' => 'custom', + 'node.full' => 'Full', + 'node.rss' => 'RSS', + 'node.search_index' => 'Search index', + 'node.search_result' => 'Search result highlighting input', + 'node.teaser' => 'Teaser', + 'paragraph.full' => 'Full', + 'paragraph.paragraphs_editor_preview' => 'paragraphs_editor_preview', + 'paragraph.preview' => 'Preview', + 'taxonomy_term.full' => 'Full', + 'user.compact' => 'Compact', + 'user.full' => 'Full', + ], + 'field_storage_config' => [ + 'block_content.body' => 'block_content.body', + 'comment.comment_body' => 'comment.comment_body', + 'comment.field_integer' => 'comment.field_integer', + 'node.body' => 'node.body', + 'node.comment' => 'node.comment', + 'node.comment_forum' => 'node.comment_forum', + 'node.comment_node_article' => 'node.comment_node_article', + 'node.comment_node_blog' => 'node.comment_node_blog', + 'node.comment_node_book' => 'node.comment_node_book', + 'node.comment_node_page' => 'node.comment_node_page', + 'node.comment_node_paragraphs_test' => 'node.comment_node_paragraphs_test', + 'node.comment_node_test_content_type' => 'node.comment_node_test_content_type', + 'node.field_any_paragraph' => 'node.field_any_paragraph', + 'node.field_boolean' => 'node.field_boolean', + 'node.field_date' => 'node.field_date', + 'node.field_date_with_end_time' => 'node.field_date_with_end_time', + 'node.field_date_without_time' => 'node.field_date_without_time', + 'node.field_datetime_without_time' => 'node.field_datetime_without_time', + 'node.field_email' => 'node.field_email', + 'node.field_field_collection_test' => 'node.field_field_collection_test', + 'node.field_file' => 'node.field_file', + 'node.field_float' => 'node.field_float', + 'node.field_image' => 'node.field_image', + 'node.field_images' => 'node.field_images', + 'node.field_integer' => 'node.field_integer', + 'node.field_integer_list' => 'node.field_integer_list', + 'node.field_link' => 'node.field_link', + 'node.field_long_text' => 'node.field_long_text', + 'node.field_nested_fc_outer' => 'node.field_nested_fc_outer', + 'node.field_node_entityreference' => 'node.field_node_entityreference', + 'node.field_paragraph_one_only' => 'node.field_paragraph_one_only', + 'node.field_phone' => 'node.field_phone', + 'node.field_private_file' => 'node.field_private_file', + 'node.field_tags' => 'node.field_tags', + 'node.field_term_entityreference' => 'node.field_term_entityreference', + 'node.field_term_reference' => 'node.field_term_reference', + 'node.field_text' => 'node.field_text', + 'node.field_text_filtered' => 'node.field_text_filtered', + 'node.field_text_list' => 'node.field_text_list', + 'node.field_text_long_filtered' => 'node.field_text_long_filtered', + 'node.field_text_long_plain' => 'node.field_text_long_plain', + 'node.field_text_plain' => 'node.field_text_plain', + 'node.field_text_sum_filtered' => 'node.field_text_sum_filtered', + 'node.field_user_entityreference' => 'node.field_user_entityreference', + 'node.taxonomy_forums' => 'node.taxonomy_forums', + 'paragraph.field_email' => 'paragraph.field_email', + 'paragraph.field_integer_list' => 'paragraph.field_integer_list', + 'paragraph.field_nested_fc_inner' => 'paragraph.field_nested_fc_inner', + 'paragraph.field_text' => 'paragraph.field_text', + 'paragraph.field_text_list' => 'paragraph.field_text_list', + 'taxonomy_term.field_integer' => 'taxonomy_term.field_integer', + 'taxonomy_term.field_term_reference' => 'taxonomy_term.field_term_reference', + 'user.field_file' => 'user.field_file', + 'user.field_integer' => 'user.field_integer', + 'user.user_picture' => 'user.user_picture', + ], + 'field_config' => [ + 'block_content.basic.body' => 'Body', + 'comment.comment.comment_body' => 'Comment', + 'comment.comment_forum.comment_body' => 'Comment', + 'comment.comment_node_article.comment_body' => 'Comment', + 'comment.comment_node_blog.comment_body' => 'Comment', + 'comment.comment_node_book.comment_body' => 'Comment', + 'comment.comment_node_page.comment_body' => 'Comment', + 'comment.comment_node_paragraphs_test.comment_body' => 'Comment', + 'comment.comment_node_test_content_type.comment_body' => 'Comment', + 'comment.comment_node_test_content_type.field_integer' => 'Integer', + 'node.article.body' => 'Body', + 'node.article.comment' => 'Comments', + 'node.article.comment_node_article' => 'Comments', + 'node.article.field_image' => 'Image', + 'node.article.field_link' => 'Link', + 'node.article.field_tags' => 'Tags', + 'node.article.field_text_filtered' => 'Text filtered', + 'node.article.field_text_long_filtered' => 'Text long filtered', + 'node.article.field_text_long_plain' => 'Text long plain', + 'node.article.field_text_plain' => 'Text plain', + 'node.article.field_text_sum_filtered' => 'Text summary filtered', + 'node.blog.body' => 'Body', + 'node.blog.comment_node_blog' => 'Comments', + 'node.blog.field_link' => 'Link', + 'node.book.body' => 'Body', + 'node.book.comment_node_book' => 'Comments', + 'node.forum.body' => 'Body', + 'node.forum.comment_forum' => 'Comments', + 'node.forum.taxonomy_forums' => 'Forums', + 'node.page.body' => 'Body', + 'node.page.comment_node_page' => 'Comments', + 'node.page.field_text_filtered' => 'Text filtered', + 'node.page.field_text_long_filtered' => 'Text long filtered', + 'node.page.field_text_long_plain' => 'Text long plain', + 'node.page.field_text_plain' => 'Text plain', + 'node.page.field_text_sum_filtered' => 'Text summary filtered', + 'node.paragraphs_test.body' => 'Body', + 'node.paragraphs_test.comment_node_paragraphs_test' => 'Comments', + 'node.paragraphs_test.field_any_paragraph' => 'Any Paragraph', + 'node.paragraphs_test.field_field_collection_test' => 'Field Collection Test', + 'node.paragraphs_test.field_nested_fc_outer' => 'Nested FC Outer', + 'node.paragraphs_test.field_paragraph_one_only' => 'Paragraph One Only', + 'node.test_content_type.field_boolean' => 'Boolean', + 'node.test_content_type.comment_node_test_content_type' => 'Comments', + 'node.test_content_type.field_date' => 'Date', + 'node.test_content_type.field_date_with_end_time' => 'Date With End Time', + 'node.test_content_type.field_date_without_time' => 'Date without time', + 'node.test_content_type.field_datetime_without_time' => 'Datetime without time', + 'node.test_content_type.field_email' => 'Email', + 'node.test_content_type.field_file' => 'File', + 'node.test_content_type.field_float' => 'Float', + 'node.test_content_type.field_images' => 'Images', + 'node.test_content_type.field_integer' => 'Integer', + 'node.test_content_type.field_integer_list' => 'Integer List', + 'node.test_content_type.field_link' => 'Link', + 'node.test_content_type.field_long_text' => 'Long text', + 'node.test_content_type.field_node_entityreference' => 'Node Entity Reference', + 'node.test_content_type.field_phone' => 'Phone', + 'node.test_content_type.field_private_file' => 'Private file', + 'node.test_content_type.field_term_entityreference' => 'Term Entity Reference', + 'node.test_content_type.field_term_reference' => 'Term Reference', + 'node.test_content_type.field_text' => 'Text', + 'node.test_content_type.field_text_list' => 'Text List', + 'node.test_content_type.field_user_entityreference' => 'User Entity Reference', + 'paragraph.field_collection_test.field_integer_list' => 'Integer List', + 'paragraph.field_collection_test.field_text' => 'Text', + 'paragraph.nested_fc_inner.field_text' => 'Text', + 'paragraph.nested_fc_outer.field_nested_fc_inner' => 'Nested FC Inner', + 'paragraph.paragraph_bundle_one.field_text' => 'Text', + 'paragraph.paragraph_bundle_one.field_text_list' => 'Text List', + 'paragraph.paragraph_bundle_two.field_email' => 'Email', + 'paragraph.paragraph_bundle_two.field_text' => 'Text', + 'taxonomy_term.test_vocabulary.field_integer' => 'Integer', + 'taxonomy_term.test_vocabulary.field_term_reference' => 'Term Reference', + 'user.user.field_file' => 'File', + 'user.user.field_integer' => 'Integer', + 'user.user.user_picture' => 'Picture', + ], + 'node_type' => [ + 'article' => 'Article', + 'blog' => 'Blog entry', + 'book' => 'Book page', + 'forum' => 'Forum topic', + 'page' => 'Basic page', + 'paragraphs_test' => 'Paragraphs Test', + 'test_content_type' => 'Test content type', + ], + 'node' => [ + 1 => 'A Node', + 2 => 'The thing about Deep Space 9', + 4 => 'is - The thing about Firefly', + 6 => 'Comments are closed :-(', + 7 => 'Comments are open :-)', + 8 => 'Paragraph Migration Test Content UND', + 9 => 'Paragraph Migration Test Content EN', + ], + 'paragraphs_type' => [ + 'field_collection_test' => 'Field collection test', + 'nested_fc_inner' => 'Nested fc inner', + 'nested_fc_outer' => 'Nested fc outer', + 'paragraph_bundle_one' => 'Paragraph Bundle One', + 'paragraph_bundle_two' => 'Paragraph Bundle Two', + ], + // Paragraph IDs and labels with 'complete' migration, where node + // revisions (even the active one) and node translations are migrated in a + // single, complete node migration. The final IDs of the paragraph + // entities aren't the same as the ones migrated with the 'classic' + // migration. + // @see https://www.drupal.org/node/3105503 + 'paragraph' => [ + 1 => 'Paragraph Migration Test Content UND > Field Collection Test', + 2 => 'Paragraph Migration Test Content UND > Field Collection Test', + 3 => 'Paragraph Migration Test Content EN > Field Collection Test', + 4 => 'Paragraph Migration Test Content EN > Field Collection Test (previous revision)', + 5 => 'Paragraph Migration Test Content EN > Field Collection Test (previous revision)', + 6 => 'Paragraph Migration Test Content EN > Field Collection Test (previous revision)', + 7 => 'Paragraph Migration Test Content UND > Nested FC Outer > Nested FC Inner', + 8 => 'Paragraph Migration Test Content UND > Nested FC Outer', + 9 => 'Paragraph Migration Test Content EN > Any Paragraph (previous revision)', + 10 => 'Paragraph Migration Test Content UND > Any Paragraph', + 11 => 'Paragraph Migration Test Content UND > Paragraph One Only', + 12 => 'Paragraph Migration Test Content EN > Any Paragraph', + 13 => 'Paragraph Migration Test Content EN > Paragraph One Only', + 14 => 'Paragraph Migration Test Content EN > Paragraph One Only (previous revision)', + 15 => 'Paragraph Migration Test Content UND > Any Paragraph', + 16 => 'Paragraph Migration Test Content EN > Any Paragraph', + 17 => 'Paragraph Migration Test Content EN > Any Paragraph (previous revision)', + 18 => 'Paragraph Migration Test Content EN > Any Paragraph (previous revision)', + ], + ]; + + // Paragraph IDs and labels with 'classic' node migration (core 8.8.x has + // only this), where nodes, node revisions and node translations are + // migrated separately. + if (Settings::get('migrate_node_migrate_type_classic', FALSE)) { + $expected_entities['paragraph'] = [ + 1 => 'Paragraph Migration Test Content UND > Field Collection Test (previous revision)', + 2 => 'Paragraph Migration Test Content UND > Field Collection Test (previous revision)', + 3 => 'Paragraph Migration Test Content EN > Field Collection Test', + 4 => 'Paragraph Migration Test Content EN > Field Collection Test (previous revision)', + 5 => 'Paragraph Migration Test Content EN > Field Collection Test (previous revision)', + 6 => 'Paragraph Migration Test Content EN > Field Collection Test (previous revision)', + 7 => 'Paragraph Migration Test Content EN > Any Paragraph (previous revision)', + 8 => 'Paragraph Migration Test Content UND > Any Paragraph (previous revision)', + 9 => 'Paragraph Migration Test Content UND > Paragraph One Only (previous revision)', + 10 => 'Paragraph Migration Test Content EN > Any Paragraph', + 11 => 'Paragraph Migration Test Content EN > Paragraph One Only', + 12 => 'Paragraph Migration Test Content EN > Paragraph One Only (previous revision)', + 13 => 'Paragraph Migration Test Content UND > Any Paragraph (previous revision)', + 14 => 'Paragraph Migration Test Content EN > Any Paragraph', + 15 => 'Paragraph Migration Test Content EN > Any Paragraph (previous revision)', + 16 => 'Paragraph Migration Test Content EN > Any Paragraph (previous revision)', + 17 => 'Paragraph Migration Test Content UND > Nested FC Outer > Nested FC Inner', + 18 => 'Paragraph Migration Test Content UND > Nested FC Outer', + ]; + } + + return $expected_entities; + } + + /** + * {@inheritdoc} + */ + protected function getEntityCounts() { + // This is not used. + $entity_counts = []; + + foreach ($this->getExpectedEntities() as $entity_type_id => $expected_entities) { + $entity_counts[$entity_type_id] = count($expected_entities); + } + + return $entity_counts; + } + + /** + * {@inheritdoc} + */ + protected function getEntityCountsIncremental() { + // Unused. + return $this->getEntityCounts(); + } + + /** + * {@inheritdoc} + */ + protected function getAvailablePaths() { + // Unused. + return []; + } + + /** + * {@inheritdoc} + */ + protected function getMissingPaths() { + // Unused. + return []; + } + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->loadFixture(\Drupal::service('extension.list.module')->getPath('paragraphs') . '/tests/fixtures/drupal7.php'); + } + + /** + * Executes the upgrade process by the UI and asserts basic expectations. + */ + protected function assertMigrateUpgradeViaUi() { + $connection_options = $this->sourceDatabase->getConnectionOptions(); + $this->drupalGet('/upgrade'); + $session = $this->assertSession(); + $session->responseContains('Upgrade a site by importing its files and the data from its database into a clean and empty new install of Drupal'); + + $this->submitForm([], $this->t('Continue')); + $session->pageTextContains('Provide credentials for the database of the Drupal site you want to upgrade.'); + + $driver = $connection_options['driver']; + if (floatval(\Drupal::VERSION) < 9.3) { + $connection_options['prefix'] = $connection_options['prefix']['default']; + } + + // Use the driver connection form to get the correct options out of the + // database settings. This supports all of the databases we test against. + $drivers = drupal_get_database_types(); + $form = $drivers[$driver]->getFormOptions($connection_options); + $connection_options = array_intersect_key($connection_options, $form + $form['advanced_options']); + $version = $this->getLegacyDrupalVersion($this->sourceDatabase); + $edit = [ + $driver => $connection_options, + 'source_private_file_path' => $this->getSourcePrivateFilesPath(), + 'version' => $version, + 'source_base_path' => $this->getSourceBasePath(), + ]; + + if (count($drivers) !== 1) { + $edit['driver'] = $driver; + } + $edits = $this->translatePostValues($edit); + + $this->submitForm($edits, $this->t('Review upgrade')); + $session->pageTextNotContains('Resolve all issues below to continue the upgrade.'); + + // ID conflict form. + $session->buttonExists($this->t('I acknowledge I may lose data. Continue anyway.')); + $this->submitForm([], $this->t('I acknowledge I may lose data. Continue anyway.')); + $session->statusCodeEquals(200); + + // Perform the upgrade. + $this->submitForm([], $this->t('Perform upgrade')); + $session->pageTextContains($this->t('Congratulations, you upgraded Drupal!')); + + // Have to reset all the statics after migration to ensure entities are + // loadable. + $this->resetAll(); + } + + /** + * Checks that migrations have been performed successfully. + */ + protected function assertParagraphsMigrationResults() { + $version = $this->getLegacyDrupalVersion($this->sourceDatabase); + + $this->assertEntities(); + + $plugin_manager = $this->container->get('plugin.manager.migration'); + /** @var \Drupal\migrate\Plugin\Migration[] $all_migrations */ + $all_migrations = $plugin_manager->createInstancesByTag('Drupal ' . $version); + + foreach ($all_migrations as $migration) { + $id_map = $migration->getIdMap(); + foreach ($id_map as $source_id => $map) { + // Convert $source_id into a keyless array so that + // \Drupal\migrate\Plugin\migrate\id_map\Sql::getSourceHash() works as + // expected. + $source_id_values = array_values(unserialize($source_id)); + $row = $id_map->getRowBySource($source_id_values); + $destination = serialize($id_map->currentDestination()); + $message = "Migration of $source_id to $destination as part of the {$migration->id()} migration. The source row status is " . $row['source_row_status']; + // A completed migration should have maps with + // MigrateIdMapInterface::STATUS_IGNORED or + // MigrateIdMapInterface::STATUS_IMPORTED. + $this->assertNotSame(MigrateIdMapInterface::STATUS_FAILED, $row['source_row_status'], $message); + $this->assertNotSame(MigrateIdMapInterface::STATUS_NEEDS_UPDATE, $row['source_row_status'], $message); + } + } + } + + /** + * Pass if the page HTML title is the given string. + * + * @param string $expected_title + * The string the page title should be. + * + * @throws \Behat\Mink\Exception\ExpectationException + * Thrown when element doesn't exist, or the title is a different one. + */ + protected function assertPageTitle($expected_title) { + $page_title_element = $this->getSession()->getPage()->find('css', 'h1.page-title'); + if (!$page_title_element) { + throw new ExpectationException('No page title element found on the page', $this->getSession()->getDriver()); + } + $actual_title = $page_title_element->getText(); + $this->assertSame($expected_title, $actual_title, 'The page title is not the same as expected.'); + } + + /** + * Asserts that the expected entities exist. + */ + protected function assertEntities() { + foreach ($this->getExpectedEntities() as $entity_type_id => $expected_entity_labels) { + if ($storage = $this->getEntityStorage($entity_type_id)) { + $entities = $storage->loadMultiple(); + $actual_labels = array_reduce($entities, function ($carry, EntityInterface $entity) { + $carry[$entity->id()] = (string) $entity->label(); + return $carry; + }); + if (\Drupal::database()->driver() === 'pgsql') { + // On PostgreSQL the entity IDs are not the same so only compare the + // labels to ensure we've migrated the expected number of entities. + $this->assertEqualsCanonicalizing($expected_entity_labels, $actual_labels, sprintf('The expected %s entities are not matching the actual ones.', $entity_type_id)); + } + else { + $this->assertEquals($expected_entity_labels, $actual_labels, sprintf('The expected %s entities are not matching the actual ones.', $entity_type_id)); + } + } + else { + $this->fail(sprintf('The expected %s entity type is missing.', $entity_type_id)); + } + } + } + + /** + * Returns the specified entity's storage when the entity definition exists. + * + * @param string $entity_type_id + * The entity type ID. + * + * @return \Drupal\Core\Entity\EntityStorageInterface|null + * The embed button's entity storage, or NULL if it does not exist. + */ + protected function getEntityStorage(string $entity_type_id) { + $entity_type_manager = $this->container->get('entity_type.manager'); + assert($entity_type_manager instanceof EntityTypeManagerInterface); + + try { + $storage = $entity_type_manager->getStorage($entity_type_id); + } + catch (PluginNotFoundException $e) { + // The entity type does not exist. + return NULL; + } + + return $storage; + } + + /** + * Sets the type of the node migration. + * + * @param bool $classic_node_migration + * Whether nodes should be migrated with the 'classic' way. If this is + * FALSE, and the current Drupal instance has the 'complete' migration, then + * the complete node migration will be used. + */ + protected function setClassicNodeMigration(bool $classic_node_migration) { + $current_method = Settings::get('migrate_node_migrate_type_classic', FALSE); + + if ($current_method !== $classic_node_migration) { + $settings['settings']['migrate_node_migrate_type_classic'] = (object) [ + 'value' => $classic_node_migration, + 'required' => TRUE, + ]; + $this->writeSettings($settings); + } + } + +} diff --git a/web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalBehaviorsTest.php b/web/modules/paragraphs/tests/src/Functional/ParagraphsBehaviorsTest.php similarity index 90% rename from web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalBehaviorsTest.php rename to web/modules/paragraphs/tests/src/Functional/ParagraphsBehaviorsTest.php index f7a83d2d543a5f705e390112e70e6a84d799c534..a2371e25b603c9d5d32317bb065f82bb27acfbf7 100644 --- a/web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalBehaviorsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/ParagraphsBehaviorsTest.php @@ -2,21 +2,21 @@ namespace Drupal\Tests\paragraphs\Functional; -use Drupal\Tests\paragraphs\Functional\Experimental\ParagraphsExperimentalTestBase; +use Drupal\Tests\paragraphs\Functional\WidgetStable\ParagraphsTestBase; /** * Tests support for Paragraphs behavior plugins. * * @group paragraphs */ -class ParagraphsExperimentalBehaviorsTest extends ParagraphsExperimentalTestBase { +class ParagraphsBehaviorsTest extends ParagraphsTestBase { /** * Modules to enable. * * @var string[] */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_test', ]; @@ -45,7 +45,7 @@ public function testBehaviorPluginsSettingsFiltering() { $edit = [ 'behavior_plugins[test_bold_text][enabled]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSame(['test_bold_text' => ['enabled' => TRUE]], \Drupal::config("paragraphs.paragraphs_type.$paragraph_type")->get('behavior_plugins')); // Add a note that uses the behavior plugin give it an empty setting. @@ -55,7 +55,7 @@ public function testBehaviorPluginsSettingsFiltering() { 'field_paragraphs[0][subform][field_text][0][value]' => 'Non-bold text', 'field_paragraphs[0][behavior_plugins][test_bold_text][bold_text]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $bolded_elements = $this->getSession()->getPage()->findAll('css', '.bold_plugin_text'); $this->assertEmpty(count($bolded_elements), 'Test plugin did not add a CSS class.'); @@ -73,7 +73,7 @@ public function testBehaviorPluginsSettingsFiltering() { 'field_paragraphs[0][subform][field_text][0][value]' => 'Bold text', 'field_paragraphs[0][behavior_plugins][test_bold_text][bold_text]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $bolded_elements = $this->getSession()->getPage()->findAll('css', '.bold_plugin_text'); $this->assertGreaterThan(0, count($bolded_elements), 'Test plugin added a CSS class.'); diff --git a/web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalUiTest.php b/web/modules/paragraphs/tests/src/Functional/ParagraphsUiTest.php similarity index 78% rename from web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalUiTest.php rename to web/modules/paragraphs/tests/src/Functional/ParagraphsUiTest.php index 45f0ba9d86d089cca267b333ba82ca25825dac0c..86efb3bfc27c84f43b94f66e0f361e0f721e7b67 100644 --- a/web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalUiTest.php +++ b/web/modules/paragraphs/tests/src/Functional/ParagraphsUiTest.php @@ -2,21 +2,21 @@ namespace Drupal\Tests\paragraphs\Functional; -use Drupal\Tests\paragraphs\Functional\Experimental\ParagraphsExperimentalTestBase; +use Drupal\Tests\paragraphs\Functional\WidgetStable\ParagraphsTestBase; /** * Tests the Paragraphs user interface. * * @group paragraphs */ -class ParagraphsExperimentalUiTest extends ParagraphsExperimentalTestBase { +class ParagraphsUiTest extends ParagraphsTestBase { /** * Modules to enable. * * @var string[] */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs', 'field', @@ -65,7 +65,7 @@ public function testSummary() { 'title[0][value]' => 'Llama test', 'paragraphs[0][subform][field_text_demo][0][value]' => '<iframe src="https://www.llamatest.neck"></iframe>', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Llama test has been created.'); // Assert that the summary contains the html text. $node = $this->getNodeByTitle('Llama test'); @@ -77,7 +77,7 @@ public function testSummary() { $edit = [ 'paragraphs[0][subform][field_text_demo][0][value]' => '<iframe src="https://www.llamatest.neck" class="this-is-a-pretty-long-class-that-needs-to-be-really-long-for-testing-purposes-so-we-have-a-better-summary-test-and-it-has-exactly-144-characters"></iframe>', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Llama test has been updated.'); $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->pageTextContains('<iframe src="https://www.llamatest.neck" class="this-is-a-pretty-long-class-that-needs-to-be-really-long-for-testing-purposes-so-we-'); @@ -88,9 +88,38 @@ public function testSummary() { $edit = [ 'paragraphs[0][subform][field_text_demo][0][value]' => '<iframe src="https://www.llamatest.neck" class="this-is-a-pretty-long-class-that-needs-to-be-really-long-for-testing-purposes-so-we-have-a-better-summary-test-and-it-has-exactly-144-characters"></iframe><h1>This is a title</h1>', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->responseContains('class="paragraphs-description paragraphs-collapsed-description"><div class="paragraphs-content-wrapper"><span class="summary-content">This is a title'); } + /** + * Test the default paragraphs widget used. + */ + public function testDefaultWidget() { + $this->loginAsAdmin(); + + // Create a new content type. + $this->drupalGet('admin/structure/types/add'); + $this->submitForm([ + 'name' => 'Test', + 'type' => 'test', + ], 'Save and manage fields'); + + // Add a new paragraphs field to the content type. + $this->clickLink('Add field'); + $this->submitForm([ + 'new_storage_type' => 'field_ui:entity_reference_revisions:paragraph', + 'label' => 'Paragraph', + 'field_name' => 'paragraph', + ], 'Save and continue'); + $this->submitForm([], 'Save field settings'); + + // Visit the "Manage form display" page of the new content type. + $this->drupalGet('admin/structure/types/manage/test/form-display'); + + // The selected widget should be "paragraphs". + $this->assertSession()->fieldValueEquals('fields[field_paragraph][type]', 'paragraphs'); + } + } diff --git a/web/modules/paragraphs/tests/src/Functional/ParagraphsUninstallTest.php b/web/modules/paragraphs/tests/src/Functional/ParagraphsUninstallTest.php index 37e98bdd783a27775e2d9f5d896ff7bb4df017f9..0c3478d53514b9130a71fbf373325e0fe82ea9fe 100644 --- a/web/modules/paragraphs/tests/src/Functional/ParagraphsUninstallTest.php +++ b/web/modules/paragraphs/tests/src/Functional/ParagraphsUninstallTest.php @@ -16,7 +16,7 @@ class ParagraphsUninstallTest extends BrowserTestBase { * * @var array */ - public static $modules = array('paragraphs_demo'); + protected static $modules = array('paragraphs_demo'); /** * {@inheritdoc} @@ -26,7 +26,7 @@ class ParagraphsUninstallTest extends BrowserTestBase { /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $admin_user = $this->drupalCreateUser(array( @@ -42,28 +42,31 @@ public function setUp() { public function testUninstall() { // Uninstall the module paragraphs_demo. - $this->drupalPostForm('admin/modules/uninstall', ['uninstall[paragraphs_demo]' => TRUE], t('Uninstall')); - $this->drupalPostForm(NULL, [], t('Uninstall')); + $this->drupalGet('admin/modules/uninstall'); + $this->submitForm(['uninstall[paragraphs_demo]' => TRUE], 'Uninstall'); + $this->submitForm([], 'Uninstall'); // Delete library data. $this->clickLink('Remove Paragraphs library items'); - $this->drupalPostForm(NULL, [], t('Delete all Paragraphs library items')); + $this->submitForm([], 'Delete all Paragraphs library items'); // Uninstall the library module. - $this->drupalPostForm('admin/modules/uninstall', ['uninstall[paragraphs_library]' => TRUE], t('Uninstall')); - $this->drupalPostForm(NULL, [], t('Uninstall')); + $this->drupalGet('admin/modules/uninstall'); + $this->submitForm(['uninstall[paragraphs_library]' => TRUE], 'Uninstall'); + $this->submitForm([], 'Uninstall'); // Delete paragraphs data. $this->clickLink('Remove Paragraphs'); - $this->drupalPostForm(NULL, [], t('Delete all Paragraphs')); + $this->submitForm([], 'Delete all Paragraphs'); // Uninstall the module paragraphs. - $this->drupalPostForm('admin/modules/uninstall', ['uninstall[paragraphs]' => TRUE], t('Uninstall')); - $this->drupalPostForm(NULL, [], t('Uninstall')); - $this->assertSession()->pageTextContains(t('The selected modules have been uninstalled.')); - $this->assertSession()->pageTextNotContains(t('Paragraphs demo')); - $this->assertSession()->pageTextNotContains(t('Paragraphs library')); - $this->assertSession()->pageTextNotContains(t('Paragraphs')); + $this->drupalGet('admin/modules/uninstall'); + $this->submitForm(['uninstall[paragraphs]' => TRUE], 'Uninstall'); + $this->submitForm([], 'Uninstall'); + $this->assertSession()->pageTextContains('The selected modules have been uninstalled.'); + $this->assertSession()->pageTextNotContains('Paragraphs demo'); + $this->assertSession()->pageTextNotContains('Paragraphs library'); + $this->assertSession()->pageTextNotContains('Paragraphs'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalWidgetButtonsTest.php b/web/modules/paragraphs/tests/src/Functional/ParagraphsWidgetButtonsTest.php similarity index 96% rename from web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalWidgetButtonsTest.php rename to web/modules/paragraphs/tests/src/Functional/ParagraphsWidgetButtonsTest.php index 3af2a108d6c0a09eb5eb7e3c9314a9da0ef67271..b50de5531cb729f829a99fe0177b1728163bb221 100644 --- a/web/modules/paragraphs/tests/src/Functional/ParagraphsExperimentalWidgetButtonsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/ParagraphsWidgetButtonsTest.php @@ -2,23 +2,23 @@ namespace Drupal\Tests\paragraphs\Functional; -use Drupal\Tests\paragraphs\Functional\Experimental\ParagraphsExperimentalTestBase; +use Drupal\Tests\paragraphs\Functional\WidgetStable\ParagraphsTestBase; use Drupal\paragraphs\Entity\Paragraph; use Drupal\node\Entity\Node; /** - * Tests paragraphs experimental widget buttons. + * Tests paragraphs stable widget buttons. * * @group paragraphs */ -class ParagraphsExperimentalWidgetButtonsTest extends ParagraphsExperimentalTestBase { +class ParagraphsWidgetButtonsTest extends ParagraphsTestBase { /** * Modules to enable. * * @var string[] */ - public static $modules = [ + protected static $modules = [ 'paragraphs_test', 'node', 'paragraphs', @@ -52,7 +52,7 @@ public function testAutocollapse() { // Add another Paragraph type so that there is no default Paragraphs type. $this->addParagraphsType('another_paragraph'); - // Check that the paragraphs field uses the experimental widget. + // Check that the paragraphs field uses the stable widget. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); $option = $this->assertSession()->optionExists('fields[field_paragraphs][type]', 'paragraphs'); $this->assertTrue($option->isSelected()); @@ -69,7 +69,7 @@ public function testAutocollapse() { 'field_paragraphs[0][subform][field_text][0][value]' => 'Fist paragraph', 'field_paragraphs[1][subform][field_text][0][value]' => 'Second paragraph', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('Autocollapse test node'); // Set the settings to "Open" edit mode without autocollapse. @@ -241,7 +241,7 @@ public function testClosedExtendNestedEditMode() { $this->setParagraphsWidgetSettings('paragraphed_test', 'field_paragraphs', $settings); - // Check that the paragraphs field uses the experimental widget on the + // Check that the paragraphs field uses the stable widget on the // paragraphed_test content type. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); $option = $this->assertSession()->optionExists('fields[field_paragraphs][type]', 'paragraphs'); @@ -250,7 +250,7 @@ public function testClosedExtendNestedEditMode() { // Check if the edit mode is set to "Closed, show nested". $this->assertSession()->pageTextContains('Edit mode: Closed, show nested'); - // Check that the paragraphs field uses the experimental widget on the + // Check that the paragraphs field uses the stable widget on the // container_paragraph paragraph type. $this->drupalGet('admin/structure/paragraphs_type/container_paragraph/form-display'); $option = $this->assertSession()->optionExists('fields[field_paragraphs][type]', 'paragraphs'); @@ -492,7 +492,8 @@ public function testAddModeSelect() { 'settings[handler_settings][negate]' => 0, 'settings[handler_settings][target_bundles_drag_drop][text][enabled]' => 1, ]; - $this->drupalPostForm('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.paragraphs', $edit, 'Save settings'); + $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.paragraphs'); + $this->submitForm($edit, 'Save settings'); $this->drupalGet('node/add/paragraphed_test'); $this->assertSession()->fieldNotExists('paragraphs[add_more][add_more_select]'); @@ -501,7 +502,7 @@ public function testAddModeSelect() { 'title[0][value]' => 'Demo text title', 'paragraphs[0][subform][field_text_demo][0][value]' => 'Demo text for the detail page', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Demo text for the detail page'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAccessTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAccessTest.php similarity index 85% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAccessTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAccessTest.php index 90530233e350c6bc7dcc229011e042289d9a71ab..8dacd53c6b5085d62d9dab6c870ab021eeb20d35 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAccessTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAccessTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\image\Entity\ImageStyle; @@ -22,7 +22,7 @@ class ParagraphsAccessTest extends ParagraphsTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'content_translation', 'image', 'field', @@ -35,7 +35,7 @@ class ParagraphsAccessTest extends ParagraphsTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); ConfigurableLanguage::create(['id' => 'de', 'label' => '1German'])->save(); ConfigurableLanguage::create(['id' => 'fr', 'label' => '2French'])->save(); @@ -70,7 +70,8 @@ protected function setUp() { 'settings[paragraph][text_image][fields][field_text_demo]' => TRUE, 'settings[node][paragraphed_content_demo][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); $view_display = \Drupal::service('entity_display.repository')->getViewDisplay('paragraph', 'images'); $view_display->setComponent('field_images_demo', ['settings' => ['image_style' => 'medium']]); @@ -103,9 +104,10 @@ public function testParagraphAccessCheck() { $edit = array( 'settings[uri_scheme]' => 'private', ); - $this->drupalPostForm('admin/structure/paragraphs_type/images/fields/paragraph.images.field_images_demo/storage', $edit, t('Save field settings')); + $this->drupalGet('admin/structure/paragraphs_type/images/fields/paragraph.images.field_images_demo/storage'); + $this->submitForm($edit, 'Save field settings'); - // Set the form display to classic. + // Set the form display to legacy. $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default') ->setComponent('field_paragraphs_demo', ['type' => 'entity_reference_paragraphs']); $form_display->save(); @@ -114,7 +116,7 @@ public function testParagraphAccessCheck() { $this->drupalGet('node/add/paragraphed_content_demo'); // Add a new paragraphs images item. - $this->drupalPostForm(NULL, NULL, t('Add images')); + $this->submitForm([], 'Add images'); $images = $this->getTestFiles('image'); @@ -134,19 +136,19 @@ public function testParagraphAccessCheck() { 'files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path, ); - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); $edit = array( 'files[field_paragraphs_demo_0_subform_field_images_demo_1][]' => $file_path_2, ); - $this->drupalPostForm(NULL, $edit, t('Preview')); + $this->submitForm($edit, 'Preview'); $image_style = ImageStyle::load('medium'); $img1_url = $image_style->buildUrl('private://' . date('Y-m') . '/privateImage.jpg'); - $image_url = file_url_transform_relative($img1_url); + $image_url = \Drupal::service('file_url_generator')->transformRelative($img1_url); $this->assertSession()->responseContains($image_url); - $this->clickLink(t('Back to content editing')); - $this->drupalPostForm(NULL, [], t('Save')); + $this->clickLink('Back to content editing'); + $this->submitForm([], 'Save'); $node = $this->drupalGetNodeByTitle('Security test node'); @@ -164,7 +166,7 @@ public function testParagraphAccessCheck() { // @todo Requesting the same $img_url again triggers a caching problem on // drupal.org test bot, thus we request a different file here. $img_url = $image_style->buildUrl('private://' . date('Y-m') . '/privateImage2.jpg'); - $image_url = file_url_transform_relative($img_url); + $image_url = \Drupal::service('file_url_generator')->transformRelative($img_url); // Check the text and image after publish. Anonymous should not see content. $this->assertSession()->responseNotContains($image_url); @@ -175,21 +177,21 @@ public function testParagraphAccessCheck() { $this->loginAsAdmin($admin_user); // Create a new demo node. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text')); + $this->submitForm([], 'Add text'); $this->assertSession()->pageTextContains('Text'); $edit = [ 'title[0][value]' => 'delete_permissions', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Edit the node. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Check the remove button is present. $this->assertNotNull($this->xpath('//*[@name="field_paragraphs_demo_0_remove"]')); // Delete the Paragraph and save. - $this->drupalPostForm(NULL, [], 'field_paragraphs_demo_0_remove'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_demo_0_confirm_remove'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_demo_0_remove'); + $this->submitForm([], 'field_paragraphs_demo_0_confirm_remove'); + $this->submitForm([], 'Save'); $node = $this->getNodeByTitle('delete_permissions'); $this->assertSession()->addressEquals('node/' . $node->id()); } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAddModesTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAddModesTest.php similarity index 95% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAddModesTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAddModesTest.php index 4829e60e246062ff69b5f1e149c8d24c0ebb110d..f3c13c3fa2db83d44a626305428a408e50b47016 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAddModesTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAddModesTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\paragraphs\Entity\ParagraphsType; @@ -20,11 +20,11 @@ public function testNoDefaultValue() { // Edit the field. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields'); - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Check that the current field does not allow to add default values. $this->assertSession()->pageTextContains('No widget available for: paragraphs_field.'); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->submitForm([], 'Save settings'); $this->assertSession()->pageTextContains('Saved paragraphs_field configuration.'); $this->assertSession()->statusCodeEquals(200); } @@ -38,8 +38,8 @@ public function testEmptyAllowedTypes() { // Edit the field and save when there are no Paragraphs types available. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields'); - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->clickLink('Edit'); + $this->submitForm([], 'Save settings'); $this->assertSession()->pageTextContains('Saved paragraphs configuration.'); } @@ -55,7 +55,7 @@ public function testDropDownMode() { $this->addParagraphedContentType('paragraphed_test', 'paragraphs', 'entity_reference_paragraphs'); // Enter to the field config since the weight is set through the form. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.paragraphs'); - $this->drupalPostForm(NULL, [], 'Save settings'); + $this->submitForm([], 'Save settings'); $this->setAddMode('paragraphed_test', 'paragraphs', 'dropdown'); @@ -89,7 +89,7 @@ public function testSelectMode() { $this->addParagraphedContentType('paragraphed_test', 'paragraphs', 'entity_reference_paragraphs'); // Enter to the field config since the weight is set through the form. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.paragraphs'); - $this->drupalPostForm(NULL, [], 'Save settings'); + $this->submitForm([], 'Save settings'); $this->setAddMode('paragraphed_test', 'paragraphs', 'select'); @@ -187,7 +187,7 @@ public function testSettingDefaultParagraphType() { $this->setDefaultParagraphType('paragraphed_test', 'paragraphs', 'paragraphs_settings_edit', 'text_image'); $this->removeDefaultParagraphType('paragraphed_test'); $edit = ['title[0][value]' => 'New Host']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/1/edit'); $this->assertSession()->pageTextContains('No Paragraph added yet.'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAdministrationTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAdministrationTest.php similarity index 72% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAdministrationTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAdministrationTest.php index 30e8ba6496e04afc5f17e92e6d33ecbb93b2ab5c..6244c048cdde22e1bf97df5924cdbd08f5be3c97 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsAdministrationTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsAdministrationTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\paragraphs\Entity\Paragraph; @@ -16,7 +16,7 @@ class ParagraphsAdministrationTest extends ParagraphsTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'image', 'file', 'views' @@ -25,7 +25,7 @@ class ParagraphsAdministrationTest extends ParagraphsTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); // Create paragraphs content type. $this->drupalCreateContentType(array('type' => 'paragraphs', 'name' => 'Paragraphs')); @@ -57,20 +57,20 @@ public function testParagraphsRevisions() { )); // Configure article fields. $this->drupalGet('admin/structure/types/manage/paragraphs/fields'); - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, array('fields[field_paragraphs][type]' => 'entity_reference_paragraphs'), t('Save')); + $this->clickLink('Manage form display'); + $this->submitForm(array('fields[field_paragraphs][type]' => 'entity_reference_paragraphs'), 'Save'); // Create node with our paragraphs. $this->drupalGet('node/add/paragraphs'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); $edit = [ 'title[0][value]' => 'TEST TITEL', 'field_paragraphs[0][subform][field_text][0][value]' => 'Test text 1', 'field_paragraphs[1][subform][field_text][0][value]' => 'Test text 2', 'status[value]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('TEST TITEL'); $paragraph1 = $node->field_paragraphs[0]->target_id; @@ -84,7 +84,8 @@ public function testParagraphsRevisions() { 'field_paragraphs[0][subform][field_text][0][value]' => 'Foo Bar 1', 'revision' => FALSE, ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm($edit, 'Save'); $this->countRevisions($node, $paragraph1, $paragraph2, 1); @@ -95,7 +96,8 @@ public function testParagraphsRevisions() { 'field_paragraphs[0][subform][field_text][0][value]' => 'Foo Bar 2', 'revision' => TRUE, ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm($edit, 'Save'); $this->countRevisions($node, $paragraph1, $paragraph2, 2); @@ -111,8 +113,8 @@ public function testParagraphsRevisions() { // Make sure two revisions available. $this->assertEquals(count($rows), 2); // Revert to the old version. - $this->clickLink(t('Revert')); - $this->drupalPostForm(NULL, [], t('Revert')); + $this->clickLink('Revert'); + $this->submitForm([], 'Revert'); $this->drupalGet('node/' . $node->id()); // Assert the node has been reverted. $this->assertSession()->pageTextNotContains('Foo Bar 2'); @@ -148,14 +150,14 @@ public function testParagraphsCreation() { 'label' => 'Paragraph', 'field_name' => 'paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Save and continue'); - $this->drupalPostForm(NULL, [], 'Save field settings'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); $this->assertSession()->linkByHrefExists('admin/structure/paragraphs_type/add'); $this->clickLink('here'); $this->assertSession()->addressEquals('admin/structure/paragraphs_type/add'); $this->drupalGet('admin/structure/paragraphs_type'); - $this->clickLink(t('Add paragraph type')); + $this->clickLink('Add paragraph type'); $this->assertSession()->titleEquals('Add Paragraphs type | Drupal'); // Create paragraph type text + image. $this->addParagraphsType('text_image'); @@ -176,10 +178,10 @@ public function testParagraphsCreation() { ), array()); // Change the add more button to select mode. - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][type]' => 'entity_reference_paragraphs'], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][add_mode]' => 'select'], t('Update')); - $this->drupalPostForm(NULL, [], t('Save')); + $this->clickLink('Manage form display'); + $this->submitForm(['fields[field_paragraphs][type]' => 'entity_reference_paragraphs'], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][add_mode]' => 'select'], 'Update'); + $this->submitForm([], 'Save'); // Create paragraph type image. $this->addParagraphsType('image'); @@ -194,7 +196,7 @@ public function testParagraphsCreation() { $this->assertSession()->pageTextContains('text_image'); $this->assertSession()->pageTextContains('image'); // Make sure there is an edit link for each type. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Make sure the field UI appears. $this->assertSession()->linkExists('Manage fields'); $this->assertSession()->linkExists('Manage form display'); @@ -206,17 +208,17 @@ public function testParagraphsCreation() { $field_name = 'field_paragraphs'; // Click on the widget settings button to open the widget settings form. - $this->drupalPostForm(NULL, array(), $field_name . "_settings_edit"); + $this->submitForm(array(), $field_name . "_settings_edit"); // Enable setting. $edit = array('fields[' . $field_name . '][settings_edit_form][settings][add_mode]' => 'button'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check if the setting is stored. $this->drupalGet('admin/structure/types/manage/article/form-display'); - $this->assertSession()->pageTextContains('Add mode: Buttons', 'Checking the settings value.'); + $this->assertSession()->pageTextContains('Add mode: Buttons'); - $this->drupalPostForm(NULL, array(), $field_name . "_settings_edit"); + $this->submitForm(array(), $field_name . "_settings_edit"); // Assert the 'Buttons' option is selected. $add_mode_option = $this->assertSession()->optionExists('edit-fields-field-paragraphs-settings-edit-form-settings-add-mode', 'button'); $this->assertTrue($add_mode_option->hasAttribute('selected'), 'Updated value correctly.'); @@ -225,10 +227,10 @@ public function testParagraphsCreation() { $this->drupalGet('node/add/article'); // Checking changes on article. - $this->assertSession()->responseContains('<div class="paragraphs-dropbutton-wrapper"><input', 'Updated value in article.'); + $this->assertSession()->responseContains('<div class="paragraphs-dropbutton-wrapper"><input'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_image_add_more'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_image_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_image_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_image_add_more'); // Upload some images. $files = $this->getTestFiles('image'); @@ -241,34 +243,32 @@ public function testParagraphsCreation() { 'field_paragraphs[1][subform][field_text][0][value]' => 'Test text 2', 'files[field_paragraphs_1_subform_field_image_0]' => $file_system->realpath($files[1]->uri), ); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('article Test article has been created.'); $node = $this->drupalGetNodeByTitle('Test article'); - $img1_url = file_create_url(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[0]->filename)); - $img2_url = file_create_url(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[1]->filename)); - $img1_size = filesize($files[0]->uri); - $img2_size = filesize($files[1]->uri); - $img1_mime = \Drupal::service('file.mime_type.guesser')->guess($files[0]->uri); - $img2_mime = \Drupal::service('file.mime_type.guesser')->guess($files[1]->uri); + $img1_url = \Drupal::service('file_url_generator')->generateString(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[0]->filename)); + $img2_url = \Drupal::service('file_url_generator')->generateString(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[1]->filename)); + $img1_mime = \Drupal::service('file.mime_type.guesser')->guessMimeType($files[0]->uri); + $img2_mime = \Drupal::service('file.mime_type.guesser')->guessMimeType($files[1]->uri); // Check the text and image after publish. $this->assertSession()->pageTextContains('Test text 1'); - $this->assertSession()->responseContains('<img src="' . file_url_transform_relative($img1_url)); + $this->assertSession()->elementExists('css', 'img[src="' . $img1_url . '"]'); $this->assertSession()->pageTextContains('Test text 2'); - $this->assertSession()->responseContains('<img src="' . file_url_transform_relative($img2_url)); + $this->assertSession()->elementExists('css', 'img[src="' . $img2_url . '"]'); // Tests for "Edit mode" settings. // Test for closed setting. $this->drupalGet('admin/structure/types/manage/article/form-display'); // Click on the widget settings button to open the widget settings form. - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->submitForm(array(), "field_paragraphs_settings_edit"); // Enable setting. $edit = array('fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check if the setting is stored. - $this->assertSession()->pageTextContains('Edit mode: Closed', 'Checking the settings value.'); - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->assertSession()->pageTextContains('Edit mode: Closed'); + $this->submitForm(array(), "field_paragraphs_settings_edit"); // Assert the 'Closed' option is selected. $edit_mode_option = $this->assertSession()->optionExists('edit-fields-field-paragraphs-settings-edit-form-settings-edit-mode', 'closed'); $this->assertTrue($edit_mode_option->hasAttribute('selected'), 'Updated value correctly.'); @@ -281,10 +281,10 @@ public function testParagraphsCreation() { // Test for preview option. $this->drupalGet('admin/structure/types/manage/article/form-display'); - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->submitForm(array(), "field_paragraphs_settings_edit"); $edit = array('fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'preview'); - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains('Edit mode: Preview', 'Checking the settings value.'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('Edit mode: Preview'); $this->drupalGet('node/1/edit'); // The texts in the paragraphs should be visible. $this->assertSession()->responseNotContains('field_paragraphs[0][subform][field_text][0][value]'); @@ -294,13 +294,13 @@ public function testParagraphsCreation() { // Test for open option. $this->drupalGet('admin/structure/types/manage/article/form-display'); - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->submitForm(array(), "field_paragraphs_settings_edit"); // Assert the 'Preview' option is selected. $edit_mode_option = $this->assertSession()->optionExists('edit-fields-field-paragraphs-settings-edit-form-settings-edit-mode', 'preview'); $this->assertTrue($edit_mode_option->hasAttribute('selected'), 'Updated value correctly.'); // Restore the value to Open for next test. $edit = array('fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'open'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/1/edit'); // The textareas for paragraphs should be visible. $this->assertSession()->responseContains('field_paragraphs[0][subform][field_text][0][value]'); @@ -313,34 +313,34 @@ public function testParagraphsCreation() { $this->drupalGet('node/' . $node->id() . '/edit'); // Check both paragraphs in edit page. $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', 'Test text 1'); - $this->assertSession()->responseContains('<a href="' . $img1_url . '" type="' . $img1_mime . '; length=' . $img1_size . '">' . $files[0]->filename . '</a>'); + $this->assertSession()->elementTextContains('css', 'A[href="' . $img1_url . '"][type^="' . $img1_mime . '"]', $files[0]->filename); $this->assertSession()->fieldValueEquals('field_paragraphs[1][subform][field_text][0][value]', 'Test text 2'); - $this->assertSession()->responseContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementTextContains('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]', $files[1]->filename); // Remove 2nd paragraph. $this->getSession()->getPage()->find('css', '[name="field_paragraphs_1_remove"]')->press(); // Confirm the removal. - $this->drupalPostForm(NULL, [], t('Confirm removal')); + $this->submitForm([], 'Confirm removal'); $this->assertSession()->fieldNotExists('field_paragraphs[1][subform][field_text][0][value]'); - $this->assertSession()->responseNotContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementNotExists('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]'); // Assert the paragraph is not deleted unless the user saves the node. $this->drupalGet('node/' . $node->id() . '/edit'); - $this->assertSession()->responseContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementTextContains('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]', $files[1]->filename); // Remove the second paragraph. $this->getSession()->getPage()->find('css', '[name="field_paragraphs_1_remove"]')->press(); // Confirm the removal. - $this->drupalPostForm(NULL, [], t('Confirm removal')); - $this->assertSession()->responseNotContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->submitForm([], 'Confirm removal'); + $this->assertSession()->elementNotExists('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]'); $edit = [ 'field_paragraphs[0][subform][field_image][0][alt]' => 'test_alt', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Assert the paragraph is deleted after the user saves the node. $this->drupalGet('node/' . $node->id() . '/edit'); - $this->assertSession()->responseNotContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementNotExists('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]'); // Delete the node. - $this->clickLink(t('Delete')); - $this->drupalPostForm(NULL, NULL, t('Delete')); + $this->clickLink('Delete'); + $this->submitForm([], 'Delete'); $this->assertSession()->pageTextContains('Test article has been deleted.'); // Check if the publish/unpublish option works. @@ -350,38 +350,38 @@ public function testParagraphsCreation() { 'fields[status][region]' => 'content', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, NULL, t('Add text_image')); + $this->submitForm([], 'Add text_image'); $this->assertSession()->responseContains('edit-field-paragraphs-0-subform-status-value'); $edit = [ 'title[0][value]' => 'Example publish/unpublish', 'field_paragraphs[0][subform][field_text][0][value]' => 'Example published and unpublished', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains(t('Example published and unpublished')); - $this->clickLink(t('Edit')); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('Example published and unpublished'); + $this->clickLink('Edit'); $edit = [ 'field_paragraphs[0][subform][status][value]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextNotContains(t('Example published and unpublished')); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextNotContains('Example published and unpublished'); // Set the fields as required. $this->drupalGet('admin/structure/types/manage/article/fields'); $this->clickLink('Edit', 1); - $this->drupalPostForm(NULL, ['preview_mode' => '1'], t('Save content type')); + $this->submitForm(['preview_mode' => '1'], 'Save content type'); $this->drupalGet('admin/structure/paragraphs_type/nested_test/fields'); $this->clickLink('Edit'); - $this->drupalPostForm(NULL, ['required' => TRUE], t('Save settings')); + $this->submitForm(['required' => TRUE], 'Save settings'); // Add a new article. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_nested_test_add_more'); + $this->submitForm([], 'field_paragraphs_nested_test_add_more'); $edit = [ 'field_paragraphs[0][subform][field_paragraphs][add_more][add_more_select]' => 'image', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); + $this->submitForm($edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); // Test the new field is displayed. $this->assertSession()->fieldExists('files[field_paragraphs_0_subform_field_paragraphs_0_subform_field_image_only_0]'); @@ -390,11 +390,11 @@ public function testParagraphsCreation() { 'title[0][value]' => 'test required', 'files[field_paragraphs_0_subform_field_paragraphs_0_subform_field_image_only_0]' => $file_system->realpath($files[2]->uri), ); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $edit = [ 'field_paragraphs[0][subform][field_paragraphs][0][subform][field_image_only][0][alt]' => 'Alternative_text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('test required has been created.'); $this->assertSession()->responseNotContains('This value should not be null.'); @@ -412,43 +412,45 @@ public function testParagraphsCreation() { 'label' => 'unsupported field', 'field_name' => 'unsupportedfield', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); + $this->submitForm($edit, 'Save and continue'); $this->assertSession()->optionNotExists('edit-settings-target-type', 'paragraph'); // Test that all Paragraph types can be referenced if none is selected. $this->addParagraphsType('nested_double_test'); static::fieldUIAddExistingField('admin/structure/paragraphs_type/nested_double_test', 'field_paragraphs', 'paragraphs_1'); - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, [], 'Save'); - //$this->drupalPostForm(NULL, array('fields[field_paragraphs][type]' => 'entity_reference_revisions_entity_view'), t('Save')); + $this->clickLink('Manage form display'); + $this->submitForm([], 'Save'); + //$this->drupalPostForm(NULL, array('fields[field_paragraphs][type]' => 'entity_reference_revisions_entity_view'), 'Save'); static::fieldUIAddNewField('admin/structure/paragraphs_type/nested_double_test', 'paragraphs_2', 'paragraphs_2', 'entity_reference_revisions', array( 'settings[target_type]' => 'paragraph', 'cardinality' => '-1', ), array()); - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, [], 'Save'); - $this->drupalPostForm('node/add/article', [], 'field_paragraphs_nested_test_add_more'); + $this->clickLink('Manage form display'); + $this->submitForm([], 'Save'); + $this->drupalGet('node/add/article'); + $this->submitForm([], 'field_paragraphs_nested_test_add_more'); $edit = [ 'field_paragraphs[0][subform][field_paragraphs][add_more][add_more_select]' => 'nested_double_test', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_paragraphs_0_subform_field_paragraphs_image_add_more'); + $this->submitForm($edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_paragraphs_0_subform_field_paragraphs_image_add_more'); $edit = array( 'title[0][value]' => 'Nested twins', ); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Nested twins has been created.'); $this->assertSession()->pageTextNotContains('This entity (paragraph: ) cannot be referenced.'); // Set the fields as not required. $this->drupalGet('admin/structure/types/manage/article/fields'); $this->clickLink('Edit', 1); - $this->drupalPostForm(NULL, ['required' => FALSE], t('Save settings')); + $this->submitForm(['required' => FALSE], 'Save settings'); // Set the Paragraph field edit mode to 'Closed'. - $this->drupalPostForm('admin/structure/types/manage/article/form-display', [], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed'], t('Update')); - $this->drupalPostForm(NULL, [], t('Save')); + $this->drupalGet('admin/structure/types/manage/article/form-display'); + $this->submitForm([], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed'], 'Update'); + $this->submitForm([], 'Save'); $this->addParagraphsType('node_test'); @@ -463,17 +465,18 @@ public function testParagraphsCreation() { $node = $this->drupalGetNodeByTitle('Nested twins'); // Create a node with a reference in a Paragraph. - $this->drupalPostForm('node/add/article', [], 'field_paragraphs_node_test_add_more'); + $this->drupalGet('node/add/article'); + $this->submitForm([], 'field_paragraphs_node_test_add_more'); \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions(); $edit = [ 'field_paragraphs[0][subform][field_entity_reference][0][target_id]' => $node->label() . ' (' . $node->id() . ')', 'title[0][value]' => 'choke test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Delete the referenced node. $node->delete(); // Edit the node with the reference. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Since we have validation error (reference to deleted node), paragraph is // by default in edit mode. $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_entity_reference][0][target_id]'); @@ -481,49 +484,51 @@ public function testParagraphsCreation() { // Assert the validation error message. $this->assertSession()->pageTextContains('The referenced entity (node: 4) does not exist'); // Triggering unrelated button, assert that error message is still present. - $this->drupalPostForm(NULL, [], t('Add another item')); + $this->submitForm([], 'Add another item'); $this->assertSession()->pageTextContains('The referenced entity (node: 4) does not exist'); $this->assertSession()->pageTextContains('Entity reference (value 1) field is required.'); // Try to collapse with an invalid reference. - $this->drupalPostForm(NULL, ['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => 'foo'], 'field_paragraphs_0_collapse'); + $this->submitForm(['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => 'foo'], 'field_paragraphs_0_collapse'); // Paragraph should be still in edit mode. $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_entity_reference][0][target_id]'); $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_entity_reference][1][target_id]'); - $this->drupalPostForm(NULL, [], t('Add another item')); + $this->submitForm([], 'Add another item'); // Assert the validation message. - $this->assertSession()->pageTextContains('There are no entities matching "foo".'); + $this->assertSession()->pageTextMatches('/There are no (entities|content items) matching "foo"./'); // Attempt to remove the Paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_remove'); + $this->submitForm([], 'field_paragraphs_0_remove'); $elements = $this->xpath('//*[@name="field_paragraphs_0_confirm_remove"]'); $this->assertNotEmpty($elements, "'Confirm removal' button appears."); // Restore the Paragraph and fix the broken reference. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_restore'); + $this->submitForm([], 'field_paragraphs_0_restore'); $node = $this->drupalGetNodeByTitle('Example publish/unpublish'); $edit = ['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => $node->label() . ' (' . $node->id() . ')']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('choke test has been updated.'); $this->assertSession()->linkExists('Example publish/unpublish'); // Delete the new referenced node. $node->delete(); // Set the Paragraph field edit mode to 'Preview'. - $this->drupalPostForm('admin/structure/types/manage/article/form-display', [], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'preview'], t('Update')); - $this->drupalPostForm(NULL, [], t('Save')); + $this->drupalGet('admin/structure/types/manage/article/form-display'); + $this->submitForm([], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'preview'], 'Update'); + $this->submitForm([], 'Save'); $node = $this->drupalGetNodeByTitle('choke test'); // Attempt to edit the Paragraph. - $this->drupalPostForm('node/' . $node->id() . '/edit', [], 'field_paragraphs_0_edit'); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->SubmitForm([], 'field_paragraphs_0_edit'); // Try to save with an invalid reference. $edit = ['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => 'foo']; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains('There are no entities matching "foo".'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextMatches('/There are no (entities|content items) matching "foo"./'); // Remove the Paragraph and save the node. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_remove'); + $this->submitForm([], 'field_paragraphs_0_remove'); $elements = $this->xpath('//*[@name="field_paragraphs_0_confirm_remove"]'); $this->assertNotEmpty($elements, "'Confirm removal' button appears."); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_confirm_remove'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_0_confirm_remove'); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('choke test has been updated.'); // Verify that the text displayed is correct when no paragraph has been @@ -541,10 +546,27 @@ public function testParagraphsCreation() { * Helper function for revision counting. */ private function countRevisions($node, $paragraph1, $paragraph2, $revisions_count) { - $node_revisions_count = \Drupal::entityQuery('node')->condition('nid', $node->id())->allRevisions()->count()->execute(); - $this->assertEquals($node_revisions_count, $revisions_count); - $this->assertEquals(\Drupal::entityQuery('paragraph')->condition('id', $paragraph1)->allRevisions()->count()->execute(), $revisions_count); - $this->assertEquals(\Drupal::entityQuery('paragraph')->condition('id', $paragraph2)->allRevisions()->count()->execute(), $revisions_count); + $node_revisions_count = \Drupal::entityQuery('node') + ->condition('nid', $node->id()) + ->accessCheck(TRUE) + ->allRevisions() + ->count() + ->execute(); + $this->assertEquals($revisions_count, $node_revisions_count); + $paragraph1_revisions_count =\Drupal::entityQuery('paragraph') + ->condition('id', $paragraph1) + ->accessCheck(TRUE) + ->allRevisions() + ->count() + ->execute(); + $this->assertEquals($revisions_count, $paragraph1_revisions_count); + $paragraph2_revisions_count =\Drupal::entityQuery('paragraph') + ->condition('id', $paragraph2) + ->accessCheck(TRUE) + ->allRevisions() + ->count() + ->execute(); + $this->assertEquals($revisions_count, $paragraph2_revisions_count); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsConfigTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsConfigTest.php similarity index 85% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsConfigTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsConfigTest.php index e0cfb8f994dbada77b32c042ae02895ebfc542bd..c4e8aba8cd5769b47d4c08bc91168d4d1ee50fc4 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsConfigTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsConfigTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\node\Entity\NodeType; @@ -17,7 +17,7 @@ class ParagraphsConfigTest extends ParagraphsTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'content_translation', ); @@ -48,19 +48,21 @@ public function testFieldTranslationDisabled() { 'settings[node][paragraphed_test][translatable]' => TRUE, 'settings[node][paragraphed_test][fields][paragraphs_field]' => FALSE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); // Create a node with a paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'paragraphs_field_paragraph_type_test_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'paragraphs_field_paragraph_type_test_add_more'); $edit = ['title[0][value]' => 'paragraphed_title']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Attempt to add a translation. $node = $this->drupalGetNodeByTitle('paragraphed_title'); $this->drupalGet('node/' . $node->id() . '/translations'); - $this->clickLink(t('Add')); + $this->clickLink('Add'); // Save the translation. - $this->drupalPostForm(NULL, [], t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('paragraphed_test paragraphed_title has been updated.'); } @@ -95,7 +97,8 @@ public function testContentTranslationForm() { 'settings[node][paragraphed_test][translatable]' => TRUE, 'settings[node][paragraphed_test][fields][paragraphs_field]' => FALSE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); // Check error message is still not displayed. $this->drupalGet('admin/config/regional/content-language'); @@ -112,7 +115,8 @@ public function testContentTranslationForm() { 'settings[node][paragraphed_test][translatable]' => TRUE, 'settings[node][paragraphed_test][fields][paragraphs_field]' => TRUE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); // Check content type field management error. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.paragraphs_field'); @@ -126,8 +130,8 @@ public function testContentTranslationForm() { 'label' => 'new_no_paragraphs_field', 'field_name' => 'new_no_paragraphs_field', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); $this->assertSession()->pageTextNotContains('Paragraphs fields do not support translation.'); $this->assertSession()->responseNotContains('<div class="messages messages--warning'); } @@ -148,7 +152,7 @@ public function testRequiredParagraphsField() { $edit = [ 'required' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, 'Save settings'); + $this->submitForm($edit, 'Save settings'); $this->assertSession()->pageTextContains('Saved paragraphs configuration.'); // Assert that the field is displayed in the form as required. @@ -157,10 +161,10 @@ public function testRequiredParagraphsField() { $edit = [ 'title[0][value]' => 'test_title', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphs field is required.'); - $this->drupalPostForm(NULL, [], 'paragraphs_paragraph_type_test_add_more'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm([], 'paragraphs_paragraph_type_test_add_more'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test test_title has been created.'); } @@ -206,12 +210,12 @@ public function testIncludedParagraphTypes() { 'settings[handler_settings][negate]' => 0, 'settings[handler_settings][target_bundles_drag_drop][paragraph_type_test][enabled]' => 1, ]; - $this->drupalPostForm(NULL, $edit, 'Save settings'); + $this->submitForm($edit, 'Save settings'); $this->assertSession()->pageTextContains('Saved paragraphs configuration.'); $this->drupalGet('node/add/paragraphed_test'); - $this->assertSession()->pageTextContains('Add paragraph_type_test'); - $this->assertSession()->pageTextNotContains('Add text'); + $this->assertSession()->buttonExists('Add paragraph_type_test'); + $this->assertSession()->responseNotContains('Add text'); } /** @@ -229,12 +233,12 @@ public function testExcludedParagraphTypes() { 'settings[handler_settings][negate]' => 1, 'settings[handler_settings][target_bundles_drag_drop][text][enabled]' => 1, ]; - $this->drupalPostForm(NULL, $edit, 'Save settings'); + $this->submitForm($edit, 'Save settings'); $this->assertSession()->pageTextContains('Saved paragraphs configuration.'); $this->drupalGet('node/add/paragraphed_test'); - $this->assertSession()->pageTextContains('Add paragraph_type_test'); - $this->assertSession()->pageTextNotContains('Add text'); + $this->assertSession()->buttonExists('Add paragraph_type_test'); + $this->assertSession()->responseNotContains('Add text'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsContactTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsContactTest.php similarity index 83% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsContactTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsContactTest.php index cc19084ea2608385d03119f41a00c654a068d142..6d11b75605c77a927fab04b5d10d7119e1087cac 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsContactTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsContactTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\contact\Entity\ContactForm; @@ -16,7 +16,7 @@ class ParagraphsContactTest extends ParagraphsTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'contact', ); @@ -40,10 +40,10 @@ public function testContactForm() { // Add a paragraph to the contact form. $this->drupalGet('contact/test_contact_form'); - $this->drupalPostForm(NULL, [], 'paragraphs_paragraphs_contact_add_more'); + $this->submitForm([], 'paragraphs_paragraphs_contact_add_more'); // Check that the paragraph is displayed. $this->assertSession()->pageTextContains('paragraphs_contact'); - $this->drupalPostForm(NULL, [], 'paragraphs_0_remove'); + $this->submitForm([], 'paragraphs_0_remove'); $this->assertSession()->pageTextContains('Deleted Paragraph: paragraphs_contact'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsEditModesTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsEditModesTest.php similarity index 76% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsEditModesTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsEditModesTest.php index 724a35ea99cf0d6c86931fd59be3d65c39bf8c69..e67b0bb9c48b7268086dc8020b2af5f10094c2f3 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsEditModesTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsEditModesTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; /** * Tests paragraphs edit modes. @@ -14,7 +14,7 @@ class ParagraphsEditModesTest extends ParagraphsTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'image', 'block_field', ]; @@ -38,13 +38,14 @@ public function testCollapsedSummary() { // Set edit mode to closed. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); - $this->drupalPostForm(NULL, [], "field_paragraphs_settings_edit"); + $this->submitForm([], "field_paragraphs_settings_edit"); $edit = ['fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Add a paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_image_text_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_title_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_image_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_title_add_more'); $files = $this->getTestFiles('image'); $file_system = \Drupal::service('file_system'); @@ -56,29 +57,29 @@ public function testCollapsedSummary() { 'files[field_paragraphs_0_subform_field_image_0]' => $file_system->realpath($files[0]->uri), 'field_paragraphs[1][subform][field_title][0][value]' => 'Title example', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Assert the summary is correctly generated. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->responseContains('<span class="summary-content">' . $files[0]->filename . '</span>, <span class="summary-content">text_summary</span>'); $this->assertSession()->responseContains('<span class="summary-content">Title example'); // Edit and remove alternative text. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); $edit = [ 'field_paragraphs[0][subform][field_image][0][alt]' => 'alternative_text_summary', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); // Assert the summary is correctly generated. $this->assertSession()->responseContains('<span class="summary-content">alternative_text_summary</span>, <span class="summary-content">text_summary</span>'); // Remove image. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_image_0_remove_button'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_subform_field_image_0_remove_button'); + $this->submitForm([], 'Save'); // Assert the summary is correctly generated. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->responseContains('<span class="summary-content">text_summary'); // Add a Block Paragraphs type. @@ -87,13 +88,13 @@ public function testCollapsedSummary() { // Test the summary of a Block field. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_block_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_block_paragraph_add_more'); $edit = [ 'title[0][value]' => 'Node with a Block Paragraph', 'field_paragraphs[0][subform][field_block][0][plugin_id]' => 'system_breadcrumb_block', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->clickLink(t('Edit')); + $this->submitForm($edit, 'Save'); + $this->clickLink('Edit'); $this->assertSession()->responseContains('<span class="summary-content">Breadcrumbs'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php similarity index 74% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php index 2a0e2edb5dea20146e7823d430644e14eb47d45f..fa1b9afce4ba5a0b781e2a2505994421fc8cf53a 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; /** * Tests the translation of heavily nested / specialized setup. @@ -14,7 +14,7 @@ class ParagraphsEntityTranslationWithNonTranslatableParagraphs extends Paragraph * * @var array */ - public static $modules = [ + protected static $modules = [ 'language', 'content_translation', ]; @@ -22,7 +22,7 @@ class ParagraphsEntityTranslationWithNonTranslatableParagraphs extends Paragraph /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->admin_user = $this->drupalCreateUser([], NULL, TRUE); @@ -32,11 +32,13 @@ protected function setUp() { $edit = array( 'predefined_langcode' => 'de', ); - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + $this->drupalGet('admin/config/regional/language/add'); + $this->submitForm($edit, 'Add language'); $edit = array( 'predefined_langcode' => 'fr', ); - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + $this->drupalGet('admin/config/regional/language/add'); + $this->submitForm($edit, 'Add language'); // Create article content type with a paragraphs field. $this->addParagraphedContentType('article', 'field_paragraphs'); @@ -45,7 +47,8 @@ protected function setUp() { $edit = array( 'language_configuration[content_translation]' => TRUE, ); - $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type')); + $this->drupalGet('admin/structure/types/manage/article'); + $this->submitForm($edit, 'Save content type'); $this->drupalGet('admin/structure/types/manage/article'); // Ensue the paragraphs field itself isn't translatable - this would be a @@ -53,7 +56,8 @@ protected function setUp() { $edit = array( 'translatable' => FALSE, ); - $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_paragraphs', $edit, t('Save settings')); + $this->drupalGet('admin/structure/types/manage/article/fields/node.article.field_paragraphs'); + $this->submitForm($edit, 'Save settings'); // Add Paragraphs type. $this->addParagraphsType('test_paragraph_type'); @@ -79,30 +83,30 @@ public function testParagraphsIEFTranslation() { $edit = [ 'title[0][value]' => 'Title English', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Add french translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add'), 1); + $this->clickLink('Translate'); + $this->clickLink('Add', 1); // Make sure that the original paragraph text is displayed. $this->assertSession()->pageTextContains('Title English'); $edit = array( 'title[0][value]' => 'Title French', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('article Title French has been updated.'); // Add german translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add')); + $this->clickLink('Translate'); + $this->clickLink('Add'); // Make sure that the original paragraph text is displayed. $this->assertSession()->pageTextContains('Title English'); $edit = array( 'title[0][value]' => 'Title German', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('article Title German has been updated.'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsFieldGroupTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsFieldGroupTest.php similarity index 74% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsFieldGroupTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsFieldGroupTest.php index b7e5d30dd496c803a6a9c1c887a438508c2bc522..6107edaa53f383d35df83876d141162b6fc5e07f 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsFieldGroupTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsFieldGroupTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; /** * Tests the field group on node. @@ -15,7 +15,7 @@ class ParagraphsFieldGroupTest extends ParagraphsTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'field_group', ]; @@ -40,22 +40,25 @@ public function testFieldGroup() { 'label' => 'paragraph_field_group_title', 'group_name' => 'field' ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display/add-group', $edit, t('Save and continue')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display/add-group'); + $this->submitForm($edit, 'Save and continue'); $edit = [ 'format_settings[label]' => 'field_group' ]; - $this->drupalPostForm(NULL, $edit, t('Create group')); + $this->submitForm($edit, 'Create group'); // Put the text field into the field group. $edit = [ 'fields[group_field][region]' => 'content', 'fields[field_text][parent]' => 'group_field' ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display', $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display'); + $this->submitForm($edit, 'Save'); // Create a node with a paragraph. $this->drupalGet('node/add/' . $content_type); - $this->drupalPostForm('node/add/' . $content_type, [], 'field_paragraphs_paragraph_type_test_add_more'); + $this->drupalGet('node/add/' . $content_type); + $this->submitForm([], 'field_paragraphs_paragraph_type_test_add_more'); // Test if the new field group is displayed. $this->assertSession()->pageTextContains('field_group'); @@ -66,6 +69,6 @@ public function testFieldGroup() { 'title[0][value]' => 'paragraphed_title', 'field_paragraphs[0][subform][field_text][0][value]' => 'paragraph_value', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsInlineEntityFormTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsInlineEntityFormTest.php similarity index 85% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsInlineEntityFormTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsInlineEntityFormTest.php index 4f07699de401c678a68be80fa434ec9895899f0c..3f91a7e52c3c491265af3c020a00495a3b010bcd 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsInlineEntityFormTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsInlineEntityFormTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; /** * Tests the configuration of paragraphs in relation to ief. @@ -14,7 +14,7 @@ class ParagraphsInlineEntityFormTest extends ParagraphsTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'inline_entity_form', ]; @@ -45,28 +45,28 @@ public function testParagraphsIEFPreview() { $edit = [ 'fields[field_article][type]' => 'inline_entity_form_simple', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Set the paragraphs widget mode to preview. $this->setParagraphsWidgetMode('article', 'field_paragraphs', 'preview'); // Create node with one paragraph. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_simple_add_more'); + $this->submitForm([], 'field_paragraphs_simple_add_more'); // Set the values and save. $edit = [ 'title[0][value]' => 'Dummy1', 'field_paragraphs[0][subform][field_article][0][inline_entity_form][title][0][value]' => 'Dummy2', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Go back into edit page. $node = $this->getNodeByTitle('Dummy1'); $this->drupalGet('node/' . $node->id() . '/edit'); // Try to open the previewed paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); } /** @@ -98,21 +98,21 @@ public function testParagraphsIEFChangeOrder() { 'settings[target_type]' => 'paragraph', 'cardinality' => '-1', ]; - $this->drupalPostForm(NULL, $edit, t('Save field settings')); + $this->submitForm($edit, 'Save field settings'); // Enable IEF simple widget. $this->drupalGet('admin/structure/paragraphs_type/simple/form-display'); $edit = [ 'fields[field_article][type]' => 'inline_entity_form_simple', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Set the paragraphs widget mode to preview. $this->setParagraphsWidgetMode('article', 'field_paragraphs', 'preview'); // Create node with one paragraph. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_simple_add_more'); + $this->submitForm([], 'field_paragraphs_simple_add_more'); // Set the values and save. $edit = [ @@ -120,14 +120,14 @@ public function testParagraphsIEFChangeOrder() { 'field_paragraphs[0][subform][field_article][0][inline_entity_form][title][0][value]' => 'Basic page 1', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Go back into edit page. $node = $this->getNodeByTitle('Article 1'); $this->drupalGet('node/' . $node->id() . '/edit'); // Create second paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_simple_add_more'); + $this->submitForm([], 'field_paragraphs_simple_add_more'); // Set the values of second paragraph and change the order. $edit = [ @@ -135,7 +135,7 @@ public function testParagraphsIEFChangeOrder() { 'field_paragraphs[0][_weight]' => -1, 'field_paragraphs[1][_weight]' => -2, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsClassicContentModerationTranslationsTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsLegacyContentModerationTranslationsTest.php similarity index 97% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsClassicContentModerationTranslationsTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsLegacyContentModerationTranslationsTest.php index 0d42db68a7861d39f216711882c52c2f7ec4f1ff..49faac07f21d72b7d8f0411ba861d1c422a1913e 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsClassicContentModerationTranslationsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsLegacyContentModerationTranslationsTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\paragraphs\Traits\ParagraphsLastEntityQueryTrait; @@ -10,7 +10,7 @@ * * @group paragraphs */ -class ParagraphsClassicContentModerationTranslationsTest extends ParagraphsTestBase { +class ParagraphsLegacyContentModerationTranslationsTest extends ParagraphsTestBase { use ParagraphsLastEntityQueryTrait; @@ -19,7 +19,7 @@ class ParagraphsClassicContentModerationTranslationsTest extends ParagraphsTestB * * @var array */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_test', 'paragraphs', @@ -41,13 +41,9 @@ class ParagraphsClassicContentModerationTranslationsTest extends ParagraphsTestB /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); - // Place the breadcrumb, tested in fieldUIAddNewField(). - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); $this->addParagraphedContentType('paragraphed_test', 'field_paragraphs', 'entity_reference_paragraphs'); @@ -114,7 +110,7 @@ protected function setUp() { 'settings[paragraph][text][fields][field_untranslatable]' => FALSE, 'settings[paragraph][container][fields][field_paragraphs]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save configuration')); + $this->submitForm($edit, 'Save configuration'); } /** diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsPreviewTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsPreviewTest.php similarity index 87% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsPreviewTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsPreviewTest.php index c147aed92fad531ab48cef209583bbbe9cac7151..3b45028aadc467b317fdf109a0f696eafe4f5312 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsPreviewTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsPreviewTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; /** * Tests the configuration of paragraphs. @@ -14,7 +14,7 @@ class ParagraphsPreviewTest extends ParagraphsTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'image', ); @@ -41,14 +41,14 @@ public function testParagraphsPreview() { $test_text_2 = 'dummy_preview_text_2'; // Create node with two paragraphs. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); // Set the value of the paragraphs. $edit = [ 'title[0][value]' => 'Page_title', 'field_paragraphs[0][subform][field_text][0][value]' => $test_text_1, ]; // Preview the article. - $this->drupalPostForm(NULL, $edit, t('Preview')); + $this->submitForm($edit, 'Preview'); // Check if the text is displayed. $this->assertSession()->responseContains($test_text_1); @@ -64,15 +64,15 @@ public function testParagraphsPreview() { $paragraph_1 = $this->xpath('//*[@id="edit-field-paragraphs-0-subform-field-text-0-value"]')[0]; $this->assertEquals($paragraph_1->getValue(), $test_text_1); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->clickLink('Edit'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); $edit = [ 'field_paragraphs[1][subform][field_text][0][value]' => $test_text_2, ]; // Preview the article. - $this->drupalPostForm(NULL, $edit, t('Preview')); + $this->submitForm($edit, 'Preview'); $this->assertSession()->responseContains($test_text_1); $this->assertSession()->responseContains($test_text_2); @@ -84,7 +84,7 @@ public function testParagraphsPreview() { 'field_paragraphs[1][subform][field_text][0][value]' => $new_test_text_2, ]; // Preview the article. - $this->drupalPostForm(NULL, $edit, t('Preview')); + $this->submitForm($edit, 'Preview'); $this->assertSession()->responseContains($test_text_1); $this->assertSession()->responseContains($new_test_text_2); @@ -100,7 +100,7 @@ public function testParagraphsPreview() { $paragraph_2 = $this->xpath('//*[@id="edit-field-paragraphs-1-subform-field-text-0-value"]')[0]; $this->assertEquals($paragraph_1->getValue(), $test_text_1); $this->assertEquals($paragraph_2->getValue(), $new_test_text_2); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->responseContains($test_text_1); $this->assertSession()->responseContains($new_test_text_2); diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsSummaryFormatterTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsSummaryFormatterTest.php similarity index 81% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsSummaryFormatterTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsSummaryFormatterTest.php index e7709e35509e19eb5fd0522f39913247c9051a31..9bb7c7b307525ccb83a9fc3868e7eb3eb87acb5b 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsSummaryFormatterTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsSummaryFormatterTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; /** * Tests the paragraphs summary formatter. @@ -14,7 +14,7 @@ class ParagraphsSummaryFormatterTest extends ParagraphsTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'image', ]; @@ -42,10 +42,11 @@ public function testParagraphsSummaryFormatter() { // Set display format to paragraphs summary. $this->drupalGet('admin/structure/types/manage/paragraphed_test/display'); $edit = ['fields[field_paragraphs][type]' => 'paragraph_summary']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Add a paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_title_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_title_add_more'); // Create a node with a text. $edit = [ @@ -53,13 +54,13 @@ public function testParagraphsSummaryFormatter() { 'field_paragraphs[0][subform][field_text][0][value]' => 'text_summary', 'field_paragraphs[1][subform][field_title][0][value]' => 'Title example', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, [], t('Add user_paragraph')); + $this->submitForm($edit, 'Save'); + $this->clickLink('Edit'); + $this->submitForm([], 'Add user_paragraph'); $edit = [ 'field_paragraphs[2][subform][field_user][0][target_id]' => $this->admin_user->label() . ' (' . $this->admin_user->id() . ')', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Assert the summary is correctly generated. $this->assertSession()->pageTextContains($this->admin_user->label()); diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTestBase.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTestBase.php similarity index 82% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTestBase.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTestBase.php index 10c2c6424e09b3b8549fcf69cd521514cec9b30d..2295be321b3b50a21b4e4a3e5759adc81394815c 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTestBase.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTestBase.php @@ -1,12 +1,13 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; +use Drupal\user\Entity\Role; /** * Base class for tests. @@ -34,7 +35,7 @@ abstract class ParagraphsTestBase extends BrowserTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs', 'field', @@ -51,13 +52,9 @@ abstract class ParagraphsTestBase extends BrowserTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); - // Place the breadcrumb, tested in fieldUIAddNewField(). - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); $this->admin_permissions = [ 'administer content types', @@ -66,6 +63,7 @@ protected function setUp() { 'administer node form display', 'administer paragraph fields', 'administer paragraph form display', + 'bypass node access', ]; } @@ -133,7 +131,7 @@ protected function setAllowedParagraphsTypes($content_type, $paragraphs_types, $ foreach ($paragraphs_types as $paragraphs_type) { $edit['settings[handler_settings][target_bundles_drag_drop][' . $paragraphs_type . '][enabled]'] = $selected; } - $this->drupalPostForm(NULL, $edit, t('Save settings')); + $this->submitForm($edit, 'Save settings'); } /** @@ -151,7 +149,7 @@ protected function setAllowedParagraphsTypes($content_type, $paragraphs_types, $ protected function setParagraphsTypeWeight($content_type, $paragraphs_type, $weight, $paragraphs_field) { $this->drupalGet('admin/structure/types/manage/' . $content_type . '/fields/node.' . $content_type . '.' . $paragraphs_field); $edit['settings[handler_settings][target_bundles_drag_drop][' . $paragraphs_type . '][weight]'] = $weight; - $this->drupalPostForm(NULL, $edit, t('Save settings')); + $this->submitForm($edit, 'Save settings'); } /** @@ -168,9 +166,9 @@ protected function setParagraphsTypeWeight($content_type, $paragraphs_type, $wei */ protected function setDefaultParagraphType($content_type, $paragraphs_name, $paragraphs_field_name, $default_type) { $this->drupalGet('admin/structure/types/manage/' . $content_type . '/form-display'); - $this->drupalPostForm(NULL, [], $paragraphs_field_name); - $this->drupalPostForm(NULL, ['fields[' . $paragraphs_name . '][settings_edit_form][settings][default_paragraph_type]' => $default_type], t('Update')); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], $paragraphs_field_name); + $this->submitForm(['fields[' . $paragraphs_name . '][settings_edit_form][settings][default_paragraph_type]' => $default_type], 'Update'); + $this->submitForm([], 'Save'); } /** @@ -181,8 +179,8 @@ protected function setDefaultParagraphType($content_type, $paragraphs_name, $par */ protected function removeDefaultParagraphType($content_type) { $this->drupalGet('node/add/' . $content_type); - $this->drupalPostForm(NULL, [], 'Remove'); - $this->drupalPostForm(NULL, [], 'Confirm removal'); + $this->submitForm([], 'Remove'); + $this->submitForm([], 'Confirm removal'); $this->assertSession()->pageTextNotContains('No paragraphs added yet.'); } @@ -195,14 +193,14 @@ protected function removeDefaultParagraphType($content_type) { * Paragraphs field to change the mode. * @param string $mode * Mode to be set. ('closed', 'preview' or 'open'). - * 'preview' is only allowed in the classic widget. Use - * setParagraphsWidgetSettings for the experimental widget, instead. + * 'preview' is only allowed in the legacy widget. Use + * setParagraphsWidgetSettings for the stable widget, instead. */ protected function setParagraphsWidgetMode($content_type, $paragraphs_field, $mode) { $this->drupalGet('admin/structure/types/manage/' . $content_type . '/form-display'); - $this->drupalPostForm(NULL, [], $paragraphs_field . '_settings_edit'); - $this->drupalPostForm(NULL, ['fields[' . $paragraphs_field . '][settings_edit_form][settings][edit_mode]' => $mode], t('Update')); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], $paragraphs_field . '_settings_edit'); + $this->submitForm(['fields[' . $paragraphs_field . '][settings_edit_form][settings][edit_mode]' => $mode], 'Update'); + $this->submitForm([], 'Save'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTranslationTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTranslationTest.php similarity index 84% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTranslationTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTranslationTest.php index ff7c84bd600d2c14a5e9feeb4950b0d0fda61f2a..f55ea0c496186a8260286da62bcf2d7ad4f5cbde 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTranslationTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTranslationTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Entity\Entity\EntityFormDisplay; @@ -22,7 +22,7 @@ class ParagraphsTranslationTest extends ParagraphsTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'content_translation', 'link', 'image', @@ -43,7 +43,7 @@ class ParagraphsTranslationTest extends ParagraphsTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); ConfigurableLanguage::create(['id' => 'de', 'label' => '1German'])->save(); ConfigurableLanguage::create(['id' => 'fr', 'label' => '2French'])->save(); @@ -84,8 +84,9 @@ protected function setUp() { 'settings[paragraph][text_image][fields][field_text_demo]' => TRUE, 'settings[node][paragraphed_content_demo][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); - // Set the form display to classic. + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); + // Set the form display to legacy. EntityFormDisplay::load('node.paragraphed_content_demo.default') ->setComponent('field_paragraphs_demo', ['type' => 'entity_reference_paragraphs']) ->save(); @@ -125,26 +126,26 @@ public function testParagraphTranslation() { 'fields[status][region]' => 'content', ); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text_image')); + $this->submitForm([], 'Add text_image'); $this->assertSession()->responseContains('edit-field-paragraphs-demo-0-subform-status-value'); $edit = [ 'title[0][value]' => 'example_publish_unpublish', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Example published and unpublished', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains(t('Example published and unpublished')); - $this->clickLink(t('Edit')); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('Example published and unpublished'); + $this->clickLink('Edit'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more'); + $this->submitForm([], 'field_paragraphs_demo_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more'); $edit = [ 'field_paragraphs_demo[0][subform][status][value]' => FALSE, 'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'Dummy text' ]; - $this->drupalPostForm(NULL, $edit + ['status[value]' => FALSE], t('Save')); - $this->assertSession()->pageTextNotContains(t('Example published and unpublished')); + $this->submitForm($edit + ['status[value]' => FALSE], 'Save'); + $this->assertSession()->pageTextNotContains('Example published and unpublished'); // Check the parent fields are set properly. Get the node. $node = $this->drupalGetNodeByTitle('example_publish_unpublish'); @@ -167,26 +168,26 @@ public function testParagraphTranslation() { // Add paragraphed content. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text_image')); + $this->submitForm([], 'Add text_image'); $edit = array( 'title[0][value]' => 'Title in english', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Text in english', ); // The button to remove a paragraph is present. - $this->assertSession()->responseContains(t('Remove')); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertSession()->responseContains('Remove'); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('Title in english'); // The text is present when editing again. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->pageTextContains('Title in english'); $this->assertSession()->pageTextContains('Text in english'); // Add french translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add'), 1); + $this->clickLink('Translate'); + $this->clickLink('Add', 1); // Make sure the Add / Remove paragraph buttons are hidden. - $this->assertSession()->responseNotContains(t('Remove')); - $this->assertSession()->responseNotContains(t('Add text_image')); + $this->assertSession()->responseNotContains('Remove'); + $this->assertSession()->responseNotContains('Add text_image'); // Make sure that the original paragraph text is displayed. $this->assertSession()->pageTextContains('Text in english'); @@ -196,7 +197,7 @@ public function testParagraphTranslation() { 'revision' => TRUE, 'revision_log[0][value]' => 'french 1', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('paragraphed_content_demo Title in french has been updated.'); // Check the english translation. @@ -212,7 +213,7 @@ public function testParagraphTranslation() { $this->assertSession()->pageTextContains('Text in french'); $this->assertSession()->pageTextNotContains('Title in english'); // The translation is still present when editing again. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->pageTextContains('Title in french'); $this->assertSession()->pageTextContains('Text in french'); $edit = array( @@ -221,35 +222,35 @@ public function testParagraphTranslation() { 'revision' => TRUE, 'revision_log[0][value]' => 'french 2', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('Title Change in french'); $this->assertSession()->pageTextContains('New text in french'); // Back to the source language. $this->drupalGet('node/' . $node->id()); - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->pageTextContains('Title in english'); $this->assertSession()->pageTextContains('Text in english'); // Save the original content on second request. - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('paragraphed_content_demo Title in english has been updated.'); // Test if reverting to old paragraphs revisions works, make sure that // the reverted node can be saved again. $this->drupalGet('fr/node/' . $node->id() . '/revisions'); - $this->clickLink(t('Revert')); - $this->drupalPostForm(NULL, ['revert_untranslated_fields' => TRUE], t('Revert')); - $this->clickLink(t('Edit')); + $this->clickLink('Revert'); + $this->submitForm(['revert_untranslated_fields' => TRUE], 'Revert'); + $this->clickLink('Edit'); $this->assertSession()->responseContains('Title in french'); $this->assertSession()->pageTextContains('Text in french'); - $this->drupalPostForm(NULL, [], t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->responseNotContains('The content has either been modified by another user, or you have already submitted modifications'); $this->assertSession()->pageTextContains('Text in french'); //Add paragraphed content with untranslatable language $this->drupalGet('node/add/paragraphed_content_demo'); $edit = array('langcode[0][value]' => LanguageInterface::LANGCODE_NOT_SPECIFIED); - $this->drupalPostForm(NULL, $edit, t('Add text_image')); + $this->submitForm($edit, 'Add text_image'); $this->assertSession()->statusCodeEquals(200); // Make 'Images' paragraph field translatable, enable alt and title fields. @@ -260,41 +261,41 @@ public function testParagraphTranslation() { 'settings[alt_field]' => 1, 'settings[title_field]' => 1, ]; - $this->drupalPostForm(NULL, $edit, t('Save settings')); + $this->submitForm($edit, 'Save settings'); // Create a node with an image paragraph, its alt and title text. $files = $this->getTestFiles('image'); $file_system = \Drupal::service('file_system'); $file_path = $file_system->realpath($file_system->realpath($files[0]->uri)); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], t('Add images')); - $this->drupalPostForm(NULL, ['files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path], t('Upload')); + $this->submitForm([], 'Add images'); + $this->submitForm(['files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path], 'Upload'); $edit = [ 'title[0][value]' => 'Title EN', 'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt', 'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Translate the node with the image paragraph. $this->clickLink('Translate'); - $this->clickLink(t('Add'), 1); + $this->clickLink('Add', 1); $edit = [ 'title[0][value]' => 'Title FR', 'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt FR', 'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title FR', ]; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->responseContains('Title FR'); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], t('Add text')); + $this->submitForm([], 'Add text'); $edit = [ 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'texto', 'title[0][value]' => 'titulo', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('titulo'); $this->assertParagraphsLangcode($node->id(), 'de'); @@ -327,7 +328,7 @@ public function testParagraphTranslation() { 'field_paragraphs_demo' => [$paragraph_1, $translated_paragraph], ]); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_content_demo ' . $node->label() . ' has been updated.'); // Check that first paragraph langcode has been updated. \Drupal::entityTypeManager()->getStorage('paragraph')->resetCache([$paragraph_1->id(), $paragraph_2->id()]); @@ -345,25 +346,26 @@ public function testParagraphTranslation() { 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'english_translation_1', 'field_paragraphs_demo[1][subform][field_text_demo][0][value]' => 'english_translation_2', ]; - $this->drupalPostForm('node/' . $node->id() . '/translations/add/de/en', $edit, t('Save (this translation)')); + $this->drupalGet('node/' . $node->id() . '/translations/add/de/en'); + $this->submitForm($edit, 'Save (this translation)'); // Attempt to create a french translation. $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr'); // Check that the german translation of the paragraphs is displayed. $this->assertSession()->fieldValueEquals('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_text_1'); $this->assertSession()->fieldValueEquals('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'german_text_2'); - $this->drupalPostForm(NULL, ['source_langcode[source]' => 'en'], t('Change')); + $this->submitForm(['source_langcode[source]' => 'en'], 'Change'); // Check that the english translation of the paragraphs is displayed. $this->assertSession()->fieldValueEquals('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_translation_1'); $this->assertSession()->fieldValueEquals('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'english_translation_2'); // Create a node with empty Paragraphs. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], t('Add nested_paragraph')); + $this->submitForm([], 'Add nested_paragraph'); $edit = ['title[0][value]' => 'empty_node']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Attempt to translate it. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add')); + $this->clickLink('Translate'); + $this->clickLink('Add'); // Check the add button is not displayed. $this->assertEquals(count($this->xpath('//*[@name="field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more"]')), 0); @@ -373,9 +375,10 @@ public function testParagraphTranslation() { 'label' => 'untranslatable_field', 'field_name' => 'untranslatable_field', ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/add-field'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); + $this->submitForm([], 'Save settings'); // Add a non translatable reference field. $edit = [ @@ -383,9 +386,10 @@ public function testParagraphTranslation() { 'label' => 'untranslatable_ref_field', 'field_name' => 'untranslatable_ref_field', ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->drupalPostForm(NULL, ['settings[handler_settings][target_bundles][paragraphed_content_demo]' => TRUE], t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/add-field'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); + $this->submitForm(['settings[handler_settings][target_bundles][paragraphed_content_demo]' => TRUE], 'Save settings'); // Add a non translatable link field. $edit = [ @@ -393,9 +397,10 @@ public function testParagraphTranslation() { 'label' => 'untranslatable_link_field', 'field_name' => 'untranslatable_link_field', ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/add-field'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); + $this->submitForm([], 'Save settings'); // Attempt to add a translation. $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr'); @@ -408,8 +413,10 @@ public function testParagraphTranslation() { $edit = [ 'translatable' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_ref_field', $edit, t('Save settings')); - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_link_field', $edit, t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_ref_field'); + $this->submitForm($edit, 'Save settings'); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_link_field'); + $this->submitForm($edit, 'Save settings'); // Attempt to add a translation. $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr'); @@ -432,7 +439,7 @@ public function testParagraphTranslationMultilingual() { // Add 'Images' paragraph and check the paragraphs buttons are displayed. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add images')); + $this->submitForm([], 'Add images'); $this->assertParagraphsButtons(1); // Upload an image and check the paragraphs buttons are still displayed. $images = $this->getTestFiles('image')[0]; @@ -440,24 +447,24 @@ public function testParagraphTranslationMultilingual() { 'title[0][value]' => 'Title in english', 'files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, ]; - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Title in english'); $node = $this->drupalGetNodeByTitle('Title in english'); // Check the paragraph langcode is 'en'. $this->assertParagraphsLangcode($node->id()); // Add french translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add'), 1); + $this->clickLink('Translate'); + $this->clickLink('Add', 1); // Make sure the host entity and its paragraphs have valid source language // and check that the paragraphs buttons are hidden. $this->assertNoParagraphsButtons(1); $edit = [ 'title[0][value]' => 'Title in french', ]; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertParagraphsLangcode($node->id(), 'en', 'fr'); $this->assertSession()->pageTextContains('paragraphed_content_demo Title in french has been updated.'); $this->assertSession()->pageTextContains('Title in french'); @@ -468,14 +475,14 @@ public function testParagraphTranslationMultilingual() { // Edit the french translation and upload a new image. $this->clickLink('Edit'); $images = $this->getTestFiles('image')[1]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); // Check editing a translation does not affect the source langcode and // check that the paragraphs buttons are still hidden. $this->assertParagraphsLangcode($node->id(), 'en', 'fr'); $this->assertNoParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('Title in french'); $this->assertSession()->pageTextNotContains('Title in english'); @@ -494,23 +501,23 @@ public function testParagraphTranslationMultilingual() { 'title[0][value]' => 'Title in english (de)', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, t('Add nested_paragraph')); + $this->submitForm($edit, 'Add nested_paragraph'); $this->assertParagraphsLangcode($node->id()); $this->assertParagraphsButtons(2); // Add an 'Images' paragraph inside the nested one, check the paragraphs // langcode are still 'en' and the paragraphs buttons are still displayed. - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_1_subform_field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_1_subform_field_paragraphs_demo_images_add_more'); $this->assertParagraphsLangcode($node->id()); $this->assertParagraphsButtons(2); // Upload a new image, check the paragraphs langcode are still 'en' and the // paragraphs buttons are displayed. $images = $this->getTestFiles('image')[2]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_1_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node->id()); $this->assertParagraphsButtons(2); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('Title in english (de)'); $this->assertSession()->pageTextNotContains('Title in french'); // Check the original node and the paragraphs langcode are now 'de'. @@ -530,9 +537,10 @@ public function testParagraphTranslationMultilingual() { // node langcode to EN. // Change the site langcode to french. - $this->drupalPostForm('admin/config/regional/language', [ + $this->drupalGet('admin/config/regional/language'); + $this->submitForm([ 'site_default_language' => 'fr', - ], t('Save configuration')); + ], 'Save configuration'); // Check the original node and its paragraphs langcode are still 'de' // and the paragraphs buttons are still displayed. @@ -542,21 +550,21 @@ public function testParagraphTranslationMultilingual() { // Go to the french translation. $this->drupalGet('node/' . $node->id() . '/translations'); - $this->clickLink(t('Edit'), 1); + $this->clickLink('Edit', 1); // Check editing a translation does not affect the source langcode and // check that the paragraphs buttons are still hidden. $this->assertParagraphsLangcode($node->id(), 'de', 'fr'); $this->assertNoParagraphsButtons(2); // Upload another image. $images = $this->getTestFiles('image')[3]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_1_subform_field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); // Check editing a translation does not affect the source langcode and // check that the paragraphs buttons are still hidden. $this->assertParagraphsLangcode($node->id(), 'de', 'fr'); $this->assertNoParagraphsButtons(2); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); // Check the paragraphs langcode are still 'de' after saving the translation. $this->assertParagraphsLangcode($node->id(), 'de', 'fr'); $this->assertSession()->pageTextContains('Title in french'); @@ -577,18 +585,18 @@ public function testParagraphTranslationMultilingual() { 'title[0][value]' => 'Title in english', 'langcode[0][value]' => 'en', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_demo_images_add_more'); + $this->submitForm($edit, 'field_paragraphs_demo_images_add_more'); $this->assertParagraphsLangcode($node->id(), 'de'); $this->assertParagraphsButtons(3); // Upload a new image, check the paragraphs langcode are still 'de' and the // paragraphs buttons are displayed. $images = $this->getTestFiles('image')[4]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_2_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node->id(), 'de'); $this->assertParagraphsButtons(3); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('paragraphed_content_demo Title in english has been updated.'); // Check the original node and the paragraphs langcode are now 'en'. $this->assertParagraphsLangcode($node->id()); @@ -616,25 +624,25 @@ public function testParagraphsMultilingualWorkflow() { 'title[0][value]' => 'Title in german', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, t('Add nested_paragraph')); + $this->submitForm($edit, 'Add nested_paragraph'); // Check that the paragraphs buttons are displayed and add an 'Images' // paragraph inside the nested paragraph. $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); // Upload an image and check the paragraphs buttons are still displayed. $images = $this->getTestFiles('image')[0]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Title in german'); $node1 = $this->getNodeByTitle('Title in german'); // Check the paragraph langcode is 'de' and its buttons are displayed. // @todo check for the nested children paragraphs buttons and langcode // when it's supported. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node1->id(), 'de'); $this->assertParagraphsButtons(1); // Change the node langcode to 'english' and upload another image. @@ -644,16 +652,16 @@ public function testParagraphsMultilingualWorkflow() { 'langcode[0][value]' => 'en', 'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri, ]; - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); // Check the paragraph langcode is still 'de' and its buttons are shown. $this->assertParagraphsLangcode($node1->id(), 'de'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraph langcode is now 'en' after saving. $this->assertParagraphsLangcode($node1->id()); // Check the paragraph langcode is 'en' and its buttons are still shown. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node1->id()); $this->assertParagraphsButtons(1); @@ -665,27 +673,27 @@ public function testParagraphsMultilingualWorkflow() { // Check that the node langcode is 'english' and add a 'Nested Paragraph'. $langcode_option = $this->assertSession()->optionExists('edit-langcode-0-value', 'en'); $this->assertTrue($langcode_option->hasAttribute('selected')); - $this->drupalPostForm(NULL, NULL, t('Add nested_paragraph')); + $this->submitForm([], 'Add nested_paragraph'); // Check that the paragraphs buttons are displayed and add an 'Images' // paragraph inside the nested paragraph. $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); // Upload an image and check the paragraphs buttons are still displayed. $images = $this->getTestFiles('image')[0]; $edit = [ 'title[0][value]' => 'Title in english', 'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, ]; - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Title in english'); $node2 = $this->drupalGetNodeByTitle('Title in english'); // Check the paragraph langcode is 'en' and its buttons are displayed. // @todo check for the nested children paragraphs buttons and langcode // when it's supported. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(1); // Change the node langcode to 'german' and add another 'Images' paragraph. @@ -693,29 +701,29 @@ public function testParagraphsMultilingualWorkflow() { 'title[0][value]' => 'Title in english (de)', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_demo_images_add_more'); + $this->submitForm($edit, 'field_paragraphs_demo_images_add_more'); // Check the paragraphs langcode are still 'en' and their buttons are shown. $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(2); // Upload an image, check the paragraphs langcode are still 'en' and their // buttons are displayed. $images = $this->getTestFiles('image')[1]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_1_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(2); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraphs langcode are now 'de' after saving. $this->assertParagraphsLangcode($node2->id(), 'de'); // Change node langcode back to 'english' and save. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $edit = [ 'title[0][value]' => 'Title in english', 'langcode[0][value]' => 'en', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check the paragraphs langcode are now 'en' after saving. $this->assertParagraphsLangcode($node2->id()); @@ -725,7 +733,8 @@ public function testParagraphsMultilingualWorkflow() { $edit = [ 'site_default_language' => 'de', ]; - $this->drupalPostForm('admin/config/regional/language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/language'); + $this->submitForm( $edit, 'Save configuration'); // Check the original node and the paragraphs langcode are still 'en' and // check that the paragraphs buttons are still displayed. @@ -733,24 +742,24 @@ public function testParagraphsMultilingualWorkflow() { $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(2); // Add another 'Images' paragraph with node langcode as 'english'. - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_images_add_more'); // Check the paragraph langcode are still 'en' and their buttons are shown. $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(3); // Upload an image, check the paragraphs langcode are still 'en' and their // buttons are displayed. $images = $this->getTestFiles('image')[2]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_2_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(3); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraphs langcode are still 'en' after saving. $this->assertParagraphsLangcode($node2->id()); // Check the paragraphs langcode are still 'en' and their buttons are shown. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(3); // Change node langcode to 'german' and add another 'Images' paragraph. @@ -758,19 +767,19 @@ public function testParagraphsMultilingualWorkflow() { 'title[0][value]' => 'Title in english (de)', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_demo_images_add_more'); + $this->submitForm($edit, 'field_paragraphs_demo_images_add_more'); // Check the paragraphs langcode are still 'en' and their buttons are shown. $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(4); // Upload an image, check the paragraphs langcode are still 'en' and their // buttons are displayed. $images = $this->getTestFiles('image')[3]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_3_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(4); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraphs langcode are now 'de' after saving. $this->assertParagraphsLangcode($node2->id(), 'de'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTypesTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTypesTest.php similarity index 91% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTypesTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTypesTest.php index 71ec3fbef3753533005156be210cd7454311a2ac..4ba56ba6189ec12a41b179bf852ad413c8766b8b 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsTypesTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTypesTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\paragraphs\Entity\ParagraphsType; @@ -24,20 +24,20 @@ public function testRemoveTypesWithContent() { // Attempt to delete the content type not used yet. $this->drupalGet('admin/structure/paragraphs_type'); - $this->clickLink(t('Delete')); + $this->clickLink('Delete'); $this->assertSession()->pageTextContains('This action cannot be undone.'); - $this->clickLink(t('Cancel')); + $this->clickLink('Cancel'); // Add a test node with a Paragraph. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'paragraphs_paragraph_type_test_add_more'); + $this->submitForm([], 'paragraphs_paragraph_type_test_add_more'); $edit = ['title[0][value]' => 'test_node']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test test_node has been created.'); // Attempt to delete the paragraph type already used. $this->drupalGet('admin/structure/paragraphs_type'); - $this->clickLink(t('Delete')); + $this->clickLink('Delete'); $this->assertSession()->pageTextContains('paragraph_type_test Paragraphs type is used by 1 piece of content on your site. You can not remove this paragraph_type_test Paragraphs type until you have removed all from the content.'); } @@ -68,7 +68,7 @@ public function testParagraphTypeIcon() { 'id' => 'test_paragraph_type_icon', 'files[icon_file]' => $fileSystem->realpath($test_files[0]->uri), ]; - $this->drupalPostForm(NULL, $edit, t('Save and manage fields')); + $this->submitForm($edit, 'Save and manage fields'); $this->assertSession()->pageTextContains('Saved the Test paragraph type Paragraphs type.'); // Check if the icon has been saved. @@ -90,8 +90,8 @@ public function testParagraphTypeIcon() { // Delete the icon. $this->drupalGet('admin/structure/paragraphs_type/test_paragraph_type_icon'); - $this->drupalPostForm(NULL, [], 'icon_file_remove_button'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'icon_file_remove_button'); + $this->submitForm([], 'Save'); // Check that the icon file usage has been deregistered. $usages = $file_usage->listUsage($file); @@ -120,7 +120,7 @@ public function testParagraphTypeDefaultIcon() { 'id' => 'test_paragraph_type_icon', 'files[icon_file]' => $fileSystem->realpath($test_files[0]->uri), ]; - $this->drupalPostForm(NULL, $edit, t('Save and manage fields')); + $this->submitForm($edit, 'Save and manage fields'); $this->assertSession()->pageTextContains('Saved the Test paragraph type Paragraphs type.'); // Check if the icon is created from defaults if not exists. @@ -155,7 +155,7 @@ public function testParagraphTypeDescription() { 'id' => 'test_paragraph_type_description', 'description' => $description_markup, ]; - $this->drupalPostForm(NULL, $edit, t('Save and manage fields')); + $this->submitForm($edit, 'Save and manage fields'); $this->assertSession()->pageTextContains("Saved the $label Paragraphs type."); // Check if the description has been saved. diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsUiTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsUiTest.php similarity index 87% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsUiTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsUiTest.php index dfe62893aa67e34330131750310adca2e4f0e868..822390292eb5fa5519953c7070cb48f218480921 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsUiTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsUiTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; use Drupal\language\Entity\ConfigurableLanguage; @@ -16,7 +16,7 @@ class ParagraphsUiTest extends ParagraphsTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'content_translation', 'image', 'field', @@ -29,7 +29,7 @@ class ParagraphsUiTest extends ParagraphsTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); ConfigurableLanguage::create(['id' => 'de', 'label' => '1German'])->save(); ConfigurableLanguage::create(['id' => 'fr', 'label' => '2French'])->save(); @@ -64,7 +64,8 @@ protected function setUp() { 'settings[paragraph][text_image][fields][field_text_demo]' => TRUE, 'settings[node][paragraphed_content_demo][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); } /** @@ -93,22 +94,23 @@ public function testEmptyRequiredField() { $form_display_edit = [ 'fields[field_content][type]' => 'entity_reference_paragraphs', ]; - $this->drupalPostForm($bundle_path . '/form-display', $form_display_edit, t('Save')); + $this->drupalGet($bundle_path . '/form-display'); + $this->submitForm($form_display_edit, 'Save'); // Attempt to create a paragraphed node with an empty required field. $title = 'Empty'; $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, ['title[0][value]' => $title], t('Save')); + $this->submitForm(['title[0][value]' => $title], 'Save'); $this->assertSession()->pageTextContains($field_title . ' field is required'); // Attempt to create a paragraphed node with only a paragraph in the // "remove" mode in the required field. $title = 'Remove mode'; $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], 'field_content_text_image_add_more'); - $this->drupalPostForm(NULL, [], 'field_content_0_remove'); + $this->submitForm([], 'field_content_text_image_add_more'); + $this->submitForm([], 'field_content_0_remove'); $this->assertSession()->pageTextNotContains($field_title . ' field is required'); - $this->drupalPostForm(NULL, ['title[0][value]' => $title], t('Save')); + $this->submitForm(['title[0][value]' => $title], 'Save'); $this->assertSession()->pageTextContains($field_title . ' field is required'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsWidgetButtonsTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsWidgetButtonsTest.php similarity index 78% rename from web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsWidgetButtonsTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsWidgetButtonsTest.php index 220af02df097400641c3a220881137371c5fab4f..28f05ae1d85d7243f11cfc9e5b3f928b4a61a04f 100644 --- a/web/modules/paragraphs/tests/src/Functional/Classic/ParagraphsWidgetButtonsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsWidgetButtonsTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Classic; +namespace Drupal\Tests\paragraphs\Functional\WidgetLegacy; /** * Tests paragraphs widget buttons. @@ -23,7 +23,8 @@ public function testWidgetButtons() { // Add a text field to the text_paragraph type. static::fieldUIAddNewField('admin/structure/paragraphs_type/' . $paragraph_type, 'text', 'Text', 'text_long', [], []); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); // Create a node with a Paragraph. $text = 'recognizable_text'; @@ -31,35 +32,35 @@ public function testWidgetButtons() { 'title[0][value]' => 'paragraphs_mode_test', 'field_paragraphs[0][subform][field_text][0][value]' => $text, ]; - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('paragraphs_mode_test'); // Test the 'Open' mode. $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', $text); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains($text); // Test the 'Closed' mode. $this->setParagraphsWidgetMode('paragraphed_test', 'field_paragraphs', 'closed'); $this->drupalGet('node/' . $node->id() . '/edit'); // Click "Edit" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_1_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_1_edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', $text); $closed_mode_text = 'closed_mode_text'; // Click "Collapse" button on both paragraphs. $edit = ['field_paragraphs[0][subform][field_text][0][value]' => $closed_mode_text]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); $edit = ['field_paragraphs[1][subform][field_text][0][value]' => $closed_mode_text]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_1_collapse'); + $this->submitForm($edit, 'field_paragraphs_1_collapse'); // Verify that we have warning message for each paragraph. $page_text = $this->getSession()->getPage()->getText(); $nr_found = substr_count($page_text, 'You have unsaved changes on this Paragraph item.'); $this->assertGreaterThan(1, $nr_found); $this->assertSession()->responseContains('<span class="summary-content">' . $closed_mode_text); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_test ' . $node->label() . ' has been updated.'); $this->assertSession()->pageTextContains($closed_mode_text); @@ -67,15 +68,15 @@ public function testWidgetButtons() { $this->setParagraphsWidgetMode('paragraphed_test', 'field_paragraphs', 'preview'); $this->drupalGet('node/' . $node->id() . '/edit'); // Click "Edit" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', $closed_mode_text); $preview_mode_text = 'preview_mode_text'; $edit = ['field_paragraphs[0][subform][field_text][0][value]' => $preview_mode_text]; // Click "Collapse" button. - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); $this->assertSession()->pageTextContains('You have unsaved changes on this Paragraph item.'); $this->assertSession()->pageTextContains($preview_mode_text); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_test ' . $node->label() . ' has been updated.'); $this->assertSession()->pageTextContains($preview_mode_text); @@ -83,14 +84,14 @@ public function testWidgetButtons() { $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->pageTextContains($preview_mode_text); // Click "Remove" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_remove'); + $this->submitForm([], 'field_paragraphs_0_remove'); $this->assertSession()->pageTextContains('Deleted Paragraph: text_paragraph'); // Click "Restore" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_restore'); + $this->submitForm([], 'field_paragraphs_0_restore'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', $preview_mode_text); $restore_text = 'restore_text'; $edit = ['field_paragraphs[0][subform][field_text][0][value]' => $restore_text]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test ' . $node->label() . ' has been updated.'); $this->assertSession()->pageTextContains($restore_text); @@ -98,11 +99,11 @@ public function testWidgetButtons() { $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->pageTextContains($restore_text); // Click "Remove" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_remove'); + $this->submitForm([], 'field_paragraphs_0_remove'); $this->assertSession()->pageTextContains('Deleted Paragraph: text_paragraph'); // Click "Confirm Removal" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_confirm_remove'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_0_confirm_remove'); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_test ' . $node->label() . ' has been updated.'); $this->assertSession()->pageTextNotContains($restore_text); } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAccessTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAccessTest.php similarity index 83% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAccessTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAccessTest.php index afd218c0537ea5fb52d715a9156565d317b6fb1c..422d7ec8cbe1b8de0f70f66feb2938254ef40a74 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAccessTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAccessTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\filter\Entity\FilterFormat; @@ -15,7 +15,7 @@ * * @group paragraphs */ -class ParagraphsExperimentalAccessTest extends ParagraphsExperimentalTestBase { +class ParagraphsAccessTest extends ParagraphsTestBase { use FieldUiTestTrait; @@ -24,7 +24,7 @@ class ParagraphsExperimentalAccessTest extends ParagraphsExperimentalTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'content_translation', 'image', 'field', @@ -37,7 +37,7 @@ class ParagraphsExperimentalAccessTest extends ParagraphsExperimentalTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); ConfigurableLanguage::create(['id' => 'de', 'label' => '1German'])->save(); ConfigurableLanguage::create(['id' => 'fr', 'label' => '2French'])->save(); @@ -72,7 +72,8 @@ protected function setUp() { 'settings[paragraph][text_image][fields][field_text_demo]' => TRUE, 'settings[node][paragraphed_content_demo][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); $view_display = \Drupal::service('entity_display.repository')->getViewDisplay('paragraph', 'images'); $view_display->setComponent('field_images_demo', ['settings' => ['image_style' => 'medium']]); @@ -105,9 +106,10 @@ public function testParagraphAccessCheck() { $edit = array( 'settings[uri_scheme]' => 'private', ); - $this->drupalPostForm('admin/structure/paragraphs_type/images/fields/paragraph.images.field_images_demo/storage', $edit, t('Save field settings')); + $this->drupalGet('admin/structure/paragraphs_type/images/fields/paragraph.images.field_images_demo/storage'); + $this->submitForm($edit, 'Save field settings'); - // Use the experimental widget. + // Use the stable widget. $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default') ->setComponent('field_paragraphs_demo', ['type' => 'paragraphs']); $form_display->save(); @@ -115,7 +117,7 @@ public function testParagraphAccessCheck() { $this->drupalGet('node/add/paragraphed_content_demo'); // Add a new Paragraphs images item. - $this->drupalPostForm(NULL, NULL, t('Add images')); + $this->submitForm([], 'Add images'); $images = $this->getTestFiles('image'); @@ -135,27 +137,27 @@ public function testParagraphAccessCheck() { 'files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path, ); - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); $edit = array( 'files[field_paragraphs_demo_0_subform_field_images_demo_1][]' => $file_path_2, ); - $this->drupalPostForm(NULL, $edit, t('Upload')); - $this->drupalPostForm(NULL, [], t('Preview')); + $this->submitForm($edit, 'Upload'); + $this->submitForm([], 'Preview'); $image_style = ImageStyle::load('medium'); $img1_url = $image_style->buildUrl('private://' . date('Y-m') . '/privateImage.jpg'); - $image_url = file_url_transform_relative($img1_url); - $this->assertSession()->responseContains($image_url, 'Image was found in preview'); - $this->clickLink(t('Back to content editing')); - $this->drupalPostForm(NULL, [], t('Save')); + $image_url = \Drupal::service('file_url_generator')->transformRelative($img1_url); + $this->assertSession()->responseContains($image_url); + $this->clickLink('Back to content editing'); + $this->submitForm([], 'Save'); $node = $this->drupalGetNodeByTitle('Security test node'); $this->drupalGet('node/' . $node->id()); // Check the text and image after publish. - $this->assertSession()->responseContains($image_url, 'Image was found in content'); + $this->assertSession()->responseContains($image_url); $this->drupalGet($img1_url); $this->assertSession()->statusCodeEquals(200); @@ -166,9 +168,9 @@ public function testParagraphAccessCheck() { // @todo Requesting the same $img_url again triggers a caching problem on // drupal.org test bot, thus we request a different file here. $img_url = $image_style->buildUrl('private://' . date('Y-m') . '/privateImage2.jpg'); - $image_url = file_url_transform_relative($img_url); + $image_url = \Drupal::service('file_url_generator')->transformRelative($img_url); // Check the text and image after publish. Anonymous should not see content. - $this->assertSession()->responseNotContains($image_url, 'Image was not found in content'); + $this->assertSession()->responseNotContains($image_url); $this->drupalGet($img_url); $this->assertSession()->statusCodeEquals(403); @@ -177,20 +179,20 @@ public function testParagraphAccessCheck() { $this->loginAsAdmin($permissions); // Create a new demo node. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text')); + $this->submitForm([], 'Add text'); $this->assertSession()->pageTextContains('Text'); $edit = [ 'title[0][value]' => 'delete_permissions', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Edit the node. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Check the remove button is present. $this->assertNotNull($this->xpath('//*[@name="field_paragraphs_demo_0_remove"]')); // Delete the Paragraph and save. - $this->drupalPostForm(NULL, [], 'field_paragraphs_demo_0_remove'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_demo_0_remove'); + $this->submitForm([], 'Save'); $node = $this->getNodeByTitle('delete_permissions'); $this->assertSession()->addressEquals('node/' . $node->id()); @@ -207,16 +209,17 @@ public function testParagraphAccessCheck() { 'fields[status][region]' => 'content', 'fields[status][type]' => 'boolean_checkbox' ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/form-display', $edit, 'Save'); + $this->drupalGet('admin/structure/paragraphs_type/text/form-display'); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text')); + $this->submitForm([], 'Add text'); $this->assertSession()->pageTextContains('Text'); $edit = [ 'title[0][value]' => 'unpublished_permissions', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'recognizable_test', 'field_paragraphs_demo[0][subform][status][value]' => FALSE ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('recognizable_test'); $this->assertSession()->responseContains('paragraph--unpublished'); $this->drupalLogout(); @@ -242,14 +245,16 @@ public function testParagraphAccessCheck() { // Grant to the user the administer Paragraphs settings permission. $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer paragraphs settings']); // Disable the show unpublished Paragraphs setting. - $this->drupalPostForm('admin/config/content/paragraphs', ['show_unpublished' => FALSE], 'Save configuration'); + $this->drupalGet('admin/config/content/paragraphs'); + $this->submitForm(['show_unpublished' => FALSE], 'Save configuration'); // Assert that the Paragraph is not displayed even if the user has the // permission to do so. $this->drupalGet('node/' . $node->id()); $this->assertSession()->pageTextNotContains('recognizable_test'); $this->assertSession()->responseNotContains('paragraph--unpublished'); // Enable the show unpublished Paragraphs setting. - $this->drupalPostForm('admin/config/content/paragraphs', ['show_unpublished' => TRUE], 'Save configuration'); + $this->drupalGet('admin/config/content/paragraphs'); + $this->submitForm(['show_unpublished' => TRUE], 'Save configuration'); // Assert that the Paragraph is displayed when the user has the permission // to do so. $this->drupalGet('node/' . $node->id()); @@ -274,13 +279,13 @@ public function testParagraphsTextFormatValidation() { $this->loginAsAdmin($permissions); // Create a node with a Text Paragraph using the filtered html format. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text')); + $this->submitForm([], 'Add text'); $this->assertSession()->pageTextContains('Text'); $edit = [ 'title[0][value]' => 'access_validation_test', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_content_demo access_validation_test has been created.'); $this->drupalLogout(); // Login as an user without the Text Format permission. @@ -291,11 +296,11 @@ public function testParagraphsTextFormatValidation() { $this->drupalLogin($user); $node = $this->getNodeByTitle('access_validation_test'); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_content_demo access_validation_test has been updated.'); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_demo_0_collapse'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_demo_0_collapse'); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_content_demo access_validation_test has been updated.'); $this->assertSession()->pageTextNotContains('The value you selected is not a valid choice.'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAddModesTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAddModesTest.php similarity index 94% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAddModesTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAddModesTest.php index baa1cdcd8c77f90b877e358811bf21834f35e9ab..4ee2055e7f4a4c14adfae161a2a7539e1bc9ba05 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAddModesTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAddModesTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\paragraphs\Entity\ParagraphsType; @@ -9,7 +9,7 @@ * * @group paragraphs */ -class ParagraphsExperimentalAddModesTest extends ParagraphsExperimentalTestBase { +class ParagraphsAddModesTest extends ParagraphsTestBase { /** * Tests that paragraphs field does not allow default values. @@ -19,11 +19,11 @@ public function testNoDefaultValue() { $this->addParagraphedContentType('paragraphed_test'); // Edit the field. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields'); - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Check that the current field does not allow to add default values. $this->assertSession()->pageTextContains('No widget available for: field_paragraphs.'); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->submitForm([], 'Save settings'); $this->assertSession()->pageTextContains('Saved field_paragraphs configuration.'); $this->assertSession()->statusCodeEquals(200); } @@ -37,8 +37,8 @@ public function testEmptyAllowedTypes() { // Edit the field and save when there are no Paragraphs types available. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields'); - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->clickLink('Edit'); + $this->submitForm([], 'Save settings'); $this->assertSession()->pageTextContains('Saved field_paragraphs configuration.'); } @@ -54,7 +54,7 @@ public function testDropDownMode() { $this->addParagraphedContentType('paragraphed_test', 'paragraphs'); // Enter to the field config since the weight is set through the form. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.paragraphs'); - $this->drupalPostForm(NULL, [], 'Save settings'); + $this->submitForm([], 'Save settings'); $this->setAddMode('paragraphed_test', 'paragraphs', 'dropdown'); @@ -88,7 +88,7 @@ public function testSelectMode() { $this->addParagraphedContentType('paragraphed_test', 'paragraphs'); // Enter to the field config since the weight is set through the form. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.paragraphs'); - $this->drupalPostForm(NULL, [], 'Save settings'); + $this->submitForm([], 'Save settings'); $this->setAddMode('paragraphed_test', 'paragraphs', 'select'); @@ -118,7 +118,7 @@ public function testSelectMode() { */ protected function assertAddButtons($options) { $this->drupalGet('node/add/paragraphed_test'); - $buttons = $this->xpath('//input[@class="field-add-more-submit button js-form-submit form-submit"]'); + $buttons = $this->xpath('//input[@class="field-add-more-submit button--small button js-form-submit form-submit"]'); // Check if the buttons are in the same order as the given array. foreach ($buttons as $key => $button) { $this->assertEquals($button->getValue(), $options[$key]); @@ -189,7 +189,7 @@ public function testSettingDefaultParagraphType() { $this->setDefaultParagraphType('paragraphed_test', 'paragraphs', 'paragraphs_settings_edit', 'text_image'); $this->removeDefaultParagraphType('paragraphed_test'); $edit = ['title[0][value]' => 'New Host']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/1/edit'); $elements = $this->xpath('//table[@id="paragraphs-values"]/tbody'); $header = $this->xpath('//table[@id="paragraphs-values"]/thead'); diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAdministrationTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAdministrationTest.php similarity index 74% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAdministrationTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAdministrationTest.php index 7d3bf6d61fb3aecb92e69c4b28159e40aba9823b..e32de40e9e120d36250695161d55445ef8898779 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAdministrationTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAdministrationTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\paragraphs\Entity\Paragraph; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; @@ -10,7 +10,7 @@ * * @group paragraphs */ -class ParagraphsExperimentalAdministrationTest extends ParagraphsExperimentalTestBase { +class ParagraphsAdministrationTest extends ParagraphsTestBase { use ParagraphsTestBaseTrait; @@ -19,7 +19,7 @@ class ParagraphsExperimentalAdministrationTest extends ParagraphsExperimentalTes * * @var array */ - public static $modules = array( + protected static $modules = array( 'image', 'file', 'views' @@ -28,7 +28,7 @@ class ParagraphsExperimentalAdministrationTest extends ParagraphsExperimentalTes /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); // Create paragraphs content type. $this->drupalCreateContentType(array('type' => 'paragraphs', 'name' => 'Paragraphs')); @@ -61,19 +61,19 @@ public function testParagraphsRevisions() { )); // Configure article fields. $this->drupalGet('admin/structure/types/manage/paragraphs/fields'); - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, array('fields[field_paragraphs][type]' => 'paragraphs'), t('Save')); + $this->clickLink('Manage form display'); + $this->submitForm(array('fields[field_paragraphs][type]' => 'paragraphs'), 'Save'); // Create node with our paragraphs. $this->drupalGet('node/add/paragraphs'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); $edit = [ 'title[0][value]' => 'TEST TITEL', 'field_paragraphs[0][subform][field_text][0][value]' => 'Test text 1', 'field_paragraphs[1][subform][field_text][0][value]' => 'Test text 2', ]; - $this->drupalPostForm(NULL, $edit + ['status[value]' => TRUE], t('Save')); + $this->submitForm($edit + ['status[value]' => TRUE], 'Save'); $node = $this->drupalGetNodeByTitle('TEST TITEL'); $paragraph1 = $node->field_paragraphs[0]->target_id; @@ -87,7 +87,8 @@ public function testParagraphsRevisions() { 'field_paragraphs[0][subform][field_text][0][value]' => 'Foo Bar 1', 'revision' => FALSE, ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm($edit, 'Save'); $this->countRevisions($node, $paragraph1, $paragraph2, 1); @@ -98,7 +99,8 @@ public function testParagraphsRevisions() { 'field_paragraphs[0][subform][field_text][0][value]' => 'Foo Bar 2', 'revision' => TRUE, ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm($edit, 'Save'); $this->countRevisions($node, $paragraph1, $paragraph2, 2); @@ -114,8 +116,8 @@ public function testParagraphsRevisions() { // Make sure two revisions available. $this->assertEquals(count($rows), 2); // Revert to the old version. - $this->clickLink(t('Revert')); - $this->drupalPostForm(NULL, [], t('Revert')); + $this->clickLink('Revert'); + $this->submitForm([], 'Revert'); $this->drupalGet('node/' . $node->id()); // Assert the node has been reverted. $this->assertSession()->pageTextNotContains('Foo Bar 2'); @@ -151,14 +153,14 @@ public function testParagraphsCreation() { 'label' => 'Paragraph', 'field_name' => 'paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Save and continue'); - $this->drupalPostForm(NULL, [], 'Save field settings'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); $this->assertSession()->linkByHrefExists('admin/structure/paragraphs_type/add'); $this->clickLink('here'); $this->assertSession()->addressEquals('admin/structure/paragraphs_type/add'); $this->drupalGet('admin/structure/paragraphs_type'); - $this->clickLink(t('Add paragraph type')); + $this->clickLink('Add paragraph type'); $this->assertSession()->titleEquals('Add Paragraphs type | Drupal'); // Create paragraph type text + image. $this->addParagraphsType('text_image'); @@ -179,10 +181,10 @@ public function testParagraphsCreation() { ), array()); // Change the add more button to select mode. - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][type]' => 'paragraphs'], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][add_mode]' => 'select'], t('Update')); - $this->drupalPostForm(NULL, [], t('Save')); + $this->clickLink('Manage form display'); + $this->submitForm(['fields[field_paragraphs][type]' => 'paragraphs'], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][add_mode]' => 'select'], 'Update'); + $this->submitForm([], 'Save'); // Create paragraph type image. $this->addParagraphsType('image'); @@ -197,7 +199,7 @@ public function testParagraphsCreation() { $this->assertSession()->pageTextContains('text_image'); $this->assertSession()->pageTextContains('image'); // Make sure there is an edit link for each type. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Make sure the field UI appears. $this->assertSession()->linkExists('Manage fields'); $this->assertSession()->linkExists('Manage form display'); @@ -209,25 +211,25 @@ public function testParagraphsCreation() { $field_name = 'field_paragraphs'; // Click on the widget settings button to open the widget settings form. - $this->drupalPostForm(NULL, ['fields[field_paragraphs][type]' => 'paragraphs'], $field_name . "_settings_edit"); + $this->submitForm(['fields[field_paragraphs][type]' => 'paragraphs'], $field_name . "_settings_edit"); // Enable setting. $edit = array('fields[' . $field_name . '][settings_edit_form][settings][add_mode]' => 'button'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check if the setting is stored. $this->drupalGet('admin/structure/types/manage/article/form-display'); - $this->assertSession()->pageTextContains('Add mode: Buttons', 'Checking the settings value.'); + $this->assertSession()->pageTextContains('Add mode: Buttons'); - $this->drupalPostForm(NULL, array(), $field_name . "_settings_edit"); + $this->submitForm(array(), $field_name . "_settings_edit"); // Assert the 'Buttons' option is selected. $add_mode_option = $this->assertSession()->optionExists('edit-fields-field-paragraphs-settings-edit-form-settings-add-mode', 'button'); $this->assertTrue($add_mode_option->hasAttribute('selected'), 'Updated value is correct!.'); // Add two Text + Image paragraphs in article. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_image_add_more'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_image_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_image_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_image_add_more'); // Upload some images. $files = $this->getTestFiles('image'); @@ -240,34 +242,32 @@ public function testParagraphsCreation() { 'field_paragraphs[1][subform][field_text][0][value]' => 'Test text 2', 'files[field_paragraphs_1_subform_field_image_0]' => $file_system->realpath($files[1]->uri), ); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('article Test article has been created.'); $node = $this->drupalGetNodeByTitle('Test article'); - $img1_url = file_create_url(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[0]->filename)); - $img2_url = file_create_url(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[1]->filename)); - $img1_size = filesize($files[0]->uri); - $img2_size = filesize($files[1]->uri); - $img1_mime = \Drupal::service('file.mime_type.guesser')->guess($files[0]->uri); - $img2_mime = \Drupal::service('file.mime_type.guesser')->guess($files[1]->uri); + $img1_url = \Drupal::service('file_url_generator')->generateString(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[0]->filename)); + $img2_url = \Drupal::service('file_url_generator')->generateString(\Drupal::token()->replace('public://[date:custom:Y]-[date:custom:m]/' . $files[1]->filename)); + $img1_mime = \Drupal::service('file.mime_type.guesser')->guessMimeType($files[0]->uri); + $img2_mime = \Drupal::service('file.mime_type.guesser')->guessMimeType($files[1]->uri); // Check the text and image after publish. $this->assertSession()->pageTextContains('Test text 1'); - $this->assertSession()->responseContains('<img src="' . file_url_transform_relative($img1_url)); + $this->assertSession()->elementExists('css', 'img[src="' . $img1_url . '"]'); $this->assertSession()->pageTextContains('Test text 2'); - $this->assertSession()->responseContains('<img src="' . file_url_transform_relative($img2_url)); + $this->assertSession()->elementExists('css', 'img[src="' . $img2_url . '"]'); // Tests for "Edit mode" settings. // Test for closed setting. $this->drupalGet('admin/structure/types/manage/article/form-display'); // Click on the widget settings button to open the widget settings form. - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->submitForm(array(), "field_paragraphs_settings_edit"); // Enable setting. $edit = array('fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check if the setting is stored. - $this->assertSession()->pageTextContains('Edit mode: Closed', 'Checking the settings value.'); - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->assertSession()->pageTextContains('Edit mode: Closed'); + $this->submitForm(array(), "field_paragraphs_settings_edit"); // Assert the 'Closed' option is selected. $edit_mode_option = $this->assertSession()->optionExists('edit-fields-field-paragraphs-settings-edit-form-settings-edit-mode', 'closed'); $this->assertTrue($edit_mode_option->hasAttribute('selected'), 'Updated value correctly.'); @@ -280,14 +280,14 @@ public function testParagraphsCreation() { // Test for preview option. $this->drupalGet('admin/structure/types/manage/article/form-display'); - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->submitForm(array(), "field_paragraphs_settings_edit"); $edit = [ 'fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed', 'fields[field_paragraphs][settings_edit_form][settings][closed_mode]' => 'preview', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains('Edit mode: Closed', 'Checking the "Edit mode" setting value.'); - $this->assertSession()->pageTextContains('Closed mode: Preview', 'Checking the "Closed mode" settings value.'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('Edit mode: Closed'); + $this->assertSession()->pageTextContains('Closed mode: Preview'); $this->drupalGet('node/1/edit'); // The texts in the paragraphs should be visible. $this->assertSession()->responseNotContains('field_paragraphs[0][subform][field_text][0][value]'); @@ -297,7 +297,7 @@ public function testParagraphsCreation() { // Test for open option. $this->drupalGet('admin/structure/types/manage/article/form-display'); - $this->drupalPostForm(NULL, array(), "field_paragraphs_settings_edit"); + $this->submitForm(array(), "field_paragraphs_settings_edit"); // Assert the "Closed" and "Preview" options are selected. $edit_mode_option = $this->assertSession()->optionExists('edit-fields-field-paragraphs-settings-edit-form-settings-edit-mode', 'closed'); $this->assertTrue($edit_mode_option->hasAttribute('selected'), 'Correctly updated the "Edit mode" value.'); @@ -305,7 +305,7 @@ public function testParagraphsCreation() { $this->assertTrue($closed_mode_option->hasAttribute('selected'),'Correctly updated the "Closed mode" value.'); // Restore the value to Open for next test. $edit = array('fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'open'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/1/edit'); // The textareas for paragraphs should be visible. $this->assertSession()->responseContains('field_paragraphs[0][subform][field_text][0][value]'); @@ -318,30 +318,30 @@ public function testParagraphsCreation() { $this->drupalGet('node/' . $node->id() . '/edit'); // Check both paragraphs in edit page. $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', 'Test text 1'); - $this->assertSession()->responseContains('<a href="' . $img1_url . '" type="' . $img1_mime . '; length=' . $img1_size . '">' . $files[0]->filename . '</a>'); + $this->assertSession()->elementTextContains('css', 'A[href="' . $img1_url . '"][type^="' . $img1_mime . '"]', $files[0]->filename); $this->assertSession()->fieldValueEquals('field_paragraphs[1][subform][field_text][0][value]', 'Test text 2'); - $this->assertSession()->responseContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementTextContains('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]', $files[1]->filename); // Remove 2nd paragraph. $this->getSession()->getPage()->find('css', '[name="field_paragraphs_1_remove"]')->press(); $this->assertSession()->fieldNotExists('field_paragraphs[1][subform][field_text][0][value]'); - $this->assertSession()->responseNotContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementNotExists('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]'); // Assert the paragraph is not deleted unless the user saves the node. $this->drupalGet('node/' . $node->id() . '/edit'); - $this->assertSession()->responseContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementTextContains('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]', $files[1]->filename); // Remove the second paragraph. $this->getSession()->getPage()->find('css', '[name="field_paragraphs_1_remove"]')->press(); - $this->assertSession()->responseNotContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementNotExists('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]'); $edit = [ 'field_paragraphs[0][subform][field_image][0][alt]' => 'test_alt', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Assert the paragraph is deleted after the user saves the node. $this->drupalGet('node/' . $node->id() . '/edit'); - $this->assertSession()->responseNotContains('<a href="' . $img2_url . '" type="' . $img2_mime . '; length=' . $img2_size . '">' . $files[1]->filename . '</a>'); + $this->assertSession()->elementNotExists('css', 'A[href="' . $img2_url . '"][type^="' . $img2_mime . '"]'); // Delete the node. - $this->clickLink(t('Delete')); - $this->drupalPostForm(NULL, NULL, t('Delete')); + $this->clickLink('Delete'); + $this->submitForm([], 'Delete'); $this->assertSession()->pageTextContains('Test article has been deleted.'); // Check if the publish/unpublish option works. @@ -351,34 +351,34 @@ public function testParagraphsCreation() { 'fields[status][region]' => 'content', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, NULL, t('Add text_image')); + $this->submitForm([], 'Add text_image'); $this->assertSession()->responseContains('edit-field-paragraphs-0-subform-status-value'); $edit = [ 'title[0][value]' => 'Example publish/unpublish', 'field_paragraphs[0][subform][field_text][0][value]' => 'Example published and unpublished', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains(t('Example published and unpublished')); - $this->clickLink(t('Edit')); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('Example published and unpublished'); + $this->clickLink('Edit'); $edit = [ 'field_paragraphs[0][subform][status][value]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextNotContains(t('Example published and unpublished')); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextNotContains('Example published and unpublished'); // Set the fields as required. $this->drupalGet('admin/structure/types/manage/article/fields'); $this->clickLink('Edit', 1); - $this->drupalPostForm(NULL, ['preview_mode' => '1'], t('Save content type')); + $this->submitForm(['preview_mode' => '1'], 'Save content type'); $this->drupalGet('admin/structure/paragraphs_type/nested_test/fields'); $this->clickLink('Edit'); - $this->drupalPostForm(NULL, ['required' => TRUE], t('Save settings')); + $this->submitForm(['required' => TRUE], 'Save settings'); // Add a new article. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_nested_test_add_more'); + $this->submitForm([], 'field_paragraphs_nested_test_add_more'); // Ensure that nested header actions do not add a visible weight field. $this->assertSession()->fieldNotExists('field_paragraphs[0][subform][field_paragraphs][header_actions][_weight]'); @@ -386,7 +386,7 @@ public function testParagraphsCreation() { $edit = [ 'field_paragraphs[0][subform][field_paragraphs][add_more][add_more_select]' => 'image', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); + $this->submitForm($edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); // Test the new field is displayed. $this->assertSession()->fieldExists('files[field_paragraphs_0_subform_field_paragraphs_0_subform_field_image_only_0]'); @@ -395,11 +395,11 @@ public function testParagraphsCreation() { 'title[0][value]' => 'test required', 'files[field_paragraphs_0_subform_field_paragraphs_0_subform_field_image_only_0]' => $file_system->realpath($files[2]->uri), ); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $edit = [ 'field_paragraphs[0][subform][field_paragraphs][0][subform][field_image_only][0][alt]' => 'Alternative_text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('test required has been created.'); $this->assertSession()->responseNotContains('This value should not be null.'); @@ -417,38 +417,39 @@ public function testParagraphsCreation() { 'label' => 'unsupported field', 'field_name' => 'unsupportedfield', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); + $this->submitForm($edit, 'Save and continue'); $this->assertSession()->optionNotExists('edit-settings-target-type', 'paragraph'); // Test that all Paragraph types can be referenced if none is selected. $this->addParagraphsType('nested_double_test'); static::fieldUIAddExistingField('admin/structure/paragraphs_type/nested_double_test', 'field_paragraphs', 'paragraphs_1'); - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, [], 'Save'); - //$this->drupalPostForm(NULL, array('fields[field_paragraphs][type]' => 'entity_reference_revisions_entity_view'), t('Save')); + $this->clickLink('Manage form display'); + $this->submitForm([], 'Save'); + //$this->drupalPostForm(NULL, array('fields[field_paragraphs][type]' => 'entity_reference_revisions_entity_view'), 'Save'); static::fieldUIAddNewField('admin/structure/paragraphs_type/nested_double_test', 'paragraphs_2', 'paragraphs_2', 'entity_reference_revisions', array( 'settings[target_type]' => 'paragraph', 'cardinality' => '-1', ), array()); - $this->clickLink(t('Manage form display')); - $this->drupalPostForm(NULL, [], 'Save'); - $this->drupalPostForm('node/add/article', [], 'field_paragraphs_nested_test_add_more'); + $this->clickLink('Manage form display'); + $this->submitForm([], 'Save'); + $this->drupalGet('node/add/article'); + $this->submitForm([], 'field_paragraphs_nested_test_add_more'); $edit = [ 'field_paragraphs[0][subform][field_paragraphs][add_more][add_more_select]' => 'nested_double_test', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_paragraphs_0_subform_field_paragraphs_image_add_more'); + $this->submitForm($edit, 'field_paragraphs_0_subform_field_paragraphs_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_paragraphs_0_subform_field_paragraphs_image_add_more'); $edit = array( 'title[0][value]' => 'Nested twins', ); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Nested twins has been created.'); $this->assertSession()->pageTextNotContains('This entity (paragraph: ) cannot be referenced.'); // Set the fields as not required. $this->drupalGet('admin/structure/types/manage/article/fields'); $this->clickLink('Edit', 1); - $this->drupalPostForm(NULL, ['required' => FALSE], t('Save settings')); + $this->submitForm(['required' => FALSE], 'Save settings'); // Set the Paragraph field edit mode to "Closed" and the closed mode to // "Summary". @@ -471,42 +472,43 @@ public function testParagraphsCreation() { $node = $this->drupalGetNodeByTitle('Nested twins'); // Create a node with a reference in a Paragraph. - $this->drupalPostForm('node/add/article', [], 'field_paragraphs_node_test_add_more'); + $this->drupalGet('node/add/article'); + $this->submitForm([], 'field_paragraphs_node_test_add_more'); \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions(); $edit = [ 'field_paragraphs[0][subform][field_entity_reference][0][target_id]' => $node->label() . ' (' . $node->id() . ')', 'title[0][value]' => 'choke test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Delete the referenced node. $node->delete(); // Edit the node with the reference. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); // Adding another required paragraph and deleting that again should not // validate closed paragraphs but trying to save the node should. - $this->drupalPostForm(NULL, array(), 'field_paragraphs_node_test_add_more'); + $this->submitForm(array(), 'field_paragraphs_node_test_add_more'); $this->assertSession()->pageTextNotContains('The referenced entity (node: ' . $node->id() . ') does not exist.'); $this->assertSession()->fieldExists('field_paragraphs[1][subform][field_entity_reference][0][target_id]'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_1_remove'); + $this->submitForm(array(), 'field_paragraphs_1_remove'); $this->assertSession()->pageTextNotContains('The referenced entity (node: ' . $node->id() . ') does not exist.'); $this->assertSession()->fieldNotExists('field_paragraphs[1][subform][field_entity_reference][0][target_id]'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Validation error on collapsed paragraph field_entity_reference.0.target_id: The referenced entity (node: ' . $node->id() . ') does not exist.'); // Attempt to edit the Paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); // Try to collapse with an invalid reference. - $this->drupalPostForm(NULL, ['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => 'foo'], 'field_paragraphs_0_collapse'); + $this->submitForm(['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => 'foo'], 'field_paragraphs_0_collapse'); // Paragraph should be still in edit mode. $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_entity_reference][0][target_id]'); $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_entity_reference][1][target_id]'); // Assert the validation message. - $this->assertSession()->pageTextContains('There are no entities matching "foo".'); + $this->assertSession()->pageTextMatches('/There are no (entities|content items) matching "foo"./'); // Fix the broken reference. $node = $this->drupalGetNodeByTitle('Example publish/unpublish'); $edit = ['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => $node->label() . ' (' . $node->id() . ')']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('choke test has been updated.'); $this->assertSession()->linkExists('Example publish/unpublish'); // Delete the new referenced node. @@ -523,19 +525,19 @@ public function testParagraphsCreation() { // Attempt to edit the Paragraph. $this->drupalGet('node/' . $node->id() . '/edit'); // Attempt to edit the Paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); // Try to save with an invalid reference. $edit = ['field_paragraphs[0][subform][field_entity_reference][0][target_id]' => 'foo']; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains('There are no entities matching "foo".'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextMatches('/There are no (entities|content items) matching "foo"./'); // Remove the Paragraph and save the node. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_remove'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_0_remove'); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('choke test has been updated.'); $this->drupalGet('admin/structure/types/manage/article/fields'); $this->clickLink('Edit'); - $this->drupalPostForm(NULL, ['description' => 'This is the description of the field.'], 'Save settings'); + $this->submitForm(['description' => 'This is the description of the field.'], 'Save settings'); // Verify that the text displayed is correct when no paragraph has been // added yet. $this->drupalGet('node/add/article'); @@ -555,10 +557,27 @@ public function testParagraphsCreation() { * Helper function for revision counting. */ private function countRevisions($node, $paragraph1, $paragraph2, $revisions_count) { - $node_revisions_count = \Drupal::entityQuery('node')->condition('nid', $node->id())->allRevisions()->count()->execute(); - $this->assertEquals($node_revisions_count, $revisions_count); - $this->assertEquals(\Drupal::entityQuery('paragraph')->condition('id', $paragraph1)->allRevisions()->count()->execute(), $revisions_count); - $this->assertEquals(\Drupal::entityQuery('paragraph')->condition('id', $paragraph2)->allRevisions()->count()->execute(), $revisions_count); + $node_revisions_count = \Drupal::entityQuery('node') + ->condition('nid', $node->id()) + ->accessCheck(TRUE) + ->allRevisions() + ->count() + ->execute(); + $this->assertEquals($revisions_count, $node_revisions_count); + $paragraph1_revisions_count = \Drupal::entityQuery('paragraph') + ->condition('id', $paragraph1) + ->accessCheck(TRUE) + ->allRevisions() + ->count() + ->execute(); + $this->assertEquals($revisions_count, $paragraph1_revisions_count); + $paragraph2_revisions_count =\Drupal::entityQuery('paragraph') + ->condition('id', $paragraph2) + ->accessCheck(TRUE) + ->allRevisions() + ->count() + ->execute(); + $this->assertEquals($revisions_count, $paragraph2_revisions_count); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAlterByTypeTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAlterByTypeTest.php similarity index 81% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAlterByTypeTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAlterByTypeTest.php index ad78b8cc33168d39d8cdf5ed5e03ae8a1d0e816f..21bc4a3e97a8831885db903bd02f2015f709c386 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalAlterByTypeTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsAlterByTypeTest.php @@ -1,20 +1,20 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; /** - * Tests paragraphs experimental alter widget by type. + * Tests paragraphs stable alter widget by type. * * @group paragraphs */ -class ParagraphsExperimentalAlterByTypeTest extends ParagraphsExperimentalTestBase { +class ParagraphsAlterByTypeTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'paragraphs_test', ]; diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalBehaviorsTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsBehaviorsTest.php similarity index 83% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalBehaviorsTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsBehaviorsTest.php index c320af2fc6debb9bb8633ff5a3d49b2c39220886..4bdf79ecd520de0120f1166b1d9c10c2fb4e0b0f 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalBehaviorsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsBehaviorsTest.php @@ -1,20 +1,20 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; /** * Tests paragraphs behavior plugins. * * @group paragraphs */ -class ParagraphsExperimentalBehaviorsTest extends ParagraphsExperimentalTestBase { +class ParagraphsBehaviorsTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = ['image', 'file', 'views']; + protected static $modules = ['image', 'file', 'views']; /** * Tests the behavior plugins for paragraphs. @@ -34,14 +34,14 @@ public function testBehaviorPluginsFields() { $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); $this->assertSession()->fieldValueEquals('behavior_plugins[test_text_color][settings][default_color]', 'blue'); - $this->assertSession()->pageTextContains('Behavior plugins are only supported by the EXPERIMENTAL paragraphs widget'); + $this->assertSession()->pageTextContains('Behavior plugins are only supported by the stable paragraphs widget'); // Enable the test plugins, with an invalid configuration value. $edit = [ 'behavior_plugins[test_bold_text][enabled]' => TRUE, 'behavior_plugins[test_text_color][enabled]' => TRUE, 'behavior_plugins[test_text_color][settings][default_color]' => 'red', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Red can not be used as the default color.'); // Ensure the form can be saved with an invalid configuration value when @@ -51,7 +51,7 @@ public function testBehaviorPluginsFields() { 'behavior_plugins[test_text_color][enabled]' => FALSE, 'behavior_plugins[test_text_color][settings][default_color]' => 'red', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Saved the text_paragraph Paragraphs type.'); // Ensure it can be saved with a valid value and that the defaults are @@ -66,7 +66,8 @@ public function testBehaviorPluginsFields() { 'behavior_plugins[test_text_color][enabled]' => TRUE, 'behavior_plugins[test_text_color][settings][default_color]' => 'green', ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('Saved the text_paragraph Paragraphs type.'); $this->drupalGet('node/add/paragraphed_test'); @@ -95,7 +96,7 @@ public function testBehaviorPluginsFields() { $behavior_xpath = $this->xpath("//div[@id = 'edit-field-paragraphs-0-top']/following-sibling::*[1][@id = 'edit-field-paragraphs-0-behavior-plugins-test-bold-text']"); $this->assertNotEquals($behavior_xpath, FALSE, 'Behavior form position incorrect'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Asserting that the error message is shown. $this->assertSession()->pageTextContains('The only allowed values are blue and red.'); // Updating the text color to an allowed value. @@ -103,7 +104,7 @@ public function testBehaviorPluginsFields() { $edit = [ 'field_paragraphs[0][behavior_plugins][test_text_color][text_color]' => $plugin_text, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Assert that the class has been added to the element. $this->assertSession()->responseContains('class="red_plugin_text'); @@ -117,7 +118,7 @@ public function testBehaviorPluginsFields() { 'field_paragraphs[0][behavior_plugins][test_text_color][text_color]' => $updated_text, 'field_paragraphs[0][behavior_plugins][test_bold_text][bold_text]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->responseNotContains('class="red_plugin_text'); $this->assertSession()->responseContains('class="bold_plugin_text blue_plugin_text'); $this->clickLink('Edit'); @@ -135,7 +136,7 @@ public function testBehaviorPluginsFields() { $this->assertSession()->fieldNotExists('field_paragraphs[0][behavior_plugins][test_text_color][text_color]'); $this->assertSession()->fieldNotExists('field_paragraphs[0][behavior_plugins][test_bold_text][bold_text]'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); // Make sure that values don't change if a user without the 'edit behavior // plugin settings' permission saves a node with paragraphs and enabled @@ -156,46 +157,51 @@ public function testBehaviorPluginsFields() { $this->assertSession()->fieldExists('behavior_plugins[test_field_selection][enabled]'); $this->assertSession()->pageTextContains('Choose paragraph field to be applied.'); // Assert that Field Selection Filter plugin properly filters field types. - $this->assertSession()->optionExists('edit-behavior-plugins-test-field-selection-settings-field-selection-filter', t('Image')); + $this->assertSession()->optionExists('edit-behavior-plugins-test-field-selection-settings-field-selection-filter', 'Image'); // Check that Field Selection Plugin does not filter any field types. - $this->assertSession()->optionExists('edit-behavior-plugins-test-field-selection-settings-field-selection', t('Image')); - $this->assertSession()->optionExists('edit-behavior-plugins-test-field-selection-settings-field-selection', t('Text')); + $this->assertSession()->optionExists('edit-behavior-plugins-test-field-selection-settings-field-selection', 'Image'); + $this->assertSession()->optionExists('edit-behavior-plugins-test-field-selection-settings-field-selection', 'Text'); // Test a plugin without behavior fields. $edit = [ 'behavior_plugins[test_dummy_behavior][enabled]' => TRUE, 'behavior_plugins[test_text_color][enabled]' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save')); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_test_add_more'); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); + $this->submitForm($edit, 'Save'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_test_add_more'); $edit = [ 'title[0][value]' => 'paragraph with no fields', 'field_paragraphs[0][subform][field_text_test][0][value]' => 'my behavior plugin does not have any field', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->responseContains('dummy_plugin_text'); // Tests behavior plugin on paragraph type with no fields. $this->addParagraphsType('fieldless'); - $this->drupalPostForm('admin/structure/paragraphs_type/fieldless', ['behavior_plugins[test_dummy_behavior][enabled]' => TRUE], t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/fieldless'); + $this->submitForm(['behavior_plugins[test_dummy_behavior][enabled]' => TRUE], 'Save'); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_fieldless_add_more'); - $edit = ['title[0][value]' => t('Fieldless')]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm([], 'field_paragraphs_fieldless_add_more'); + $edit = ['title[0][value]' => 'Fieldless']; + $this->submitForm($edit, 'Save'); $this->assertSession()->statusCodeEquals(200); // Add a paragraphed content. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_test_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_test_add_more'); $edit = [ 'title[0][value]' => 'field_override_test', 'field_paragraphs[0][subform][field_text_test][0][value]' => 'This is a test', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Check that the summary does not have the user displayed. $node = $this->getNodeByTitle('field_override_test'); - $this->drupalPostForm('node/' . $node->id() . '/edit', [], 'field_paragraphs_0_collapse'); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm([], 'field_paragraphs_0_collapse'); $this->assertSession()->responseContains('class="paragraphs-description paragraphs-collapsed-description"><div class="paragraphs-content-wrapper"><span class="summary-content">This is a test'); } @@ -220,7 +226,8 @@ public function testCollapsedSummary() { 'behavior_plugins[test_bold_text][enabled]' => TRUE, 'behavior_plugins[test_text_color][enabled]' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); + $this->submitForm($edit, 'Save'); // Add a nested Paragraph type. $paragraph_type = 'nested_paragraph'; @@ -230,11 +237,13 @@ public function testCollapsedSummary() { $edit = [ 'behavior_plugins[test_bold_text][enabled]' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); + $this->submitForm($edit, 'Save'); // Add a node and enabled plugins. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_1_subform_paragraphs_text_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_1_subform_paragraphs_text_paragraph_add_more'); $this->assertSession()->fieldExists('field_paragraphs[0][behavior_plugins][test_bold_text][bold_text]'); $this->assertSession()->fieldExists('field_paragraphs[1][behavior_plugins][test_bold_text][bold_text]'); @@ -246,7 +255,7 @@ public function testCollapsedSummary() { 'field_paragraphs[1][subform][paragraphs][0][subform][field_text][0][value]' => 'nested_paragraph', 'field_paragraphs[1][behavior_plugins][test_bold_text][bold_text]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->clickLink('Edit'); @@ -260,11 +269,12 @@ public function testCollapsedSummary() { $this->assertSession()->responseContains('nested_paragraph</span></div><div class="paragraphs-plugin-wrapper"><span class="summary-plugin"><span class="summary-plugin-label">Bold</span>Yes</span></div></div>'); // Add an empty nested paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_nested_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); $edit = [ 'title[0][value]' => 'collapsed_test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check an empty nested paragraph summary. $this->clickLink('Edit'); @@ -292,7 +302,8 @@ public function testBehaviorSubform() { 'behavior_plugins[test_bold_text][enabled]' => TRUE, 'behavior_plugins[test_text_color][enabled]' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); + $this->submitForm($edit, 'Save'); // Add a nested Paragraph type. $paragraph_type = 'nested_paragraph'; @@ -305,12 +316,14 @@ public function testBehaviorSubform() { $edit = [ 'behavior_plugins[test_bold_text][enabled]' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); + $this->submitForm($edit, 'Save'); // Add a node and enabled plugins. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_nested_text_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_text_paragraph_add_more'); $edit = [ 'title[0][value]' => 'collapsed_test', 'field_paragraphs[0][subform][field_nested][0][subform][field_text][0][value]' => 'nested text paragraph', @@ -318,7 +331,7 @@ public function testBehaviorSubform() { 'field_paragraphs[1][subform][field_text][0][value]' => 'first_paragraph', 'field_paragraphs[1][behavior_plugins][test_bold_text][bold_text]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->clickLink('Edit'); $edit = [ @@ -327,7 +340,7 @@ public function testBehaviorSubform() { 'field_paragraphs[1][behavior_plugins][test_text_color][text_color]' => 'red', 'field_paragraphs[1][_weight]' => 0, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->clickLink('Edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][behavior_plugins][test_text_color][text_color]', 'red'); diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalConfigTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsConfigTest.php similarity index 85% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalConfigTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsConfigTest.php index 1e044b26d93704116fe8d6944fd881ca57ce117d..5f3e1249260428369404ed7e3f849b02f6bdd630 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalConfigTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsConfigTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\node\Entity\NodeType; @@ -10,14 +10,14 @@ * * @group paragraphs */ -class ParagraphsExperimentalConfigTest extends ParagraphsExperimentalTestBase { +class ParagraphsConfigTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = array( + protected static $modules = array( 'content_translation', ); @@ -49,19 +49,21 @@ public function testFieldTranslationDisabled() { 'settings[node][paragraphed_test][translatable]' => TRUE, 'settings[node][paragraphed_test][fields][field_paragraphs]' => FALSE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); // Create a node with a paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_paragraph_type_test_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_paragraph_type_test_add_more'); $edit = ['title[0][value]' => 'paragraphed_title']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Attempt to add a translation. $node = $this->drupalGetNodeByTitle('paragraphed_title'); $this->drupalGet('node/' . $node->id() . '/translations'); - $this->clickLink(t('Add')); + $this->clickLink('Add'); // Save the translation. - $this->drupalPostForm(NULL, [], t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('paragraphed_test paragraphed_title has been updated.'); } @@ -95,7 +97,8 @@ public function testContentTranslationForm() { 'settings[node][paragraphed_test][translatable]' => TRUE, 'settings[node][paragraphed_test][fields][field_paragraphs]' => FALSE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); // Check error message is still not displayed. $this->drupalGet('admin/config/regional/content-language'); @@ -112,7 +115,8 @@ public function testContentTranslationForm() { 'settings[node][paragraphed_test][translatable]' => TRUE, 'settings[node][paragraphed_test][fields][field_paragraphs]' => TRUE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); // Check content type field management error. $this->drupalGet('admin/structure/types/manage/paragraphed_test/fields/node.paragraphed_test.field_paragraphs'); @@ -126,8 +130,8 @@ public function testContentTranslationForm() { 'label' => 'new_no_field_paragraphs', 'field_name' => 'new_no_field_paragraphs', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); $this->assertSession()->pageTextNotContains('Paragraphs fields do not support translation.'); $this->assertSession()->responseNotContains('<div class="messages messages--warning'); } @@ -174,16 +178,16 @@ public function testIncludedParagraphTypes() { 'settings[handler_settings][negate]' => 0, 'settings[handler_settings][target_bundles_drag_drop][paragraph_type_test][enabled]' => 1, ]; - $this->drupalPostForm(NULL, $edit, 'Save settings'); + $this->submitForm($edit, 'Save settings'); $this->assertSession()->pageTextContains('Saved paragraphs configuration.'); $this->drupalGet('node/add/paragraphed_test'); - $this->assertSession()->pageTextContains('Add paragraph_type_test'); - $this->assertSession()->pageTextNotContains('Add text'); + $this->assertSession()->buttonExists('Add paragraph_type_test'); + $this->assertSession()->responseNotContains('Add text'); $edit = [ 'title[0][value]' => 'Testing included types' ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Testing included types has been created.'); // Include all types. @@ -193,7 +197,7 @@ public function testIncludedParagraphTypes() { 'settings[handler_settings][target_bundles_drag_drop][text][enabled]' => 1, 'settings[handler_settings][target_bundles_drag_drop][paragraph_type_test][enabled]' => 1, ]; - $this->drupalPostForm(NULL, $edit, 'Save settings'); + $this->submitForm($edit, 'Save settings'); $this->drupalGet('node/add/paragraphed_test'); $button_paragraphed_type_test = $this->xpath('//input[@id=:id]', [':id' => 'paragraphs-paragraph-type-test-add-more']); $button_text = $this->xpath('//input[@id=:id]', [':id' => 'paragraphs-text-add-more']); @@ -202,7 +206,7 @@ public function testIncludedParagraphTypes() { $edit = [ 'title[0][value]' => 'Testing all excluded types' ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Testing all excluded types has been created.'); } @@ -221,16 +225,16 @@ public function testExcludedParagraphTypes() { 'settings[handler_settings][negate]' => 1, 'settings[handler_settings][target_bundles_drag_drop][text][enabled]' => 1, ]; - $this->drupalPostForm(NULL, $edit, 'Save settings'); + $this->submitForm($edit, 'Save settings'); $this->assertSession()->pageTextContains('Saved paragraphs configuration.'); $this->drupalGet('node/add/paragraphed_test'); - $this->assertSession()->pageTextContains('Add paragraph_type_test'); - $this->assertSession()->pageTextNotContains('Add text'); + $this->assertSession()->buttonExists('Add paragraph_type_test'); + $this->assertSession()->responseNotContains('Add text'); $edit = [ 'title[0][value]' => 'Testing excluded types' ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Testing excluded types has been created.'); // Exclude all types. @@ -240,13 +244,13 @@ public function testExcludedParagraphTypes() { 'settings[handler_settings][target_bundles_drag_drop][text][enabled]' => 1, 'settings[handler_settings][target_bundles_drag_drop][paragraph_type_test][enabled]' => 1, ]; - $this->drupalPostForm(NULL, $edit, 'Save settings'); + $this->submitForm($edit, 'Save settings'); $this->drupalGet('node/add/paragraphed_test'); $this->assertSession()->pageTextContains('You are not allowed to add any of the Paragraph types.'); $edit = [ 'title[0][value]' => 'Testing all excluded types' ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Testing all excluded types has been created.'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalContactTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsContactTest.php similarity index 80% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalContactTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsContactTest.php index 23c1ac17213b9bb21242304c4fe1e544176b1dc3..136754447cd3106f3cdd7c2115bd8a93a5550961 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalContactTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsContactTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\contact\Entity\ContactForm; @@ -9,14 +9,14 @@ * * @group paragraphs */ -class ParagraphsExperimentalContactTest extends ParagraphsExperimentalTestBase { +class ParagraphsContactTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = array( + protected static $modules = array( 'contact', ); @@ -39,10 +39,10 @@ public function testContactForm() { $this->addParagraphsField($contact_form->id(), 'paragraphs', 'contact_message'); // Add a paragraph to the contact form. $this->drupalGet('contact/test_contact_form'); - $this->drupalPostForm(NULL, [], 'paragraphs_paragraphs_contact_add_more'); + $this->submitForm([], 'paragraphs_paragraphs_contact_add_more'); // Check that the paragraph is displayed. $this->assertSession()->pageTextContains('paragraphs_contact'); - $this->drupalPostForm(NULL, [], 'paragraphs_0_remove'); + $this->submitForm([], 'paragraphs_0_remove'); $elements = $this->xpath('//table[starts-with(@id, :id)]/tbody', [':id' => 'paragraphs-values']); $header = $this->xpath('//table[starts-with(@id, :id)]/thead', [':id' => 'paragraphs-values']); $this->assertEquals($elements, []); diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalContentModerationTranslationsTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsContentModerationTranslationsTest.php similarity index 97% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalContentModerationTranslationsTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsContentModerationTranslationsTest.php index fed2b6e0a62029aa227445ec3b5f362e9b8f80c9..b0ed7eb169cfef4ca57b40b42517740389d054e1 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalContentModerationTranslationsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsContentModerationTranslationsTest.php @@ -1,8 +1,9 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; use Drupal\Tests\paragraphs\Traits\ParagraphsLastEntityQueryTrait; /** @@ -10,16 +11,16 @@ * * @group paragraphs */ -class ParagraphsExperimentalContentModerationTranslationsTest extends ParagraphsExperimentalTestBase { +class ParagraphsContentModerationTranslationsTest extends ParagraphsTestBase { - use ParagraphsLastEntityQueryTrait; + use ParagraphsLastEntityQueryTrait, ParagraphsCoreVersionUiTestTrait; /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_test', 'paragraphs', @@ -41,13 +42,9 @@ class ParagraphsExperimentalContentModerationTranslationsTest extends Paragraphs /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); - // Place the breadcrumb, tested in fieldUIAddNewField(). - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); $this->addParagraphedContentType('paragraphed_test'); @@ -94,7 +91,7 @@ protected function setUp() { $edit = [ 'behavior_plugins[test_bold_text][enabled]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Add a text field to the text_paragraph type. static::fieldUIAddNewField('admin/structure/paragraphs_type/text', 'text', 'Text', 'text_long', [], []); @@ -121,7 +118,7 @@ protected function setUp() { 'settings[paragraph][text][fields][field_untranslatable]' => FALSE, 'settings[paragraph][container][fields][field_paragraphs]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save configuration')); + $this->submitForm($edit, 'Save configuration'); } /** diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalDragAndDropModeTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsDragAndDropModeTest.php similarity index 95% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalDragAndDropModeTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsDragAndDropModeTest.php index c99d382fc90afaffbd09ea53233e25e42eafbe01..e2aaaacbb2fdfbfc211e02e032c3a4b20a8ceacf 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalDragAndDropModeTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsDragAndDropModeTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\node\Entity\Node; @@ -11,12 +11,12 @@ * * @group paragraphs */ -class ParagraphsExperimentalDragAndDropModeTest extends ParagraphsExperimentalTestBase { +class ParagraphsDragAndDropModeTest extends ParagraphsTestBase { /** * Modules to be enabled. */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs', 'field' @@ -25,7 +25,7 @@ class ParagraphsExperimentalDragAndDropModeTest extends ParagraphsExperimentalTe /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->addParagraphedContentType('paragraphed_test', 'field_paragraphs'); $this->addParagraphsType('paragraphs_container'); @@ -110,7 +110,7 @@ public function testChangeParagraphParentWeight() { $this->assertEquals($text_paragraph_2->get('parent_type')->value, 'paragraph'); $this->drupalGet('/node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); $assert_session = $this->assertSession(); $assert_session->hiddenFieldValueEquals('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][_path]', 'field_paragraphs][0][paragraphs_container_paragraphs'); @@ -133,8 +133,8 @@ public function testChangeParagraphParentWeight() { ->hiddenFieldExists('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][1][_weight]') ->setValue(0); - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Complete drag & drop'); + $this->submitForm([], 'Save'); // Check the new structure of the node and its paragraphs. \Drupal::entityTypeManager()->getStorage('node')->resetCache(); @@ -210,7 +210,7 @@ public function testChangeParagraphContainerMove() { // Change the path of the text paragraph to the empty container as its // parent. $this->drupalGet('/node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); // Ensure that the summary is displayed correctly. $this->assertSession()->elementTextContains('css', '.paragraphs-dragdrop-wrapper li:nth-of-type(1)', 'Test text 1'); @@ -219,7 +219,7 @@ public function testChangeParagraphContainerMove() { $this->assertSession() ->hiddenFieldExists('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][_path]') ->setValue('field_paragraphs][1][paragraphs_container_paragraphs'); - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); + $this->submitForm([], 'Complete drag & drop'); // Ensure the summary is displayed correctly for the collapsed paragraphs. $this->assertSession()->elementTextNotContains('css', '.field--name-field-paragraphs tbody tr:nth-of-type(1) .paragraph-summary', 'Test text 1'); @@ -227,12 +227,12 @@ public function testChangeParagraphContainerMove() { // Ensure that the summary was updated correctly when going back to drag and // drop mode. - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); $this->assertSession()->elementTextNotContains('css', '.paragraphs-dragdrop-wrapper li:nth-of-type(1)', 'Test text 1'); $this->assertSession()->elementTextContains('css', '.paragraphs-dragdrop-wrapper li:nth-of-type(2)', 'Test text 1'); - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); + $this->submitForm([], 'Complete drag & drop'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); // Check that the parent of the text paragraph is the second paragraph // container. @@ -337,7 +337,7 @@ public function testMultipleChangesParagraphs() { $edit = [ 'field_paragraphs[2][subform][paragraphs_container_paragraphs][0][subform][field_text][0][value]' => 'new paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Drag & drop'); + $this->submitForm($edit, 'Drag & drop'); // Change the structure of the node, third text paragraph goes to first // container, the first text paragraph goes to the second container (child @@ -370,7 +370,7 @@ public function testMultipleChangesParagraphs() { ->setValue(1); // Save immediately, without separately confirming the widget changes. - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); // Reset the cache to make sure that the loaded parents are the new ones. \Drupal::entityTypeManager()->getStorage('paragraph')->resetCache(); @@ -450,7 +450,7 @@ public function testChangeParagraphContainerMultipleFields() { // Change the path of the text paragraph to the empty container as its // parent. $this->drupalGet('/node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); // Make sure that the second paragraph field is still displayed normally by // checking that it displays the edit button, as it is closed by default. @@ -462,7 +462,7 @@ public function testChangeParagraphContainerMultipleFields() { $this->assertSession() ->hiddenFieldExists('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][_path]') ->setValue('field_paragraphs][1][paragraphs_container_paragraphs'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); // Check that the parent of the text paragraph is the second paragraph // container. @@ -548,16 +548,16 @@ public function testChangeParagraphMoveBeforeReorder() { 'field_paragraphs[1][_weight]' => 2, 'field_paragraphs[2][_weight]' => 1, ]; - $this->drupalPostForm(NULL, $edit, 'Drag & drop'); + $this->submitForm($edit, 'Drag & drop'); // Change the path of the text paragraph to the empty container as its // parent. $this->assertSession() ->hiddenFieldExists('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][_path]') ->setValue('field_paragraphs][1][paragraphs_container_paragraphs'); - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); + $this->submitForm([], 'Complete drag & drop'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); // Check that the parent of the text paragraph is the second paragraph // container. @@ -633,7 +633,7 @@ public function testChangeParagraphMoveAfterDelete() { // Delete the first container, move the text 2 paragraph into the second // container. $this->getSession()->getPage()->pressButton('field_paragraphs_0_remove'); - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); $assert_session = $this->assertSession(); @@ -649,8 +649,8 @@ public function testChangeParagraphMoveAfterDelete() { ->hiddenFieldExists('field_paragraphs[dragdrop][field_paragraphs][list][1][_weight]') ->setValue(0); - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Complete drag & drop'); + $this->submitForm([], 'Save'); // Check that the parent of the text paragraph is the second paragraph // container. @@ -715,7 +715,7 @@ public function testChangeParagraphMoveAllFromTopLevelContainer() { $this->assertEquals($text_paragraph_2->get('parent_type')->value, 'paragraph'); $this->drupalGet('/node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); $assert_session = $this->assertSession(); $assert_session->hiddenFieldValueEquals('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][_path]', 'field_paragraphs][0][paragraphs_container_paragraphs'); @@ -738,8 +738,8 @@ public function testChangeParagraphMoveAllFromTopLevelContainer() { ->hiddenFieldExists('field_paragraphs[dragdrop][field_paragraphs][list][0][_weight]') ->setValue(2); - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Complete drag & drop'); + $this->submitForm([], 'Save'); // Check the new structure of the node and its paragraphs. \Drupal::entityTypeManager()->getStorage('node')->resetCache(); @@ -818,7 +818,7 @@ public function testChangeParagraphMoveAllFromNestedContainer() { $this->assertEquals($text_paragraph_2->get('parent_type')->value, 'paragraph'); $this->drupalGet('/node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); $assert_session = $this->assertSession(); $assert_session->hiddenFieldValueEquals('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][_path]', 'field_paragraphs][0][paragraphs_container_paragraphs][0][paragraphs_container_paragraphs'); @@ -842,8 +842,8 @@ public function testChangeParagraphMoveAllFromNestedContainer() { ->hiddenFieldExists('field_paragraphs[dragdrop][field_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][0][dragdrop][paragraphs_container_paragraphs][list][1][_weight]') ->setValue(2); - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Complete drag & drop'); + $this->submitForm([], 'Save'); // Check the new structure of the node and its paragraphs. \Drupal::entityTypeManager()->getStorage('node')->resetCache(); @@ -884,10 +884,10 @@ public function testEmptyNodeTitle() { $this->getSession()->getPage()->pressButton('Add text'); // Enable drag and drop. - $this->drupalPostForm(NULL, [], 'Drag & drop'); + $this->submitForm([], 'Drag & drop'); // Complete drag and drop. - $this->drupalPostForm(NULL, [], 'Complete drag & drop'); + $this->submitForm([], 'Complete drag & drop'); $this->assertSession()->fieldExists('field_paragraphs[0][subform][field_text][0][value]'); $this->assertSession()->pageTextNotContains('Title field is required.'); diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalDuplicateFeatureTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsDuplicateFeatureTest.php similarity index 80% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalDuplicateFeatureTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsDuplicateFeatureTest.php index bf13604b201d63f8d0c2d425c8c2210a6cde3311..513df797155c7cead770e5bd4a864015518b7da2 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalDuplicateFeatureTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsDuplicateFeatureTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\field\Entity\FieldStorageConfig; @@ -9,9 +9,9 @@ * * @group paragraphs */ -class ParagraphsExperimentalDuplicateFeatureTest extends ParagraphsExperimentalTestBase { +class ParagraphsDuplicateFeatureTest extends ParagraphsTestBase { - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs', 'field', @@ -33,8 +33,9 @@ public function testDuplicateButton() { // Add a text field to the text_paragraph type. static::fieldUIAddNewField('admin/structure/paragraphs_type/' . $paragraph_type, 'text', 'Text', 'text_long', [], []); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); // Create a node with a Paragraph. $edit = [ @@ -43,14 +44,14 @@ public function testDuplicateButton() { 'field_paragraphs[1][subform][field_text][0][value]' => 'B', 'field_paragraphs[2][subform][field_text][0][value]' => 'C', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('paragraphs_mode_test'); $this->drupalGet('node/' . $node->id() . '/edit'); // Click "Duplicate" button on A and move C to the first position. $edit = ['field_paragraphs[2][_weight]' => -1]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_duplicate'); + $this->submitForm($edit, 'field_paragraphs_0_duplicate'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', 'A'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][_weight]', 1); $this->assertSession()->fieldValueEquals('field_paragraphs[1][subform][field_text][0][value]', 'B'); @@ -69,7 +70,7 @@ public function testDuplicateButton() { ]; // Save and check if all paragraphs are present in the correct order. - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', 'A'); $this->assertSession()->fieldValueEquals('field_paragraphs[1][subform][field_text][0][value]', 'A'); @@ -77,9 +78,9 @@ public function testDuplicateButton() { $this->assertSession()->fieldValueEquals('field_paragraphs[3][subform][field_text][0][value]', 'B'); // Delete the second A, then duplicate C. - $this->drupalPostForm(NULL, [], 'field_paragraphs_1_remove'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_2_duplicate'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_1_remove'); + $this->submitForm([], 'field_paragraphs_2_duplicate'); + $this->submitForm([], 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', 'A'); @@ -92,10 +93,10 @@ public function testDuplicateButton() { // Disable show duplicate action. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); $this->assertSession()->pageTextContains('Features: Duplicate, Collapse / Edit all'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][features][duplicate]' => FALSE], t('Update')); + $this->submitForm([], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][features][duplicate]' => FALSE], 'Update'); $this->assertSession()->pageTextContains('Features: Collapse / Edit all'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); // Check that the duplicate action is not present. $this->assertSession()->buttonNotExists('field_paragraphs_0_duplicate'); @@ -104,10 +105,10 @@ public function testDuplicateButton() { // Enable show duplicate action. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); $this->assertSession()->pageTextContains('Features: Collapse / Edit all'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][features][duplicate]' => TRUE], t('Update')); + $this->submitForm([], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][features][duplicate]' => TRUE], 'Update'); $this->assertSession()->pageTextContains('Features: Duplicate, Collapse / Edit all'); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); // Check that the duplicate action is present. $this->assertSession()->buttonExists('field_paragraphs_0_duplicate'); @@ -136,30 +137,32 @@ public function testDuplicateButtonWithNesting() { 'settings[target_type]' => 'paragraph', 'cardinality' => '-1', ], []); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_nested_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); // Create a node with a Paragraph. $edit = [ 'title[0][value]' => 'paragraphs_mode_test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('paragraphs_mode_test'); // Add a text field to nested paragraph. $text = 'recognizable_text'; - $this->drupalPostForm('node/' . $node->id() . '/edit', [], 'field_paragraphs_0_subform_field_nested_text_add_more'); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_text_add_more'); $edit = [ 'field_paragraphs[0][subform][field_nested][0][subform][field_text][0][value]' => $text, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Switch mode to closed. $this->setParagraphsWidgetMode('paragraphed_test', 'field_paragraphs', 'closed'); $this->drupalGet('node/' . $node->id() . '/edit'); // Click "Duplicate" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_duplicate'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_duplicate'); + $this->submitForm([], 'field_paragraphs_0_edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_nested][0][subform][field_text][0][value]', $text); $this->assertSession()->fieldValueEquals('field_paragraphs[1][subform][field_nested][0][subform][field_text][0][value]', $text); @@ -171,7 +174,7 @@ public function testDuplicateButtonWithNesting() { // Save and check if the changed text paragraph value of the duplicated // paragraph is not the same as in the original paragraph. - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $page_text = $this->getSession()->getPage()->getText(); $text_nr_found = substr_count($page_text, $text); @@ -199,19 +202,20 @@ public function testDuplicateButtonWithLimitedCardinality() { // Add a text field to the text_paragraph type. static::fieldUIAddNewField('admin/structure/paragraphs_type/' . $paragraph_type, 'text', 'Text', 'text_long', [], []); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); $edit = [ 'title[0][value]' => 'paragraphs_mode_test', 'field_paragraphs[0][subform][field_text][0][value]' => 'A', 'field_paragraphs[1][subform][field_text][0][value]' => 'B', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('paragraphs_mode_test'); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->assertNoField('field_paragraphs_0_duplicate'); - $this->assertNoField('field_paragraphs_1_duplicate'); + $this->assertSession()->fieldNotExists('field_paragraphs_0_duplicate'); + $this->assertSession()->fieldNotExists('field_paragraphs_1_duplicate'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalEditModesTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsEditModesTest.php similarity index 74% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalEditModesTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsEditModesTest.php index 6db5857c76c83af38220acedf33880486ae0f5a7..83ad6406c5015c40fa417793f21afd30c3ca44db 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalEditModesTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsEditModesTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\block_content\Entity\BlockContent; @@ -9,14 +9,14 @@ * * @group paragraphs */ -class ParagraphsExperimentalEditModesTest extends ParagraphsExperimentalTestBase { +class ParagraphsEditModesTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'image', 'block_field', 'block_content', @@ -48,12 +48,13 @@ public function testCollapsedSummary() { // Set edit mode to closed. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); - $this->drupalPostForm(NULL, [], "field_paragraphs_settings_edit"); + $this->submitForm([], "field_paragraphs_settings_edit"); $edit = ['fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Add a paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_image_text_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_title_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_image_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_title_add_more'); $files = $this->getTestFiles('image'); $file_system = \Drupal::service('file_system'); @@ -65,61 +66,61 @@ public function testCollapsedSummary() { 'files[field_paragraphs_0_subform_field_image_0]' => $file_system->realpath($files[0]->uri), 'field_paragraphs[1][subform][field_title][0][value]' => 'Title example', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, [], t('Add user_paragraph')); + $this->submitForm($edit, 'Save'); + $this->clickLink('Edit'); + $this->submitForm([], 'Add user_paragraph'); $edit = [ 'field_paragraphs[2][subform][field_user][0][target_id]' => $this->admin_user->label() . ' (' . $this->admin_user->id() . ')', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Assert the summary is correctly generated. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->responseContains('<span class="summary-content">' . $files[0]->filename . '</span>, <span class="summary-content">text_summary</span>'); $this->assertSession()->responseContains('<span class="summary-content">' . $this->admin_user->label()); $this->assertSession()->responseContains('<span class="summary-content">Title example'); // Edit and remove alternative text. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); $edit = [ 'field_paragraphs[0][subform][field_image][0][alt]' => 'alternative_text_summary', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); // Assert the summary is correctly generated. $this->assertSession()->responseContains('<span class="summary-content">alternative_text_summary</span>, <span class="summary-content">text_summary</span>'); // Remove image. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_image_0_remove_button'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_subform_field_image_0_remove_button'); + $this->submitForm([], 'Save'); // Assert the summary is correctly generated. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->responseContains('<span class="summary-content">text_summary'); $this->addParagraphsType('nested_paragraph'); static::fieldUIAddNewField('admin/structure/paragraphs_type/nested_paragraph', 'nested_content', 'Nested Content', 'entity_reference_revisions', ['settings[target_type]' => 'paragraph'], []); $this->drupalGet('admin/structure/paragraphs_type/nested_paragraph/form-display'); - $this->drupalPostForm(NULL, ['fields[field_nested_content][type]' => 'entity_reference_paragraphs'], t('Save')); + $this->submitForm(['fields[field_nested_content][type]' => 'entity_reference_paragraphs'], 'Save'); $test_user = $this->drupalCreateUser([]); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, t('Add nested_paragraph')); - $this->drupalPostForm(NULL, NULL, t('field_paragraphs_0_subform_field_nested_content_user_paragraph_add_more')); + $this->submitForm([], 'Add nested_paragraph'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_content_user_paragraph_add_more'); $edit = [ 'title[0][value]' => 'Node title', 'field_paragraphs[0][subform][field_nested_content][0][subform][field_user][0][target_id]' => $test_user->label() . ' (' . $test_user->id() . ')', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Create an orphaned ER field item by deleting the target entity. $test_user->delete(); $nodes = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['title' => 'Node title']); $this->drupalGet('node/' . current($nodes)->id() . '/edit'); - $this->drupalPostForm(NULL, [], t('field_paragraphs_0_edit')); - $this->drupalPostForm(NULL, [], t('field_paragraphs_0_collapse')); + $this->submitForm([], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_collapse'); $this->assertSession()->statusCodeEquals(200); // Add a Block Paragraphs type. @@ -136,14 +137,14 @@ public function testCollapsedSummary() { $this->placeBlock($after_block2->id()); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_block_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_block_paragraph_add_more'); $edit = [ 'field_paragraphs[0][subform][field_block][0][plugin_id]' => 'block_content:' . $after_block2->uuid(), ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); $this->assertSession()->responseContains('<span class="summary-content">Llama custom block'); $edit = ['title[0][value]' => 'Test llama block']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Delete the block. $after_block2->delete(); // Attempt to edit the node when the node is deleted. @@ -156,23 +157,24 @@ public function testCollapsedSummary() { $this->addParagraphsType($paragraph_type); static::fieldUIAddNewField('admin/structure/paragraphs_type/' . $paragraph_type, 'link', 'Link', 'link', [], []); // Create a node with a link paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_link_paragraph_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_link_paragraph_add_more'); $edit = [ 'title[0][value]' => 'Test link', 'field_paragraphs[0][subform][field_link][0][uri]' => 'http://www.google.com', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check the summary when no link title is provided. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->responseContains('<span class="summary-content">http://www.google.com'); // Set a link title. - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); $edit = [ 'field_paragraphs[0][subform][field_link][0][title]' => 'Link title', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check the summary when the link title is set. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->responseContains('<span class="summary-content">Link title'); // Allow the user to select if the paragraphs is published or not. @@ -180,30 +182,34 @@ public function testCollapsedSummary() { 'fields[status][region]' => 'content', 'fields[status][type]' => 'boolean_checkbox' ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $title_paragraphs_type . '/form-display', $edit, 'Save'); + $this->drupalGet('admin/structure/paragraphs_type/' . $title_paragraphs_type . '/form-display'); + $this->submitForm($edit, 'Save'); $edit = [ 'fields[field_nested_content][type]' => 'paragraphs', 'fields[status][region]' => 'content', 'fields[status][type]' => 'boolean_checkbox' ]; - $this->drupalPostForm('admin/structure/paragraphs_type/nested_paragraph/form-display', $edit, 'Save'); + $this->drupalGet('admin/structure/paragraphs_type/nested_paragraph/form-display'); + $this->submitForm($edit, 'Save'); // Add a unpublished text paragraph and check its summary when unpublished. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_title_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_title_add_more'); $edit = [ 'title[0][value]' => 'Access summary test', 'field_paragraphs[0][subform][field_title][0][value]' => 'memorable_summary_title', 'field_paragraphs[0][subform][status][value]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextNotContains('memorable_summary_title'); $node = $this->getNodeByTitle('Access summary test'); $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->responseContains('<span class="summary-content">memorable_summary_title'); $this->assertEquals(1, count($this->xpath("//*[contains(@class, 'paragraphs-icon-view')]"))); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_nested_content_title_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_content_title_add_more'); // Add a nested paragraph and with the parent unpublished, check the // summary. @@ -213,14 +219,14 @@ public function testCollapsedSummary() { 'field_paragraphs[0][subform][field_nested_content][0][subform][status][value]' => FALSE, 'field_paragraphs[0][subform][field_nested_content][0][subform][field_title][0][value]' => 'memorable_nested_summary_title', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextNotContains('memorable_nested_summary_title'); $node = $this->getNodeByTitle('Access nested summary test'); $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->responseContains('<span class="summary-content">memorable_nested_summary_title'); $this->assertEquals(1, count($this->xpath("//*[contains(@class, 'paragraphs-icon-view')]"))); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_nested_content_0_collapse'); + $this->submitForm([], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_content_0_collapse'); $this->assertSession()->responseContains('<span class="summary-content">memorable_nested_summary_title'); $this->assertEquals(1, count($this->xpath("//*[contains(@class, 'paragraphs-icon-view')]"))); @@ -232,8 +238,8 @@ public function testCollapsedSummary() { $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->responseContains('<span class="summary-content">memorable_nested_summary_title'); $this->assertEquals(1, count($this->xpath("//*[contains(@class, 'paragraphs-icon-view')]"))); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_nested_content_0_collapse'); + $this->submitForm([], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_content_0_collapse'); $this->assertSession()->responseContains('<span class="summary-content">memorable_nested_summary_title'); $this->assertEquals(1, count($this->xpath("//*[contains(@class, 'paragraphs-icon-view')]"))); } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalEntityTranslationWithNonTranslatableParagraphs.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php similarity index 71% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalEntityTranslationWithNonTranslatableParagraphs.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php index 766535c702bd01bde8757db34815aef616a8439a..98da3e6449aae660a3dbf16aefb644585cfe1ee1 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalEntityTranslationWithNonTranslatableParagraphs.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsEntityTranslationWithNonTranslatableParagraphs.php @@ -1,20 +1,20 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; /** * Tests the translation of heavily nested / specialized setup. * * @group paragraphs */ -class ParagraphsExperimentalEntityTranslationWithNonTranslatableParagraphs extends ParagraphsExperimentalTestBase { +class ParagraphsEntityTranslationWithNonTranslatableParagraphs extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'language', 'content_translation', ]; @@ -22,7 +22,7 @@ class ParagraphsExperimentalEntityTranslationWithNonTranslatableParagraphs exten /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->admin_user = $this->drupalCreateUser([], NULL, TRUE); @@ -32,11 +32,13 @@ protected function setUp() { $edit = array( 'predefined_langcode' => 'de', ); - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + $this->drupalGet('admin/config/regional/language/add'); + $this->submitForm($edit, 'Add language'); $edit = array( 'predefined_langcode' => 'fr', ); - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + $this->drupalGet('admin/config/regional/language/add'); + $this->submitForm($edit, 'Add language'); // Create article content type with a paragraphs field. $this->addParagraphedContentType('article', 'field_paragraphs'); @@ -45,7 +47,8 @@ protected function setUp() { $edit = array( 'language_configuration[content_translation]' => TRUE, ); - $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type')); + $this->drupalGet('admin/structure/types/manage/article'); + $this->submitForm($edit, 'Save content type'); $this->drupalGet('admin/structure/types/manage/article'); // Ensue the paragraphs field itself isn't translatable - this would be a @@ -53,7 +56,8 @@ protected function setUp() { $edit = array( 'translatable' => FALSE, ); - $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_paragraphs', $edit, t('Save settings')); + $this->drupalGet('admin/structure/types/manage/article/fields/node.article.field_paragraphs'); + $this->submitForm($edit, 'Save settings'); // Add Paragraphs type. $this->addParagraphsType('test_paragraph_type'); @@ -79,30 +83,30 @@ public function testParagraphsIEFTranslation() { $edit = [ 'title[0][value]' => 'Title English', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Add french translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add'), 1); + $this->clickLink('Translate'); + $this->clickLink('Add', 1); // Make sure that the original paragraph text is displayed. $this->assertSession()->pageTextContains('Title English'); $edit = array( 'title[0][value]' => 'Title French', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('article Title French has been updated.'); // Add german translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add')); + $this->clickLink('Translate'); + $this->clickLink('Add'); // Make sure that the original paragraph text is displayed. $this->assertSession()->pageTextContains('Title English'); $edit = array( 'title[0][value]' => 'Title German', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('article Title German has been updated.'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalFieldGroupTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsFieldGroupTest.php similarity index 70% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalFieldGroupTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsFieldGroupTest.php index a80cbd0ed1d26d0c2446aff8e47f398232539bb9..3f2223a653354252c540b778447234fcdcc54202 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalFieldGroupTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsFieldGroupTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; /** * Tests the field group on node. @@ -8,14 +8,14 @@ * @group paragraphs * @requires module field_group */ -class ParagraphsExperimentalFieldGroupTest extends ParagraphsExperimentalTestBase { +class ParagraphsFieldGroupTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'field_group', ]; @@ -41,22 +41,25 @@ public function testFieldGroup() { 'label' => 'paragraph_field_group_title', 'group_name' => 'field' ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display/add-group', $edit, t('Save and continue')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display/add-group'); + $this->submitForm($edit, 'Save and continue'); $edit = [ 'format_settings[label]' => 'field_group' ]; - $this->drupalPostForm(NULL, $edit, t('Create group')); + $this->submitForm($edit, 'Create group'); // Put the text field into the field group. $edit = [ 'fields[group_field][region]' => 'content', 'fields[field_text][parent]' => 'group_field' ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display', $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type . '/form-display'); + $this->submitForm($edit, 'Save'); // Create a node with a paragraph. $this->drupalGet('node/add/' . $content_type); - $this->drupalPostForm('node/add/' . $content_type, [], 'field_paragraphs_paragraph_type_test_add_more'); + $this->drupalGet('node/add/' . $content_type); + $this->submitForm([], 'field_paragraphs_paragraph_type_test_add_more'); // Test if the new field group is displayed. $this->assertSession()->pageTextContains('field_group'); @@ -67,7 +70,7 @@ public function testFieldGroup() { 'title[0][value]' => 'paragraphed_title', 'field_paragraphs[0][subform][field_text][0][value]' => 'paragraph_value', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalHeaderActionsTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsHeaderActionsTest.php similarity index 80% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalHeaderActionsTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsHeaderActionsTest.php index cf8063d59701fd7cdaeede00ea27fb3a91f14514..174ecd618f808f090fadd28a81d34e80a6ff48b2 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalHeaderActionsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsHeaderActionsTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\language\Entity\ConfigurableLanguage; use Symfony\Component\CssSelector\CssSelectorConverter; @@ -10,14 +10,14 @@ * * @group paragraphs */ -class ParagraphsExperimentalHeaderActionsTest extends ParagraphsExperimentalTestBase { +class ParagraphsHeaderActionsTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = array( + protected static $modules = array( 'content_translation', ); @@ -62,7 +62,7 @@ public function testHeaderActions() { $this->assertEquals(1, count($table_rows)); // Add second paragraph and check for Collapse/Edit all button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); $this->assertSession()->responseContains('field_paragraphs_collapse_all'); $this->assertSession()->responseContains('field_paragraphs_edit_all'); @@ -70,21 +70,21 @@ public function testHeaderActions() { 'field_paragraphs[0][subform][field_text][0][value]' => 'First text', 'field_paragraphs[1][subform][field_text][0][value]' => 'Second text', ]; - $this->drupalPostForm(NULL, $edit, 'Collapse all'); + $this->submitForm($edit, 'Collapse all'); // Checks that after collapsing all we can edit again these paragraphs. $this->assertSession()->responseContains('field_paragraphs_0_edit'); $this->assertSession()->responseContains('field_paragraphs_1_edit'); // Test Edit all button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_edit_all'); + $this->submitForm([], 'field_paragraphs_edit_all'); $this->assertSession()->responseContains('field_paragraphs_0_collapse'); $this->assertSession()->responseContains('field_paragraphs_1_collapse'); $edit = [ 'title[0][value]' => 'Test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Test has been created.'); $node = $this->getNodeByTitle('Test'); @@ -93,41 +93,41 @@ public function testHeaderActions() { $this->assertSession()->pageTextNotContains('No Paragraph added yet.'); // Add and remove another paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); $edit = [ 'field_paragraphs[2][subform][field_text][0][value]' => 'Third text', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_2_remove'); + $this->submitForm($edit, 'field_paragraphs_2_remove'); // Check that pressing "Collapse all" does not restore the removed // paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_edit_all'); + $this->submitForm([], 'field_paragraphs_edit_all'); $this->assertSession()->pageTextContains('First text'); $this->assertSession()->pageTextContains('Second text'); $this->assertSession()->pageTextNotContains('Third text'); // Check that pressing "Edit all" does not restore the removed paragraph, // either. - $this->drupalPostForm(NULL, [], 'field_paragraphs_collapse_all'); + $this->submitForm([], 'field_paragraphs_collapse_all'); $this->assertSession()->pageTextContains('First text'); $this->assertSession()->pageTextContains('Second text'); $this->assertSession()->pageTextNotContains('Third text'); $this->assertSession()->buttonExists('field_paragraphs_collapse_all'); $this->assertSession()->buttonExists('field_paragraphs_edit_all'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); // Check that the drag and drop button is present when there is a paragraph // and that it is not shown when the paragraph is deleted. $this->drupalGet('node/add/paragraphed_test'); $this->assertSession()->responseContains('name="field_paragraphs_dragdrop_mode"'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_remove'); + $this->submitForm([], 'field_paragraphs_0_remove'); $this->assertSession()->responseNotContains('name="field_paragraphs_dragdrop_mode"'); // Disable show multiple actions. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][features][collapse_edit_all]' => FALSE], t('Update')); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][features][collapse_edit_all]' => FALSE], 'Update'); + $this->submitForm([], 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); // Check that the collapse/edit all actions are not present. $this->assertSession()->buttonNotExists('field_paragraphs_collapse_all'); @@ -136,9 +136,9 @@ public function testHeaderActions() { // Enable show "Collapse / Edit all" actions. $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_settings_edit'); - $this->drupalPostForm(NULL, ['fields[field_paragraphs][settings_edit_form][settings][features][collapse_edit_all]' => TRUE], t('Update')); - $this->drupalPostForm(NULL, [], 'Save'); + $this->submitForm([], 'field_paragraphs_settings_edit'); + $this->submitForm(['fields[field_paragraphs][settings_edit_form][settings][features][collapse_edit_all]' => TRUE], 'Update'); + $this->submitForm([], 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); // Check that the collapse/edit all actions are present. $this->assertSession()->buttonExists('field_paragraphs_collapse_all'); @@ -186,34 +186,34 @@ public function testHeaderActionsWithNesting() { ); $this->drupalGet('admin/structure/paragraphs_type/nested_paragraph/form-display'); - $this->drupalPostForm(NULL, ['fields[field_nested][type]' => 'paragraphs'], t('Save')); + $this->submitForm(['fields[field_nested][type]' => 'paragraphs'], 'Save'); $this->setParagraphsWidgetSettings($nested_paragraph_type, 'nested', ['edit_mode' => 'closed'], 'paragraphs', 'paragraph'); // Checks that Collapse/Edit all button is presented. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_add_more'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_text_add_more'); $this->assertSession()->responseContains('field_paragraphs_collapse_all'); $this->assertSession()->responseContains('field_paragraphs_edit_all'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_nested_text_add_more'); + $this->submitForm([], 'field_paragraphs_text_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_text_add_more'); $this->assertSession()->responseNotContains('field_paragraphs_0_collapse_all'); $this->assertSession()->responseNotContains('field_paragraphs_0_edit_all'); $edit = [ 'field_paragraphs[0][subform][field_nested][0][subform][field_text][0][value]' => 'Nested text', 'field_paragraphs[1][subform][field_text][0][value]' => 'Second text paragraph', ]; - $this->drupalPostForm(NULL, $edit, 'Collapse all'); + $this->submitForm($edit, 'Collapse all'); $this->assertSession()->responseContains('field-paragraphs-0-edit'); $this->assertSession()->elementExists('css', '[name="field_paragraphs_1_edit"] + .paragraphs-dropdown'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_edit_all'); + $this->submitForm([], 'field_paragraphs_edit_all'); $this->assertSession()->responseContains('field-paragraphs-0-collapse'); $edit = [ 'title[0][value]' => 'Test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Test has been created.'); $node = $this->getNodeByTitle('Test'); @@ -221,12 +221,12 @@ public function testHeaderActionsWithNesting() { $this->clickLink('Edit'); $this->assertSession()->pageTextNotContains('No Paragraph added yet.'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_subform_field_nested_text_add_more'); + $this->submitForm([], 'field_paragraphs_0_subform_field_nested_text_add_more'); $edit = [ 'field_paragraphs[0][subform][field_nested][1][subform][field_text][0][value]' => 'Second nested text', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); + $this->submitForm([], 'field_paragraphs_0_edit'); $this->assertSession()->responseContains('field_paragraphs_0_subform_field_nested_collapse_all'); $this->assertSession()->responseContains('field_paragraphs_0_subform_field_nested_edit_all'); } @@ -250,15 +250,15 @@ public function testHeaderActionsWithMultiFields() { 'label' => 'Second paragraph', 'field_name' => 'second', ]; - $this->drupalPostForm(NULL, $edit, 'Save and continue'); - $this->drupalPostForm(NULL, [], 'Save field settings'); - $this->drupalPostForm(NULL, [], 'Save settings'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); + $this->submitForm([], 'Save settings'); $this->drupalGet('/admin/structure/types/manage/paragraphed_test/form-display'); $edit = [ 'fields[field_second][type]' => 'paragraphs', ]; - $this->drupalPostForm(NULL, $edit, 'Save'); + $this->submitForm($edit, 'Save'); // Add a text field to the text_paragraph type. static::fieldUIAddNewField( @@ -271,8 +271,8 @@ public function testHeaderActionsWithMultiFields() { ); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_second_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'field_second_text_paragraph_add_more'); // Checks that we have Collapse\Edit all for each field. $this->assertSession()->responseContains('field_paragraphs_collapse_all'); @@ -283,23 +283,23 @@ public function testHeaderActionsWithMultiFields() { $edit = [ 'field_second[0][subform][field_text][0][value]' => 'Second field', ]; - $this->drupalPostForm(NULL, $edit, 'field_second_collapse_all'); + $this->submitForm($edit, 'field_second_collapse_all'); // Checks that we collapsed only children from second field. $this->assertSession()->responseNotContains('field_paragraphs_0_edit'); $this->assertSession()->responseContains('field_second_0_edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_collapse_all'); + $this->submitForm([], 'field_paragraphs_collapse_all'); $this->assertSession()->responseContains('field_paragraphs_0_edit'); $this->assertSession()->responseContains('field_second_0_edit'); - $this->drupalPostForm(NULL, [], 'field_second_edit_all'); + $this->submitForm([], 'field_second_edit_all'); $this->assertSession()->responseContains('field_second_0_collapse'); $edit = [ 'title[0][value]' => 'Test', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test Test has been created.'); $node = $this->getNodeByTitle('Test'); @@ -333,7 +333,7 @@ function testHeaderActionsWhileTranslating() { 'entity_types[node]' => TRUE, 'settings[node][paragraphed_test][translatable]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, 'Save configuration'); + $this->submitForm($edit, 'Save configuration'); // Add a Paragraph type. $paragraph_type = 'text_paragraph'; @@ -347,7 +347,7 @@ function testHeaderActionsWhileTranslating() { 'title[0][value]' => 'Title', 'field_paragraphs[0][subform][field_text][0][value]' => 'First', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->clickLink('Translate'); $this->clickLink('Add'); // Assert that the drag and drop button is not present while translating. diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalInlineEntityFormTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsInlineEntityFormTest.php similarity index 83% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalInlineEntityFormTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsInlineEntityFormTest.php index 236253ea95658a1eb9f5fc82056f0f4f4e5be16d..99a7b16a7c2a84084eab284a8b506f62e00d22df 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalInlineEntityFormTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsInlineEntityFormTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; @@ -9,7 +9,7 @@ * * @group paragraphs */ -class ParagraphsExperimentalInlineEntityFormTest extends ParagraphsExperimentalTestBase { +class ParagraphsInlineEntityFormTest extends ParagraphsTestBase { use ParagraphsTestBaseTrait; @@ -18,7 +18,7 @@ class ParagraphsExperimentalInlineEntityFormTest extends ParagraphsExperimentalT * * @var array */ - public static $modules = [ + protected static $modules = [ 'inline_entity_form', ]; @@ -49,7 +49,7 @@ public function testParagraphsIEFPreview() { $edit = [ 'fields[field_article][type]' => 'inline_entity_form_simple', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Set the paragraphs widget edit mode to "Closed" and the closed mode to // "Preview". @@ -61,21 +61,21 @@ public function testParagraphsIEFPreview() { // Create node with one paragraph. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_simple_add_more'); + $this->submitForm([], 'field_paragraphs_simple_add_more'); // Set the values and save. $edit = [ 'title[0][value]' => 'Dummy1', 'field_paragraphs[0][subform][field_article][0][inline_entity_form][title][0][value]' => 'Dummy2', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Go back into edit page. $node = $this->getNodeByTitle('Dummy1'); $this->drupalGet('node/' . $node->id() . '/edit'); // Try to open the previewed paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); } /** @@ -106,21 +106,21 @@ public function testParagraphsIEFChangeOrder() { 'settings[target_type]' => 'paragraph', 'cardinality' => '-1', ]; - $this->drupalPostForm(NULL, $edit, t('Save field settings')); + $this->submitForm($edit, 'Save field settings'); // Enable IEF simple widget. $this->drupalGet('admin/structure/paragraphs_type/simple/form-display'); $edit = [ 'fields[field_article][type]' => 'inline_entity_form_simple', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Set the paragraphs widget closed mode to preview. $this->setParagraphsWidgetSettings('article', 'field_paragraphs', ['closed_mode' => 'preview']); // Create node with one paragraph. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_simple_add_more'); + $this->submitForm([], 'field_paragraphs_simple_add_more'); // Set the values and save. $edit = [ @@ -128,20 +128,20 @@ public function testParagraphsIEFChangeOrder() { 'field_paragraphs[0][subform][field_article][0][inline_entity_form][title][0][value]' => 'Basic page 1', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Go back into edit page. $node = $this->getNodeByTitle('Article 1'); $this->drupalGet('node/' . $node->id() . '/edit'); // Create second paragraph. - $this->drupalPostForm(NULL, [], 'field_paragraphs_simple_add_more'); + $this->submitForm([], 'field_paragraphs_simple_add_more'); // Set the values of second paragraph. $edit = [ 'field_paragraphs[1][subform][field_article][0][inline_entity_form][title][0][value]' => 'Basic 2' ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalPreviewTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsPreviewTest.php similarity index 85% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalPreviewTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsPreviewTest.php index c94aabdee41abdc25ac5b81c9f51dcbe521505bc..bf47bf24bfa71ae38d45cc13b6b7f8bb910ef239 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalPreviewTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsPreviewTest.php @@ -1,20 +1,20 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; /** * Tests the configuration of paragraphs. * * @group paragraphs */ -class ParagraphsExperimentalPreviewTest extends ParagraphsExperimentalTestBase { +class ParagraphsPreviewTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = array( + protected static $modules = array( 'image', ); @@ -44,14 +44,14 @@ public function testParagraphsPreview() { $test_text_2 = 'dummy_preview_text_2'; // Create node with two paragraphs. $this->drupalGet('node/add/article'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); // Set the value of the paragraphs. $edit = [ 'title[0][value]' => 'Page_title', 'field_paragraphs[0][subform][field_text][0][value]' => $test_text_1, ]; // Preview the article. - $this->drupalPostForm(NULL, $edit, t('Preview')); + $this->submitForm($edit, 'Preview'); // Check if the text is displayed. $this->assertSession()->responseContains($test_text_1); @@ -67,15 +67,15 @@ public function testParagraphsPreview() { $paragraph_1 = $this->xpath('//*[@id="edit-field-paragraphs-0-subform-field-text-0-value"]')[0]; $this->assertEquals($paragraph_1->getValue(), $test_text_1); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->clickLink('Edit'); - $this->drupalPostForm(NULL, array(), 'field_paragraphs_text_add_more'); + $this->submitForm(array(), 'field_paragraphs_text_add_more'); $edit = [ 'field_paragraphs[1][subform][field_text][0][value]' => $test_text_2, ]; // Preview the article. - $this->drupalPostForm(NULL, $edit, t('Preview')); + $this->submitForm($edit, 'Preview'); $this->assertSession()->responseContains($test_text_1); $this->assertSession()->responseContains($test_text_2); @@ -87,7 +87,7 @@ public function testParagraphsPreview() { 'field_paragraphs[1][subform][field_text][0][value]' => $new_test_text_2, ]; // Preview the article. - $this->drupalPostForm(NULL, $edit, t('Preview')); + $this->submitForm($edit, 'Preview'); $this->assertSession()->responseContains($test_text_1); $this->assertSession()->responseContains($new_test_text_2); @@ -103,7 +103,7 @@ public function testParagraphsPreview() { $paragraph_2 = $this->xpath('//*[@id="edit-field-paragraphs-1-subform-field-text-0-value"]')[0]; $this->assertEquals($paragraph_1->getValue(), $test_text_1); $this->assertEquals($paragraph_2->getValue(), $new_test_text_2); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->responseContains($test_text_1); $this->assertSession()->responseContains($new_test_text_2); diff --git a/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsReplicateEnableTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsReplicateEnableTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a5ee9956a8e9cf8174195544d00ac173302a5d7f --- /dev/null +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsReplicateEnableTest.php @@ -0,0 +1,17 @@ +<?php + +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; + +/** + * Enables replicate module. + * + * @group paragraphs + */ + +class ParagraphsReplicateEnableTest extends ParagraphsDuplicateFeatureTest { + + protected static $modules = [ + 'replicate', + ]; + +} diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalSummaryFormatterTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsSummaryFormatterTest.php similarity index 77% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalSummaryFormatterTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsSummaryFormatterTest.php index 8402f6e31059a24f1a4c043e20a354a4600ac76e..5083e42c0648b7d50ccea5d0a8397aa5e359d358 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalSummaryFormatterTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsSummaryFormatterTest.php @@ -1,20 +1,20 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; /** * Tests the paragraphs summary formatter. * * @group paragraphs */ -class ParagraphsExperimentalSummaryFormatterTest extends ParagraphsExperimentalTestBase { +class ParagraphsSummaryFormatterTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'image', ]; @@ -41,10 +41,11 @@ public function testParagraphsSummaryFormatter() { // Set display format to paragraphs summary. $this->drupalGet('admin/structure/types/manage/paragraphed_test/display'); $edit = ['fields[field_paragraphs][type]' => 'paragraph_summary']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Add a paragraph. - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_title_add_more'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_title_add_more'); // Create a node with a text. $edit = [ @@ -52,13 +53,13 @@ public function testParagraphsSummaryFormatter() { 'field_paragraphs[0][subform][field_text][0][value]' => 'text_summary', 'field_paragraphs[1][subform][field_title][0][value]' => 'Title example', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, [], t('Add user_paragraph')); + $this->submitForm($edit, 'Save'); + $this->clickLink('Edit'); + $this->submitForm([], 'Add user_paragraph'); $edit = [ 'field_paragraphs[2][subform][field_user][0][target_id]' => $this->admin_user->label() . ' (' . $this->admin_user->id() . ')', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Assert the summary is correctly generated. $this->assertSession()->pageTextContains($this->admin_user->label()); diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTestBase.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTestBase.php similarity index 81% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTestBase.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTestBase.php index 681658117d586580f513173a998718beea0fd871..dae186edaf5eb78cc8d8767b6d2b01dfe6031191 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTestBase.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTestBase.php @@ -1,15 +1,15 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Tests\paragraphs\Functional\Classic\ParagraphsTestBase; +use Drupal\Tests\paragraphs\Functional\WidgetLegacy\ParagraphsTestBase as LegacyParagraphsTestBase; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; /** * Base class for tests. */ -abstract class ParagraphsExperimentalTestBase extends ParagraphsTestBase { +abstract class ParagraphsTestBase extends LegacyParagraphsTestBase { use ParagraphsTestBaseTrait; @@ -40,7 +40,7 @@ protected function setAddMode($content_type, $paragraphs_field, $mode) { */ protected function removeDefaultParagraphType($content_type) { $this->drupalGet('node/add/' . $content_type); - $this->drupalPostForm(NULL, [], 'Remove'); + $this->submitForm([], 'Remove'); $this->assertSession()->pageTextNotContains('No paragraphs added yet.'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTranslationTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationTest.php similarity index 83% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTranslationTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationTest.php index cd34ddf56087402ab488d9e3349f66919cbc71e9..66c6fc35bc1c96690a4b4a2eccaa38be0867fd7d 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTranslationTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Entity\Entity\EntityFormDisplay; @@ -15,14 +15,14 @@ * * @group paragraphs */ -class ParagraphsExperimentalTranslationTest extends ParagraphsExperimentalTestBase { +class ParagraphsTranslationTest extends ParagraphsTestBase { /** * Modules to enable. * * @var array */ - public static $modules = array( + protected static $modules = array( 'content_translation', 'link', 'image', @@ -36,7 +36,7 @@ class ParagraphsExperimentalTranslationTest extends ParagraphsExperimentalTestBa /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); ConfigurableLanguage::create(['id' => 'de', 'label' => '1German'])->save(); ConfigurableLanguage::create(['id' => 'fr', 'label' => '2French'])->save(); @@ -77,7 +77,8 @@ protected function setUp() { 'settings[paragraph][text_image][fields][field_text_demo]' => TRUE, 'settings[node][paragraphed_content_demo][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); if (version_compare(\Drupal::VERSION, '8.4', '>=')) { // @todo Workaround for file usage/unable to save the node with no usages. @@ -110,38 +111,38 @@ public function testParagraphTranslation() { 'fields[status][type]' => 'boolean_checkbox', 'fields[status][region]' => 'content', ); - // Use the experimental widget. + // Use the stable widget. $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default') ->setComponent('field_paragraphs_demo', [ 'type' => 'paragraphs', ]); $form_display->save(); - // Use the experimental widget. + // Use the stable widget. $form_display = EntityFormDisplay::load('paragraph.nested_paragraph.default') ->setComponent('field_paragraphs_demo', [ 'type' => 'paragraphs', ]); $form_display->save(); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text_image')); + $this->submitForm([], 'Add text_image'); $this->assertSession()->responseContains('edit-field-paragraphs-demo-0-subform-status-value'); $edit = [ 'title[0][value]' => 'example_publish_unpublish', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Example published and unpublished', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextContains(t('Example published and unpublished')); - $this->clickLink(t('Edit')); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('Example published and unpublished'); + $this->clickLink('Edit'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more'); + $this->submitForm([], 'field_paragraphs_demo_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more'); $edit = [ 'field_paragraphs_demo[0][subform][status][value]' => FALSE, 'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'Dummy text' ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertSession()->pageTextNotContains(t('Example published and unpublished')); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextNotContains('Example published and unpublished'); // Check the parent fields are set properly. Get the node. $node = $this->drupalGetNodeByTitle('example_publish_unpublish'); @@ -164,26 +165,26 @@ public function testParagraphTranslation() { // Add paragraphed content. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text_image')); + $this->submitForm([], 'Add text_image'); $edit = array( 'title[0][value]' => 'Title in english', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Text in english', ); // The button to remove a paragraph is present. - $this->assertSession()->responseContains(t('Remove')); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertSession()->responseContains('Remove'); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('Title in english'); // The text is present when editing again. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->pageTextContains('Title in english'); $this->assertSession()->pageTextContains('Text in english'); // Add french translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add'), 1); + $this->clickLink('Translate'); + $this->clickLink('Add', 1); // Make sure the Add / Remove paragraph buttons are hidden. - $this->assertSession()->responseNotContains(t('Remove')); - $this->assertSession()->responseNotContains(t('Add text_image')); + $this->assertSession()->responseNotContains('Remove'); + $this->assertSession()->responseNotContains('Add text_image'); // Make sure that the original paragraph text is displayed. $this->assertSession()->pageTextContains('Text in english'); @@ -193,7 +194,7 @@ public function testParagraphTranslation() { 'revision' => TRUE, 'revision_log[0][value]' => 'french 1', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('paragraphed_content_demo Title in french has been updated.'); // Check the english translation. @@ -209,7 +210,7 @@ public function testParagraphTranslation() { $this->assertSession()->pageTextContains('Text in french'); $this->assertSession()->pageTextNotContains('Title in english'); // The translation is still present when editing again. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->pageTextContains('Title in french'); $this->assertSession()->pageTextContains('Text in french'); $edit = array( @@ -218,35 +219,35 @@ public function testParagraphTranslation() { 'revision' => TRUE, 'revision_log[0][value]' => 'french 2', ); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->pageTextContains('Title Change in french'); $this->assertSession()->pageTextContains('New text in french'); // Back to the source language. $this->drupalGet('node/' . $node->id()); - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertSession()->pageTextContains('Title in english'); $this->assertSession()->pageTextContains('Text in english'); // Save the original content on second request. - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('paragraphed_content_demo Title in english has been updated.'); // Test if reverting to old paragraphs revisions works, make sure that // the reverted node can be saved again. $this->drupalGet('fr/node/' . $node->id() . '/revisions'); - $this->clickLink(t('Revert')); - $this->drupalPostForm(NULL, ['revert_untranslated_fields' => TRUE], t('Revert')); - $this->clickLink(t('Edit')); + $this->clickLink('Revert'); + $this->submitForm(['revert_untranslated_fields' => TRUE], 'Revert'); + $this->clickLink('Edit'); $this->assertSession()->responseContains('Title in french'); $this->assertSession()->pageTextContains('Text in french'); - $this->drupalPostForm(NULL, [], t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->responseNotContains('The content has either been modified by another user, or you have already submitted modifications'); $this->assertSession()->pageTextContains('Text in french'); //Add paragraphed content with untranslatable language $this->drupalGet('node/add/paragraphed_content_demo'); $edit = array('langcode[0][value]' => LanguageInterface::LANGCODE_NOT_SPECIFIED); - $this->drupalPostForm(NULL, $edit, t('Add text_image')); + $this->submitForm($edit, 'Add text_image'); $this->assertSession()->statusCodeEquals(200); // Make 'Images' paragraph field translatable, enable alt and title fields. @@ -257,41 +258,41 @@ public function testParagraphTranslation() { 'settings[alt_field]' => 1, 'settings[title_field]' => 1, ]; - $this->drupalPostForm(NULL, $edit, t('Save settings')); + $this->submitForm($edit, 'Save settings'); // Create a node with an image paragraph, its alt and title text. $files = $this->getTestFiles('image'); $file_system = \Drupal::service('file_system'); $file_path = $file_system->realpath($file_system->realpath($files[0]->uri)); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], t('Add images')); - $this->drupalPostForm(NULL, ['files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path], t('Upload')); + $this->submitForm([], 'Add images'); + $this->submitForm(['files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path], 'Upload'); $edit = [ 'title[0][value]' => 'Title EN', 'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt', 'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Translate the node with the image paragraph. $this->clickLink('Translate'); - $this->clickLink(t('Add'), 1); + $this->clickLink('Add', 1); $edit = [ 'title[0][value]' => 'Title FR', 'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt FR', 'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title FR', ]; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertSession()->responseContains('Title FR'); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], t('Add text')); + $this->submitForm([], 'Add text'); $edit = [ 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'texto', 'title[0][value]' => 'titulo', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('titulo'); $this->assertParagraphsLangcode($node->id(), 'de'); @@ -324,7 +325,7 @@ public function testParagraphTranslation() { 'field_paragraphs_demo' => [$paragraph_1, $translated_paragraph], ]); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_content_demo ' . $node->label() . ' has been updated.'); // Check that first paragraph langcode has been updated. \Drupal::entityTypeManager()->getStorage('paragraph')->resetCache([$paragraph_1->id(), $paragraph_2->id()]); @@ -342,25 +343,26 @@ public function testParagraphTranslation() { 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'english_translation_1', 'field_paragraphs_demo[1][subform][field_text_demo][0][value]' => 'english_translation_2', ]; - $this->drupalPostForm('node/' . $node->id() . '/translations/add/de/en', $edit, t('Save (this translation)')); + $this->drupalGet('node/' . $node->id() . '/translations/add/de/en'); + $this->submitForm($edit, 'Save (this translation)'); // Attempt to create a french translation. $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr'); // Check that the german translation of the paragraphs is displayed. $this->assertSession()->fieldValueEquals('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_text_1'); $this->assertSession()->fieldValueEquals('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'german_text_2'); - $this->drupalPostForm(NULL, ['source_langcode[source]' => 'en'], t('Change')); + $this->submitForm(['source_langcode[source]' => 'en'], 'Change'); // Check that the english translation of the paragraphs is displayed. $this->assertSession()->fieldValueEquals('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_translation_1'); $this->assertSession()->fieldValueEquals('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'english_translation_2'); // Create a node with empty Paragraphs. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], t('Add nested_paragraph')); + $this->submitForm([], 'Add nested_paragraph'); $edit = ['title[0][value]' => 'empty_node']; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Attempt to translate it. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add')); + $this->clickLink('Translate'); + $this->clickLink('Add'); // Check the add button is not displayed. $this->assertEquals(count($this->xpath('//*[@name="field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more"]')), 0); @@ -370,9 +372,10 @@ public function testParagraphTranslation() { 'label' => 'untranslatable_field', 'field_name' => 'untranslatable_field', ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/add-field'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); + $this->submitForm([], 'Save settings'); // Add a non translatable reference field. $edit = [ @@ -380,9 +383,10 @@ public function testParagraphTranslation() { 'label' => 'untranslatable_ref_field', 'field_name' => 'untranslatable_ref_field', ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->drupalPostForm(NULL, ['settings[handler_settings][target_bundles][paragraphed_content_demo]' => TRUE], t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/add-field'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); + $this->submitForm(['settings[handler_settings][target_bundles][paragraphed_content_demo]' => TRUE], 'Save settings'); // Add a non translatable link field. $edit = [ @@ -390,9 +394,10 @@ public function testParagraphTranslation() { 'label' => 'untranslatable_link_field', 'field_name' => 'untranslatable_link_field', ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->drupalPostForm(NULL, [], t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/add-field'); + $this->submitForm($edit, 'Save and continue'); + $this->submitForm([], 'Save field settings'); + $this->submitForm([], 'Save settings'); // Attempt to add a translation. $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr'); @@ -405,8 +410,10 @@ public function testParagraphTranslation() { $edit = [ 'translatable' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_ref_field', $edit, t('Save settings')); - $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_link_field', $edit, t('Save settings')); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_ref_field'); + $this->submitForm($edit, 'Save settings'); + $this->drupalGet('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_link_field'); + $this->submitForm($edit, 'Save settings'); // Attempt to add a translation. $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr'); @@ -420,27 +427,27 @@ public function testParagraphTranslation() { $this->setParagraphsWidgetSettings('paragraphed_content_demo', 'field_paragraphs_demo', ['edit_mode' => 'closed']); // Create a node with a text and a nested paragraph. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add text')); - $this->drupalPostForm(NULL, NULL, t('Add nested_paragraph')); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more'); + $this->submitForm([], 'Add text'); + $this->submitForm([], 'Add nested_paragraph'); + $this->submitForm([], 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more'); $edit = [ 'title[0][value]' => 'EN llama', 'langcode[0][value]' => 'en', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'EN text llama', 'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'EN nested text llama', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_content_demo EN llama has been created.'); // Create a german translation. $node = $this->drupalGetNodeByTitle('EN llama'); $this->drupalGet('node/' . $node->id() . '/translations/add/en/de'); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_edit_all'); + $this->submitForm([], 'field_paragraphs_demo_edit_all'); $edit = [ 'title[0][value]' => 'DE llama', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'DE text llama', 'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'DE nested text llama', ]; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); // Assert that the summary is displayed in the current language. $this->drupalGet('de/node/' . $node->id() . '/edit'); $this->assertSession()->fieldValueEquals('title[0][value]', 'DE llama'); @@ -457,20 +464,20 @@ public function testParagraphTranslation() { ]); // Add a node with a reference paragraph. $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add node_reference')); + $this->submitForm([], 'Add node_reference'); $edit = [ 'title[0][value]' => 'EN referencing llama', 'langcode[0][value]' => 'en', 'field_paragraphs_demo[0][subform][field_entity_reference][0][target_id]' => $node->label() . ' (' . $node->id() . ')', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $referencing_node = $this->drupalGetNodeByTitle('EN referencing llama'); // Translate the node. $this->drupalGet('node/' . $referencing_node->id() . '/translations/add/en/de'); $edit = [ 'title[0][value]' => 'DE referencing llama', ]; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); // Edit the node again and check the paragraph summary. $this->drupalGet('de/node/' . $referencing_node->id() . '/edit'); $this->assertSession()->responseContains('<span class="summary-content">DE llama</span></div></div>'); @@ -488,20 +495,20 @@ public function testParagraphTranslationMultilingual() { // Case 1: original node langcode in EN, translate in FR, change to DE. // Add 'Images' paragraph and check the paragraphs buttons are displayed. - // Use the experimental widget. + // Use the stable widget. $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default') ->setComponent('field_paragraphs_demo', [ 'type' => 'paragraphs', ]); $form_display->save(); - // Use the experimental widget. + // Use the stable widget. $form_display = EntityFormDisplay::load('paragraph.nested_paragraph.default') ->setComponent('field_paragraphs_demo', [ 'type' => 'paragraphs', ]); $form_display->save(); $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, NULL, t('Add images')); + $this->submitForm([], 'Add images'); $this->assertParagraphsButtons(1); // Upload an image and check the paragraphs buttons are still displayed. $images = $this->getTestFiles('image')[0]; @@ -509,24 +516,24 @@ public function testParagraphTranslationMultilingual() { 'title[0][value]' => 'Title in english', 'files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, ]; - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Title in english'); $node = $this->drupalGetNodeByTitle('Title in english'); // Check the paragraph langcode is 'en'. $this->assertParagraphsLangcode($node->id()); // Add french translation. - $this->clickLink(t('Translate')); - $this->clickLink(t('Add'), 1); + $this->clickLink('Translate'); + $this->clickLink('Add', 1); // Make sure the host entity and its paragraphs have valid source language // and check that the paragraphs buttons are hidden. $this->assertNoParagraphsButtons(1); $edit = [ 'title[0][value]' => 'Title in french', ]; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $this->submitForm($edit, 'Save (this translation)'); $this->assertParagraphsLangcode($node->id(), 'en', 'fr'); $this->assertSession()->pageTextContains('paragraphed_content_demo Title in french has been updated.'); $this->assertSession()->pageTextContains('Title in french'); @@ -537,14 +544,14 @@ public function testParagraphTranslationMultilingual() { // Edit the french translation and upload a new image. $this->clickLink('Edit'); $images = $this->getTestFiles('image')[1]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); // Check editing a translation does not affect the source langcode and // check that the paragraphs buttons are still hidden. $this->assertParagraphsLangcode($node->id(), 'en', 'fr'); $this->assertNoParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('Title in french'); $this->assertSession()->pageTextNotContains('Title in english'); @@ -563,23 +570,23 @@ public function testParagraphTranslationMultilingual() { 'title[0][value]' => 'Title in english (de)', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, t('Add nested_paragraph')); + $this->submitForm($edit, 'Add nested_paragraph'); $this->assertParagraphsLangcode($node->id()); $this->assertParagraphsButtons(2); // Add an 'Images' paragraph inside the nested one, check the paragraphs // langcode are still 'en' and the paragraphs buttons are still displayed. - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_1_subform_field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_1_subform_field_paragraphs_demo_images_add_more'); $this->assertParagraphsLangcode($node->id()); $this->assertParagraphsButtons(2); // Upload a new image, check the paragraphs langcode are still 'en' and the // paragraphs buttons are displayed. $images = $this->getTestFiles('image')[2]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_1_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node->id()); $this->assertParagraphsButtons(2); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); $this->assertSession()->pageTextContains('Title in english (de)'); $this->assertSession()->pageTextNotContains('Title in french'); // Check the original node and the paragraphs langcode are now 'de'. @@ -599,9 +606,10 @@ public function testParagraphTranslationMultilingual() { // node langcode to EN. // Change the site langcode to french. - $this->drupalPostForm('admin/config/regional/language', [ + $this->drupalGet('admin/config/regional/language'); + $this->submitForm([ 'site_default_language' => 'fr', - ], t('Save configuration')); + ], 'Save configuration'); // Check the original node and its paragraphs langcode are still 'de' // and the paragraphs buttons are still displayed. @@ -611,21 +619,21 @@ public function testParagraphTranslationMultilingual() { // Go to the french translation. $this->drupalGet('node/' . $node->id() . '/translations'); - $this->clickLink(t('Edit'), 1); + $this->clickLink('Edit', 1); // Check editing a translation does not affect the source langcode and // check that the paragraphs buttons are still hidden. $this->assertParagraphsLangcode($node->id(), 'de', 'fr'); $this->assertNoParagraphsButtons(2); // Upload another image. $images = $this->getTestFiles('image')[3]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_1_subform_field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); // Check editing a translation does not affect the source langcode and // check that the paragraphs buttons are still hidden. $this->assertParagraphsLangcode($node->id(), 'de', 'fr'); $this->assertNoParagraphsButtons(2); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); // Check the paragraphs langcode are still 'de' after saving the translation. $this->assertParagraphsLangcode($node->id(), 'de', 'fr'); $this->assertSession()->pageTextContains('Title in french'); @@ -646,18 +654,18 @@ public function testParagraphTranslationMultilingual() { 'title[0][value]' => 'Title in english', 'langcode[0][value]' => 'en', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_demo_images_add_more'); + $this->submitForm($edit, 'field_paragraphs_demo_images_add_more'); $this->assertParagraphsLangcode($node->id(), 'de'); $this->assertParagraphsButtons(3); // Upload a new image, check the paragraphs langcode are still 'de' and the // paragraphs buttons are displayed. $images = $this->getTestFiles('image')[4]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_2_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node->id(), 'de'); $this->assertParagraphsButtons(3); - $this->drupalPostForm(NULL, NULL, t('Save (this translation)')); + $this->submitForm([], 'Save (this translation)'); // Check the original node and the paragraphs langcode are now 'en'. $this->assertParagraphsLangcode($node->id()); } @@ -674,13 +682,13 @@ public function testParagraphTranslationMultilingual() { public function testParagraphsMultilingualWorkflow() { // Case 1: Check the paragraphs buttons after changing the NODE language // (original node langcode in GERMAN, default site langcode in english). - // Use the experimental widget. + // Use the stable widget. $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default') ->setComponent('field_paragraphs_demo', [ 'type' => 'paragraphs', ]); $form_display->save(); - // Use the experimental widget. + // Use the stable widget. $form_display = EntityFormDisplay::load('paragraph.nested_paragraph.default') ->setComponent('field_paragraphs_demo', [ 'type' => 'paragraphs', @@ -695,25 +703,25 @@ public function testParagraphsMultilingualWorkflow() { 'title[0][value]' => 'Title in german', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, t('Add nested_paragraph')); + $this->submitForm($edit, 'Add nested_paragraph'); // Check that the paragraphs buttons are displayed and add an 'Images' // paragraph inside the nested paragraph. $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); // Upload an image and check the paragraphs buttons are still displayed. $images = $this->getTestFiles('image')[0]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Title in german'); $node1 = $this->getNodeByTitle('Title in german'); // Check the paragraph langcode is 'de' and its buttons are displayed. // @todo check for the nested children paragraphs buttons and langcode // when it's supported. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node1->id(), 'de'); $this->assertParagraphsButtons(1); // Change the node langcode to 'english' and upload another image. @@ -723,16 +731,16 @@ public function testParagraphsMultilingualWorkflow() { 'langcode[0][value]' => 'en', 'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri, ]; - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); // Check the paragraph langcode is still 'de' and its buttons are shown. $this->assertParagraphsLangcode($node1->id(), 'de'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraph langcode is now 'en' after saving. $this->assertParagraphsLangcode($node1->id()); // Check the paragraph langcode is 'en' and its buttons are still shown. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node1->id()); $this->assertParagraphsButtons(1); @@ -744,27 +752,27 @@ public function testParagraphsMultilingualWorkflow() { // Check that the node langcode is 'english' and add a 'Nested Paragraph'. $option_field = $this->assertSession()->optionExists('edit-langcode-0-value', 'en'); $this->assertTrue($option_field->hasAttribute('selected')); - $this->drupalPostForm(NULL, NULL, t('Add nested_paragraph')); + $this->submitForm([], 'Add nested_paragraph'); // Check that the paragraphs buttons are displayed and add an 'Images' // paragraph inside the nested paragraph. $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more'); // Upload an image and check the paragraphs buttons are still displayed. $images = $this->getTestFiles('image')[0]; $edit = [ 'title[0][value]' => 'Title in english', 'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri, ]; - $this->drupalPostForm(NULL, $edit, t('Upload')); + $this->submitForm($edit, 'Upload'); $this->assertParagraphsButtons(1); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Title in english'); $node2 = $this->drupalGetNodeByTitle('Title in english'); // Check the paragraph langcode is 'en' and its buttons are displayed. // @todo check for the nested children paragraphs buttons and langcode // when it's supported. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(1); // Change the node langcode to 'german' and add another 'Images' paragraph. @@ -772,29 +780,29 @@ public function testParagraphsMultilingualWorkflow() { 'title[0][value]' => 'Title in english (de)', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_demo_images_add_more'); + $this->submitForm($edit, 'field_paragraphs_demo_images_add_more'); // Check the paragraphs langcode are still 'en' and their buttons are shown. $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(2); // Upload an image, check the paragraphs langcode are still 'en' and their // buttons are displayed. $images = $this->getTestFiles('image')[1]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_1_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(2); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraphs langcode are now 'de' after saving. $this->assertParagraphsLangcode($node2->id(), 'de'); // Change node langcode back to 'english' and save. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $edit = [ 'title[0][value]' => 'Title in english', 'langcode[0][value]' => 'en', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check the paragraphs langcode are now 'en' after saving. $this->assertParagraphsLangcode($node2->id()); @@ -804,7 +812,8 @@ public function testParagraphsMultilingualWorkflow() { $edit = [ 'site_default_language' => 'de', ]; - $this->drupalPostForm('admin/config/regional/language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/language'); + $this->submitForm($edit, 'Save configuration'); // Check the original node and the paragraphs langcode are still 'en' and // check that the paragraphs buttons are still displayed. @@ -812,24 +821,24 @@ public function testParagraphsMultilingualWorkflow() { $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(2); // Add another 'Images' paragraph with node langcode as 'english'. - $this->drupalPostForm(NULL, NULL, 'field_paragraphs_demo_images_add_more'); + $this->submitForm([], 'field_paragraphs_demo_images_add_more'); // Check the paragraph langcode are still 'en' and their buttons are shown. $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(3); // Upload an image, check the paragraphs langcode are still 'en' and their // buttons are displayed. $images = $this->getTestFiles('image')[2]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_2_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(3); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraphs langcode are still 'en' after saving. $this->assertParagraphsLangcode($node2->id()); // Check the paragraphs langcode are still 'en' and their buttons are shown. - $this->clickLink(t('Edit')); + $this->clickLink('Edit'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(3); // Change node langcode to 'german' and add another 'Images' paragraph. @@ -837,19 +846,19 @@ public function testParagraphsMultilingualWorkflow() { 'title[0][value]' => 'Title in english (de)', 'langcode[0][value]' => 'de', ]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_demo_images_add_more'); + $this->submitForm($edit, 'field_paragraphs_demo_images_add_more'); // Check the paragraphs langcode are still 'en' and their buttons are shown. $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(4); // Upload an image, check the paragraphs langcode are still 'en' and their // buttons are displayed. $images = $this->getTestFiles('image')[3]; - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'files[field_paragraphs_demo_3_subform_field_images_demo_0][]' => $images->uri, - ], t('Upload')); + ], 'Upload'); $this->assertParagraphsLangcode($node2->id()); $this->assertParagraphsButtons(4); - $this->drupalPostForm(NULL, NULL, t('Save')); + $this->submitForm([], 'Save'); // Check the paragraphs langcode are now 'de' after saving. $this->assertParagraphsLangcode($node2->id(), 'de'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTranslationsTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationsTest.php similarity index 95% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTranslationsTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationsTest.php index 13a6774296fffd102dc3cf80c4b185b885d20d2e..75ef6f6be6b64b400692667b3916daae6fd1d5ec 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTranslationsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationsTest.php @@ -1,8 +1,9 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; use Drupal\Tests\paragraphs\Traits\ParagraphsLastEntityQueryTrait; /** @@ -10,16 +11,16 @@ * * @group paragraphs */ -class ParagraphsExperimentalTranslationsTest extends ParagraphsExperimentalTestBase { +class ParagraphsTranslationsTest extends ParagraphsTestBase { - use ParagraphsLastEntityQueryTrait; + use ParagraphsLastEntityQueryTrait, ParagraphsCoreVersionUiTestTrait; /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_test', 'paragraphs', @@ -40,13 +41,9 @@ class ParagraphsExperimentalTranslationsTest extends ParagraphsExperimentalTestB /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); - // Place the breadcrumb, tested in fieldUIAddNewField(). - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); $this->addParagraphedContentType('paragraphed_test', 'field_paragraphs', 'paragraphs'); @@ -104,7 +101,7 @@ protected function setUp() { 'settings[paragraph][text_untranslatable_hide][fields][field_text_untranslatable_hide]' => FALSE, 'settings[paragraph][container][fields][field_paragraphs]' => FALSE, ]; - $this->drupalPostForm(NULL, $edit, t('Save configuration')); + $this->submitForm($edit, 'Save configuration'); } /** diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTypesTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTypesTest.php similarity index 78% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTypesTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTypesTest.php index ceee3ba906a2380686d500d881ba7cc22651105d..14465243357f46a13bf4ffed7a99696928035988 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalTypesTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsTypesTest.php @@ -1,13 +1,13 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; /** * Tests paragraphs types. * * @group paragraphs */ -class ParagraphsExperimentalTypesTest extends ParagraphsExperimentalTestBase { +class ParagraphsTypesTest extends ParagraphsTestBase { /** * Tests the deletion of Paragraphs types. @@ -22,26 +22,26 @@ public function testRemoveTypesWithContent() { // Attempt to delete the content type not used yet. $this->drupalGet('admin/structure/paragraphs_type'); - $this->clickLink(t('Delete')); + $this->clickLink('Delete'); $this->assertSession()->pageTextContains('This action cannot be undone.'); - $this->clickLink(t('Cancel')); + $this->clickLink('Cancel'); // Add a test node with a Paragraph. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, [], 'paragraphs_paragraph_type_test_add_more'); + $this->submitForm([], 'paragraphs_paragraph_type_test_add_more'); $edit = ['title[0][value]' => 'test_node']; $table_rows = $this->xpath('//table[contains(@class, :class)]/tbody/tr', [':class' => 'field-multiple-table']); $this->assertEquals(1, count($table_rows)); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains('paragraphed_test test_node has been created.'); // Attempt to delete the paragraph type already used. $this->drupalGet('admin/structure/paragraphs_type'); - $this->clickLink(t('Delete')); + $this->clickLink('Delete'); $this->assertSession()->pageTextContains('paragraph_type_test Paragraphs type is used by 1 piece of content on your site. You can not remove this paragraph_type_test Paragraphs type until you have removed all from the content.'); // Delete all entities of that Paragraph type. - $this->drupalPostForm(NULL, [], t('Delete existing Paragraph')); + $this->submitForm([], 'Delete existing Paragraph'); $this->assertSession()->pageTextContains('Entity is successfully deleted.'); $node = $this->drupalGetNodeByTitle('test_node'); $this->drupalGet('node/' . $node->id() . '/edit'); @@ -49,22 +49,22 @@ public function testRemoveTypesWithContent() { $this->assertEquals(0, count($table_rows)); // @todo Remove this when https://www.drupal.org/node/2846549 is resolved. - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); // Add two different Paragraphs to the node. - $this->drupalPostForm(NULL, [], 'paragraphs_paragraph_type_test_add_more'); - $this->drupalPostForm(NULL, [], 'paragraphs_text_add_more'); + $this->submitForm([], 'paragraphs_paragraph_type_test_add_more'); + $this->submitForm([], 'paragraphs_text_add_more'); $table_rows = $this->xpath('//table[contains(@class, :class)]/tbody/tr', [':class' => 'field-multiple-table']); $this->assertEquals(2, count($table_rows)); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); // Attempt to delete the Paragraph type. $this->drupalGet('admin/structure/paragraphs_type'); - $this->clickLink(t('Delete')); + $this->clickLink('Delete'); $this->assertSession()->pageTextContains('paragraph_type_test Paragraphs type is used by 1 piece of content on your site. You can not remove this paragraph_type_test Paragraphs type until you have removed all from the content.'); - $this->drupalPostForm(NULL, [], t('Delete existing Paragraph')); + $this->submitForm([], 'Delete existing Paragraph'); $this->assertSession()->pageTextContains('Entity is successfully deleted.'); - $this->drupalPostForm(NULL, [], t('Delete')); + $this->submitForm([], 'Delete'); // Check that the Paragraph of the deleted type is removed and the rest // remains. $node = $this->drupalGetNodeByTitle('test_node'); @@ -88,10 +88,10 @@ public function testCreateParagraphType() { 'label' => 'Test', 'id' => 'test_name_with_more_than_32_characters' ]; - $this->drupalPostForm(NULL, $edit, 'Save and manage fields'); + $this->submitForm($edit, 'Save and manage fields'); $this->assertSession()->pageTextContains('Machine-readable name cannot be longer than 32 characters but is currently 38 characters long.'); $edit['id'] = 'new_test_id'; - $this->drupalPostForm(NULL, $edit, 'Save and manage fields'); + $this->submitForm($edit, 'Save and manage fields'); $this->assertSession()->pageTextContains('Saved the Test Paragraphs type.'); } } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalUiTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsUiTest.php similarity index 82% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalUiTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsUiTest.php index 066007d473e18a048cc52bdfcda996bb5d970d86..bfcac0a82f2507a181d9af5a5caaf4a5212237b7 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalUiTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsUiTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\language\Entity\ConfigurableLanguage; @@ -9,12 +9,12 @@ * * @group paragraphs */ -class ParagraphsExperimentalUiTest extends ParagraphsExperimentalTestBase { +class ParagraphsUiTest extends ParagraphsTestBase { /** * {@inheritdoc} */ - public static $modules = array( + protected static $modules = array( 'content_translation', 'image', 'field', @@ -27,7 +27,7 @@ class ParagraphsExperimentalUiTest extends ParagraphsExperimentalTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); ConfigurableLanguage::create(['id' => 'de', 'label' => '1German'])->save(); ConfigurableLanguage::create(['id' => 'fr', 'label' => '2French'])->save(); @@ -62,7 +62,8 @@ protected function setUp() { 'settings[paragraph][text_image][fields][field_text_demo]' => TRUE, 'settings[node][paragraphed_content_demo][settings][language][language_alterable]' => TRUE ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); } /** @@ -90,33 +91,34 @@ public function testEmptyRequiredField() { $form_display_edit = [ 'fields[field_content][type]' => 'paragraphs', ]; - $this->drupalPostForm($bundle_path . '/form-display', $form_display_edit, t('Save')); + $this->drupalGet($bundle_path . '/form-display'); + $this->submitForm($form_display_edit, 'Save'); // Attempt to create a paragraphed node with an empty required field. $title = 'Empty'; $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, ['title[0][value]' => $title], t('Save')); + $this->submitForm(['title[0][value]' => $title], 'Save'); $this->assertSession()->pageTextContains($field_title . ' field is required'); // Attempt to create a paragraphed node with only a paragraph in the // "remove" mode in the required field. $title = 'Remove all items'; $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], 'field_content_text_image_add_more'); - $this->drupalPostForm(NULL, [], 'field_content_0_remove'); + $this->submitForm([], 'field_content_text_image_add_more'); + $this->submitForm([], 'field_content_0_remove'); $this->assertSession()->pageTextNotContains($field_title . ' field is required'); - $this->drupalPostForm(NULL, ['title[0][value]' => $title], t('Save')); + $this->submitForm(['title[0][value]' => $title], 'Save'); $this->assertSession()->pageTextContains($field_title . ' field is required'); // Attempt to create a paragraphed node with a valid paragraph and a // removed paragraph. $title = 'Valid Removal'; $this->drupalGet('node/add/paragraphed_content_demo'); - $this->drupalPostForm(NULL, [], 'field_content_text_image_add_more'); - $this->drupalPostForm(NULL, [], 'field_content_text_image_add_more'); - $this->drupalPostForm(NULL, [], 'field_content_1_remove'); + $this->submitForm([], 'field_content_text_image_add_more'); + $this->submitForm([], 'field_content_text_image_add_more'); + $this->submitForm([], 'field_content_1_remove'); $this->assertSession()->pageTextNotContains($field_title . ' field is required'); - $this->drupalPostForm(NULL, ['title[0][value]' => $title], t('Save')); + $this->submitForm(['title[0][value]' => $title], 'Save'); $this->assertSession()->pageTextNotContains($field_title . ' field is required'); } diff --git a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalWidgetButtonsTest.php b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsWidgetButtonsTest.php similarity index 84% rename from web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalWidgetButtonsTest.php rename to web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsWidgetButtonsTest.php index 989c0dd87d8bc9aee3f6779beb4154c951163d5a..3c0fb53547bdfd67c36108dd3cb3df4a9ded50ad 100644 --- a/web/modules/paragraphs/tests/src/Functional/Experimental/ParagraphsExperimentalWidgetButtonsTest.php +++ b/web/modules/paragraphs/tests/src/Functional/WidgetStable/ParagraphsWidgetButtonsTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\paragraphs\Functional\Experimental; +namespace Drupal\Tests\paragraphs\Functional\WidgetStable; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait; @@ -9,11 +9,11 @@ use Drupal\node\Entity\NodeType; /** - * Tests paragraphs experimental widget buttons. + * Tests paragraphs stable widget buttons. * * @group paragraphs */ -class ParagraphsExperimentalWidgetButtonsTest extends ParagraphsExperimentalTestBase { +class ParagraphsWidgetButtonsTest extends ParagraphsTestBase { use ParagraphsTestBaseTrait; @@ -22,7 +22,7 @@ class ParagraphsExperimentalWidgetButtonsTest extends ParagraphsExperimentalTest * * @var array */ - public static $modules = [ + protected static $modules = [ 'paragraphs_test', 'language', 'content_translation', @@ -45,8 +45,10 @@ public function testWidgetButtons() { $edit = [ 'fields[field_paragraphs][type]' => 'paragraphs', ]; - $this->drupalPostForm('admin/structure/types/manage/paragraphed_test/form-display', $edit, t('Save')); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more'); + $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); + $this->submitForm($edit, 'Save'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); // Create a node with a Paragraph. $text = 'recognizable_text'; @@ -54,33 +56,33 @@ public function testWidgetButtons() { 'title[0][value]' => 'paragraphs_mode_test', 'field_paragraphs[0][subform][field_text][0][value]' => $text, ]; - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('paragraphs_mode_test'); // Test the 'Open' edit mode. $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', $text); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains($text); // Test the 'Closed' edit mode. $this->setParagraphsWidgetMode('paragraphed_test', 'field_paragraphs', 'closed'); $this->drupalGet('node/' . $node->id() . '/edit'); // Click "Edit" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_1_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_1_edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', $text); $closed_mode_text = 'closed_mode_text'; // Click "Collapse" button on both paragraphs. $edit = ['field_paragraphs[0][subform][field_text][0][value]' => $closed_mode_text]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); $edit = ['field_paragraphs[1][subform][field_text][0][value]' => $closed_mode_text]; - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_1_collapse'); + $this->submitForm($edit, 'field_paragraphs_1_collapse'); // Verify that we have warning message for each paragraph. $this->assertEquals(2, count($this->xpath("//*[contains(@class, 'paragraphs-icon-changed')]"))); $this->assertSession()->responseContains('<span class="summary-content">' . $closed_mode_text); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_test ' . $node->label() . ' has been updated.'); $this->assertSession()->pageTextContains($closed_mode_text); @@ -88,24 +90,24 @@ public function testWidgetButtons() { $this->setParagraphsWidgetSettings('paragraphed_test', 'field_paragraphs', ['closed_mode' => 'preview']); $this->drupalGet('node/' . $node->id() . '/edit'); // Click "Edit" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_edit'); + $this->submitForm([], 'field_paragraphs_0_edit'); $this->assertSession()->fieldValueEquals('field_paragraphs[0][subform][field_text][0][value]', $closed_mode_text); $preview_mode_text = 'preview_mode_text'; $edit = ['field_paragraphs[0][subform][field_text][0][value]' => $preview_mode_text]; // Click "Collapse" button. - $this->drupalPostForm(NULL, $edit, 'field_paragraphs_0_collapse'); + $this->submitForm($edit, 'field_paragraphs_0_collapse'); $this->assertSession()->pageTextContains('You have unsaved changes on this Paragraph item.'); $this->assertEquals(1, count($this->xpath("//*[contains(@class, 'paragraphs-icon-changed')]"))); $this->assertSession()->pageTextContains($preview_mode_text); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_test ' . $node->label() . ' has been updated.'); $this->assertSession()->pageTextContains($preview_mode_text); // Test the remove function. $this->drupalGet('node/' . $node->id() . '/edit'); // Click "Remove" button. - $this->drupalPostForm(NULL, [], 'field_paragraphs_0_remove'); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'field_paragraphs_0_remove'); + $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('paragraphed_test ' . $node->label() . ' has been updated.'); $this->assertSession()->pageTextNotContains($preview_mode_text); } @@ -134,8 +136,10 @@ public function testButtonsVisibility() { $edit = [ 'fields[field_paragraphs][type]' => 'paragraphs', ]; - $this->drupalPostForm('admin/structure/types/manage/paragraphed_test/form-display', $edit, t('Save')); - $this->drupalPostForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more'); + $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); + $this->submitForm($edit, 'Save'); + $this->drupalGet('node/add/paragraphed_test'); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); // Create a node with a Paragraph. $text = 'recognizable_text'; @@ -143,8 +147,8 @@ public function testButtonsVisibility() { 'title[0][value]' => 'paragraphs_mode_test', 'field_paragraphs[0][subform][field_text][0][value]' => $text, ]; - $this->drupalPostForm(NULL, [], 'field_paragraphs_text_paragraph_add_more'); - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm([], 'field_paragraphs_text_paragraph_add_more'); + $this->submitForm($edit, 'Save'); $node = $this->drupalGetNodeByTitle('paragraphs_mode_test'); // Checking visible buttons on "Open" mode. @@ -177,21 +181,21 @@ public function testButtonsVisibility() { $edit = [ 'fields[field_nested][type]' => 'paragraphs', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $this->drupalGet('node/' . $node->id() . '/edit'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_nested_paragraph_add_more'); - $this->drupalPostForm(NULL, [], 'field_paragraphs_2_subform_field_nested_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_nested_paragraph_add_more'); + $this->submitForm([], 'field_paragraphs_2_subform_field_nested_nested_paragraph_add_more'); // Collapse is present on each nesting level. $this->assertSession()->buttonExists('field_paragraphs_2_collapse'); $this->assertSession()->buttonExists('field_paragraphs_2_subform_field_nested_0_collapse'); // Tests hook_paragraphs_widget_actions_alter. $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, t('Add text')); + $this->submitForm([], 'Add text'); $this->assertSession()->buttonNotExists('edit-field-paragraphs-0-top-links-test-button'); \Drupal::state()->set('paragraphs_test_dropbutton', TRUE); $this->drupalGet('node/add/paragraphed_test'); - $this->drupalPostForm(NULL, NULL, t('Add text')); + $this->submitForm([], 'Add text'); $this->assertSession()->buttonNotExists('edit-field-paragraphs-0-top-links-test-button'); ConfigurableLanguage::createFromLangcode('sr')->save(); @@ -202,7 +206,7 @@ public function testButtonsVisibility() { 'entity_types[node]' => TRUE, 'settings[node][paragraphed_test][translatable]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, 'Save configuration'); + $this->submitForm($edit, 'Save configuration'); // Check that operation is hidden during translation. $this->drupalGet('sr/node/' . $node->id() . '/translations/add/en/sr'); @@ -283,7 +287,8 @@ public function testButtonsVisibilityException() { $edit = [ 'fields[field_paragraphs][type]' => 'paragraphs', ]; - $this->drupalPostForm('admin/structure/types/manage/paragraphed_test/form-display', $edit, t('Save')); + $this->drupalGet('admin/structure/types/manage/paragraphed_test/form-display'); + $this->submitForm($edit, 'Save'); // Checking hidden button on "Open" mode. $this->drupalGet('node/add/paragraphed_test'); diff --git a/web/modules/paragraphs/tests/src/FunctionalJavascript/LoginAdminTrait.php b/web/modules/paragraphs/tests/src/FunctionalJavascript/LoginAdminTrait.php index baf30320126ca5d657e48937fd36645442c29b5f..6ddd332c1028d6cbe98338f901c68c79cbb0ae1f 100644 --- a/web/modules/paragraphs/tests/src/FunctionalJavascript/LoginAdminTrait.php +++ b/web/modules/paragraphs/tests/src/FunctionalJavascript/LoginAdminTrait.php @@ -28,6 +28,7 @@ public function loginAsAdmin($additional_permissions = [], $reset_permissions = 'administer node form display', 'administer paragraph fields', 'administer paragraph form display', + 'bypass node access', ]; if ($reset_permissions) { diff --git a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalAddWidgetTest.php b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsAddWidgetTest.php similarity index 94% rename from web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalAddWidgetTest.php rename to web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsAddWidgetTest.php index 55244887a07c1b18f829d6a229817ca5270f0456..0327df745db8152c8bebbfd07ce94e7f63f62ba5 100644 --- a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalAddWidgetTest.php +++ b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsAddWidgetTest.php @@ -12,7 +12,7 @@ * * @group paragraphs */ -class ParagraphsExperimentalAddWidgetTest extends WebDriverTestBase { +class ParagraphsAddWidgetTest extends WebDriverTestBase { use LoginAdminTrait; use FieldUiTestTrait; @@ -24,7 +24,7 @@ class ParagraphsExperimentalAddWidgetTest extends WebDriverTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_test', 'paragraphs', @@ -42,14 +42,9 @@ class ParagraphsExperimentalAddWidgetTest extends WebDriverTestBase { /** * {@inheritdoc} */ - protected function setUp() - { + protected function setUp(): void { parent::setUp(); - // Place the breadcrumb, tested in fieldUIAddNewField(). - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); } @@ -73,10 +68,10 @@ public function testAddWidgetButton() { 'fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed', 'fields[field_paragraphs][settings_edit_form][settings][add_mode]' => 'modal' ]; - $this->drupalPostForm(NULL, $edit, 'Update'); + $this->submitForm($edit, 'Update'); $this->assertSession()->assertWaitOnAjaxRequest(); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); // Add a Paragraph type. $paragraph_type = 'text_paragraph'; @@ -149,7 +144,7 @@ public function testAddWidgetButton() { $edit = [ 'title[0][value]' => 'Example title', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Check the created paragraphed test. $this->assertSession()->pageTextContainsOnce('paragraphed_test Example title has been created.'); @@ -202,9 +197,9 @@ public function testModalAddWidgetDelta() { 'fields[field_paragraphs][settings_edit_form][settings][edit_mode]' => 'closed', 'fields[field_paragraphs][settings_edit_form][settings][add_mode]' => 'modal', ]; - $this->drupalPostForm(NULL, $edit, 'Update'); + $this->submitForm($edit, 'Update'); $this->assertSession()->assertWaitOnAjaxRequest(); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); // Add a Paragraph types. $this->addParagraphsType('test_1'); @@ -267,7 +262,7 @@ public function testModalAddWidgetDelta() { // // This case covers full execution of // ParagraphsWidget::prepareDeltaPosition() when list is empty. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').last().val(-100)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').last().val(-100)"); $page->find('xpath', '//*[@name="button_add_modal"]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_nested")]')->click(); @@ -281,7 +276,7 @@ public function testModalAddWidgetDelta() { // paragraph respectively. // // Add 2 additional paragraphs in base field. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').last().val('')"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').last().val('')"); for ($i = 1; $i <= 2; $i++) { $page->find('xpath', '//*[@name="button_add_modal" and not(ancestor::table)]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); @@ -295,7 +290,7 @@ public function testModalAddWidgetDelta() { $this->assertEquals('test_2', $base_paragraphs[2]->getText(), 'Last paragraph should be type "test_2".'); // Add new paragraph to 1st position - set delta to 0 for base paragraphs. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').last().val(0)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').last().val(0)"); $page->find('xpath', '//*[@name="button_add_modal" and not(ancestor::table)]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_3")]')->click(); @@ -307,7 +302,7 @@ public function testModalAddWidgetDelta() { $this->assertEquals('test_3', $base_paragraphs[0]->getText(), '1st paragraph should be type "test_3".'); // Add new paragraph to 3rd position - set delta to 2 for base paragraphs. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').last().val(2)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').last().val(2)"); $page->find('xpath', '//*[@name="button_add_modal" and not(ancestor::table)]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_2")]')->click(); @@ -319,7 +314,7 @@ public function testModalAddWidgetDelta() { $this->assertEquals('test_2', $base_paragraphs[2]->getText(), '3rd paragraph should be type "test_2".'); // Add new paragraph to last position - using really big delta. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').last().val(1000)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').last().val(1000)"); $page->find('xpath', '//*[@name="button_add_modal" and not(ancestor::table)]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_1")]')->click(); @@ -331,7 +326,7 @@ public function testModalAddWidgetDelta() { $this->assertEquals('test_1', $base_paragraphs[5]->getText(), 'Last paragraph should be type "test_1".'); // Clear delta base paragraphs. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').last().val('')"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').last().val('')"); $page->find('xpath', '//*[@name="button_add_modal" and not(ancestor::table)]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_3")]')->click(); @@ -376,28 +371,28 @@ public function testModalAddWidgetDelta() { $this->assertSession()->assertWaitOnAjaxRequest(); // Add new paragraph to first position. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').first().val(0)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').first().val(0)"); $page->find('xpath', '//*[@name="button_add_modal" and ancestor::table]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_3")]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); // Add new paragraph to 2nd position - using float value for index. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').first().val(1.1111)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').first().val(1.1111)"); $page->find('xpath', '//*[@name="button_add_modal" and ancestor::table]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_2")]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); // Add new paragraph to first position - using negative index. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').first().val(-100)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').first().val(-100)"); $page->find('xpath', '//*[@name="button_add_modal" and ancestor::table]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_2")]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); // Add new paragraph to last position - using some text as position. - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').first().val('some_text')"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').first().val('some_text')"); $page->find('xpath', '//*[@name="button_add_modal" and ancestor::table]')->click(); $this->assertSession()->assertWaitOnAjaxRequest(); $page->find('xpath', '//*[contains(@class, "paragraphs-add-dialog") and contains(@class, "ui-dialog-content")]//*[contains(@name, "test_3")]')->click(); @@ -430,9 +425,9 @@ public function testModalAddWidgetDelta() { $this->assertSession()->assertWaitOnAjaxRequest(); // Attempt to add a new Paragraph above and cancel. $page->find('xpath', '//*[@name="button_add_modal"]')->click(); - $this->getSession()->executeScript("jQuery('input.paragraph-type-add-modal-delta').first().val(0)"); + $this->getSession()->executeScript("jQuery('input.paragraph-type-add-delta').first().val(0)"); $this->assertSession()->elementExists('css', '.ui-dialog-titlebar-close')->press(); - $delta = $this->getSession()->evaluateScript("jQuery('paragraph-type-add-modal-delta').val()"); + $delta = $this->getSession()->evaluateScript("jQuery('.paragraph-type-add-delta').val()"); $this->assertEquals($delta, ''); // Add a new Paragraph with the Add button at the bottom. $page->find('xpath', '//*[@name="button_add_modal"]')->click(); diff --git a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalClientsideButtonsTest.php b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsClientsideButtonsTest.php similarity index 89% rename from web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalClientsideButtonsTest.php rename to web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsClientsideButtonsTest.php index 1ca60d565f4ed9ecb1edebb05def97cefa959c19..ad994ea0164020d412356e0b47f29f8cca3e69de 100644 --- a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalClientsideButtonsTest.php +++ b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsClientsideButtonsTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\paragraphs\FunctionalJavascript; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; @@ -12,7 +13,7 @@ * * @group paragraphs */ -class ParagraphsExperimentalClientsideButtonsTest extends WebDriverTestBase { +class ParagraphsClientsideButtonsTest extends WebDriverTestBase { use LoginAdminTrait; use FieldUiTestTrait; @@ -23,7 +24,7 @@ class ParagraphsExperimentalClientsideButtonsTest extends WebDriverTestBase { /** * {@inheritdoc} */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_test', 'paragraphs', @@ -41,13 +42,9 @@ class ParagraphsExperimentalClientsideButtonsTest extends WebDriverTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); - // Place the breadcrumb, tested in fieldUIAddNewField(). - $this->drupalPlaceBlock('system_breadcrumb_block'); - $this->drupalPlaceBlock('local_tasks_block'); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalPlaceBlock('page_title_block'); + $this->placeDefaultBlocks(); } /** @@ -117,6 +114,8 @@ public function testAddParagraphAboveButton() { $dialog->pressButton('text'); $assert_session->assertWaitOnAjaxRequest(); $session->wait(2000); + // Check that the add above button has the button--small class. + $page->find('xpath', '//input[@class="paragraphs-dropdown-action paragraphs-dropdown-action--add-above button button--small js-form-submit form-submit"]'); // At this point we should have 3 injected "Add above" buttons. $all_add_above_buttons = $page->findAll('css', '#edit-field-paragraphs-wrapper input.paragraphs-dropdown-action--add-above'); $this->assertEquals(3, count($all_add_above_buttons)); @@ -128,7 +127,7 @@ public function testAddParagraphAboveButton() { 'field_paragraphs[1][subform][field_text][0][value]' => 'Second text', 'field_paragraphs[2][subform][field_text][0][value]' => 'Third text', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); $node_id = $this->getLastEntityOfType('node'); // Make sure we honor the widget settings when injecting the button. @@ -269,7 +268,31 @@ public function testAddParagraphAboveButton() { $dialog->pressButton('text'); $assert_session->assertWaitOnAjaxRequest(); - // 5 paragraphs, we expect 5 injected buttons. + // 5 paragraphs, we expect 4 injected buttons as the cardinality of the + // nested paragraph is one and we cannot Add Above. + $all_add_above_buttons = $page->findAll('css', '#edit-field-paragraphs-wrapper input.paragraphs-dropdown-action--add-above'); + $this->assertEquals(4, count($all_add_above_buttons)); + + // Remove the new added Paragraph. + $rich_paragraph_row = $assert_session->elementExists('css', '#field-paragraphs-add-more-wrapper tr:nth-of-type(2) .field--name-field-nested-paragraphs tr.draggable'); + $dropdown = $assert_session->elementExists('css', '.paragraphs-dropdown', $rich_paragraph_row); + $dropdown->click(); + $remove_button = $assert_session->buttonExists('field_paragraphs_3_subform_field_nested_paragraphs_0_remove'); + $remove_button->click(); + $assert_session->assertWaitOnAjaxRequest(); + // Set the config to allow more than one Paragraph. + $field_storage = FieldStorageConfig::loadByName('paragraph', 'field_nested_paragraphs'); + $field_storage->setCardinality(-1); + $field_storage->save(); + // Add the Paragraph back. + $add_paragraph_rich_row->click(); + $assert_session->assertWaitOnAjaxRequest(); + $dialog = $page->find('xpath', '//div[contains(@class, "ui-dialog")]'); + $dialog->pressButton('text'); + $assert_session->assertWaitOnAjaxRequest(); + + // 5 paragraphs, we expect 5 injected buttons as the cardinality of the + // nested paragraph is unlimited. $all_add_above_buttons = $page->findAll('css', '#edit-field-paragraphs-wrapper input.paragraphs-dropdown-action--add-above'); $this->assertEquals(5, count($all_add_above_buttons)); @@ -297,7 +320,7 @@ public function testAddParagraphAboveButton() { // We have one more injected add_more button. $all_add_above_buttons = $page->findAll('css', '#edit-field-paragraphs-wrapper input.paragraphs-dropdown-action--add-above'); $this->assertEquals(6, count($all_add_above_buttons)); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->drupalGet("/node/{$node_id}/edit"); $edit_all_button = $assert_session->buttonExists('field_paragraphs_edit_all'); diff --git a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalEditPerspectivesUiTest.php b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsStableEditPerspectivesUiTest.php similarity index 95% rename from web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalEditPerspectivesUiTest.php rename to web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsStableEditPerspectivesUiTest.php index f6217e53c084aebe609ca098017e5b44b6db320a..e712e20980eb54f7b7f23e290970cef6fa6e33dc 100644 --- a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalEditPerspectivesUiTest.php +++ b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsStableEditPerspectivesUiTest.php @@ -5,23 +5,25 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; use Drupal\paragraphs\Entity\ParagraphsType; +use Drupal\Tests\paragraphs\Traits\ParagraphsCoreVersionUiTestTrait; /** * Test paragraphs user interface. * * @group paragraphs */ -class ParagraphsExperimentalEditPerspectivesUiTest extends WebDriverTestBase { +class ParagraphsStableEditPerspectivesUiTest extends WebDriverTestBase { use LoginAdminTrait; use ParagraphsTestBaseTrait; + use ParagraphsCoreVersionUiTestTrait; /** * Modules to enable. * * @var array */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs_test', 'paragraphs', @@ -40,8 +42,9 @@ class ParagraphsExperimentalEditPerspectivesUiTest extends WebDriverTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); + $this->placeDefaultBlocks(); } /** @@ -72,7 +75,7 @@ public function testEditPerspectives() { $this->assertFalse($style_selector->isVisible()); // Assert scroll position when switching tabs. - $this->getSession()->resizeWindow(800, 500); + $this->getSession()->resizeWindow(800, 450); $this->drupalGet('node/add/testcontent'); $button = $this->getSession ()->getPage()->findButton('Add TestPlugin'); $button->press(); @@ -202,12 +205,12 @@ public function testTabsVisibility() { $edit = [ 'settings[target_type]' => 'paragraph', ]; - $this->drupalPostForm(NULL, $edit, t('Save field settings')); - $this->drupalPostForm(NULL, NULL, t('Save settings')); + $this->submitForm($edit, 'Save field settings'); + $this->submitForm([], 'Save settings'); $this->drupalGet('admin/structure/types/manage/testcontent/form-display'); $page->selectFieldOption('fields[field_testparagraphfield][type]', 'paragraphs'); $this->assertSession()->assertWaitOnAjaxRequest(); - $this->drupalPostForm(NULL, [], t('Save')); + $this->submitForm([], 'Save'); $this->drupalGet('node/add/testcontent'); $style_selector = $page->find('css', '.paragraphs-tabs'); $this->assertFalse($style_selector->isVisible()); @@ -228,7 +231,8 @@ public function testPerspectivesWithMultipleFields() { $edit = [ 'behavior_plugins[test_bold_text][enabled]' => TRUE, ]; - $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save')); + $this->drupalGet('admin/structure/paragraphs_type/' . $paragraph_type); + $this->submitForm($edit, 'Save'); $this->addParagraphedContentType('testcontent'); $this->addParagraphsField('testcontent', 'field_paragraphs2', 'node'); diff --git a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsTestBaseTrait.php b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsTestBaseTrait.php index e872e300bcc993186bedb2dc109c1923cfeaf41e..f6f19db6403e33a0d191e28c69142729067ff5d4 100644 --- a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsTestBaseTrait.php +++ b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsTestBaseTrait.php @@ -33,9 +33,9 @@ trait ParagraphsTestBaseTrait { * @param string $paragraphs_field_name * (optional) Field name to be used. Defaults to 'field_paragraphs'. * @param string $widget_type - * (optional) Declares if we use experimental or classic widget. - * Defaults to 'paragraphs' for experimental widget. - * Use 'entity_reference_paragraphs' for classic widget. + * (optional) Declares if we use stable or legacy widget. + * Defaults to 'paragraphs' for stable widget. + * Use 'entity_reference_paragraphs' for legacy widget. */ protected function addParagraphedContentType($content_type_name, $paragraphs_field_name = 'field_paragraphs', $widget_type = 'paragraphs') { // Create the content type. @@ -58,9 +58,9 @@ protected function addParagraphedContentType($content_type_name, $paragraphs_fie * @param string $entity_type * Entity type where to add the field. * @param string $widget_type - * (optional) Declares if we use experimental or classic widget. - * Defaults to 'paragraphs' for experimental widget. - * Use 'entity_reference_paragraphs' for classic widget. + * (optional) Declares if we use stable or legacy widget. + * Defaults to 'paragraphs' for stable widget. + * Use 'entity_reference_paragraphs' for legacy widget. */ protected function addParagraphsField($bundle, $paragraphs_field_name, $entity_type, $widget_type = 'paragraphs') { $field_storage = FieldStorageConfig::loadByName($entity_type, $paragraphs_field_name); @@ -209,7 +209,7 @@ protected function setParagraphsWidgetSettings($bundle, $paragraphs_field, array $component = $default_form_display->getComponent($paragraphs_field); $updated_component = $component; - if ($field_widget === NULL || $field_widget === $component['type']) { + if ($field_widget === NULL || (isset($component['type']) && $field_widget === $component['type'])) { // The widget stays the same. $updated_component['settings'] = $settings + $component['settings']; } diff --git a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalWidgetElementsTest.php b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsWidgetElementsTest.php similarity index 91% rename from web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalWidgetElementsTest.php rename to web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsWidgetElementsTest.php index 2e9e7efac1028b6b98c19b7eb2faa1d6dbed4f84..5875c39785ca0c7aa698518123ab989b58bbc2b4 100644 --- a/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsExperimentalWidgetElementsTest.php +++ b/web/modules/paragraphs/tests/src/FunctionalJavascript/ParagraphsWidgetElementsTest.php @@ -10,7 +10,7 @@ * * @group paragraphs */ -class ParagraphsExperimentalWidgetElementsTest extends WebDriverTestBase { +class ParagraphsWidgetElementsTest extends WebDriverTestBase { use LoginAdminTrait; use ParagraphsTestBaseTrait; @@ -20,7 +20,7 @@ class ParagraphsExperimentalWidgetElementsTest extends WebDriverTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'node', 'paragraphs', 'field', @@ -61,7 +61,8 @@ public function testDragHandler() { 'settings[paragraph][text][translatable]' => TRUE, 'settings[paragraph][text][settings][language][language_alterable]' => TRUE, ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + $this->drupalGet('admin/config/regional/content-language'); + $this->submitForm($edit, 'Save configuration'); $settings = [ 'add_mode' => 'modal', ]; @@ -81,7 +82,7 @@ public function testDragHandler() { 'title[0][value]' => 'Title', 'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'First', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->submitForm($edit, 'Save'); // Translate the node. $node = $this->getNodeByTitle('Title'); $this->drupalGet('node/' . $node->id() . '/translations/add/en/sr'); diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsAccessTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsAccessTest.php index 9dc7e00163f9858a4b48804c5b992d82d59e2363..eec1a1aec8c1461e0bef96903401225489a7d33f 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsAccessTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsAccessTest.php @@ -17,7 +17,7 @@ class ParagraphsAccessTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = [ + protected static $modules = [ 'paragraphs', ]; diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsBehaviorPluginsTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsBehaviorPluginsTest.php index 7d2508c9c1753ba9d62753d3d233a723633fcac7..b9ecc2e6f5c9349d0b2bd098ea94da6a5fbb381e 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsBehaviorPluginsTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsBehaviorPluginsTest.php @@ -18,7 +18,7 @@ class ParagraphsBehaviorPluginsTest extends KernelTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'paragraphs', 'user', 'system', @@ -31,7 +31,7 @@ class ParagraphsBehaviorPluginsTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); $this->installEntitySchema('paragraph'); @@ -87,6 +87,17 @@ public function testBehaviorSettings() { $plugin = $paragraph->getParagraphType()->getBehaviorPlugins()->getEnabled(); $this->assertEquals($plugin['test_text_color']->settingsSummary($paragraph)[0], ['label' => 'Text color', 'value' => 'blue']); + // Settings another behavior settings should retain the original behaviors + // from another plugin. + \Drupal::entityTypeManager()->getStorage('paragraph')->resetCache(); + $paragraph = Paragraph::load($paragraph->id()); + $paragraph->setBehaviorSettings('test_another_id', ['foo' => 'bar']); + $paragraph->save(); + + $paragraph = Paragraph::load($paragraph->id()); + $settings = $paragraph->getAllBehaviorSettings(); + $this->assertArrayHasKey('test_text_color', $settings); + $this->assertArrayHasKey('test_another_id', $settings); } /** diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsCollapsedSummaryTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsCollapsedSummaryTest.php index 93be4840afa6ecf9a039530e3fa088cdc5070338..6b926c939c8aed7fcc5b811de384ff180c288de4 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsCollapsedSummaryTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsCollapsedSummaryTest.php @@ -27,12 +27,11 @@ class ParagraphsCollapsedSummaryTest extends KernelTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'paragraphs', 'user', 'system', 'field', - 'entity_reference', 'entity_reference_revisions', 'paragraphs_test', 'file', @@ -41,7 +40,7 @@ class ParagraphsCollapsedSummaryTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); $this->installEntitySchema('paragraph'); diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsCompositeRelationshipTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsCompositeRelationshipTest.php index 4be7c37a80939ab76718016c87f9cdef221e2cae..72bc9c5d9a6a8f0fe66668ca2c12edf2623ee207 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsCompositeRelationshipTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsCompositeRelationshipTest.php @@ -25,7 +25,7 @@ class ParagraphsCompositeRelationshipTest extends KernelTestBase { * * @var array */ - public static $modules = array( + protected static $modules = array( 'paragraphs', 'node', 'user', @@ -39,7 +39,7 @@ class ParagraphsCompositeRelationshipTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); // Create paragraphs and article content types. $values = ['type' => 'article', 'name' => 'Article']; diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsEntityMethodsTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsEntityMethodsTest.php index c4b7805737cdece1e4a517b6afbd7e70cc9d02d4..aaf784a666282f48a84efddd2c6b19d550438714 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsEntityMethodsTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsEntityMethodsTest.php @@ -23,7 +23,7 @@ class ParagraphsEntityMethodsTest extends KernelTestBase { * * @var string[] */ - public static $modules = [ + protected static $modules = [ 'paragraphs', 'node', 'user', @@ -36,7 +36,7 @@ class ParagraphsEntityMethodsTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); $this->installEntitySchema('node'); diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsIsChangedTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsIsChangedTest.php index b8a9e21ae25400eaf3292a2a0d2fe595abb3dffd..7c4bc8b67244b0be0455c800d95284c028cab95a 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsIsChangedTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsIsChangedTest.php @@ -18,7 +18,7 @@ class ParagraphsIsChangedTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = [ + protected static $modules = [ 'paragraphs', 'user', 'system', @@ -30,7 +30,7 @@ class ParagraphsIsChangedTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); $this->installEntitySchema('paragraph'); diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsLangcodeChangeTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsLangcodeChangeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3b3e6046dcb51df95afc802a180301652771878a --- /dev/null +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsLangcodeChangeTest.php @@ -0,0 +1,384 @@ +<?php + +namespace Drupal\Tests\paragraphs\Kernel; + +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Core\Form\FormState; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; +use Drupal\language\Entity\ContentLanguageSettings; +use Drupal\paragraphs_test\Form\TestEmbeddedEntityForm; + +/** + * Tests the langcode change mechanics of paragraphs. + * + * @group paragraphs + */ +class ParagraphsLangcodeChangeTest extends EntityKernelTestBase { + + /** + * Modules to enable. + * + * @var array + */ + protected static $modules = [ + 'user', + 'system', + 'field', + 'text', + 'filter', + 'entity_test', + 'paragraphs', + 'paragraphs_test', + 'entity_reference_revisions', + 'node', + 'language', + 'file', + ]; + + /** + * The machine name of the node type. + * + * @var string + */ + protected $nodeType = 'page'; + + /** + * The machine name of the node's paragraphs field. + * + * @var string + */ + protected $nodeParagraphsFieldName = 'field_paragraphs'; + + /** + * The machine name of the paragraph type. + * + * @var string + */ + protected $paragraphType = 'paragraph_type'; + + /** + * The current node. + * + * @var \Drupal\node\NodeInterface + */ + protected $node; + + /** + * The current paragraph. + * + * @var \Drupal\paragraphs\ParagraphInterface + */ + protected $paragraph; + + /** + * The array of the current form. + * + * @var array + */ + protected $form; + + /** + * The current form state. + * + * @var \Drupal\Core\Form\FormStateInterface + */ + protected $formState; + + /** + * The current form object. + * + * @var \Drupal\Core\Entity\ContentEntityFormInterface + */ + protected $formObject; + + /** + * The current entity form display. + * + * @var \Drupal\Core\Entity\Entity\EntityFormDisplay + */ + protected $formDisplay; + + /** + * The current form builder. + * + * @var \Drupal\Core\Form\FormBuilderInterface + */ + protected $formBuilder; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->installEntitySchema('file'); + $this->installEntitySchema('node'); + $this->installEntitySchema('paragraph'); + + $this->installSchema('node', ['node_access']); + + $this->installConfig(static::$modules); + + $this->formBuilder = $this->container->get('form_builder'); + + // Activate Spanish language, so there are two languages activated. + $this->entityTypeManager->getStorage('configurable_language')->create([ + 'id' => 'es', + ])->save(); + + // Create a paragraph type. + $this->entityTypeManager->getStorage('paragraphs_type')->create([ + 'label' => 'Paragraph type', + 'id' => $this->paragraphType, + 'status' => TRUE, + ])->save(); + + // Create a node type. + $this->entityTypeManager->getStorage('node_type')->create([ + 'name' => 'Example page', + 'type' => $this->nodeType, + 'create_body' => FALSE, + ])->save(); + + // Enable translations on the node type and paragraph type. + ContentLanguageSettings::loadByEntityTypeBundle('node', $this->nodeType) + ->setLanguageAlterable(TRUE) + ->setDefaultLangcode('en') + ->save(); + ContentLanguageSettings::loadByEntityTypeBundle('paragraph', $this->paragraphType) + ->setLanguageAlterable(TRUE) + ->setDefaultLangcode('en') + ->save(); + + // Create a field with paragraphs for the node type. + FieldStorageConfig::create([ + 'entity_type' => 'node', + 'type' => 'entity_reference_revisions', + 'field_name' => $this->nodeParagraphsFieldName, + 'settings' => [ + 'target_type' => 'paragraph', + ], + 'cardinality' => -1, + 'translatable' => TRUE, + ])->save(); + FieldConfig::create([ + 'entity_type' => 'node', + 'bundle' => $this->nodeType, + 'field_name' => $this->nodeParagraphsFieldName, + 'label' => $this->randomString(), + 'settings' => [ + 'handler' => 'default:paragraph', + 'handler_settings' => [ + 'negate' => 1, + 'target_bundles' => NULL, + 'target_bundles_drag_drop' => [ + $this->paragraphType => [ + 'weight' => 0, + 'enabled' => FALSE, + ], + ], + ], + ], + ])->save(); + + // Create the form display of the node type, + // with the language switcher enabled. + // The default autocomplete widget does not work properly + // within a kernel test. Thus, use a simple select list widget instead. + EntityFormDisplay::create([ + 'targetEntityType' => 'node', + 'bundle' => $this->nodeType, + 'mode' => 'default', + 'status' => TRUE, + ])->setComponent('langcode', [ + 'type' => 'language_select', + 'region' => 'content', + 'weight' => 10, + ])->setComponent('uid', [ + 'type' => 'options_select', + 'region' => 'content', + 'weight' => 100, + ])->save(); + + $this->formDisplay = EntityFormDisplay::load('node.' . $this->nodeType . '.default'); + + $this->createUser(['uid' => 1, 'name' => 'user1'])->save(); + + $this->paragraph = $this->entityTypeManager->getStorage('paragraph')->create([ + 'type' => $this->paragraphType, + ]); + + $this->node = $this->entityTypeManager->getStorage('node')->create([ + 'type' => $this->nodeType, + 'title' => $this->randomString(), + 'status' => TRUE, + 'uid' => 1, + 'langcode' => 'es', + $this->nodeParagraphsFieldName => [$this->paragraph], + ]); + } + + /** + * Tests the langcode change within a node form using the legacy widget. + */ + public function testChangeWithLegacyWidget() { + $this->doTestLangcodeChange( + [ + 'type' => 'entity_reference_paragraphs', + 'weight' => 5, + ], + FALSE + ); + } + + /** + * Tests the langcode change within a node form using the stable widget. + */ + public function testChangeWithStableWidget() { + $this->doTestLangcodeChange( + [ + 'type' => 'paragraphs', + 'weight' => 15, + ], + FALSE + ); + } + + /** + * Tests langcode change within an embedded node form and the legacy widget. + */ + public function testChangeWithEmbeddedLegacyWidget() { + $this->doTestLangcodeChange( + [ + 'type' => 'entity_reference_paragraphs', + 'weight' => 5, + ], + TRUE + ); + } + + /** + * Tests langcode change within an embedded node form and the stable widget. + */ + public function testChangeWithEmbeddedStableWidget() { + $this->doTestLangcodeChange( + [ + 'type' => 'paragraphs', + 'weight' => 15, + ], + TRUE + ); + } + + /** + * Performs the test run with the given options. + * + * @param array $widget_options + * The paragraph widget options. + * @param bool $embedded + * (Optional) Whether the embedded form should be used or not. + */ + protected function doTestLangcodeChange(array $widget_options, $embedded = FALSE) { + $this->formDisplay + ->setComponent($this->nodeParagraphsFieldName, $widget_options) + ->save(); + $this->doTestChangeWithinNodeForm($embedded); + } + + /** + * Performs the test run regards the node form. + * + * @param bool $embedded + * (Optional) Whether the embedded form should be used or not. + */ + protected function doTestChangeWithinNodeForm($embedded = FALSE) { + $this->assertEquals('es', $this->node->language()->getId(), "The node was created with langcode es."); + $this->assertEquals('en', $this->paragraph->language()->getId(), "The paragraph was created with its default langcode en."); + + // Use this form to add a node. + $this->buildNodeForm($embedded); + + $this->submitNodeForm(); + + $langcode = $this->node->language()->getId(); + $this->assertEquals('es', $langcode, "The node's langcode remains unchanged to value es (after submission)."); + $this->assertEquals($langcode, $this->paragraph->language()->getId(), "The paragraph's langcode was inherited from its parent (after submission)."); + + // Switch to the form again. + $this->buildNodeForm($embedded); + + // Change the node's language from es to en. + if ($embedded) { + $this->formState->setValue(['embedded_entity_form', 'langcode'], [['value' => 'en']]); + } + else { + $this->formState->setValue('langcode', [['value' => 'en']]); + } + $this->submitNodeForm(); + + $langcode = $this->node->language()->getId(); + $this->assertEquals('en', $langcode, "The node's langcode was updated to value en (after submission)."); + $this->assertEquals($langcode, $this->paragraph->language()->getId(), "The paragraph's updated langcode was inherited from its parent (after submission)."); + + // Rebuild the form once more and make sure + // that the langcode change does not get lost. + $this->buildNodeForm($embedded); + + // Change the node's language from en to es. + if ($embedded) { + $this->formState->setValue(['embedded_entity_form', 'langcode'], [['value' => 'es']]); + } + else { + $this->formState->setValue('langcode', [['value' => 'es']]); + } + + $this->submitNodeForm(); + + $langcode = $this->node->language()->getId(); + $this->assertEquals('es', $langcode, "The node's langcode was set to es (after rebuild and submission)."); + $this->assertEquals($langcode, $this->paragraph->language()->getId(), "The paragraph's langcode was inherited from its parent (after rebuild and submission)."); + } + + /** + * Builds the node form. + * + * @param bool $embedded + * (Optional) Whether the embedded form should be used or not. + */ + protected function buildNodeForm($embedded = FALSE) { + if ($embedded) { + $this->formObject = new TestEmbeddedEntityForm($this->node); + } + else { + $this->formObject = $this->entityTypeManager->getFormObject('node', 'default'); + $this->formObject->setEntity($this->node); + } + $this->formState = (new FormState()) + ->disableRedirect() + ->setFormObject($this->formObject); + $this->form = $this->formBuilder->buildForm($this->formObject, $this->formState); + $this->reassignEntities(); + } + + /** + * Submits the node form, emulating the save operation as triggering element. + */ + protected function submitNodeForm() { + // Submit the form with the default save operation. + $this->formState->setValue('op', $this->formState->getValue('submit')); + $this->formBuilder->submitForm($this->formObject, $this->formState); + $this->reassignEntities(); + } + + /** + * Helper method to reassign the current entity objects. + */ + protected function reassignEntities() { + $this->node = $this->formObject->getEntity(); + $paragraphs = $this->node->get($this->nodeParagraphsFieldName)->referencedEntities(); + $this->paragraph = reset($paragraphs); + } + +} diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsReplicateTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsReplicateTest.php index 2d2b68a03b0b66e930c1ffd27cd4511daddd671a..c28c5c47df8f9d632d39150f28e342dc7548f4b5 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsReplicateTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsReplicateTest.php @@ -23,7 +23,7 @@ class ParagraphsReplicateTest extends KernelTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'paragraphs', 'replicate', 'node', @@ -37,7 +37,7 @@ class ParagraphsReplicateTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); // Create paragraphs and article content types. $values = ['type' => 'article', 'name' => 'Article']; diff --git a/web/modules/paragraphs/tests/src/Kernel/ParagraphsTypeHasEnabledBehaviorPluginTest.php b/web/modules/paragraphs/tests/src/Kernel/ParagraphsTypeHasEnabledBehaviorPluginTest.php index 05de58617fb831ea2291b813a7675a91d6b7df77..e016c4a7f633587fd66827a6d233a43d658c384d 100644 --- a/web/modules/paragraphs/tests/src/Kernel/ParagraphsTypeHasEnabledBehaviorPluginTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/ParagraphsTypeHasEnabledBehaviorPluginTest.php @@ -18,7 +18,7 @@ class ParagraphsTypeHasEnabledBehaviorPluginTest extends KernelTestBase { * * @var array */ - public static $modules = [ + protected static $modules = [ 'paragraphs', 'user', 'paragraphs_test', @@ -35,7 +35,7 @@ class ParagraphsTypeHasEnabledBehaviorPluginTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void{ parent::setUp(); $this->installEntitySchema('user'); $this->installEntitySchema('paragraph'); diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemRevisionSourceTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemRevisionSourceTest.php index 029541499207e16afe936ac3089ceeff315654ab..5136f27505bf96311dd01afe3704b4e774785a2e 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemRevisionSourceTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemRevisionSourceTest.php @@ -17,7 +17,7 @@ class FieldCollectionItemRevisionSourceTest extends MigrateSqlSourceTestBase { /** * {@inheritdoc} */ - public static $modules = ['migrate_drupal', 'paragraphs']; + protected static $modules = ['migrate_drupal', 'paragraphs']; /** * {@inheritdoc} diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemSourceTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemSourceTest.php index 0f30cce131b99bc1104fa79f089d05f7360e42af..3a545420e5cae0cc473070d41beb40043a988d92 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemSourceTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionItemSourceTest.php @@ -17,7 +17,7 @@ class FieldCollectionItemSourceTest extends MigrateSqlSourceTestBase { /** * {@inheritdoc} */ - public static $modules = ['migrate_drupal', 'paragraphs']; + protected static $modules = ['migrate_drupal', 'paragraphs']; /** * {@inheritdoc} diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionTypeSourceTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionTypeSourceTest.php index 1beaa8059a79a3fdb6bc266ee432623c33c57fd9..dec70ed8d0d5c3720851d040049148edfd31d929 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionTypeSourceTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/FieldCollectionTypeSourceTest.php @@ -17,7 +17,7 @@ class FieldCollectionTypeSourceTest extends MigrateSqlSourceTestBase { /** * {@inheritdoc} */ - public static $modules = ['migrate_drupal', 'paragraphs']; + protected static $modules = ['migrate_drupal', 'paragraphs']; /** * {@inheritdoc} diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphContentMigrationTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphContentMigrationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dc71738682eae7729f252bb952be0891046e5405 --- /dev/null +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphContentMigrationTest.php @@ -0,0 +1,112 @@ +<?php + +namespace Drupal\Tests\paragraphs\Kernel\migrate; + +use Drupal\Core\TypedData\TranslatableInterface; +use Drupal\node\Entity\Node; +use Drupal\Tests\paragraphs\Traits\ParagraphsNodeMigrationAssertionsTrait; + +/** + * Test 'classic' Paragraph content migration. + * + * @group paragraphs + * @require entity_reference_revisions + */ +class ParagraphContentMigrationTest extends ParagraphsMigrationTestBase { + + use ParagraphsNodeMigrationAssertionsTrait; + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'comment', + 'datetime', + 'datetime_range', + 'field', + 'file', + 'image', + 'link', + 'menu_ui', + 'node', + 'options', + 'system', + 'taxonomy', + 'telephone', + 'text', + 'user', + 'content_translation', + 'language' + ]; + + /** + * {@inheritdoc} + */ + public function setUp(): void { + parent::setUp(); + + $this->installEntitySchema('file'); + $this->installEntitySchema('node'); + $this->installEntitySchema('paragraph'); + $this->installEntitySchema('comment'); + $this->installSchema('node', ['node_access']); + $this->installSchema('comment', [ + 'comment_entity_statistics', + ]); + + $this->executeMigrationWithDependencies('d7_field_collection_revisions'); + $this->executeMigrationWithDependencies('d7_paragraphs_revisions'); + $this->executeMigrationWithDependencies('d7_node:paragraphs_test'); + + $this->prepareMigrations([ + 'd7_node:article' => [], + 'd7_node:blog' => [], + 'd7_node:book' => [], + 'd7_node:forum' => [], + 'd7_node:test_content_type' => [], + ]); + } + + /** + * Tests the migration of a content with paragraphs and field collections. + * + * @dataProvider providerParagraphContentMigration + */ + public function testParagraphContentMigration($migration_to_run) { + if ($migration_to_run) { + // Drupal 8.8.x only has 'classic' node migrations. + // @see https://www.drupal.org/node/3105503 + if (strpos($migration_to_run, 'd7_node_complete') === 0 && version_compare(\Drupal::VERSION, '8.9', '<')) { + $this->pass("Drupal 8.8.x has only the 'classic' node migration."); + return; + } + + $this->executeMigration($migration_to_run); + } + + $this->assertNode8Paragraphs(); + + $this->assertNode9Paragraphs(); + + $node_9 = Node::load(9); + if ($node_9 instanceof TranslatableInterface && !empty($node_9->getTranslationLanguages(FALSE))) { + $this->assertIcelandicNode9Paragraphs(); + } + } + + /** + * Provides data and expected results for testing paragraph migrations. + * + * @return string[][] + * The node migration to run. + */ + public function providerParagraphContentMigration() { + return [ + ['node_migration' => NULL], + ['node_migration' => 'd7_node_revision:paragraphs_test'], + ['node_migration' => 'd7_node_translation:paragraphs_test'], + ['node_migration' => 'd7_node_complete:paragraphs_test'], + ]; + } + +} diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsFieldMigrationTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsFieldMigrationTest.php index e4d93d7a24873db6dece757bca6b5318fe37baa6..434410f2bc8af7ede31d06370a749f1e9d71be0c 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsFieldMigrationTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsFieldMigrationTest.php @@ -18,20 +18,17 @@ class ParagraphsFieldMigrationTest extends ParagraphsMigrationTestBase { /** * {@inheritdoc} */ - public static $modules = [ + protected static $modules = [ 'comment', 'datetime', 'datetime_range', - 'entity_reference_revisions', 'field', 'file', 'image', 'link', 'menu_ui', - 'migrate_drupal', 'node', 'options', - 'paragraphs', 'system', 'taxonomy', 'telephone', diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemRevisionSourceTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemRevisionSourceTest.php index 70c3fa5e3f62d283be22b786cc73cc4c44f426bf..fca6b996430d1ea7a43edeba6232bd3c8d5ced45 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemRevisionSourceTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemRevisionSourceTest.php @@ -17,7 +17,7 @@ class ParagraphsItemRevisionSourceTest extends MigrateSqlSourceTestBase { /** * {@inheritdoc} */ - public static $modules = ['migrate_drupal', 'paragraphs']; + protected static $modules = ['migrate_drupal', 'paragraphs']; /** * {@inheritdoc} @@ -31,6 +31,8 @@ public function providerSource() { 'field_name' => 'field_paragraphs_field', 'bundle' => 'paragraphs_field', 'archived' => '0', + 'parent_id' => '42', + 'parent_type' => 'taxonomy_term', 'field_text' => [ 0 => [ 'value' => 'PID2R2 text', diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemSourceTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemSourceTest.php index 1ab9d2e5e8610f2dfdbfbc09ce7925398dd57da6..f55a234a4c929782ade9c3d13a5ae2445cc1f6a9 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemSourceTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsItemSourceTest.php @@ -17,7 +17,7 @@ class ParagraphsItemSourceTest extends MigrateSqlSourceTestBase { /** * {@inheritdoc} */ - public static $modules = ['migrate_drupal', 'paragraphs']; + protected static $modules = ['migrate_drupal', 'paragraphs']; /** * {@inheritdoc} @@ -31,6 +31,8 @@ public function providerSource() { 'field_name' => 'field_paragraphs_field', 'bundle' => 'paragraphs_field', 'archived' => '0', + 'parent_id' => '5', + 'parent_type' => 'node', 'field_text' => [ 0 => [ 'value' => 'PID1R1 text', @@ -43,6 +45,8 @@ public function providerSource() { 'field_name' => 'field_paragraphs_field', 'bundle' => 'paragraphs_field', 'archived' => '0', + 'parent_id' => '42', + 'parent_type' => 'taxonomy_term', 'field_text' => [ 0 => [ 'value' => 'PID2R3 text', diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsMigrationTestBase.php b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsMigrationTestBase.php index 4766443d80355264e0671c3e4bc7f891d3b4d462..10e6a33932b6130b9e1b6619be1a7cbd13fb400c 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsMigrationTestBase.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsMigrationTestBase.php @@ -16,7 +16,17 @@ abstract class ParagraphsMigrationTestBase extends MigrateDrupalTestBase { /** * {@inheritdoc} */ - public function setUp() { + protected static $modules = [ + 'entity_reference_revisions', + 'migrate', + 'migrate_drupal', + 'paragraphs', + ]; + + /** + * {@inheritdoc} + */ + public function setUp(): void { parent::setUp(); $this->loadFixture(__DIR__ . '/../../../fixtures/drupal7.php'); @@ -119,8 +129,7 @@ protected function executeMigrationDependencies(MigrationInterface $migration) { * {@inheritdoc} */ protected function prepareMigration(MigrationInterface $migration) { - - // We want to run the revision migraiton without running all the node + // We want to run the revision migration without running all the node // migrations. if ($migration->id() == 'd7_node_revision:paragraphs_test') { $migration->set('migration_dependencies', [ @@ -128,7 +137,6 @@ protected function prepareMigration(MigrationInterface $migration) { 'optional' => [], ]); $migration->set('requirements', ['d7_node:paragraphs_test' => 'd7_node:paragraphs_test']); - } } diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeMigrationTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeMigrationTest.php index ecb2d280a026f621f79295135350955919d804b8..1586d4d25e80a454d45019fa3bf93697b15ee6a4 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeMigrationTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeMigrationTest.php @@ -9,14 +9,6 @@ */ class ParagraphsTypeMigrationTest extends ParagraphsMigrationTestBase { - /** - * {@inheritdoc} - */ - public static $modules = [ - 'migrate', - 'paragraphs', - ]; - /** * Test if the paragraph/fc types were brought over as a paragraph. */ diff --git a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeSourceTest.php b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeSourceTest.php index 329113c6e2f2a7af8cc9ab48cdc03fa7cca882e9..565b5837f6dfeb25f815ca02e998973e43ec4409 100644 --- a/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeSourceTest.php +++ b/web/modules/paragraphs/tests/src/Kernel/migrate/ParagraphsTypeSourceTest.php @@ -17,7 +17,7 @@ class ParagraphsTypeSourceTest extends MigrateSqlSourceTestBase { /** * {@inheritdoc} */ - public static $modules = ['migrate_drupal', 'paragraphs']; + protected static $modules = ['migrate_drupal', 'paragraphs']; /** * {@inheritdoc} diff --git a/web/modules/paragraphs/tests/src/Traits/ParagraphsCoreVersionUiTestTrait.php b/web/modules/paragraphs/tests/src/Traits/ParagraphsCoreVersionUiTestTrait.php index f08040b2714618c118145daeb2b45893bc7b04a3..319d1718a83039e998080e014f7b4316fb0734d7 100644 --- a/web/modules/paragraphs/tests/src/Traits/ParagraphsCoreVersionUiTestTrait.php +++ b/web/modules/paragraphs/tests/src/Traits/ParagraphsCoreVersionUiTestTrait.php @@ -35,24 +35,38 @@ protected function paragraphsPostNodeForm($path, $edit, $submit, array $options if ($drupal_version > 8.3) { switch ($submit) { case t('Save and unpublish'): - $submit = t('Save'); + $submit = 'Save'; $edit['status[value]'] = FALSE; break; - case t('Save and publish'): - $submit = t('Save'); + case 'Save and publish': + $submit = 'Save'; $edit['status[value]'] = TRUE; break; - case t('Save and keep published (this translation)'): - $submit = t('Save (this translation)'); + case 'Save and keep published (this translation)': + $submit = 'Save (this translation)'; break; default: - $submit = t('Save'); + $submit = 'Save'; } } parent::drupalPostForm($path, $edit, $submit, $options, $headers, $form_html_id, $extra_post); } + /** + * Places commonly used blocks in a consistent order. + */ + protected function placeDefaultBlocks() { + // Place the system main block explicitly and first to have a consistent + // block order before and after Drupal 9.4 + $this->drupalPlaceBlock('system_main_block', ['weight' => -1, 'region' => 'content']); + // Place the breadcrumb, tested in fieldUIAddNewField(). + $this->drupalPlaceBlock('system_breadcrumb_block', ['region' => 'content']); + $this->drupalPlaceBlock('local_tasks_block', ['region' => 'content']); + $this->drupalPlaceBlock('local_actions_block', ['region' => 'content']); + $this->drupalPlaceBlock('page_title_block', ['region' => 'content']); + } + } diff --git a/web/modules/paragraphs/tests/src/Traits/ParagraphsLastEntityQueryTrait.php b/web/modules/paragraphs/tests/src/Traits/ParagraphsLastEntityQueryTrait.php index 91d74244136415e5f0e41f1d6335d861397e4d0a..0e4b239a4714117695e8e093dc1a46fa1a0dde04 100644 --- a/web/modules/paragraphs/tests/src/Traits/ParagraphsLastEntityQueryTrait.php +++ b/web/modules/paragraphs/tests/src/Traits/ParagraphsLastEntityQueryTrait.php @@ -25,6 +25,7 @@ trait ParagraphsLastEntityQueryTrait { */ protected function getLastEntityOfType($entity_type_id, $load = FALSE) { $query_result = \Drupal::entityQuery($entity_type_id) + ->accessCheck(TRUE) ->sort('created', 'DESC') ->range(0, 1) ->execute(); diff --git a/web/modules/paragraphs/tests/src/Traits/ParagraphsNodeMigrationAssertionsTrait.php b/web/modules/paragraphs/tests/src/Traits/ParagraphsNodeMigrationAssertionsTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..ed28675031abb68189cab48d2b1cc6a78c7daead --- /dev/null +++ b/web/modules/paragraphs/tests/src/Traits/ParagraphsNodeMigrationAssertionsTrait.php @@ -0,0 +1,136 @@ +<?php + +namespace Drupal\Tests\paragraphs\Traits; + +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\TypedData\TranslatableInterface; +use Drupal\entity_reference_revisions\EntityReferenceRevisionsFieldItemList; +use Drupal\node\Entity\Node; +use Drupal\node\NodeInterface; +use Drupal\paragraphs\ParagraphInterface; + +trait ParagraphsNodeMigrationAssertionsTrait { + + /** + * Assertions on node 8. + */ + protected function assertNode8Paragraphs() { + $node_8 = Node::load(8); + assert($node_8 instanceof NodeInterface); + // Check 'field collection test' field. + $node_8_field_collection_field_entities = $this->getReferencedEntities($node_8, 'field_field_collection_test', 2); + $this->assertEquals('Field Collection Text Data One UND', $node_8_field_collection_field_entities[0]->field_text->value); + $this->assertEquals('1', $node_8_field_collection_field_entities[0]->field_integer_list->value); + $this->assertEquals('Field Collection Text Data Two UND', $node_8_field_collection_field_entities[1]->field_text->value); + $this->assertNull($node_8_field_collection_field_entities[1]->field_integer_list->value); + // Check 'any paragraph' field. + $node_8_field_any_paragraph_entities = $this->getReferencedEntities($node_8, 'field_any_paragraph', 2); + $this->assertEquals('Paragraph Field One Bundle One UND', $node_8_field_any_paragraph_entities[0]->field_text->value); + $this->assertEquals('Some Text', $node_8_field_any_paragraph_entities[0]->field_text_list->value); + $this->assertEquals('Paragraph Field One Bundle Two UND', $node_8_field_any_paragraph_entities[1]->field_text->value); + $this->assertEquals('joe@joe.com', $node_8_field_any_paragraph_entities[1]->field_email->value); + // Check 'paragraph one only' field. + $node_8_field_paragraph_one_only_entities = $this->getReferencedEntities($node_8, 'field_paragraph_one_only', 1); + $this->assertEquals('Paragraph Field Two Bundle One Revision Two UND', $node_8_field_paragraph_one_only_entities[0]->field_text->value); + $this->assertEquals('Some more text', $node_8_field_paragraph_one_only_entities[0]->field_text_list->value); + // Check 'nested fc outer' field. + $node_8_field_nested_fc_outer_entities = $this->getReferencedEntities($node_8, 'field_nested_fc_outer', 1); + assert($node_8_field_nested_fc_outer_entities[0] instanceof ParagraphInterface); + $node_8_inner_nested_fc_0_entities = $this->getReferencedEntities($node_8_field_nested_fc_outer_entities[0], 'field_nested_fc_inner', 1); + $this->assertEquals('Nested FC test text', $node_8_inner_nested_fc_0_entities[0]->field_text->value); + } + + /** + * Assertions of node 9. + */ + protected function assertNode9Paragraphs() { + $node_9 = Node::load(9); + assert($node_9 instanceof NodeInterface); + + if ($this->container->get('module_handler')->moduleExists('content_translation') && $node_9 instanceof TranslatableInterface) { + // Test the default translation. + $node_9 = $node_9->getUntranslated(); + $this->assertSame('en', $node_9->language()->getId()); + } + + // Check 'field collection test' field. + $node_9_field_collection_field_entities = $this->getReferencedEntities($node_9, 'field_field_collection_test', 1); + $this->assertEquals('Field Collection Text Data Two EN', $node_9_field_collection_field_entities[0]->field_text->value); + $this->assertEquals('2', $node_9_field_collection_field_entities[0]->field_integer_list->value); + // Check 'any paragraph' field. + $node_9_field_any_paragraph_entities = $this->getReferencedEntities($node_9, 'field_any_paragraph', 2); + $this->assertEquals('Paragraph Field One Bundle One EN', $node_9_field_any_paragraph_entities[0]->field_text->value); + $this->assertEquals('Some Text', $node_9_field_any_paragraph_entities[0]->field_text_list->value); + $this->assertEquals('Paragraph Field One Bundle Two EN', $node_9_field_any_paragraph_entities[1]->field_text->value); + $this->assertEquals('jose@jose.com', $node_9_field_any_paragraph_entities[1]->field_email->value); + // Check 'paragraph one only' field. + $node_9_field_paragraph_one_only_entities = $this->getReferencedEntities($node_9, 'field_paragraph_one_only', 1); + $this->assertEquals('Paragraph Field Two Bundle One EN', $node_9_field_paragraph_one_only_entities[0]->field_text->value); + $this->assertEquals('Some Text', $node_9_field_paragraph_one_only_entities[0]->field_text_list->value); + // The 'nested fc outer' field should be empty. + $this->getReferencedEntities($node_9, 'field_nested_fc_outer', 0); + } + + /** + * Assertions of the Icelandic translation of node 9. + */ + protected function assertIcelandicNode9Paragraphs() { + // Confirm that the Icelandic translation of node 9 (which was node 10 on + // the source site) has the expected data. + $node_9 = Node::load(9); + assert($node_9 instanceof NodeInterface); + assert($node_9 instanceof TranslatableInterface); + $node_9_translation_languages = $node_9->getTranslationLanguages(FALSE); + $this->assertEquals(['is'], array_keys($node_9_translation_languages)); + $node_9 = $node_9->getTranslation('is'); + $this->assertSame('is', $node_9->language()->getId()); + + // Check 'field collection test' field. + $node_9_field_collection_field_entities = $this->getReferencedEntities($node_9, 'field_field_collection_test', 3); + $this->assertEquals('Field Collection Text Data One IS', $node_9_field_collection_field_entities[0]->field_text->value); + $this->assertEquals('1', $node_9_field_collection_field_entities[0]->field_integer_list->value); + $this->assertEquals('Field Collection Text Data Two IS', $node_9_field_collection_field_entities[1]->field_text->value); + $this->assertEquals('2', $node_9_field_collection_field_entities[1]->field_integer_list->value); + $this->assertEquals('Field Collection Text Data Three IS', $node_9_field_collection_field_entities[2]->field_text->value); + $this->assertEquals('3', $node_9_field_collection_field_entities[2]->field_integer_list->value); + // Check 'any paragraph' field. + $node_9_field_any_paragraph_entities = $this->getReferencedEntities($node_9, 'field_any_paragraph', 3); + $this->assertEquals('Paragraph Field One Bundle One IS', $node_9_field_any_paragraph_entities[0]->field_text->value); + $this->assertEquals('Some Text', $node_9_field_any_paragraph_entities[0]->field_text_list->value); + $this->assertEquals('Paragraph Field One Bundle Two IS', $node_9_field_any_paragraph_entities[1]->field_text->value); + $this->assertEquals('jose@jose.com', $node_9_field_any_paragraph_entities[1]->field_email->value); + $this->assertEquals('Paragraph Field One Bundle Two Delta 3 IS', $node_9_field_any_paragraph_entities[2]->field_text->value); + $this->assertEquals('john@john.com', $node_9_field_any_paragraph_entities[2]->field_email->value); + // Check 'paragraph one only' field. + $node_9_field_paragraph_one_only_entities = $this->getReferencedEntities($node_9, 'field_paragraph_one_only', 1); + $this->assertEquals('Paragraph Field Two Bundle One IS', $node_9_field_paragraph_one_only_entities[0]->field_text->value); + $this->assertEquals('Some more text', $node_9_field_paragraph_one_only_entities[0]->field_text_list->value); + // The 'nested fc outer' field should be empty. + $this->getReferencedEntities($node_9, 'field_nested_fc_outer', 0); + } + + /** + * Get the referred entities. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The parent entity. + * @param string $field_name + * The name of the entity revision reference field. + * @param int $expected_count + * The expected number of the referenced entities. + * + * @return \Drupal\Core\Entity\EntityInterface[] + * An array of entity objects keyed by field item deltas. + */ + protected function getReferencedEntities(ContentEntityInterface $entity, $field_name, int $expected_count) { + $entity_field = $entity->hasField($field_name) ? + $entity->get($field_name) : + NULL; + assert($entity_field instanceof EntityReferenceRevisionsFieldItemList); + $entity_field_entities = $entity_field->referencedEntities(); + $this->assertCount($expected_count, $entity_field_entities); + + return $entity_field_entities; + } + +} diff --git a/web/modules/paragraphs/tests/src/Traits/ParagraphsSourceData.php b/web/modules/paragraphs/tests/src/Traits/ParagraphsSourceData.php index 970e0da19d7cec6e07c4e4ece116bea406774e0c..aba892a72ef8256057971203d5995161a029d8a6 100644 --- a/web/modules/paragraphs/tests/src/Traits/ParagraphsSourceData.php +++ b/web/modules/paragraphs/tests/src/Traits/ParagraphsSourceData.php @@ -16,7 +16,7 @@ trait ParagraphsSourceData { protected function getSourceData() { $data = []; - $data[]['source_data'] = [ + $data[0]['source_data'] = [ 'paragraphs_bundle' => [ [ 'bundle' => 'paragraphs_field', @@ -103,7 +103,31 @@ protected function getSourceData() { 'revision_id' => '3', ], ], + 'field_data_field_paragraphs_field' => [ + [ + 'entity_type' => 'node', + 'entity_id' => '5', + // @todo Don't we have to match also entity revision IDs? + // 'revision_id' => 'something', + 'field_paragraphs_field_value' => '1', + 'field_paragraphs_field_revision_id' => '1', + ], + [ + 'entity_type' => 'taxonomy_term', + 'entity_id' => '42', + 'field_paragraphs_field_value' => '2', + 'field_paragraphs_field_revision_id' => '3', + ], + ], ]; + $data[0]['source_data']['field_revision_field_paragraphs_field'] = array_merge($data[0]['source_data']['field_data_field_paragraphs_field'], [ + [ + 'entity_type' => 'taxonomy_term', + 'entity_id' => '42', + 'field_paragraphs_field_value' => '2', + 'field_paragraphs_field_revision_id' => '2', + ], + ]); return $data; } diff --git a/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionFieldSettingsTest.php b/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionFieldSettingsTest.php index 20248a114cd27b19738f157ed632091c954a107d..e47d6fbd80ad904d35ea928d3918bb4528f8eded 100644 --- a/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionFieldSettingsTest.php +++ b/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionFieldSettingsTest.php @@ -16,7 +16,7 @@ class FieldCollectionFieldSettingsTest extends MigrateProcessTestCase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { $this->plugin = new FieldCollectionFieldSettings([], 'field_collection_field_settings', []); parent::setUp(); @@ -31,7 +31,7 @@ public function testParagraphsFieldSettings() { ->with('type') ->willReturn('field_collection'); $value = $this->plugin->transform([], $this->migrateExecutable, $this->row, 'settings'); - $this->assertArrayEquals(['target_type' => 'paragraph'], $value); + $this->assertEquals(['target_type' => 'paragraph'], $value); } /** @@ -55,7 +55,7 @@ public function testTaxonomyParagraphFieldSettings() { ->with('type') ->willReturn('taxonomy_term'); $value = $this->plugin->transform(['target_type' => 'some_preset_vaue'], $this->migrateExecutable, $this->row, 'settings'); - $this->assertArrayEquals(['target_type' => 'some_preset_vaue'], $value); + $this->assertEquals(['target_type' => 'some_preset_vaue'], $value); } } diff --git a/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionsFieldInstanceSettingsTest.php b/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionsFieldInstanceSettingsTest.php index 1a845317e2d998dd59c0acccb987ca1bddc17c02..00fafb6609b108fb130646cbf0fdd8a4ad103589 100644 --- a/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionsFieldInstanceSettingsTest.php +++ b/web/modules/paragraphs/tests/src/Unit/migrate/FieldCollectionsFieldInstanceSettingsTest.php @@ -16,7 +16,7 @@ class FieldCollectionsFieldInstanceSettingsTest extends ProcessTestCase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->plugin = new FieldCollectionFieldInstanceSettings([], 'field_collection_field_instance_settings', [], $this->entityTypeBundleInfo); @@ -43,7 +43,7 @@ public function testFieldCollectionInstanceFieldSettings(array $source, array $e ]); $value = $this->plugin->transform($source, $this->migrateExecutable, $this->row, 'settings'); - $this->assertArrayEquals($expected, $value); + $this->assertEquals($expected, $value); } /** diff --git a/web/modules/paragraphs/tests/src/Unit/migrate/MigrationPluginsAltererTest.php b/web/modules/paragraphs/tests/src/Unit/migrate/MigrationPluginsAltererTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4ac93577a65896415a4eb45a86816eb0728d3e76 --- /dev/null +++ b/web/modules/paragraphs/tests/src/Unit/migrate/MigrationPluginsAltererTest.php @@ -0,0 +1,197 @@ +<?php + +namespace Drupal\Tests\paragraphs\Unit\migrate; + +use Drupal\paragraphs\MigrationPluginsAlterer; +use Drupal\Tests\UnitTestCase; + +/** + * Tests the MigrationPluginsAlterer service. + * + * @todo Cover every method. + * + * @coversDefaultClass \Drupal\paragraphs\MigrationPluginsAlterer + * + * @group paragraphs + */ +class MigrationPluginsAltererTest extends UnitTestCase { + + /** + * The migration plugin alterer. + * + * @var \Drupal\paragraphs\MigrationPluginsAlterer + */ + protected $paragraphsMigrationPluginsAlterer; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $logger_channel = $this->createMock('Drupal\Core\Logger\LoggerChannelInterface'); + $logger_factory = $this->getMockBuilder('Drupal\Core\Logger\LoggerChannelFactory') + ->getMock(); + $logger_factory->expects($this->atLeastOnce()) + ->method('get') + ->with('paragraphs') + ->will($this->returnValue($logger_channel)); + + $this->paragraphsMigrationPluginsAlterer = new MigrationPluginsAlterer($logger_factory); + } + + /** + * Tests that migration processes are transformed to an array of processors. + * + * @dataProvider providerParagraphsMigrationPrepareProcess + * @covers ::paragraphsMigrationPrepareProcess + */ + public function testParagraphsMigrationPrepareProcess(array $input, array $expected) { + ['process' => $process, 'property' => $property] = $input; + $success = $this->paragraphsMigrationPluginsAlterer->paragraphsMigrationPrepareProcess($process, $property); + $this->assertSame($expected['return'], $success); + $this->assertEquals($expected['process'], $process); + } + + /** + * Provides data and expected results for testing the prepare process method. + * + * @return array[] + * Data and expected results. + */ + public function providerParagraphsMigrationPrepareProcess() { + return [ + // Missing property (no change). + [ + 'input' => [ + 'process' => [ + 'catname' => 'Picurka', + 'wont/touch' => 'this', + ], + 'property' => 'missing', + ], + 'expected' => [ + 'return' => FALSE, + 'process' => [ + 'catname' => 'Picurka', + 'wont/touch' => 'this', + ], + ], + ], + // Existing string property. + [ + 'input' => [ + 'process' => [ + 'catname' => 'Picurka', + 'wont/touch' => 'this', + ], + 'property' => 'catname', + ], + 'expected' => [ + 'return' => TRUE, + 'process' => [ + 'catname' => [ + [ + 'plugin' => 'get', + 'source' => 'Picurka', + ], + ], + 'wont/touch' => 'this', + ], + ], + ], + // Single process plugin. + [ + 'input' => [ + 'process' => [ + 'cat' => [ + 'plugin' => 'migration_lookup', + 'migration' => 'cats', + 'source' => 'cat_id', + ], + ], + 'property' => 'cat', + ], + 'expected' => [ + 'return' => TRUE, + 'process' => [ + 'cat' => [ + [ + 'plugin' => 'migration_lookup', + 'migration' => 'cats', + 'source' => 'cat_id', + ], + ], + ], + ], + ], + // Array of process plugins (no change). + [ + 'input' => [ + 'process' => [ + 'catname' => [ + [ + 'plugin' => 'migration_lookup', + 'migration' => 'cats', + 'source' => 'cat_id', + ], + [ + 'plugin' => 'extract', + 'index' => ['name'], + ], + [ + 'plugin' => 'callback', + 'callable' => 'ucfirst', + ], + ], + ], + 'property' => 'catname', + ], + 'expected' => [ + 'return' => TRUE, + 'process' => [ + 'catname' => [ + [ + 'plugin' => 'migration_lookup', + 'migration' => 'cats', + 'source' => 'cat_id', + ], + [ + 'plugin' => 'extract', + 'index' => ['name'], + ], + [ + 'plugin' => 'callback', + 'callable' => 'ucfirst', + ], + ], + ], + ], + ], + // Invalid type. + [ + 'input' => [ + 'process' => [ + 'invalid' => (object) [ + [ + 'not a' => 'kitten', + ], + ], + ], + 'property' => 'invalid', + ], + 'expected' => [ + 'return' => FALSE, + 'process' => [ + 'invalid' => (object) [ + [ + 'not a' => 'kitten', + ], + ], + ], + ], + ], + ]; + } + +} diff --git a/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldInstanceSettingsTest.php b/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldInstanceSettingsTest.php index 848a73f1ac8924062a1f7f717fd408109bb9573d..4bbb55c6d790a4974f8408efab53547b7d4f8cb5 100644 --- a/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldInstanceSettingsTest.php +++ b/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldInstanceSettingsTest.php @@ -15,7 +15,7 @@ class ParagraphsFieldInstanceSettingsTest extends ProcessTestCase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->row->expects($this->any()) ->method('getSourceProperty') @@ -39,7 +39,7 @@ public function testParagraphsInstanceFieldSettings(array $source, array $expect $value = $this->plugin->transform($source, $this->migrateExecutable, $this->row, 'settings'); - $this->assertArrayEquals($expected, $value); + $this->assertEquals($expected, $value); } /** diff --git a/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldSettingsTest.php b/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldSettingsTest.php index 2c8e84fa7ef0322e145c8fbb2cda0baa84b4444b..6c73cb1461dab8d68316066e3229a5ad745b8f43 100644 --- a/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldSettingsTest.php +++ b/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsFieldSettingsTest.php @@ -16,7 +16,7 @@ class ParagraphsFieldSettingsTest extends MigrateProcessTestCase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { $this->plugin = new ParagraphsFieldSettings([], 'paragraphs_field_settings', []); parent::setUp(); @@ -31,7 +31,7 @@ public function testParagraphsFieldSettings() { ->with('type') ->willReturn('paragraphs'); $value = $this->plugin->transform([], $this->migrateExecutable, $this->row, 'settings'); - $this->assertArrayEquals(['target_type' => 'paragraph'], $value); + $this->assertEquals(['target_type' => 'paragraph'], $value); } /** @@ -55,7 +55,7 @@ public function testTaxonomyParagraphFieldSettings() { ->with('type') ->willReturn('taxonomy_term'); $value = $this->plugin->transform(['target_type' => 'some_preset_vaue'], $this->migrateExecutable, $this->row, 'settings'); - $this->assertArrayEquals(['target_type' => 'some_preset_vaue'], $value); + $this->assertEquals(['target_type' => 'some_preset_vaue'], $value); } } diff --git a/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsProcessOnValueTest.php b/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsProcessOnValueTest.php index c016690460b39b609d09ab49e05dbf3253da946e..e3ec84256c504c083bd23f57b7405b3695aa37f0 100644 --- a/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsProcessOnValueTest.php +++ b/web/modules/paragraphs/tests/src/Unit/migrate/ParagraphsProcessOnValueTest.php @@ -26,7 +26,7 @@ class ParagraphsProcessOnValueTest extends ProcessTestCase { /** * {@inheritdoc} */ - public function setup() { + public function setUp(): void { parent::setup(); $configuration = [ 'source_value' => 'source', diff --git a/web/modules/paragraphs/tests/src/Unit/migrate/ProcessTestCase.php b/web/modules/paragraphs/tests/src/Unit/migrate/ProcessTestCase.php index c2fe37d0910af3591b7813a9bfbbc90bc83253ba..0dfca72955764c5802d5066f85c93915222c2f56 100644 --- a/web/modules/paragraphs/tests/src/Unit/migrate/ProcessTestCase.php +++ b/web/modules/paragraphs/tests/src/Unit/migrate/ProcessTestCase.php @@ -20,7 +20,7 @@ abstract class ProcessTestCase extends MigrateProcessTestCase { /** * {@inheritdoc} */ - protected function setup() { + protected function setUp(): void { parent::setUp(); $this->entityTypeBundleInfo = $this->getMockBuilder(EntityTypeBundleInfo::class)