diff --git a/apps/dev/src/__tests__/doctor.test.ts b/apps/dev/src/__tests__/doctor.test.ts index 806680ff5..af4a3b436 100644 --- a/apps/dev/src/__tests__/doctor.test.ts +++ b/apps/dev/src/__tests__/doctor.test.ts @@ -640,6 +640,40 @@ describe('runDoctor', () => { ); }); + it.each([ + 'R_SLACK_CLIENT_ID', + 'R_SLACK_CLIENT_SECRET', + 'R_MICROSOFT_CLIENT_ID', + 'R_MICROSOFT_CLIENT_SECRET', + 'R_MICROSOFT_TENANT_ID', + ])('warns when %s contains only whitespace', async (key) => { + const isSlack = key.startsWith('R_SLACK_'); + mockExeca({ + includeDefaultAuth: false, + extraWebEnv: { + ...(isSlack + ? { + R_SLACK_CLIENT_ID: 'slack-client-id', + R_SLACK_CLIENT_SECRET: 'slack-client-secret', + } + : { + R_MICROSOFT_CLIENT_ID: 'microsoft-client-id', + R_MICROSOFT_CLIENT_SECRET: 'microsoft-client-secret', + R_MICROSOFT_TENANT_ID: 'microsoft-tenant-id', + }), + [key]: ' \t\n ', + }, + }); + + expect(await runDoctor()).toContainEqual({ + name: 'Auth providers', + status: 'warn', + detail: isSlack + ? 'incomplete Slack client ID/secret pair' + : 'incomplete Microsoft Teams client ID/secret/tenant set', + }); + }); + it('fails when an HTTP health endpoint returns a non-2xx response', async () => { mockFetch(503); diff --git a/apps/dev/src/doctor.ts b/apps/dev/src/doctor.ts index 1a106bf9b..f47d4bf6e 100644 --- a/apps/dev/src/doctor.ts +++ b/apps/dev/src/doctor.ts @@ -467,7 +467,7 @@ function checkAuthProviders( const configuredProviders: string[] = []; const incompleteProviders: string[] = []; const configEnv = Object.keys(env).length > 0 ? env : process.env; - const hasValue = (key: string) => Boolean(configEnv[key]); + const hasValue = (key: string) => Boolean(configEnv[key]?.trim()); const checkProvider = ({ name, requiredKeyGroups,