blob: e05a9a2377457cea1a344e2930b782ac49c6d431 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001// Copyright 2019 The Chromium Authors
Copybara854996b2021-09-07 19:36:02 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {assert} from 'chai';
6import {arrayDifference, setHasAny, capitalizeFirst, hasPrefix, objectToMap,
7 objectValuesForKeys, equalsIgnoreCase, immutableSplice, userIsMember,
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01008 urlWithNewParams, createObjectComparisonFunc, generateProjectIssueURL} from './helpers.js';
Copybara854996b2021-09-07 19:36:02 +00009
10describe('arrayDifference', () => {
11 it('empty array stays empty', () => {
12 assert.deepEqual(arrayDifference([], []), []);
13 assert.deepEqual(arrayDifference([], undefined), []);
14 assert.deepEqual(arrayDifference([], ['a']), []);
15 });
16
17 it('subtracting empty array does nothing', () => {
18 assert.deepEqual(arrayDifference(['a'], []), ['a']);
19 assert.deepEqual(arrayDifference([1, 2, 3], []), [1, 2, 3]);
20 assert.deepEqual(arrayDifference([1, 2, 'test'], []), [1, 2, 'test']);
21 assert.deepEqual(arrayDifference([1, 2, 'test'], undefined),
22 [1, 2, 'test']);
23 });
24
25 it('subtracts elements from array', () => {
26 assert.deepEqual(arrayDifference(['a', 'b', 'c'], ['b', 'c']), ['a']);
27 assert.deepEqual(arrayDifference(['a', 'b', 'c'], ['a']), ['b', 'c']);
28 assert.deepEqual(arrayDifference(['a', 'b', 'c'], ['b']), ['a', 'c']);
29 assert.deepEqual(arrayDifference([1, 2, 3], [2]), [1, 3]);
30 });
31
32 it('does not subtract missing elements from array', () => {
33 assert.deepEqual(arrayDifference(['a', 'b', 'c'], ['d']), ['a', 'b', 'c']);
34 assert.deepEqual(arrayDifference([1, 2, 3], [5]), [1, 2, 3]);
35 assert.deepEqual(arrayDifference([1, 2, 3], [-1, 2]), [1, 3]);
36 });
37
38 it('custom equals function', () => {
39 assert.deepEqual(arrayDifference(['a', 'b'], ['A']), ['a', 'b']);
40 assert.deepEqual(arrayDifference(['a', 'b'], ['A'], equalsIgnoreCase),
41 ['b']);
42 });
43});
44
45describe('setHasAny', () => {
46 it('empty set never has any values', () => {
47 assert.isFalse(setHasAny(new Set(), []));
48 assert.isFalse(setHasAny(new Set(), ['test']));
49 assert.isFalse(setHasAny(new Set(), ['nope', 'yup', 'no']));
50 });
51
52 it('false when no values found', () => {
53 assert.isFalse(setHasAny(new Set(['hello', 'world']), []));
54 assert.isFalse(setHasAny(new Set(['hello', 'world']), ['wor']));
55 assert.isFalse(setHasAny(new Set(['test']), ['other', 'values']));
56 assert.isFalse(setHasAny(new Set([1, 2, 3]), [4, 5, 6]));
57 });
58
59 it('true when values found', () => {
60 assert.isTrue(setHasAny(new Set(['hello', 'world']), ['world']));
61 assert.isTrue(setHasAny(new Set([1, 2, 3]), [3, 4, 5]));
62 assert.isTrue(setHasAny(new Set([1, 2, 3]), [1, 3]));
63 });
64});
65
66describe('capitalizeFirst', () => {
67 it('empty string', () => {
68 assert.equal(capitalizeFirst(''), '');
69 });
70
71 it('ignores non-letters', () => {
72 assert.equal(capitalizeFirst('8fcsdf'), '8fcsdf');
73 });
74
75 it('preserves existing caps', () => {
76 assert.equal(capitalizeFirst('HELLO world'), 'HELLO world');
77 });
78
79 it('capitalizes lowercase', () => {
80 assert.equal(capitalizeFirst('hello world'), 'Hello world');
81 });
82});
83
84describe('hasPrefix', () => {
85 it('only true when has prefix', () => {
86 assert.isFalse(hasPrefix('teststring', 'test-'));
87 assert.isFalse(hasPrefix('stringtest-', 'test-'));
88 assert.isFalse(hasPrefix('^test-$', 'test-'));
89 assert.isTrue(hasPrefix('test-', 'test-'));
90 assert.isTrue(hasPrefix('test-fsdfsdf', 'test-'));
91 });
92
93 it('ignores case when checking prefix', () => {
94 assert.isTrue(hasPrefix('TEST-string', 'test-'));
95 assert.isTrue(hasPrefix('test-string', 'test-'));
96 assert.isTrue(hasPrefix('tEsT-string', 'test-'));
97 });
98});
99
100describe('objectToMap', () => {
101 it('converts Object to Map with the same keys', () => {
102 assert.deepEqual(objectToMap({}), new Map());
103 assert.deepEqual(objectToMap({test: 'value'}),
104 new Map([['test', 'value']]));
105 assert.deepEqual(objectToMap({['weird:key']: 'value',
106 ['what is this key']: 'v2'}), new Map([['weird:key', 'value'],
107 ['what is this key', 'v2']]));
108 });
109});
110
111describe('objectValuesForKeys', () => {
112 it('no values when no matching keys', () => {
113 assert.deepEqual(objectValuesForKeys({}, []), []);
114 assert.deepEqual(objectValuesForKeys({}, []), []);
115 assert.deepEqual(objectValuesForKeys({key: 'value'}, []), []);
116 });
117
118 it('returns values when keys match', () => {
119 assert.deepEqual(objectValuesForKeys({a: 1, b: 2, c: 3}, ['a', 'b']),
120 [1, 2]);
121 assert.deepEqual(objectValuesForKeys({a: 1, b: 2, c: 3}, ['b', 'c']),
122 [2, 3]);
123 assert.deepEqual(objectValuesForKeys({['weird:key']: {nested: 'obj'}},
124 ['weird:key']), [{nested: 'obj'}]);
125 });
126
127 it('sets non-matching keys to undefined', () => {
128 assert.deepEqual(objectValuesForKeys({a: 1, b: 2, c: 3}, ['c', 'd', 'e']),
129 [3, undefined, undefined]);
130 assert.deepEqual(objectValuesForKeys({a: 1, b: 2, c: 3}, [1, 2, 3]),
131 [undefined, undefined, undefined]);
132 });
133});
134
135describe('equalsIgnoreCase', () => {
136 it('matches same case strings', () => {
137 assert.isTrue(equalsIgnoreCase('', ''));
138 assert.isTrue(equalsIgnoreCase('HelloWorld', 'HelloWorld'));
139 assert.isTrue(equalsIgnoreCase('hmm', 'hmm'));
140 assert.isTrue(equalsIgnoreCase('TEST', 'TEST'));
141 });
142
143 it('matches different case strings', () => {
144 assert.isTrue(equalsIgnoreCase('a', 'A'));
145 assert.isTrue(equalsIgnoreCase('HelloWorld', 'helloworld'));
146 assert.isTrue(equalsIgnoreCase('hmm', 'HMM'));
147 assert.isTrue(equalsIgnoreCase('TEST', 'teSt'));
148 });
149
150 it('does not match different strings', () => {
151 assert.isFalse(equalsIgnoreCase('hello', 'hello '));
152 assert.isFalse(equalsIgnoreCase('superstring', 'string'));
153 assert.isFalse(equalsIgnoreCase('aaa', 'aa'));
154 });
155});
156
157describe('immutableSplice', () => {
158 it('does not edit original array', () => {
159 const arr = ['apples', 'pears', 'oranges'];
160
161 assert.deepEqual(immutableSplice(arr, 1, 1),
162 ['apples', 'oranges']);
163
164 assert.deepEqual(arr, ['apples', 'pears', 'oranges']);
165 });
166
167 it('removes multiple items', () => {
168 const arr = [1, 2, 3, 4, 5, 6];
169
170 assert.deepEqual(immutableSplice(arr, 1, 0), [1, 2, 3, 4, 5, 6]);
171 assert.deepEqual(immutableSplice(arr, 1, 4), [1, 6]);
172 assert.deepEqual(immutableSplice(arr, 0, 6), []);
173 });
174
175 it('adds items', () => {
176 const arr = [1, 2, 3];
177
178 assert.deepEqual(immutableSplice(arr, 1, 1, 4, 5, 6), [1, 4, 5, 6, 3]);
179 assert.deepEqual(immutableSplice(arr, 2, 1, 4, 5, 6), [1, 2, 4, 5, 6]);
180 assert.deepEqual(immutableSplice(arr, 0, 0, -3, -2, -1, 0),
181 [-3, -2, -1, 0, 1, 2, 3]);
182 });
183});
184
185describe('urlWithNewParams', () => {
186 it('empty', () => {
187 assert.equal(urlWithNewParams(), '');
188 assert.equal(urlWithNewParams(''), '');
189 assert.equal(urlWithNewParams('', {}), '');
190 assert.equal(urlWithNewParams('', {}, {}), '');
191 assert.equal(urlWithNewParams('', {}, {}, []), '');
192 });
193
194 it('preserves existing URL without changes', () => {
195 assert.equal(urlWithNewParams('/p/chromium/issues/list'),
196 '/p/chromium/issues/list');
197 assert.equal(urlWithNewParams('/p/chromium/issues/list', {q: 'owner:me'}),
198 '/p/chromium/issues/list?q=owner%3Ame');
199 assert.equal(
200 urlWithNewParams('/p/chromium/issues/list', {q: 'owner:me', can: '1'}),
201 '/p/chromium/issues/list?q=owner%3Ame&can=1');
202 });
203
204 it('adds new params', () => {
205 assert.equal(
206 urlWithNewParams('/p/chromium/issues/list', {}, {q: 'owner:me'}),
207 '/p/chromium/issues/list?q=owner%3Ame');
208 assert.equal(
209 urlWithNewParams('/p/chromium/issues/list',
210 {can: '1'}, {q: 'owner:me'}),
211 '/p/chromium/issues/list?can=1&q=owner%3Ame');
212
213 // Override existing params.
214 assert.equal(
215 urlWithNewParams('/p/chromium/issues/list',
216 {can: '1', q: 'owner:me'}, {q: 'test'}),
217 '/p/chromium/issues/list?can=1&q=test');
218 });
219
220 it('clears existing params', () => {
221 assert.equal(
222 urlWithNewParams('/p/chromium/issues/list', {q: 'owner:me'}, {}, ['q']),
223 '/p/chromium/issues/list');
224 assert.equal(
225 urlWithNewParams('/p/chromium/issues/list',
226 {can: '1'}, {q: 'owner:me'}, ['can']),
227 '/p/chromium/issues/list?q=owner%3Ame');
228 assert.equal(
229 urlWithNewParams('/p/chromium/issues/list', {q: 'owner:me'}, {can: '2'},
230 ['q', 'can', 'fakeparam']),
231 '/p/chromium/issues/list');
232 });
233});
234
235describe('userIsMember', () => {
236 it('false when no user', () => {
237 assert.isFalse(userIsMember(undefined));
238 assert.isFalse(userIsMember({}));
239 assert.isFalse(userIsMember({}, 'chromium',
240 new Map([['123', {ownerOf: ['chromium']}]])));
241 });
242
243 it('true when user is member of project', () => {
244 assert.isTrue(userIsMember({userId: '123'}, 'chromium',
245 new Map([['123', {contributorTo: ['chromium']}]])));
246
247 assert.isTrue(userIsMember({userId: '123'}, 'chromium',
248 new Map([['123', {ownerOf: ['chromium']}]])));
249
250 assert.isTrue(userIsMember({userId: '123'}, 'chromium',
251 new Map([['123', {memberOf: ['chromium']}]])));
252 });
253
254 it('true when user is member of multiple projects', () => {
255 assert.isTrue(userIsMember({userId: '123'}, 'chromium', new Map([
256 ['123', {contributorTo: ['test', 'chromium', 'fakeproject']}],
257 ])));
258
259 assert.isTrue(userIsMember({userId: '123'}, 'chromium', new Map([
260 ['123', {ownerOf: ['test', 'chromium', 'fakeproject']}],
261 ])));
262
263 assert.isTrue(userIsMember({userId: '123'}, 'chromium', new Map([
264 ['123', {memberOf: ['test', 'chromium', 'fakeproject']}],
265 ])));
266 });
267
268 it('false when user is member of different project', () => {
269 assert.isFalse(userIsMember({userId: '123'}, 'chromium', new Map([
270 ['123', {contributorTo: ['test', 'fakeproject']}],
271 ])));
272
273 assert.isFalse(userIsMember({userId: '123'}, 'chromium', new Map([
274 ['123', {ownerOf: ['test', 'fakeproject']}],
275 ])));
276
277 assert.isFalse(userIsMember({userId: '123'}, 'chromium', new Map([
278 ['123', {memberOf: ['test', 'fakeproject']}],
279 ])));
280 });
281
282 it('false when no project data for user', () => {
283 assert.isFalse(userIsMember({userId: '123'}, 'chromium'));
284 assert.isFalse(userIsMember({userId: '123'}, 'chromium', new Map()));
285 assert.isFalse(userIsMember({userId: '123'}, 'chromium', new Map([
286 ['543', {ownerOf: ['chromium']}],
287 ])));
288 });
289});
290
291describe('createObjectComparisonFunc', () => {
292 it('returns a function', () => {
293 const result = createObjectComparisonFunc(new Set());
294 assert.instanceOf(result, Function);
295 });
296
297 describe('returned function', () => {
298 it('returns false if both inputs are undefined', () => {
299 const comparableProps = new Set(['a', 'b', 'c']);
300 const func = createObjectComparisonFunc(comparableProps);
301 const result = func(undefined, undefined);
302
303 assert.isFalse(result);
304 });
305
306 it('returns true if only one inputs is undefined', () => {
307 const comparableProps = new Set(['a', 'b', 'c']);
308 const func = createObjectComparisonFunc(comparableProps);
309 const result = func({}, undefined);
310
311 assert.isTrue(result);
312 });
313
314 it('returns false if both inputs are null', () => {
315 const comparableProps = new Set(['a', 'b', 'c']);
316 const func = createObjectComparisonFunc(comparableProps);
317 const result = func(null, null);
318
319 assert.isFalse(result);
320 });
321
322 it('returns true if only one inputs is null', () => {
323 const comparableProps = new Set(['a', 'b', 'c']);
324 const func = createObjectComparisonFunc(comparableProps);
325 const result = func({}, null);
326
327 assert.isTrue(result);
328 });
329
330 it('returns true if any comparable property is different', () => {
331 const comparableProps = new Set(['a', 'b', 'c']);
332 const func = createObjectComparisonFunc(comparableProps);
333 const a = {a: 1, b: 2, c: 3};
334 const b = {a: 1, b: 2, c: '3'};
335 const result = func(a, b);
336
337 assert.isTrue(result);
338 });
339
340 it('returns false if all comparable properties are the same', () => {
341 const comparableProps = new Set(['a', 'b', 'c']);
342 const func = createObjectComparisonFunc(comparableProps);
343 const a = {a: 1, b: 2, c: 3};
344 const b = {a: 1, b: 2, c: 3};
345 const result = func(a, b);
346
347 assert.isFalse(result);
348 });
349
350 it('ignores non-comparable properties', () => {
351 const comparableProps = new Set(['a', 'b', 'c']);
352 const func = createObjectComparisonFunc(comparableProps);
353 const a = {a: 1, b: 2, c: 3, d: 4};
354 const b = {a: 1, b: 2, c: 3, d: 'not four', e: 'exists'};
355 const result = func(a, b);
356
357 assert.isFalse(result);
358 });
359 });
360});
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100361
362describe('generateProjectIssueURL', () => {
363 it('no redirect required and no param', () => {
364 assert.equal(generateProjectIssueURL('project', '/list'), '/p/project/issues/list');
365 });
366
367 it('no redirect required and with param', () => {
368 assert.equal(generateProjectIssueURL('project', '/detail', {'id': 123}), '/p/project/issues/detail?id=123');
369 });
370
371 //TODO(crbug.com/monorail/12029): add more unit test.
372});