Skip to content

Commit 080bff5

Browse files
authored
feat(service): handle flash object preventDuplicates similar to global option (#282)
fixes #281
1 parent 2c92e3b commit 080bff5

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

addon/services/flash-messages.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ export default Service.extend({
8888
_newFlashMessage(options = {}) {
8989
assert('The flash message cannot be empty when preventDuplicates is enabled.',
9090
get(this, 'defaultPreventDuplicates') ? options.message : true);
91+
assert('The flash message cannot be empty when preventDuplicates is enabled.',
92+
get(options, 'preventDuplicates') ? options.message : true);
9193

9294
const flashService = this;
9395
const allDefaults = getWithDefault(this, 'flashMessageDefaults', {});
@@ -155,7 +157,11 @@ export default Service.extend({
155157
},
156158

157159
_enqueue(flashInstance) {
158-
const preventDuplicates = get(this, 'defaultPreventDuplicates');
160+
const instancePreventDuplicates = get(flashInstance, 'preventDuplicates');
161+
const preventDuplicates = typeof instancePreventDuplicates === 'boolean' ?
162+
// always prefer instance option over global option
163+
instancePreventDuplicates :
164+
get(this, 'defaultPreventDuplicates');
159165

160166
if (preventDuplicates) {
161167
const guid = get(flashInstance, '_guid');

addon/utils/computed.js

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { typeOf } from '@ember/utils';
22
import { computed, get } from '@ember/object';
33
import { guidFor as emberGuidFor } from '@ember/object/internals';
44
import { A as emberArray } from '@ember/array';
5+
import { isNone } from '@ember/utils';
56

67
export function add(...dependentKeys) {
78
const computedFunc = computed({
@@ -30,6 +31,10 @@ export function guidFor(dependentKey) {
3031
get() {
3132
const value = get(this, dependentKey);
3233

34+
// it's possible that a value has no toString as some objects don't implement the guid field
35+
// this early return it to avoid errors being thrown when calling undefined.toString()
36+
if (isNone(value)) return;
37+
3338
return emberGuidFor(value.toString());
3439
}
3540
});

tests/unit/services/flash-messages-test.js

+48
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ module('FlashMessagesService', function(hooks) {
184184
);
185185
});
186186

187+
test('when preventDuplicates is `false` but flashInstance preventDuplicates is `true` setting a message is not required', function(assert) {
188+
set(service, 'defaultPreventDuplicates', false);
189+
190+
assert.throws(() => {
191+
service.add({ preventDuplicates: true });
192+
},
193+
new EmberError('Assertion Failed: The flash message cannot be empty when preventDuplicates is enabled.'),
194+
'Error is thrown'
195+
);
196+
});
197+
187198
test('it adds duplicate messages to the queue if preventDuplicates is `false`', function(assert) {
188199
set(service, 'defaultPreventDuplicates', false);
189200
const expectedResult = emberArray([ 'foo', 'foo', 'bar' ]);
@@ -205,6 +216,43 @@ module('FlashMessagesService', function(hooks) {
205216
assert.equal(get(service, 'queue').length, 2, 'it does not add duplicate messages to the queue');
206217
});
207218

219+
test('it does not add duplicate messages to the queue if flashInstance preventDuplicates is `true`', function(assert) {
220+
set(service, 'defaultPreventDuplicates', false);
221+
const messages = emberArray([ 'foo', 'foo', 'bar' ]);
222+
const expectedResult = messages.uniq();
223+
messages.forEach((message) => service.success(message, {preventDuplicates: true}));
224+
const result = get(service, 'queue').mapBy('message');
225+
226+
assert.deepEqual(result, expectedResult, 'it does not add duplicate messages to the queue');
227+
assert.equal(get(service, 'queue').length, 2, 'it does not add duplicate messages to the queue');
228+
});
229+
230+
test('flashInstance preventDuplicates prefers instance preventDuplicates over global', function(assert) {
231+
set(service, 'defaultPreventDuplicates', true);
232+
const messages = emberArray([ 'foo', 'foo', 'bar' ]);
233+
const expectedResult = [ 'foo', 'foo', 'bar' ];
234+
messages.forEach((message) => service.success(message, {preventDuplicates: false}));
235+
const result = get(service, 'queue').mapBy('message');
236+
237+
assert.deepEqual(result, expectedResult, 'it adds duplicate messages to the queue');
238+
assert.equal(get(service, 'queue').length, 3, 'it adds duplicate messages to the queue');
239+
});
240+
241+
test('it does use the global preventDuplicates if the instance option isn\'t set', function(assert) {
242+
set(service, 'defaultPreventDuplicates', false);
243+
service.success('foo');
244+
service.success('foo');
245+
service.success('bar', {preventDuplicates: true});
246+
service.success('bar', {preventDuplicates: true});
247+
service.success('foo');
248+
service.success('baz', {preventDuplicates: true});
249+
250+
const result = get(service, 'queue').mapBy('message');
251+
252+
assert.deepEqual(result, ['foo', 'foo', 'bar', 'foo', 'baz'], 'it adds duplicated messages if preventDuplicates isn\'t set');
253+
assert.equal(get(service, 'queue').length, 5, 'it handles duplicates where preventDuplicates is false');
254+
});
255+
208256
test('it supports chaining', function(assert) {
209257
service
210258
.registerTypes(['meow'])

0 commit comments

Comments
 (0)