Skip to content

Commit 37acc55

Browse files
committed
Merge remote-tracking branch 'origin/spartans_pr_26082025_AC-14607' into spartans_pr_29082025
2 parents 115d1a0 + 1306e6a commit 37acc55

File tree

3 files changed

+310
-2
lines changed

3 files changed

+310
-2
lines changed
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
2-
* Copyright © Magento, Inc. All rights reserved.
3-
* See COPYING.txt for license details.
2+
* Copyright 2011 Adobe
3+
* All Rights Reserved.
44
*/
55

66
var config = {
@@ -10,5 +10,12 @@ var config = {
1010
addToWishlist: 'Magento_Wishlist/js/add-to-wishlist',
1111
wishlistSearch: 'Magento_Wishlist/js/search'
1212
}
13+
},
14+
config: {
15+
mixins: {
16+
'Magento_Wishlist/js/view/wishlist': {
17+
'Magento_Wishlist/js/view/wishlist-mixin': true
18+
}
19+
}
1320
}
1421
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Copyright 2025 Adobe
3+
* All Rights Reserved.
4+
*/
5+
6+
define(['jquery', 'Magento_Customer/js/customer-data'], function ($, customerData) {
7+
'use strict';
8+
9+
return function (WishlistComponent) {
10+
return WishlistComponent.extend({
11+
initialize: function () {
12+
this._super();
13+
14+
const selector = '.wishlist .counter.qty, .customer-menu .wishlist .counter, .link.wishlist .counter',
15+
wishlist = customerData.get('wishlist');
16+
17+
wishlist.subscribe(function (updatedWishlist) {
18+
const counters = $(selector);
19+
20+
if (typeof updatedWishlist.counter !== 'undefined'
21+
&& updatedWishlist.counter !== null
22+
&& counters.length
23+
) {
24+
counters.text(updatedWishlist.counter);
25+
}
26+
if (updatedWishlist.counter === null) {
27+
counters.hide();
28+
}
29+
});
30+
31+
return this;
32+
}
33+
});
34+
};
35+
});
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
/**
2+
* Copyright 2025 Adobe
3+
* All Rights Reserved.
4+
*/
5+
6+
define([
7+
'jquery',
8+
'Magento_Customer/js/customer-data',
9+
'Magento_Wishlist/js/view/wishlist-mixin'
10+
], function ($, customerData, wishlistMixin) {
11+
'use strict';
12+
13+
describe('Magento_Wishlist/js/view/wishlist-mixin', function () {
14+
var WishlistComponent, mixin, customerDataMock, wishlistDataMock, subscribeCallback;
15+
16+
beforeEach(function () {
17+
// Mock customerData
18+
customerDataMock = {
19+
reload: jasmine.createSpy('reload'),
20+
get: jasmine.createSpy('get')
21+
};
22+
23+
// Helper function to set up subscribe callback
24+
function setupSubscribeCallback(callback) {
25+
subscribeCallback = callback;
26+
}
27+
28+
wishlistDataMock = {
29+
subscribe: jasmine.createSpy('subscribe').and.callFake(setupSubscribeCallback)
30+
};
31+
32+
customerDataMock.get.and.returnValue(wishlistDataMock);
33+
34+
// Mock the customerData module
35+
spyOn(customerData, 'reload').and.callFake(customerDataMock.reload);
36+
spyOn(customerData, 'get').and.callFake(customerDataMock.get);
37+
38+
// Create a proper mock WishlistComponent with extend method and _super
39+
WishlistComponent = function () {};
40+
WishlistComponent.prototype = {
41+
initialize: function () {
42+
return this;
43+
}
44+
};
45+
46+
// Add the extend method that Magento components typically have
47+
WishlistComponent.extend = function (extensions) {
48+
var ExtendedComponent = function () {},
49+
key,
50+
methodName,
51+
originalMethod;
52+
53+
ExtendedComponent.prototype = Object.create(WishlistComponent.prototype);
54+
55+
// Copy the extensions to the prototype
56+
for (key in extensions) {
57+
if (extensions.hasOwnProperty(key)) {
58+
ExtendedComponent.prototype[key] = extensions[key];
59+
}
60+
}
61+
62+
// Add the extend method to the new component
63+
ExtendedComponent.extend = WishlistComponent.extend;
64+
65+
// Add _super method for each extended method
66+
for (methodName in extensions) {
67+
if (!extensions.hasOwnProperty(methodName) || typeof extensions[methodName] !== 'function') {
68+
continue;
69+
}
70+
71+
originalMethod = WishlistComponent.prototype[methodName];
72+
if (!originalMethod) {
73+
continue;
74+
}
75+
76+
// Use IIFE to create proper closure for _super method
77+
(function (method) {
78+
ExtendedComponent.prototype['_super'] = function () {
79+
return method.apply(this, arguments);
80+
};
81+
})(originalMethod);
82+
}
83+
84+
return ExtendedComponent;
85+
};
86+
87+
// Apply the mixin
88+
mixin = wishlistMixin(WishlistComponent);
89+
});
90+
91+
describe('Initialization', function () {
92+
it('should call _super() during initialization', function () {
93+
var instance = new mixin();
94+
95+
spyOn(instance, '_super').and.callThrough();
96+
instance.initialize();
97+
98+
expect(instance._super).toHaveBeenCalled();
99+
});
100+
101+
it('should get wishlist data from customer data', function () {
102+
var instance = new mixin();
103+
104+
instance.initialize();
105+
expect(customerData.get).toHaveBeenCalledWith('wishlist');
106+
});
107+
108+
it('should return the instance after initialization', function () {
109+
var instance = new mixin(),
110+
result = instance.initialize();
111+
112+
expect(result).toBe(instance);
113+
});
114+
});
115+
116+
describe('Wishlist subscription', function () {
117+
it('should subscribe to wishlist data updates', function () {
118+
var instance = new mixin();
119+
120+
instance.initialize();
121+
expect(wishlistDataMock.subscribe).toHaveBeenCalledWith(jasmine.any(Function));
122+
});
123+
124+
it('should handle undefined counter gracefully', function () {
125+
var instance = new mixin();
126+
127+
instance.initialize();
128+
// Call with undefined counter
129+
expect(function () {
130+
subscribeCallback({ counter: undefined });
131+
}).not.toThrow();
132+
});
133+
134+
it('should handle null counter gracefully', function () {
135+
var instance = new mixin();
136+
137+
instance.initialize();
138+
// Call with null counter
139+
expect(function () {
140+
subscribeCallback({ counter: null });
141+
}).not.toThrow();
142+
});
143+
144+
it('should handle missing counter property gracefully', function () {
145+
var instance = new mixin();
146+
147+
instance.initialize();
148+
// Call with no counter property
149+
expect(function () {
150+
subscribeCallback({});
151+
}).not.toThrow();
152+
});
153+
});
154+
155+
describe('Subscription callback behavior', function () {
156+
it('should handle counter updates when counters exist', function () {
157+
var instance = new mixin();
158+
159+
instance.initialize();
160+
// Call with counter update
161+
expect(function () {
162+
subscribeCallback({ counter: 3 });
163+
}).not.toThrow();
164+
});
165+
166+
it('should handle string counter values', function () {
167+
var instance = new mixin();
168+
169+
instance.initialize();
170+
// Call with string counter
171+
expect(function () {
172+
subscribeCallback({ counter: '7' });
173+
}).not.toThrow();
174+
});
175+
176+
it('should handle zero counter value', function () {
177+
var instance = new mixin();
178+
179+
instance.initialize();
180+
// Call with zero counter
181+
expect(function () {
182+
subscribeCallback({ counter: 0 });
183+
}).not.toThrow();
184+
});
185+
186+
it('should handle multiple counter updates', function () {
187+
var instance = new mixin();
188+
189+
instance.initialize();
190+
// Multiple updates
191+
expect(function () {
192+
subscribeCallback({ counter: 1 });
193+
subscribeCallback({ counter: 2 });
194+
subscribeCallback({ counter: 0 });
195+
}).not.toThrow();
196+
});
197+
198+
it('should handle rapid counter updates', function () {
199+
var instance = new mixin(),
200+
i;
201+
202+
instance.initialize();
203+
// Rapid updates
204+
expect(function () {
205+
for (i = 0; i < 10; i++) {
206+
subscribeCallback({ counter: i });
207+
}
208+
}).not.toThrow();
209+
});
210+
});
211+
212+
describe('Mixin functionality', function () {
213+
it('should extend the WishlistComponent correctly', function () {
214+
var instance = new mixin();
215+
216+
expect(instance).toBeDefined();
217+
expect(typeof instance.initialize).toBe('function');
218+
});
219+
220+
it('should maintain the original component structure', function () {
221+
var instance = new mixin();
222+
223+
// The mixin should add functionality but not break the original
224+
expect(instance.initialize).toBeDefined();
225+
});
226+
227+
it('should handle initialization multiple times', function () {
228+
var instance = new mixin(),
229+
result1 = instance.initialize(), // First initialization
230+
result2 = instance.initialize(); // Second initialization
231+
232+
expect(result1).toBe(instance);
233+
expect(result2).toBe(instance);
234+
});
235+
});
236+
237+
describe('Error handling', function () {
238+
it('should throw error when customerData.get returns null', function () {
239+
var instance = new mixin();
240+
241+
customerDataMock.get.and.returnValue(null);
242+
expect(function () {
243+
instance.initialize();
244+
}).toThrow();
245+
});
246+
247+
it('should throw error when customerData.get returns undefined', function () {
248+
var instance = new mixin();
249+
250+
customerDataMock.get.and.returnValue(undefined);
251+
expect(function () {
252+
instance.initialize();
253+
}).toThrow();
254+
});
255+
256+
it('should throw error when wishlist data has no subscribe method', function () {
257+
var instance = new mixin();
258+
259+
customerDataMock.get.and.returnValue({});
260+
expect(function () {
261+
instance.initialize();
262+
}).toThrow();
263+
});
264+
});
265+
});
266+
});

0 commit comments

Comments
 (0)