Unverified Commit d5cd1f07 authored by Denys Mishunov's avatar Denys Mishunov
Browse files

feat(chat): show chat only when it can be used by user

parent 771b0ef7
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@
          "type": "webview",
          "id": "gl.chatView",
          "name": "Experiment",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable"
        }
      ]
    },
@@ -103,23 +103,23 @@
      "commandPalette": [
        {
          "command": "gl.openChat",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable"
        },
        {
          "command": "gl.explainSelectedCode",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection"
        },
        {
          "command": "gl.generateTests",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection"
        },
        {
          "command": "gl.refactorCode",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection"
        },
        {
          "command": "gl.newChatConversation",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable"
        }
      ],
      "editor/context": [
@@ -132,44 +132,44 @@
        {
          "command": "gl.explainSelectedCode",
          "group": "navigation",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection"
        },
        {
          "command": "gl.generateTests",
          "group": "navigation",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection"
        },
        {
          "command": "gl.refactorCode",
          "group": "navigation",
          "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection"
          "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection"
        }
      ]
    },
    "keybindings": [
      {
        "command": "gl.openChat",
        "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount",
        "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable",
        "key": "alt+d"
      },
      {
        "command": "gl.explainSelectedCode",
        "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection",
        "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection",
        "key": "alt+e"
      },
      {
        "command": "gl.generateTests",
        "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection",
        "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection",
        "key": "alt+t"
      },
      {
        "command": "gl.refactorCode",
        "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount && editorHasSelection",
        "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && editorHasSelection",
        "key": "alt+r"
      },
      {
        "command": "gl.newChatConversation",
        "when": "config.gitlab.duoChat.enabled && !gitlab:noAccount",
        "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable",
        "key": "alt+n"
      }
    ],
+4 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import { activateCommon } from '../common/main';
import * as featureFlags from '../common/feature_flags';
import { registerLanguageServer } from '../common/language_server/register_language_server';
import { CodeSuggestions } from '../common/code_suggestions/code_suggestions';
import { getChatSupport } from '../common/chat/api/get_chat_support';
import { browserLanguageClientFactory } from './language_server/browser_language_client_factory';
import { createDependencyContainer } from './dependency_container_browser';

@@ -16,6 +17,9 @@ export const activate = async (context: vscode.ExtensionContext) => {
  await vscode.commands.executeCommand('setContext', 'gitlab:noAccount', false);
  await vscode.commands.executeCommand('setContext', 'gitlab:validState', true);

  const duoChatAvailable: boolean = await getChatSupport(dependencyContainer.gitLabPlatformManager);
  await vscode.commands.executeCommand('setContext', 'gitlab:chatAvailable', duoChatAvailable);

  const platform = await dependencyContainer.gitLabPlatformManager.getForSaaSAccount();

  await vscode.commands.executeCommand(
+69 −0
Original line number Diff line number Diff line
import { GitLabPlatformManager } from '../../platform/gitlab_platform';
import { GitLabPlatformManagerForChat } from '../get_platform_manager_for_chat';
import { gitlabPlatformForAccount } from '../../test_utils/entities';
import { createFakePartial } from '../../test_utils/create_fake_partial';
import { log } from '../../log';
import { getChatSupport, ChatAvailableResponseType } from './get_chat_support';

jest.mock('../get_platform_manager_for_chat');

describe('getChatSupport', () => {
  let manager: GitLabPlatformManager;
  let platformManagerForChat: GitLabPlatformManagerForChat;
  const mockApiResponse = (duoChatAvailable: boolean = true) => {
    const apiResponse: ChatAvailableResponseType = {
      currentUser: {
        duoChatAvailable,
      },
    };
    jest.mocked(platformManagerForChat.getGitLabPlatform).mockResolvedValue({
      ...gitlabPlatformForAccount,
      fetchFromApi: jest.fn().mockResolvedValue(apiResponse),
    });
  };

  beforeEach(() => {
    manager = createFakePartial<GitLabPlatformManager>({
      getForAllAccounts: jest.fn(),
    });
    platformManagerForChat = createFakePartial<GitLabPlatformManagerForChat>({
      getGitLabPlatform: jest.fn(),
    });
    jest.mocked(GitLabPlatformManagerForChat).mockImplementation(() => platformManagerForChat);
    jest.spyOn(log, 'error');
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('returns false if there is no platform', async () => {
    jest.mocked(platformManagerForChat.getGitLabPlatform).mockResolvedValue(undefined);
    const result = await getChatSupport(manager);
    expect(result).toBe(false);
  });

  it('returns false and logs if fetching `duoChatAvailable` fails', async () => {
    jest.mocked(platformManagerForChat.getGitLabPlatform).mockResolvedValue({
      ...gitlabPlatformForAccount,
      fetchFromApi: jest.fn().mockRejectedValueOnce('foo'),
    });
    const result = await getChatSupport(manager);
    expect(result).toBe(false);
    expect(log.error).toHaveBeenCalledWith('foo');
  });

  it('returns false and does not log if the user does not have chat support', async () => {
    mockApiResponse(false);
    const result = await getChatSupport(manager);
    expect(result).toBe(false);
    expect(log.error).not.toHaveBeenCalled();
  });

  it('returns true if the user has chat support', async () => {
    mockApiResponse();
    const result = await getChatSupport(manager);
    expect(result).toBe(true);
    expect(log.error).not.toHaveBeenCalled();
  });
});
+40 −0
Original line number Diff line number Diff line
import { gql } from 'graphql-request';
import { GraphQLRequest } from '../../platform/web_ide';
import { GitLabPlatformManager } from '../../platform/gitlab_platform';
import { GitLabPlatformManagerForChat } from '../get_platform_manager_for_chat';
import { log } from '../../log';

const queryGetChatAvailability = gql`
  query duoChatAvailable {
    currentUser {
      duoChatAvailable
    }
  }
`;

export type ChatAvailableResponseType = {
  currentUser: {
    duoChatAvailable: boolean;
  };
};

export async function getChatSupport(manager: GitLabPlatformManager): Promise<boolean> {
  let user;
  const platformManagerForChat = new GitLabPlatformManagerForChat(manager);
  const request: GraphQLRequest<ChatAvailableResponseType> = {
    type: 'graphql',
    query: queryGetChatAvailability,
    variables: {},
  };
  const platform = await platformManagerForChat.getGitLabPlatform();
  if (!platform) {
    return false;
  }
  try {
    user = await platform.fetchFromApi(request);
    return user.currentUser.duoChatAvailable;
  } catch (e) {
    log.error(e);
    return false;
  }
}
+2 −1
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ export const activate = async (context: vscode.ExtensionContext) => {
    'GitLab.com Authentication',
    new GitLabAuthenticationProvider(),
  );
  await extensionState.init(accountService);

  registerSidebarTreeDataProviders();
  registerRepositoryRootProvider(
    issuableController,
@@ -274,6 +274,7 @@ export const activate = async (context: vscode.ExtensionContext) => {
  await migrateCredentials(context, accountService).catch(e => handleError(e));

  const dependencyContainer = createDependencyContainer();
  await extensionState.init(accountService, dependencyContainer.gitLabPlatformManager);

  if (featureFlags.isEnabled(featureFlags.FeatureFlag.LanguageServer)) {
    await registerLanguageServer(
Loading