6 declare(strict_types=1);
11 use PHPUnit_Framework_MockObject_MockObject as MockObject;
37 private $bundleOptions;
42 private $baseCalculator;
47 private $objectManagerHelper;
52 private $saleableItemMock;
57 private $bundleCalculatorMock;
62 private $selectionFactoryMock;
67 private $amountFactory;
72 private $priceInfoMock;
76 $this->priceInfoMock = $this->getMockBuilder(BasePriceInfo::class)
77 ->disableOriginalConstructor()
79 $this->saleableItemMock = $this->getMockBuilder(Product::class)
80 ->disableOriginalConstructor()
82 $priceCurrency = $this->getMockBuilder(PriceCurrencyInterface::class)->getMock();
83 $priceCurrency->expects($this->any())->method(
'round')->willReturnArgument(0);
85 $this->selectionFactoryMock = $this->getMockBuilder(BundleSelectionFactory::class)
86 ->disableOriginalConstructor()
88 $this->amountFactory = $this->getMockBuilder(AmountFactory::class)
89 ->disableOriginalConstructor()
91 $factoryCallback = $this->returnCallback(
92 function ($fullAmount, $adjustments) {
93 return $this->createAmountMock([
'amount' => $fullAmount,
'adjustmentAmounts' => $adjustments]);
96 $this->amountFactory->expects($this->any())->method(
'create')->will($factoryCallback);
97 $this->baseCalculator = $this->getMockBuilder(AdjustmentCalculator::class)
98 ->disableOriginalConstructor()
101 $taxData = $this->getMockBuilder(TaxHelperData::class)
102 ->disableOriginalConstructor()
105 $this->bundleCalculatorMock = $this->getMockBuilder(BundleAdjustmentCalculator::class)
106 ->setConstructorArgs(
107 [$this->baseCalculator, $this->amountFactory, $this->selectionFactoryMock, $taxData, $priceCurrency]
109 ->setMethods([
'getOptionsAmount'])
111 $this->objectManagerHelper =
new ObjectManagerHelper($this);
112 $this->bundleOptions = $this->objectManagerHelper->getObject(
113 BundleOptions::class,
115 'calculator' => $this->bundleCalculatorMock,
116 'bundleSelectionFactory' => $this->selectionFactoryMock,
130 $this->bundleOptions->getOptions($this->saleableItemMock);
131 $this->assertSame(
$selectionCollection, $this->bundleOptions->getOptions($this->saleableItemMock));
141 $this->saleableItemMock->expects($this->atLeastOnce())
142 ->method(
'getStoreId')
144 $priceTypeMock = $this->getMockBuilder(BundleProductType::class)
145 ->disableOriginalConstructor()
147 $priceTypeMock->expects($this->atLeastOnce())
148 ->method(
'setStoreFilter')
149 ->with(1, $this->saleableItemMock)
152 $priceTypeMock->expects($this->atLeastOnce())
153 ->method(
'getOptionsIds')
154 ->with($this->saleableItemMock)
156 $priceTypeMock->expects($this->atLeastOnce())
157 ->method(
'getSelectionsCollection')
160 $collection = $this->getMockBuilder(BundleOptionCollection::class)
161 ->disableOriginalConstructor()
164 ->method(
'appendSelections')
167 $priceTypeMock->expects($this->atLeastOnce())
168 ->method(
'getOptionsCollection')
169 ->with($this->saleableItemMock)
171 $this->saleableItemMock->expects($this->atLeastOnce())
172 ->method(
'getTypeInstance')
173 ->willReturn($priceTypeMock);
199 $selection = $this->createPartialMock(Product::class, [
'getSelectionQty',
'__wakeup']);
200 $amountInterfaceMock = $this->getMockBuilder(AmountInterface::class)
201 ->getMockForAbstractClass();
202 $amountInterfaceMock->expects($this->once())
204 ->willReturn($selectionAmount);
205 $selection->expects($this->once())
206 ->method(
'getSelectionQty')
207 ->willReturn($selectionQty);
208 $priceMock = $this->getMockBuilder(BundleSelectionPrice::class)
209 ->disableOriginalConstructor()
211 $priceMock->expects($this->once())
212 ->method(
'getAmount')
213 ->willReturn($amountInterfaceMock);
214 $this->selectionFactoryMock->expects($this->once())
216 ->with($this->saleableItemMock, $selection, $selectionQty)
217 ->willReturn($priceMock);
218 $optionSelectionAmount = $this->bundleOptions->getOptionSelectionAmount(
219 $this->saleableItemMock,
223 $this->assertSame($selectionAmount, $optionSelectionAmount->getValue());
243 private function createAmountMock(array $amountData)
246 $amount = $this->getMockBuilder(BaseAmount::class)
247 ->disableOriginalConstructor()
249 $amount->expects($this->any())->method(
'getAdjustmentAmounts')
250 ->willReturn($amountData[
'adjustmentAmounts'] ?? []);
251 $amount->expects($this->any())->method(
'getValue')->willReturn($amountData[
'amount']);
262 private function createOptionMock(array
$optionData)
265 $option = $this->createPartialMock(BundleOption::class, [
'isMultiSelection',
'__wakeup']);
266 $option->expects($this->any())->method(
'isMultiSelection')
269 foreach (
$optionData[
'selections'] as $selectionData) {
270 $selections[] = $this->createSelectionMock($selectionData);
275 $option->setData(
'selections', $selections);
286 private function createSelectionMock(array $selectionData)
288 $selection = $this->getMockBuilder(Product::class)
289 ->setMethods([
'isSalable',
'getAmount',
'getQuantity',
'getProduct',
'__wakeup'])
290 ->disableOriginalConstructor()
294 $selection->expects($this->any())->method(
'isSalable')->willReturn(
true);
295 foreach ($selectionData[
'data'] as $key =>
$value) {
296 $selection->setData($key,
$value);
298 $amountMock = $this->createAmountMock($selectionData[
'amount']);
299 $selection->expects($this->any())->method(
'getAmount')->willReturn($amountMock);
300 $selection->expects($this->any())->method(
'getQuantity')->willReturn(1);
302 $innerProduct = $this->getMockBuilder(Product::class)
303 ->setMethods([
'getSelectionCanChangeQty',
'__wakeup'])
304 ->disableOriginalConstructor()
306 $innerProduct->expects($this->any())->method(
'getSelectionCanChangeQty')->willReturn(
true);
307 $selection->expects($this->any())->method(
'getProduct')->willReturn($innerProduct);
319 public function testCalculation(array $optionList, array $expected)
322 $this->saleableItemMock->expects($this->any())->method(
'getStoreId')->willReturn(
$storeId);
323 $this->selectionFactoryMock->expects($this->any())->method(
'create')->willReturnArgument(1);
325 $this->baseCalculator->expects($this->atLeastOnce())->method(
'getAmount')
326 ->willReturn($this->createAmountMock([
'amount' => 0.]));
333 $optionsCollection = $this->getMockBuilder(BundleOptionCollection::class)
334 ->disableOriginalConstructor()
336 $optionsCollection->expects($this->atLeastOnce())->method(
'appendSelections')->willReturn(
$options);
339 $typeMock = $this->getMockBuilder(BundleProductType::class)
340 ->disableOriginalConstructor()
342 $typeMock->expects($this->any())->method(
'setStoreFilter')
343 ->with(
$storeId, $this->saleableItemMock);
344 $typeMock->expects($this->any())->method(
'getOptionsCollection')
345 ->with($this->saleableItemMock)
346 ->willReturn($optionsCollection);
347 $this->saleableItemMock->expects($this->any())->method(
'getTypeInstance')->willReturn($typeMock);
349 $this->assertEquals($expected[
'min'], $this->bundleOptions->calculateOptions($this->saleableItemMock));
350 $this->assertEquals($expected[
'max'], $this->bundleOptions->calculateOptions($this->saleableItemMock,
false));
363 'isMultiSelection' =>
false,
365 'title' =>
'test option 1',
366 'default_title' =>
'test option 1',
374 'data' => [
'price' => 70.],
375 'amount' => [
'amount' => 70],
378 'data' => [
'price' => 80.],
379 'amount' => [
'amount' => 80],
382 'data' => [
'price' => 50.],
383 'amount' => [
'amount' => 50],
389 'isMultiSelection' =>
false,
391 'title' =>
'test option 2',
392 'default_title' =>
'test option 2',
400 'data' => [
'value' => 20.],
401 'amount' => [
'amount' => 20],
407 'isMultiSelection' =>
true,
409 'title' =>
'test option 3',
410 'default_title' =>
'test option 3',
418 'data' => [
'price' => 40.],
419 'amount' => [
'amount' => 40],
422 'data' => [
'price' => 20.],
423 'amount' => [
'amount' => 20],
426 'data' => [
'price' => 60.],
427 'amount' => [
'amount' => 60],
433 'isMultiSelection' =>
true,
435 'title' =>
'test option 3',
436 'default_title' =>
'test option 3',
445 'expected' => [
'min' => 70,
'max' => 220],
testGetOptions(array $selectionCollection)
getTestDataForCalculation()
testGetOptionSelectionAmount(float $selectionQty, $selectionAmount, bool $useRegularPrice)
selectionAmountDataProvider()