Prepare bulk actions model to take RelatedChangeAndCommitInfo

Change 346455 is adding bulk actions for related changes which
means the input to the sync() method can be of type
RelatedChangeAndCommitInfo which has the same change number
but with the property _change_number.

Google-bug-id: b/246912339
Release-Notes: skip
Change-Id: Ia004826a63de4e69ceb316e1b845dfcd7ba41532
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts
index a4e026b..11fe0e2 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts
@@ -28,8 +28,8 @@
 import {pluralize} from '../../../utils/string-util';
 import {
   changeIsOpen,
+  getChangeNumber,
   getRevisionKey,
-  isChangeInfo,
 } from '../../../utils/change-util';
 import {DEFALT_NUM_CHANGES_WHEN_COLLAPSED} from './gr-related-collapse';
 import {createChangeUrl} from '../../../models/views/change';
@@ -639,29 +639,12 @@
     a?: ChangeInfo | RelatedChangeAndCommitInfo,
     b?: ChangeInfo | ParsedChangeInfo | RelatedChangeAndCommitInfo
   ) {
-    const aNum = this._getChangeNumber(a);
-    const bNum = this._getChangeNumber(b);
+    if (!a || !b) return false;
+    const aNum = getChangeNumber(a);
+    const bNum = getChangeNumber(b);
     return aNum === bNum;
   }
 
-  /**
-   * Get the change number from either a ChangeInfo (such as those included in
-   * SubmittedTogetherInfo responses) or get the change number from a
-   * RelatedChangeAndCommitInfo (such as those included in a
-   * RelatedChangesInfo response).
-   */
-  _getChangeNumber(
-    change?: ChangeInfo | ParsedChangeInfo | RelatedChangeAndCommitInfo
-  ) {
-    // Default to 0 if change property is not defined.
-    if (!change) return 0;
-
-    if (isChangeInfo(change)) {
-      return change._number;
-    }
-    return change._change_number;
-  }
-
   /*
    * A list of commit ids connected to change to understand if other change
    * is direct or indirect ancestor / descendant.
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.ts b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.ts
index 09cdf5f..dcc6039 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.ts
@@ -36,6 +36,7 @@
   SubmittedTogetherInfo,
 } from '../../../types/common';
 import {ParsedChangeInfo} from '../../../types/types';
+import {getChangeNumber} from '../../../utils/change-util';
 import {GrEndpointDecorator} from '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
 import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
 import './gr-related-changes-list';
@@ -359,8 +360,8 @@
       change_id: '456' as ChangeId,
       _number: 1 as NumericChangeId,
     };
-    assert.equal(element._getChangeNumber(change1), 0);
-    assert.equal(element._getChangeNumber(change2), 1);
+    assert.equal(getChangeNumber(change1), 0);
+    assert.equal(getChangeNumber(change2), 1);
   });
 
   suite('get conflicts tests', () => {
diff --git a/polygerrit-ui/app/models/bulk-actions/bulk-actions-model.ts b/polygerrit-ui/app/models/bulk-actions/bulk-actions-model.ts
index 1d3802a..f58ad14 100644
--- a/polygerrit-ui/app/models/bulk-actions/bulk-actions-model.ts
+++ b/polygerrit-ui/app/models/bulk-actions/bulk-actions-model.ts
@@ -22,8 +22,10 @@
   ReviewInput,
   ReviewerInput,
   AttentionSetInput,
+  RelatedChangeAndCommitInfo,
 } from '../../types/common';
 import {getUserId} from '../../utils/account-util';
+import {getChangeNumber} from '../../utils/change-util';
 
 export const bulkActionsModelToken =
   define<BulkActionsModel>('bulk-actions-model');
@@ -136,12 +138,12 @@
         return Promise.resolve(new Response());
       }
       return this.restApiService.executeChangeAction(
-        change._number,
+        getChangeNumber(change),
         change.actions!.abandon!.method,
         '/abandon',
         undefined,
         {message: reason ?? ''},
-        () => errFn && errFn(change._number)
+        () => errFn && errFn(getChangeNumber(change))
       );
     });
   }
@@ -152,7 +154,7 @@
       const change = current.allChanges.get(changeNum)!;
       if (!change) throw new Error('invalid change id');
       return this.restApiService.saveChangeReview(
-        change._number,
+        getChangeNumber(change),
         'current',
         reviewInput,
         () => {
@@ -196,7 +198,7 @@
         add_to_attention_set: attentionSetUpdates,
       };
       return this.restApiService.saveChangeReview(
-        change._number,
+        getChangeNumber(change),
         'current',
         reviewInput
       );
@@ -233,13 +235,13 @@
     );
   }
 
-  async sync(changes: ChangeInfo[]) {
-    const basicChanges = new Map(changes.map(c => [c._number, c]));
+  async sync(changes: (ChangeInfo | RelatedChangeAndCommitInfo)[]) {
+    const basicChanges = new Map(changes.map(c => [getChangeNumber(c), c]));
     let currentState = this.getState();
     const selectedChangeNums = currentState.selectedChangeNums.filter(
       changeNum => basicChanges.has(changeNum)
     );
-    const selectableChangeNums = changes.map(c => c._number);
+    const selectableChangeNums = changes.map(c => getChangeNumber(c));
     this.updateState({
       loadingState: LoadingState.LOADING,
       selectedChangeNums,
@@ -252,7 +254,7 @@
     }
     const changeDetails =
       await this.restApiService.getDetailedChangesWithActions(
-        changes.map(c => c._number)
+        changes.map(c => getChangeNumber(c))
       );
     currentState = this.getState();
     // Return early if sync has been called again since starting the load.
diff --git a/polygerrit-ui/app/utils/change-util.ts b/polygerrit-ui/app/utils/change-util.ts
index ad5d48a..07b63d6 100644
--- a/polygerrit-ui/app/utils/change-util.ts
+++ b/polygerrit-ui/app/utils/change-util.ts
@@ -137,6 +137,20 @@
 ) {
   return change?.status === ChangeStatus.ABANDONED;
 }
+/**
+ * Get the change number from either a ChangeInfo (such as those included in
+ * SubmittedTogetherInfo responses) or get the change number from a
+ * RelatedChangeAndCommitInfo (such as those included in a
+ * RelatedChangesInfo response).
+ */
+export function getChangeNumber(
+  change: ChangeInfo | ParsedChangeInfo | RelatedChangeAndCommitInfo
+): NumericChangeId {
+  if (isChangeInfo(change)) {
+    return change._number;
+  }
+  return change._change_number!;
+}
 
 export function changeStatuses(
   change: ChangeInfo,