Skip to content

Commit 040b212

Browse files
committed
MC-30257: Price of a Bundle Product is calculated incorrectly at the product page
1 parent 87b0a4b commit 040b212

File tree

3 files changed

+104
-12
lines changed

3 files changed

+104
-12
lines changed

app/code/Magento/Bundle/view/base/web/js/price-bundle.js

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ define([
2828
controlContainer: 'dd', // should be eliminated
2929
priceFormat: {},
3030
isFixedPrice: false,
31-
optionTierPricesBlocksSelector: '#option-tier-prices-{1} [data-role="selection-tier-prices"]'
31+
optionTierPricesBlocksSelector: '#option-tier-prices-{1} [data-role="selection-tier-prices"]',
32+
isOptionsInitialized: false
3233
};
3334

3435
$.widget('mage.priceBundle', {
@@ -53,20 +54,37 @@ define([
5354
priceBox = $(this.options.priceBoxSelector, form),
5455
qty = $(this.options.qtyFieldSelector, form);
5556

56-
if (priceBox.data('magePriceBox') &&
57-
priceBox.priceBox('option') &&
58-
priceBox.priceBox('option').priceConfig
59-
) {
60-
if (priceBox.priceBox('option').priceConfig.optionTemplate) {
61-
this._setOption('optionTemplate', priceBox.priceBox('option').priceConfig.optionTemplate);
57+
this._updatePriceBox();
58+
priceBox.on('price-box-initialized', this._updatePriceBox.bind(this));
59+
options.on('change', this._onBundleOptionChanged.bind(this));
60+
qty.on('change', this._onQtyFieldChanged.bind(this));
61+
},
62+
63+
/**
64+
* Update price box config with bundle option prices
65+
* @private
66+
*/
67+
_updatePriceBox: function () {
68+
var form = this.element,
69+
options = $(this.options.productBundleSelector, form),
70+
priceBox = $(this.options.priceBoxSelector, form);
71+
72+
if (!this.options.isOptionsInitialized) {
73+
if (priceBox.data('magePriceBox') &&
74+
priceBox.priceBox('option') &&
75+
priceBox.priceBox('option').priceConfig
76+
) {
77+
if (priceBox.priceBox('option').priceConfig.optionTemplate) { //eslint-disable-line max-depth
78+
this._setOption('optionTemplate', priceBox.priceBox('option').priceConfig.optionTemplate);
79+
}
80+
this._setOption('priceFormat', priceBox.priceBox('option').priceConfig.priceFormat);
81+
priceBox.priceBox('setDefault', this.options.optionConfig.prices);
82+
this.options.isOptionsInitialized = true;
6283
}
63-
this._setOption('priceFormat', priceBox.priceBox('option').priceConfig.priceFormat);
64-
priceBox.priceBox('setDefault', this.options.optionConfig.prices);
84+
this._applyOptionNodeFix(options);
6585
}
66-
this._applyOptionNodeFix(options);
6786

68-
options.on('change', this._onBundleOptionChanged.bind(this));
69-
qty.on('change', this._onQtyFieldChanged.bind(this));
87+
return this;
7088
},
7189

7290
/**

app/code/Magento/Catalog/view/base/web/js/price-box.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ define([
4949

5050
box.on('reloadPrice', this.reloadPrice.bind(this));
5151
box.on('updatePrice', this.onUpdatePrice.bind(this));
52+
box.trigger('price-box-initialized');
5253
},
5354

5455
/**
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
define([
7+
'jquery',
8+
'Magento_Bundle/js/price-bundle',
9+
'Magento_Catalog/js/price-box'
10+
], function ($) {
11+
'use strict';
12+
13+
describe('Magento_Bundle/js/price-bundle', function () {
14+
15+
var htmlContainer;
16+
17+
beforeEach(function () {
18+
htmlContainer = $('<div class="price-final_price" data-role="priceBox"><ul class="price-box"></ul></div>');
19+
});
20+
21+
afterEach(function () {
22+
htmlContainer.remove();
23+
});
24+
25+
it('Widget extends jQuery object.', function () {
26+
expect($.fn.priceBundle).toBeDefined();
27+
});
28+
29+
it('Check _updatePriceBox method call.', function () {
30+
31+
spyOn($.mage.priceBundle.prototype, '_updatePriceBox');
32+
33+
htmlContainer.priceBundle();
34+
35+
expect($.mage.priceBundle.prototype._updatePriceBox).toEqual(jasmine.any(Function));
36+
expect($.mage.priceBundle.prototype._updatePriceBox).toHaveBeenCalledTimes(1);
37+
});
38+
39+
it('Check _updatePriceBox method call after priceBox was initialized.', function () {
40+
spyOn($.mage.priceBundle.prototype, '_updatePriceBox').and.callThrough();
41+
htmlContainer.priceBundle();
42+
$('.price-box', htmlContainer).priceBox();
43+
expect($.mage.priceBundle.prototype._updatePriceBox).toEqual(jasmine.any(Function));
44+
expect($.mage.priceBundle.prototype._updatePriceBox).toHaveBeenCalledTimes(2);
45+
});
46+
47+
it('Check _applyOptionNodeFix method doesn\'t call after priceBox initialization.', function () {
48+
var optionConfig = {
49+
optionConfig: {
50+
prices: {}
51+
}
52+
},
53+
priceConfig = {
54+
priceConfig: 10
55+
};
56+
57+
spyOn($.mage.priceBundle.prototype, '_applyOptionNodeFix').and.callThrough();
58+
htmlContainer.priceBundle(optionConfig);
59+
$('.price-box', htmlContainer).priceBox(priceConfig);
60+
$('.price-box', htmlContainer).trigger('price-box-initialized');
61+
expect($.mage.priceBundle.prototype._applyOptionNodeFix).toEqual(jasmine.any(Function));
62+
expect($.mage.priceBundle.prototype._applyOptionNodeFix).toHaveBeenCalledTimes(2);
63+
});
64+
65+
it('Check _updatePriceBox method call before priceBox was initialized.', function () {
66+
spyOn($.mage.priceBundle.prototype, '_updatePriceBox').and.callThrough();
67+
$('.price-box', htmlContainer).priceBox();
68+
htmlContainer.priceBundle();
69+
expect($.mage.priceBundle.prototype._updatePriceBox).toEqual(jasmine.any(Function));
70+
expect($.mage.priceBundle.prototype._updatePriceBox).toHaveBeenCalledTimes(1);
71+
});
72+
});
73+
});

0 commit comments

Comments
 (0)