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

test(data:export): add NUTs for big exports #1145

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions test/commands/data/export/bulk.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import path from 'node:path';
import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit';
import { expect } from 'chai';
import { ensureNumber } from '@salesforce/ts-types';
import { ensureNumber, ensureString } from '@salesforce/ts-types';
import { validateCsv, validateJson } from '../../../testUtil.js';
import { DataExportBulkResult } from '../../../../src/commands/data/export/bulk.js';

Expand Down Expand Up @@ -42,6 +42,9 @@ describe('data export bulk NUTs', () => {
});

const soqlQuery = 'select id,name,phone, annualrevenue from account';
const soqlQueryFields = ['Id', 'Name', 'Phone', 'AnnualRevenue'];

const na40username = ensureString(process.env.TESTKIT_HUB_USERNAME);

it('should export records in csv format', async () => {
const outputFile = 'export-accounts.csv';
Expand All @@ -55,6 +58,34 @@ describe('data export bulk NUTs', () => {
await validateCsv(path.join(session.dir, 'data-project', outputFile), 'COMMA', ensureNumber(result?.totalSize));
});

it('should export +1 million records in csv format', async () => {
const outputFile = 'export-scratch-info.csv';
const command = `data export bulk -q "select id,ExpirationDate from scratchorginfo" --output-file ${outputFile} --wait 10 --json -o ${na40username}`;
Copy link
Member Author

Choose a reason for hiding this comment

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

query scratchorginfo records in our na40 hub:

➜  plugin-data git:(cd/large-bulk-export-nut) sf data query -q 'select count() from scratchorginfo' -o na40

Total number of records retrieved: 1622618.


const result = execCmd<DataExportBulkResult>(command, { ensureExitCode: 0 }).jsonOutput?.result;

expect(result?.totalSize).to.be.greaterThan(1_000_000);
expect(result?.filePath).to.equal(outputFile);

await validateCsv(path.join(session.dir, 'data-project', outputFile), 'COMMA', ensureNumber(result?.totalSize));
});

it('should export +1 million records in json format', async () => {
const outputFile = 'export-scratch-info.json';
const command = `data export bulk -q "SELECT Id,ExpirationDate FROM scratchorginfo" --output-file ${outputFile} --wait 10 --json -o ${na40username} --result-format json`;

const result = execCmd<DataExportBulkResult>(command, { ensureExitCode: 0 }).jsonOutput?.result;

expect(result?.totalSize).to.be.greaterThan(1_000_000);
expect(result?.filePath).to.equal(outputFile);

await validateJson(
path.join(session.dir, 'data-project', outputFile),
['Id', 'ExpirationDate'],
ensureNumber(result?.totalSize)
);
});

it('should export records in csv format with PIPE delimiter', async () => {
const outputFile = 'export-accounts.csv';
const command = `data export bulk -q "${soqlQuery}" --output-file ${outputFile} --wait 10 --column-delimiter PIPE --json`;
Expand All @@ -76,6 +107,10 @@ describe('data export bulk NUTs', () => {
expect(result?.totalSize).to.equal(totalAccountRecords);
expect(result?.filePath).to.equal(outputFile);

await validateJson(path.join(session.dir, 'data-project', outputFile), ensureNumber(totalAccountRecords));
await validateJson(
path.join(session.dir, 'data-project', outputFile),
soqlQueryFields,
ensureNumber(totalAccountRecords)
);
});
});
7 changes: 6 additions & 1 deletion test/commands/data/export/resume.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe('data export resume NUTs', () => {
});

const soqlQuery = 'select id,name,phone, annualrevenue from account';
const soqlQueryFields = ['Id', 'Name', 'Phone', 'AnnualRevenue'];

it('should resume export in csv format', async () => {
const outputFile = 'export-accounts.csv';
Expand Down Expand Up @@ -85,6 +86,10 @@ describe('data export resume NUTs', () => {
expect(exportResumeResult?.totalSize).to.be.equal(totalAccountRecords);
expect(exportResumeResult?.filePath).to.equal(outputFile);

await validateJson(path.join(session.dir, 'data-project', outputFile), ensureNumber(totalAccountRecords));
await validateJson(
path.join(session.dir, 'data-project', outputFile),
soqlQueryFields,
ensureNumber(totalAccountRecords)
);
});
});
17 changes: 9 additions & 8 deletions test/testUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,17 @@ export async function validateCsv(
}

/**
* Validate that a JSON file has X records
* Validate that a JSON file has an array of records (and props)
*
* @param filePath JSON file to validate
* @param props Array of props each record should have
* @param totalqty Total amount of records in the file
*/
export async function validateJson(filePath: string, totalqty: number): Promise<void> {
export async function validateJson(filePath: string, props: string[], totalqty: number): Promise<void> {
// check records have expected fields
const fieldsRes = await exec(
`jq 'map(has("Id") and has("Name") and has("Phone") and has("AnnualRevenue")) | all' ${filePath}`,
{
shell: 'pwsh',
}
);
const fieldsRes = await exec(`jq 'map(${props.map((field) => `has("${field}")`).join(' and ')}) | all' ${filePath}`, {
shell: 'pwsh',
Copy link
Member Author

@cristiand391 cristiand391 Dec 9, 2024

Choose a reason for hiding this comment

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

small refactor to remove hardcoded fields in the jq query, the caller can now pass them as an array of string. No functional changes.

});
expect(fieldsRes.stdout.trim()).equal('true');

// check all records were written
Expand Down
Loading