diff --git a/src/module-elasticsuite-core/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TopHits.php b/src/module-elasticsuite-core/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TopHits.php index 1c385473f..8a7d41d18 100644 --- a/src/module-elasticsuite-core/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TopHits.php +++ b/src/module-elasticsuite-core/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TopHits.php @@ -39,6 +39,8 @@ public function buildBucket(BucketInterface $bucket) throw new \InvalidArgumentException("Query builder : invalid aggregation type {$bucket->getType()}."); } + $params = []; + if (!empty($bucket->getSource())) { $params['_source']['includes'] = $bucket->getSource(); } diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/DateHistogramTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/DateHistogramTest.php new file mode 100644 index 000000000..15de878bf --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/DateHistogramTest.php @@ -0,0 +1,123 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\DateHistogram as HistogramBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Bucket\DateHistogram as HistogramBucket; +use Smile\ElasticsuiteCore\Search\Request\BucketInterface; + +/** + * Search adapter date histogram aggregation builder test case. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class DateHistogramTest extends \PHPUnit\Framework\TestCase +{ + /** + * Build a histogram aggregation from a bucket. + */ + public function testBasicAggregationBuild(): void + { + $aggBuilder = $this->getHistogramAggregationBuilder(); + $bucket = new HistogramBucket('aggregationName', 'fieldName'); + + $aggregation = $aggBuilder->buildBucket($bucket); + + $this->assertArrayHasKey('date_histogram', $aggregation); + $this->assertEquals('fieldName', $aggregation['date_histogram']['field']); + $this->assertArrayNotHasKey('interval', $aggregation['date_histogram']); + $this->assertEquals('1d', $aggregation['date_histogram']['fixed_interval']); + $this->assertArrayNotHasKey('calendar_interval', $aggregation['date_histogram']); + $this->assertEquals(0, $aggregation['date_histogram']['min_doc_count']); + } + + /** + * Build a histogram aggregation from a bucket. + */ + public function testComplexeAggregationBuild(): void + { + $aggBuilder = $this->getHistogramAggregationBuilder(); + $bucket = new HistogramBucket( + 'aggregationName', + 'fieldName', + [], + [], + [], + null, + null, + null, + '1d', // Deprecated. + null, + '2y', + 10, + ['min' => 2008, 'max' => 2050] + ); + + $aggregation = $aggBuilder->buildBucket($bucket); + + $this->assertArrayHasKey('date_histogram', $aggregation); + $this->assertEquals('fieldName', $aggregation['date_histogram']['field']); + $this->assertEquals('2y', $aggregation['date_histogram']['fixed_interval']); + $this->assertArrayNotHasKey('calendar_interval', $aggregation['date_histogram']); + $this->assertEquals(10, $aggregation['date_histogram']['min_doc_count']); + $this->assertEquals(['min' => 2008, 'max' => 2050], $aggregation['date_histogram']['extended_bounds']); + + $bucket = new HistogramBucket( + 'aggregationName', + 'fieldName', + [], + [], + [], + null, + null, + null, + '1d', // Deprecated. + '1y' + ); + + $aggregation = $aggBuilder->buildBucket($bucket); + + $this->assertArrayHasKey('date_histogram', $aggregation); + $this->assertEquals('fieldName', $aggregation['date_histogram']['field']); + $this->assertArrayNotHasKey('fixed_interval', $aggregation['date_histogram']); + $this->assertEquals('1y', $aggregation['date_histogram']['calendar_interval']); + $this->assertEquals(0, $aggregation['date_histogram']['min_doc_count']); + $this->assertArrayNotHasKey('extended_bounds', $aggregation['date_histogram']); + } + + /** + * Test an exception is thrown when using the term aggs builder with another bucket type. + */ + public function testInvalidBucketAggregationBuild(): void + { + $aggBuilder = $this->getHistogramAggregationBuilder(); + $this->expectExceptionMessage('Query builder : invalid aggregation type invalidType.'); + $this->expectException(\InvalidArgumentException::class); + $termsBucket = $this->getMockBuilder(BucketInterface::class)->getMock(); + $termsBucket->method('getType')->willReturn('invalidType'); + + $aggBuilder->buildBucket($termsBucket); + } + /** + * Get the histogram builder used in tests. + * + * @return HistogramBuilder + */ + private function getHistogramAggregationBuilder() + { + return new HistogramBuilder(); + } +} diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/MetricTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/MetricTest.php new file mode 100644 index 000000000..66fed2d72 --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/MetricTest.php @@ -0,0 +1,135 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\Metric as MetricBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Bucket\Metric as MetricBucket; +use Smile\ElasticsuiteCore\Search\Request\BucketInterface; +use Smile\ElasticsuiteCore\Search\Request\MetricInterface; +use Smile\ElasticsuiteCore\Search\Request\SortOrderInterface; + +/** + * Search adapter top level metrics aggregation builder test case. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class MetricTest extends \PHPUnit\Framework\TestCase +{ + /** + * Test the basic metric aggregation building. + * + * @return void + */ + public function testBasicMetricAggregationBuild(): void + { + $aggBuilder = $this->getAggregationBuilder(); + $metricBucket = new MetricBucket( + 'aggregationName', + 'aggregationField' + ); + + $aggregation = $aggBuilder->buildBucket($metricBucket); + $this->assertEquals(MetricInterface::TYPE_STATS, $metricBucket->getMetricType()); + $this->assertArrayHasKey($metricBucket->getMetricType(), $aggregation); + $this->assertArrayHasKey('field', $aggregation[$metricBucket->getMetricType()]); + $this->assertEquals('aggregationField', $aggregation[$metricBucket->getMetricType()]['field']); + } + + /** + * Test the basic metric aggregation building. + * + * @return void + */ + public function testBasicMetricConfigAggregationBuild(): void + { + $aggBuilder = $this->getAggregationBuilder(); + $metricBucket = new MetricBucket( + 'aggregationName', + 'aggregationField', + [], + [], + [], + null, + null, + null, + MetricInterface::TYPE_PERCENTILES, + ['values' => [500, 600]] + ); + + $aggregation = $aggBuilder->buildBucket($metricBucket); + $this->assertEquals(MetricInterface::TYPE_PERCENTILES, $metricBucket->getMetricType()); + $this->assertArrayHasKey($metricBucket->getMetricType(), $aggregation); + $this->assertArrayHasKey('field', $aggregation[$metricBucket->getMetricType()]); + $this->assertEquals('aggregationField', $aggregation[$metricBucket->getMetricType()]['field']); + $this->assertArrayHasKey('values', $aggregation[$metricBucket->getMetricType()]); + $this->assertEquals([500, 600], $aggregation[$metricBucket->getMetricType()]['values']); + } + + /** + * Test the metric aggregation building with a script. + * + * @return void + */ + public function testScriptMetricAggregationBuild(): void + { + $aggBuilder = $this->getAggregationBuilder(); + $metricBucket = new MetricBucket( + 'aggregationName', + 'aggregationField', + [], + [], + [], + null, + null, + null, + MetricInterface::TYPE_AVG, + ['script' => '_score'] + ); + + $aggregation = $aggBuilder->buildBucket($metricBucket); + $this->assertEquals(MetricInterface::TYPE_AVG, $metricBucket->getMetricType()); + $this->assertArrayHasKey($metricBucket->getMetricType(), $aggregation); + + $this->assertArrayNotHasKey('field', $aggregation[$metricBucket->getMetricType()]); + $this->assertArrayHasKey('script', $aggregation[$metricBucket->getMetricType()]); + $this->assertEquals('_score', $aggregation[$metricBucket->getMetricType()]['script']); + } + + /** + * Test an exception is thrown when using the metric aggs builder with another bucket type. + * + * @return void + */ + public function testInvalidMetricAggregationBuild(): void + { + $this->expectExceptionMessage("Query builder : invalid aggregation type invalidType."); + $this->expectException(\InvalidArgumentException::class); + $metricBucket = $this->getMockBuilder(BucketInterface::class)->getMock(); + $metricBucket->method('getType')->will($this->returnValue('invalidType')); + + $this->getAggregationBuilder()->buildBucket($metricBucket); + } + + /** + * Aggregation builder used in tests. + * + * @return MetricBuilder + */ + private function getAggregationBuilder(): MetricBuilder + { + return new MetricBuilder(); + } +} diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/ReverseNestedTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/ReverseNestedTest.php new file mode 100644 index 000000000..2c110e820 --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/ReverseNestedTest.php @@ -0,0 +1,56 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\ReverseNested as ReverseNestedBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Bucket\ReverseNested; +use Smile\ElasticsuiteCore\Search\Request\BucketInterface; + +/** + * Search adapter reverse nested aggregation builder test case. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class ReverseNestedTest extends \PHPUnit\Framework\TestCase +{ + /** + * Build a reverse nested aggregation from a bucket. + */ + public function testReverseNestedAggregationBuild(): void + { + $aggBuilder = new ReverseNestedBuilder(); + $bucket = new ReverseNested('aggregationName', 'fieldName'); + + $aggregation = $aggBuilder->buildBucket($bucket); + + $this->assertArrayHasKey('reverse_nested', $aggregation); + $this->assertIsObject($aggregation['reverse_nested']); + } + + /** + * Test an exception is thrown when using the term aggs builder with another bucket type. + */ + public function testInvalidBucketAggregationBuild(): void + { + $aggBuilder = new ReverseNestedBuilder(); + $this->expectExceptionMessage('Query builder : invalid aggregation type invalidType.'); + $this->expectException(\InvalidArgumentException::class); + $termsBucket = $this->getMockBuilder(BucketInterface::class)->getMock(); + $termsBucket->method('getType')->willReturn('invalidType'); + + $aggBuilder->buildBucket($termsBucket); + } +} diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/SignificantTermTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/SignificantTermTest.php new file mode 100644 index 000000000..b938eeb77 --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/SignificantTermTest.php @@ -0,0 +1,89 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\SignificantTerm as SignificantTermBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Bucket\SignificantTerm; +use Smile\ElasticsuiteCore\Search\Request\BucketInterface; + +/** + * Search adapter significant term aggregation builder test case. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class SignificantTermTest extends \PHPUnit\Framework\TestCase +{ + /** + * Build a significant term aggregation from a bucket. + */ + public function testBasicAggregationBuild(): void + { + $aggBuilder = new SignificantTermBuilder(); + $bucket = new SignificantTerm('aggregationName', 'fieldName'); + + $aggregation = $aggBuilder->buildBucket($bucket); + + $this->assertArrayHasKey('significant_terms', $aggregation); + $this->assertEquals('fieldName', $aggregation['significant_terms']['field']); + $this->assertEquals(BucketInterface::MAX_BUCKET_SIZE, $aggregation['significant_terms']['size']); + $this->assertEquals(5, $aggregation['significant_terms']['min_doc_count']); + $this->assertArrayHasKey('gnd', $aggregation['significant_terms']); + } + + /** + * Build a significant term aggregation from a bucket. + */ + public function testComplexAggregationBuild(): void + { + $aggBuilder = new SignificantTermBuilder(); + $bucket = new SignificantTerm( + 'aggregationName', + 'fieldName', + [], + [], + [], + null, + null, + null, + 12, + 10, + SignificantTerm::ALGORITHM_PERCENTAGE, + ); + + $aggregation = $aggBuilder->buildBucket($bucket); + + $this->assertArrayHasKey('significant_terms', $aggregation); + $this->assertEquals('fieldName', $aggregation['significant_terms']['field']); + $this->assertEquals(12, $aggregation['significant_terms']['size']); + $this->assertEquals(10, $aggregation['significant_terms']['min_doc_count']); + $this->assertArrayNotHasKey('gnd', $aggregation['significant_terms']); + $this->assertArrayHasKey('percentage', $aggregation['significant_terms']); + } + + /** + * Test an exception is thrown when using the term aggs builder with another bucket type. + */ + public function testInvalidBucketAggregationBuild(): void + { + $aggBuilder = new SignificantTermBuilder(); + $this->expectExceptionMessage('Query builder : invalid aggregation type invalidType.'); + $this->expectException(\InvalidArgumentException::class); + $termsBucket = $this->getMockBuilder(BucketInterface::class)->getMock(); + $termsBucket->method('getType')->willReturn('invalidType'); + + $aggBuilder->buildBucket($termsBucket); + } +} diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TermTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TermTest.php index 5ba8b43b3..44f2de05c 100644 --- a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TermTest.php +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TermTest.php @@ -121,6 +121,102 @@ public function testRelevanceSortOrderTermAggregationBuild() $this->assertEquals(['avg' => ['script' => TermBucket::SORT_ORDER_RELEVANCE]], $aggregation['aggregations']['termRelevance']); } + /** + * Test the standard term aggregation building sorted by provided params. + * + * @return void + */ + public function testComplexSortOrderTermAggregationBuild() + { + $aggBuilder = $this->getAggregationBuilder(); + $termBucket = new TermBucket( + 'aggregationName', + 'fieldName', + [], + [], + [], + null, + null, + null, + 1, + ['sortField' => SortOrderInterface::SORT_DESC] + ); + + $aggregation = $aggBuilder->buildBucket($termBucket); + + $this->assertArrayHasKey('terms', $aggregation); + $this->assertEquals('fieldName', $aggregation['terms']['field']); + $this->assertEquals(['sortField' => SortOrderInterface::SORT_DESC], $aggregation['terms']['order']); + } + + /** + * Test the standard term aggregation building when using include and exclude params. + * + * @return void + */ + public function testFilteringValuesTermAggregationBuild() + { + $aggBuilder = $this->getAggregationBuilder(); + $termBucket = new TermBucket( + 'aggregationName', + 'fieldName', + [], + [], + [], + null, + null, + null, + 1, + BucketInterface::SORT_ORDER_COUNT, + ['.*sport.*'], + ['water', 'rain', 'snow'] + ); + + $aggregation = $aggBuilder->buildBucket($termBucket); + + $this->assertArrayHasKey('terms', $aggregation); + $this->assertEquals('fieldName', $aggregation['terms']['field']); + $this->assertEquals([TermBucket::SORT_ORDER_COUNT => SortOrderInterface::SORT_DESC], $aggregation['terms']['order']); + $this->assertEquals(['.*sport.*'], $aggregation['terms']['include']); + $this->assertEquals(['water', 'rain', 'snow'], $aggregation['terms']['exclude']); + $this->assertArrayNotHasKey('min_doc_count', $aggregation['terms']); + } + + /** + * Test the standard term aggregation building when min doc count param. + * + * @return void + */ + public function testNoFilterMinDocCountTermAggregationBuild() + { + $aggBuilder = $this->getAggregationBuilder(); + $termBucket = new TermBucket( + 'aggregationName', + 'fieldName', + [], + [], + [], + null, + null, + null, + 1, + BucketInterface::SORT_ORDER_COUNT, + [], + [], + 5 + ); + + $aggregation = $aggBuilder->buildBucket($termBucket); + + $this->assertArrayHasKey('terms', $aggregation); + $this->assertEquals('fieldName', $aggregation['terms']['field']); + $this->assertEquals([TermBucket::SORT_ORDER_COUNT => SortOrderInterface::SORT_DESC], $aggregation['terms']['order']); + $this->assertArrayNotHasKey('include', $aggregation['terms']); + $this->assertArrayNotHasKey('exclude', $aggregation['terms']); + $this->assertArrayHasKey('min_doc_count', $aggregation['terms']); + $this->assertEquals(5, $aggregation['terms']['min_doc_count']); + } + /** * Test an exception is thrown when using the term aggs builder with another bucket type. * diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TopHitsTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TopHitsTest.php new file mode 100644 index 000000000..9472c1748 --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/Builder/TopHitsTest.php @@ -0,0 +1,220 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\TopHits as TopHitsBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Bucket\Term as TermBucket; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Bucket\TopHits as TopHitsBucket; +use Smile\ElasticsuiteCore\Search\Request\BucketInterface; +use Smile\ElasticsuiteCore\Search\Request\SortOrderInterface; + +/** + * Search adapter top hits aggregation builder test case. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class TopHitsTest extends \PHPUnit\Framework\TestCase +{ + /** + * Test the max bucket size limitation. + * + * @dataProvider sizeDataProvider + * @SuppressWarnings(PHPMD.ElseExpression) + * + * @param integer $size Configured bucket size. + * @param integer $hasSize Will the built bucket have a size param. + * @param integer $expected Expected bucket size in the built aggregation. + * + * @return void + */ + public function testBucketNoSize($size, $hasSize, $expected) + { + $aggBuilder = $this->getAggregationBuilder(); + $topHitsBucket = new TopHitsBucket( + 'aggregationName', + [], + $size + ); + + $aggregation = $aggBuilder->buildBucket($topHitsBucket); + $this->assertArrayHasKey('top_hits', $aggregation); + if ($hasSize) { + $this->assertArrayHasKey('size', $aggregation['top_hits']); + $this->assertEquals($expected, $aggregation['top_hits']['size']); + } else { + $this->assertArrayNotHasKey('size', $aggregation['top_hits']); + } + } + + /** + * Test the bucket default max size. + * + * @return void + */ + public function testBucketDefaultSize() + { + $aggBuilder = $this->getAggregationBuilder(); + $topHitsBucket = new TopHitsBucket( + 'aggregationName', + [] + ); + + $aggregation = $aggBuilder->buildBucket($topHitsBucket); + $this->assertArrayHasKey('top_hits', $aggregation); + $this->assertArrayHasKey('size', $aggregation['top_hits']); + $this->assertEquals(1, $aggregation['top_hits']['size']); + } + + /** + * Dataset used to run testBucketSize. + * + * @return array + */ + public function sizeDataProvider() + { + return [ + [0, false, 0], + [TermBucket::MAX_BUCKET_SIZE - 1, true, TermBucket::MAX_BUCKET_SIZE - 1], + [TermBucket::MAX_BUCKET_SIZE, true, TermBucket::MAX_BUCKET_SIZE], + [TermBucket::MAX_BUCKET_SIZE + 1, true, TermBucket::MAX_BUCKET_SIZE + 1], + ]; + } + + /** + * Test the bucket default max size. + * + * @return void + */ + public function testTopHitsSourceInnerHits() + { + $aggBuilder = $this->getAggregationBuilder(); + $topHitsBucket = new TopHitsBucket( + 'aggregationName' + ); + + $aggregation = $aggBuilder->buildBucket($topHitsBucket); + $this->assertArrayHasKey('top_hits', $aggregation); + $this->assertArrayNotHasKey('_source', $aggregation['top_hits']); + + $topHitsBucket = new TopHitsBucket( + 'aggregationName', + ['name', 'sku'] + ); + $aggregation = $aggBuilder->buildBucket($topHitsBucket); + $this->assertArrayHasKey('top_hits', $aggregation); + $this->assertArrayHasKey('_source', $aggregation['top_hits']); + $this->assertArrayHasKey('includes', $aggregation['top_hits']['_source']); + $this->assertEquals(['name', 'sku'], $aggregation['top_hits']['_source']['includes']); + } + + /** + * Test the standard term aggregation building sorted by provided params. + * + * @return void + */ + public function testComplexSortOrderTopHitsAggregationBuild() + { + $aggBuilder = $this->getAggregationBuilder(); + $topHitsBucket = new TopHitsBucket( + 'aggregationName', + [], + 1, + ['sortField' => SortOrderInterface::SORT_DESC] + ); + + $aggregation = $aggBuilder->buildBucket($topHitsBucket); + + $this->assertArrayHasKey('top_hits', $aggregation); + $this->assertEquals(['sortField' => SortOrderInterface::SORT_DESC], $aggregation['top_hits']['sort']); + } + + /** + * Test the standard term aggregation building sorted basic/scalar provided param. + * + * @return void + */ + public function testSimpleSortOrderTopHitsAggregationBuild() + { + $aggBuilder = $this->getAggregationBuilder(); + $topHitsBucket = new TopHitsBucket( + 'aggregationName', + [], + 1, + BucketInterface::SORT_ORDER_RELEVANCE + ); + $aggregation = $aggBuilder->buildBucket($topHitsBucket); + + $this->assertArrayHasKey('top_hits', $aggregation); + $this->assertArrayHasKey('sort', $aggregation['top_hits']); + $this->assertEquals([BucketInterface::SORT_ORDER_RELEVANCE => SortOrderInterface::SORT_DESC], $aggregation['top_hits']['sort']); + + $topHitsNestedBucket = new TopHitsBucket( + 'aggregationName', + [], + 1, + BucketInterface::SORT_ORDER_RELEVANCE, + [], + [], + [], + 'nestedPath' + ); + $aggregation = $aggBuilder->buildBucket($topHitsNestedBucket); + + $this->assertArrayHasKey('top_hits', $aggregation); + $this->assertArrayNotHasKey('sort', $aggregation['top_hits']); + + + $topHitsUnsupportedSortBucket = new TopHitsBucket( + 'aggregationName', + [], + 1, + BucketInterface::SORT_ORDER_COUNT, + [], + [], + [], + 'nestedPath' + ); + $aggregation = $aggBuilder->buildBucket($topHitsUnsupportedSortBucket); + + $this->assertArrayHasKey('top_hits', $aggregation); + $this->assertArrayNotHasKey('sort', $aggregation['top_hits']); + } + + /** + * Test an exception is thrown when using the term aggs builder with another bucket type. + * + * @return void + */ + public function testInvalidBucketAggregationBuild() + { + $this->expectExceptionMessage("Query builder : invalid aggregation type invalidType."); + $this->expectException(\InvalidArgumentException::class); + $topHitsBucket = $this->getMockBuilder(BucketInterface::class)->getMock(); + $topHitsBucket->method('getType')->will($this->returnValue('invalidType')); + + $this->getAggregationBuilder()->buildBucket($topHitsBucket); + } + + /** + * Aggregation builder used in tests. + * + * @return TopHitsBuilder + */ + private function getAggregationBuilder() + { + return new TopHitsBuilder(); + } +} diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/BucketSelectorTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/BucketSelectorTest.php new file mode 100644 index 000000000..e644d9c14 --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/BucketSelectorTest.php @@ -0,0 +1,84 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\PipelineBuilder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\PipelineBuilder\BucketSelector as BucketSelectorBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Pipeline\BucketSelector; +use Smile\ElasticsuiteCore\Search\Request\PipelineInterface; + +/** + * Search adapter bucket selector pipeline builder test cases. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class BucketSelectorTest extends \PHPUnit\Framework\TestCase +{ + /** + * Build a bucket selector aggregation from a pipeline. + */ + public function testBasicAggregationBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $pipeline = new BucketSelector('aggregationName', 'bucket.path', 'testScript'); + + $aggregation = $pipelineBuilder->buildPipeline($pipeline); + + $this->assertArrayHasKey('bucket_selector', $aggregation); + $this->assertEquals('bucket.path', $aggregation['bucket_selector']['buckets_path']); + $this->assertEquals('testScript', $aggregation['bucket_selector']['script']); + $this->assertEquals(PipelineInterface::GAP_POLICY_SKIP, $aggregation['bucket_selector']['gap_policy']); + } + + /** + * Build a bucket selector aggregation from a pipeline. + */ + public function testComplexAggregationBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $pipeline = new BucketSelector('aggregationName', 'bucket.path', 'testScript', PipelineInterface::GAP_POLICY_INSERT_ZEROS); + + $aggregation = $pipelineBuilder->buildPipeline($pipeline); + + $this->assertArrayHasKey('bucket_selector', $aggregation); + $this->assertEquals('bucket.path', $aggregation['bucket_selector']['buckets_path']); + $this->assertEquals('testScript', $aggregation['bucket_selector']['script']); + $this->assertEquals(PipelineInterface::GAP_POLICY_INSERT_ZEROS, $aggregation['bucket_selector']['gap_policy']); + } + + /** + * Test an exception is thrown when using the bucket selector pipeline with another pipeline type. + */ + public function testInvalidPipelineBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $this->expectExceptionMessage('Query builder : invalid aggregation type invalidType.'); + $this->expectException(\InvalidArgumentException::class); + $pipeline = $this->getMockBuilder(PipelineInterface::class)->getMock(); + $pipeline->method('getType')->willReturn('invalidType'); + + $pipelineBuilder->buildPipeline($pipeline); + } + + /** + * Aggregation builder used in tests. + * + * @return BucketSelectorBuilder + */ + private function getPipelineBuilder() + { + return new BucketSelectorBuilder(); + } +} diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/MaxBucketTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/MaxBucketTest.php new file mode 100644 index 000000000..4b2b8f218 --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/MaxBucketTest.php @@ -0,0 +1,84 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\PipelineBuilder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\PipelineBuilder\MaxBucket as MaxBucketBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Pipeline\MaxBucket; +use Smile\ElasticsuiteCore\Search\Request\PipelineInterface; + +/** + * Search adapter bucket selector pipeline builder test cases. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class MaxBucketTest extends \PHPUnit\Framework\TestCase +{ + /** + * Build a bucket selector aggregation from a bucket. + */ + public function testBasicAggregationBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $pipeline = new MaxBucket('aggregationName', 'bucket.path'); + + $aggregation = $pipelineBuilder->buildPipeline($pipeline); + + $this->assertArrayHasKey('max_bucket', $aggregation); + $this->assertEquals('bucket.path', $aggregation['max_bucket']['buckets_path']); + $this->assertEquals('', $aggregation['max_bucket']['format']); + $this->assertEquals(PipelineInterface::GAP_POLICY_SKIP, $aggregation['max_bucket']['gap_policy']); + } + + /** + * Build a bucket selector aggregation from a bucket. + */ + public function testComplexAggregationBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $pipeline = new MaxBucket('aggregationName', 'bucket.path', PipelineInterface::GAP_POLICY_INSERT_ZEROS, 'testFormat'); + + $aggregation = $pipelineBuilder->buildPipeline($pipeline); + + $this->assertArrayHasKey('max_bucket', $aggregation); + $this->assertEquals('bucket.path', $aggregation['max_bucket']['buckets_path']); + $this->assertEquals('testFormat', $aggregation['max_bucket']['format']); + $this->assertEquals(PipelineInterface::GAP_POLICY_INSERT_ZEROS, $aggregation['max_bucket']['gap_policy']); + } + + /** + * Test an exception is thrown when using the max bucket pipeline with another pipeline type. + */ + public function testInvalidPipelineBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $this->expectExceptionMessage('Query builder : invalid aggregation type invalidType.'); + $this->expectException(\InvalidArgumentException::class); + $pipeline = $this->getMockBuilder(PipelineInterface::class)->getMock(); + $pipeline->method('getType')->willReturn('invalidType'); + + $pipelineBuilder->buildPipeline($pipeline); + } + + /** + * Aggregation builder used in tests. + * + * @return MaxBucketBuilder + */ + private function getPipelineBuilder() + { + return new MaxBucketBuilder(); + } +} diff --git a/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/MovingFunctionTest.php b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/MovingFunctionTest.php new file mode 100644 index 000000000..10f2f3920 --- /dev/null +++ b/src/module-elasticsuite-core/Test/Unit/Search/Adapter/Elasticsuite/Request/Aggregation/PipelineBuilder/MovingFunctionTest.php @@ -0,0 +1,86 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteCore\Test\Unit\Search\Adapter\Elasticsuite\Request\Aggregation\Builder\PipelineBuilder; + +use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Request\Aggregation\PipelineBuilder\MovingFunction as MovingFunctionBuilder; +use Smile\ElasticsuiteCore\Search\Request\Aggregation\Pipeline\MovingFunction; +use Smile\ElasticsuiteCore\Search\Request\PipelineInterface; + +/** + * Search adapter bucket selector pipeline builder test cases. + * + * @category Smile + * @package Smile\ElasticsuiteCore + * @author Richard BAYET + */ +class MovingFunctionTest extends \PHPUnit\Framework\TestCase +{ + /** + * Build a moving function aggregation from a bucket. + */ + public function testBasicAggregationBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $pipeline = new MovingFunction('aggregationName', 'bucket.path', 'testScript'); + + $aggregation = $pipelineBuilder->buildPipeline($pipeline); + + $this->assertArrayHasKey('moving_fn', $aggregation); + $this->assertEquals('bucket.path', $aggregation['moving_fn']['buckets_path']); + $this->assertEquals('testScript', $aggregation['moving_fn']['script']); + $this->assertEquals(10, $aggregation['moving_fn']['window']); + $this->assertEquals(PipelineInterface::GAP_POLICY_SKIP, $aggregation['moving_fn']['gap_policy']); + } + + /** + * Build a moving function aggregation from a bucket. + */ + public function testComplexAggregationBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $pipeline = new MovingFunction('aggregationName', 'bucket.path', 'testScript', 20, PipelineInterface::GAP_POLICY_INSERT_ZEROS); + + $aggregation = $pipelineBuilder->buildPipeline($pipeline); + + $this->assertArrayHasKey('moving_fn', $aggregation); + $this->assertEquals('bucket.path', $aggregation['moving_fn']['buckets_path']); + $this->assertEquals('testScript', $aggregation['moving_fn']['script']); + $this->assertEquals(20, $aggregation['moving_fn']['window']); + $this->assertEquals(PipelineInterface::GAP_POLICY_INSERT_ZEROS, $aggregation['moving_fn']['gap_policy']); + } + + /** + * Test an exception is thrown when using the bucket selector pipeline with another pipeline type. + */ + public function testInvalidPipelineBuild(): void + { + $pipelineBuilder = $this->getPipelineBuilder(); + $this->expectExceptionMessage('Query builder : invalid aggregation type invalidType.'); + $this->expectException(\InvalidArgumentException::class); + $pipeline = $this->getMockBuilder(PipelineInterface::class)->getMock(); + $pipeline->method('getType')->willReturn('invalidType'); + + $pipelineBuilder->buildPipeline($pipeline); + } + + /** + * Aggregation builder used in tests. + * + * @return MovingFunctionBuilder + */ + private function getPipelineBuilder() + { + return new MovingFunctionBuilder(); + } +} diff --git a/src/module-elasticsuite-tracker/Model/Event/Processor/MapPageIdentifier.php b/src/module-elasticsuite-tracker/Model/Event/Processor/MapPageIdentifier.php index d95409156..01dc15aa9 100644 --- a/src/module-elasticsuite-tracker/Model/Event/Processor/MapPageIdentifier.php +++ b/src/module-elasticsuite-tracker/Model/Event/Processor/MapPageIdentifier.php @@ -31,6 +31,19 @@ class MapPageIdentifier implements EventProcessorInterface 'multishipping_checkout_shipping' => 'checkout_index_index', ]; + /** + * @var array + */ + private $mapping = []; + + /** + * @param array $mapping an additional mapping of pages identifiers (coming from the DI) + */ + public function __construct($mapping = []) + { + $this->mapping = array_merge_recursive(self::MAPPING_REPLACE_IDENTIFIER, $mapping); + } + /** * {@inheritDoc} */ @@ -38,8 +51,8 @@ public function process($eventData) { if (isset($eventData['page']['type']['identifier'])) { $pageIdentifier = $eventData['page']['type']['identifier']; - if (isset(self::MAPPING_REPLACE_IDENTIFIER[$pageIdentifier])) { - $eventData['page']['type']['identifier'] = self::MAPPING_REPLACE_IDENTIFIER[$pageIdentifier]; + if (isset($this->mapping[$pageIdentifier])) { + $eventData['page']['type']['identifier'] = $this->mapping[$pageIdentifier]; } } diff --git a/src/module-elasticsuite-tracker/etc/di.xml b/src/module-elasticsuite-tracker/etc/di.xml index 0c1ffe92e..ef6066da5 100644 --- a/src/module-elasticsuite-tracker/etc/di.xml +++ b/src/module-elasticsuite-tracker/etc/di.xml @@ -122,4 +122,12 @@ + + + + + checkout_onepage_success + + +