Skip to content

Commit a1745d6

Browse files
committed
Merge branch '2.4-develop' of https://github.com/magento-commerce/magento2ce into ACP2E-111
2 parents cc8206c + 7431f26 commit a1745d6

File tree

125 files changed

+1943
-498
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+1943
-498
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminFillCaptchaOnResetPasswordFormActionGroup">
12+
<arguments>
13+
<argument name="captcha" type="string"/>
14+
</arguments>
15+
<fillField userInput="{{captcha}}" selector="{{AdminResetPasswordFormSection.captchaField}}" stepKey="fillCaptchaField"/>
16+
</actionGroup>
17+
</actionGroups>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AssertCaptchaVisibleOnAdminResetPasswordFormActionGroup">
12+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaField}}" stepKey="waitToSeeCaptchaField"/>
13+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImage"/>
14+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButton"/>
15+
<reloadPage stepKey="refreshPage"/>
16+
<waitForPageLoad stepKey="waitForPageReloaded"/>
17+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaField}}" stepKey="waitToSeeCaptchaFieldAfterPageReload"/>
18+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaImg}}" stepKey="waitToSeeCaptchaImageAfterPageReload"/>
19+
<waitForElementVisible selector="{{AdminResetPasswordFormSection.captchaReload}}" stepKey="waitToSeeCaptchaReloadButtonAfterPageReload"/>
20+
</actionGroup>
21+
</actionGroups>

app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,33 @@
163163
<data key="label">ABCDEFGHJKMnpqrstuvwxyz23456789</data>
164164
<data key="value">ABCDEFGHJKMnpqrstuvwxyz23456789</data>
165165
</entity>
166+
<entity name="AdminCaptchaForgotPasswordFormConfigData">
167+
<!-- Magento default value -->
168+
<data key="path">admin/captcha/forms</data>
169+
<data key="scope_id">1</data>
170+
<data key="label">Admin Forgot Password</data>
171+
<data key="value">backend_forgotpassword</data>
172+
</entity>
173+
<entity name="AdminCaptchaDisplayModeConfigData">
174+
<data key="path">admin/captcha/mode</data>
175+
<data key="scope_id">1</data>
176+
<data key="label">Always</data>
177+
<data key="value">always</data>
178+
</entity>
179+
<entity name="AdminCaptchaDefaultDisplayModeConfigData">
180+
<!-- Magento default value -->
181+
<data key="path">admin/captcha/mode</data>
182+
<data key="scope_id">0</data>
183+
<data key="label">After number of attempts to login</data>
184+
<data key="value">after_fail</data>
185+
</entity>
186+
<entity name="AdminCaptchaAdminLoginFormConfigData">
187+
<!-- Magento default value -->
188+
<data key="path">admin/captcha/forms</data>
189+
<data key="scope_id">1</data>
190+
<data key="label">AdminLogin</data>
191+
<data key="value">backend_login</data>
192+
</entity>
166193
<entity name="StorefrontCaptchaOnCheckoutConfigData">
167194
<data key="path">customer/captcha/forms</data>
168195
<data key="scope_id">0</data>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
11+
<section name="AdminResetPasswordFormSection">
12+
<element name="captchaField" type="input" selector="#login-form input[name='captcha[backend_forgotpassword]']"/>
13+
<element name="captchaImg" type="block" selector="#login-form img#backend_forgotpassword"/>
14+
<element name="captchaReload" type="block" selector="#login-form img#captcha-reload.captcha-reload"/>
15+
</section>
16+
</sections>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AdminResetUserPasswordWithEnabledCaptchaTest">
12+
<annotations>
13+
<features value="captcha"/>
14+
<stories value="Password Reset procedure for Admin Panel"/>
15+
<title value="Admin user reset password with enabled captcha "/>
16+
<description value="Admin user should be able reset the password with enabled captcha"/>
17+
<severity value="MAJOR"/>
18+
<group value="captcha"/>
19+
</annotations>
20+
<before>
21+
<magentoCLI command="config:set {{AdminCaptchaLength3ConfigData.path}} {{AdminCaptchaLength3ConfigData.value}}" stepKey="setCaptchaLength"/>
22+
<magentoCLI command="config:set {{AdminCaptchaSymbols1ConfigData.path}} {{AdminCaptchaSymbols1ConfigData.value}}" stepKey="setCaptchaSymbols"/>
23+
<magentoCLI command="config:set {{AdminCaptchaForgotPasswordFormConfigData.path}} {{AdminCaptchaForgotPasswordFormConfigData.value}}" stepKey="enableResetPasswordCaptcha"/>
24+
<magentoCLI command="config:set {{AdminCaptchaDisplayModeConfigData.path}} {{AdminCaptchaDisplayModeConfigData.value}}" stepKey="setCaptchaAlwaysVisible"/>
25+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches">
26+
<argument name="tags" value="config full_page"/>
27+
</actionGroup>
28+
</before>
29+
30+
<after>
31+
<magentoCLI command="config:set {{AdminCaptchaDefaultLengthConfigData.path}} {{AdminCaptchaDefaultLengthConfigData.value}}" stepKey="setDefaultCaptchaLength"/>
32+
<magentoCLI command="config:set {{AdminCaptchaDefaultSymbolsConfigData.path}} {{AdminCaptchaDefaultSymbolsConfigData.value}}" stepKey="setDefaultCaptchaSymbols"/>
33+
<magentoCLI command="config:set {{AdminCaptchaDefaultDisplayModeConfigData.path}} {{AdminCaptchaDefaultDisplayModeConfigData.value}}" stepKey="setCaptchaDefaultVisibility"/>
34+
<magentoCLI command="config:set {{AdminCaptchaForgotPasswordFormConfigData.path}} {{AdminCaptchaForgotPasswordFormConfigData.value}},{{AdminCaptchaAdminLoginFormConfigData.value}}" stepKey="setDefaultCaptchaValuesOnForms"/>
35+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches">
36+
<argument name="tags" value="config full_page"/>
37+
</actionGroup>
38+
</after>
39+
40+
<actionGroup ref="AdminOpenForgotPasswordPageActionGroup" stepKey="openAdminForgotPasswordPage"/>
41+
<actionGroup ref="AssertCaptchaVisibleOnAdminResetPasswordFormActionGroup" stepKey="assertCaptchaVisible"/>
42+
<actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillAdminForgotPasswordForm">
43+
<argument name="email" value="{{inactiveAdmin.email}}"/>
44+
</actionGroup>
45+
<actionGroup ref="AdminFillCaptchaOnResetPasswordFormActionGroup" stepKey="fillCaptchaWithInvalidValues">
46+
<argument name="captcha" value="{{WrongCaptcha.value}}"/>
47+
</actionGroup>
48+
<actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordForm"/>
49+
<actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeErrorMessage">
50+
<argument name="messageType" value="error"/>
51+
<argument name="message" value="Incorrect CAPTCHA"/>
52+
</actionGroup>
53+
<actionGroup ref="AdminFillForgotPasswordFormActionGroup" stepKey="fillEmailOnAdminForgotPasswordForm">
54+
<argument name="email" value="{{inactiveAdmin.email}}"/>
55+
</actionGroup>
56+
<actionGroup ref="AdminFillCaptchaOnResetPasswordFormActionGroup" stepKey="fillCaptchaWithCorrectValues">
57+
<argument name="captcha" value="{{PreconfiguredCaptcha.value}}"/>
58+
</actionGroup>
59+
<actionGroup ref="AdminSubmitForgotPasswordFormActionGroup" stepKey="submitAdminForgotPasswordFormWithCorrectCaptcha"/>
60+
<actionGroup ref="AssertMessageOnAdminLoginActionGroup" stepKey="seeSuccessMessage">
61+
<argument name="messageType" value="success"/>
62+
<argument name="message" value="We'll email you a link to reset your password."/>
63+
</actionGroup>
64+
</test>
65+
</tests>

app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ protected function _getIndexableAttributes($multiSelect)
105105
);
106106

107107
if ($multiSelect == true) {
108-
$select->where('ea.backend_type = ?', 'varchar')->where('ea.frontend_input = ?', 'multiselect');
108+
$select->where('ea.backend_type = ?', 'text')->where('ea.frontend_input = ?', 'multiselect');
109109
} else {
110110
$select->where('ea.backend_type = ?', 'int')->where('ea.frontend_input IN( ? )', ['select', 'boolean']);
111111
}
@@ -303,14 +303,14 @@ protected function _prepareMultiselectIndex($entityIds = null, $attributeId = nu
303303
// prepare get multiselect values query
304304
$productValueExpression = $connection->getCheckSql('pvs.value_id > 0', 'pvs.value', 'pvd.value');
305305
$select = $connection->select()->from(
306-
['pvd' => $this->getTable('catalog_product_entity_varchar')],
306+
['pvd' => $this->getTable('catalog_product_entity_text')],
307307
[]
308308
)->join(
309309
['cs' => $this->getTable('store')],
310310
'',
311311
[]
312312
)->joinLeft(
313-
['pvs' => $this->getTable('catalog_product_entity_varchar')],
313+
['pvs' => $this->getTable('catalog_product_entity_text')],
314314
"pvs.{$productIdField} = pvd.{$productIdField} AND pvs.attribute_id = pvd.attribute_id"
315315
. ' AND pvs.store_id=cs.store_id',
316316
[]

app/code/Magento/Catalog/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,72 @@
1+
#Magento_Catalog
12
Magento_Catalog module functionality is represented by the following sub-systems:
23
- Products Management. It includes CRUD operation of product, product media, product attributes, etc...
34
- Category Management. It includes CRUD operation of category, category attributes
45

56
Catalog module provides mechanism for creating new product type in the system.
67
Catalog module provides API filtering that allows to limit product selection with advanced filters.
8+
9+
## Structure
10+
11+
[Learn about a typical file structure for a Magento 2 module]
12+
(https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html).
13+
14+
## Observer
15+
This module observes the following events:
16+
`etc/events.xml`
17+
`magento_catalog_api_data_productinterface_save_before` event in
18+
`Magento\Framework\EntityManager\Observer\BeforeEntitySave` file.
19+
`magento_catalog_api_data_productinterface_save_after` event in
20+
`Magento\Framework\EntityManager\Observer\AfterEntitySave` file.
21+
`magento_catalog_api_data_productinterface_delete_before` event in
22+
`Magento\Framework\EntityManager\Observer\BeforeEntityDelete` file.
23+
`magento_catalog_api_data_productinterface_delete_after` event in
24+
`Magento\Framework\EntityManager\Observer\AfterEntityDelete` file.
25+
`magento_catalog_api_data_productinterface_load_after` event in
26+
`Magento\Framework\EntityManager\Observer\AfterEntityLoad` file.
27+
`magento_catalog_api_data_categoryinterface_save_before` event in
28+
`Magento\Framework\EntityManager\Observer\BeforeEntitySave` file.
29+
`magento_catalog_api_data_categoryinterface_save_after` event in
30+
`Magento\Framework\EntityManager\Observer\AfterEntitySave` file.
31+
`magento_catalog_api_data_categoryinterface_save_after` event in
32+
`Magento\Catalog\Observer\InvalidateCacheOnCategoryDesignChange` file.
33+
`magento_catalog_api_data_categoryinterface_delete_before` event in
34+
`Magento\Framework\EntityManager\Observer\BeforeEntityDelete` file.
35+
`magento_catalog_api_data_categoryinterface_delete_after` event in
36+
`Magento\Framework\EntityManager\Observer\AfterEntityDelete` file.
37+
`magento_catalog_api_data_categoryinterface_load_after` event in
38+
`Magento\Framework\EntityManager\Observer\AfterEntityLoad` file.
39+
`magento_catalog_api_data_categorytreeinterface_save_before` event in
40+
`Magento\Framework\EntityManager\Observer\BeforeEntitySave` file.
41+
`magento_catalog_api_data_categorytreeinterface_save_after` event in
42+
`Magento\Framework\EntityManager\Observer\AfterEntitySave` file.
43+
`magento_catalog_api_data_categorytreeinterface_delete_before` event in
44+
`Magento\Framework\EntityManager\Observer\BeforeEntityDelete` file.
45+
`magento_catalog_api_data_categorytreeinterface_delete_after` event in
46+
`Magento\Framework\EntityManager\Observer\AfterEntityDelete` file.
47+
`magento_catalog_api_data_categorytreeinterface_load_after` event in
48+
`Magento\Framework\EntityManager\Observer\AfterEntityLoad` file.
49+
`admin_system_config_changed_section_catalog` event in
50+
`Magento\Catalog\Observer\SwitchPriceAttributeScopeOnConfigChange` file.
51+
`catalog_product_save_before` event in
52+
`Magento\Catalog\Observer\SetSpecialPriceStartDate` file.
53+
`store_save_after` event in
54+
`Magento\Catalog\Observer\SynchronizeWebsiteAttributesOnStoreChange` file.
55+
`catalog_product_save_commit_after` event in
56+
`Magento\Catalog\Observer\ImageResizeAfterProductSave` file.
57+
`catalog_category_prepare_save` event in
58+
`Magento\Catalog\Observer\CategoryDesignAuthorization` file.
59+
60+
`/etc/frontend/events.xml`
61+
`customer_login` event in
62+
`Magento\Catalog\Observer\Compare\BindCustomerLoginObserver` file.
63+
`customer_logout` event in
64+
`Magento\Catalog\Observer\Compare\BindCustomerLogoutObserver` file.
65+
66+
`/etc/adminhtml/events.xml`
67+
`cms_wysiwyg_images_static_urls_allowed` event in
68+
`Magento\Catalog\Observer\CatalogCheckIsUsingStaticUrlsAllowedObserver` file.
69+
`catalog_category_change_products` event in
70+
`Magento\Catalog\Observer\CategoryProductIndexer` file.
71+
`category_move` event in
72+
`Magento\Catalog\Observer\FlushCategoryPagesCache`
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Setup\Patch\Data;
8+
9+
use Magento\Catalog\Model\Product;
10+
use Magento\Eav\Setup\EavSetup;
11+
use Magento\Eav\Setup\EavSetupFactory;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\Setup\ModuleDataSetupInterface;
14+
use Magento\Framework\Setup\Patch\DataPatchInterface;
15+
16+
class UpdateMultiselectAttributesBackendTypes implements DataPatchInterface
17+
{
18+
/**
19+
* @var ModuleDataSetupInterface
20+
*/
21+
private $dataSetup;
22+
/**
23+
* @var EavSetupFactory
24+
*/
25+
private $eavSetupFactory;
26+
27+
/**
28+
* MigrateMultiselectAttributesData constructor.
29+
* @param ModuleDataSetupInterface $dataSetup
30+
* @param EavSetupFactory $eavSetupFactory
31+
*/
32+
public function __construct(
33+
ModuleDataSetupInterface $dataSetup,
34+
EavSetupFactory $eavSetupFactory
35+
) {
36+
$this->dataSetup = $dataSetup;
37+
$this->eavSetupFactory = $eavSetupFactory;
38+
}
39+
40+
/**
41+
* @inheritdoc
42+
*/
43+
public static function getDependencies()
44+
{
45+
return [];
46+
}
47+
48+
/**
49+
* @inheritdoc
50+
*/
51+
public function getAliases()
52+
{
53+
return [];
54+
}
55+
56+
/**
57+
* @inheritdoc
58+
*/
59+
public function apply()
60+
{
61+
$this->dataSetup->startSetup();
62+
63+
$connection = $this->dataSetup->getConnection();
64+
$attributeTable = $connection->getTableName('eav_attribute');
65+
/** @var EavSetup $eavSetup */
66+
$eavSetup = $this->eavSetupFactory->create(['setup' => $this->dataSetup]);
67+
$entityTypeId = $eavSetup->getEntityTypeId(Product::ENTITY);
68+
$attributesToMigrate = $connection->fetchCol(
69+
$connection
70+
->select()
71+
->from($attributeTable, ['attribute_id'])
72+
->where('entity_type_id = ?', $entityTypeId)
73+
->where('backend_type = ?', 'varchar')
74+
->where('frontend_input = ?', 'multiselect')
75+
);
76+
77+
$varcharTable = $connection->getTableName('catalog_product_entity_varchar');
78+
$textTable = $connection->getTableName('catalog_product_entity_text');
79+
$varcharTableDataSql = $connection
80+
->select()
81+
->from($varcharTable)
82+
->where('attribute_id in (?)', $attributesToMigrate);
83+
$dataToMigrate = array_map(static function ($row) {
84+
$row['value_id'] = null;
85+
return $row;
86+
}, $connection->fetchAll($varcharTableDataSql));
87+
88+
foreach (array_chunk($dataToMigrate, 2000) as $dataChunk) {
89+
$connection->insertMultiple($textTable, $dataChunk);
90+
}
91+
92+
$connection->query($connection->deleteFromSelect($varcharTableDataSql, $varcharTable));
93+
94+
foreach ($attributesToMigrate as $attributeId) {
95+
$eavSetup->updateAttribute($entityTypeId, $attributeId, 'backend_type', 'text');
96+
}
97+
98+
$this->dataSetup->endSetup();
99+
100+
return $this;
101+
}
102+
}

app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveAndNotIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,26 @@
3333
<actionGroup ref="AdminOpenCategoryPageActionGroup" stepKey="openAdminCategoryIndexPage"/>
3434
<!--Create subcategory under parent category -->
3535
<actionGroup ref="AdminExpandCategoryTreeActionGroup" stepKey="clickOnExpandTree"/>
36-
<click selector="{{AdminCategorySidebarTreeSection.categoryInTree($$createCategory.name$$)}}" stepKey="selectCategory"/>
37-
<waitForPageLoad stepKey="waitForPageToLoad"/>
36+
<actionGroup ref="AdminCategoriesOpenCategoryActionGroup" stepKey="selectCategory">
37+
<argument name="category" value="$$createCategory$$"/>
38+
</actionGroup>
39+
<comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageToLoad"/>
3840
<click selector="{{AdminCategorySidebarActionSection.AddSubcategoryButton}}" stepKey="clickOnAddSubCategoryButton"/>
3941
<checkOption selector="{{AdminCategoryBasicFieldSection.EnableCategory}}" stepKey="enableCategory"/>
4042
<checkOption selector="{{AdminCategoryBasicFieldSection.IncludeInMenu}}" stepKey="enableIncludeInMenu"/>
4143
<fillField selector="{{AdminCategoryBasicFieldSection.CategoryNameInput}}" userInput="{{SimpleSubCategory.name}}" stepKey="addSubCategoryName"/>
4244
<actionGroup ref="AdminSaveCategoryActionGroup" stepKey="saveSubCategory"/>
43-
<seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="seeSuccessMessage"/>
45+
<actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="seeSuccessMessage">
46+
<argument name="message" value="You saved the category."/>
47+
</actionGroup>
4448
<!-- Verify Parent Category and Sub category is not visible in navigation menu -->
4549
<amOnPage url="$$createCategory.custom_attributes[url_key]$$/{{SimpleSubCategory.urlKey}}.html" stepKey="openCategoryStoreFrontPage"/>
4650
<waitForPageLoad stepKey="waitForCategoryStoreFrontPageToLoad"/>
47-
<dontSeeElement selector="{{StorefrontHeaderSection.NavigationCategoryByName($$createCategory.name$$)}}" stepKey="dontSeeCategoryOnStoreNavigationBar"/>
48-
<dontSeeElement selector="{{StorefrontHeaderSection.NavigationCategoryByName(SimpleSubCategory.name)}}" stepKey="dontSeeSubCategoryOnStoreNavigation"/>
51+
<actionGroup ref="StorefrontAssertCategoryNameIsNotShownInMenuActionGroup" stepKey="dontSeeCategoryOnStoreNavigationBar">
52+
<argument name="categoryName" value="$$createCategory.name$$"/>
53+
</actionGroup>
54+
<actionGroup ref="StorefrontAssertCategoryNameIsNotShownInMenuActionGroup" stepKey="dontSeeSubCategoryOnStoreNavigation">
55+
<argument name="categoryName" value="{{SimpleSubCategory.name}}"/>
56+
</actionGroup>
4957
</test>
5058
</tests>

0 commit comments

Comments
 (0)