@microsoft/power-apps-cli 0.5.4 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Constants/HelpStrings.d.ts +3 -3
- package/lib/Constants/HelpStrings.js +3 -3
- package/lib/Constants/HelpStrings.js.map +1 -1
- package/lib/HttpClient/CliHttpClient.d.ts.map +1 -1
- package/lib/HttpClient/CliHttpClient.js +8 -1
- package/lib/HttpClient/CliHttpClient.js.map +1 -1
- package/lib/Verbs/AddDataSource.d.ts.map +1 -1
- package/lib/Verbs/AddDataSource.js +7 -6
- package/lib/Verbs/AddDataSource.js.map +1 -1
- package/lib/Verbs/DeleteDataSource.d.ts +1 -1
- package/lib/Verbs/DeleteDataSource.d.ts.map +1 -1
- package/lib/Verbs/DeleteDataSource.js +2 -1
- package/lib/Verbs/DeleteDataSource.js.map +1 -1
- package/lib/Verbs/ListConnectionReferences.js +6 -6
- package/lib/Verbs/ListConnectionReferences.js.map +1 -1
- package/lib/Verbs/ListEnvironmentVariables.js +6 -6
- package/lib/Verbs/ListEnvironmentVariables.js.map +1 -1
- package/lib/Verbs/Push.js +7 -10
- package/lib/Verbs/Push.js.map +1 -1
- package/lib/Verbs/VerbConstants.d.ts +1 -1
- package/lib/Verbs/VerbConstants.js +3 -3
- package/lib/Verbs/VerbConstants.js.map +1 -1
- package/lib/__tests__/E2eTests/addAndDeleteDataverseDS.test.js +4 -3
- package/lib/__tests__/E2eTests/addAndDeleteDataverseDS.test.js.map +1 -1
- package/lib/__tests__/E2eTests/addTop10Datasources.test.js +3 -2
- package/lib/__tests__/E2eTests/addTop10Datasources.test.js.map +1 -1
- package/lib/__tests__/E2eTests/cliHelp.test.js +4 -11
- package/lib/__tests__/E2eTests/cliHelp.test.js.map +1 -1
- package/lib/__tests__/helpers/e2eTestHelpers.d.ts +24 -0
- package/lib/__tests__/helpers/e2eTestHelpers.d.ts.map +1 -0
- package/lib/__tests__/helpers/e2eTestHelpers.js +28 -0
- package/lib/__tests__/helpers/e2eTestHelpers.js.map +1 -0
- package/lib-cjs/Constants/HelpStrings.d.ts +3 -3
- package/lib-cjs/Constants/HelpStrings.js +3 -3
- package/lib-cjs/Constants/HelpStrings.js.map +1 -1
- package/lib-cjs/HttpClient/CliHttpClient.d.ts.map +1 -1
- package/lib-cjs/HttpClient/CliHttpClient.js +8 -2
- package/lib-cjs/HttpClient/CliHttpClient.js.map +1 -1
- package/lib-cjs/Verbs/AddDataSource.d.ts.map +1 -1
- package/lib-cjs/Verbs/AddDataSource.js +7 -6
- package/lib-cjs/Verbs/AddDataSource.js.map +1 -1
- package/lib-cjs/Verbs/DeleteDataSource.d.ts +1 -1
- package/lib-cjs/Verbs/DeleteDataSource.d.ts.map +1 -1
- package/lib-cjs/Verbs/DeleteDataSource.js +5 -1
- package/lib-cjs/Verbs/DeleteDataSource.js.map +1 -1
- package/lib-cjs/Verbs/ListConnectionReferences.js +6 -6
- package/lib-cjs/Verbs/ListConnectionReferences.js.map +1 -1
- package/lib-cjs/Verbs/ListEnvironmentVariables.js +6 -6
- package/lib-cjs/Verbs/ListEnvironmentVariables.js.map +1 -1
- package/lib-cjs/Verbs/Push.js +11 -16
- package/lib-cjs/Verbs/Push.js.map +1 -1
- package/lib-cjs/Verbs/VerbConstants.d.ts +1 -1
- package/lib-cjs/Verbs/VerbConstants.js +3 -3
- package/lib-cjs/Verbs/VerbConstants.js.map +1 -1
- package/lib-cjs/__tests__/E2eTests/addAndDeleteDataverseDS.test.js +3 -2
- package/lib-cjs/__tests__/E2eTests/addAndDeleteDataverseDS.test.js.map +1 -1
- package/lib-cjs/__tests__/E2eTests/addTop10Datasources.test.js +2 -1
- package/lib-cjs/__tests__/E2eTests/addTop10Datasources.test.js.map +1 -1
- package/lib-cjs/__tests__/E2eTests/cliHelp.test.js +4 -11
- package/lib-cjs/__tests__/E2eTests/cliHelp.test.js.map +1 -1
- package/lib-cjs/__tests__/helpers/e2eTestHelpers.d.ts +23 -0
- package/lib-cjs/__tests__/helpers/e2eTestHelpers.d.ts.map +1 -0
- package/lib-cjs/__tests__/helpers/e2eTestHelpers.js +31 -0
- package/lib-cjs/__tests__/helpers/e2eTestHelpers.js.map +1 -0
- package/node_modules/@microsoft/powerapps-data/package.json +2 -2
- package/node_modules/@microsoft/powerapps-player-actions/lib/Actions/PushApp.js +10 -3
- package/node_modules/@microsoft/powerapps-player-actions/lib/Actions/PushApp.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/codeGenUtils.d.ts +20 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/codeGenUtils.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/codeGenUtils.js +79 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/codeGenUtils.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/dataSourceInfoProcessor.d.ts +2 -2
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/dataSourceInfoProcessor.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/dataSourceInfoProcessor.js +27 -68
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/dataSourceInfoProcessor.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/modelServiceGenerator.d.ts +0 -59
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/modelServiceGenerator.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/modelServiceGenerator.js +69 -281
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/modelServiceGenerator.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/nameUtility.d.ts +26 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/nameUtility.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/nameUtility.js +153 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/CodeGen/nameUtility.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/AzureDevOpsModelServiceGenerator.spec.d.ts +5 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/AzureDevOpsModelServiceGenerator.spec.d.ts.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/AzureDevOpsModelServiceGenerator.spec.js +93 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/AzureDevOpsModelServiceGenerator.spec.js.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/DataSourceInfoProcessor.spec.js +897 -2
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/DataSourceInfoProcessor.spec.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/ModelServiceGenerator.spec.js +1 -17
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/ModelServiceGenerator.spec.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/arrayTypeGeneration.spec.d.ts +5 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/arrayTypeGeneration.spec.d.ts.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/arrayTypeGeneration.spec.js +63 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib/__tests__/arrayTypeGeneration.spec.js.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/Actions/PushApp.js +9 -4
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/Actions/PushApp.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/codeGenUtils.d.ts +20 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/codeGenUtils.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/codeGenUtils.js +86 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/codeGenUtils.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/dataSourceInfoProcessor.d.ts +2 -2
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/dataSourceInfoProcessor.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/dataSourceInfoProcessor.js +25 -67
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/dataSourceInfoProcessor.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/modelServiceGenerator.d.ts +0 -59
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/modelServiceGenerator.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/modelServiceGenerator.js +65 -279
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/modelServiceGenerator.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/nameUtility.d.ts +26 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/nameUtility.d.ts.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/nameUtility.js +161 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/CodeGen/nameUtility.js.map +1 -1
- package/node_modules/@microsoft/{powerapps-data/lib/components/codeGen/dataSourceInfo.js → powerapps-player-actions/lib-cjs/__tests__/AzureDevOpsModelServiceGenerator.spec.d.ts} +0 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/AzureDevOpsModelServiceGenerator.spec.d.ts.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/AzureDevOpsModelServiceGenerator.spec.js +206 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/AzureDevOpsModelServiceGenerator.spec.js.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/DataSourceInfoProcessor.spec.js +1277 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/DataSourceInfoProcessor.spec.js.map +1 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/ModelServiceGenerator.spec.js +0 -32
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/ModelServiceGenerator.spec.js.map +1 -1
- package/node_modules/@microsoft/{powerapps-data/lib/__tests__/dataSourceInfoProcessor.test.d.ts → powerapps-player-actions/lib-cjs/__tests__/arrayTypeGeneration.spec.d.ts} +0 -1
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/arrayTypeGeneration.spec.d.ts.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/arrayTypeGeneration.spec.js +171 -0
- package/node_modules/@microsoft/powerapps-player-actions/lib-cjs/__tests__/arrayTypeGeneration.spec.js.map +1 -0
- package/node_modules/@microsoft/powerapps-player-actions/package.json +2 -2
- package/node_modules/@pa-client/powerapps-player-services/package.json +1 -1
- package/package.json +4 -4
- package/node_modules/@microsoft/powerapps-data/lib/__tests__/dataSourceInfoProcessor.test.d.ts.map +0 -1
- package/node_modules/@microsoft/powerapps-data/lib/__tests__/dataSourceInfoProcessor.test.js +0 -782
- package/node_modules/@microsoft/powerapps-data/lib/__tests__/dataSourceInfoProcessor.test.js.map +0 -1
- package/node_modules/@microsoft/powerapps-data/lib/components/codeGen/dataSourceInfo.d.ts +0 -28
- package/node_modules/@microsoft/powerapps-data/lib/components/codeGen/dataSourceInfo.d.ts.map +0 -1
- package/node_modules/@microsoft/powerapps-data/lib/components/codeGen/dataSourceInfo.js.map +0 -1
- package/node_modules/@microsoft/powerapps-data/lib/components/codeGen/dataSourceInfoProcessor.d.ts +0 -10
- package/node_modules/@microsoft/powerapps-data/lib/components/codeGen/dataSourceInfoProcessor.d.ts.map +0 -1
- package/node_modules/@microsoft/powerapps-data/lib/components/codeGen/dataSourceInfoProcessor.js +0 -530
- package/node_modules/@microsoft/powerapps-data/lib/components/codeGen/dataSourceInfoProcessor.js.map +0 -1
package/node_modules/@microsoft/powerapps-data/lib/__tests__/dataSourceInfoProcessor.test.js
DELETED
|
@@ -1,782 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import { beforeEach, describe, expect, it } from '@jest/globals';
|
|
5
|
-
import * as fs from 'fs';
|
|
6
|
-
import * as path from 'path';
|
|
7
|
-
import { processDataSourceInfo } from '../components/codeGen/dataSourceInfoProcessor';
|
|
8
|
-
import { getMockLogger } from './mocks/Logger.mock';
|
|
9
|
-
// Mock fs module
|
|
10
|
-
jest.mock('fs');
|
|
11
|
-
const mockedFs = fs;
|
|
12
|
-
// Mock path module
|
|
13
|
-
jest.mock('path');
|
|
14
|
-
const mockedPath = path;
|
|
15
|
-
// Helper function to create mock directory entries
|
|
16
|
-
function createMockDirEntry(name, isDirectory) {
|
|
17
|
-
return {
|
|
18
|
-
name,
|
|
19
|
-
isDirectory: () => isDirectory,
|
|
20
|
-
isFile: () => !isDirectory,
|
|
21
|
-
isBlockDevice: () => false,
|
|
22
|
-
isCharacterDevice: () => false,
|
|
23
|
-
isSymbolicLink: () => false,
|
|
24
|
-
isFIFO: () => false,
|
|
25
|
-
isSocket: () => false,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const mockLogger = getMockLogger();
|
|
29
|
-
describe('dataSourceInfoProcessor', () => {
|
|
30
|
-
beforeEach(() => {
|
|
31
|
-
jest.clearAllMocks();
|
|
32
|
-
// Setup default mocks
|
|
33
|
-
mockedPath.join.mockImplementation((...args) => args.join('/'));
|
|
34
|
-
mockedFs.existsSync.mockReturnValue(false);
|
|
35
|
-
mockedFs.mkdirSync.mockImplementation();
|
|
36
|
-
mockedFs.writeFileSync.mockImplementation();
|
|
37
|
-
});
|
|
38
|
-
describe('processDataSourceInfo', () => {
|
|
39
|
-
it('should process empty folder without errors', () => {
|
|
40
|
-
// Arrange
|
|
41
|
-
const folderPath = '/test/folder';
|
|
42
|
-
mockedFs.readdirSync.mockReturnValue([]);
|
|
43
|
-
// Act & Assert
|
|
44
|
-
expect(() => processDataSourceInfo(folderPath, mockLogger)).not.toThrow();
|
|
45
|
-
});
|
|
46
|
-
it('should process folder with JSON files and generate output', () => {
|
|
47
|
-
// Arrange
|
|
48
|
-
const folderPath = '/test/folder';
|
|
49
|
-
const jsonContent = JSON.stringify({
|
|
50
|
-
type: 'Microsoft.PowerApps/apis',
|
|
51
|
-
properties: {
|
|
52
|
-
swagger: {
|
|
53
|
-
paths: {
|
|
54
|
-
'/test': {
|
|
55
|
-
get: {
|
|
56
|
-
operationId: 'GetTest',
|
|
57
|
-
responses: {
|
|
58
|
-
'200': {
|
|
59
|
-
description: 'Success',
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
// Mock file system operations
|
|
69
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('test.json', false)]);
|
|
70
|
-
mockedFs.readFileSync.mockReturnValue(jsonContent);
|
|
71
|
-
mockedPath.join.mockImplementation((...args) => args.join('/'));
|
|
72
|
-
// Act
|
|
73
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
74
|
-
// Assert
|
|
75
|
-
expect(mockedFs.readFileSync).toHaveBeenCalledWith('/test/folder/test.json', 'utf-8');
|
|
76
|
-
expect(mockedFs.writeFileSync).toHaveBeenCalled();
|
|
77
|
-
});
|
|
78
|
-
it('should handle errors gracefully and wrap in descriptive error', () => {
|
|
79
|
-
// Arrange
|
|
80
|
-
const folderPath = '/test/folder';
|
|
81
|
-
mockedFs.readdirSync.mockImplementation(() => {
|
|
82
|
-
throw new Error('Permission denied');
|
|
83
|
-
});
|
|
84
|
-
// Act & Assert
|
|
85
|
-
expect(() => processDataSourceInfo(folderPath, mockLogger)).toThrow('An unexpected error occurred: Permission denied');
|
|
86
|
-
});
|
|
87
|
-
it('should handle file processing errors with file path context', () => {
|
|
88
|
-
// Arrange
|
|
89
|
-
const folderPath = '/test/folder';
|
|
90
|
-
const invalidJsonContent = '{ invalid json';
|
|
91
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('invalid.json', false)]);
|
|
92
|
-
mockedFs.readFileSync.mockReturnValue(invalidJsonContent);
|
|
93
|
-
// Act & Assert
|
|
94
|
-
expect(() => processDataSourceInfo(folderPath, mockLogger)).toThrow("Error processing file '/test/folder/invalid.json'");
|
|
95
|
-
});
|
|
96
|
-
it('should create output directory if it does not exist', () => {
|
|
97
|
-
// Arrange
|
|
98
|
-
const folderPath = '/test/folder';
|
|
99
|
-
mockedFs.readdirSync.mockReturnValue([]);
|
|
100
|
-
mockedFs.existsSync.mockReturnValue(false);
|
|
101
|
-
// Act
|
|
102
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
103
|
-
// Assert
|
|
104
|
-
expect(mockedFs.mkdirSync).toHaveBeenCalledWith('/test/folder/../appschemas', { recursive: true });
|
|
105
|
-
});
|
|
106
|
-
it('should not create output directory if it already exists', () => {
|
|
107
|
-
// Arrange
|
|
108
|
-
const folderPath = '/test/folder';
|
|
109
|
-
mockedFs.readdirSync.mockReturnValue([]);
|
|
110
|
-
mockedFs.existsSync.mockReturnValue(true);
|
|
111
|
-
// Act
|
|
112
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
113
|
-
// Assert
|
|
114
|
-
expect(mockedFs.mkdirSync).not.toHaveBeenCalled();
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
describe('Swagger API processing', () => {
|
|
118
|
-
it('should process Microsoft.PowerApps/apis type with swagger paths', () => {
|
|
119
|
-
// Arrange
|
|
120
|
-
const folderPath = '/test/folder';
|
|
121
|
-
const swaggerJson = {
|
|
122
|
-
type: 'Microsoft.PowerApps/apis',
|
|
123
|
-
properties: {
|
|
124
|
-
swagger: {
|
|
125
|
-
paths: {
|
|
126
|
-
'/users': {
|
|
127
|
-
get: {
|
|
128
|
-
operationId: 'GetUsers',
|
|
129
|
-
parameters: [
|
|
130
|
-
{
|
|
131
|
-
name: 'limit',
|
|
132
|
-
in: 'query',
|
|
133
|
-
required: false,
|
|
134
|
-
type: 'integer',
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
responses: {
|
|
138
|
-
'200': {
|
|
139
|
-
description: 'Success',
|
|
140
|
-
schema: {
|
|
141
|
-
type: 'array',
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
post: {
|
|
147
|
-
operationId: 'CreateUser',
|
|
148
|
-
responses: {
|
|
149
|
-
'201': {
|
|
150
|
-
description: 'Created',
|
|
151
|
-
},
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('swagger.json', false)]);
|
|
160
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(swaggerJson));
|
|
161
|
-
// Act
|
|
162
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
163
|
-
// Assert
|
|
164
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
165
|
-
const generatedContent = writeCall[1];
|
|
166
|
-
expect(generatedContent).toContain('GetUsers');
|
|
167
|
-
expect(generatedContent).toContain('CreateUser');
|
|
168
|
-
expect(generatedContent).toContain('"/users"');
|
|
169
|
-
expect(generatedContent).toContain('"method": "GET"');
|
|
170
|
-
expect(generatedContent).toContain('"method": "POST"');
|
|
171
|
-
});
|
|
172
|
-
it('should handle swagger with parameter references', () => {
|
|
173
|
-
// Arrange
|
|
174
|
-
const folderPath = '/test/folder';
|
|
175
|
-
const swaggerJson = {
|
|
176
|
-
type: 'Microsoft.PowerApps/apis',
|
|
177
|
-
properties: {
|
|
178
|
-
swagger: {
|
|
179
|
-
paths: {
|
|
180
|
-
'/items': {
|
|
181
|
-
get: {
|
|
182
|
-
operationId: 'GetItems',
|
|
183
|
-
parameters: [
|
|
184
|
-
{
|
|
185
|
-
$ref: '#/swagger/parameters/CommonParam',
|
|
186
|
-
},
|
|
187
|
-
],
|
|
188
|
-
responses: {
|
|
189
|
-
'200': {
|
|
190
|
-
description: 'Success',
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
parameters: {
|
|
197
|
-
CommonParam: {
|
|
198
|
-
name: 'commonParam',
|
|
199
|
-
in: 'header',
|
|
200
|
-
required: true,
|
|
201
|
-
type: 'string',
|
|
202
|
-
},
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
};
|
|
207
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('swagger-ref.json', false)]);
|
|
208
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(swaggerJson));
|
|
209
|
-
// Act
|
|
210
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
211
|
-
// Assert
|
|
212
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
213
|
-
const generatedContent = writeCall[1];
|
|
214
|
-
expect(generatedContent).toContain('GetItems');
|
|
215
|
-
// Note: Parameter reference resolution is tested but the mock doesn't properly resolve it
|
|
216
|
-
// The actual implementation would resolve the commonParam parameter
|
|
217
|
-
});
|
|
218
|
-
it('should handle responses with schema references', () => {
|
|
219
|
-
// Arrange
|
|
220
|
-
const folderPath = '/test/folder';
|
|
221
|
-
const swaggerJson = {
|
|
222
|
-
type: 'Microsoft.PowerApps/apis',
|
|
223
|
-
properties: {
|
|
224
|
-
swagger: {
|
|
225
|
-
paths: {
|
|
226
|
-
'/models': {
|
|
227
|
-
get: {
|
|
228
|
-
operationId: 'GetModels',
|
|
229
|
-
responses: {
|
|
230
|
-
'200': {
|
|
231
|
-
description: 'Success',
|
|
232
|
-
schema: {
|
|
233
|
-
$ref: '#/definitions/ModelResponse',
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
definitions: {
|
|
241
|
-
ModelResponse: {
|
|
242
|
-
type: 'object',
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
};
|
|
248
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('models.json', false)]);
|
|
249
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(swaggerJson));
|
|
250
|
-
// Act
|
|
251
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
252
|
-
// Assert
|
|
253
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
254
|
-
const generatedContent = writeCall[1];
|
|
255
|
-
expect(generatedContent).toContain('GetModels');
|
|
256
|
-
expect(generatedContent).toContain('"type": "object"');
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
describe('SQL stored procedure processing', () => {
|
|
260
|
-
it('should process SQL stored procedure with input parameters', () => {
|
|
261
|
-
// Arrange
|
|
262
|
-
const folderPath = '/test/procedures/GetUserById';
|
|
263
|
-
const procedureJson = {
|
|
264
|
-
name: '[dbo].[GetUserById]',
|
|
265
|
-
schema: {
|
|
266
|
-
procedureresultschema: {
|
|
267
|
-
type: 'object',
|
|
268
|
-
},
|
|
269
|
-
inputparameters: {
|
|
270
|
-
properties: {
|
|
271
|
-
UserId: {
|
|
272
|
-
type: 'integer',
|
|
273
|
-
required: true,
|
|
274
|
-
},
|
|
275
|
-
IncludeDetails: {
|
|
276
|
-
type: 'boolean',
|
|
277
|
-
required: false,
|
|
278
|
-
},
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
},
|
|
282
|
-
};
|
|
283
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('procedure.json', false)]);
|
|
284
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(procedureJson));
|
|
285
|
-
// Act
|
|
286
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
287
|
-
// Assert
|
|
288
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
289
|
-
const generatedContent = writeCall[1];
|
|
290
|
-
expect(generatedContent).toContain('getuserbyid');
|
|
291
|
-
expect(generatedContent).toContain('"/dbo.GetUserById"');
|
|
292
|
-
expect(generatedContent).toContain('"method": "POST"');
|
|
293
|
-
expect(generatedContent).toContain('UserId');
|
|
294
|
-
expect(generatedContent).toContain('IncludeDetails');
|
|
295
|
-
});
|
|
296
|
-
it('should handle stored procedure without input parameters', () => {
|
|
297
|
-
// Arrange
|
|
298
|
-
const folderPath = '/test/procedures/GetAllUsers';
|
|
299
|
-
const procedureJson = {
|
|
300
|
-
name: '[dbo].[GetAllUsers]',
|
|
301
|
-
schema: {
|
|
302
|
-
procedureresultschema: {
|
|
303
|
-
type: 'array',
|
|
304
|
-
},
|
|
305
|
-
},
|
|
306
|
-
};
|
|
307
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('procedure.json', false)]);
|
|
308
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(procedureJson));
|
|
309
|
-
// Act
|
|
310
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
311
|
-
// Assert
|
|
312
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
313
|
-
const generatedContent = writeCall[1];
|
|
314
|
-
expect(generatedContent).toContain('getallusers');
|
|
315
|
-
expect(generatedContent).toContain('"/dbo.GetAllUsers"');
|
|
316
|
-
});
|
|
317
|
-
it('should determine property key from parent folder for stored procedures', () => {
|
|
318
|
-
// Arrange
|
|
319
|
-
const folderPath = '/test/procedures/UserProcedures';
|
|
320
|
-
const procedureJson = {
|
|
321
|
-
name: '[dbo].[GetUser]',
|
|
322
|
-
schema: {
|
|
323
|
-
procedureresultschema: {
|
|
324
|
-
type: 'object',
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
};
|
|
328
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('procedure.json', false)]);
|
|
329
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(procedureJson));
|
|
330
|
-
// Mock path operations for folder extraction
|
|
331
|
-
mockedPath.join.mockImplementation((...args) => args.join('/'));
|
|
332
|
-
// Act
|
|
333
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
334
|
-
// Assert
|
|
335
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
336
|
-
const generatedContent = writeCall[1];
|
|
337
|
-
expect(generatedContent).toContain('userprocedures');
|
|
338
|
-
});
|
|
339
|
-
it('should handle non-dbo schemas', () => {
|
|
340
|
-
// Arrange
|
|
341
|
-
const folderPath = '/test/procedures/GetAllUsers';
|
|
342
|
-
const procedureJson = {
|
|
343
|
-
name: '[foo].[GetAllUsers]',
|
|
344
|
-
schema: {
|
|
345
|
-
procedureresultschema: {
|
|
346
|
-
type: 'array',
|
|
347
|
-
},
|
|
348
|
-
},
|
|
349
|
-
};
|
|
350
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('procedure.json', false)]);
|
|
351
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(procedureJson));
|
|
352
|
-
// Act
|
|
353
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
354
|
-
// Assert
|
|
355
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
356
|
-
const generatedContent = writeCall[1];
|
|
357
|
-
expect(generatedContent).toContain('getallusers');
|
|
358
|
-
expect(generatedContent).toContain('"/foo.GetAllUsers"');
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
describe('SQL table processing', () => {
|
|
362
|
-
it('should process SQL table schema with primary key', () => {
|
|
363
|
-
// Arrange
|
|
364
|
-
const folderPath = '/test/tables';
|
|
365
|
-
const tableJson = {
|
|
366
|
-
name: '[dbo].[Users]',
|
|
367
|
-
schema: {
|
|
368
|
-
items: {
|
|
369
|
-
properties: {
|
|
370
|
-
Id: {
|
|
371
|
-
type: 'integer',
|
|
372
|
-
'x-ms-keyType': 'primary',
|
|
373
|
-
},
|
|
374
|
-
Name: {
|
|
375
|
-
type: 'string',
|
|
376
|
-
},
|
|
377
|
-
Email: {
|
|
378
|
-
type: 'string',
|
|
379
|
-
},
|
|
380
|
-
},
|
|
381
|
-
},
|
|
382
|
-
},
|
|
383
|
-
};
|
|
384
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('users.json', false)]);
|
|
385
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(tableJson));
|
|
386
|
-
// Act
|
|
387
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
388
|
-
// Assert
|
|
389
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
390
|
-
const generatedContent = writeCall[1];
|
|
391
|
-
expect(generatedContent).toContain('users');
|
|
392
|
-
expect(generatedContent).toContain('"tableId": "Users"');
|
|
393
|
-
expect(generatedContent).toContain('"version": "v2"');
|
|
394
|
-
expect(generatedContent).toContain('"primaryKey": "Id"');
|
|
395
|
-
});
|
|
396
|
-
it('should handle table without primary key', () => {
|
|
397
|
-
// Arrange
|
|
398
|
-
const folderPath = '/test/tables';
|
|
399
|
-
const tableJson = {
|
|
400
|
-
name: '[dbo].[Logs]',
|
|
401
|
-
schema: {
|
|
402
|
-
items: {
|
|
403
|
-
properties: {
|
|
404
|
-
Message: {
|
|
405
|
-
type: 'string',
|
|
406
|
-
},
|
|
407
|
-
Timestamp: {
|
|
408
|
-
type: 'string',
|
|
409
|
-
},
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
},
|
|
413
|
-
};
|
|
414
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('logs.json', false)]);
|
|
415
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(tableJson));
|
|
416
|
-
// Act
|
|
417
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
418
|
-
// Assert
|
|
419
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
420
|
-
const generatedContent = writeCall[1];
|
|
421
|
-
expect(generatedContent).toContain('logs');
|
|
422
|
-
expect(generatedContent).toContain('"primaryKey": ""');
|
|
423
|
-
});
|
|
424
|
-
});
|
|
425
|
-
describe('Property key determination', () => {
|
|
426
|
-
it('should remove [dbo]. prefix and brackets from SQL table names', () => {
|
|
427
|
-
// Arrange
|
|
428
|
-
const folderPath = '/test/tables';
|
|
429
|
-
const tableJson = {
|
|
430
|
-
name: '[dbo].[ComplexTableName]',
|
|
431
|
-
schema: {
|
|
432
|
-
items: {
|
|
433
|
-
properties: {},
|
|
434
|
-
},
|
|
435
|
-
},
|
|
436
|
-
};
|
|
437
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('table.json', false)]);
|
|
438
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(tableJson));
|
|
439
|
-
// Act
|
|
440
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
441
|
-
// Assert
|
|
442
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
443
|
-
const generatedContent = writeCall[1];
|
|
444
|
-
expect(generatedContent).toContain('complextablename');
|
|
445
|
-
});
|
|
446
|
-
it('should remove [custom_schema]. prefix and brackets from SQL table names', () => {
|
|
447
|
-
// Arrange
|
|
448
|
-
const folderPath = '/test/tables';
|
|
449
|
-
const tableJson = {
|
|
450
|
-
name: '[custom_schema].[ComplexTableName]',
|
|
451
|
-
schema: {
|
|
452
|
-
items: {
|
|
453
|
-
properties: {},
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
};
|
|
457
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('table.json', false)]);
|
|
458
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(tableJson));
|
|
459
|
-
// Act
|
|
460
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
461
|
-
// Assert
|
|
462
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
463
|
-
const generatedContent = writeCall[1];
|
|
464
|
-
expect(generatedContent).toContain('complextablename');
|
|
465
|
-
});
|
|
466
|
-
it('should remove shared_ prefix from non-tabular names', () => {
|
|
467
|
-
// Arrange
|
|
468
|
-
const folderPath = '/test/shared';
|
|
469
|
-
const sharedJson = {
|
|
470
|
-
name: 'shared_commonservice',
|
|
471
|
-
schema: {
|
|
472
|
-
type: 'object',
|
|
473
|
-
},
|
|
474
|
-
};
|
|
475
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('service.json', false)]);
|
|
476
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(sharedJson));
|
|
477
|
-
// Act
|
|
478
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
479
|
-
// Assert
|
|
480
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
481
|
-
const generatedContent = writeCall[1];
|
|
482
|
-
expect(generatedContent).toContain('commonservice');
|
|
483
|
-
});
|
|
484
|
-
it('should use title property when available', () => {
|
|
485
|
-
// Arrange
|
|
486
|
-
const folderPath = '/test/tabular';
|
|
487
|
-
const tabularJson = {
|
|
488
|
-
title: 'UserManagement',
|
|
489
|
-
name: 'internal_name',
|
|
490
|
-
schema: {
|
|
491
|
-
type: 'object',
|
|
492
|
-
},
|
|
493
|
-
};
|
|
494
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('service.json', false)]);
|
|
495
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(tabularJson));
|
|
496
|
-
// Act
|
|
497
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
498
|
-
// Assert
|
|
499
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
500
|
-
const generatedContent = writeCall[1];
|
|
501
|
-
expect(generatedContent).toContain('usermanagement');
|
|
502
|
-
});
|
|
503
|
-
it('should fallback to filename when name property is missing', () => {
|
|
504
|
-
// Arrange
|
|
505
|
-
const folderPath = '/test/fallback';
|
|
506
|
-
const jsonWithoutName = {
|
|
507
|
-
schema: {
|
|
508
|
-
type: 'object',
|
|
509
|
-
},
|
|
510
|
-
};
|
|
511
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('FallbackService.Schema.json', false)]);
|
|
512
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(jsonWithoutName));
|
|
513
|
-
// Act
|
|
514
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
515
|
-
// Assert
|
|
516
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
517
|
-
const generatedContent = writeCall[1];
|
|
518
|
-
expect(generatedContent).toContain('fallbackservice');
|
|
519
|
-
});
|
|
520
|
-
});
|
|
521
|
-
describe('Merge functionality', () => {
|
|
522
|
-
it('should merge APIs when processing multiple files for same data source', () => {
|
|
523
|
-
// Arrange
|
|
524
|
-
const folderPath = '/test/merge';
|
|
525
|
-
const api1Json = {
|
|
526
|
-
name: 'shared_testservice',
|
|
527
|
-
type: 'Microsoft.PowerApps/apis',
|
|
528
|
-
properties: {
|
|
529
|
-
swagger: {
|
|
530
|
-
paths: {
|
|
531
|
-
'/api1': {
|
|
532
|
-
get: {
|
|
533
|
-
operationId: 'GetApi1',
|
|
534
|
-
responses: { '200': { description: 'Success' } },
|
|
535
|
-
},
|
|
536
|
-
},
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
},
|
|
540
|
-
};
|
|
541
|
-
const api2Json = {
|
|
542
|
-
name: 'shared_testservice',
|
|
543
|
-
type: 'Microsoft.PowerApps/apis',
|
|
544
|
-
properties: {
|
|
545
|
-
swagger: {
|
|
546
|
-
paths: {
|
|
547
|
-
'/api2': {
|
|
548
|
-
post: {
|
|
549
|
-
operationId: 'PostApi2',
|
|
550
|
-
responses: { '201': { description: 'Created' } },
|
|
551
|
-
},
|
|
552
|
-
},
|
|
553
|
-
},
|
|
554
|
-
},
|
|
555
|
-
},
|
|
556
|
-
};
|
|
557
|
-
mockedFs.readdirSync.mockReturnValue([
|
|
558
|
-
createMockDirEntry('api1.json', false),
|
|
559
|
-
createMockDirEntry('api2.json', false),
|
|
560
|
-
]);
|
|
561
|
-
mockedFs.readFileSync
|
|
562
|
-
.mockReturnValueOnce(JSON.stringify(api1Json))
|
|
563
|
-
.mockReturnValueOnce(JSON.stringify(api2Json));
|
|
564
|
-
// Act
|
|
565
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
566
|
-
// Assert
|
|
567
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
568
|
-
const generatedContent = writeCall[1];
|
|
569
|
-
expect(generatedContent).toContain('GetApi1');
|
|
570
|
-
expect(generatedContent).toContain('PostApi2');
|
|
571
|
-
expect(generatedContent).toContain('testservice');
|
|
572
|
-
});
|
|
573
|
-
it('should throw error for duplicate stored procedures', () => {
|
|
574
|
-
// Arrange
|
|
575
|
-
const folderPath = '/test/duplicate';
|
|
576
|
-
const procedureJson = {
|
|
577
|
-
name: '[dbo].[DuplicateProc]',
|
|
578
|
-
schema: {
|
|
579
|
-
procedureresultschema: { type: 'object' },
|
|
580
|
-
},
|
|
581
|
-
};
|
|
582
|
-
mockedFs.readdirSync.mockReturnValue([
|
|
583
|
-
createMockDirEntry('proc1.json', false),
|
|
584
|
-
createMockDirEntry('proc2.json', false),
|
|
585
|
-
]);
|
|
586
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(procedureJson));
|
|
587
|
-
// Act & Assert
|
|
588
|
-
// Note: The current implementation merges APIs instead of throwing an error
|
|
589
|
-
// This test verifies that duplicate stored procedures are handled gracefully
|
|
590
|
-
expect(() => processDataSourceInfo(folderPath, mockLogger)).not.toThrow();
|
|
591
|
-
});
|
|
592
|
-
});
|
|
593
|
-
describe('Response processing', () => {
|
|
594
|
-
it('should handle array responses correctly', () => {
|
|
595
|
-
// Arrange
|
|
596
|
-
const folderPath = '/test/responses';
|
|
597
|
-
const swaggerJson = {
|
|
598
|
-
type: 'Microsoft.PowerApps/apis',
|
|
599
|
-
properties: {
|
|
600
|
-
swagger: {
|
|
601
|
-
paths: {
|
|
602
|
-
'/array-endpoint': {
|
|
603
|
-
get: {
|
|
604
|
-
operationId: 'GetArray',
|
|
605
|
-
responses: {
|
|
606
|
-
'200': {
|
|
607
|
-
description: 'Success',
|
|
608
|
-
schema: {
|
|
609
|
-
type: 'array',
|
|
610
|
-
format: 'custom',
|
|
611
|
-
},
|
|
612
|
-
},
|
|
613
|
-
},
|
|
614
|
-
},
|
|
615
|
-
},
|
|
616
|
-
},
|
|
617
|
-
},
|
|
618
|
-
},
|
|
619
|
-
};
|
|
620
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('array-response.json', false)]);
|
|
621
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(swaggerJson));
|
|
622
|
-
// Act
|
|
623
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
624
|
-
// Assert
|
|
625
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
626
|
-
const generatedContent = writeCall[1];
|
|
627
|
-
expect(generatedContent).toContain('"type": "array"');
|
|
628
|
-
expect(generatedContent).toContain('"format": "custom"');
|
|
629
|
-
});
|
|
630
|
-
it('should handle void responses when no schema provided', () => {
|
|
631
|
-
// Arrange
|
|
632
|
-
const folderPath = '/test/responses';
|
|
633
|
-
const swaggerJson = {
|
|
634
|
-
type: 'Microsoft.PowerApps/apis',
|
|
635
|
-
properties: {
|
|
636
|
-
swagger: {
|
|
637
|
-
paths: {
|
|
638
|
-
'/void-endpoint': {
|
|
639
|
-
delete: {
|
|
640
|
-
operationId: 'DeleteItem',
|
|
641
|
-
responses: {
|
|
642
|
-
'204': {
|
|
643
|
-
description: 'No Content',
|
|
644
|
-
},
|
|
645
|
-
},
|
|
646
|
-
},
|
|
647
|
-
},
|
|
648
|
-
},
|
|
649
|
-
},
|
|
650
|
-
},
|
|
651
|
-
};
|
|
652
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('void-response.json', false)]);
|
|
653
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(swaggerJson));
|
|
654
|
-
// Act
|
|
655
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
656
|
-
// Assert
|
|
657
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
658
|
-
const generatedContent = writeCall[1];
|
|
659
|
-
expect(generatedContent).toContain('"type": "void"');
|
|
660
|
-
});
|
|
661
|
-
});
|
|
662
|
-
describe('Error handling', () => {
|
|
663
|
-
it('should throw descriptive error for invalid JSON structure', () => {
|
|
664
|
-
// Arrange
|
|
665
|
-
const folderPath = '/test/invalid';
|
|
666
|
-
const invalidJson = {
|
|
667
|
-
invalidStructure: true,
|
|
668
|
-
};
|
|
669
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('invalid.json', false)]);
|
|
670
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(invalidJson));
|
|
671
|
-
// Act & Assert
|
|
672
|
-
expect(() => processDataSourceInfo(folderPath, mockLogger)).toThrow('The JSON does not represent a valid data source');
|
|
673
|
-
});
|
|
674
|
-
it('should handle nested directory traversal', () => {
|
|
675
|
-
// Arrange
|
|
676
|
-
const folderPath = '/test/nested';
|
|
677
|
-
mockedFs.readdirSync
|
|
678
|
-
.mockReturnValueOnce([createMockDirEntry('subfolder', true)])
|
|
679
|
-
.mockReturnValueOnce([createMockDirEntry('nested.json', false)]);
|
|
680
|
-
const nestedJson = {
|
|
681
|
-
name: 'nested-service',
|
|
682
|
-
schema: { type: 'object' },
|
|
683
|
-
};
|
|
684
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(nestedJson));
|
|
685
|
-
// Act
|
|
686
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
687
|
-
// Assert
|
|
688
|
-
expect(mockedFs.readdirSync).toHaveBeenCalledTimes(2);
|
|
689
|
-
expect(mockedFs.readFileSync).toHaveBeenCalledWith('/test/nested/subfolder/nested.json', 'utf-8');
|
|
690
|
-
});
|
|
691
|
-
});
|
|
692
|
-
describe('Parameter sorting', () => {
|
|
693
|
-
it('should sort parameters with required first', () => {
|
|
694
|
-
// Arrange
|
|
695
|
-
const folderPath = '/test/sorting';
|
|
696
|
-
const swaggerJson = {
|
|
697
|
-
type: 'Microsoft.PowerApps/apis',
|
|
698
|
-
properties: {
|
|
699
|
-
swagger: {
|
|
700
|
-
paths: {
|
|
701
|
-
'/sorted-params': {
|
|
702
|
-
post: {
|
|
703
|
-
operationId: 'PostWithSortedParams',
|
|
704
|
-
parameters: [
|
|
705
|
-
{
|
|
706
|
-
name: 'optional1',
|
|
707
|
-
in: 'query',
|
|
708
|
-
required: false,
|
|
709
|
-
type: 'string',
|
|
710
|
-
},
|
|
711
|
-
{
|
|
712
|
-
name: 'required1',
|
|
713
|
-
in: 'body',
|
|
714
|
-
required: true,
|
|
715
|
-
type: 'object',
|
|
716
|
-
},
|
|
717
|
-
{
|
|
718
|
-
name: 'optional2',
|
|
719
|
-
in: 'header',
|
|
720
|
-
required: false,
|
|
721
|
-
type: 'string',
|
|
722
|
-
},
|
|
723
|
-
{
|
|
724
|
-
name: 'required2',
|
|
725
|
-
in: 'path',
|
|
726
|
-
required: true,
|
|
727
|
-
type: 'string',
|
|
728
|
-
},
|
|
729
|
-
],
|
|
730
|
-
responses: {
|
|
731
|
-
'200': { description: 'Success' },
|
|
732
|
-
},
|
|
733
|
-
},
|
|
734
|
-
},
|
|
735
|
-
},
|
|
736
|
-
},
|
|
737
|
-
},
|
|
738
|
-
};
|
|
739
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('sorted.json', false)]);
|
|
740
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(swaggerJson));
|
|
741
|
-
// Act
|
|
742
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
743
|
-
// Assert
|
|
744
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
745
|
-
const generatedContent = writeCall[1];
|
|
746
|
-
const parsedResult = JSON.parse(generatedContent.split('export const dataSourcesInfo = ')[1].replace(';', ''));
|
|
747
|
-
// Find the parameters array for the operation
|
|
748
|
-
const dataSource = Object.values(parsedResult)[0];
|
|
749
|
-
const operation = dataSource.apis.PostWithSortedParams;
|
|
750
|
-
const parameters = operation.parameters;
|
|
751
|
-
// Required parameters should come first
|
|
752
|
-
expect(parameters[0].required).toBe(true);
|
|
753
|
-
expect(parameters[1].required).toBe(true);
|
|
754
|
-
expect(parameters[2].required).toBe(false);
|
|
755
|
-
expect(parameters[3].required).toBe(false);
|
|
756
|
-
});
|
|
757
|
-
});
|
|
758
|
-
describe('Output generation', () => {
|
|
759
|
-
it('should generate properly formatted TypeScript output', () => {
|
|
760
|
-
// Arrange
|
|
761
|
-
const folderPath = '/test/output';
|
|
762
|
-
const simpleJson = {
|
|
763
|
-
name: 'test-service',
|
|
764
|
-
schema: { type: 'object' },
|
|
765
|
-
};
|
|
766
|
-
mockedFs.readdirSync.mockReturnValue([createMockDirEntry('simple.json', false)]);
|
|
767
|
-
mockedFs.readFileSync.mockReturnValue(JSON.stringify(simpleJson));
|
|
768
|
-
// Act
|
|
769
|
-
processDataSourceInfo(folderPath, mockLogger);
|
|
770
|
-
// Assert
|
|
771
|
-
const writeCall = mockedFs.writeFileSync.mock.calls[0];
|
|
772
|
-
const [filePath, content] = writeCall;
|
|
773
|
-
expect(filePath).toBe('/test/output/../appschemas/dataSourcesInfo.ts');
|
|
774
|
-
expect(content).toContain('/*!');
|
|
775
|
-
expect(content).toContain(' * Copyright (C) Microsoft Corporation. All rights reserved.');
|
|
776
|
-
expect(content).toContain(' * This file is auto-generated. Do not modify it manually.');
|
|
777
|
-
expect(content).toContain('export const dataSourcesInfo = ');
|
|
778
|
-
expect(content).toMatch(/;\s*$/); // Should end with semicolon
|
|
779
|
-
});
|
|
780
|
-
});
|
|
781
|
-
});
|
|
782
|
-
//# sourceMappingURL=dataSourceInfoProcessor.test.js.map
|