@@ -185,6 +185,13 @@ describe('resolveServiceAccountIntegration', () => {
185185 } )
186186} )
187187
188+ /**
189+ * Integrations whose `oauthServiceId` is shared with a sibling, so the id names
190+ * a pair rather than a block: Google Slides rides Drive's service, Jira Service
191+ * Management rides Jira's. The bridge deliberately resolves none of them.
192+ */
193+ const SHARED_OAUTH_ID_SLUGS = [ 'google-drive' , 'google-slides' , 'jira' , 'jira-service-management' ]
194+
188195/** Resolved block type with any version suffix dropped, for stable assertions. */
189196function baseTypeFor ( ...keys : ( string | undefined ) [ ] ) : string | undefined {
190197 const blockType = resolveIntegrationBlockTypeForOAuth ( ...keys )
@@ -223,18 +230,27 @@ describe('resolveIntegrationBlockTypeForOAuth', () => {
223230 expect ( resolveIntegrationBlockTypeForOAuth ( undefined , '' ) ) . toBeUndefined ( )
224231 } )
225232
226- it . concurrent ( 'resolves every OAuth integration in the catalog to a block type' , ( ) => {
233+ it . concurrent ( 'refuses to guess when one OAuth id names more than one block' , ( ) => {
234+ // Google Slides is authenticated by Drive's service and JSM by Jira's, so
235+ // these ids name a pair. Answering with either member would put the wrong
236+ // brand on the other's connect dialog, so the bridge declines.
237+ expect ( resolveIntegrationBlockTypeForOAuth ( 'google-drive' ) ) . toBeUndefined ( )
238+ expect ( resolveIntegrationBlockTypeForOAuth ( 'jira' ) ) . toBeUndefined ( )
239+ } )
240+
241+ it . concurrent ( 'resolves every OAuth integration whose id names it alone' , ( ) => {
227242 // A credential surface that cannot reach a block type falls back to the
228243 // colourless OAUTH_PROVIDERS mark, which is the bug this bridge exists to
229- // close — so no OAuth integration may be missing from the index.
244+ // close — so every unambiguous integration must be in the index, and the
245+ // only permitted misses are the shared ids above.
230246 const unresolved = INTEGRATIONS . filter (
231247 ( integration ) =>
232248 integration . authType === 'oauth' &&
233249 integration . oauthServiceId &&
234250 ! resolveIntegrationBlockTypeForOAuth ( integration . oauthServiceId )
235251 ) . map ( ( integration ) => integration . slug )
236252
237- expect ( unresolved ) . toEqual ( [ ] )
253+ expect ( unresolved . sort ( ) ) . toEqual ( SHARED_OAUTH_ID_SLUGS )
238254 } )
239255} )
240256
@@ -244,7 +260,10 @@ describe('the OAuth bridge reaches a renderable tile', () => {
244260 // A type that resolves but has no registered icon or colour would paint an
245261 // empty square in the connect dialog — worse than the grey mark it replaced.
246262 const broken = INTEGRATIONS . filter (
247- ( integration ) => integration . authType === 'oauth' && integration . oauthServiceId
263+ ( integration ) =>
264+ integration . authType === 'oauth' &&
265+ integration . oauthServiceId &&
266+ ! SHARED_OAUTH_ID_SLUGS . includes ( integration . slug )
248267 ) . flatMap ( ( integration ) => {
249268 const blockType = resolveIntegrationBlockTypeForOAuth ( integration . oauthServiceId )
250269 if ( ! blockType ) return [ `${ integration . slug } : unresolved` ]
0 commit comments