Skip to content

Commit

Permalink
feat: adds a test session and test project class for NUTs
Browse files Browse the repository at this point in the history
  • Loading branch information
shetzel committed Feb 3, 2021
1 parent 6a40278 commit c17a39d
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 2 deletions.
2 changes: 0 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ workflows:
node_version: '10'
name: node-10
- release-management/release-package:
post-job-steps:
- run: yarn ci-docs
requires:
- node-latest
- node-14
Expand Down
64 changes: 64 additions & 0 deletions src/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import * as path from 'path';
import { debug, Debugger } from 'debug';
import * as shell from 'shelljs';
import { genUniqueString } from './genUniqueString';
import { execCmd } from './execCmd';

export interface TestProjectConfig {
sourceDir?: string;
gitClone?: string;
name?: string;
dir?: string;
}

/**
* A SFDX project for use with testing.
*/
export class TestProject {
public createdDate: Date;
public path: string;
private debug: Debugger;

public constructor(options: TestProjectConfig) {
this.debug = debug('testkit:project');
this.createdDate = new Date();

const dir = options.dir || path.join(process.cwd(), 'tmp');

// Copy a dir containing a SFDX project to a dir for testing.
if (options?.sourceDir) {
shell.cp(options.sourceDir, dir);
this.path = path.join(dir, path.dirname(options.sourceDir));
}
// Clone a git repo containing a SFDX project in a dir for testing.
else if (options?.gitClone) {
const rc = shell.exec(`git clone ${options.gitClone} ${dir}`, { silent: true });
this.debug('git clone rc=', rc);
if (rc.code !== 0) {
throw new Error(`git clone failed \n${rc.stderr}`);
}
this.path = path.join(dir, 'changeme');
}
// Create a new project using the command.
else {
const name = options.name || genUniqueString('project_%s');
execCmd(`force:project:create -n ${name}`, { ensureExitCode: 0 });
this.path = path.join(dir, name);
}
this.debug(`Created test project: ${this.path}`);
}

/**
* Return a list of org usernames this project knows about.
*/
public getOrgs(): string {
return 'NOT YET IMPLEMENTED';
}
}
127 changes: 127 additions & 0 deletions src/session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import * as path from 'path';
import * as os from 'os';
import { debug, Debugger } from 'debug';
import { fs as fsCore } from '@salesforce/core';
import { env } from '@salesforce/kit';
import { createSandbox, SinonStub } from 'sinon';
import { genUniqueString } from './genUniqueString';
import { TestProject, TestProjectConfig } from './project';

export interface SessionOptions {
sessionDir?: string;
project?: TestProjectConfig;
}

/*
*** ENV VARS ***
TESTKIT_SESSION_DIR = path to a directory for all testkit artifacts to live
TESTKIT_SFDX_DIR = path to a .sfdx directory
*/

// Map of existing test sessions
const sessions = new Map<SessionOptions, Session>();

/**
* Represents a test session.
*/
export class Session {
public id: string;
public createdDate: Date;
public dir: string;
public sfdxDir: string;
public projects: TestProject[] = [];
public sandbox = createSandbox();

private debug: Debugger;
private cwdStub?: SinonStub;

private constructor(options: SessionOptions = {}) {
this.debug = debug('testkit:session');
this.createdDate = new Date();
this.id = genUniqueString(`${this.createdDate.valueOf()}%s`);

// Create the test session directory
const defaultDir = path.join(process.cwd(), `test_session_${this.id}`);
this.dir = env.getString('TESTKIT_SESSION_DIR', defaultDir);
fsCore.mkdirpSync(this.dir);

// Create the .sfdx directory used by this test
const defaultSfdxDir = path.join(this.dir, '.sfdx');
this.sfdxDir = env.getString('TESTKIT_SFDX_DIR', defaultSfdxDir);
fsCore.mkdirpSync(this.sfdxDir);
this.sandbox.stub(os, 'homedir').returns(this.dir);

// Setup a test project
if (options.project) {
const project = this.addProject(options.project);
this.stubCwd(project.path);
}

const props = Object.getOwnPropertyNames(this);
this.debug(`Created testkit session: ${props}`);
}

/**
* Get an existing test session created with the same options,
* or create a new session if a match is not found. This allows
* sharing of test sessions between multiple test files.
*/
public static get(options: SessionOptions = {}): Session {
return sessions.get(options) ?? new Session(options);
}

/**
* Create a test session with the provided options.
*/
public static create(options: SessionOptions = {}): Session {
return new Session(options);
}

/**
* Stub process.cwd() to return the provided directory path.
*
* @param dir The directory path to set as the current working directory
*/
public stubCwd(dir: string): void {
if (this.cwdStub) {
this.cwdStub.restore();
}
this.cwdStub = this.sandbox.stub(process, 'cwd').returns(dir);
}

/**
* Clean the test session by restoring the sandbox and
* deleting all orgs created during the test.
*/
public clean(): void {
this.sandbox.restore();
// delete test orgs unless TESTKIT_SAVE_ARTIFACTS set
// this.projects.
}

/**
* Zip the test session contents
*/
public zip(): string {
return 'NOT YET IMPLEMENTED';
}

/**
* Add another SFDX project to the test session.
*
* @param config a test project config to use for the new project
*/
public addProject(config: TestProjectConfig): TestProject {
const projConfig = { ...{ dir: this.dir }, ...config };
const project = new TestProject(projConfig);
this.projects.push(project);
return project;
}
}

0 comments on commit c17a39d

Please sign in to comment.