diff --git a/packages/store/src/cli/utilities/store-lookup/organization.test.ts b/packages/store/src/cli/utilities/store-lookup/organization.test.ts index 717e9c1a0fd..caa5e981314 100644 --- a/packages/store/src/cli/utilities/store-lookup/organization.test.ts +++ b/packages/store/src/cli/utilities/store-lookup/organization.test.ts @@ -3,6 +3,7 @@ import {fetchDestinationsContext} from './destinations.js' import {selectOrg} from '@shopify/organizations' import {AbortError} from '@shopify/cli-kit/node/error' import {terminalSupportsPrompting} from '@shopify/cli-kit/node/system' +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' import {describe, expect, test, vi, beforeEach} from 'vitest' vi.mock('./destinations.js') @@ -45,6 +46,7 @@ describe('resolveOrganizationForStore', () => { vi.mocked(selectOrg).mockResolvedValue(selectedOrg) vi.mocked(fetchDestinationsContext).mockResolvedValue({owningOrg: {id: '67890', name: 'Inferred Org'}}) vi.mocked(terminalSupportsPrompting).mockReturnValue(true) + mockAndCaptureOutput().clear() }) test('selects the organization by ID when an organization ID is provided', async () => { @@ -72,6 +74,32 @@ describe('resolveOrganizationForStore', () => { expect(organization).toEqual(selectedOrg) }) + test('explains why the organization prompt is appearing, naming the store the developer provided', async () => { + vi.mocked(fetchDestinationsContext).mockResolvedValue({owningOrg: undefined}) + const output = mockAndCaptureOutput() + + await resolveOrganizationForStore(STORE) + + expect(output.info()).toMatchInlineSnapshot(` + "╭─ info ───────────────────────────────────────────────────────────────────────╮ + │ │ + │ Could not determine which organization owns shop.myshopify.com. │ + │ │ + │ Select one below, or specify it with \`--organization-id\`. │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────╯ + " + `) + }) + + test('stays quiet when the owning organization is inferred', async () => { + const output = mockAndCaptureOutput() + + await resolveOrganizationForStore(STORE) + + expect(output.info()).toBe('') + }) + test('does not prompt non-interactively when ownership can be inferred', async () => { vi.mocked(terminalSupportsPrompting).mockReturnValue(false) diff --git a/packages/store/src/cli/utilities/store-lookup/organization.ts b/packages/store/src/cli/utilities/store-lookup/organization.ts index 362376d178e..752e7c1fcd1 100644 --- a/packages/store/src/cli/utilities/store-lookup/organization.ts +++ b/packages/store/src/cli/utilities/store-lookup/organization.ts @@ -3,6 +3,7 @@ import {selectOrg, type Organization} from '@shopify/organizations' import {AbortError} from '@shopify/cli-kit/node/error' import {outputDebug} from '@shopify/cli-kit/node/output' import {terminalSupportsPrompting} from '@shopify/cli-kit/node/system' +import {renderInfo} from '@shopify/cli-kit/node/ui' interface FindStoreOwningOrganizationOptions { store: string @@ -55,5 +56,12 @@ export async function resolveOrganizationForStore(store: string, organizationId? ) } + // The developer only gave a store domain, so explain why they're suddenly being asked to + // pick an organization. Echoing the domain back also makes a typo in it easy to spot. + renderInfo({ + headline: `Could not determine which organization owns ${store}.`, + body: ['Select one below, or specify it with', {command: '--organization-id'}, {char: '.'}], + }) + return selectOrg() }