Skip to content

Commit aefd8a7

Browse files
authored
Merge pull request #1663 from algolia/feat/MAGE-1084-multistore-replica-tests
MAGE-1084: Multistore Replicas tests
2 parents 4bf715d + e414a96 commit aefd8a7

File tree

5 files changed

+453
-160
lines changed

5 files changed

+453
-160
lines changed

Test/Integration/Config/MultiStoreConfigTest.php

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
use Algolia\AlgoliaSearch\Exceptions\AlgoliaException;
66
use Algolia\AlgoliaSearch\Helper\AlgoliaHelper;
77
use Algolia\AlgoliaSearch\Helper\ConfigHelper;
8+
use Algolia\AlgoliaSearch\Test\Integration\Config\Traits\ConfigAssertionsTrait;
89
use Algolia\AlgoliaSearch\Test\Integration\MultiStoreTestCase;
910

1011
/**
1112
* @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php
1213
*/
1314
class MultiStoreConfigTest extends MultiStoreTestCase
1415
{
16+
use ConfigAssertionsTrait;
1517

1618
const ADDITIONAL_ATTRIBUTE = 'additional_attribute';
1719

@@ -30,11 +32,13 @@ public function testMultiStoreIndicesCreation()
3032

3133
$defaultStore = $this->storeRepository->get('default');
3234
$fixtureSecondStore = $this->storeRepository->get('fixture_second_store');
35+
$fixtureThirdStore = $this->storeRepository->get('fixture_third_store');
3336

3437
$indicesCreatedByTest = 0;
3538

36-
$indicesCreatedByTest += $this->countStoreIndices($defaultStore->getId());
37-
$indicesCreatedByTest += $this->countStoreIndices($fixtureSecondStore->getId());
39+
$indicesCreatedByTest += $this->countStoreIndices($defaultStore);
40+
$indicesCreatedByTest += $this->countStoreIndices($fixtureSecondStore);
41+
$indicesCreatedByTest += $this->countStoreIndices($fixtureThirdStore);
3842

3943
// Check that the configuration created the appropriate number of indices (7 (4 mains + 3 replicas per store => 3*7=21)
4044
$this->assertEquals(21, $indicesCreatedByTest);
@@ -121,28 +125,6 @@ public function testMultiStoreIndicesCreation()
121125
$this->assertEquals(1, $fixtureProductIndexRules['nbHits']);
122126
}
123127

124-
/**
125-
* @param int|null $storeId
126-
* @return int
127-
* @throws AlgoliaException
128-
*/
129-
protected function countStoreIndices(int $storeId = null): int
130-
{
131-
$indices = $this->algoliaHelper->listIndexes($storeId);
132-
133-
$indicesCreatedByTest = 0;
134-
135-
foreach ($indices['items'] as $index) {
136-
$name = $index['name'];
137-
138-
if (mb_strpos($name, $this->indexPrefix) === 0) {
139-
$indicesCreatedByTest++;
140-
}
141-
}
142-
143-
return $indicesCreatedByTest;
144-
}
145-
146128
protected function tearDown(): void
147129
{
148130
parent::tearDown();
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Algolia\AlgoliaSearch\Test\Integration\Config\Traits;
4+
5+
use Algolia\AlgoliaSearch\Exceptions\AlgoliaException;
6+
use Magento\Store\Api\Data\StoreInterface;
7+
8+
trait ConfigAssertionsTrait
9+
{
10+
/**
11+
* @param StoreInterface|null $store
12+
* @return int
13+
* @throws AlgoliaException
14+
*/
15+
protected function countStoreIndices(StoreInterface $store = null): int
16+
{
17+
$indices = $this->algoliaHelper->listIndexes($store->getId());
18+
19+
$indicesCreatedByTest = 0;
20+
21+
foreach ($indices['items'] as $index) {
22+
$name = $index['name'];
23+
24+
if (mb_strpos($name, $this->indexPrefix . $store->getCode()) === 0) {
25+
$indicesCreatedByTest++;
26+
}
27+
}
28+
29+
return $indicesCreatedByTest;
30+
}
31+
}
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
<?php
2+
3+
namespace Algolia\AlgoliaSearch\Test\Integration\Product;
4+
5+
use Algolia\AlgoliaSearch\Api\Product\ReplicaManagerInterface;
6+
use Algolia\AlgoliaSearch\Console\Command\ReplicaRebuildCommand;
7+
use Algolia\AlgoliaSearch\Console\Command\ReplicaSyncCommand;
8+
use Algolia\AlgoliaSearch\Helper\ConfigHelper;
9+
use Algolia\AlgoliaSearch\Service\Product\SortingTransformer;
10+
use Algolia\AlgoliaSearch\Test\Integration\Config\Traits\ConfigAssertionsTrait;
11+
use Algolia\AlgoliaSearch\Test\Integration\MultiStoreTestCase;
12+
use Algolia\AlgoliaSearch\Test\Integration\Product\Traits\ReplicaAssertionsTrait;
13+
use Magento\Framework\Serialize\SerializerInterface;
14+
use Magento\Store\Api\Data\StoreInterface;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
use Symfony\Component\Console\Output\OutputInterface;
17+
18+
/**
19+
* @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php
20+
*/
21+
class MultiStoreReplicaTest extends MultiStoreTestCase
22+
{
23+
use ReplicaAssertionsTrait;
24+
use ConfigAssertionsTrait;
25+
26+
const COLOR_ATTR = 'color';
27+
const CREATED_AT_ATTR = 'created_at';
28+
const ASC_DIR = 'asc';
29+
const DESC_DIR = 'desc';
30+
31+
protected ?ReplicaManagerInterface $replicaManager = null;
32+
33+
protected ?SerializerInterface $serializer = null;
34+
35+
protected function setUp(): void
36+
{
37+
parent::setUp();
38+
$this->replicaManager = $this->objectManager->get(ReplicaManagerInterface::class);
39+
$this->serializer = $this->objectManager->get(SerializerInterface::class);
40+
41+
$stores = $this->storeManager->getStores();
42+
43+
foreach ($stores as $store) {
44+
$this->setupStore($store, true);
45+
}
46+
}
47+
48+
public function testMultiStoreReplicaConfig()
49+
{
50+
$defaultStore = $this->storeRepository->get('default');
51+
$fixtureSecondStore = $this->storeRepository->get('fixture_second_store');
52+
53+
// Check replica config for created_at desc
54+
$this->checkReplicaIsStandard($defaultStore, self::CREATED_AT_ATTR, self::DESC_DIR);
55+
$this->checkReplicaIsStandard($fixtureSecondStore, self::CREATED_AT_ATTR, self::DESC_DIR);
56+
57+
// add color asc sorting (virtual on a single store)
58+
$this->addSortingByStore($defaultStore, self::COLOR_ATTR, self::ASC_DIR);
59+
$this->addSortingByStore($fixtureSecondStore, self::COLOR_ATTR, self::ASC_DIR,true);
60+
61+
// Check replica config for color asc
62+
$this->checkReplicaIsStandard($defaultStore, self::COLOR_ATTR, self::ASC_DIR);
63+
$this->checkReplicaIsVirtual($fixtureSecondStore, self::COLOR_ATTR, self::ASC_DIR);
64+
}
65+
66+
public function testCustomerGroupsConfig()
67+
{
68+
$defaultStore = $this->storeRepository->get('default');
69+
$fixtureSecondStore = $this->storeRepository->get('fixture_second_store');
70+
$fixtureThirdStore = $this->storeRepository->get('fixture_third_store');
71+
72+
// Enable customer groups for second fixture store and save configuration
73+
$this->setConfig( ConfigHelper::CUSTOMER_GROUPS_ENABLE, 1, $fixtureSecondStore->getCode());
74+
$this->indicesConfigurator->saveConfigurationToAlgolia($fixtureSecondStore->getId());
75+
$this->algoliaHelper->waitLastTask($fixtureSecondStore->getId());
76+
77+
// 7 indices for default store and third store:
78+
// - 1 for categories
79+
// - 1 for pages
80+
// - 1 for suggestions
81+
// - 4 for products (1 main and 3 for sorting replicas)
82+
$this->assertEquals(7, $this->countStoreIndices($defaultStore));
83+
$this->assertEquals(7, $this->countStoreIndices($fixtureThirdStore));
84+
85+
// 13 indices for second store:
86+
// - 1 for categories
87+
// - 1 for pages
88+
// - 1 for suggestions
89+
// - 10 for products (1 main and 9 replicas (2 prices sortings * 4 customer groups + 1 other sorting (created_at))
90+
$this->assertEquals(13, $this->countStoreIndices($fixtureSecondStore));
91+
}
92+
93+
public function testReplicaCommands()
94+
{
95+
$defaultStore = $this->storeRepository->get('default');
96+
$fixtureSecondStore = $this->storeRepository->get('fixture_second_store');
97+
98+
$defaultIndexName = $this->indexPrefix . $defaultStore->getCode() . '_products';
99+
$fixtureIndexName = $this->indexPrefix . $fixtureSecondStore->getCode() . '_products';
100+
101+
// Update store config for fixture only
102+
$this->mockSortUpdate('price', 'desc', ['virtualReplica' => 1], $fixtureSecondStore);
103+
104+
$defaultSortings = $this->objectManager->get(SortingTransformer::class)->getSortingIndices(
105+
$defaultStore->getId(),
106+
null,
107+
null,
108+
true
109+
);
110+
111+
$fixtureSortings = $this->objectManager->get(SortingTransformer::class)->getSortingIndices(
112+
$fixtureSecondStore->getId(),
113+
null,
114+
null,
115+
true
116+
);
117+
118+
// Executing commands - Start
119+
$syncCmd = $this->objectManager->get(ReplicaSyncCommand::class);
120+
$this->mockProperty($syncCmd, 'output', OutputInterface::class);
121+
$syncCmd->syncReplicas();
122+
$this->algoliaHelper->waitLastTask($defaultStore->getId());
123+
$this->algoliaHelper->waitLastTask($fixtureSecondStore->getId());
124+
125+
$rebuildCmd = $this->objectManager->get(ReplicaRebuildCommand::class);
126+
$this->invokeMethod(
127+
$rebuildCmd,
128+
'execute',
129+
[
130+
$this->createMock(InputInterface::class),
131+
$this->createMock(OutputInterface::class)
132+
]
133+
);
134+
$this->algoliaHelper->waitLastTask($defaultStore->getId());
135+
$this->algoliaHelper->waitLastTask($fixtureSecondStore->getId());
136+
// Executing commands - End
137+
138+
$currentDefaultSettings = $this->algoliaHelper->getSettings($defaultIndexName, $defaultStore->getId());
139+
$currentFixtureSettings = $this->algoliaHelper->getSettings($fixtureIndexName, $fixtureSecondStore->getId());
140+
141+
$this->assertArrayHasKey('replicas', $currentDefaultSettings);
142+
$this->assertArrayHasKey('replicas', $currentFixtureSettings);
143+
144+
$defaultReplicas = $currentDefaultSettings['replicas'];
145+
$fixtureReplicas = $currentFixtureSettings['replicas'];
146+
147+
$this->assertEquals(count($defaultSortings), count($defaultReplicas));
148+
$this->assertEquals(count($fixtureSortings), count($fixtureReplicas));
149+
150+
$this->assertSortToReplicaConfigParity(
151+
$defaultIndexName,
152+
$defaultSortings,
153+
$defaultReplicas,
154+
$defaultStore->getId()
155+
);
156+
157+
$this->assertSortToReplicaConfigParity(
158+
$fixtureIndexName,
159+
$fixtureSortings,
160+
$fixtureReplicas,
161+
$fixtureSecondStore->getId()
162+
);
163+
}
164+
165+
protected function checkReplicaIsStandard(StoreInterface $store, $sortAttr, $sortDir)
166+
{
167+
$this->checkReplicaConfigByStore($store, $sortAttr, $sortDir, 'standard');
168+
}
169+
170+
protected function checkReplicaIsVirtual(StoreInterface $store, $sortAttr, $sortDir)
171+
{
172+
$this->checkReplicaConfigByStore($store, $sortAttr, $sortDir, 'virtual');
173+
}
174+
175+
protected function checkReplicaConfigByStore(StoreInterface $store, $sortAttr, $sortDir, $type)
176+
{
177+
$indexName = $this->indexPrefix . $store->getCode() . '_products';
178+
179+
$settings = $this->algoliaHelper->getSettings($indexName, $store->getId());
180+
181+
$this->assertArrayHasKey('replicas', $settings);
182+
183+
$replicaIndexName = $indexName . '_' . $sortAttr . '_' . $sortDir;
184+
185+
$type === 'virtual' ?
186+
$this->assertTrue($this->isVirtualReplica($settings['replicas'], $replicaIndexName)) :
187+
$this->assertTrue($this->isStandardReplica($settings['replicas'], $replicaIndexName));
188+
189+
$replicaSettings = $this->assertReplicaIndexExists($indexName, $replicaIndexName, $store->getId());
190+
191+
$type === 'virtual' ?
192+
$this->assertVirtualReplicaRanking($replicaSettings, "$sortDir($sortAttr)"):
193+
$this->assertStandardReplicaRanking($replicaSettings, "$sortDir($sortAttr)");
194+
}
195+
196+
protected function addSortingByStore(StoreInterface $store, $attr, $dir, $isVirtual = false)
197+
{
198+
$sorting = $this->configHelper->getSorting($store->getId());
199+
$newSorting = [
200+
'attribute' => $attr,
201+
'sort' => $dir,
202+
'sortLabel' => $attr,
203+
];
204+
205+
if ($isVirtual) {
206+
$newSorting['virtualReplica'] = 1;
207+
}
208+
209+
$sorting[] = $newSorting;
210+
211+
$this->setConfig(
212+
ConfigHelper::SORTING_INDICES,
213+
$this->serializer->serialize($sorting),
214+
$store->getCode()
215+
);
216+
217+
$this->assertSortingAttribute($attr, $dir);
218+
$this->indicesConfigurator->saveConfigurationToAlgolia($store->getId());
219+
$this->algoliaHelper->waitLastTask($store->getId());
220+
}
221+
222+
protected function resetAllSortings()
223+
{
224+
$stores = $this->storeManager->getStores();
225+
226+
foreach ($stores as $store) {
227+
$this->setConfig(
228+
ConfigHelper::SORTING_INDICES,
229+
$this->serializer->serialize([
230+
[
231+
'attribute' => 'price',
232+
'sort' => 'asc',
233+
'sortLabel' => 'Lowest Price'
234+
],
235+
[
236+
'attribute' => 'price',
237+
'sort' => 'desc',
238+
'sortLabel' => 'Highest Price'
239+
],
240+
[
241+
'attribute' => 'created_at',
242+
'sort' => 'desc',
243+
'sortLabel' => 'Newest first'
244+
]
245+
]),
246+
$store->getCode()
247+
);
248+
249+
$this->setConfig( ConfigHelper::CUSTOMER_GROUPS_ENABLE, 0, $store->getCode());
250+
}
251+
}
252+
253+
protected function tearDown(): void
254+
{
255+
$this->resetAllSortings();
256+
257+
parent::tearDown();
258+
}
259+
}

0 commit comments

Comments
 (0)