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

Chore: Add jest unit test for salesforcedx-utils package #4470

Merged
merged 11 commits into from
Oct 14, 2022
2 changes: 1 addition & 1 deletion config/jest.base.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: [ "**/unit/**/?(*.)+(spec|test).[t]s?(x)" ],
testMatch: [ "**/(unit|jest)/**/?(*.)+(spec|test).[t]s?(x)" ],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unit tests will now be valid under a unit or jest directory.
The intention is the jest directory is the new location for jest true unit tests.

setupFilesAfterEnv: ['../../scripts/setup-jest.ts'],
reporters: ['default', [ "jest-junit", { outputName: "junit-custom-unitTests.xml" } ]],
coverageReporters: ['lcov', 'text']
Expand Down
5 changes: 1 addition & 4 deletions packages/salesforcedx-utils/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
const baseConfig = require('../../config/jest.base.config');

module.exports = Object.assign({},
baseConfig,
{
testMatch: [ "**/unit/**/?(*.)+(spec|test).[t]s?(x)" ],
}
baseConfig
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clean up unnecessary override.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏽
Also, TS is complaining about top line of this file for me:
2022-10-12_13-57-55

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool..yeah it's a js file so can be ignored. I can add a ignore comment I think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just an FYI this was only showing u in the utils projects which using eslint vs tslint. So I only updated that config file

);
16 changes: 11 additions & 5 deletions packages/salesforcedx-utils/src/cli/cliCommandExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import * as kill from 'tree-kill';
import { CancellationToken, CommandExecution } from '../types';
import { Command } from './command';

export const NO_PID_ERROR = 'No process associated with sfdx command.';
export const NO_STDOUT_ERROR = 'No stdout found for childProcess';
export const NO_STDERR_ERROR = 'No stderr found for childProcess';
export const CANCELATION_INTERVAL = 1000;
export const KILL_CODE = 'SIGKILL';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported constants so they can be verified in unit tests.


export class CliCommandExecution implements CommandExecution {
public readonly command: Command;
public readonly cancellationToken?: CancellationToken;
Expand All @@ -25,7 +31,7 @@ export class CliCommandExecution implements CommandExecution {
this.cancellationToken = cancellationToken;

if (!childProcess.pid) {
throw new Error('No process associated with sfdx command.');
throw new Error(NO_PID_ERROR);
}
this.childProcessPid = childProcess.pid;

Expand Down Expand Up @@ -53,17 +59,17 @@ export class CliCommandExecution implements CommandExecution {

// Output
if (!childProcess.stdout) {
throw new Error('No stdout found for childProcess');
throw new Error(NO_STDOUT_ERROR);
}
this.stdoutSubject = Observable.fromEvent(childProcess.stdout, 'data');
if (!childProcess.stderr) {
throw new Error('No stderr found for childProcess');
throw new Error(NO_STDERR_ERROR);
}
this.stderrSubject = Observable.fromEvent(childProcess.stderr, 'data');

// Cancellation watcher
if (cancellationToken) {
const timer = Observable.interval(1000);
const timer = Observable.interval(CANCELATION_INTERVAL);
timerSubscriber = timer.subscribe(async () => {
if (cancellationToken.isCancellationRequested) {
try {
Expand All @@ -76,7 +82,7 @@ export class CliCommandExecution implements CommandExecution {
}
}

public async killExecution(signal = 'SIGKILL') {
public async killExecution(signal = KILL_CODE) {
return killPromise(this.childProcessPid, signal);
}
}
Expand Down
93 changes: 4 additions & 89 deletions packages/salesforcedx-utils/src/cli/cliCommandExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@

import { SpawnOptions } from 'child_process';
import * as cross_spawn from 'cross-spawn';
import * as os from 'os';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/interval';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';

import { Command } from '../types';
import { CancellationToken } from '../types';
import { CommandExecution } from '../types/commandExecution';
import { TELEMETRY_HEADER } from '../constants';
import { CancellationToken, Command } from '../types';
import { CliCommandExecution } from './cliCommandExecution';

export class GlobalCliEnvironment {
public static readonly environmentVariables = new Map<string, string>();
}
import { GlobalCliEnvironment } from './globalCliEnvironment';

export class CliCommandExecutor {
protected static patchEnv(
Expand All @@ -39,9 +31,8 @@ export class CliCommandExecutor {
env[key] = value;
});

// telemetry header
if (env) {
env.SFDX_TOOL = 'salesforce-vscode-extensions';
env.SFDX_TOOL = TELEMETRY_HEADER;
}

// then specific environment from Spawn Options
Expand Down Expand Up @@ -83,79 +74,3 @@ export class CliCommandExecutor {
);
}
}

export class CompositeCliCommandExecutor {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put class in it's own file for cleaner organization and import.

private readonly command: Command;

public constructor(commands: Command) {
this.command = commands;
}

public execute(
cancellationToken?: CancellationToken
): CompositeCliCommandExecution {
return new CompositeCliCommandExecution(this.command, cancellationToken);
}
}

export class CompositeCliCommandExecution implements CommandExecution {
public readonly command: Command;
public readonly cancellationToken?: CancellationToken;
public readonly processExitSubject: Observable<number | undefined>;
public readonly processErrorSubject: Observable<Error | undefined>;
public readonly stdoutSubject: Observable<string>;
public readonly stderrSubject: Observable<string>;
private readonly exitSubject: Subject<number | undefined>;
private readonly errorSubject: Subject<Error | undefined>;
private readonly stdout: Subject<string>;
private readonly stderr: Subject<string>;

constructor(command: Command, cancellationToken?: CancellationToken) {
this.exitSubject = new Subject();
this.errorSubject = new Subject();
this.stdout = new Subject();
this.stderr = new Subject();
this.command = command;
this.cancellationToken = cancellationToken;
this.processExitSubject = this.exitSubject.asObservable();
this.processErrorSubject = this.errorSubject.asObservable();
this.stdoutSubject = this.stdout.asObservable();
this.stderrSubject = this.stderr.asObservable();

let timerSubscriber: Subscription | null;
if (cancellationToken) {
const timer = Observable.interval(1000);
timerSubscriber = timer.subscribe(async () => {
if (cancellationToken.isCancellationRequested) {
try {
this.exitSubject.next();
} catch (e) {
console.log(e);
}
}
});
}
this.processErrorSubject.subscribe(() => {
if (timerSubscriber) {
timerSubscriber.unsubscribe();
}
});

this.processExitSubject.subscribe(() => {
if (timerSubscriber) {
timerSubscriber.unsubscribe();
}
});
}

public successfulExit() {
this.exitSubject.next(0);
}

public failureExit(e?: Error | undefined) {
if (e) {
this.stderr.next(`${e}${os.EOL}`);
}
this.exitSubject.next(1);
}
}
10 changes: 7 additions & 3 deletions packages/salesforcedx-utils/src/cli/commandBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

import { Command } from './command';

export const JSON_FLAG = '--json';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this centralized place for these. Our libraries could do with the same treatment, if we were investing there.

export const LOG_LEVEL_FLAG = '--loglevel';
export const FATAL = 'fatal';

export class CommandBuilder {
public readonly command: string;
public description?: string;
Expand All @@ -23,7 +27,7 @@ export class CommandBuilder {
}

public withArg(arg: string): CommandBuilder {
if (arg === '--json') {
if (arg === JSON_FLAG) {
this.withJson();
} else {
this.args.push(arg);
Expand All @@ -37,8 +41,8 @@ export class CommandBuilder {
}

public withJson(): CommandBuilder {
this.args.push('--json');
this.args.push('--loglevel', 'fatal');
this.args.push(JSON_FLAG);
this.args.push(LOG_LEVEL_FLAG, FATAL);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as os from 'os';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
import { CancellationToken } from '../types/cancellationToken';
import { CommandExecution } from '../types/commandExecution';
import { Command } from './command';

export class CompositeCliCommandExecution implements CommandExecution {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing new here just moved to a separate file.

public readonly command: Command;
public readonly cancellationToken?: CancellationToken;
public readonly processExitSubject: Observable<number | undefined>;
public readonly processErrorSubject: Observable<Error | undefined>;
public readonly stdoutSubject: Observable<string>;
public readonly stderrSubject: Observable<string>;
private readonly exitSubject: Subject<number | undefined>;
private readonly errorSubject: Subject<Error | undefined>;
private readonly stdout: Subject<string>;
private readonly stderr: Subject<string>;

constructor(command: Command, cancellationToken?: CancellationToken) {
this.exitSubject = new Subject();
this.errorSubject = new Subject();
this.stdout = new Subject();
this.stderr = new Subject();
this.command = command;
this.cancellationToken = cancellationToken;
this.processExitSubject = this.exitSubject.asObservable();
this.processErrorSubject = this.errorSubject.asObservable();
this.stdoutSubject = this.stdout.asObservable();
this.stderrSubject = this.stderr.asObservable();

let timerSubscriber: Subscription | null;
if (cancellationToken) {
const timer = Observable.interval(1000);
timerSubscriber = timer.subscribe(async () => {
if (cancellationToken.isCancellationRequested) {
try {
this.exitSubject.next();
} catch (e) {
console.log(e);
}
}
});
}
this.processErrorSubject.subscribe(() => {
if (timerSubscriber) {
timerSubscriber.unsubscribe();
}
});

this.processExitSubject.subscribe(() => {
if (timerSubscriber) {
timerSubscriber.unsubscribe();
}
});
}

public successfulExit() {
this.exitSubject.next(0);
}

public failureExit(e?: Error | undefined) {
if (e) {
this.stderr.next(`${e}${os.EOL}`);
}
this.exitSubject.next(1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CancellationToken } from '../types';
import { Command } from './command';
import { CompositeCliCommandExecution } from './compositeCliCommandExecution';

export class CompositeCliCommandExecutor {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same story: 1 class exported to its own file.

private readonly command: Command;

public constructor(commands: Command) {
this.command = commands;
}

public execute(
cancellationToken?: CancellationToken
): CompositeCliCommandExecution {
return new CompositeCliCommandExecution(this.command, cancellationToken);
}
}
3 changes: 2 additions & 1 deletion packages/salesforcedx-utils/src/cli/forceConfigGet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { CommandOutput } from './commandOutput';
import { SfdxCommandBuilder } from './sfdxCommandBuilder';
/**
* @deprecated
* NOTE: This code is deprecated in favor of using ConfigUtil.ts
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why I deleted this NOTE honestly. Probably need to visit if this command is necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to put this back? Or add to the same line as deprecated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok..yeah I'll put it back. This is only used in the debuggers currently that can't access configUtils in the vscode-utils package FYI.



*/
export class ForceConfigGet {
public async getConfig(
Expand Down
3 changes: 3 additions & 0 deletions packages/salesforcedx-utils/src/cli/globalCliEnvironment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class GlobalCliEnvironment {
public static readonly environmentVariables = new Map<string, string>();
}
3 changes: 2 additions & 1 deletion packages/salesforcedx-utils/src/cli/sfdxCommandBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { CommandBuilder } from './commandBuilder';

export const SFDX_COMMAND = 'sfdx';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should probably put this in constants.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good idea!

export class SfdxCommandBuilder extends CommandBuilder {
public constructor() {
super('sfdx');
super(SFDX_COMMAND);
}
}
3 changes: 3 additions & 0 deletions packages/salesforcedx-utils/src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
export const CLIENT_ID = 'sfdx-vscode';
export const DEFAULT_CONNECTION_TIMEOUT_MS = 20000;
export const ENV_SFDX_DEFAULTUSERNAME = 'SFDX_DEFAULTUSERNAME';
export const ENV_HTTP_PROXY = 'HTTP_PROXY';
export const ENV_HTTPS_PROXY = 'HTTPS_PROXY';
export const ENV_SFDX_INSTANCE_URL = 'SFDX_INSTANCE_URL';
export const BASE_FILE_NAME = 'i18n';
export const BASE_FILE_EXTENSION = 'js';
export const DEFAULT_LOCALE = 'en';
export const MISSING_LABEL_MSG = '!!! MISSING LABEL !!!';
export const SFDX_CONFIG_ISV_DEBUGGER_SID = 'isvDebuggerSid';
export const SFDX_CONFIG_ISV_DEBUGGER_URL = 'isvDebuggerUrl';
export const TELEMETRY_HEADER = 'salesforce-vscode-extensions';
3 changes: 2 additions & 1 deletion packages/salesforcedx-utils/src/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

export { Config, Localization, Message, MessageBundle } from './localization';
export { Localization } from './localization';
export { Message } from './message';
Loading