diff --git a/.phpunit.result.cache b/.phpunit.result.cache index e28de50..784ee99 100644 --- a/.phpunit.result.cache +++ b/.phpunit.result.cache @@ -1 +1 @@ -{"version":1,"defects":{"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":4,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":3,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenNoApiKey":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenWrongApiKey":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenStoredKeyEmpty":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingEndpoint":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingAction":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns404ForUnknownEndpoint":4,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueKeepsTaskWhenApiloOrderIdIsNull":3,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueRemovesTaskAfterMaxAttempts":3,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeRejectsGetMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeReturns400WhenNoBody":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueRejectsGetMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueReturns400WhenNoBody":4,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextUpdatesStatusToProcessing":3,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorAcceptsRepository":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasMainViewMethod":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testMainViewReturnsString":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateMethod":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateAllMethod":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorRequiresRepository":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeletePermanentlyRemovesArticleAndRelations":3,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsTrueWhenDeleted":3},"times":{"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsCorrectValue":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsNullWhenProductNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindReturnsProductData":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateQuantitySuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsPromoPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularWhenPromoIsHigher":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsProductName":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsInteger":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveReturnsBool":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveReturnsBool":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasUnarchiveMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testUnarchiveMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorRequiresProductRepository":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsBannerWithTranslations":0.001,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testDeleteReturnsTrue":0.002,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveInsertsNewBanner":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithRedis":0.001,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheRedisUnavailable":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithoutRedis":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheReturnStructure":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testCanBeInstantiated":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasSaveSettingsMethod":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasGetSettingsMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheAjaxMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasViewMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testIsNotAbstract":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testCanCreateController":0.005,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testEditMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsArticleWithRelations":0.006,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsNullWhenArticleDoesNotExist":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedFilesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedImagesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":0.001,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveReturnsZeroWhenInsertFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":0.001,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveSetsStatusToMinusOne":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveReturnsFalseWhenUpdateFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderUpdatesImageOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderSkipsEmptyValues":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasBrowseListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasGalleryOrderSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testBrowseListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testGalleryOrderSaveMethodReturnType":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminUsesBoundParamsForTitleFilter":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveWithLegacyFormat":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveUpdatesExistingTranslationsByBannerAndLang":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testListForAdminIncludesThumbnailSrc":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testRestoreSetsStatusToZero":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeletePermanentlyRemovesArticleAndRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListArchivedForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsUnitWithTranslations":0.001,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsNullWhenUnitNotFound":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testSaveInsertsNewUnitAndTranslationsForStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testDeleteRemovesUnitAndTranslations":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdReturnsTextFromDatabase":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdSupportsStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testAllUnitsReturnsArrayIndexedById":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguageDetailsReturnsArrayOrNull":0.002,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguagesListReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveLanguageRejectsInvalidLanguageId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveTranslationInsertsNewTranslationAndReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDeleteTranslationReturnsBoolean":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdReturnsLanguageWithStartFlag":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdFallsBackToFirstLanguageOrPl":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsLayoutWithRelations":0.001,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testDeleteReturnsFalseWhenOnlyOneLayoutExists":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsDefaultLayoutWhenRecordDoesNotExist":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testSaveInsertsNewLayoutAndReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testListAllReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsNullForInvalidId":0.003,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSaveSettingsUpdatesHeaderAndFooter":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testDeleteTemplateReturnsFalseForAdminTemplate":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateByNameReturnsText":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsDefaultContainerForInvalidId":0.002,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsContainerWithTranslations":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDetailsForLanguageReturnsNullForInvalidData":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsUserWhenExists":0.002,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsErrorWhenLoginIsTaken":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsOkWhenAvailable":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveCreatesUserWithNormalizedSwitches":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithoutPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsTrue":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsFalseOnFailure":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsUserByLogin":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsSuccessForValidCredentials":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsZeroForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsNegativeOneForBlockedUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseAfterMaxAttempts":0.079,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForExpiredCode":0.077,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsTrueForValidCode":0.153,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseWhen2FADisabled":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseForInvalidEmail":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testUpdateByIdCallsDbUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorAcceptsRepository":0.003,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorRequiresDictionariesRepository":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorRequiresLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorRequiresLayoutsRepository":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorRequiresRepositoryAndRenderer":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorRequiresRepositoryAndLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasViewListMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserEditMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasTwofaMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasLoginFormMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorRequiresUserRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserReturnsDefaultsForNull":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserCastsTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserHandlesPartialData":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderUpdatesFilesOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderSkipsEmptyValues":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPagesSummaryForArticlesBuildsLabels":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testUpdateImageAltDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testMarkFileToDeleteDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindReturnsDefaultCouponForInvalidId":0.001,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindNormalizesCouponData":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveInsertsCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveUpdatesCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingsReturnsArray":0.002,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingUpdatesExistingValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingInsertsNewValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testInvalidProviderThrowsException":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testLinkProductUpdatesDatabase":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testUnlinkProductClearsFields":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloGetAccessTokenReturnsNullWithoutSettings":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListThrowsForInvalidType":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testAllPublicMethodsExist":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSettingsTableMapping":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShopproProviderWorks":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenusListReturnsArray":0.002,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenuDeleteReturnsFalseWhenMenuHasPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testGenerateSeoLinkAddsSuffixWhenBaseSlugExists":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testPageUrlPreviewBuildsLanguagePrefixedUrlForNonDefaultLanguage":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testFindReturnsDefaultPromotionForInvalidId":0.002,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testSaveInsertsPromotionAndReturnsId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageAltChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileNameChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageAltChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileNameChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorAcceptsDependencies":0.003,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloSettingsMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloDataFetchMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloProductMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllShopproMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testApiloSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testShopproSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testVoidReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveSellasistMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveBaselinkerMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorRequiresPagesLanguagesAndLayoutsRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorRequiresPromotionRepository":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullForNegativeId":0.001,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsStatusWithIdZero":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindNormalizesNullApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveUpdatesColorAndApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithIdZeroWorks":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithEmptyApiloStatusIdSetsNull":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveRejectsNegativeId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsValue":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsNullWhenNotSet":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdForApilo":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdReturnsNullForUnknownIntegration":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testAllStatusesReturnsOrderedList":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorRequiresShopStatusRepository":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsFalseForFarFutureDate":0.001,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsTrueForNearExpiryDate":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListResultReturnsDetailedErrorWhenConfigMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloIntegrationStatusReturnsMissingConfigMessage":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListRejectsErrorPayload":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListAcceptsIdNameList":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullForInvalidId":0.001,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveUpdatesRowAndReturnsId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSavePreservesNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllForAdminReturnsRowsIncludingInactive":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindKeepsNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveNormalizesStatusValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdHandlesNullAndInt":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsStringForNonNumericValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindNormalizesDataAndIncludesPaymentMethods":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindHandlesNullMaxWpAndApiloId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNewId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveUpdateReturnsExistingId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNullOnFailure":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveResetsDefaultWhenSettingNew":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveSwitchValuesNormalization":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testListForAdminWhitelistsSortColumn":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsIntOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetTransportCostReturnsFloatOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllForAdminReturnsAllTransports":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorRequiresPaymentMethodRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFindAttributeReturnsDefaultAttributeForInvalidId":0.003,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForAdminWhitelistsSortDirectionAndPerPage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesRemovesObsoleteRowsAndSetsDefault":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesDeletesTranslationWhenNameIsEmpty":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testGetAttributeValueByIdUsesDefaultLanguageWhenNotProvided":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSortTypesReturnsExpectedKeys":0.002,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsReturnsDefaultForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsLoadsTranslations":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderReturnsFalseForNonArray":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderUpdatesOrderAndParent":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderReturnsFalseForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderUpdatesCategoryProductOrder":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsFalseWhenHasChildren":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsTrueWhenDeleted":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsFirstAvailableTitle":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testListForAdminWhitelistsSortAndPagination":0.001,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientReturnsEmptyOnMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientNormalizesRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsZeroForMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsAggregatedValues":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testConstructorAcceptsDb":0.001,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testHasAllPublicMethods":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testSalesGridReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testLastOrdersReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testMostViewedProductsReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testBestSalesProductsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsFallbackWhenEmpty":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsList":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsEmptyArrayWhenNone":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsDefaultsToPl":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsForDifferentLanguage":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionUpdatesStatus":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailReturnsFalseForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSignupReturnsFalseForExistingEmail":0.001,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConstructorAcceptsOptionalDependencies":0.003,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusesReturnsMappedArray":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testNextAndPrevOrderIdReturnNullForInvalidInput":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindReturnsDefaultProducerForInvalidId":0.001,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindNormalizesProducerData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveInsertsNewProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveUpdatesExistingProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllProducersReturnsFormattedList":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testProducerProductsReturnsPaginatedResults":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindReturnsDefaultSetForInvalidId":0.001,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindNormalizesSetData":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveInsertsNewSetAndSyncsProducts":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveUpdatesExistingSet":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testAllSetsReturnsFormattedList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditReturnsMap":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsEmptyArray":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsNullForInvalidProduct":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsCorrectPrices":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentZeroPercentNullsPromo":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsAssociativeArray":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsEmptyArrayWhenNoSettings":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsHandlesNullFromDb":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsCorrectParam":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueUsesParamNotHardcoded":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsEmptyStringWhenNotFound":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testConstructorAcceptsDb":0.002,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasUpdateMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testUpdateReturnsArray":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasRunPendingMigrationsMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testRunPendingMigrationsWithNoResults":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasPrivateHelperMethods":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorAcceptsRepositories":0.003,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsErrorsForMissingDefaultLanguageAndDefaultSelection":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsEmptyArrayForValidRows":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorAcceptsDependencies":0.003,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorRequiresCategoryAndLanguagesRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorRequiresClientRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsService":0.003,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderAdminService":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testActionMethodReturnTypes":0.001,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorAcceptsRepositories":0.003,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasMassEditActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasViewListMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasEditAndSaveMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasOperationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasCombinationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasImageAndFileMethods":0.001,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditReturnsString":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditSaveReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testGetProductsByCategoryReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasFormBuildingHelpers":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testSaveMethodReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorRequiresProductSetRepository":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateAllMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsSortedIds":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsNullForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsInt":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsZeroForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesPagination":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsBool":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsFalseForNonNoindex":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsReturnsArticlesArray":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsActiveBannersWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsNullWhenNoBanners":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsActiveBannerWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsNullWhenNoBanner":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsNullWhenNone":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutFallsBackToDefault":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutReturnsNullWhenNothingFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsPageWithLanguage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdReturnsStartPage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdFallsBackToFirstActive":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageSortReturnsValue":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsMenuWithPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsNullForInvalidMenu":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuPagesReturnsEmptyForNoPages":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsAttributeWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsValueWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpCalculatesTotal":0.001,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsSumsQuantities":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextSingular":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural2to4":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural5Plus":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextCastsToInt":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsSortType":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsTitle":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsCategoryWithLanguage":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyWhenCategoryNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoriesTreeReturnsEmptyWhenNoCategories":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsZeroForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsCount":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsProductIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsClampsPage":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsRowOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsStringOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesHandlesFalseFromDb":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsRow":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveReturnsFalseForInvalidClientId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveInsertsNewAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveUpdatesExistingAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentReturnsFalseForInvalidIds":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentResetsAndSets":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorWhenClientNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsInactiveForUnconfirmedAccount":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnWrongPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsOkOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullWhenEmailTaken":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsIdAndHashOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationActivatesAndReturnsEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsEmailAndPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullOnEmptyEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoverySetsRecoveryFlagAndReturnsHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientOrdersReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsObjectWhenFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullForEmptyName":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsTrueForActiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForUsedCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForInactiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForNullCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableWorksWithArray":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedSkipsInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountSkipsInvalidId":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsIdWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullForEmptyHash":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsHashWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByIdReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByHashReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberFormatsCorrectly":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberStartsAt001":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsFullData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsProducerWithLanguage":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderRepository":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorRequiresProducerRepository":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsOneForActivePayment":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNormalizedData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsSku":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackReturnsEan":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsOneForActive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInactive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsCategories":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontUsesParentId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testTopProductIdsReturnsActiveProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsProductIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsEmptyWhenNone":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeWholeBasketAppliesDiscountToAll":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesOrAppliesDiscountToMatchingCategories":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionAppliesWhenConditionMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionNoDiscountWhenConditionNotMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesAndAppliesWhenBothConditionsMet":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportCostCachedReturnsCost":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsTransport":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsNullForInvalid":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsTransports":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnNullBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsEmptyArrayOnNull":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsBasketArrayAsIs":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsOnlyOrderRepository":0.006,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsAllDependencies":0.012,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsEmptyForEmptyQuery":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsEmptyWithoutProductRepo":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsFormattedResults":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsReturnsFalseForInvalidOrderId":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsDeletesRemovedProducts":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsUpdatesQuantityAndAdjustsStock":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsAddsNewProductAndDecreasesStock":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testGetFreeDeliveryThresholdReturnsZeroWithoutSettingsRepo":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testGetFreeDeliveryThresholdReturnsValue":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGetOrderProductReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGetOrderProductReturnsArray":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testAddOrderProductReturnsNullForInvalidOrderId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testAddOrderProductInsertsAndReturnsId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductUpdatesFields":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductReturnsFalseForEmptyData":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testDeleteOrderProductReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testDeleteOrderProductCallsDelete":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateTransportCostDoesNothingForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateTransportCostUpdatesOrder":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenNoApiKey":0.001,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenWrongApiKey":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenStoredKeyEmpty":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingEndpoint":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingAction":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns404ForUnknownEndpoint":0,"Tests\\Unit\\api\\ApiRouterTest::testSendSuccessOutputsCorrectJson":0,"Tests\\Unit\\api\\ApiRouterTest::testSendErrorOutputsCorrectJson":0,"Tests\\Unit\\api\\ApiRouterTest::testRequireMethodReturnsTrueForMatchingMethod":0,"Tests\\Unit\\api\\ApiRouterTest::testRequireMethodReturnsFalseAndSendsErrorForMismatch":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesReturnsFormattedList":0.001,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsReturnsFormattedList":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsReturnsFormattedList":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testListReturnsOrders":0.001,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testListRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testListPassesFiltersToRepository":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testGetReturnsOrder":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testGetReturns404WhenOrderNotFound":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testGetReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testChangeStatusUpdatesOrder":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testChangeStatusReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testChangeStatusRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetPaidReturns404WhenOrderNotFound":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetPaidReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetPaidCallsServiceWhenOrderExists":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetUnpaidReturns404WhenOrderNotFound":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetUnpaidCallsServiceWhenOrderExists":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListReturnsProducts":0.002,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListPassesFiltersToRepository":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListDefaultPagination":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListClampsPerPageTo100":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetReturnsProduct":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetReturns404WhenProductNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateReturns404WhenProductNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataConvertsStatusToCheckbox":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsLanguages":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsNumericFields":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsCategories":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataPartialUpdatePreservesExisting":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsForeignKeys":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testVerifyChecksumValidFormat":0.013,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testVerifyChecksumInvalidHash":0.011,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testVerifyChecksumInvalidFormat":0.001,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testCreateBackupWithEmptyManifest":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testDownloadManifestReturnsNullForInvalidUrl":0.281,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForApiReturnsActiveAttributesWithValues":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForApiReturnsEmptyWhenNoAttributes":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantsForApiReturnsVariants":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantsForApiReturnsEmptyWhenNoVariants":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantForApiReturnsVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantForApiReturnsNullForNonVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantForApiReturnsNullForNonexistent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiSuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullForArchivedParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullWhenParentIsVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullForEmptyAttributes":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullForDuplicateHash":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiSuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiReturnsFalseForNonVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiReturnsFalseForNonexistent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiFiltersUnallowedFields":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testDeleteVariantForApiSuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testDeleteVariantForApiReturnsFalseForNonVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testDeleteVariantForApiReturnsFalseForNonexistent":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesReturnsFormattedList":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturnsVariantsList":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturns404WhenProductNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturns400ForVariantProduct":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateVariantRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateVariantReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateVariantReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateVariantRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateVariantReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateVariantReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantReturns404WhenNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantSuccess":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListPassesAttributeFilters":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiCastsTypes":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSavePersistsMinMaxOrderAmount":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveConvertsEmptyMinMaxToNull":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesMinMaxOrderAmount":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesNullMinMaxOrderAmount":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontHidesTransportWhenAllPaymentsExceedMaxAmount":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontHidesTransportWhenAllPaymentsBelowMinAmount":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontHidesTransportWithNoPaymentMethods":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontKeepsBothTransportsWhenPaymentsAvailable":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontKeepsTransportIfAtLeastOnePaymentAvailable":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusDataReturnsBothNamesAndColors":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusDataFiltersInvalidHexColors":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusDataReturnsEmptyOnDbFailure":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorReturnsBlackForLightColor":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorReturnsWhiteForDarkColor":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorHandlesShortHex":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorDefaultsToWhiteForInvalidHex":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlStripsDisallowedTags":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlStripsAttributesFromAllowedTags":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlPreservesCleanTags":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlHandlesPlainText":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetLogsReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetLogsReturnsEmptyWhenNoResults":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetLogsHandlesNullFromSelect":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testDeleteLogCallsDelete":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testClearLogsDeletesAll":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasLogsMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testLogsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testLogsClearReturnsVoid":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueKeepsTaskWhenApiloOrderIdIsNull":0.023,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueRemovesTaskAfterMaxAttempts":0.014,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataPreservesZeroBasePriceForSaveProduct":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueReturns400WhenNoBody":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testRegisterHandlerAndProcessJob":0.003,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueReturnsEmptyStatsWhenNoJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueHandlerReturnsFalse":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueHandlerThrowsException":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueNoHandlerRegistered":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueHandlerReturnsArray":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueuePassesPayloadToHandler":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueMultipleJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsFromDueSchedules":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsSkipsDuplicates":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsWithPayload":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsReturnsZeroWhenNoSchedules":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testRunExecutesFullPipeline":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testRunReturnsScheduledCount":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueInsertsJobAndReturnsId":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueWithPayloadEncodesJson":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueWithoutPayloadDoesNotSetPayloadKey":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueWithScheduledAt":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueReturnsNullOnFailure":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextReturnsEmptyArrayWhenNoJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextUpdatesStatusToProcessing":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextDecodesPayloadJson":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkCompletedUpdatesStatus":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkCompletedWithResult":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkFailedWithRetriesLeft":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkFailedWhenMaxAttemptsReached":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkFailedTruncatesErrorTo500Chars":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testHasPendingJobReturnsTrueWhenExists":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testHasPendingJobReturnsFalseWhenNone":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testHasPendingJobWithPayloadMatch":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testCleanupDeletesOldCompletedJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testRecoverStuckResetsProcessingJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testGetDueSchedulesReturnsEnabledSchedules":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testTouchScheduleUpdatesTimestamps":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testAllTypesReturnsAllJobTypes":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testAllStatusesReturnsAllStatuses":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testPriorityConstants":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testCalculateBackoffExponential":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testCalculateBackoffCapsAtMax":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testJobTypeConstantsMatchStrings":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testStatusConstantsMatchStrings":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsCronJobRepo":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasBulkDeletePermanentMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testBulkDeletePermanentMethodReturnType":0}} \ No newline at end of file +{"version":1,"defects":{"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":4,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":3,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenNoApiKey":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenWrongApiKey":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenStoredKeyEmpty":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingEndpoint":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingAction":4,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns404ForUnknownEndpoint":4,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueKeepsTaskWhenApiloOrderIdIsNull":3,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueRemovesTaskAfterMaxAttempts":3,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesReturnsFormattedList":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesRejectsPostMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeRejectsGetMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeReturns400WhenNoBody":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueRejectsGetMethod":4,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueReturns400WhenNoBody":4,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextUpdatesStatusToProcessing":3,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorAcceptsRepository":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasMainViewMethod":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testMainViewReturnsString":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateMethod":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateAllMethod":4,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorRequiresRepository":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeletePermanentlyRemovesArticleAndRelations":3,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsTrueWhenDeleted":3},"times":{"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsCorrectValue":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsNullWhenProductNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindReturnsProductData":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateQuantitySuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsPromoPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularWhenPromoIsHigher":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsProductName":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsInteger":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveReturnsBool":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveReturnsBool":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasUnarchiveMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testUnarchiveMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorRequiresProductRepository":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsBannerWithTranslations":0.001,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testDeleteReturnsTrue":0.002,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveInsertsNewBanner":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithRedis":0.001,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheRedisUnavailable":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithoutRedis":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheReturnStructure":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testCanBeInstantiated":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasSaveSettingsMethod":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasGetSettingsMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheAjaxMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasViewMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testIsNotAbstract":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testCanCreateController":0.004,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testEditMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsArticleWithRelations":0.005,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsNullWhenArticleDoesNotExist":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedFilesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedImagesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":0.001,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveReturnsZeroWhenInsertFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveSetsStatusToMinusOne":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveReturnsFalseWhenUpdateFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderUpdatesImageOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderSkipsEmptyValues":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasBrowseListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasGalleryOrderSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testBrowseListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testGalleryOrderSaveMethodReturnType":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminUsesBoundParamsForTitleFilter":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveWithLegacyFormat":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveUpdatesExistingTranslationsByBannerAndLang":0.001,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testListForAdminIncludesThumbnailSrc":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testRestoreSetsStatusToZero":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeletePermanentlyRemovesArticleAndRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListArchivedForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsUnitWithTranslations":0.001,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsNullWhenUnitNotFound":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testSaveInsertsNewUnitAndTranslationsForStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testDeleteRemovesUnitAndTranslations":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdReturnsTextFromDatabase":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdSupportsStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testAllUnitsReturnsArrayIndexedById":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguageDetailsReturnsArrayOrNull":0.002,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguagesListReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveLanguageRejectsInvalidLanguageId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveTranslationInsertsNewTranslationAndReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDeleteTranslationReturnsBoolean":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdReturnsLanguageWithStartFlag":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdFallsBackToFirstLanguageOrPl":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsLayoutWithRelations":0.002,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testDeleteReturnsFalseWhenOnlyOneLayoutExists":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsDefaultLayoutWhenRecordDoesNotExist":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testSaveInsertsNewLayoutAndReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testListAllReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsNullForInvalidId":0.002,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSaveSettingsUpdatesHeaderAndFooter":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testDeleteTemplateReturnsFalseForAdminTemplate":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateByNameReturnsText":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsDefaultContainerForInvalidId":0.001,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsContainerWithTranslations":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDetailsForLanguageReturnsNullForInvalidData":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsUserWhenExists":0.001,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsErrorWhenLoginIsTaken":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsOkWhenAvailable":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveCreatesUserWithNormalizedSwitches":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithoutPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsTrue":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsFalseOnFailure":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsUserByLogin":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsSuccessForValidCredentials":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsZeroForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsNegativeOneForBlockedUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseAfterMaxAttempts":0.078,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForExpiredCode":0.077,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsTrueForValidCode":0.152,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseWhen2FADisabled":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseForInvalidEmail":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testUpdateByIdCallsDbUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorRequiresDictionariesRepository":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorRequiresLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorRequiresLayoutsRepository":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorRequiresRepositoryAndRenderer":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorAcceptsDependencies":0.001,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorRequiresRepositoryAndLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasViewListMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserEditMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasTwofaMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasLoginFormMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorRequiresUserRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserReturnsDefaultsForNull":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserCastsTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserHandlesPartialData":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderUpdatesFilesOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderSkipsEmptyValues":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPagesSummaryForArticlesBuildsLabels":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testUpdateImageAltDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testMarkFileToDeleteDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindReturnsDefaultCouponForInvalidId":0.001,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindNormalizesCouponData":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveInsertsCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveUpdatesCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingsReturnsArray":0.003,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingUpdatesExistingValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingInsertsNewValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testInvalidProviderThrowsException":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testLinkProductUpdatesDatabase":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testUnlinkProductClearsFields":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloGetAccessTokenReturnsNullWithoutSettings":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListThrowsForInvalidType":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testAllPublicMethodsExist":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSettingsTableMapping":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShopproProviderWorks":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenusListReturnsArray":0.002,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenuDeleteReturnsFalseWhenMenuHasPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testGenerateSeoLinkAddsSuffixWhenBaseSlugExists":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testPageUrlPreviewBuildsLanguagePrefixedUrlForNonDefaultLanguage":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testFindReturnsDefaultPromotionForInvalidId":0.002,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testSaveInsertsPromotionAndReturnsId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageAltChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileNameChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageAltChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileNameChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloSettingsMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloDataFetchMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloProductMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllShopproMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testApiloSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testShopproSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testVoidReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveSellasistMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveBaselinkerMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorRequiresPagesLanguagesAndLayoutsRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorRequiresPromotionRepository":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullForNegativeId":0.001,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsStatusWithIdZero":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindNormalizesNullApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveUpdatesColorAndApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithIdZeroWorks":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithEmptyApiloStatusIdSetsNull":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveRejectsNegativeId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsValue":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsNullWhenNotSet":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdForApilo":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdReturnsNullForUnknownIntegration":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testAllStatusesReturnsOrderedList":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorRequiresShopStatusRepository":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsFalseForFarFutureDate":0.001,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsTrueForNearExpiryDate":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListResultReturnsDetailedErrorWhenConfigMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloIntegrationStatusReturnsMissingConfigMessage":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListRejectsErrorPayload":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListAcceptsIdNameList":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullForInvalidId":0.001,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveUpdatesRowAndReturnsId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSavePreservesNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllForAdminReturnsRowsIncludingInactive":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindKeepsNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveNormalizesStatusValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdHandlesNullAndInt":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsStringForNonNumericValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindNormalizesDataAndIncludesPaymentMethods":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindHandlesNullMaxWpAndApiloId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNewId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveUpdateReturnsExistingId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNullOnFailure":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveResetsDefaultWhenSettingNew":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveSwitchValuesNormalization":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testListForAdminWhitelistsSortColumn":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsIntOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetTransportCostReturnsFloatOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllForAdminReturnsAllTransports":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorRequiresPaymentMethodRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFindAttributeReturnsDefaultAttributeForInvalidId":0.002,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForAdminWhitelistsSortDirectionAndPerPage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesRemovesObsoleteRowsAndSetsDefault":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesDeletesTranslationWhenNameIsEmpty":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testGetAttributeValueByIdUsesDefaultLanguageWhenNotProvided":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSortTypesReturnsExpectedKeys":0.002,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsReturnsDefaultForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsLoadsTranslations":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderReturnsFalseForNonArray":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderUpdatesOrderAndParent":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderReturnsFalseForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderUpdatesCategoryProductOrder":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsFalseWhenHasChildren":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsTrueWhenDeleted":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsFirstAvailableTitle":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testListForAdminWhitelistsSortAndPagination":0.001,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientReturnsEmptyOnMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientNormalizesRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsZeroForMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsAggregatedValues":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testConstructorAcceptsDb":0.001,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testHasAllPublicMethods":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testSalesGridReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testLastOrdersReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testMostViewedProductsReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testBestSalesProductsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsFallbackWhenEmpty":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsList":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsEmptyArrayWhenNone":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsDefaultsToPl":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsForDifferentLanguage":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionUpdatesStatus":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailReturnsFalseForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSignupReturnsFalseForExistingEmail":0.001,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConstructorAcceptsOptionalDependencies":0.003,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusesReturnsMappedArray":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testNextAndPrevOrderIdReturnNullForInvalidInput":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindReturnsDefaultProducerForInvalidId":0.001,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindNormalizesProducerData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveInsertsNewProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveUpdatesExistingProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllProducersReturnsFormattedList":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testProducerProductsReturnsPaginatedResults":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindReturnsDefaultSetForInvalidId":0.001,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindNormalizesSetData":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveInsertsNewSetAndSyncsProducts":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveUpdatesExistingSet":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testAllSetsReturnsFormattedList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditReturnsMap":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsEmptyArray":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsNullForInvalidProduct":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsCorrectPrices":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentZeroPercentNullsPromo":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsAssociativeArray":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsEmptyArrayWhenNoSettings":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsHandlesNullFromDb":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsCorrectParam":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueUsesParamNotHardcoded":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsEmptyStringWhenNotFound":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testConstructorAcceptsDb":0.001,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasUpdateMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testUpdateReturnsArray":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasRunPendingMigrationsMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testRunPendingMigrationsWithNoResults":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasPrivateHelperMethods":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsErrorsForMissingDefaultLanguageAndDefaultSelection":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsEmptyArrayForValidRows":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorRequiresCategoryAndLanguagesRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorRequiresClientRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsService":0.002,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderAdminService":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepositories":0.003,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasMassEditActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasViewListMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasEditAndSaveMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasOperationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasCombinationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasImageAndFileMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditReturnsString":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditSaveReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testGetProductsByCategoryReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasFormBuildingHelpers":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testSaveMethodReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorRequiresProductSetRepository":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateAllMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsSortedIds":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsNullForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsInt":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsZeroForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesPagination":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsBool":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsFalseForNonNoindex":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsReturnsArticlesArray":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsActiveBannersWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsNullWhenNoBanners":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsActiveBannerWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsNullWhenNoBanner":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsNullWhenNone":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutFallsBackToDefault":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutReturnsNullWhenNothingFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsPageWithLanguage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdReturnsStartPage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdFallsBackToFirstActive":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageSortReturnsValue":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsMenuWithPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsNullForInvalidMenu":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuPagesReturnsEmptyForNoPages":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsAttributeWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsValueWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpCalculatesTotal":0.001,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsSumsQuantities":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextSingular":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural2to4":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural5Plus":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextCastsToInt":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsSortType":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsTitle":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsCategoryWithLanguage":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyWhenCategoryNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoriesTreeReturnsEmptyWhenNoCategories":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsZeroForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsCount":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsProductIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsClampsPage":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsRowOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsStringOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesHandlesFalseFromDb":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsRow":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveReturnsFalseForInvalidClientId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveInsertsNewAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveUpdatesExistingAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentReturnsFalseForInvalidIds":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentResetsAndSets":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorWhenClientNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsInactiveForUnconfirmedAccount":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnWrongPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsOkOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullWhenEmailTaken":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsIdAndHashOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationActivatesAndReturnsEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsEmailAndPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullOnEmptyEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoverySetsRecoveryFlagAndReturnsHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientOrdersReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsObjectWhenFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullForEmptyName":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsTrueForActiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForUsedCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForInactiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForNullCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableWorksWithArray":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedSkipsInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountSkipsInvalidId":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsIdWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullForEmptyHash":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsHashWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByIdReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByHashReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberFormatsCorrectly":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberStartsAt001":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsFullData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsProducerWithLanguage":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderRepository":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorRequiresProducerRepository":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsOneForActivePayment":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNormalizedData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsSku":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackReturnsEan":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsOneForActive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInactive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsCategories":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontUsesParentId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testTopProductIdsReturnsActiveProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsProductIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsEmptyWhenNone":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeWholeBasketAppliesDiscountToAll":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesOrAppliesDiscountToMatchingCategories":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionAppliesWhenConditionMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionNoDiscountWhenConditionNotMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesAndAppliesWhenBothConditionsMet":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportCostCachedReturnsCost":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsTransport":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsNullForInvalid":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsTransports":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnNullBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsEmptyArrayOnNull":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsBasketArrayAsIs":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsOnlyOrderRepository":0.005,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsAllDependencies":0.013,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsEmptyForEmptyQuery":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsEmptyWithoutProductRepo":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsFormattedResults":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsReturnsFalseForInvalidOrderId":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsDeletesRemovedProducts":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsUpdatesQuantityAndAdjustsStock":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsAddsNewProductAndDecreasesStock":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testGetFreeDeliveryThresholdReturnsZeroWithoutSettingsRepo":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testGetFreeDeliveryThresholdReturnsValue":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGetOrderProductReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGetOrderProductReturnsArray":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testAddOrderProductReturnsNullForInvalidOrderId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testAddOrderProductInsertsAndReturnsId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductUpdatesFields":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductReturnsFalseForEmptyData":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testDeleteOrderProductReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testDeleteOrderProductCallsDelete":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateTransportCostDoesNothingForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateTransportCostUpdatesOrder":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenNoApiKey":0.001,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenWrongApiKey":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns401WhenStoredKeyEmpty":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingEndpoint":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns400WhenMissingAction":0,"Tests\\Unit\\api\\ApiRouterTest::testHandleReturns404ForUnknownEndpoint":0,"Tests\\Unit\\api\\ApiRouterTest::testSendSuccessOutputsCorrectJson":0,"Tests\\Unit\\api\\ApiRouterTest::testSendErrorOutputsCorrectJson":0,"Tests\\Unit\\api\\ApiRouterTest::testRequireMethodReturnsTrueForMatchingMethod":0,"Tests\\Unit\\api\\ApiRouterTest::testRequireMethodReturnsFalseAndSendsErrorForMismatch":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesReturnsFormattedList":0.001,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testStatusesRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsReturnsFormattedList":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testTransportsRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsReturnsFormattedList":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testPaymentMethodsRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testListReturnsOrders":0.001,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testListRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testListPassesFiltersToRepository":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testGetReturnsOrder":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testGetReturns404WhenOrderNotFound":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testGetReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testChangeStatusUpdatesOrder":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testChangeStatusReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testChangeStatusRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetPaidReturns404WhenOrderNotFound":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetPaidReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetPaidCallsServiceWhenOrderExists":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetUnpaidReturns404WhenOrderNotFound":0,"Tests\\Unit\\api\\Controllers\\OrdersApiControllerTest::testSetUnpaidCallsServiceWhenOrderExists":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListReturnsProducts":0.001,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListPassesFiltersToRepository":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListDefaultPagination":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListClampsPerPageTo100":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetReturnsProduct":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetReturns404WhenProductNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testGetRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateReturns404WhenProductNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataConvertsStatusToCheckbox":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsLanguages":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsNumericFields":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsCategories":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataPartialUpdatePreservesExisting":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataMapsForeignKeys":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testVerifyChecksumValidFormat":0.012,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testVerifyChecksumInvalidHash":0.009,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testVerifyChecksumInvalidFormat":0.001,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testCreateBackupWithEmptyManifest":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testDownloadManifestReturnsNullForInvalidUrl":0.041,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForApiReturnsActiveAttributesWithValues":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForApiReturnsEmptyWhenNoAttributes":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantsForApiReturnsVariants":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantsForApiReturnsEmptyWhenNoVariants":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantForApiReturnsVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantForApiReturnsNullForNonVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindVariantForApiReturnsNullForNonexistent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiSuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullForArchivedParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullWhenParentIsVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullForEmptyAttributes":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testCreateVariantForApiReturnsNullForDuplicateHash":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiSuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiReturnsFalseForNonVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiReturnsFalseForNonexistent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiFiltersUnallowedFields":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testDeleteVariantForApiSuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testDeleteVariantForApiReturnsFalseForNonVariant":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testDeleteVariantForApiReturnsFalseForNonexistent":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesReturnsFormattedList":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testAttributesRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturnsVariantsList":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturns404WhenProductNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsReturns400ForVariantProduct":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testVariantsRejectsPostMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateVariantRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateVariantReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testCreateVariantReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateVariantRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateVariantReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testUpdateVariantReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantReturns400WhenMissingId":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantReturns404WhenNotFound":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testDeleteVariantSuccess":0,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testListPassesAttributeFilters":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateVariantForApiCastsTypes":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSavePersistsMinMaxOrderAmount":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveConvertsEmptyMinMaxToNull":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesMinMaxOrderAmount":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesNullMinMaxOrderAmount":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontHidesTransportWhenAllPaymentsExceedMaxAmount":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontHidesTransportWhenAllPaymentsBelowMinAmount":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontHidesTransportWithNoPaymentMethods":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontKeepsBothTransportsWhenPaymentsAvailable":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportMethodsFrontKeepsTransportIfAtLeastOnePaymentAvailable":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusDataReturnsBothNamesAndColors":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusDataFiltersInvalidHexColors":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusDataReturnsEmptyOnDbFailure":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorReturnsBlackForLightColor":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorReturnsWhiteForDarkColor":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorHandlesShortHex":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testContrastTextColorDefaultsToWhiteForInvalidHex":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlStripsDisallowedTags":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlStripsAttributesFromAllowedTags":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlPreservesCleanTags":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testSanitizeInlineHtmlHandlesPlainText":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetLogsReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetLogsReturnsEmptyWhenNoResults":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetLogsHandlesNullFromSelect":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testDeleteLogCallsDelete":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testClearLogsDeletesAll":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasLogsMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testLogsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testLogsClearReturnsVoid":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueKeepsTaskWhenApiloOrderIdIsNull":0.023,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testProcessApiloSyncQueueRemovesTaskAfterMaxAttempts":0.014,"Tests\\Unit\\api\\Controllers\\ProductsApiControllerTest::testMapApiToFormDataPreservesZeroBasePriceForSaveProduct":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeReturns400WhenNoBody":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueRejectsGetMethod":0,"Tests\\Unit\\api\\Controllers\\DictionariesApiControllerTest::testEnsureAttributeValueReturns400WhenNoBody":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testRegisterHandlerAndProcessJob":0.002,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueReturnsEmptyStatsWhenNoJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueHandlerReturnsFalse":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueHandlerThrowsException":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueNoHandlerRegistered":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueHandlerReturnsArray":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueuePassesPayloadToHandler":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testProcessQueueMultipleJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsFromDueSchedules":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsSkipsDuplicates":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsWithPayload":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testCreateScheduledJobsReturnsZeroWhenNoSchedules":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testRunExecutesFullPipeline":0,"Tests\\Unit\\Domain\\CronJob\\CronJobProcessorTest::testRunReturnsScheduledCount":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueInsertsJobAndReturnsId":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueWithPayloadEncodesJson":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueWithoutPayloadDoesNotSetPayloadKey":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueWithScheduledAt":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testEnqueueReturnsNullOnFailure":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextReturnsEmptyArrayWhenNoJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextUpdatesStatusToProcessing":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testFetchNextDecodesPayloadJson":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkCompletedUpdatesStatus":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkCompletedWithResult":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkFailedWithRetriesLeft":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkFailedWhenMaxAttemptsReached":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testMarkFailedTruncatesErrorTo500Chars":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testHasPendingJobReturnsTrueWhenExists":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testHasPendingJobReturnsFalseWhenNone":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testHasPendingJobWithPayloadMatch":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testCleanupDeletesOldCompletedJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testRecoverStuckResetsProcessingJobs":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testGetDueSchedulesReturnsEnabledSchedules":0,"Tests\\Unit\\Domain\\CronJob\\CronJobRepositoryTest::testTouchScheduleUpdatesTimestamps":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testAllTypesReturnsAllJobTypes":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testAllStatusesReturnsAllStatuses":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testPriorityConstants":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testCalculateBackoffExponential":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testCalculateBackoffCapsAtMax":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testJobTypeConstantsMatchStrings":0,"Tests\\Unit\\Domain\\CronJob\\CronJobTypeTest::testStatusConstantsMatchStrings":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsCronJobRepo":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasBulkDeletePermanentMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testBulkDeletePermanentMethodReturnType":0}} \ No newline at end of file diff --git a/.serena/project.yml b/.serena/project.yml index 5fc4073..a29cfe0 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -123,3 +123,7 @@ symbol_info_budget: # Note: the backend is fixed at startup. If a project with a different backend # is activated post-init, an error will be returned. language_backend: + +# list of regex patterns which, when matched, mark a memory entry as read‑only. +# Extends the list from the global configuration, merging the two lists. +read_only_memory_patterns: [] diff --git a/AGENTS.md b/AGENTS.md index addcb36..aa464f7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,30 +1,246 @@ -# Workflow +# CLAUDE.md -## KONIEC PRACY +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. -Gdy użytkownik napisze `KONIEC PRACY`, wykonaj kolejno: +## Project Overview -1. Przeprowadzenie testów. -2. Aktualizacja dokumentacji technicznej, jeśli zmiany tego wymagają: - - `docs/DATABASE_STRUCTURE.md` - - `docs/PROJECT_STRUCTURE.md` - - `docs/FORM_EDIT_SYSTEM.md` - - `docs/CHANGELOG.md` - - `docs/TESTING.md` -3. Migracje SQL (jeśli były zmiany w bazie danych): - - Plik: `migrations/{version}.sql` (np. `migrations/0.304.sql`) - - **NIE** w `updates/` — build script sam wczyta z `migrations/` - - Sprawdź czy plik istnieje i jest poprawnie nazwany przed commitem -4. Commit. -5. Push. +shopPRO is a PHP e-commerce platform with an admin panel and customer-facing storefront. It uses Medoo ORM (`$mdb`), Redis caching, and a Domain-Driven Design architecture with Dependency Injection (migration from legacy architecture complete). -## PRZED ROZPOCZĘCIEM PRACY +## Zasady pisania kodu +- Kod ma być czytelny „dla obcego”: jasne nazwy, mało magii +- Brak „skrótów na szybko” typu logika w widokach, copy-paste, losowe helpery bez spójności +- Każda funkcja/klasa ma mieć jedną odpowiedzialność, zwykle do 30–50 linii (jeśli dłuższe – dzielić) +- max 3 poziomy zagnieżdżeń (if/foreach), reszta do osobnych metod +- Nazewnictwo: + - klasy: PascalCase + - metody/zmienne: camelCase + - stałe: UPPER_SNAKE_CASE +- Zero „skrótologii” w nazwach (np. $d, $tmp, $x1) poza pętlami 2–3 linijki +- medoo + prepared statements bez wyjątków (żadnego sklejania SQL stringiem) +- XSS: escape w widokach (np. helper e()) +- CSRF dla formularzy, sensowna obsługa sesji +- Kod ma mieć komentarze tylko tam, gdzie wyjaśniają „dlaczego”, nie „co” -Przed rozpoczęciem implementacji sprawdź aktualną zawartość: +## PHP Version Constraint -- `docs/DATABASE_STRUCTURE.md` -- `docs/PROJECT_STRUCTURE.md` -- `docs/CHANGELOG.md` -- `docs/TESTING.md` +**Production runs PHP < 8.0.** Do NOT use: +- `match` expressions (use ternary operators or if/else) +- Named arguments +- Union types (`int|string`) +- `str_contains()`, `str_starts_with()`, `str_ends_with()` +- Other PHP 8.0+ syntax -To ma pomóc zachować spójność zmian i dokumentacji. +`composer.json` requires `>=7.4`. + +## Commands + +### Running Tests +```bash +# Full suite (recommended — PowerShell, auto-finds php) +./test.ps1 + +# Specific file +./test.ps1 tests/Unit/Domain/Product/ProductRepositoryTest.php + +# Specific test method +./test.ps1 --filter testGetQuantityReturnsCorrectValue + +# Alternative +composer test +``` + +PHPUnit 9.6 via `phpunit.phar`. Bootstrap: `tests/bootstrap.php`. Config: `phpunit.xml`. + +Current suite: **805 tests, 2253 assertions**. + +### Creating Updates +See `docs/UPDATE_INSTRUCTIONS.md` for the full procedure. Updates are ZIP packages in `updates/0.XX/`. Never include `*.md` files, `updates/changelog.php`, or root `.htaccess` in update ZIPs. + +## Architecture + +### Directory Structure +``` +shopPRO/ +├── autoload/ # Autoloaded classes (core codebase) +│ ├── Domain/ # Business logic repositories (\Domain\) +│ ├── Shared/ # Shared utilities (\Shared\) +│ │ ├── Cache/ # CacheHandler, RedisConnection +│ │ ├── Email/ # Email (PHPMailer wrapper) +│ │ ├── Helpers/ # Helpers (formerly class.S.php) +│ │ ├── Html/ # Html utility +│ │ ├── Image/ # ImageManipulator +│ │ └── Tpl/ # Template engine +│ ├── api/ # REST API layer (\api\) +│ │ ├── ApiRouter.php # API router (\api\ApiRouter) +│ │ └── Controllers/ # API controllers (\api\Controllers\) +│ ├── admin/ # Admin panel layer +│ │ ├── App.php # Admin router (\admin\App) +│ │ ├── Controllers/ # DI controllers (\admin\Controllers\) — 28 controllers +│ │ ├── Support/ # TableListRequestFactory, Forms/FormRequestHandler, Forms/FormFieldRenderer +│ │ ├── Validation/ # FormValidator +│ │ └── ViewModels/ # Forms/ (FormEditViewModel, FormField, FormTab, FormAction, FormFieldType), Common/ (PaginatedTableViewModel) +│ └── front/ # Frontend layer +│ ├── App.php # Frontend router (\front\App) +│ ├── LayoutEngine.php # Layout engine (\front\LayoutEngine) +│ ├── Controllers/ # DI controllers (\front\Controllers\) — 8 controllers +│ └── Views/ # Static views (\front\Views\) — 11 view classes +├── admin/ # Admin panel +│ ├── templates/ # Admin view templates +│ └── layout/ # Admin CSS/JS/icons +├── templates/ # Frontend view templates +├── libraries/ # Third-party libraries (Medoo, RedBeanPHP, PHPMailer) +├── tests/ # PHPUnit tests +│ ├── bootstrap.php +│ ├── stubs/ # Test stubs (CacheHandler, Helpers, ShopProduct) +│ └── Unit/ +│ ├── Domain/ # Repository tests +│ ├── admin/Controllers/ # Controller tests +│ └── api/ # API tests +├── updates/ # Update packages for clients +├── docs/ # Technical documentation +├── config.php # Database/Redis config (not in repo) +├── index.php # Frontend entry point +├── ajax.php # Frontend AJAX handler +├── admin/index.php # Admin entry point +├── admin/ajax.php # Admin AJAX handler +├── cron.php # CRON jobs (Apilo sync) +└── api.php # REST API (ordersPRO + Ekomi) +``` + +### Autoloader + +Custom autoloader in each entry point (not Composer autoload at runtime). Tries two filename conventions: +1. `autoload/{namespace}/class.{ClassName}.php` (legacy) +2. `autoload/{namespace}/{ClassName}.php` (PSR-4 style, fallback) + +### Namespace Conventions (case-sensitive on Linux!) +- `\Domain\` → `autoload/Domain/` (uppercase D) +- `\admin\Controllers\` → `autoload/admin/Controllers/` (lowercase a) +- `\Shared\` → `autoload/Shared/` +- `\api\` → `autoload/api/` +- Do NOT use `\Admin\` (uppercase A) — the server directory is `admin/` (lowercase) +- `\shop\` namespace is **deleted** — all 12 legacy classes migrated to `\Domain\`, `autoload/shop/` directory removed + +### Domain-Driven Architecture (migration complete) + +All legacy directories (`admin/controls/`, `admin/factory/`, `admin/view/`, `front/controls/`, `front/view/`, `front/factory/`, `shop/`) have been deleted. All modules now use this pattern: + +**Domain Layer** (`autoload/Domain/{Module}/`): +- `{Module}Repository.php` — data access, business logic, Redis caching +- Constructor DI with `$db` (Medoo instance) +- Methods serve both admin and frontend (shared Domain, no separate services) + +**Domain Modules**: Article, Attribute, Banner, Basket, Cache, Category, Client, Coupon, CronJob, Dashboard, Dictionaries, Integrations, Languages, Layouts, Newsletter, Order, Pages, PaymentMethod, Producer, Product, ProductSet, Promotion, Scontainers, Settings, ShopStatus, Transport, Update, User + +**Admin Controllers** (`autoload/admin/Controllers/`): +- DI via constructor (repositories injected) +- Wired in `admin\App::getControllerFactories()` + +**Frontend Controllers** (`autoload/front/Controllers/`): +- DI via constructor +- Wired in `front\App::getControllerFactories()` + +**Frontend Views** (`autoload/front/Views/`): +- Static classes, no state, no DI — pure rendering + +**API Controllers** (`autoload/api/Controllers/`): +- DI via constructor, stateless (no session) +- Wired in `api\ApiRouter::getControllerFactories()` +- Auth: `X-Api-Key` header vs `pp_settings.api_key` + +### Key Classes +| Class | Purpose | +|-------|---------| +| `\admin\App` | Admin router — maps URL segments to controllers | +| `\front\App` | Frontend router — `route()`, `checkUrlParams()` | +| `\front\LayoutEngine` | Frontend layout engine — `show()`, tag replacement | +| `\Shared\Helpers\Helpers` | Utility methods (SEO, email, cache clearing) | +| `\Shared\Tpl\Tpl` | Template engine — `render()`, `set()` | +| `\Shared\Cache\CacheHandler` | Redis cache — `get()`, `set()`, `delete()`, `deletePattern()` | +| `\api\ApiRouter` | REST API router — auth, routing, response helpers | + +### Database +- ORM: Medoo (`$mdb` global variable, injected via DI in new code) +- Table prefix: `pp_` +- Key tables: `pp_shop_products`, `pp_shop_orders`, `pp_shop_categories`, `pp_shop_clients` +- Full schema: `docs/DATABASE_STRUCTURE.md` + +### Form Edit System +Universal form system for admin edit views. Docs: `docs/FORM_EDIT_SYSTEM.md`. +- **ViewModels** (`admin\ViewModels\Forms\`): `FormEditViewModel`, `FormField`, `FormTab`, `FormAction`, `FormFieldType` +- **Validation**: `admin\Validation\FormValidator` +- **Rendering**: `admin\Support\Forms\FormFieldRenderer`, `admin\Support\Forms\FormRequestHandler` +- **Template**: `admin/templates/components/form-edit.php` +- **Table lists**: `admin\Support\TableListRequestFactory` + `admin\ViewModels\Common\PaginatedTableViewModel` + +### Caching +- Redis via `\Shared\Cache\CacheHandler` (singleton `RedisConnection`) +- Key pattern for products: `shop\product:{id}:{lang}:{permutation_hash}` +- Clear product cache: `\Shared\Helpers\Helpers::clear_product_cache($id)` +- Pattern delete: `CacheHandler::deletePattern("shop\\product:{$id}:*")` +- Default TTL: 86400 (24h) +- Data is serialized — requires `unserialize()` after `get()` +- Config: `config.php` (`$config['redis']`) + +## Code Patterns + +### New code should follow DI pattern +```php +// Repository with constructor DI +class ExampleRepository { + private $db; + public function __construct($db) { + $this->db = $db; + } + public function find(int $id): ?array { + return $this->db->get('pp_table', '*', ['id' => $id]); + } +} + +// Controller wiring (in admin\App or front\App) +$repo = new \Domain\Example\ExampleRepository($mdb); +$controller = new \admin\Controllers\ExampleController($repo); +``` + +### Medoo ORM pitfalls +- `$mdb->delete($table, $where)` takes **2 arguments**, NOT 3 — has caused bugs +- `$mdb->get()` returns `null` when no record, NOT `false` +- After `$mdb->insert()`, check `$mdb->id()` to confirm success + +### File naming +- New classes: `ClassName.php` (no `class.` prefix) +- Legacy classes: `class.ClassName.php` (leave until migrated) + +### Test conventions +- Extend `PHPUnit\Framework\TestCase` +- Mock Medoo: `$this->createMock(\medoo::class)` +- AAA pattern: Arrange, Act, Assert +- Tests mirror source structure: `tests/Unit/Domain/{Module}/{Class}Test.php` + +## Workflow (AGENTS.md) + +When user says **"KONIEC PRACY"**, execute in order: +1. Run tests +2. Update documentation if needed: `docs/DATABASE_STRUCTURE.md`, `docs/PROJECT_STRUCTURE.md`, `docs/FORM_EDIT_SYSTEM.md`, `docs/CHANGELOG.md`, `docs/TESTING.md` +3. SQL migrations (if DB changes): place in `migrations/{version}.sql` (e.g. `migrations/0.304.sql`). **NOT** in `updates/` — build script reads from `migrations/` automatically +4. Commit +5. Push +6. Build update package: `git tag v0.XXX && powershell.exe -ExecutionPolicy Bypass -File build-update.ps1 -FromTag v0.PREV -ToTag v0.XXX -ChangelogEntry "opis"` — skrypt automatycznie aktualizuje `versions.php` +7. Commit i push plików paczki (`updates/0.30/ver_0.XXX.zip`, `ver_0.XXX_manifest.json`, `updates/versions.php`, `updates/changelog-data.html`) + +Before starting implementation, review current state of docs (see AGENTS.md for full list). + +## Key Documentation +- `docs/MEMORY.md` — project memory: known issues, confirmed patterns, ORM pitfalls, caching conventions +- `docs/PROJECT_STRUCTURE.md` — current architecture, layers, cache, entry points, integrations +- `docs/DATABASE_STRUCTURE.md` — full database schema +- `docs/TESTING.md` — test suite guide and structure +- `docs/FORM_EDIT_SYSTEM.md` — form system architecture +- `docs/CHANGELOG.md` — version history +- `api-docs/api-reference.json` — REST API documentation (ordersPRO) +- `api-docs/index.html` — REST API documentation (ordersPRO) +- `docs/UPDATE_INSTRUCTIONS.md` — how to build client update packages + +## Za każdym razem jak próbujesz sprawdzić jakiś plik z logami spróbuj go najpierw pobrać z serwera FTP + +## Wszystkie pliki które tworzysz jako pomocnicze, np build_0330.ps1 czy build-update.ps1 twórz w folderze temp \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index a72ab9e..aa464f7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,21 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co shopPRO is a PHP e-commerce platform with an admin panel and customer-facing storefront. It uses Medoo ORM (`$mdb`), Redis caching, and a Domain-Driven Design architecture with Dependency Injection (migration from legacy architecture complete). +## Zasady pisania kodu +- Kod ma być czytelny „dla obcego”: jasne nazwy, mało magii +- Brak „skrótów na szybko” typu logika w widokach, copy-paste, losowe helpery bez spójności +- Każda funkcja/klasa ma mieć jedną odpowiedzialność, zwykle do 30–50 linii (jeśli dłuższe – dzielić) +- max 3 poziomy zagnieżdżeń (if/foreach), reszta do osobnych metod +- Nazewnictwo: + - klasy: PascalCase + - metody/zmienne: camelCase + - stałe: UPPER_SNAKE_CASE +- Zero „skrótologii” w nazwach (np. $d, $tmp, $x1) poza pętlami 2–3 linijki +- medoo + prepared statements bez wyjątków (żadnego sklejania SQL stringiem) +- XSS: escape w widokach (np. helper e()) +- CSRF dla formularzy, sensowna obsługa sesji +- Kod ma mieć komentarze tylko tam, gdzie wyjaśniają „dlaczego”, nie „co” + ## PHP Version Constraint **Production runs PHP < 8.0.** Do NOT use: @@ -222,7 +237,8 @@ Before starting implementation, review current state of docs (see AGENTS.md for - `docs/TESTING.md` — test suite guide and structure - `docs/FORM_EDIT_SYSTEM.md` — form system architecture - `docs/CHANGELOG.md` — version history -- `docs/API.md` — REST API documentation (ordersPRO) +- `api-docs/api-reference.json` — REST API documentation (ordersPRO) +- `api-docs/index.html` — REST API documentation (ordersPRO) - `docs/UPDATE_INSTRUCTIONS.md` — how to build client update packages ## Za każdym razem jak próbujesz sprawdzić jakiś plik z logami spróbuj go najpierw pobrać z serwera FTP diff --git a/api-docs/api-reference.json b/api-docs/api-reference.json new file mode 100644 index 0000000..0496cb5 --- /dev/null +++ b/api-docs/api-reference.json @@ -0,0 +1,292 @@ +{ + "name": "shopPRO API", + "version": "1.0.0", + "entrypoint": "/api.php", + "authentication": { + "type": "header", + "header": "X-Api-Key", + "required": true, + "description": "API key stored in pp_settings.param=api_key" + }, + "response_format": { + "success": { + "status": "ok", + "data": {} + }, + "error": { + "status": "error", + "code": "BAD_REQUEST", + "message": "Human-readable error message" + }, + "error_codes": [ + { "code": "UNAUTHORIZED", "http": 401 }, + { "code": "BAD_REQUEST", "http": 400 }, + { "code": "NOT_FOUND", "http": 404 }, + { "code": "METHOD_NOT_ALLOWED", "http": 405 }, + { "code": "INTERNAL_ERROR", "http": 500 } + ] + }, + "endpoints": [ + { + "group": "orders", + "action": "list", + "method": "GET", + "url_template": "/api.php?endpoint=orders&action=list", + "query_params": [ + { "name": "status", "type": "string", "required": false }, + { "name": "paid", "type": "string", "required": false }, + { "name": "date_from", "type": "string", "required": false, "format": "YYYY-MM-DD" }, + { "name": "date_to", "type": "string", "required": false, "format": "YYYY-MM-DD" }, + { "name": "updated_since", "type": "string", "required": false, "format": "YYYY-MM-DD HH:MM:SS" }, + { "name": "number", "type": "string", "required": false }, + { "name": "client", "type": "string", "required": false }, + { "name": "page", "type": "integer", "required": false, "default": 1, "min": 1 }, + { "name": "per_page", "type": "integer", "required": false, "default": 50, "min": 1, "max": 100 } + ] + }, + { + "group": "orders", + "action": "get", + "method": "GET", + "url_template": "/api.php?endpoint=orders&action=get&id={order_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ] + }, + { + "group": "orders", + "action": "change_status", + "method": "PUT", + "url_template": "/api.php?endpoint=orders&action=change_status&id={order_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ], + "json_body": { + "required_fields": ["status_id"], + "fields": { + "status_id": { "type": "integer" }, + "send_email": { "type": "boolean", "required": false } + } + } + }, + { + "group": "orders", + "action": "set_paid", + "method": "PUT", + "url_template": "/api.php?endpoint=orders&action=set_paid&id={order_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ], + "json_body": { + "required_fields": [], + "fields": { + "send_email": { "type": "boolean", "required": false } + } + } + }, + { + "group": "orders", + "action": "set_unpaid", + "method": "PUT", + "url_template": "/api.php?endpoint=orders&action=set_unpaid&id={order_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ] + }, + { + "group": "products", + "action": "list", + "method": "GET", + "url_template": "/api.php?endpoint=products&action=list", + "query_params": [ + { "name": "search", "type": "string", "required": false }, + { "name": "status", "type": "string", "required": false }, + { "name": "promoted", "type": "string", "required": false }, + { "name": "attribute_{id}", "type": "integer", "required": false, "description": "e.g. attribute_5=12" }, + { "name": "sort", "type": "string", "required": false, "default": "id", "allowed": ["id", "name", "price_brutto", "status", "promoted", "quantity"] }, + { "name": "sort_dir", "type": "string", "required": false, "default": "DESC", "allowed": ["ASC", "DESC"] }, + { "name": "page", "type": "integer", "required": false, "default": 1, "min": 1 }, + { "name": "per_page", "type": "integer", "required": false, "default": 50, "min": 1, "max": 100 } + ] + }, + { + "group": "products", + "action": "get", + "method": "GET", + "url_template": "/api.php?endpoint=products&action=get&id={product_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ] + }, + { + "group": "products", + "action": "create", + "method": "POST", + "url_template": "/api.php?endpoint=products&action=create", + "json_body": { + "required_fields": ["languages", "price_brutto"], + "rules": [ + "languages must be an object with at least one language entry containing name", + "price_brutto must be numeric and >= 0" + ] + } + }, + { + "group": "products", + "action": "update", + "method": "PUT", + "url_template": "/api.php?endpoint=products&action=update&id={product_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ], + "json_body": { + "required_fields": [], + "rules": ["partial update; only changed fields are needed"] + } + }, + { + "group": "products", + "action": "variants", + "method": "GET", + "url_template": "/api.php?endpoint=products&action=variants&id={product_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ] + }, + { + "group": "products", + "action": "create_variant", + "method": "POST", + "url_template": "/api.php?endpoint=products&action=create_variant&id={product_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ], + "json_body": { + "required_fields": ["attributes"], + "fields": { + "attributes": { "type": "object", "description": "Map attribute_id -> value_id" } + } + } + }, + { + "group": "products", + "action": "update_variant", + "method": "PUT", + "url_template": "/api.php?endpoint=products&action=update_variant&id={variant_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ], + "json_body": { + "required_fields": [], + "rules": ["partial update of variant fields"] + } + }, + { + "group": "products", + "action": "delete_variant", + "method": "DELETE", + "url_template": "/api.php?endpoint=products&action=delete_variant&id={variant_id}", + "query_params": [ + { "name": "id", "type": "integer", "required": true, "min": 1 } + ] + }, + { + "group": "products", + "action": "upload_image", + "method": "POST", + "url_template": "/api.php?endpoint=products&action=upload_image", + "json_body": { + "required_fields": ["id", "file_name", "content_base64"], + "fields": { + "id": { "type": "integer", "description": "product id" }, + "file_name": { "type": "string" }, + "content_base64": { "type": "string", "description": "base64 payload" }, + "alt": { "type": "string", "required": false }, + "o": { "type": "integer", "required": false, "description": "image position" } + } + } + }, + { + "group": "dictionaries", + "action": "statuses", + "method": "GET", + "url_template": "/api.php?endpoint=dictionaries&action=statuses" + }, + { + "group": "dictionaries", + "action": "transports", + "method": "GET", + "url_template": "/api.php?endpoint=dictionaries&action=transports" + }, + { + "group": "dictionaries", + "action": "payment_methods", + "method": "GET", + "url_template": "/api.php?endpoint=dictionaries&action=payment_methods" + }, + { + "group": "dictionaries", + "action": "attributes", + "method": "GET", + "url_template": "/api.php?endpoint=dictionaries&action=attributes" + }, + { + "group": "dictionaries", + "action": "ensure_attribute", + "method": "POST", + "url_template": "/api.php?endpoint=dictionaries&action=ensure_attribute", + "json_body": { + "required_fields": ["name"], + "fields": { + "name": { "type": "string" }, + "type": { "type": "integer", "required": false, "default": 0 }, + "lang": { "type": "string", "required": false, "default": "pl" } + } + } + }, + { + "group": "dictionaries", + "action": "ensure_attribute_value", + "method": "POST", + "url_template": "/api.php?endpoint=dictionaries&action=ensure_attribute_value", + "json_body": { + "required_fields": ["attribute_id", "name"], + "fields": { + "attribute_id": { "type": "integer" }, + "name": { "type": "string" }, + "lang": { "type": "string", "required": false, "default": "pl" } + } + } + }, + { + "group": "dictionaries", + "action": "ensure_producer", + "method": "POST", + "url_template": "/api.php?endpoint=dictionaries&action=ensure_producer", + "json_body": { + "required_fields": ["name"], + "fields": { + "name": { "type": "string" } + } + } + }, + { + "group": "categories", + "action": "list", + "method": "GET", + "url_template": "/api.php?endpoint=categories&action=list" + } + ], + "examples": { + "curl_list_products": "curl -X GET \"https://twoja-domena.pl/api.php?endpoint=products&action=list&page=1&per_page=20\" -H \"X-Api-Key: TWOJ_KLUCZ\"", + "curl_get_order": "curl -X GET \"https://twoja-domena.pl/api.php?endpoint=orders&action=get&id=42\" -H \"X-Api-Key: TWOJ_KLUCZ\"", + "curl_create_product": "curl -X POST \"https://twoja-domena.pl/api.php?endpoint=products&action=create\" -H \"X-Api-Key: TWOJ_KLUCZ\" -H \"Content-Type: application/json\" -d \"{\\\"price_brutto\\\":99.99,\\\"languages\\\":{\\\"pl\\\":{\\\"name\\\":\\\"Nowy produkt\\\"}}}\"" + }, + "source_of_truth": [ + "autoload/api/ApiRouter.php", + "autoload/api/Controllers/OrdersApiController.php", + "autoload/api/Controllers/ProductsApiController.php", + "autoload/api/Controllers/DictionariesApiController.php", + "autoload/api/Controllers/CategoriesApiController.php" + ] +} diff --git a/api-docs/index.html b/api-docs/index.html new file mode 100644 index 0000000..9cee90a --- /dev/null +++ b/api-docs/index.html @@ -0,0 +1,60 @@ + + +
+ + +Machine-readable JSON: api-reference.json
+ +| Group | +Action | +Method | +URL template | +
|---|
Pelny opis produktu
", - "meta_description": null, - "meta_keywords": null, - "meta_title": null, - "seo_link": "produkt-testowy", - "copy_from": null, - "warehouse_message_zero": null, - "warehouse_message_nonzero": null, - "tab_name_1": null, - "tab_description_1": null, - "tab_name_2": null, - "tab_description_2": null, - "canonical": null, - "security_information": null - } - }, - "images": [ - {"id": 1, "src": "product1.jpg", "alt": "Zdjecie produktu"} - ], - "categories": [1, 5], - "attributes": [ - { - "attribute_id": 1, - "attribute_type": 1, - "attribute_names": {"pl": "Kolor", "en": "Color"}, - "value_id": 3, - "value_names": {"pl": "Czerwony", "en": "Red"} - } - ], - "custom_fields": [ - {"name": "Napis na koszulce", "type": "text", "is_required": 1} - ], - "variants": [ - { - "id": 101, - "permutation_hash": "1-3|2-5", - "sku": "PROD-001-RED-L", - "ean": null, - "price_brutto": 109.99, - "price_brutto_promo": null, - "price_netto": 89.42, - "price_netto_promo": null, - "quantity": 5, - "stock_0_buy": 0, - "weight": 0.5, - "status": 1, - "attributes": [ - {"attribute_id": 1, "attribute_names": {"pl": "Kolor"}, "value_id": 3, "value_names": {"pl": "Czerwony"}}, - {"attribute_id": 2, "attribute_names": {"pl": "Rozmiar"}, "value_id": 5, "value_names": {"pl": "L"}} - ] - } - ] - } -} -``` - -#### Tworzenie produktu -``` -POST api.php?endpoint=products&action=create -Content-Type: application/json - -{ - "price_brutto": 99.99, - "vat": 23, - "quantity": 10, - "status": 1, - "sku": "PROD-001", - "ean": "5901234123457", - "new_to_date": null, - "additional_message": 0, - "additional_message_required": 0, - "additional_message_text": null, - "weight": 0.5, - "languages": { - "pl": { - "name": "Nowy produkt", - "description": "Opis produktu
" - } - }, - "categories": [1, 5], - "products_related": [10, 20], - "custom_fields": [ - {"name": "Napis na koszulce", "type": "text", "is_required": 1} - ] -} -``` - -Wymagane: `languages` (min. 1 jezyk z `name`) oraz `price_brutto`. -`custom_fields` — opcjonalne; kazdy element wymaga `name`, `type` (domyslnie `text`), `is_required` (0/1). - -Odpowiedz (HTTP 201): -```json -{ - "status": "ok", - "data": { - "id": 42 - } -} -``` - -#### Aktualizacja produktu -``` -PUT api.php?endpoint=products&action=update&id={product_id} -Content-Type: application/json - -{ - "price_brutto": 129.99, - "status": 1, - "new_to_date": "2026-12-31", - "additional_message": 1, - "additional_message_required": 0, - "additional_message_text": "Dodaj tresc do personalizacji", - "languages": { - "pl": { - "name": "Zaktualizowana nazwa" - } - } -} -``` - -Partial update — wystarczy przeslac tylko zmienione pola. Pola nieprzeslane zachowuja aktualna wartosc. -Pola ustawien produktu obslugiwane przez API: `new_to_date`, `additional_message`, `additional_message_required`, `additional_message_text`. - -Odpowiedz: pelne dane produktu (jak w `get`). - -### Warianty produktow - -#### Lista wariantow produktu -``` -GET api.php?endpoint=products&action=variants&id={product_id} -``` - -Zwraca warianty produktu nadrzednego wraz z dostepnymi atrybutami. - -Odpowiedz: -```json -{ - "status": "ok", - "data": { - "product_id": 1, - "available_attributes": [ - { - "id": 1, - "type": 1, - "status": 1, - "names": {"pl": "Kolor", "en": "Color"}, - "values": [ - {"id": 3, "names": {"pl": "Czerwony", "en": "Red"}, "is_default": 0, "impact_on_the_price": null}, - {"id": 4, "names": {"pl": "Niebieski", "en": "Blue"}, "is_default": 0, "impact_on_the_price": 10.0} - ] - } - ], - "variants": [ - { - "id": 101, - "permutation_hash": "1-3", - "sku": "PROD-001-RED", - "ean": null, - "price_brutto": 109.99, - "price_brutto_promo": null, - "price_netto": 89.42, - "price_netto_promo": null, - "quantity": 5, - "stock_0_buy": 0, - "weight": 0.5, - "status": 1, - "attributes": [ - {"attribute_id": 1, "attribute_names": {"pl": "Kolor"}, "value_id": 3, "value_names": {"pl": "Czerwony"}} - ] - } - ] - } -} -``` - -#### Tworzenie wariantu -``` -POST api.php?endpoint=products&action=create_variant&id={product_id} -Content-Type: application/json - -{ - "attributes": {"1": 3, "2": 5}, - "sku": "PROD-001-RED-L", - "ean": "5901234123458", - "price_brutto": 109.99, - "quantity": 5, - "weight": 0.5 -} -``` - -Wymagane: `attributes` (mapa attribute_id -> value_id, min. 1). Kombinacja atrybutow musi byc unikalna. - -Odpowiedz (HTTP 201): pelne dane wariantu. - -#### Aktualizacja wariantu -``` -PUT api.php?endpoint=products&action=update_variant&id={variant_id} -Content-Type: application/json - -{ - "sku": "PROD-001-RED-XL", - "price_brutto": 119.99, - "quantity": 3 -} -``` - -Partial update — mozna zmienic: sku, ean, price_brutto, price_netto, price_brutto_promo, price_netto_promo, quantity, stock_0_buy, weight, status. - -Odpowiedz: pelne dane wariantu. - -#### Usuwanie wariantu -``` -DELETE api.php?endpoint=products&action=delete_variant&id={variant_id} -``` - -Odpowiedz: -```json -{ - "status": "ok", - "data": {"id": 101, "deleted": true} -} -``` - -### Kategorie - -#### Lista kategorii -``` -GET api.php?endpoint=categories&action=list -``` - -Zwraca plaska liste wszystkich aktywnych kategorii w domyslnym jezyku sklepu. - -Odpowiedz: -```json -{ - "status": "ok", - "data": { - "categories": [ - {"id": 1, "parent_id": null, "title": "Kategoria glowna"}, - {"id": 3, "parent_id": 1, "title": "Podkategoria A"}, - {"id": 5, "parent_id": 1, "title": "Podkategoria B"} - ] - } -} -``` - -Pola odpowiedzi: -| Pole | Typ | Opis | -|------|-----|------| -| `id` | int | ID kategorii | -| `parent_id` | int\|null | ID kategorii nadrzednej (null = kategoria glowna) | -| `title` | string | Nazwa w domyslnym jezyku; fallback na inny jezyk jesli brak tlumaczenia | - ---- - -### Slowniki - -#### Lista statusow zamowien -``` -GET api.php?endpoint=dictionaries&action=statuses -``` - -Odpowiedz: -```json -{ - "status": "ok", - "data": [ - {"id": 0, "name": "Nowe"}, - {"id": 1, "name": "Oplacone"}, - {"id": 4, "name": "W realizacji"}, - {"id": 6, "name": "Wyslane"} - ] -} -``` - -#### Lista metod transportu -``` -GET api.php?endpoint=dictionaries&action=transports -``` - -#### Lista metod platnosci -``` -GET api.php?endpoint=dictionaries&action=payment_methods -``` - -#### Lista atrybutow -``` -GET api.php?endpoint=dictionaries&action=attributes -``` - -Zwraca aktywne atrybuty z wartosciami i wielojezycznymi nazwami. - -#### Znajdz lub utworz producenta -``` -POST api.php?endpoint=dictionaries&action=ensure_producer -Content-Type: application/json - -{ - "name": "Nike" -} -``` - -Zwraca istniejacego producenta po nazwie lub tworzy nowego. Uzyc przed tworzeniem produktu, jesli producent moze nie istniec. - -Odpowiedz: -```json -{ - "status": "ok", - "data": { - "id": 5, - "created": false - } -} -``` - -`created: true` gdy producent zostal nowo dodany, `false` gdy juz istnial. - -Odpowiedz: -```json -{ - "status": "ok", - "data": [ - { - "id": 1, - "type": 1, - "status": 1, - "names": {"pl": "Kolor", "en": "Color"}, - "values": [ - {"id": 3, "names": {"pl": "Czerwony"}, "is_default": 0, "impact_on_the_price": null}, - {"id": 4, "names": {"pl": "Niebieski"}, "is_default": 1, "impact_on_the_price": 10.0} - ] - } - ] -} -``` - -## Polling - -Aby pobierac tylko nowe/zmienione zamowienia, uzyj parametru `updated_since`: - -``` -GET api.php?endpoint=orders&action=list&updated_since=2026-02-19 12:00:00 -``` - -Kolumna `updated_at` w `pp_shop_orders` jest aktualizowana automatycznie przy kazdej modyfikacji zamowienia (zmiana statusu, platnosci, edycja danych, tworzenie zamowienia). - -## Konfiguracja - -Klucz API ustawia sie w panelu admina w ustawieniach sklepu lub bezposrednio w bazie: - -```sql -INSERT INTO pp_settings (param, value) VALUES ('api_key', 'twoj-klucz-api'); --- lub -UPDATE pp_settings SET value = 'twoj-klucz-api' WHERE param = 'api_key'; -``` - -## Architektura - -- Entry point: `api.php` -- Router: `\api\ApiRouter` (`autoload/api/ApiRouter.php`) -- Kontrolery: `autoload/api/Controllers/` - - `OrdersApiController` — zamowienia (5 akcji) - - `ProductsApiController` — produkty (8 akcji: list, get, create, update, variants, create_variant, update_variant, delete_variant) - - `DictionariesApiController` — slowniki (5 akcji: statuses, transports, payment_methods, attributes, ensure_producer) - - `CategoriesApiController` — kategorie (1 akcja: list) diff --git a/docs/TODO.md b/docs/TODO.md index c75bb12..9b54b1a 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -4,3 +4,4 @@ naprawić działanie newslettera i zapis do bazy newslettera program lojalnościowy proponowane produkty w koszyku Do zamówień w statusie: realizowane lub oczekuje na wpłatę. Opcja tylko dla zarejestrowanych klientów. https://royal-stone.pl/pl/order1.html +Dodać możliwość ustawienia limitu znaków w wiadomościach do produktu \ No newline at end of file diff --git a/docs/plans/2026-02-27-htaccess-conf-elimination.md b/docs/plans/2026-02-27-htaccess-conf-elimination.md deleted file mode 100644 index 2024753..0000000 --- a/docs/plans/2026-02-27-htaccess-conf-elimination.md +++ /dev/null @@ -1,658 +0,0 @@ -# htaccess.conf Elimination — Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Eliminate `libraries/htaccess.conf` as a template file and move all remaining hardcoded URL routes into `pp_routes`, leaving only true Apache-level directives in the generated `.htaccess`. - -**Architecture:** `Helpers::htacces()` generates the full `.htaccess` content from PHP strings instead of loading a template. All URL→PHP mappings (static system routes + dynamic per language/producer) are inserted into `pp_routes` with `type='system'`, deleted and reinserted on every `htacces()` call. Apache-level rules (HTTPS redirect, admin routing, thumb.php) stay in `.htaccess` only. - -**Tech Stack:** PHP 7.4, Medoo ORM (`$mdb`), Redis (CacheHandler), PHPUnit 9.6 - ---- - -## Context - -### Current `Helpers::htacces()` structure (before this plan) -1. Loads `libraries/htaccess.conf` template (contains many hardcoded URL routes) -2. Appends language switch rules to `$htaccess_data` -3. Appends newsletter and producer rules to `$htaccess_data` -4. Inserts category/product/page/article routes into `pp_routes` (done in v0.329) -5. Replaces `{HTACCESS_CACHE}` placeholder -6. Appends catch-all, writes files - -### What stays in `.htaccess` after this plan -- `RewriteEngine On`, `RewriteBase /`, `Options` -- www→https redirect -- http→https redirect (with tpay/przelewy24/hotpay exclusion) -- Trailing slash removal (excluding `/admin/`) -- Admin routing: `^admin/([^/]*)/([^/]*)/(.*)$` -- `^admin/$` -- Thumbnail: `^thumb/([0-9]*)/([0-9]*)/(.*)$` → `/libraries/thumb.php` (different PHP file, cannot use pp_routes) -- `THE_REQUEST` index.php redirect -- Cache headers block (gzip/expires or no-cache based on `$settings['htaccess_cache']`) -- File protection: `