From 03cb39acb4058c74f294c6bcc3121d26a84fd5f9 Mon Sep 17 00:00:00 2001 From: Kevin Gilpin Date: Sun, 4 Jun 2023 20:41:45 -0400 Subject: [PATCH] feat: Prompt to install under broader conditions Prompt to install if a project satisfies all of: * Has a supported language * Has a supported framework * Does not already have an appmap.yml --- src/actions/promptInstall.ts | 8 ++-- src/extension.ts | 3 +- .../integration/actions/promptInstall.test.ts | 42 +++++++++---------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/actions/promptInstall.ts b/src/actions/promptInstall.ts index c5a2cc8c..44a6c586 100644 --- a/src/actions/promptInstall.ts +++ b/src/actions/promptInstall.ts @@ -3,6 +3,7 @@ import { WorkspaceServices } from '../services/workspaceServices'; import * as vscode from 'vscode'; import { INSTALL_PROMPT, Telemetry } from '../telemetry'; import ExtensionState from '../configuration/extensionState'; +import { hasSupportedFramework, isLanguageSupported } from '../workspace/projectMetadata'; export enum ButtonText { Confirm = 'Open instructions', @@ -23,10 +24,9 @@ const promptResponses: ReadonlyArray = [ ]; const meetsPromptCriteria = (project: ProjectStateServiceInstance): boolean => - project.installable && - !project.metadata.agentInstalled && - project.metadata.language?.name === 'Ruby' && - project.metadata.webFramework?.name === 'Rails'; + isLanguageSupported(project.metadata) && + hasSupportedFramework(project.metadata) && + !project.metadata.agentInstalled; export default async function promptInstall( services: WorkspaceServices, diff --git a/src/extension.ts b/src/extension.ts index 185e3a94..937b12b6 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -261,8 +261,7 @@ export async function activate(context: vscode.ExtensionContext): Promise { Telemetry.sendEvent(TELEMETRY_ENABLED, { diff --git a/test/integration/actions/promptInstall.test.ts b/test/integration/actions/promptInstall.test.ts index a2468cc4..c6fdbe31 100644 --- a/test/integration/actions/promptInstall.test.ts +++ b/test/integration/actions/promptInstall.test.ts @@ -7,8 +7,9 @@ import promptInstall, { ButtonText } from '../../../src/actions/promptInstall'; import ExtensionState from '../../../src/configuration/extensionState'; import { ProjectStateServiceInstance } from '../../../src/services/projectStateService'; import { ProjectA, unsafeCast } from '../util'; +import Feature from '../../../src/workspace/feature'; -const stubWorkspaceServices = (installable = true, language = 'Ruby', webFramework = 'Rails') => +const stubWorkspaceServices = (language: Feature, webFramework?: Feature) => unsafeCast({ getService: () => sinon.stub(), getServiceInstances: () => @@ -17,20 +18,26 @@ const stubWorkspaceServices = (installable = true, language = 'Ruby', webFramewo folder: { name: path.basename(ProjectA), uri: vscode.Uri.parse(ProjectA), index: -1 }, metadata: { agentInstalled: false, - language: { name: language }, - webFramework: { name: webFramework }, + language, + languages: [language], + webFramework, }, - installable, }, ]), }); describe('promptInstall', () => { - const workspaceServices = stubWorkspaceServices(); + const langAndFrameworkProject = stubWorkspaceServices( + { name: 'Ruby', score: 2, text: 'GA language' }, + { name: 'Rails', score: 2, text: 'GA framework' } + ); + const langOnlyProject = stubWorkspaceServices({ name: 'Ruby', score: 2, text: 'GA language' }); afterEach(() => sinon.restore()); context('in an installable project', () => { + const project = langAndFrameworkProject; + let hideInstallPrompt = false; const extensionState = unsafeCast({ getHideInstallPrompt: () => hideInstallPrompt, @@ -47,7 +54,7 @@ describe('promptInstall', () => { it('prompts the user to install AppMap', async () => { const showInformationMessage = sinon.stub(vscode.window, 'showInformationMessage').resolves(); - await promptInstall(workspaceServices, extensionState); + await promptInstall(project, extensionState); assert( showInformationMessage.calledWith( @@ -61,7 +68,7 @@ describe('promptInstall', () => { sinon.stub(vscode.window, 'showInformationMessage').resolves({ title: ButtonText.Confirm }); const executeCommand = sinon.stub(vscode.commands, 'executeCommand').resolves(); - await promptInstall(workspaceServices, extensionState); + await promptInstall(project, extensionState); assert(executeCommand.calledWith('appmap.openInstallGuide', 'project-picker')); }); @@ -73,7 +80,7 @@ describe('promptInstall', () => { const executeCommand = sinon.stub(vscode.commands, 'executeCommand').resolves(); for (let i = 0; i < 5; ++i) { - await promptInstall(workspaceServices, extensionState); + await promptInstall(project, extensionState); assert(!executeCommand.called); assert(showInformationMessage.calledOnce); assert((extensionState.setHideInstallPrompt as sinon.SinonStub).calledOnce); @@ -82,34 +89,23 @@ describe('promptInstall', () => { }); context('when the user requests to never prompt in this project', () => { - const workspaceServices = stubWorkspaceServices(); + const project = langAndFrameworkProject; const extensionState = unsafeCast({ getHideInstallPrompt: () => true }); it('does not prompt', async () => { const showInformationMessage = sinon.stub(vscode.window, 'showInformationMessage'); - await promptInstall(workspaceServices, extensionState); + await promptInstall(project, extensionState); assert(!showInformationMessage.called); }); }); context('when in an uninstallable project', () => { - const workspaceServices = stubWorkspaceServices(false); - const extensionState = unsafeCast({ getHideInstallPrompt: () => false }); - - it('does not prompt', async () => { - const showInformationMessage = sinon.stub(vscode.window, 'showInformationMessage'); - await promptInstall(workspaceServices, extensionState); - assert(!showInformationMessage.called); - }); - }); - - context('when in an installable java project', () => { - const workspaceServices = stubWorkspaceServices(true, 'Java', 'Spring'); + const project = langOnlyProject; const extensionState = unsafeCast({ getHideInstallPrompt: () => false }); it('does not prompt', async () => { const showInformationMessage = sinon.stub(vscode.window, 'showInformationMessage'); - await promptInstall(workspaceServices, extensionState); + await promptInstall(project, extensionState); assert(!showInformationMessage.called); }); });