Skip to content

Commit 59071e2

Browse files
committed
fix a response validation
1 parent 6e60b63 commit 59071e2

4 files changed

Lines changed: 56 additions & 74 deletions

File tree

packages/devextreme/js/__internal/grids/grid_core/ai_assistant/__tests__/ai_assistant_controller.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ import {
1616
AI_ASSISTANT_AUTHOR_ID,
1717
MessageStatus,
1818
} from '../const';
19+
import { GridCommands } from '../grid_commands';
20+
import type { CommandResult } from '../types';
21+
22+
jest.mock('../grid_commands');
23+
24+
const MockedGridCommands = jest.mocked(GridCommands);
1925

2026
let sendRequestCallbacks: RequestCallbacks<ExecuteGridAssistantCommandResult> = {};
2127

@@ -59,6 +65,12 @@ const getStore = (controller: AIAssistantController): ArrayStore<Message, string
5965
describe('AIAssistantController', () => {
6066
beforeEach(() => {
6167
jest.clearAllMocks();
68+
69+
// TODO: Rework the tests using updated GridCommands implementation
70+
MockedGridCommands.mockImplementation(() => ({
71+
validate: jest.fn().mockReturnValue(true),
72+
executeCommands: jest.fn<() => Promise<CommandResult[]>>().mockResolvedValue([{ status: 'success', message: 'sort' }]),
73+
}) as unknown as GridCommands);
6274
});
6375

6476
describe('getMessageDataSource', () => {

packages/devextreme/js/__internal/grids/grid_core/ai_assistant/__tests__/grid_commands.test.ts

Lines changed: 40 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -339,42 +339,20 @@ describe('GridCommands', () => {
339339
});
340340
const gridCommands = new GridCommands(createMockComponent(), [command]);
341341

342-
const result = gridCommands.validate({
343-
actions: [{ name: 'test', args: { value: 'hello' } }],
344-
});
342+
const result = gridCommands.validate(
343+
[{ name: 'test', args: { value: 'hello' } }],
344+
);
345345

346346
expect(result).toBe(true);
347347
});
348348

349-
it('should return false if response.actions is not an array', () => {
350-
const gridCommands = new GridCommands(createMockComponent(), []);
351-
352-
expect(gridCommands.validate({ actions: 'not-array' })).toBe(false);
353-
expect(gridCommands.validate({ actions: 123 })).toBe(false);
354-
expect(gridCommands.validate({ actions: {} })).toBe(false);
355-
});
356-
357-
it('should return false if response.actions is missing', () => {
358-
const gridCommands = new GridCommands(createMockComponent(), []);
359-
360-
expect(gridCommands.validate({})).toBe(false);
361-
expect(gridCommands.validate({ other: [] })).toBe(false);
362-
});
363-
364-
it('should return false if response is null or undefined', () => {
365-
const gridCommands = new GridCommands(createMockComponent(), []);
366-
367-
expect(gridCommands.validate(null)).toBe(false);
368-
expect(gridCommands.validate(undefined)).toBe(false);
369-
});
370-
371349
it('should return false if any action has an unknown name', () => {
372350
const command = createMockCommand('known');
373351
const gridCommands = new GridCommands(createMockComponent(), [command]);
374352

375-
const result = gridCommands.validate({
376-
actions: [{ name: 'unknown', args: {} }],
377-
});
353+
const result = gridCommands.validate(
354+
[{ name: 'unknown', args: {} }],
355+
);
378356

379357
expect(result).toBe(false);
380358
});
@@ -384,23 +362,23 @@ describe('GridCommands', () => {
384362
createMockCommand('test'),
385363
]);
386364

387-
expect(gridCommands.validate({
388-
actions: [{ name: 123, args: {} }],
389-
})).toBe(false);
365+
expect(gridCommands.validate(
366+
[{ name: 123 as unknown as string, args: {} }],
367+
)).toBe(false);
390368

391-
expect(gridCommands.validate({
392-
actions: [{ name: true, args: {} }],
393-
})).toBe(false);
369+
expect(gridCommands.validate(
370+
[{ name: true as unknown as string, args: {} }],
371+
)).toBe(false);
394372
});
395373

396374
it('should return false if any action name is an empty string', () => {
397375
const gridCommands = new GridCommands(createMockComponent(), [
398376
createMockCommand('test'),
399377
]);
400378

401-
const result = gridCommands.validate({
402-
actions: [{ name: '', args: {} }],
403-
});
379+
const result = gridCommands.validate(
380+
[{ name: '', args: {} }],
381+
);
404382

405383
expect(result).toBe(false);
406384
});
@@ -410,23 +388,23 @@ describe('GridCommands', () => {
410388
createMockCommand('test'),
411389
]);
412390

413-
expect(gridCommands.validate({
414-
actions: [{ args: {} }],
415-
})).toBe(false);
391+
expect(gridCommands.validate(
392+
[{ args: {} } as any],
393+
)).toBe(false);
416394

417-
expect(gridCommands.validate({
418-
actions: [{ name: 'test' }],
419-
})).toBe(false);
395+
expect(gridCommands.validate(
396+
[{ name: 'test' } as any],
397+
)).toBe(false);
420398
});
421399

422400
it('should return false if any action args is null', () => {
423401
const gridCommands = new GridCommands(createMockComponent(), [
424402
createMockCommand('test'),
425403
]);
426404

427-
const result = gridCommands.validate({
428-
actions: [{ name: 'test', args: null }],
429-
});
405+
const result = gridCommands.validate(
406+
[{ name: 'test', args: null as unknown as Record<string, unknown> }],
407+
);
430408

431409
expect(result).toBe(false);
432410
});
@@ -437,9 +415,9 @@ describe('GridCommands', () => {
437415
});
438416
const gridCommands = new GridCommands(createMockComponent(), [command]);
439417

440-
const result = gridCommands.validate({
441-
actions: [{ name: 'test', args: { value: 123 } }],
442-
});
418+
const result = gridCommands.validate(
419+
[{ name: 'test', args: { value: 123 } }],
420+
);
443421

444422
expect(result).toBe(false);
445423
});
@@ -450,9 +428,9 @@ describe('GridCommands', () => {
450428
});
451429
const gridCommands = new GridCommands(createMockComponent(), [command]);
452430

453-
const result = gridCommands.validate({
454-
actions: [{ name: 'test', args: {} }],
455-
});
431+
const result = gridCommands.validate(
432+
[{ name: 'test', args: {} }],
433+
);
456434

457435
expect(result).toBe(false);
458436
});
@@ -463,17 +441,17 @@ describe('GridCommands', () => {
463441
});
464442
const gridCommands = new GridCommands(createMockComponent(), [command]);
465443

466-
const result = gridCommands.validate({
467-
actions: [{ name: 'test', args: { value: 'ok', extra: true } }],
468-
});
444+
const result = gridCommands.validate(
445+
[{ name: 'test', args: { value: 'ok', extra: true } }],
446+
);
469447

470448
expect(result).toBe(false);
471449
});
472450

473451
it('should return true for an empty actions array', () => {
474452
const gridCommands = new GridCommands(createMockComponent(), []);
475453

476-
const result = gridCommands.validate({ actions: [] });
454+
const result = gridCommands.validate([]);
477455

478456
expect(result).toBe(true);
479457
});
@@ -482,9 +460,9 @@ describe('GridCommands', () => {
482460
const command = createMockCommand('clearFilter');
483461
const gridCommands = new GridCommands(createMockComponent(), [command]);
484462

485-
const result = gridCommands.validate({
486-
actions: [{ name: 'clearFilter', args: {} }],
487-
});
463+
const result = gridCommands.validate(
464+
[{ name: 'clearFilter', args: {} }],
465+
);
488466

489467
expect(result).toBe(true);
490468
});
@@ -493,12 +471,12 @@ describe('GridCommands', () => {
493471
const command = createMockCommand('valid');
494472
const gridCommands = new GridCommands(createMockComponent(), [command]);
495473

496-
const result = gridCommands.validate({
497-
actions: [
474+
const result = gridCommands.validate(
475+
[
498476
{ name: 'valid', args: {} },
499477
{ name: 'invalid', args: {} },
500478
],
501-
});
479+
);
502480

503481
expect(result).toBe(false);
504482
});

packages/devextreme/js/__internal/grids/grid_core/ai_assistant/ai_assistant_controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class AIAssistantController extends Controller {
3333
}
3434

3535
private processResponse(response: ExecuteGridAssistantCommandResult): Promise<CommandResults> {
36-
if (!response?.actions) {
36+
if (!response?.actions || !Array.isArray(response.actions)) {
3737
// TODO: need to localize default error message when there are no commands
3838
return Promise.reject(new Error('Default error message'));
3939
}

packages/devextreme/js/__internal/grids/grid_core/ai_assistant/grid_commands.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import type {
2-
ExecuteGridAssistantAction,
3-
} from '@js/common/ai-integration';
1+
import type { ExecuteGridAssistantAction } from '@js/common/ai-integration';
42
import messageLocalization from '@js/common/core/localization/message';
53
import { isDefined, isObject } from '@js/core/utils/type';
64
import { zodToJsonSchema } from 'zod-to-json-schema';
@@ -118,14 +116,8 @@ export class GridCommands {
118116
};
119117
}
120118

121-
public validate(response: unknown): boolean {
122-
const res = response as Record<string, unknown>;
123-
124-
if (!res || !Array.isArray(res.actions)) {
125-
return false;
126-
}
127-
128-
for (const action of res.actions as Record<string, unknown>[]) {
119+
public validate(actions: ExecuteGridAssistantAction[]): boolean {
120+
for (const action of actions as Record<string, unknown>[]) {
129121
if (!action || typeof action.name !== 'string' || action.name === '') {
130122
return false;
131123
}

0 commit comments

Comments
 (0)