From 5b9e10e067ff269f62098dc2e895f5c5bd5fa36d Mon Sep 17 00:00:00 2001 From: chowwinston Date: Thu, 14 Sep 2017 09:42:00 -0700 Subject: [PATCH] Winston/sobject fetch (#96) * SObject describe and integration tests @W-4252302@ * Update path for mac builds * Refactor and address issues from PR * Cleanup code and add describeSObject test * Add permset for FLS in integration test * Update to dependencies to 40.9 * Buffer output to only return when stdout finishes streaming * Enable jwt auth for CI tests * Fail fast for now for truncated JSON * Rename to use devhub.key * Try Ascii encoding * Fix some logging calls * Debug autobuilds * Validate key through openssl * Extract jwt key location to env variable * Give absolute path for appveyor * Extract appveyor keylocation to web * Remove key env variable * Use absolute path for keyfile * Escape character in appveyor path * Change travis key path * Distinguish key path for linux vs mac * Update to 40.10.0 --- .appveyor.yml | 6 +- .travis.yml | 10 +- .vscode/launch.json | 22 ++ docs/tests.md | 5 +- .../README.md | 5 + .../package.json | 45 ++++ .../src/describe/index.ts | 8 + .../src/describe/sObjectDescribe.ts | 216 ++++++++++++++++++ .../src/generator/fauxClassGenerator.ts | 33 +++ .../src/generator/index.ts | 8 + .../test/index.ts | 21 ++ .../MyCustomObject__c.object-meta.xml | 65 ++++++ .../fields/MyCustomField__c.field-meta.xml | 12 + .../test/integration/integrationTestUtil.ts | 148 ++++++++++++ .../test/integration/sObjectDescribe.test.ts | 106 +++++++++ .../tsconfig.json | 16 ++ .../salesforcedx-vscode-apex/package.json | 1 + 17 files changed, 720 insertions(+), 7 deletions(-) create mode 100644 packages/salesforcedx-sobjects-faux-generator/README.md create mode 100644 packages/salesforcedx-sobjects-faux-generator/package.json create mode 100644 packages/salesforcedx-sobjects-faux-generator/src/describe/index.ts create mode 100644 packages/salesforcedx-sobjects-faux-generator/src/describe/sObjectDescribe.ts create mode 100644 packages/salesforcedx-sobjects-faux-generator/src/generator/fauxClassGenerator.ts create mode 100644 packages/salesforcedx-sobjects-faux-generator/src/generator/index.ts create mode 100644 packages/salesforcedx-sobjects-faux-generator/test/index.ts create mode 100644 packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/MyCustomObject__c.object-meta.xml create mode 100644 packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/fields/MyCustomField__c.field-meta.xml create mode 100644 packages/salesforcedx-sobjects-faux-generator/test/integration/integrationTestUtil.ts create mode 100644 packages/salesforcedx-sobjects-faux-generator/test/integration/sObjectDescribe.test.ts create mode 100644 packages/salesforcedx-sobjects-faux-generator/tsconfig.json diff --git a/.appveyor.yml b/.appveyor.yml index feebd2c..62dd8dd 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -25,9 +25,8 @@ install: - sfdx update - npm install -g codecov # the JWT key should be stored base 64 encoded in AppVeyor settings - - ps: "[System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($env:SFDX_CI_DEVHUB_JWTKEY)) | Out-File -Encoding \"ASCII\" devhub.key" - - sfdx force:auth:jwt:grant --clientid %SFDX_CI_DEVHUB_CLIENTID% --username %SFDX_CI_DEVHUB_USERNAME% --jwtkeyfile devhub.key --setdefaultdevhubusername --setalias devhub - - del devhub.key + - ps: "[System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($env:SFDX_CI_DEVHUB_JWTKEY)) | Out-File -Encoding \"ASCII\" C:\\projects\\devhub.key" + - sfdx force:auth:jwt:grant --clientid %SFDX_CI_DEVHUB_CLIENTID% --username %SFDX_CI_DEVHUB_USERNAME% --jwtkeyfile C:\projects\devhub.key --setdefaultdevhubusername --setalias devhub build_script: @@ -41,5 +40,6 @@ test_script: - npm run coverage:system-tests on_finish: + - del C:\projects\devhub.key - codecov \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 3bfb5b0..a73d262 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ before_install: "./sfdx/install" export PATH=./sfdx/$(pwd):$PATH sfdx update + export SFDX_CI_KEY_LOCATION=/home/travis/devhub.key fi - | if [[ $TRAVIS_OS_NAME == "osx" ]]; then @@ -50,12 +51,12 @@ before_install: wget -q $SFDX_URL_OSX sudo installer -pkg sfdx-osx.pkg -target / sfdx update + export SFDX_CI_KEY_LOCATION=/Users/travis/devhub.key fi - | # the key should be stored in Travis Repository Setting, wrapped in quotes and newlines replaced with \n - echo -e $SFDX_CI_DEVHUB_JWTKEY > devhub.key - sfdx force:auth:jwt:grant --clientid $SFDX_CI_DEVHUB_CLIENTID --username $SFDX_CI_DEVHUB_USERNAME --jwtkeyfile devhub.key --setdefaultdevhubusername --setalias devhub - rm devhub.key + echo -e $SFDX_CI_DEVHUB_JWTKEY > $SFDX_CI_KEY_LOCATION + sfdx force:auth:jwt:grant --clientid $SFDX_CI_DEVHUB_CLIENTID --username $SFDX_CI_DEVHUB_USERNAME --jwtkeyfile $SFDX_CI_KEY_LOCATION --setdefaultdevhubusername --setalias devhub curl -sL https://raw.githubusercontent.com/travis-ci/artifacts/master/install | bash install: @@ -77,3 +78,6 @@ script: npm run test:without-system-tests fi - codecov + +after_script: + - rm $SFDX_CI_KEY_LOCATION \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 575caea..01619ed 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -166,6 +166,28 @@ ], "preLaunchTask": "Compile", "internalConsoleOptions": "openOnSessionStart" + }, + { + "name": "Launch SObject Generator Tests", + "type": "node", + "request": "launch", + "cwd": "${workspaceRoot}/packages/salesforcedx-sobjects-faux-generator", + "program": + "${workspaceRoot}/packages/salesforcedx-sobjects-faux-generator/node_modules/mocha/bin/_mocha", + "args": [ + "-u", + "tdd", + "--timeout", + "100000", + "--colors", + "--recursive", + "${workspaceRoot}/packages/salesforcedx-sobjects-faux-generator/out/test/" + ], + "sourceMaps": true, + "outFiles": [ + "${workspaceRoot}/packages/salesforcedx-sobjects-faux-generator/out/test/**/*.js" + ], + "preLaunchTask": "Compile" } ], "compounds": [ diff --git a/docs/tests.md b/docs/tests.md index d9ba094..8c5a98c 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -6,6 +6,9 @@ describes them and give pointers on how to run/debug them. These tests are described in the order in which we prefer to write them. Always prefer unit tests, integration tests, and system tests, in that order. +Ensure that you have set a default dev hub through the `sfdx force:auth:*` commands, +passing in `--setdefaultdevhubusername`. + To run all tests, execute `npm run compile && npm run test` from the top-level folder. @@ -88,7 +91,7 @@ There are some optional environment variables to configure the test runner: | ------------|-------------------| | `CODE_VERSION` | Version of VS Code to run the tests against (e.g. `0.10.10`) | | `CODE_DOWNLOAD_URL` | Full URL of a VS Code drop to use for running tests against | -| `CODE_TESTS_PATH` | Location of the tests to execute (default is `proces.cwd()/out/test` or `process.cwd()/test`) | +| `CODE_TESTS_PATH` | Location of the tests to execute (default is `process.cwd()/out/test` or `process.cwd()/test`) | | `CODE_EXTENSIONS_PATH` | Location of the extensions to load (default is `proces.cwd()`) | | `CODE_TESTS_WORKSPACE` | Location of a workspace to open for the test instance (default is CODE_TESTS_PATH) | diff --git a/packages/salesforcedx-sobjects-faux-generator/README.md b/packages/salesforcedx-sobjects-faux-generator/README.md new file mode 100644 index 0000000..62c4cd0 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/README.md @@ -0,0 +1,5 @@ +# salesforcedx-sobjects-faux-generator +This repository contains a generator that transforms Salesforce objects and their fields +into faux classes understood by the Apex Language Server. + +## Resources \ No newline at end of file diff --git a/packages/salesforcedx-sobjects-faux-generator/package.json b/packages/salesforcedx-sobjects-faux-generator/package.json new file mode 100644 index 0000000..584f8c5 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/package.json @@ -0,0 +1,45 @@ +{ + "name": "@salesforce/salesforcedx-sobjects-faux-generator", + "displayName": "Salesforce SObject Faux Generator", + "description": + "Fetches sobjects and generates their faux apex class to be used for Apex Language Server", + "version": "40.10.0", + "publisher": "salesforce", + "license": "BSD-3-Clause", + "engines": { + "vscode": "^1.15.0" + }, + "dependencies": { + "@salesforce/salesforcedx-utils-vscode": "40.10.0", + "jsforce": "1.7.1" + }, + "devDependencies": { + "@types/chai": "^4.0.0", + "@types/jsforce": "^1.7.1", + "@types/mocha": "2.2.38", + "@types/node": "^6.0.40", + "@types/rimraf": "^2.0.2", + "@types/sinon": "^2.3.2", + "chai": "^4.0.2", + "cross-env": "5.0.4", + "jsforce": "1.7.1", + "mocha": "3.2.0", + "mock-spawn": "0.2.6", + "nyc": "^11.0.2", + "sinon": "^2.3.6", + "typescript": "2.4.0", + "vscode": "1.1.4" + }, + "scripts": { + "vscode:package": "npm prune --production", + "compile": "tsc -p ./", + "lint": "tslint --project .", + "watch": "tsc -watch -p .", + "clean": "shx rm -rf node_modules && shx rm -rf out", + "test": + "./node_modules/.bin/cross-env VSCODE_NLS_CONFIG={} ./node_modules/.bin/nyc ./node_modules/.bin/_mocha --recursive out/test" + }, + "nyc": { + "reporter": ["text-summary", "lcov"] + } +} diff --git a/packages/salesforcedx-sobjects-faux-generator/src/describe/index.ts b/packages/salesforcedx-sobjects-faux-generator/src/describe/index.ts new file mode 100644 index 0000000..2023026 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/src/describe/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2017, 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 + */ + +export { SObjectCategory, SObjectDescribe } from './sObjectDescribe'; diff --git a/packages/salesforcedx-sobjects-faux-generator/src/describe/sObjectDescribe.ts b/packages/salesforcedx-sobjects-faux-generator/src/describe/sObjectDescribe.ts new file mode 100644 index 0000000..2a20186 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/src/describe/sObjectDescribe.ts @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2017, 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 { + CliCommandExecutor, + CommandOutput, + SfdxCommandBuilder +} from '@salesforce/salesforcedx-utils-vscode/out/src/cli'; + +export interface SObject { + actionOverrides: any[]; + activateable: boolean; + childRelationships: ChildRelationship[]; + compactLayoutable: boolean; + createable: boolean; + custom: boolean; + customSetting: boolean; + deletable: boolean; + deprecatedAndHidden: boolean; + feedEnabled: boolean; + fields: Field[]; + hasSubtypes: boolean; + isSubtype: boolean; + keyPrefix: string; + label: string; + labelPlural: string; + layoutable: boolean; + listviewable?: any; + lookupLayoutable?: any; + mergeable: boolean; + mruEnabled: boolean; + name: string; + namedLayoutInfos: any[]; + networkScopeFieldName?: any; + queryable: boolean; + recordTypeInfos: RecordTypeInfo[]; + replicateable: boolean; + retrieveable: boolean; + searchLayoutable: boolean; + searchable: boolean; + supportedScopes: SupportedScope[]; + triggerable: boolean; + undeletable: boolean; + updateable: boolean; + urls: Urls2; +} + +export interface ChildRelationship { + cascadeDelete: boolean; + childSObject: string; + deprecatedAndHidden: boolean; + field: string; + junctionIdListNames: any[]; + junctionReferenceTo: any[]; + relationshipName: string; + restrictedDelete: boolean; +} + +export interface Field { + aggregatable: boolean; + autoNumber: boolean; + byteLength: number; + calculated: boolean; + calculatedFormula?: any; + cascadeDelete: boolean; + caseSensitive: boolean; + compoundFieldName?: any; + controllerName?: any; + createable: boolean; + custom: boolean; + defaultValue?: boolean; + defaultValueFormula?: any; + defaultedOnCreate: boolean; + dependentPicklist: boolean; + deprecatedAndHidden: boolean; + digits: number; + displayLocationInDecimal: boolean; + encrypted: boolean; + externalId: boolean; + extraTypeInfo?: any; + filterable: boolean; + filteredLookupInfo?: any; + groupable: boolean; + highScaleNumber: boolean; + htmlFormatted: boolean; + idLookup: boolean; + inlineHelpText?: any; + label: string; + length: number; + mask?: any; + maskType?: any; + name: string; + nameField: boolean; + namePointing: boolean; + nillable: boolean; + permissionable: boolean; + picklistValues: any[]; + polymorphicForeignKey: boolean; + precision: number; + queryByDistance: boolean; + referenceTargetField?: any; + referenceTo: string[]; + relationshipName: string; + relationshipOrder?: any; + restrictedDelete: boolean; + restrictedPicklist: boolean; + scale: number; + searchPrefilterable: boolean; + soapType: string; + sortable: boolean; + type: string; + unique: boolean; + updateable: boolean; + writeRequiresMasterRead: boolean; +} + +export interface Urls { + layout: string; +} + +export interface RecordTypeInfo { + active: boolean; + available: boolean; + defaultRecordTypeMapping: boolean; + master: boolean; + name: string; + recordTypeId: string; + urls: Urls; +} + +export interface SupportedScope { + label: string; + name: string; +} + +export interface Urls2 { + compactLayouts: string; + rowTemplate: string; + approvalLayouts: string; + uiDetailTemplate: string; + uiEditTemplate: string; + defaultValues: string; + describe: string; + uiNewRecord: string; + quickActions: string; + layouts: string; + sobject: string; +} + +export interface DescribeSObjectResult { + result: SObject; +} + +export enum SObjectCategory { + ALL = 'ALL', + STANDARD = 'STANDARD', + CUSTOM = 'CUSTOM' +} + +export class SObjectDescribe { + public async describeSObject( + projectPath: string, + type: string, + username?: string + ): Promise { + const builder = new SfdxCommandBuilder() + .withArg('force:schema:sobject:describe') + .withFlag('--sobjecttype', type); + if (username) { + builder.args.push('--targetusername', username); + } + const command = builder.withJson().build(); + const execution = new CliCommandExecutor(command, { + cwd: projectPath + }).execute(); + + const cmdOutput = new CommandOutput(); + const result = await cmdOutput.getCmdResult(execution); + try { + const sobject = JSON.parse(result).result as SObject; + return Promise.resolve(sobject); + } catch (e) { + return Promise.reject(result); + } + } + + public async describeGlobal( + projectPath: string, + type: SObjectCategory, + username?: string + ): Promise { + const builder = new SfdxCommandBuilder() + .withArg('force:schema:sobject:list') + .withFlag('--sobjecttypecategory', type.toString()); + if (username) { + builder.args.push('--targetusername', username); + } + const command = builder.withJson().build(); + const execution = new CliCommandExecutor(command, { + cwd: projectPath + }).execute(); + + const cmdOutput = new CommandOutput(); + const result = await cmdOutput.getCmdResult(execution); + try { + const sobjects = JSON.parse(result).result as string[]; + return Promise.resolve(sobjects); + } catch (e) { + return Promise.reject(result); + } + } +} diff --git a/packages/salesforcedx-sobjects-faux-generator/src/generator/fauxClassGenerator.ts b/packages/salesforcedx-sobjects-faux-generator/src/generator/fauxClassGenerator.ts new file mode 100644 index 0000000..22b3667 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/src/generator/fauxClassGenerator.ts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, 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 fs from 'fs'; +import * as path from 'path'; +import { SObjectCategory, SObjectDescribe } from '../describe'; + +export class FauxClassGenerator { + public async generate(projectPath: string, type: SObjectCategory) { + const describe = new SObjectDescribe(); + const sobjects = await describe.describeGlobal(projectPath, type); + console.log(sobjects.length); + for (let i = 0; i < sobjects.length; i++) { + const sobject = await describe.describeSObject(projectPath, sobjects[i]); + console.log(sobject.name); + this.generateFauxClass(projectPath, sobject); + } + } + + private async generateFauxClass( + projectPath: string, + sobject: any + ): Promise { + const folderPath = path.join(projectPath, '.sfdx', 'sobjects'); + if (!fs.existsSync(folderPath)) { + //fs.mkdirSync(folderPath); + } + //const isCustom = sobject.custom; + } +} diff --git a/packages/salesforcedx-sobjects-faux-generator/src/generator/index.ts b/packages/salesforcedx-sobjects-faux-generator/src/generator/index.ts new file mode 100644 index 0000000..8dad088 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/src/generator/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2017, 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 + */ + +export { FauxClassGenerator } from './fauxClassGenerator'; diff --git a/packages/salesforcedx-sobjects-faux-generator/test/index.ts b/packages/salesforcedx-sobjects-faux-generator/test/index.ts new file mode 100644 index 0000000..d6382c4 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/test/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017, 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 + */ + +// tslint:disable-next-line:no-var-requires +// tslint:disable-next-line:variable-name +import Mocha = require('mocha'); + +// You can directly control Mocha options by uncommenting the following lines +// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info + +const mocha = new Mocha({ + ui: 'bdd', + timeout: 100000 +}); +mocha.useColors(true); + +module.exports = mocha; diff --git a/packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/MyCustomObject__c.object-meta.xml b/packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/MyCustomObject__c.object-meta.xml new file mode 100644 index 0000000..faf9fc7 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/MyCustomObject__c.object-meta.xml @@ -0,0 +1,65 @@ + + + + Accept + Default + + + CancelEdit + Default + + + Clone + Default + + + Delete + Default + + + Edit + Default + + + List + Default + + + New + Default + + + SaveEdit + Default + + + Tab + Default + + + View + Default + + false + SYSTEM + Deployed + false + true + false + false + false + false + false + true + true + ReadWrite + + + + Text + + MyCustomObjects + + ReadWrite + Public + \ No newline at end of file diff --git a/packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/fields/MyCustomField__c.field-meta.xml b/packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/fields/MyCustomField__c.field-meta.xml new file mode 100644 index 0000000..e557dcd --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/test/integration/config/simpleObjectAndField/objects/MyCustomObject__c/fields/MyCustomField__c.field-meta.xml @@ -0,0 +1,12 @@ + + + MyCustomField__c + false + + 18 + false + 0 + false + Number + false + \ No newline at end of file diff --git a/packages/salesforcedx-sobjects-faux-generator/test/integration/integrationTestUtil.ts b/packages/salesforcedx-sobjects-faux-generator/test/integration/integrationTestUtil.ts new file mode 100644 index 0000000..456b162 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/test/integration/integrationTestUtil.ts @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2017, 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 { + CliCommandExecutor, + CommandOutput, + SfdxCommandBuilder +} from '@salesforce/salesforcedx-utils-vscode/out/src/cli'; +import childProcess = require('child_process'); +import * as path from 'path'; +import * as util from 'util'; + +// Used only for CI purposes. Must call delete if you call create +export async function createSFDXProject(projectName: string): Promise { + const execution = new CliCommandExecutor( + new SfdxCommandBuilder() + .withArg('force:project:create') + .withFlag('--projectname', projectName) + .withJson() + .build(), + { cwd: process.cwd() } + ).execute(); + const cmdOutput = new CommandOutput(); + await cmdOutput.getCmdResult(execution); + return Promise.resolve(); +} + +export async function createScratchOrg(projectName: string): Promise { + const scratchDefFilePath = path.join( + process.cwd(), + projectName, + 'config', + 'project-scratch-def.json' + ); + const execution = new CliCommandExecutor( + new SfdxCommandBuilder() + .withArg('force:org:create') + .withFlag('--definitionfile', scratchDefFilePath) + .withJson() + .build(), + { cwd: path.join(process.cwd(), projectName) } + ).execute(); + const cmdOutput = new CommandOutput(); + const result = await cmdOutput.getCmdResult(execution); + const username = JSON.parse(result).result.username; + return Promise.resolve(username); +} + +export async function push( + sourceFolder: string, + projectName: string, + username: string +): Promise { + const targetFolder = path.join( + process.cwd(), + projectName, + 'force-app', + 'main', + 'default' + ); + childProcess.execSync('cp -R ' + sourceFolder + ' ' + targetFolder); + const execution = new CliCommandExecutor( + new SfdxCommandBuilder() + .withArg('force:source:push') + .withFlag('--targetusername', username) + .withJson() + .build(), + { cwd: path.join(process.cwd(), projectName) } + ).execute(); + const cmdOutput = new CommandOutput(); + const result = await cmdOutput.getCmdResult(execution); + const source = JSON.parse(result).result.pushedSource; + return Promise.resolve(source); +} + +export async function createPermissionSet( + permissionSetName: string, + username: string +): Promise { + const execution = new CliCommandExecutor( + new SfdxCommandBuilder() + .withArg('force:data:record:create') + .withFlag('--sobjecttype', 'PermissionSet') + .withFlag('--targetusername', username) + .withFlag( + '--values', + 'Name=' + permissionSetName + " Label='Give FLS Read'" + ) + .withJson() + .build(), + { cwd: process.cwd() } + ).execute(); + const cmdOutput = new CommandOutput(); + const result = await cmdOutput.getCmdResult(execution); + const permissionSetId = JSON.parse(result).result.id as string; + return Promise.resolve(permissionSetId); +} + +export async function createFieldPermissions( + permissionSetId: string, + sobjectType: string, + fieldName: string, + username: string +): Promise { + const execution = new CliCommandExecutor( + new SfdxCommandBuilder() + .withArg('force:data:record:create') + .withFlag('--sobjecttype', 'FieldPermissions') + .withFlag('--targetusername', username) + .withFlag( + '--values', + util.format( + 'ParentId=%s SobjectType=%s Field=%s PermissionsRead=true', + permissionSetId, + sobjectType, + fieldName + ) + ) + .withJson() + .build(), + { cwd: process.cwd() } + ).execute(); + const cmdOutput = new CommandOutput(); + await cmdOutput.getCmdResult(execution); + return Promise.resolve(); +} + +export async function assignPermissionSet( + permissionSetName: string, + username: string +): Promise { + const execution = new CliCommandExecutor( + new SfdxCommandBuilder() + .withArg('force:user:permset:assign') + .withFlag('--permsetname', permissionSetName) + .withFlag('--targetusername', username) + .withJson() + .build(), + { cwd: process.cwd() } + ).execute(); + const cmdOutput = new CommandOutput(); + await cmdOutput.getCmdResult(execution); + return Promise.resolve(); +} diff --git a/packages/salesforcedx-sobjects-faux-generator/test/integration/sObjectDescribe.test.ts b/packages/salesforcedx-sobjects-faux-generator/test/integration/sObjectDescribe.test.ts new file mode 100644 index 0000000..e456ea6 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/test/integration/sObjectDescribe.test.ts @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017, 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 rimraf = require('rimraf'); +import { expect } from 'chai'; +import * as path from 'path'; +import { + SObjectCategory, + SObjectDescribe +} from '../../src/describe/sObjectDescribe'; +import * as util from './integrationTestUtil'; + +const PROJECT_NAME = `project_${new Date().getTime()}`; +const CUSTOM_OBJECT_NAME = 'MyCustomObject__c'; +const CUSTOM_FIELD_FULLNAME = CUSTOM_OBJECT_NAME + '.MyCustomField__c'; +const SIMPLE_OBJECT_DIR = path.join( + 'test', + 'integration', + 'config', + 'simpleObjectAndField', + 'objects' +); + +const sobjectdescribe = new SObjectDescribe(); + +// tslint:disable:no-unused-expression +describe('Fetch sObjects', function() { + // tslint:disable-next-line:no-invalid-this + this.timeout(60000); + let username: string; + + before(async function() { + await util.createSFDXProject(PROJECT_NAME); + username = await util.createScratchOrg(PROJECT_NAME); + + const sourceFolder = path.join( + __dirname, + '..', + '..', + '..', + SIMPLE_OBJECT_DIR + ); + await util.push(sourceFolder, PROJECT_NAME, username); + + const permSetName = 'AllowRead'; + const permissionSetId = await util.createPermissionSet( + permSetName, + username + ); + + await util.createFieldPermissions( + permissionSetId, + CUSTOM_OBJECT_NAME, + CUSTOM_FIELD_FULLNAME, + username + ); + + await util.assignPermissionSet(permSetName, username); + }); + + after(function() { + const projectPath = path.join(process.cwd(), PROJECT_NAME); + rimraf.sync(projectPath); + }); + + it('Should be able to call describeGlobal', async function() { + const cmdOutput = await sobjectdescribe.describeGlobal( + process.cwd(), + SObjectCategory.CUSTOM, + username + ); + expect(cmdOutput.length).to.be.equal(1); + expect(cmdOutput[0]).to.be.equal(CUSTOM_OBJECT_NAME); + }); + + it('Should be able to call describeSObject on custom object', async function() { + const cmdOutput = await sobjectdescribe.describeSObject( + process.cwd(), + CUSTOM_OBJECT_NAME, + username + ); + expect(cmdOutput.name).to.be.equal(CUSTOM_OBJECT_NAME); + expect(cmdOutput.custom).to.be.true; + expect(cmdOutput.fields.length).to.be.least(9); + const customField = cmdOutput.fields[cmdOutput.fields.length - 1]; + expect(customField.custom).to.be.true; + expect(customField.precision).to.be.equal(18); + expect(customField.scale).to.be.equal(0); + expect(customField.name).to.be.equal('MyCustomField__c'); + }); + + it('Should be able to call describeSObject on standard object', async function() { + // const cmdOutput = await sobjectdescribe.describeSObject( + // process.cwd(), + // 'Account', + // username + // ); + // expect(cmdOutput.name).to.be.equal('Account'); + // expect(cmdOutput.custom).to.be.false; + // expect(cmdOutput.fields.length).to.be.least(59); + }); +}); diff --git a/packages/salesforcedx-sobjects-faux-generator/tsconfig.json b/packages/salesforcedx-sobjects-faux-generator/tsconfig.json new file mode 100644 index 0000000..1bda842 --- /dev/null +++ b/packages/salesforcedx-sobjects-faux-generator/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "lib": ["dom", "es6"], + "sourceMap": true, + "declaration": true, + "moduleResolution": "node", + "noImplicitAny": true, + "rootDir": ".", + "outDir": "out", + "preserveConstEnums": true, + "strict": true + }, + "exclude": ["node_modules", "out"] +} diff --git a/packages/salesforcedx-vscode-apex/package.json b/packages/salesforcedx-vscode-apex/package.json index 32cff0b..10ed396 100644 --- a/packages/salesforcedx-vscode-apex/package.json +++ b/packages/salesforcedx-vscode-apex/package.json @@ -80,6 +80,7 @@ ] }, "dependencies": { + "@salesforce/salesforcedx-sobjects-faux-generator": "40.9.0", "@salesforce/salesforcedx-utils-vscode": "^40.10.0", "expand-home-dir": "0.0.3", "find-java-home": "0.2.0",