Skip to content

Commit 766ab40

Browse files
authored
feat: warning messages when fields are missing in the org
2 parents 191174f + ba74288 commit 766ab40

8 files changed

Lines changed: 530 additions & 789 deletions

File tree

messages/connected-objects.upsert.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ Nothing changed
5050
# connector.not.found
5151

5252
Connector named %s not found. Create an empty data connection to proceed
53+
54+
# fields.not.found
55+
56+
The following field/s of %s (%s) is/are missing and cannot be updated: %s

src/commands/analytics/connected-objects/upsert.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ export default class ConnectedObjectUpsert extends SfCommand<ConnectedObjectUpse
9898
const progressBar = new Progress(!this.jsonEnabled());
9999
progressBar.start(total, {}, { format: '%s | {bar} | {value}/{total} Objects' });
100100

101+
const warnMessages = new Array<string>();
102+
101103
// Create / Update connected-objects
102104
const resultMap = new Map<string, ConnectedObjectUpsertResult>();
103105
for (const connectorName of connectorObjectFields.keys()) {
@@ -112,7 +114,12 @@ export default class ConnectedObjectUpsert extends SfCommand<ConnectedObjectUpse
112114
resultMap.set(objectName, { objectName, isNew: false, connectorName });
113115
}
114116
const fieldSet = objectFields.get(dataset.sourceObjectName) as Set<string>;
115-
const changedFields = await service.updateReplicatedDatasetFields(dataset.id, fieldSet);
117+
const {changedFields, missingFields} = await service.updateReplicatedDatasetFields(dataset.id, fieldSet);
118+
119+
if(missingFields.length > 0){
120+
const message = messages.getMessage('fields.not.found', [objectName, connectorName, missingFields.join(', ')]);
121+
warnMessages.push(message);
122+
}
116123
if (changedFields.length > 0) {
117124
const item = resultMap.get(dataset.sourceObjectName) as ConnectedObjectUpsertResult;
118125
item.fields = changedFields;
@@ -124,6 +131,15 @@ export default class ConnectedObjectUpsert extends SfCommand<ConnectedObjectUpse
124131
}
125132
progressBar.stop();
126133

134+
if(warnMessages.length > 0){
135+
if(!flags.json){
136+
warnMessages[warnMessages.length -1] += '\n'; // Last warning line break
137+
}
138+
for(const warnMessage of warnMessages){
139+
this.warn(warnMessage);
140+
}
141+
}
142+
127143
const result: ConnectedObjectUpsertResult[] = Array.from(resultMap.values()).filter(
128144
(x) => x.fields && x.fields.length > 0
129145
);

src/dataConnectionHelper.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Connection } from '@salesforce/core';
2-
import { GetDataConnectors, GetReplicatedDatasets, PostReplicatedDataset, ReplicatedDataset } from './modules/upsert';
2+
import { ChangedAndMissingFields, GetDataConnectors, GetReplicatedDatasets, PostReplicatedDataset, ReplicatedDataset } from './modules/upsert';
33
import { GetReplicatedDatasetFields } from './modules/upsert';
44

55
export class DataConnectionHelper {
@@ -35,19 +35,27 @@ export class DataConnectionHelper {
3535
return result;
3636
}
3737

38-
public async updateReplicatedDatasetFields(datasetId: string, repositoryFieldSet: Set<string>): Promise<string[]> {
38+
public async updateReplicatedDatasetFields(datasetId: string, repositoryFieldSet: Set<string>): Promise<ChangedAndMissingFields> {
3939
const replicatedDatasetFieldsObject = await this.getReplicatedDatasetFields(datasetId);
40-
const result = new Array<string>();
40+
const changedFields = new Array<string>();
41+
const orgFieldSet = new Set<string>();
4142
for (const field of replicatedDatasetFieldsObject.fields) {
43+
orgFieldSet.add(field.name);
4244
if (repositoryFieldSet?.has(field.name) && field.skipped) {
4345
field.skipped = false;
44-
result.push(field.name);
46+
changedFields.push(field.name);
4547
}
4648
}
47-
if (result.length > 0) {
49+
if (changedFields.length > 0) {
4850
await this.patchReplicatedDatasetFields(datasetId, replicatedDatasetFieldsObject);
4951
}
50-
return result;
52+
const missingFields = new Array<string>();
53+
for (const field of Array.from(repositoryFieldSet)){
54+
if(!orgFieldSet.has(field)){
55+
missingFields.push(field);
56+
}
57+
}
58+
return {changedFields, missingFields};
5159
}
5260

5361
private async getReplicatedDatasetFields(datasetId: string): Promise<GetReplicatedDatasetFields> {

src/modules/upsert.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@ export type GetDataConnectors = {
8080
dataConnectors: DataConnector[];
8181
url: string;
8282
};
83+
84+
export type ChangedAndMissingFields = {
85+
changedFields: string[];
86+
missingFields: string[];
87+
}

test/commands/analytics/connected-objects/upsert.nut.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import * as path from 'path';
22
import { expect } from 'chai';
33
import { TestSession, execCmd } from '@salesforce/cli-plugins-testkit';
4+
import { Messages } from '@salesforce/core';
45
import ConnectedObjectUpsertResult from '../../../../src/commands/analytics/connected-objects/upsert';
56

7+
Messages.importMessagesDirectory(__dirname);
8+
const messages = Messages.loadMessages('plugin-analytics-connected-objects', 'connected-objects.upsert');
9+
610
describe('analytics connected-objects upsert NUTs', () => {
711
let session: TestSession;
812
let defaultUsername: string | undefined;
@@ -37,12 +41,13 @@ describe('analytics connected-objects upsert NUTs', () => {
3741
]);
3842
});
3943

40-
it('should evaluate multiple recipes and upsert the respective connected-objects', () => {
44+
it('should evaluate multiple recipes and upsert the respective connected-objects (warn: 1 extra field found)', () => {
4145
const name = 'Simple_Recipe,Complex_Recipe';
4246
const command = `analytics connected-objects upsert --recipe-names ${name} -o ${defaultUsername} --json`;
43-
const result = execCmd<ConnectedObjectUpsertResult[]>(command, { ensureExitCode: 0, cli: 'sf' }).jsonOutput?.result;
44-
expect(result).to.deep.equal([
45-
{
47+
const output = execCmd<ConnectedObjectUpsertResult[]>(command, { ensureExitCode: 0, cli: 'sf' }).jsonOutput;
48+
expect(output).to.deep.equal({
49+
status: 0,
50+
result: [{
4651
connectorName: 'SFDC_LOCAL',
4752
objectName: 'User',
4853
isNew: false,
@@ -68,7 +73,10 @@ describe('analytics connected-objects upsert NUTs', () => {
6873
isNew: true,
6974
fields: ['Id', 'Name'],
7075
fieldsCount: 2,
71-
},
72-
]);
76+
}],
77+
warnings: [
78+
messages.getMessage('fields.not.found', [ 'User', 'SFDC_LOCAL' , 'Extra__c'])
79+
]
80+
});
7381
});
7482
});

test/commands/analytics/connected-objects/upsert.test.ts

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,15 @@ import { PostReplicatedDataset } from '../../../../src/modules/upsert';
1111
import { MetadataBuilder } from '../../../../src/metadataBuilder';
1212
import ConnectedObjectUpsert from '../../../../src/commands/analytics/connected-objects/upsert';
1313
import {
14-
createReplicatedDateset,
15-
getDataConnectors,
16-
getEmptyReplicatedDataset,
17-
getReplicatedDatasetFields,
18-
getReplicatedDatasets,
14+
createReplicatedDateset, getDataConnectors, getEmptyReplicatedDataset, getReplicatedDatasetFields, getReplicatedDatasets
1915
} from './mocks/apis';
2016
import { recipeFields, simpleRecipe } from './mocks/recipes';
2117

2218
describe('analytics recipe run', () => {
2319
const $$ = new TestContext();
2420
const testOrg = new MockTestOrgData();
2521
const config = new Config({ root: resolve(__dirname, '../../../package.json') });
22+
const commandParams = ['--target-org', 'test@org.com', '--recipe-names', 'Simple_Recipe'];
2623

2724
beforeEach('prepare session', async () => {
2825
await $$.stubAuths(testOrg);
@@ -40,50 +37,42 @@ describe('analytics recipe run', () => {
4037
result = createReplicatedDateset(body.connectorId, body.sourceObjectName);
4138
} else {
4239
// Replicated Data Fields API
43-
const fieldIsSkipped = new Map([...recipeFields, 'Extra'].map((field) => [field, true]));
40+
const fieldIsSkipped = new Map(recipeFields.map((field) => [field, true]));
4441
result = getReplicatedDatasetFields(fieldIsSkipped);
4542
}
4643
return Promise.resolve(result);
4744
};
4845
});
4946

50-
after(async () => {
51-
$$.restore();
52-
});
53-
54-
it('should create a new connected-object with all recipe fields (except "Extra"), return a json', async () => {
47+
after(async () => { $$.restore(); });
48+
49+
it('should mark multiple fields and return a json', async () => {
5550
stubMethodsInMetadataBuilder($$, simpleRecipe);
56-
const cmd = new ConnectedObjectUpsert(
57-
['--target-org', 'test@org.com', '--recipe-names', 'Simple_Recipe', '--json'],
58-
config
59-
);
51+
const cmd = new ConnectedObjectUpsert([...commandParams, '--json'], config);
6052
const result = await cmd.run();
6153
expect(result).to.deep.equal([
6254
{
6355
objectName: 'User',
6456
isNew: true,
6557
fields: recipeFields,
6658
fieldsCount: recipeFields.length,
67-
connectorName: 'SFDC_LOCAL',
68-
},
59+
connectorName: 'SFDC_LOCAL'
60+
}
6961
]);
7062
});
7163

72-
it('should update a single connected-object with 1 changed fields, return a json', async () => {
64+
it('should mark a single field and return a json', async () => {
7365
$$.SANDBOX.stub(MetadataBuilder.prototype, 'getElements').resolves([simpleRecipe]);
7466
$$.SANDBOX.stub(DataConnectionHelper.prototype, 'getReplicatedDatasets').resolves(
7567
getReplicatedDatasets(['User']).replicatedDatasets
7668
);
77-
const fieldIsSkipped = new Map([...recipeFields, 'Extra'].map((field) => [field, false]));
69+
const fieldIsSkipped = new Map(recipeFields.map((field) => [field, false]));
7870
const USERNAME = 'Username';
7971
fieldIsSkipped.set(USERNAME, true);
8072
$$.SANDBOX.stub(DataConnectionHelper.prototype, 'getReplicatedDatasetFields' as any).resolves(
8173
getReplicatedDatasetFields(fieldIsSkipped)
8274
);
83-
const cmd = new ConnectedObjectUpsert(
84-
['--target-org', 'test@org.com', '--recipe-names', 'Simple_Recipe', '--json', '--verbose'],
85-
config
86-
);
75+
const cmd = new ConnectedObjectUpsert([...commandParams, '--json'], config);
8776
const result = await cmd.run();
8877
expect(result).to.deep.equal([
8978
{
@@ -92,39 +81,35 @@ describe('analytics recipe run', () => {
9281
fields: [USERNAME],
9382
fieldsCount: 1,
9483
connectorName: 'SFDC_LOCAL',
95-
},
84+
}
9685
]);
9786
});
9887

99-
it('should update a single connected-object with 1 changed field, print result', async () => {
88+
it('should mark multiple fields and print result (warn: 1 extra field found)', async () => {
10089
$$.SANDBOX.stub(MetadataBuilder.prototype, 'getElements').resolves([simpleRecipe]);
10190
$$.SANDBOX.stub(DataConnectionHelper.prototype, 'getReplicatedDatasets').resolves(
10291
getReplicatedDatasets(['User']).replicatedDatasets
10392
);
104-
const fieldIsSkipped = new Map([...recipeFields, 'Extra'].map((field) => [field, true]));
93+
const fieldIsSkipped = new Map(recipeFields.map((field) => [field, true]));
94+
recipeFields.push('Extra__c');
10595
$$.SANDBOX.stub(DataConnectionHelper.prototype, 'getReplicatedDatasetFields' as any).resolves(
10696
getReplicatedDatasetFields(fieldIsSkipped)
10797
);
108-
const cmd = new ConnectedObjectUpsert(
109-
['--target-org', 'test@org.com', '--recipe-names', 'Simple_Recipe', '--verbose'],
110-
config
111-
);
98+
const cmd = new ConnectedObjectUpsert([...commandParams, '--verbose'], config);
11299
await cmd.run();
113100
});
114101

115-
it('should make no change and return a json', async () => {
102+
it('should make no changes and return a json', async () => {
116103
$$.SANDBOX.stub(MetadataBuilder.prototype, 'getElements').resolves([simpleRecipe]);
117104
$$.SANDBOX.stub(DataConnectionHelper.prototype, 'getReplicatedDatasets').resolves(
118105
getReplicatedDatasets(['User']).replicatedDatasets
119106
);
120-
const fieldIsSkipped = new Map([...recipeFields, 'Extra'].map((field) => [field, false]));
107+
const fieldIsSkipped = new Map(recipeFields.map((field) => [field, false]));
108+
recipeFields.push('Extra__c');
121109
$$.SANDBOX.stub(DataConnectionHelper.prototype, 'getReplicatedDatasetFields' as any).resolves(
122110
getReplicatedDatasetFields(fieldIsSkipped)
123111
);
124-
const cmd = new ConnectedObjectUpsert(
125-
['--target-org', 'test@org.com', '--recipe-names', 'Simple_Recipe', '--json', '--verbose'],
126-
config
127-
);
112+
const cmd = new ConnectedObjectUpsert([...commandParams, '--json', '--verbose'], config);
128113
const result = await cmd.run();
129114
expect(result).to.lengthOf(0);
130115
});

0 commit comments

Comments
 (0)