Skip to content

Commit

Permalink
unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
amunger committed Oct 16, 2023
1 parent f5be1c0 commit 955e973
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,42 @@ export class NotebookCellAnchor implements IDisposable {

constructor(
private readonly notebookExecutionStateService: INotebookExecutionStateService,
private readonly configurationService: IConfigurationService) {
private readonly configurationService: IConfigurationService,
private readonly scrollEvent: Event<ScrollEvent>) {
}

public shouldAnchor(focusMode: CellFocusMode, growing: boolean) {
public shouldAnchor(focusMode: CellFocusMode, growing: boolean, executingCellUri: ICellViewModel) {
if (focusMode === CellFocusMode.Editor) {
return true;
}
if (this.stopAnchoring) {
return false;
}
const cellEditorIsFocused = focusMode === CellFocusMode.Editor;

const anchorFocusedSetting = this.configurationService.getValue(NotebookSetting.anchorToFocusedCell);
const allowScrolling = this.configurationService.getValue(NotebookSetting.scrollToRevealCell) !== 'none';
const autoAnchor = allowScrolling && growing && anchorFocusedSetting !== 'off';

return (cellEditorIsFocused || autoAnchor || anchorFocusedSetting === 'on');
if (autoAnchor || anchorFocusedSetting === 'on') {
this.watchAchorDuringExecution(executingCellUri);
return true;
}

return false;
}

public watchAchorDuringExecution(viewCell: ICellViewModel, scrollEvent: Event<ScrollEvent>) {
public watchAchorDuringExecution(executingCell: ICellViewModel) {
// anchor while the cell is executing unless the user scrolls up.
if (!this.executionWatcher && viewCell && viewCell.cellKind === CellKind.Code) {
const executionState = this.notebookExecutionStateService.getCellExecution(viewCell.uri);

if (!this.executionWatcher && executingCell.cellKind === CellKind.Code) {
const executionState = this.notebookExecutionStateService.getCellExecution(executingCell.uri);
if (executionState && executionState.state === NotebookCellExecutionState.Executing) {
this.executionWatcher = (viewCell as CodeCellViewModel).onDidStopExecution(() => {
this.executionWatcher = (executingCell as CodeCellViewModel).onDidStopExecution(() => {
this.executionWatcher?.dispose();
this.executionWatcher = undefined;
this.scrollWatcher?.dispose();
this.stopAnchoring = false;
});
this.scrollWatcher = scrollEvent((scrollEvent) => {
this.scrollWatcher = this.scrollEvent((scrollEvent) => {
if (scrollEvent.scrollTop < scrollEvent.oldScrollTop) {
this.stopAnchoring = true;
this.scrollWatcher?.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
const cursorSelectionListener = this._localDisposableStore.add(new MutableDisposable());
const textEditorAttachListener = this._localDisposableStore.add(new MutableDisposable());

this._notebookCellAnchor = new NotebookCellAnchor(notebookExecutionStateService, configurationService);
this._notebookCellAnchor = new NotebookCellAnchor(notebookExecutionStateService, configurationService, this.onDidScroll);

const recomputeContext = (element: CellViewModel) => {
switch (element.cursorAtBoundary()) {
Expand Down Expand Up @@ -1215,12 +1215,10 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
const focused = this.getFocus();
const focus = focused.length ? focused[0] : null;

// If the cell is growing, we should favor anchoring to the focused cell
if (focus) {
const focusMode = this.element(focused[0]).focusMode;
// If the cell is growing, we should favor anchoring to the focused cell
const growing = this.view.elementHeight(index) < size;
if (this._notebookCellAnchor.shouldAnchor(focusMode, growing)) {
this._notebookCellAnchor.watchAchorDuringExecution(this.element(index), this.onDidScroll);
if (this._notebookCellAnchor.shouldAnchor(this.element(focused[0]).focusMode, growing, this.element(index))) {
return this.view.updateElementHeight(index, size, focus);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookCellAnchor } from 'vs/workbench/contrib/notebook/browser/view/notebookCellAnchor';
import { Emitter } from 'vs/base/common/event';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { CellKind, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';


suite('NotebookCellAnchor', () => {

const store = ensureNoDisposablesAreLeakedInTestSuite();

const config = new TestConfigurationService();
const scrollEvent = new Emitter<ScrollEvent>();
const onDidStopExecution = new Emitter<void>();
const executionService = {
getCellExecution: () => { return { state: NotebookCellExecutionState.Executing }; },
} as unknown as INotebookExecutionStateService;
const cell = {
cellKind: CellKind.Code,
onDidStopExecution: onDidStopExecution.event
} as unknown as CodeCellViewModel;

test('Basic anchoring', async function () {
const cellAnchor = store.add(new NotebookCellAnchor(executionService, config, scrollEvent.event));

assert(cellAnchor.shouldAnchor(CellFocusMode.Editor, false, cell), 'should anchor if cell editor is focused');
assert(cellAnchor.shouldAnchor(CellFocusMode.Editor, true, cell), 'should anchor if cell editor is focused');

assert(cellAnchor.shouldAnchor(CellFocusMode.Container, true, cell), 'should anchor if cell is growing');
assert(cellAnchor.shouldAnchor(CellFocusMode.Output, true, cell), 'should anchor if cell is growing');

assert(!cellAnchor.shouldAnchor(CellFocusMode.Container, false, cell), 'should not focus if not growing and editor not focused');
});

test('Anchor during execution until user scrolls up', async function () {
const cellAnchor = store.add(new NotebookCellAnchor(executionService, config, scrollEvent.event));

assert(cellAnchor.shouldAnchor(CellFocusMode.Container, true, cell));

scrollEvent.fire({ oldScrollTop: 100, scrollTop: 150 } as ScrollEvent);
assert(cellAnchor.shouldAnchor(CellFocusMode.Container, true, cell), 'cell should still be anchored after scrolling down');

scrollEvent.fire({ oldScrollTop: 150, scrollTop: 100 } as ScrollEvent);
assert(!cellAnchor.shouldAnchor(CellFocusMode.Container, true, cell), 'cell should not be anchored after scrolling up');
assert(cellAnchor.shouldAnchor(CellFocusMode.Editor, true, cell), 'cell should anchor again if the editor is focused');

onDidStopExecution.fire();
assert(cellAnchor.shouldAnchor(CellFocusMode.Container, true, cell), 'cell should anchor for new execution');
});
});

0 comments on commit 955e973

Please sign in to comment.