Skip to content

Commit

Permalink
feat: project api version (#539)
Browse files Browse the repository at this point in the history
* feat: specify project api version

* refactor: clearer type for apiVersion

* docs: sample for api version

* refactor: remove unnecessary type

* refactor: ts exclusions for project options

* chore: remove copyright bits

* refactor: no string formatter for api version

* fix: small bug fixes

* chore: update test

---------

Co-authored-by: Steve Hetzel <[email protected]>
  • Loading branch information
mshanemc and shetzel committed Aug 9, 2023
1 parent 2963ffb commit a569636
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 66 deletions.
87 changes: 33 additions & 54 deletions SAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ WARNING: THIS IS A GENERATED FILE. DO NOT MODIFY DIRECTLY. USE topics.json
### TestSession Class

- [Testing with generated sfdx project](#testing-with-generated-sfdx-project)
- [Testing with generated sfdx project with a specific api version](#testing-with-generated-sfdx-project-with-a-specific-api-version)
- [Testing with local sfdx project](#testing-with-local-sfdx-project)
- [Testing with git cloned sfdx project](#testing-with-git-cloned-sfdx-project)
- [Testing with no sfdx project](#testing-with-no-sfdx-project)
Expand Down Expand Up @@ -101,12 +102,6 @@ describe('execCmd', () => {

```typescript
import { execCmd } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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
*/

describe('execCmd', () => {
// This would actually be set in the shell or CI environment.
Expand Down Expand Up @@ -173,12 +168,6 @@ A TestSession provides conveniences to testing plugin commands with options to a

```typescript
import { execCmd, TestSession, TestProject } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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
*/

describe('TestSession', () => {
let testSession: TestSession;
Expand All @@ -201,6 +190,35 @@ describe('TestSession', () => {
});
```

## Testing with generated sfdx project with a specific api version

**_Usecase: I have a plugin with commands that require a SFDX project that need a specific api version in the sfdx-project.json._**

```typescript
import { execCmd, TestSession, TestProject } from '@salesforce/cli-plugins-testkit';

describe('TestSession', () => {
let testSession: TestSession;

before(async () => {
testSession = await TestSession.create({
project: {
name: 'MyTestProject',
apiVersion: '57.0',
},
});
});

it('should run a command from within a generated project', () => {
execCmd('project:convert:source', { ensureExitCode: 0 });
});

after(async () => {
await testSession?.clean();
});
});
```

## Testing with local sfdx project

**_Usecase: I have a plugin with commands that require a SFDX project and the test project I want to use is in a local directory within my plugin repo._**
Expand Down Expand Up @@ -264,12 +282,6 @@ describe('TestSession', () => {

```typescript
import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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
*/

describe('TestSession', () => {
let testSession: TestSession;
Expand All @@ -294,12 +306,7 @@ describe('TestSession', () => {

```typescript
import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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 { tmpdir } from 'os';
import { expect } from 'chai';

Expand Down Expand Up @@ -381,12 +388,6 @@ describe('TestSession', () => {

```typescript
import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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
*/

describe('TestSession', () => {
let testSession: TestSession;
Expand Down Expand Up @@ -417,12 +418,6 @@ describe('TestSession', () => {

```typescript
import { execCmd, TestSession, TestProject } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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
*/

describe('TestSession', () => {
let testSession: TestSession;
Expand Down Expand Up @@ -455,12 +450,6 @@ describe('TestSession', () => {

```typescript
import { execCmd, TestSession, TestProject } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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
*/

describe('TestSession', () => {
let testSession: TestSession;
Expand Down Expand Up @@ -491,12 +480,7 @@ describe('TestSession', () => {

```typescript
import { execCmd, TestSession, TestProject } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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';

describe('TestSession', () => {
Expand Down Expand Up @@ -537,12 +521,7 @@ describe('TestSession', () => {

```typescript
import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit';
/*
* Copyright (c) 2023, 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 shelljs from 'shelljs';

/*
Expand Down
29 changes: 29 additions & 0 deletions samples/TestSession.sample1b.nut.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2023, 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 { execCmd } from '../src/execCmd';
import { TestSession } from '../src/testSession';

describe('TestSession', () => {
let testSession: TestSession;

before(async () => {
testSession = await TestSession.create({
project: {
name: 'MyTestProject',
apiVersion: '57.0',
},
});
});

it('should run a command from within a generated project', () => {
execCmd('project:convert:source', { ensureExitCode: 0 });
});

after(async () => {
await testSession?.clean();
});
});
5 changes: 5 additions & 0 deletions samples/topics.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
"usecase": "I have a plugin with commands that require a SFDX project but the tests don’t care about the contents of the project.",
"file": "TestSession.sample1.nut.ts"
},
{
"header": "Testing with generated sfdx project with a specific api version",
"usecase": "I have a plugin with commands that require a SFDX project that need a specific api version in the sfdx-project.json.",
"file": "TestSession.sample1b.nut.ts"
},
{
"header": "Testing with local sfdx project",
"usecase": "I have a plugin with commands that require a SFDX project and the test project I want to use is in a local directory within my plugin repo.",
Expand Down
18 changes: 11 additions & 7 deletions src/testProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import { env } from '@salesforce/kit';
import { genUniqueString } from './genUniqueString';
import { zipDir, ZipDirConfig } from './zip';

export interface TestProjectOptions {
sourceDir?: string;
gitClone?: string;
export type TestProjectOptions = {
name?: string;
destinationDir?: string;
}
} & (
| { sourceDir?: string; gitClone?: never; apiVersion?: never }
| { sourceDir?: never; gitClone?: string; apiVersion?: never }
| { sourceDir?: never; gitClone?: never; apiVersion?: string }
);

/**
* A SFDX project for use with testing. The project can be defined by:
Expand Down Expand Up @@ -53,15 +55,15 @@ export class TestProject {
}

// Copy a dir containing a SFDX project to a dir for testing.
if (options?.sourceDir) {
if (options.sourceDir) {
const rv = shell.cp('-r', options.sourceDir, destDir);
if (rv.code !== 0) {
throw new Error(`project copy failed with error:\n${rv.stderr}`);
}
this.dir = path.join(destDir, path.basename(options.sourceDir));
}
// Clone a git repo containing a SFDX project in a dir for testing.
else if (options?.gitClone) {
else if (options.gitClone) {
// verify git is found
if (!shell.which('git')) {
throw new Error('git executable not found for creating a project from a git clone');
Expand All @@ -85,7 +87,9 @@ export class TestProject {
}
const name = options.name ?? genUniqueString('project_%s');
const rv = shell.exec(
`sf project:generate -n ${name} -d ${destDir}`,
`sf project:generate -n ${name} -d ${destDir}${
options.apiVersion ? ` --api-version ${options.apiVersion}` : ''
}`,
this.shelljsExecOptions
) as shell.ShellString;
if (rv.code !== 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/testSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ export class TestSession<T extends TestSessionOptions = TestSessionOptions> exte
throw new Error(`${executable} executable not found for creating scratch orgs`);
}

let baseCmd = `sf env:create:scratch --json -y ${org.duration ?? '1'} -w ${org.wait ?? 60}`;
let baseCmd = `sf org:create:scratch --json -y ${org.duration ?? '1'} -w ${org.wait ?? 60}`;

if (org.config) {
baseCmd += ` -f ${org.config}`;
Expand All @@ -355,7 +355,7 @@ export class TestSession<T extends TestSessionOptions = TestSessionOptions> exte
}

if (org.username) {
baseCmd += `--username ${org.username}`;
baseCmd += ` --username ${org.username}`;
}

if (org.edition) {
Expand Down
17 changes: 17 additions & 0 deletions test/unit/testProject.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@ describe('TestProject', () => {
expect(execStub.firstCall.args[1]).to.have.property('shell', shellOverride);
});

it('should generate from a name with api version', () => {
const apiVersion = '50.0';
stubMethod(sandbox, shelljs, 'which').returns(true);
const shellOverride = 'powershell.exe';
stubMethod(sandbox, env, 'getString').returns(shellOverride);
const shellString = new ShellString('');
shellString.code = 0;
const execStub = stubMethod(sandbox, shelljs, 'exec').returns(shellString);
const name = 'MyTestProject';
const destinationDir = pathJoin('foo', 'bar');
const testProject = new TestProject({ name, destinationDir, apiVersion });
expect(testProject.dir).to.equal(pathJoin(destinationDir, name));
const execArg1 = `sf project:generate -n ${name} -d ${destinationDir} --api-version ${apiVersion}`;
expect(execStub.firstCall.args[0]).to.equal(execArg1);
expect(execStub.firstCall.args[1]).to.have.property('shell', shellOverride);
});

it('should generate by default', () => {
stubMethod(sandbox, shelljs, 'which').returns(true);
const shellString = new ShellString('');
Expand Down
6 changes: 3 additions & 3 deletions test/unit/testSession.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ describe('TestSession', () => {
expect(execStub.callCount).to.equal(scratchOrgs.length * (retries + 1));
expect(session.orgs.get(username)).to.deep.equal({ username, orgId: '12345' });
expect(execStub.firstCall.args[0]).to.equal(
'sf env:create:scratch --json -y 1 -w 60 -f config/project-scratch-def.json'
'sf org:create:scratch --json -y 1 -w 60 -f config/project-scratch-def.json'
);
});

Expand Down Expand Up @@ -215,7 +215,7 @@ describe('TestSession', () => {
expect(session.orgs.get(username)).to.deep.equal({ username, orgId: '12345' });
expect(session.orgs.get('default')).to.deep.equal({ username, orgId: '12345' });
expect(execStub.firstCall.args[0]).to.equal(
'sf env:create:scratch --json -y 1 -w 60 -f config/project-scratch-def.json -a my-org -d -e developer'
'sf org:create:scratch --json -y 1 -w 60 -f config/project-scratch-def.json -a my-org -d -e developer'
);
expect(process.env.HOME).to.equal(session.homeDir);
expect(process.env.USERPROFILE).to.equal(session.homeDir);
Expand Down Expand Up @@ -256,7 +256,7 @@ describe('TestSession', () => {

it('should error if setup command fails', async () => {
stubMethod(sandbox, shelljs, 'which').returns(true);
const expectedCmd = 'sf env:create:scratch --json -y 1 -w 60 -f config/project-scratch-def.json';
const expectedCmd = 'sf org:create:scratch --json -y 1 -w 60 -f config/project-scratch-def.json';
const execRv = 'Cannot foo before bar';
const shellString = new ShellString(JSON.stringify(execRv));
shellString.code = 1;
Expand Down

0 comments on commit a569636

Please sign in to comment.