Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Node Detail Page in Scenegraph Node Inspector and Added Roku Test Automation Panel #499

Merged
merged 24 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fba7124
roku automation panel progress commit, standardize event messages to …
triwav Jun 14, 2023
6705371
finish up roku automation panel
triwav Aug 7, 2023
3001f27
Merge branch 'master' into add_roku_automation_panel
triwav Aug 7, 2023
e246128
remove unneeded code
triwav Aug 22, 2023
e2b8d64
progress commit on new node detail page
triwav Aug 29, 2023
2d383af
Merge branch 'add_roku_automation_panel' into clean_up_node_detail_page
triwav Aug 29, 2023
0b7ec55
increase screenshotOutOfDateTimeOut to 10 seconds
triwav Aug 29, 2023
e5125dd
Move Autorun on deploy out of RokuAutomationView into view header
triwav Aug 29, 2023
7907ab5
Add support for getting persistent keypath in more spots
triwav Aug 30, 2023
d5e918c
Make RokuAutomatView layout responsive
triwav Aug 30, 2023
95d415e
Add clear button and make run and stop buttons have fixed positions
triwav Aug 30, 2023
b3198a2
move NumberField to shared folder
triwav Aug 30, 2023
690bd5d
automation view improvements
triwav Aug 30, 2023
23a23f3
disable screenshotOutOfDate for now
triwav Aug 30, 2023
2b5da36
More cleanup of NodeDetailPage
triwav Aug 30, 2023
1af7b04
fix warning
triwav Aug 30, 2023
2003543
Store autorunOnDeploy in workspaceState
triwav Sep 5, 2023
8b41c19
fix reordering of steps
triwav Sep 5, 2023
beef781
Fix colorfield updating properly
triwav Sep 5, 2023
bd1e921
Fix NumberField stepping
triwav Sep 5, 2023
6515fd8
fix failing unit tests
triwav Sep 11, 2023
1f4887d
remove unneeded code
triwav Sep 11, 2023
c8991b2
Improvements discovered while reviewing with Bronley
triwav Sep 11, 2023
27b6fc3
Merge branch 'master' into clean_up_node_detail_page
TwitchBronBron Sep 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
966 changes: 435 additions & 531 deletions package-lock.json

Large diffs are not rendered by default.

52 changes: 51 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"pretty-bytes": "^5.6.0",
"roku-debug": "^0.20.3",
"roku-deploy": "^3.10.3",
"roku-test-automation": "^2.0.0-beta.19",
"roku-test-automation": "^2.0.0-beta.20",
"semver": "^7.1.3",
"source-map": "^0.7.3",
"thenby": "^1.3.4",
Expand Down Expand Up @@ -214,6 +214,11 @@
"id": "rokuCommandsView",
"name": "Roku Commands",
"type": "webview"
},
{
"id": "rokuAutomationView",
"name": "Roku Automation",
"type": "webview"
}
]
},
Expand Down Expand Up @@ -290,6 +295,26 @@
"command": "extension.brightscript.rokuDeviceView.disableNodeInspector",
"when": "view == rokuDeviceView && brightscript.isOnDeviceComponentAvailable && brightscript.rokuDeviceView.isInspectingNodes",
"group": "navigation@3"
},
{
"command": "extension.brightscript.rokuAutomationView.startRecording",
"when": "view == rokuAutomationView && !brightscript.rokuAutomationView.isRecording",
"group": "navigation"
},
{
"command": "extension.brightscript.rokuAutomationView.stopRecording",
"when": "view == rokuAutomationView && brightscript.rokuAutomationView.isRecording",
"group": "navigation"
},
{
"command": "extension.brightscript.rokuAutomationView.enableAutorunOnDeploy",
"when": "view == rokuAutomationView && !brightscript.rokuAutomationView.autorunOnDeploy",
"group": "navigation@2"
},
{
"command": "extension.brightscript.rokuAutomationView.disableAutorunOnDeploy",
"when": "view == rokuAutomationView && brightscript.rokuAutomationView.autorunOnDeploy",
"group": "navigation@2"
}
],
"commandPalette": []
Expand Down Expand Up @@ -2676,6 +2701,31 @@
"category": "BrighterScript",
"icon": "$(arrow-up)"
},
{
"command": "extension.brightscript.rokuAutomationView.startRecording",
"title": "Start Recording",
"category": "BrighterScript",
"icon": "$(record)"
},
{
"command": "extension.brightscript.rokuAutomationView.stopRecording",
"title": "Stop Recording",
"category": "BrighterScript",
"icon": "$(debug-stop)"
},

{
"command": "extension.brightscript.rokuAutomationView.enableAutorunOnDeploy",
"title": "Enable Autorun on deploy",
"category": "BrighterScript",
"icon": "$(pass)"
},
{
"command": "extension.brightscript.rokuAutomationView.disableAutorunOnDeploy",
"title": "Disable autorun on deploy",
"category": "BrighterScript",
"icon": "$(pass-filled)"
},
{
"command": "extension.brightscript.languageServer.restart",
"title": "Restart Language Server",
Expand Down
18 changes: 15 additions & 3 deletions src/BrightScriptCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class BrightScriptCommands {

private fileUtils: BrightScriptFileUtils;
private host: string;
private keypressNotifiers = [] as ((key: string, literalCharacter: boolean) => void)[];

public registerCommands() {

Expand Down Expand Up @@ -306,7 +307,15 @@ export class BrightScriptCommands {
}
}

public async sendRemoteCommand(key: string, host?: string) {
public async sendRemoteCommand(key: string, host?: string, literalCharacter = false) {
for (const notifier of this.keypressNotifiers) {
notifier(key, literalCharacter);
}

if (literalCharacter) {
key = 'Lit_' + encodeURIComponent(key);
}

// do we have a temporary override?
if (!host) {
// Get the long lived host ip
Expand Down Expand Up @@ -356,14 +365,17 @@ export class BrightScriptCommands {
}
}

public registerKeypressNotifier(notifier: (key: string, literalCharacter: boolean) => void) {
this.keypressNotifiers.push(notifier);
}

private registerCommand(name: string, callback: (...args: any[]) => any, thisArg?: any) {
const prefix = 'extension.brightscript.';
const commandName = name.startsWith(prefix) ? name : prefix + name;
this.context.subscriptions.push(vscode.commands.registerCommand(commandName, callback, thisArg));
}

private async sendAsciiToDevice(character: string) {
let commandToSend: string = 'Lit_' + encodeURIComponent(character);
await this.sendRemoteCommand(commandToSend);
await this.sendRemoteCommand(character, undefined, true);
}
}
8 changes: 7 additions & 1 deletion src/commands/VscodeCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@ export enum VscodeCommand {
rokuRegistryExportRegistry = 'extension.brightscript.rokuRegistry.exportRegistry',
rokuRegistryImportRegistry = 'extension.brightscript.rokuRegistry.importRegistry',
rokuRegistryClearRegistry = 'extension.brightscript.rokuRegistry.clearRegistry',
rokuRegistryRefreshRegistry = 'extension.brightscript.rokuRegistry.refreshRegistry'
rokuRegistryRefreshRegistry = 'extension.brightscript.rokuRegistry.refreshRegistry',
rokuAutomationViewEnableAutorunOnDeploy = 'extension.brightscript.rokuAutomationView.enableAutorunOnDeploy',
rokuAutomationViewDisableAutorunOnDeploy = 'extension.brightscript.rokuAutomationView.disableAutorunOnDeploy',
rokuAutomationViewStartRecording = 'extension.brightscript.rokuAutomationView.startRecording',
rokuAutomationViewStopRecording = 'extension.brightscript.rokuAutomationView.stopRecording',
enableRemoteControlMode = 'extension.brightscript.enableRemoteControlMode',
disableRemoteControlMode = 'extension.brightscript.disableRemoteControlMode'
}
28 changes: 7 additions & 21 deletions src/extension.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,6 @@ describe('extension', () => {
beforeEach(() => {
sinon.stub(languageServerManager, 'init').returns(Promise.resolve());

context = {
extensionPath: '',
subscriptions: [],
asAbsolutePath: () => { },
globalState: {
get: () => {

},
update: () => {

}
}
};

originalWebviews = extensionInstance['webviews'];
extensionInstance['webviews'] = [];
});
Expand All @@ -54,48 +40,48 @@ describe('extension', () => {
it('registers configuration provider', async () => {
let spy = sinon.spy(vscode.debug, 'registerDebugConfigurationProvider');
expect(spy.calledOnce).to.be.false;
await extension.activate(context);
await extension.activate(vscode.context);
expect(spy.calledOnce).to.be.true;
});

it('registers formatter', async () => {
let spy = sinon.spy(vscode.languages, 'registerDocumentRangeFormattingEditProvider');
expect(spy.getCalls().length).to.equal(0);
await extension.activate(context);
await extension.activate(vscode.context);
expect(spy.getCalls().length).to.be.greaterThan(1);
});

it('registers definition provider', async () => {
let spy = sinon.spy(vscode.languages, 'registerDefinitionProvider');
expect(spy.calledOnce).to.be.false;
await extension.activate(context);
await extension.activate(vscode.context);
expect(spy.callCount).to.be.greaterThan(0);
});

it('registers all commands', async () => {
let stub = sinon.stub(BrightScriptCommands.prototype, 'registerCommands').callsFake(() => { });
await extension.activate(context);
await extension.activate(vscode.context);
expect(stub.callCount).to.equal(1);
});

it('registers onDidStartDebugSession', async () => {
let spy = sinon.spy(vscode.debug, 'onDidStartDebugSession');
expect(spy.calledOnce).to.be.false;
await extension.activate(context);
await extension.activate(vscode.context);
expect(spy.calledOnce).to.be.true;
});

it('registers onDidTerminateDebugSession', async () => {
let spy = sinon.spy(vscode.debug, 'onDidTerminateDebugSession');
expect(spy.calledOnce).to.be.false;
await extension.activate(context);
await extension.activate(vscode.context);
expect(spy.calledOnce).to.be.true;
});

it('registers onDidReceiveDebugSessionCustomEvent', async () => {
let spy = sinon.spy(vscode.debug, 'onDidReceiveDebugSessionCustomEvent');
expect(spy.calledOnce).to.be.false;
await extension.activate(context);
await extension.activate(vscode.context);
expect(spy.getCalls().length).to.be.greaterThan(0);
});
});
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class Extension {
);

this.rtaManager = new RtaManager();
this.webviewViewProviderManager = new WebviewViewProviderManager(context, this.rtaManager);
this.webviewViewProviderManager = new WebviewViewProviderManager(context, this.rtaManager, this.brightScriptCommands);
this.rtaManager.setWebviewViewProviderManager(this.webviewViewProviderManager);

//update the tracked version of the extension
Expand Down
6 changes: 6 additions & 0 deletions src/managers/RemoteControlManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as vscode from 'vscode';
import { vscodeContextManager } from './VscodeContextManager';
import type { TelemetryManager } from './TelemetryManager';
import { VscodeCommand } from '../commands/VscodeCommand';

export class RemoteControlManager {
constructor(
Expand Down Expand Up @@ -70,6 +71,11 @@ export class RemoteControlManager {
}

public async setRemoteControlMode(isEnabled: boolean, initiator: RemoteControlModeInitiator) {
if (this.isEnabled && !isEnabled) {
// Want to also stop Roku automation recording if it was running
await vscode.commands.executeCommand(VscodeCommand.rokuAutomationViewStopRecording);
}

//only send a telemetry event if we know who initiated the mode. `undefined` usually means our internal system set the value...so don't track that
if (initiator) {
this.telemetryManager.sendSetRemoteControlModeEvent(isEnabled, initiator);
Expand Down
8 changes: 6 additions & 2 deletions src/managers/RtaManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class RtaManager {

public setupRtaWithConfig(config: { host: string; password: string; logLevel?: string; disableScreenSaver?: boolean; injectRdbOnDeviceComponent?: boolean }) {
const enableDebugging = ['info', 'debug', 'trace'].includes(config.logLevel);
rta.odc.setConfig({
const rtaConfig: rta.ConfigOptions = {
RokuDevice: {
devices: [{
host: config.host,
Expand All @@ -26,7 +26,11 @@ export class RtaManager {
disableTelnet: true,
disableCallOriginationLine: true
}
});
};

rta.odc.setConfig(rtaConfig);

rta.ecp.setConfig(rtaConfig);

this.device = rta.device;

Expand Down
11 changes: 7 additions & 4 deletions src/managers/WebviewViewProviderManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { vscode } from '../mockVscode.spec';
import type { BrightScriptLaunchConfiguration } from '../DebugConfigurationProvider';
import { WebviewViewProviderManager } from './WebviewViewProviderManager';
import { RtaManager } from './RtaManager';
import { BrightScriptCommands } from '../BrightScriptCommands';


const sinon = createSandbox();
Expand All @@ -14,6 +15,7 @@ describe('WebviewViewProviderManager', () => {
const config = {} as BrightScriptLaunchConfiguration;
let webviewViewProviderManager: WebviewViewProviderManager;
let rtaManager: RtaManager;
const brightScriptCommands = new BrightScriptCommands({} as any, {} as any, {} as any, {} as any);

before(() => {
context = {
Expand Down Expand Up @@ -46,16 +48,17 @@ describe('WebviewViewProviderManager', () => {
before(() => {
spy = sinon.spy(vscode.window, 'registerWebviewViewProvider');
rtaManager = new RtaManager();
webviewViewProviderManager = new WebviewViewProviderManager(context, rtaManager);
webviewViewProviderManager = new WebviewViewProviderManager(context, rtaManager, brightScriptCommands);
});

it('initializes webview providers and calls registerWebviewViewProvider for each', () => {
expect(spy.callCount).to.equal(webviewViewProviderManager.getWebviewViewProviders().length);
});

it('assigns RtaManager to each webviewViewProvider', () => {
it('assigns dependencies to each webviewViewProvider', () => {
for (const webviewViewProvider of webviewViewProviderManager.getWebviewViewProviders()) {
expect(webviewViewProvider['rtaManager']).to.equal(rtaManager);
expect(webviewViewProvider['dependencies']['rtaManager']).to.equal(rtaManager);
expect(webviewViewProvider['dependencies']['brightScriptCommands']).to.equal(brightScriptCommands);
}
expect(spy.callCount).to.equal(webviewViewProviderManager.getWebviewViewProviders().length);
});
Expand All @@ -74,7 +77,7 @@ describe('WebviewViewProviderManager', () => {
};

rtaManager = new RtaManager();
webviewViewProviderManager = new WebviewViewProviderManager(context, rtaManager);
webviewViewProviderManager = new WebviewViewProviderManager(context, rtaManager, brightScriptCommands);
rtaManager.setWebviewViewProviderManager(webviewViewProviderManager);
});

Expand Down
28 changes: 18 additions & 10 deletions src/managers/WebviewViewProviderManager.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import type { ChannelPublishedEvent } from 'roku-debug';
import type { BrightScriptLaunchConfiguration } from '../DebugConfigurationProvider';
import type { RtaManager } from './RtaManager';
import type { BrightScriptCommands } from '../BrightScriptCommands';
import * as vscode from 'vscode';
import { RokuCommandsViewProvider } from '../viewProviders/RokuCommandsViewProvider';
import { RokuDeviceViewViewProvider } from '../viewProviders/RokuDeviceViewViewProvider';
import { RokuRegistryViewProvider } from '../viewProviders/RokuRegistryViewProvider';
import { SceneGraphInspectorViewProvider } from '../viewProviders/SceneGraphInspectorViewProvider';

import { RokuAutomationViewViewProvider } from '../viewProviders/RokuAutomationViewViewProvider';

export class WebviewViewProviderManager {
constructor(context: vscode.ExtensionContext, rtaManager: RtaManager) {
this.rtaManager = rtaManager;
constructor(
private context: vscode.ExtensionContext,
private rtaManager: RtaManager,
private brightScriptCommands: BrightScriptCommands
) {

for (const webview of this.webviewViews) {
if (!webview.provider) {
webview.provider = new webview.constructor(context);
webview.provider = new webview.constructor(context, {
rtaManager: rtaManager,
brightScriptCommands: brightScriptCommands
});
vscode.window.registerWebviewViewProvider(webview.provider.id, webview.provider);

webview.provider.setWebviewViewProviderManager(this);

if (typeof webview.provider.setRtaManager === 'function') {
webview.provider.setRtaManager(this.rtaManager);
}
}
}
}

private rtaManager?: RtaManager;

private webviewViews = [{
constructor: SceneGraphInspectorViewProvider,
provider: undefined as SceneGraphInspectorViewProvider
Expand All @@ -40,6 +41,9 @@ export class WebviewViewProviderManager {
}, {
constructor: RokuDeviceViewViewProvider,
provider: undefined as RokuDeviceViewViewProvider
}, {
constructor: RokuAutomationViewViewProvider,
provider: undefined as RokuAutomationViewViewProvider
}];

public getWebviewViewProviders() {
Expand All @@ -54,6 +58,10 @@ export class WebviewViewProviderManager {
public onChannelPublishedEvent(e: ChannelPublishedEvent) {
const config = e.body.launchConfiguration as BrightScriptLaunchConfiguration;
this.rtaManager.setupRtaWithConfig(config);

for (const webview of this.webviewViews) {
void webview.provider.onChannelPublishedEvent(e);
}
}

// Mainly for communicating between webviews
Expand Down
10 changes: 9 additions & 1 deletion src/mockVscode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,16 @@ export let vscode = {
return this._data[key];
}
} as any,
workspaceState: {
_data: {},
update: function(key: string, value: any) {
this._data[key] = value;
},
get: function(key: string) {
return this._data[key];
}
} as any,
globalStorageUri: undefined as Uri,
workspaceState: {} as any,
environmentVariableCollection: {} as any,
logUri: undefined as Uri,
logPath: '',
Expand Down
Loading
Loading