From 4e8c94fc2cb3b39ad174135609cf6e41d9f4b7f2 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Tue, 31 May 2022 11:28:47 -0600 Subject: [PATCH 01/10] fix: human output no longer displaying undefined @W-11216045@ fixed case for subquery data displaying undefined fixed case where subquery returns more than one row --- src/reporters.ts | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/reporters.ts b/src/reporters.ts index 1d76457a..e4831ee6 100644 --- a/src/reporters.ts +++ b/src/reporters.ts @@ -124,7 +124,15 @@ export class HumanReporter extends QueryReporter { (field: string) => (formattedColumns[field] = { header: field.toUpperCase(), - get: (row): string => get(row, field) as string, + get: (row): string => { + // first test if key exists, if so, return value + if (Reflect.has(row, field)) { + return (Reflect.get(row, field) as string) || ''; + } else { + // if not, try to find it query + return get(row, field) as string; + } + }, }) ); return formattedColumns; @@ -136,7 +144,7 @@ export class HumanReporter extends QueryReporter { // some fields will return a JSON object that isn't accessible via the query (SELECT Metadata FROM RemoteProxy) // some will return a JSON that IS accessible via the query (SELECT owner.Profile.Name FROM Lead) // querying (SELECT Metadata.isActive FROM RemoteProxy) throws a SOQL validation error, so we have to display the entire Metadata object - queryResults.map((qr) => { + queryResults.forEach((qr) => { const result = qr as Record; this.data.columns.forEach((col) => { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment @@ -167,6 +175,7 @@ export class HumanReporter extends QueryReporter { } } + const subResults: Array> = []; if (children.length > 0) { const childrenRows: Record = {}; children.forEach((child) => { @@ -180,19 +189,28 @@ export class HumanReporter extends QueryReporter { if (childO) { const childRecords = getArray(childO, 'records', []); // eslint-disable-next-line @typescript-eslint/no-explicit-any - childRecords.forEach((record: unknown) => { + childRecords.forEach((record: unknown, index) => { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const newResult: Record = {}; Object.entries(record as never).forEach(([key, value]) => { - // merge subqueries with the "parent" so they are on the same row - Reflect.defineProperty(result as Record, `${child.toString()}.${key}`, { - value: value ? value : chalk.bold('null'), - }); + if (!index) { + Reflect.defineProperty(result as Record, `${child.toString()}.${key}`, { + value: value ? value : chalk.bold('null'), + }); + } else { + Reflect.defineProperty(newResult, `${child.toString()}.${key}`, { + value: value ? value : chalk.bold('null'), + }); + } }); + if (index) { + subResults.push(newResult); + } }); } }); } - newResults.push(result); + newResults.push(result, ...subResults); return newResults; }, [] as unknown[]); } From f0de9f75b93f2c51097554e7f6e10a2e0abdb872 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Tue, 31 May 2022 11:56:27 -0600 Subject: [PATCH 02/10] chore: never return undefined --- src/reporters.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reporters.ts b/src/reporters.ts index e4831ee6..ec0ec55b 100644 --- a/src/reporters.ts +++ b/src/reporters.ts @@ -130,7 +130,7 @@ export class HumanReporter extends QueryReporter { return (Reflect.get(row, field) as string) || ''; } else { // if not, try to find it query - return get(row, field) as string; + return (get(row, field) as string) || ''; } }, }) From a1fa148e7099ff1a1f52fe9e325afa67a58ffc07 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Thu, 2 Jun 2022 12:03:07 -0600 Subject: [PATCH 03/10] chore: modify existing test to verify nested contacts --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index b2b2527e..f61dc0a7 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -154,14 +154,16 @@ describe('data:soql:query command', () => { }); it('should return account records with nested contacts', () => { const query = - "SELECT Id, Name, Phone, Website, NumberOfEmployees, Industry, (SELECT Lastname, Title, Email FROM Contacts) FROM Account WHERE Name LIKE 'SampleAccount%' limit 1"; + "SELECT Id, Name, Phone, Website, NumberOfEmployees, Industry, (SELECT Lastname, Title, Email FROM Contacts) FROM Account WHERE Name LIKE 'SampleAccount%'"; const queryResult = runQuery(query, { ensureExitCode: 0, json: false }) as string; expect(queryResult).to.match( /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); - expect(queryResult).to.match(/Total number of records retrieved: 1\./g); + const nestedContacts = queryResult.split('\n').filter((contact) => /^Smith|Washington/.test(contact.trim())); + expect(nestedContacts).to.have.lengthOf(2); + expect(queryResult).to.match(/Total number of records retrieved: 2\./g); }); it('should handle count()', () => { const queryResult = execCmd('force:data:soql:query -q "SELECT Count() from User"', { From b7fbcb959dfb998fc1462406385ca150ecd6092f Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Thu, 2 Jun 2022 12:22:35 -0600 Subject: [PATCH 04/10] chore: use os.EOL in lieu of \n --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index f61dc0a7..4df94909 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -4,6 +4,7 @@ * 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 os from 'os'; import * as path from 'path'; import { expect } from 'chai'; import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; @@ -161,7 +162,7 @@ describe('data:soql:query command', () => { expect(queryResult).to.match( /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); - const nestedContacts = queryResult.split('\n').filter((contact) => /^Smith|Washington/.test(contact.trim())); + const nestedContacts = queryResult.split(os.EOL).filter((contact) => /^Smith|Washington/.test(contact.trim())); expect(nestedContacts).to.have.lengthOf(2); expect(queryResult).to.match(/Total number of records retrieved: 2\./g); }); From 1549b6ff38e085c597836244e1d7484affd47785 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Thu, 2 Jun 2022 12:56:01 -0600 Subject: [PATCH 05/10] chore: try different split pattern --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index 4df94909..9a90af37 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -4,7 +4,6 @@ * 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 os from 'os'; import * as path from 'path'; import { expect } from 'chai'; import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; @@ -162,7 +161,7 @@ describe('data:soql:query command', () => { expect(queryResult).to.match( /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); - const nestedContacts = queryResult.split(os.EOL).filter((contact) => /^Smith|Washington/.test(contact.trim())); + const nestedContacts = queryResult.split(/\r?\n/).filter((contact) => /^\s+?Smith|^\s+?Washington/.test(contact)); expect(nestedContacts).to.have.lengthOf(2); expect(queryResult).to.match(/Total number of records retrieved: 2\./g); }); From 721824a1d7d69b7c0706accb27847f17ce250bfe Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Thu, 2 Jun 2022 13:22:47 -0600 Subject: [PATCH 06/10] chore: debug --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index 9a90af37..eb7d2932 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -158,6 +158,8 @@ describe('data:soql:query command', () => { const queryResult = runQuery(query, { ensureExitCode: 0, json: false }) as string; + // eslint-disable-next-line no-console + console.log(Buffer.from(queryResult).toString('base64')); expect(queryResult).to.match( /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); From 810e2d7f901ab408c9beb7f092ecd3218b6c79c3 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Thu, 2 Jun 2022 13:46:13 -0600 Subject: [PATCH 07/10] chore: more debug --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index eb7d2932..7fea8627 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -164,6 +164,8 @@ describe('data:soql:query command', () => { /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); const nestedContacts = queryResult.split(/\r?\n/).filter((contact) => /^\s+?Smith|^\s+?Washington/.test(contact)); + // eslint-disable-next-line no-console + console.log(nestedContacts); expect(nestedContacts).to.have.lengthOf(2); expect(queryResult).to.match(/Total number of records retrieved: 2\./g); }); From 18af6b96880347ce66c0f4578c83ee9c3cfdbc49 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Thu, 2 Jun 2022 14:20:51 -0600 Subject: [PATCH 08/10] chore: fix test --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index 7fea8627..436b2434 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -158,15 +158,11 @@ describe('data:soql:query command', () => { const queryResult = runQuery(query, { ensureExitCode: 0, json: false }) as string; - // eslint-disable-next-line no-console - console.log(Buffer.from(queryResult).toString('base64')); expect(queryResult).to.match( /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); - const nestedContacts = queryResult.split(/\r?\n/).filter((contact) => /^\s+?Smith|^\s+?Washington/.test(contact)); - // eslint-disable-next-line no-console - console.log(nestedContacts); - expect(nestedContacts).to.have.lengthOf(2); + expect(queryResult).to.match(/\s{50,}?Smith/g); + expect(queryResult).to.match(/\s{50,}?Washington/g); expect(queryResult).to.match(/Total number of records retrieved: 2\./g); }); it('should handle count()', () => { From f5bd404cfa8d3f4a7a60d77a1be491dc43306f88 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Thu, 2 Jun 2022 15:03:59 -0600 Subject: [PATCH 09/10] chore: really fix the test --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index 436b2434..5350d3d8 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -161,8 +161,7 @@ describe('data:soql:query command', () => { expect(queryResult).to.match( /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); - expect(queryResult).to.match(/\s{50,}?Smith/g); - expect(queryResult).to.match(/\s{50,}?Washington/g); + expect(queryResult).to.match(/\s{30,30}Smith/g); expect(queryResult).to.match(/Total number of records retrieved: 2\./g); }); it('should handle count()', () => { From c2dbc573f2a9e1f2f6fb8a2b4486fd383ee91ae5 Mon Sep 17 00:00:00 2001 From: Peter Hale Date: Fri, 3 Jun 2022 06:27:33 -0600 Subject: [PATCH 10/10] chore: wip --- test/commands/force/data/soql/query/dataSoqlQuery.nut.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts index 5350d3d8..37ba8ec9 100644 --- a/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts +++ b/test/commands/force/data/soql/query/dataSoqlQuery.nut.ts @@ -161,7 +161,7 @@ describe('data:soql:query command', () => { expect(queryResult).to.match( /ID\s+?NAME\s+?PHONE\s+?WEBSITE\s+?NUMBEROFEMPLOYEES\s+?INDUSTRY\s+?CONTACTS.LASTNAME\s+?CONTACTS.TITLE\s+?CONTACTS.EMAIL/g ); - expect(queryResult).to.match(/\s{30,30}Smith/g); + expect(queryResult).to.match(/\sSmith/g); expect(queryResult).to.match(/Total number of records retrieved: 2\./g); }); it('should handle count()', () => {