blob: d1a070c4a5c59b6cba1884a9e7fd40c86b075890 [file]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {assert} from 'chai';
import {afterEach, beforeEach, it} from 'mocha';
import sinon from 'sinon';
import * as Common from '../../../core/common/common.js';
import * as Host from '../../../core/host/host.js';
import * as Root from '../../../core/root/root.js';
import {renderElementIntoDOM} from '../../../testing/DOMHelpers.js';
import {describeWithEnvironment, updateHostConfig} from '../../../testing/EnvironmentHelpers.js';
import {createViewFunctionStub} from '../../../testing/ViewFunctionHelpers.js';
import * as UI from '../../legacy/legacy.js';
import * as Dialogs from '../dialogs/dialogs.js';
import * as Snackbars from '../snackbars/snackbars.js';
import * as TextEditor from './text_editor.js';
const {AiCodeCompletionTeaser} = TextEditor.AiCodeCompletionTeaser;
const {FreDialog} = Dialogs.FreDialog;
describeWithEnvironment('AiCodeCompletionTeaser', () => {
let showFreDialogStub: sinon.SinonStub<Parameters<typeof FreDialog.show>, Promise<boolean>>;
let checkAccessPreconditionsStub: sinon.SinonStub;
beforeEach(() => {
showFreDialogStub = sinon.stub(FreDialog, 'show');
checkAccessPreconditionsStub = sinon.stub(Host.AidaClient.AidaClient, 'checkAccessPreconditions');
checkAccessPreconditionsStub.resolves(Host.AidaClient.AidaAccessPreconditions.AVAILABLE);
});
async function createTeaser() {
const view = createViewFunctionStub(AiCodeCompletionTeaser);
const widget = new AiCodeCompletionTeaser({onDetach: sinon.stub()}, view);
widget.markAsRoot();
renderElementIntoDOM(widget);
await view.nextInput;
return {view, widget};
}
afterEach(() => {
Common.Settings.Settings.instance().settingForTest('ai-code-completion-teaser-dismissed').set(false);
Common.Settings.Settings.instance().settingForTest('ai-code-completion-enabled').set(false);
});
it('should dismiss and open snackbar on dismiss click', async () => {
const {view, widget} = await createTeaser();
const showSnackbar = sinon.stub(Snackbars.Snackbar.Snackbar, 'show');
assert.isTrue(widget.isShowing());
assert.exists(view.input.onDismiss);
view.input.onDismiss(new Event('click'));
await widget.updateComplete;
sinon.assert.calledOnce(showSnackbar);
assert.isTrue(Common.Settings.Settings.instance().settingForTest('ai-code-completion-teaser-dismissed').get());
assert.isFalse(widget.isShowing());
});
it('should open settings on snackbar action click', async () => {
const {view, widget} = await createTeaser();
const showSnackbar = sinon.stub(Snackbars.Snackbar.Snackbar, 'show');
const showViewStub = sinon.stub(UI.ViewManager.ViewManager.instance(), 'showView');
assert.exists(view.input.onDismiss);
view.input.onDismiss(new Event('click'));
sinon.assert.calledOnce(showSnackbar);
const snackbarOptions = showSnackbar.firstCall.args[0];
assert.exists(snackbarOptions.actionProperties);
snackbarOptions.actionProperties.onClick();
assert.isTrue(showViewStub.calledOnceWith('chrome-ai'));
widget.detach();
});
it('should FRE text include no logging case when the enterprise policy value is ALLOW_WITHOUT_LOGGING', async () => {
updateHostConfig(
{aidaAvailability: {enterprisePolicyValue: Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING}});
const {view, widget} = await createTeaser();
view.input.onAction(new Event(''));
sinon.assert.called(showFreDialogStub);
assert.exists(showFreDialogStub.lastCall.args[0].reminderItems.find(
reminderItem =>
reminderItem.content.toString().includes('This data won’t be used to improve Google’s AI models.')));
widget.detach();
});
it('should FRE text not include no logging case when the enterprise policy value is ALLOW', async () => {
updateHostConfig({aidaAvailability: {enterprisePolicyValue: Root.Runtime.GenAiEnterprisePolicyValue.ALLOW}});
const {view, widget} = await createTeaser();
view.input.onAction(new Event(''));
sinon.assert.called(showFreDialogStub);
assert.notExists(showFreDialogStub.lastCall.args[0].reminderItems.find(
reminderItem =>
reminderItem.content.toString().includes('This data won’t be used to improve Google’s AI models.')));
widget.detach();
});
it('renders when AIDA becomes available', async () => {
checkAccessPreconditionsStub.resolves(Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL);
const {view, widget} = await createTeaser();
assert.strictEqual(view.input.aidaAvailability, Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL);
Host.AidaClient.HostConfigTracker.instance().dispatchEventToListeners(
Host.AidaClient.Events.AIDA_AVAILABILITY_CHANGED, Host.AidaClient.AidaAccessPreconditions.AVAILABLE);
await view.nextInput;
assert.strictEqual(view.input.aidaAvailability, Host.AidaClient.AidaAccessPreconditions.AVAILABLE);
widget.detach();
});
it('does not render when AIDA becomes unavailable', async () => {
checkAccessPreconditionsStub.resolves(Host.AidaClient.AidaAccessPreconditions.AVAILABLE);
const {view, widget} = await createTeaser();
assert.strictEqual(view.input.aidaAvailability, Host.AidaClient.AidaAccessPreconditions.AVAILABLE);
Host.AidaClient.HostConfigTracker.instance().dispatchEventToListeners(
Host.AidaClient.Events.AIDA_AVAILABILITY_CHANGED, Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL);
await view.nextInput;
assert.strictEqual(view.input.aidaAvailability, Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL);
widget.detach();
});
});