PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.21
ووسلام – همگام سازی ووکامرس و باسلام v1.10.21
1.10.21 1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 All 54 releases
sync-basalam / tests / Services / VariationUpdateRoutingTest.php

VariationUpdateRoutingTest.php in ووسلام – همگام سازی ووکامرس و باسلام 1.10.21, at tests/Services/VariationUpdateRoutingTest.php

209 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace {
4 if (!function_exists('esc_html')) {
5 function esc_html($value)
6 {
7 return (string) $value;
8 }
9 }
10
11 if (!function_exists('wc_get_product')) {
12 function wc_get_product($productId)
13 {
14 return $GLOBALS['sync_basalam_test_products'][$productId] ?? null;
15 }
16 }
17
18 if (!function_exists('get_option')) {
19 function get_option($name, $default = false)
20 {
21 return $GLOBALS['sync_basalam_test_options'][$name] ?? $default;
22 }
23 }
24
25 if (!function_exists('update_option')) {
26 function update_option($name, $value, $autoload = null)
27 {
28 $GLOBALS['sync_basalam_test_options'][$name] = $value;
29 return true;
30 }
31 }
32 }
33
34 namespace SyncBasalam\Services\Products {
35 if (!function_exists(__NAMESPACE__ . '\\syncBasalamContainer')) {
36 function syncBasalamContainer()
37 {
38 if (!isset($GLOBALS['sync_basalam_test_container'])) {
39 throw new \RuntimeException('The test service container has not been configured.');
40 }
41
42 return $GLOBALS['sync_basalam_test_container'];
43 }
44 }
45 }
46
47 namespace SyncBasalam\Tests\Services {
48 use PHPUnit\Framework\TestCase;
49 use ReflectionMethod;
50 use SyncBasalam\Services\Products\UpdateSingleProductService;
51
52 require_once dirname(__DIR__, 2) . '/includes/Admin/Settings/SettingsConfig.php';
53 require_once dirname(__DIR__, 2) . '/includes/Admin/Settings/SettingsManager.php';
54 require_once dirname(__DIR__, 2) . '/includes/Jobs/Exceptions/JobException.php';
55 require_once dirname(__DIR__, 2) . '/includes/Jobs/Exceptions/NonRetryableException.php';
56 require_once dirname(__DIR__, 2) . '/includes/Jobs/Exceptions/RetryableException.php';
57 require_once dirname(__DIR__, 2) . '/includes/Jobs/Exceptions/StaleVariationException.php';
58 require_once dirname(__DIR__, 2) . '/includes/Services/Products/UpdateProductVariationsService.php';
59 require_once dirname(__DIR__, 2) . '/includes/Services/Products/UpdateSingleProductService.php';
60
61 class VariationUpdateRoutingTest extends TestCase
62 {
63 protected function setUp(): void
64 {
65 $GLOBALS['sync_basalam_test_products'] = [];
66 $GLOBALS['sync_basalam_test_options'] = [];
67 $GLOBALS['sync_basalam_test_products'][7196] = new class {
68 public function is_type($type)
69 {
70 return $type === 'variable';
71 }
72 };
73 }
74
75 protected function tearDown(): void
76 {
77 unset(
78 $GLOBALS['sync_basalam_test_products'],
79 $GLOBALS['sync_basalam_test_options'],
80 $GLOBALS['sync_basalam_test_container']
81 );
82 }
83
84 public function testAllFieldsModeNeverUsesTheVariationEndpoint(): void
85 {
86 $this->withActiveVendor();
87 $this->withSettings(['sync_product_fields' => 'all']);
88
89 // Even fully connected variations stay inside the product PATCH.
90 self::assertFalse($this->shouldUpdateSeparately([
91 'variants' => [['id' => 43666032, 'primary_price' => 1, 'stock' => 1, 'properties' => []]],
92 ]));
93 }
94
95 public function testPriceStockModeNeverUsesTheVariationEndpoint(): void
96 {
97 $this->withActiveVendor();
98 $this->withSettings(['sync_product_fields' => 'price_stock']);
99
100 self::assertFalse($this->shouldUpdateSeparately([
101 'variants' => [['id' => 43666032, 'primary_price' => 1, 'stock' => 1]],
102 ]));
103 }
104
105 public function testCustomModeWithVariationFieldsUsesPerVariationRequests(): void
106 {
107 $this->withActiveVendor();
108 $this->withSettings([
109 'sync_product_fields' => 'custom',
110 'sync_product_field_variant_price' => 1,
111 ]);
112
113 self::assertTrue($this->shouldUpdateSeparately([
114 'variants' => [['id' => 43666032, 'primary_price' => 1, 'stock' => 1]],
115 ]));
116 }
117
118 public function testCustomModeWithoutVariationFieldsDoesNotUsePerVariationRequests(): void
119 {
120 $this->withActiveVendor();
121 $this->withSettings([
122 'sync_product_fields' => 'custom',
123 'sync_product_field_name' => 1,
124 ]);
125
126 self::assertFalse($this->shouldUpdateSeparately([
127 'variants' => [['id' => 43666032, 'primary_price' => 1, 'stock' => 1]],
128 ]));
129 }
130
131 public function testUnconnectedVariationFallsBackToTheProductRequest(): void
132 {
133 $this->withActiveVendor();
134 $this->withSettings([
135 'sync_product_fields' => 'custom',
136 'sync_product_field_variant_price' => 1,
137 ]);
138
139 self::assertFalse($this->shouldUpdateSeparately([
140 'variants' => [
141 ['id' => 43666032, 'primary_price' => 1, 'stock' => 1],
142 ['primary_price' => 2, 'stock' => 2], // no Basalam id yet
143 ],
144 ]));
145 }
146
147 public function testRestrictedVendorUsesTheProductRequest(): void
148 {
149 // A limited inactive vendor must also use one product PATCH. The
150 // restricted payload keeps unchanged properties for variant identity
151 // and UpdateSingleProductService removes the stored ids before send.
152 $this->withRestrictedVendor();
153 $this->withSettings(['sync_product_fields' => 'all']);
154
155 self::assertFalse($this->shouldUpdateSeparately([
156 'variants' => [['id' => 43666032, 'primary_price' => 1, 'stock' => 1, 'properties' => []]],
157 ]));
158 }
159
160 private function shouldUpdateSeparately(array $productData): bool
161 {
162 $service = new UpdateSingleProductService(new \stdClass(), new \stdClass(), new \stdClass());
163
164 $method = new ReflectionMethod(UpdateSingleProductService::class, 'shouldUpdateVariationsSeparately');
165 $method->setAccessible(true);
166
167 return $method->invoke($service, 7196, $productData);
168 }
169
170 private function withSettings(array $settings): void
171 {
172 $GLOBALS['sync_basalam_test_options']['sync_basalam_settings'] = $settings;
173 }
174
175 private function withActiveVendor(): void
176 {
177 $GLOBALS['sync_basalam_test_container'] = new class {
178 public function get($id)
179 {
180 return new class {
181 public function __call($method, $args)
182 {
183 return false; // shouldRestrictUpdateFields, canUpdate, ...
184 }
185 };
186 }
187 };
188 }
189
190 private function withRestrictedVendor(): void
191 {
192 $GLOBALS['sync_basalam_test_container'] = new class {
193 public function get($id)
194 {
195 return new class {
196 public function __call($method, $args)
197 {
198 // shouldRestrictUpdateFields() === true
199 if (strpos($method, 'shouldRestrict') === 0) return true;
200
201 return false;
202 }
203 };
204 }
205 };
206 }
207 }
208 }
209