Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | import {assert} from 'chai'; |
| 6 | import {UserInputError} from 'shared/errors.js'; |
| 7 | import * as exampleUsers from 'shared/test/constants-users.js'; |
| 8 | import {displayNameToUserRef, userIdOrDisplayNameToUserRef, |
| 9 | userNameToId, userV3ToRef, labelStringToRef, |
| 10 | labelRefToString, labelRefsToStrings, labelRefsToOneWordLabels, |
| 11 | isOneWordLabel, _makeRestrictionLabel, restrictionLabelsForPermissions, |
| 12 | fieldDefToName, statusRefToString, statusRefsToStrings, |
| 13 | componentStringToRef, componentRefToString, componentRefsToStrings, |
| 14 | issueStringToRef, issueStringToBlockingRef, issueRefToString, |
| 15 | issueRefToUrl, fieldNameToLabelPrefix, labelNameToLabelPrefixes, |
| 16 | labelNameToLabelValue, commentListToDescriptionList, valueToFieldValue, |
| 17 | issueToIssueRef, issueNameToRef, issueNameToRefString, issueToName, |
| 18 | } from './convertersV0.js'; |
| 19 | |
| 20 | describe('displayNameToUserRef', () => { |
| 21 | it('converts displayName', () => { |
| 22 | assert.deepEqual( |
| 23 | displayNameToUserRef('foo@bar.com'), |
| 24 | {displayName: 'foo@bar.com'}); |
| 25 | }); |
| 26 | |
| 27 | it('throws on invalid email', () => { |
| 28 | assert.throws(() => displayNameToUserRef('foo'), UserInputError); |
| 29 | }); |
| 30 | }); |
| 31 | |
| 32 | describe('userIdOrDisplayNameToUserRef', () => { |
| 33 | it('converts userId', () => { |
| 34 | assert.throws(() => displayNameToUserRef('foo')); |
| 35 | assert.deepEqual( |
| 36 | userIdOrDisplayNameToUserRef('12345678'), |
| 37 | {userId: 12345678}); |
| 38 | }); |
| 39 | |
| 40 | it('converts displayName', () => { |
| 41 | assert.deepEqual( |
| 42 | userIdOrDisplayNameToUserRef('foo@bar.com'), |
| 43 | {displayName: 'foo@bar.com'}); |
| 44 | }); |
| 45 | |
| 46 | it('throws if not an email or numeric id', () => { |
| 47 | assert.throws(() => userIdOrDisplayNameToUserRef('foo'), UserInputError); |
| 48 | }); |
| 49 | }); |
| 50 | |
| 51 | it('userNameToId', () => { |
| 52 | assert.deepEqual(userNameToId(exampleUsers.NAME), exampleUsers.ID); |
| 53 | }); |
| 54 | |
| 55 | it('userV3ToRef', () => { |
| 56 | assert.deepEqual(userV3ToRef(exampleUsers.USER), exampleUsers.USER_REF); |
| 57 | }); |
| 58 | |
| 59 | describe('labelStringToRef', () => { |
| 60 | it('converts label', () => { |
| 61 | assert.deepEqual(labelStringToRef('foo'), {label: 'foo'}); |
| 62 | }); |
| 63 | }); |
| 64 | |
| 65 | describe('labelRefToString', () => { |
| 66 | it('converts labelRef', () => { |
| 67 | assert.deepEqual(labelRefToString({label: 'foo'}), 'foo'); |
| 68 | }); |
| 69 | }); |
| 70 | |
| 71 | describe('labelRefsToStrings', () => { |
| 72 | it('converts labelRefs', () => { |
| 73 | assert.deepEqual(labelRefsToStrings([{label: 'foo'}, {label: 'test'}]), |
| 74 | ['foo', 'test']); |
| 75 | }); |
| 76 | }); |
| 77 | |
| 78 | describe('labelRefsToOneWordLabels', () => { |
| 79 | it('empty', () => { |
| 80 | assert.deepEqual(labelRefsToOneWordLabels(), []); |
| 81 | assert.deepEqual(labelRefsToOneWordLabels([]), []); |
| 82 | }); |
| 83 | |
| 84 | it('filters multi-word labels', () => { |
| 85 | assert.deepEqual(labelRefsToOneWordLabels([ |
| 86 | {label: 'hello'}, |
| 87 | {label: 'filter-me'}, |
| 88 | {label: 'hello-world'}, |
| 89 | {label: 'world'}, |
| 90 | {label: 'this-label-has-so-many-words'}, |
| 91 | ]), [ |
| 92 | {label: 'hello'}, |
| 93 | {label: 'world'}, |
| 94 | ]); |
| 95 | }); |
| 96 | }); |
| 97 | |
| 98 | describe('isOneWordLabel', () => { |
| 99 | it('true only for one word labels', () => { |
| 100 | assert.isTrue(isOneWordLabel('test')); |
| 101 | assert.isTrue(isOneWordLabel('LABEL')); |
| 102 | assert.isTrue(isOneWordLabel('Security')); |
| 103 | |
| 104 | assert.isFalse(isOneWordLabel('Restrict-View-EditIssue')); |
| 105 | assert.isFalse(isOneWordLabel('Type-Feature')); |
| 106 | }); |
| 107 | }); |
| 108 | |
| 109 | describe('_makeRestrictionLabel', () => { |
| 110 | it('creates label', () => { |
| 111 | assert.deepEqual(_makeRestrictionLabel('View', 'Google'), { |
| 112 | label: `Restrict-View-Google`, |
| 113 | docstring: `Permission Google needed to use View`, |
| 114 | }); |
| 115 | }); |
| 116 | |
| 117 | it('capitalizes permission name', () => { |
| 118 | assert.deepEqual(_makeRestrictionLabel('EditIssue', 'security'), { |
| 119 | label: `Restrict-EditIssue-Security`, |
| 120 | docstring: `Permission Security needed to use EditIssue`, |
| 121 | }); |
| 122 | }); |
| 123 | }); |
| 124 | |
| 125 | describe('restrictionLabelsForPermissions', () => { |
| 126 | it('creates labels for permissions and actions', () => { |
| 127 | assert.deepEqual(restrictionLabelsForPermissions(['google', 'security'], |
| 128 | ['View', 'EditIssue'], []), [ |
| 129 | { |
| 130 | label: 'Restrict-View-Google', |
| 131 | docstring: 'Permission Google needed to use View', |
| 132 | }, { |
| 133 | label: 'Restrict-View-Security', |
| 134 | docstring: 'Permission Security needed to use View', |
| 135 | }, { |
| 136 | label: 'Restrict-EditIssue-Google', |
| 137 | docstring: 'Permission Google needed to use EditIssue', |
| 138 | }, { |
| 139 | label: 'Restrict-EditIssue-Security', |
| 140 | docstring: 'Permission Security needed to use EditIssue', |
| 141 | }, |
| 142 | ]); |
| 143 | }); |
| 144 | |
| 145 | it('appends default labels when specified', () => { |
| 146 | assert.deepEqual(restrictionLabelsForPermissions(['Google'], ['View'], [ |
| 147 | {label: 'Restrict-Hello-World', docstring: 'description of label'}, |
| 148 | ]), [ |
| 149 | { |
| 150 | label: 'Restrict-View-Google', |
| 151 | docstring: 'Permission Google needed to use View', |
| 152 | }, |
| 153 | {label: 'Restrict-Hello-World', docstring: 'description of label'}, |
| 154 | ]); |
| 155 | }); |
| 156 | }); |
| 157 | |
| 158 | describe('fieldNameToLabelPrefix', () => { |
| 159 | it('converts fieldName', () => { |
| 160 | assert.deepEqual(fieldNameToLabelPrefix('test'), 'test-'); |
| 161 | assert.deepEqual(fieldNameToLabelPrefix('test-hello'), 'test-hello-'); |
| 162 | assert.deepEqual(fieldNameToLabelPrefix('WHATEVER'), 'whatever-'); |
| 163 | }); |
| 164 | }); |
| 165 | |
| 166 | describe('labelNameToLabelPrefixes', () => { |
| 167 | it('converts labelName', () => { |
| 168 | assert.deepEqual(labelNameToLabelPrefixes('test'), []); |
| 169 | assert.deepEqual(labelNameToLabelPrefixes('test-hello'), ['test']); |
| 170 | assert.deepEqual(labelNameToLabelPrefixes('WHATEVER-this-label-is'), |
| 171 | ['WHATEVER', 'WHATEVER-this', 'WHATEVER-this-label']); |
| 172 | }); |
| 173 | }); |
| 174 | |
| 175 | describe('labelNameToLabelValue', () => { |
| 176 | it('returns null when no matching value found in label', () => { |
| 177 | assert.isNull(labelNameToLabelValue('test-hello', '')); |
| 178 | assert.isNull(labelNameToLabelValue('', 'test')); |
| 179 | assert.isNull(labelNameToLabelValue('test-hello', 'hello')); |
| 180 | assert.isNull(labelNameToLabelValue('test-hello', 'tes')); |
| 181 | assert.isNull(labelNameToLabelValue('test', 'test')); |
| 182 | }); |
| 183 | |
| 184 | it('converts labelName', () => { |
| 185 | assert.deepEqual(labelNameToLabelValue('test-hello', 'test'), 'hello'); |
| 186 | assert.deepEqual(labelNameToLabelValue('WHATEVER-this-label-is', |
| 187 | 'WHATEVER'), 'this-label-is'); |
| 188 | assert.deepEqual(labelNameToLabelValue('WHATEVER-this-label-is', |
| 189 | 'WHATEVER-this'), 'label-is'); |
| 190 | assert.deepEqual(labelNameToLabelValue('WHATEVER-this-label-is', |
| 191 | 'WHATEVER-this-label'), 'is'); |
| 192 | }); |
| 193 | |
| 194 | it('fieldName is case insenstitive', () => { |
| 195 | assert.deepEqual(labelNameToLabelValue('test-hello', 'TEST'), 'hello'); |
| 196 | assert.deepEqual(labelNameToLabelValue('test-hello', 'tEsT'), 'hello'); |
| 197 | assert.deepEqual(labelNameToLabelValue('TEST-hello', 'test'), 'hello'); |
| 198 | }); |
| 199 | }); |
| 200 | |
| 201 | describe('fieldDefToName', () => { |
| 202 | it('converts fieldDef', () => { |
| 203 | const fieldDef = {fieldRef: {fieldId: '1'}}; |
| 204 | const actual = fieldDefToName('project-name', fieldDef); |
| 205 | assert.equal(actual, 'projects/project-name/fieldDefs/1'); |
| 206 | }); |
| 207 | }); |
| 208 | |
| 209 | describe('statusRefToString', () => { |
| 210 | it('converts statusRef', () => { |
| 211 | assert.deepEqual(statusRefToString({status: 'foo'}), 'foo'); |
| 212 | }); |
| 213 | }); |
| 214 | |
| 215 | describe('statusRefsToStrings', () => { |
| 216 | it('converts statusRefs', () => { |
| 217 | assert.deepEqual(statusRefsToStrings( |
| 218 | [{status: 'hello'}, {status: 'world'}]), ['hello', 'world']); |
| 219 | }); |
| 220 | }); |
| 221 | |
| 222 | describe('componentStringToRef', () => { |
| 223 | it('converts component', () => { |
| 224 | assert.deepEqual(componentStringToRef('foo'), {path: 'foo'}); |
| 225 | }); |
| 226 | }); |
| 227 | |
| 228 | describe('componentRefToString', () => { |
| 229 | it('converts componentRef', () => { |
| 230 | assert.deepEqual(componentRefToString({path: 'Hello>World'}), |
| 231 | 'Hello>World'); |
| 232 | }); |
| 233 | }); |
| 234 | |
| 235 | describe('componentRefsToStrings', () => { |
| 236 | it('converts componentRefs', () => { |
| 237 | assert.deepEqual(componentRefsToStrings( |
| 238 | [{path: 'Hello>World'}, {path: 'Test'}]), ['Hello>World', 'Test']); |
| 239 | }); |
| 240 | }); |
| 241 | |
| 242 | describe('issueStringToRef', () => { |
| 243 | it('converts issue default project', () => { |
| 244 | assert.deepEqual( |
| 245 | issueStringToRef('1234', 'proj'), |
| 246 | {projectName: 'proj', localId: 1234}); |
| 247 | }); |
| 248 | |
| 249 | it('converts issue with project', () => { |
| 250 | assert.deepEqual( |
| 251 | issueStringToRef('foo:1234', 'proj'), |
| 252 | {projectName: 'foo', localId: 1234}); |
| 253 | }); |
| 254 | |
| 255 | it('converts external issue references', () => { |
| 256 | assert.deepEqual( |
| 257 | issueStringToRef('b/123456', 'proj'), |
| 258 | {extIdentifier: 'b/123456'}); |
| 259 | }); |
| 260 | |
| 261 | it('throws on invalid input', () => { |
| 262 | assert.throws(() => issueStringToRef('foo', 'proj')); |
| 263 | }); |
| 264 | }); |
| 265 | |
| 266 | describe('issueStringToBlockingRef', () => { |
| 267 | it('converts issue default project', () => { |
| 268 | assert.deepEqual( |
| 269 | issueStringToBlockingRef({projectName: 'proj', localId: 1}, '1234'), |
| 270 | {projectName: 'proj', localId: 1234}); |
| 271 | }); |
| 272 | |
| 273 | it('converts issue with project', () => { |
| 274 | assert.deepEqual( |
| 275 | issueStringToBlockingRef({projectName: 'proj', localId: 1}, 'foo:1234'), |
| 276 | {projectName: 'foo', localId: 1234}); |
| 277 | }); |
| 278 | |
| 279 | it('throws on invalid input', () => { |
| 280 | assert.throws(() => issueStringToBlockingRef( |
| 281 | {projectName: 'proj', localId: 1}, 'foo')); |
| 282 | }); |
| 283 | |
| 284 | it('throws when blocking an issue on itself', () => { |
| 285 | assert.throws(() => issueStringToBlockingRef( |
| 286 | {projectName: 'proj', localId: 123}, 'proj:123')); |
| 287 | assert.throws(() => issueStringToBlockingRef( |
| 288 | {projectName: 'proj', localId: 123}, '123')); |
| 289 | }); |
| 290 | }); |
| 291 | |
| 292 | describe('issueRefToString', () => { |
| 293 | it('no ref', () => { |
| 294 | assert.equal(issueRefToString(), ''); |
| 295 | }); |
| 296 | |
| 297 | it('ref with no project name', () => { |
| 298 | assert.equal( |
| 299 | 'other:1234', |
| 300 | issueRefToString({projectName: 'other', localId: 1234}), |
| 301 | ); |
| 302 | }); |
| 303 | |
| 304 | it('ref with different project name', () => { |
| 305 | assert.equal( |
| 306 | 'other:1234', |
| 307 | issueRefToString({projectName: 'other', localId: 1234}, 'proj'), |
| 308 | ); |
| 309 | }); |
| 310 | |
| 311 | it('ref with same project name', () => { |
| 312 | assert.equal( |
| 313 | '1234', |
| 314 | issueRefToString({projectName: 'proj', localId: 1234}, 'proj'), |
| 315 | ); |
| 316 | }); |
| 317 | |
| 318 | it('external ref', () => { |
| 319 | assert.equal( |
| 320 | 'b/123456', |
| 321 | issueRefToString({extIdentifier: 'b/123456'}, 'proj'), |
| 322 | ); |
| 323 | }); |
| 324 | }); |
| 325 | |
| 326 | describe('issueToIssueRef', () => { |
| 327 | it('creates ref', () => { |
| 328 | const issue = {'localId': 1, 'projectName': 'proj', 'starCount': 1}; |
| 329 | const expectedRef = {'localId': 1, |
| 330 | 'projectName': 'proj'}; |
| 331 | assert.deepEqual(issueToIssueRef(issue), expectedRef); |
| 332 | }); |
| 333 | }); |
| 334 | |
| 335 | describe('issueRefToUrl', () => { |
| 336 | it('no ref', () => { |
| 337 | assert.equal(issueRefToUrl(), ''); |
| 338 | }); |
| 339 | |
| 340 | it('issue ref', () => { |
| 341 | assert.equal(issueRefToUrl({ |
| 342 | projectName: 'test', |
| 343 | localId: 11, |
| 344 | }), '/p/test/issues/detail?id=11'); |
| 345 | }); |
| 346 | |
| 347 | it('issue ref with params', () => { |
| 348 | assert.equal(issueRefToUrl({ |
| 349 | projectName: 'test', |
| 350 | localId: 11, |
| 351 | }, { |
| 352 | q: 'owner:me', |
| 353 | id: 44, |
| 354 | }), '/p/test/issues/detail?id=11&q=owner%3Ame'); |
| 355 | }); |
| 356 | |
| 357 | it('federated issue ref', () => { |
| 358 | assert.equal(issueRefToUrl({ |
| 359 | extIdentifier: 'b/5678', |
| 360 | }), 'https://issuetracker.google.com/issues/5678'); |
| 361 | }); |
| 362 | |
| 363 | it('does not mutate input queryParams', () => { |
| 364 | const queryParams = {q: 'owner:me', id: 44}; |
| 365 | const EXPECTED = JSON.stringify(queryParams); |
| 366 | const ref = {projectName: 'test', localId: 11}; |
| 367 | issueRefToUrl(ref, queryParams); |
| 368 | assert.equal(EXPECTED, JSON.stringify(queryParams)); |
| 369 | }); |
| 370 | }); |
| 371 | |
| 372 | it('issueNameToRef', () => { |
| 373 | const actual = issueNameToRef('projects/project-name/issues/2'); |
| 374 | assert.deepEqual(actual, {projectName: 'project-name', localId: 2}); |
| 375 | }); |
| 376 | |
| 377 | it('issueNameToRefString', () => { |
| 378 | const actual = issueNameToRefString('projects/project-name/issues/2'); |
| 379 | assert.equal(actual, 'project-name:2'); |
| 380 | }); |
| 381 | |
| 382 | it('issueToName', () => { |
| 383 | const actual = issueToName({projectName: 'project-name', localId: 2}); |
| 384 | assert.equal(actual, 'projects/project-name/issues/2'); |
| 385 | }); |
| 386 | |
| 387 | describe('commentListToDescriptionList', () => { |
| 388 | it('empty list', () => { |
| 389 | assert.deepEqual(commentListToDescriptionList(), []); |
| 390 | assert.deepEqual(commentListToDescriptionList([]), []); |
| 391 | }); |
| 392 | |
| 393 | it('first comment is description', () => { |
| 394 | assert.deepEqual(commentListToDescriptionList([ |
| 395 | {content: 'test'}, |
| 396 | {content: 'hello'}, |
| 397 | {content: 'world'}, |
| 398 | ]), [{content: 'test'}]); |
| 399 | }); |
| 400 | |
| 401 | it('some descriptions', () => { |
| 402 | assert.deepEqual(commentListToDescriptionList([ |
| 403 | {content: 'test'}, |
| 404 | {content: 'hello', descriptionNum: 1}, |
| 405 | {content: 'world'}, |
| 406 | {content: 'this'}, |
| 407 | {content: 'is a'}, |
| 408 | {content: 'description', descriptionNum: 2}, |
| 409 | ]), [ |
| 410 | {content: 'test'}, |
| 411 | {content: 'hello', descriptionNum: 1}, |
| 412 | {content: 'description', descriptionNum: 2}, |
| 413 | ]); |
| 414 | }); |
| 415 | }); |
| 416 | |
| 417 | describe('valueToFieldValue', () => { |
| 418 | it('converts field ref and value', () => { |
| 419 | assert.deepEqual(valueToFieldValue( |
| 420 | {fieldName: 'name', fieldId: 'id'}, |
| 421 | 'value', |
| 422 | ), { |
| 423 | fieldRef: {fieldName: 'name', fieldId: 'id'}, |
| 424 | value: 'value', |
| 425 | }); |
| 426 | }); |
| 427 | }); |