Skip to content

Commit 9c0f4b4

Browse files
committed
AC-14607: Wishlist count not displayed on homepage/other pages except wishlist page in customer menu
fix: Optimize wishlist count display for cached pages Use manual DOM updates as primary mechanism since Knockout.js data binding is broken on cached pages. Ensures wishlist count displays correctly on all page types. Test coverage for the wishlist JS file.
1 parent fab20b0 commit 9c0f4b4

File tree

2 files changed

+188
-17
lines changed
  • app/code/Magento/Wishlist/view/frontend/web/js/view
  • dev/tests/js/jasmine/tests/app/code/Magento/Wishlist/view/frontend/web/js/view

2 files changed

+188
-17
lines changed

app/code/Magento/Wishlist/view/frontend/web/js/view/wishlist.js

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
define([
77
'uiComponent',
88
'Magento_Customer/js/customer-data',
9-
'underscore'
10-
], function (Component, customerData, _) {
9+
'underscore',
10+
'jquery'
11+
], function (Component, customerData, _, $) {
1112
'use strict';
1213

1314
var wishlistReloaded = false;
@@ -18,6 +19,7 @@ define([
1819
this._super();
1920
this.wishlist = customerData.get('wishlist');
2021
this.company = customerData.get('company');
22+
2123
if (!wishlistReloaded
2224
&& !_.isEmpty(this.wishlist())
2325
// Expired section names are reloaded on page load.
@@ -32,6 +34,91 @@ define([
3234
customerData.reload(['wishlist'], false);
3335
wishlistReloaded = true;
3436
}
37+
38+
// Ensure wishlist data is loaded on initialization
39+
this.ensureWishlistDataLoaded();
40+
41+
// Always try depersonalization for cached pages
42+
this.handleDepersonalization();
43+
},
44+
45+
/**
46+
* Ensure wishlist data is loaded
47+
*/
48+
ensureWishlistDataLoaded: function () {
49+
var self = this;
50+
51+
// Check if wishlist data is empty
52+
if (_.isEmpty(this.wishlist())) {
53+
// Load wishlist data
54+
customerData.reload(['wishlist'], false).done(function (data) {
55+
if (data.wishlist && data.wishlist.counter) {
56+
self.updateWishlistUI();
57+
}
58+
});
59+
} else {
60+
self.updateWishlistUI();
61+
}
62+
},
63+
64+
/**
65+
* Handle depersonalization scenarios
66+
*/
67+
handleDepersonalization: function () {
68+
var self = this,
69+
attempts = [1000, 3000, 5000]; // Try at 1s, 3s, and 5s
70+
71+
function onWishlistReloaded(data) {
72+
if (data.wishlist && data.wishlist.counter) {
73+
self.updateWishlistUI();
74+
}
75+
}
76+
77+
function reloadIfEmpty() {
78+
// Only reload if data is still empty
79+
if (_.isEmpty(self.wishlist())) {
80+
customerData.reload(['wishlist'], false).done(onWishlistReloaded);
81+
} else {
82+
self.updateWishlistUI();
83+
}
84+
}
85+
86+
// Listen for page load events to handle depersonalized pages
87+
$(function () {
88+
attempts.forEach(function (delay) {
89+
setTimeout(reloadIfEmpty, delay);
90+
});
91+
});
92+
},
93+
94+
/**
95+
* Update wishlist UI elements
96+
*/
97+
updateWishlistUI: function () {
98+
var wishlistData = this.wishlist(),
99+
selectors = [
100+
'.wishlist .counter.qty',
101+
'.customer-menu .wishlist .counter',
102+
'[data-bind*="wishlist"] .counter',
103+
'.link.wishlist .counter'
104+
];
105+
106+
if (wishlistData && wishlistData.counter) {
107+
// Try multiple selectors to find wishlist counters
108+
selectors.forEach(function (selector) {
109+
var counters = $(selector);
110+
111+
if (counters.length > 0) {
112+
counters.each(function () {
113+
var $counter = $(this);
114+
115+
if ($counter.text() !== wishlistData.counter) {
116+
$counter.text(wishlistData.counter);
117+
}
118+
});
119+
}
120+
});
121+
}
35122
}
36123
});
37124
});

dev/tests/js/jasmine/tests/app/code/Magento/Wishlist/view/frontend/web/js/view/wishlist.test.js

Lines changed: 99 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,61 +50,145 @@ define([
5050
injector.clean();
5151
injector.remove();
5252
delete window.checkout;
53-
} catch (e) {}
53+
} catch (e) { // eslint-disable-line no-unused-vars
54+
// Ignore cleanup errors
55+
}
5456
}
5557

56-
async function loadWishlistComponent() {
58+
function loadWishlistComponent() {
5759
return new Promise(resolve => {
58-
injector.require(['Magento_Wishlist/js/view/wishlist'], async function (WishlistComponent) {
60+
injector.require(['Magento_Wishlist/js/view/wishlist'], function (WishlistComponent) {
5961
wishlistComponent = new WishlistComponent();
6062
resolve();
6163
});
6264
});
6365
}
6466

65-
beforeEach(async function () {
67+
beforeEach(function (done) {
6668
setupInjector();
67-
await loadWishlistComponent();
69+
loadWishlistComponent().then(function () {
70+
done();
71+
});
6872
});
6973

7074
afterEach(function () {
7175
cleanupInjector();
7276
});
7377

7478
describe('Initialization', function () {
75-
it('should call customerData.get with "wishlist"', async function () {
79+
it('should call customerData.get with "wishlist"', function () {
7680
expect(mockCustomerData.get).toHaveBeenCalledWith('wishlist');
7781
});
7882

79-
it('should call customerData.get with "company"', async function () {
83+
it('should call customerData.get with "company"', function () {
8084
expect(mockCustomerData.get).toHaveBeenCalledWith('company');
8185
});
8286

83-
it('should invalidate wishlist if storeIds do not match', async function () {
87+
it('should invalidate wishlist if storeIds do not match', function () {
8488
window.checkout = { storeId: 2 };
85-
await wishlistComponent.initialize();
89+
wishlistComponent.initialize();
8690
expect(mockCustomerData.invalidate).toHaveBeenCalledWith(['wishlist']);
8791
});
8892

89-
it('should not reload wishlist if storeIds match and company is disabled', async function () {
93+
it('should not reload wishlist if storeIds match and company is disabled', function () {
9094
window.checkout = { storeId: 1 };
9195
mockCompany.is_enabled = false;
92-
await wishlistComponent.initialize();
96+
wishlistComponent.initialize();
9397
expect(mockCustomerData.reload).not.toHaveBeenCalledWith(['wishlist'], false);
9498
});
9599

96-
it('should reload wishlist if storeIds do not match', async function () {
100+
it('should reload wishlist if storeIds do not match', function () {
97101
window.checkout = { storeId: 2 };
98-
await wishlistComponent.initialize();
102+
wishlistComponent.initialize();
99103
expect(mockCustomerData.reload).toHaveBeenCalledWith(['wishlist'], false);
100104
});
101105

102-
it('should reload wishlist if storeIds match and company is enabled', async function () {
106+
it('should reload wishlist if storeIds match and company is enabled', function () {
103107
window.checkout = { storeId: 1 };
104108
mockCompany.is_enabled = true;
105-
await wishlistComponent.initialize();
109+
wishlistComponent.initialize();
106110
expect(mockCustomerData.reload).toHaveBeenCalledWith(['wishlist'], false);
107111
});
108112
});
113+
114+
describe('Core Methods', function () {
115+
it('should have ensureWishlistDataLoaded method', function () {
116+
expect(typeof wishlistComponent.ensureWishlistDataLoaded).toBe('function');
117+
});
118+
119+
it('should have handleDepersonalization method', function () {
120+
expect(typeof wishlistComponent.handleDepersonalization).toBe('function');
121+
});
122+
123+
it('should have updateWishlistUI method', function () {
124+
expect(typeof wishlistComponent.updateWishlistUI).toBe('function');
125+
});
126+
});
127+
128+
describe('Data Handling', function () {
129+
it('should have wishlist data available', function () {
130+
expect(wishlistComponent.wishlist).toBeDefined();
131+
expect(wishlistComponent.wishlist()).toEqual(mockWishlist);
132+
});
133+
134+
it('should have company data available', function () {
135+
expect(wishlistComponent.company).toBeDefined();
136+
expect(wishlistComponent.company()).toEqual(mockCompany);
137+
});
138+
139+
it('should handle empty wishlist data', function () {
140+
mockWishlist.counter = 0;
141+
expect(wishlistComponent.wishlist().counter).toBe(0);
142+
});
143+
});
144+
145+
describe('ensureWishlistDataLoaded', function () {
146+
it('should not call customerData.reload when wishlist has data', function () {
147+
mockWishlist.counter = 3;
148+
wishlistComponent.ensureWishlistDataLoaded();
149+
expect(mockCustomerData.reload).not.toHaveBeenCalled();
150+
});
151+
});
152+
153+
describe('handleDepersonalization', function () {
154+
it('should set up timeout attempts', function () {
155+
spyOn(window, 'setTimeout');
156+
wishlistComponent.handleDepersonalization();
157+
expect(window.setTimeout).toHaveBeenCalledTimes(1);
158+
});
159+
160+
it('should not call customerData.reload when wishlist has data', function () {
161+
// Reset mock and set wishlist to have data
162+
mockCustomerData.reload.calls.reset();
163+
mockWishlist.counter = 3;
164+
spyOn(window, 'setTimeout').and.callFake(function (callback) {
165+
callback();
166+
});
167+
wishlistComponent.handleDepersonalization();
168+
expect(mockCustomerData.reload).not.toHaveBeenCalled();
169+
});
170+
});
171+
172+
describe('updateWishlistUI', function () {
173+
it('should execute without errors when called', function () {
174+
expect(function () {
175+
wishlistComponent.updateWishlistUI();
176+
}).not.toThrow();
177+
});
178+
179+
it('should handle wishlist data with counter', function () {
180+
mockWishlist.counter = '5 items';
181+
expect(function () {
182+
wishlistComponent.updateWishlistUI();
183+
}).not.toThrow();
184+
});
185+
186+
it('should handle wishlist data without counter', function () {
187+
mockWishlist.counter = null;
188+
expect(function () {
189+
wishlistComponent.updateWishlistUI();
190+
}).not.toThrow();
191+
});
192+
});
109193
});
110194
});

0 commit comments

Comments
 (0)