Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/test/prompts/newWorkspace.stest.ts
13388 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import assert from 'assert';
6
import { FileContentsGenerator } from '../../src/extension/intents/node/generateNewWorkspaceContent';
7
import { NewWorkspaceContentsPromptProps } from '../../src/extension/prompts/node/panel/newWorkspace/newWorkspaceContents';
8
import { CancellationToken } from '../../src/util/vs/base/common/cancellation';
9
import { IInstantiationService } from '../../src/util/vs/platform/instantiation/common/instantiation';
10
import { ssuite, stest } from '../base/stest';
11
12
interface IGenerateFileContentsScenario {
13
args: {
14
PROJECT_DESCRIPTION: string;
15
PROJECT_TREE_STRUCTURE: string;
16
PROJECT_SPECIFICATION: string;
17
FILEPATH: string;
18
};
19
validate?: (response: string) => void;
20
}
21
22
function generateFileContentsPromptTest(scenario: IGenerateFileContentsScenario, language: string) {
23
stest({ description: `File contents generation: ${scenario.args.FILEPATH} in ${scenario.args.PROJECT_DESCRIPTION}`, language }, async (testingServiceCollection) => {
24
const accessor = testingServiceCollection.createTestingAccessor();
25
const fileContentGenerator = accessor.get(IInstantiationService).createInstance(FileContentsGenerator);
26
const promptArgs: NewWorkspaceContentsPromptProps = {
27
query: scenario.args.PROJECT_DESCRIPTION,
28
fileTreeStr: scenario.args.PROJECT_TREE_STRUCTURE,
29
projectSpecification: scenario.args.PROJECT_SPECIFICATION,
30
filePath: scenario.args.FILEPATH,
31
history: [],
32
};
33
34
const result = await fileContentGenerator.generate(promptArgs, CancellationToken.None);
35
const trimmedResult = result.trim();
36
37
// Generated file contents should never be empty
38
assert.ok(trimmedResult.length > 0);
39
40
// Generated file contents should never start with backticks
41
assert.ok(!trimmedResult.startsWith('```'));
42
43
// The AI shouldn't refuse to generate file contents
44
assert.ok(!trimmedResult.startsWith('Sorry, I cannot generate file contents'));
45
46
// Perform additional scenario-specific validation if provided
47
scenario.validate?.(trimmedResult);
48
});
49
}
50
51
namespace TypeScript {
52
export const PROJECT_DESCRIPTION = 'Create a TypeScript Express app';
53
export const PROJECT_TREE_STRUCTURE = `
54
my-express-app
55
├── src
56
│ ├── app.ts
57
│ ├── controllers
58
│ │ └── index.ts
59
│ ├── routes
60
│ │ └── index.ts
61
│ └── types
62
│ └── index.ts
63
├── package.json
64
├── tsconfig.json
65
└── README.md`;
66
export const PROJECT_SPECIFICATION = `The project has the following files:
67
1. \`src/app.ts\`: This file is the entry point of the application. It creates an instance of the express app and sets up middleware and routes.
68
2. \`src/controllers/index.ts\`: This file exports a class \`IndexController\` which has a method \`getIndex\` that handles the root route of the application.
69
3. \`src/routes/index.ts\`: This file exports a function \`setRoutes\` which sets up the routes for the application. It uses the \`IndexController\` to handle the root route.
70
4. \`src/types/index.ts\`: This file exports interfaces \`Request\` and \`Response\` which extend the interfaces from the \`express\` library.
71
5. \`tsconfig.json\`: This file is the configuration file for TypeScript. It specifies the compiler options and the files to include in the compilation.
72
6. \`package.json\`: This file is the configuration file for npm. It lists the dependencies and scripts for the project.
73
7. \`README.md\`: This file contains the documentation for the project.`;
74
}
75
76
namespace PythonDjango {
77
export const PROJECT_DESCRIPTION = 'python Django backend that uses REST API to connect to Azure CosmosDB NoSQL';
78
export const PROJECT_TREE_STRUCTURE = `
79
my-django-cosmosdb-project
80
├── myapp
81
│ ├── migrations
82
│ ├── __init__.py
83
│ ├── admin.py
84
│ ├── apps.py
85
│ ├── models.py
86
│ ├── serializers.py
87
│ ├── tests.py
88
│ ├── urls.py
89
│ └── views.py
90
├── myproject
91
│ ├── __init__.py
92
│ ├── asgi.py
93
│ ├── settings.py
94
│ ├── urls.py
95
│ └── wsgi.py
96
├── requirements.txt
97
├── Dockerfile
98
├── .dockerignore
99
├── .gitignore
100
├── README.md`;
101
export const PROJECT_SPECIFICATION = `The project tree structure consists of the following files and directories:
102
103
- \`myapp/\`: This directory contains the Django app for the project.
104
- \`migrations/\`: This directory contains the database migration files.
105
- \`__init__.py\`: This file is an empty file that tells Python that this directory should be considered as a package.
106
- \`admin.py\`: This file contains the configuration for the Django admin interface.
107
- \`apps.py\`: This file contains the configuration for the app.
108
- \`models.py\`: This file contains the database models for the app.
109
- \`serializers.py\`: This file contains the serializers for the app.
110
- \`tests.py\`: This file contains the tests for the app.
111
- \`urls.py\`: This file contains the URL routing for the app.
112
- \`views.py\`: This file contains the views for the app.
113
- \`myproject/\`: This directory contains the Django project settings.
114
- \`__init__.py\`: This file is an empty file that tells Python that this directory should be considered as a package.
115
- \`asgi.py\`: This file contains the ASGI configuration for the project.
116
- \`settings.py\`: This file contains the project settings.
117
- \`urls.py\`: This file contains the URL routing for the project.
118
- \`wsgi.py\`: This file contains the WSGI configuration for the project.
119
- \`requirements.txt\`: This file contains the Python dependencies required for the project.
120
- \`Dockerfile\`: This file contains the instructions for building a Docker image for the project.
121
- \`.dockerignore\`: This file contains the files and directories that should be excluded from the Docker build context.
122
- \`.gitignore\`: This file contains the files and directories that should be excluded from version control.
123
- \`README.md\`: This file contains the project documentation.`;
124
}
125
126
namespace CPP {
127
export const PROJECT_DESCRIPTION = 'A nodejs native node module that has a fib function in C++ exported to TS using NAPI. Include a tsconfig.json. The fib function takes an integer N as its argument.';
128
export const PROJECT_TREE_STRUCTURE = `
129
my-node-module
130
├── src
131
│ ├── fibModule.cpp
132
│ ├── fibModule.h
133
│ └── index.ts
134
├── binding.gyp
135
├── package.json
136
├── tsconfig.json
137
└── README.md
138
`;
139
export const PROJECT_SPECIFICATION = `
140
The project has the following files:
141
142
\`src/fibModule.cpp\`: This file contains the C++ implementation of the Fibonacci function. It exports a function \`Fib\` that takes an integer N as its argument and returns the Nth Fibonacci number.
143
144
\`src/fibModule.h\`: This file contains the header for the Fibonacci function. It declares the \`Fib\` function.
145
146
\`src/index.ts\`: This file is the entry point of the module. It imports the \`Fib\` function from the C++ module using NAPI and exports it to be used in TypeScript.
147
148
\`binding.gyp\`: This file is used by node-gyp to build the native module. It specifies the source files and the dependencies for the build.
149
150
\`package.json\`: This file is the configuration file for npm. It lists the dependencies and scripts for the project. It also specifies the build command to use node-gyp to build the native module.
151
152
\`tsconfig.json\`: This file is the configuration file for TypeScript. It specifies the compiler options and the files to include in the compilation.
153
154
\`README.md\`: This file contains the documentation for the project. It explains how to use the module and the Fibonacci function.
155
Think step by step and give me just the file /my-node-module/src/fibModule.h within this project. The code should not contain bugs.
156
If the file is supposed to be empty, please respond with a code comment saying that this file is intentionally left blank.
157
Do not include comments in json files.
158
Do not use code blocks or backticks.
159
Do not include product names such as Visual Studio in the comments.`;
160
}
161
162
ssuite({ title: 'new', subtitle: 'prompt', location: 'panel' }, () => {
163
164
// #region TypeScript
165
166
generateFileContentsPromptTest({
167
args: {
168
PROJECT_DESCRIPTION: TypeScript.PROJECT_DESCRIPTION,
169
PROJECT_TREE_STRUCTURE: TypeScript.PROJECT_TREE_STRUCTURE,
170
PROJECT_SPECIFICATION: TypeScript.PROJECT_SPECIFICATION,
171
FILEPATH: 'README.md',
172
},
173
validate: (response: string) => {
174
assert.ok(response.startsWith('#'), `Generated README.md does not start with a #`);
175
}
176
}, 'typescript');
177
178
generateFileContentsPromptTest({
179
args: {
180
PROJECT_DESCRIPTION: TypeScript.PROJECT_DESCRIPTION,
181
PROJECT_TREE_STRUCTURE: TypeScript.PROJECT_TREE_STRUCTURE,
182
PROJECT_SPECIFICATION: TypeScript.PROJECT_SPECIFICATION,
183
FILEPATH: 'package.json',
184
},
185
validate: (response: string) => {
186
try {
187
JSON.parse(response);
188
} catch (ex) {
189
assert.fail(`Generated package.json is not valid JSON: ${JSON.stringify(ex)}`);
190
}
191
}
192
}, 'typescript');
193
194
generateFileContentsPromptTest({
195
args: {
196
PROJECT_DESCRIPTION: TypeScript.PROJECT_DESCRIPTION,
197
PROJECT_TREE_STRUCTURE: TypeScript.PROJECT_TREE_STRUCTURE,
198
PROJECT_SPECIFICATION: TypeScript.PROJECT_SPECIFICATION,
199
FILEPATH: 'src/app.ts',
200
}
201
}, 'typescript');
202
203
// #endregion
204
205
// #region Python
206
generateFileContentsPromptTest({
207
args: {
208
PROJECT_DESCRIPTION: PythonDjango.PROJECT_DESCRIPTION,
209
PROJECT_TREE_STRUCTURE: PythonDjango.PROJECT_TREE_STRUCTURE,
210
FILEPATH: 'myapp/__init__.py',
211
PROJECT_SPECIFICATION: PythonDjango.PROJECT_SPECIFICATION
212
},
213
validate: (response: string) => {
214
assert.ok(response.includes('# This file is intentionally left blank.'), 'Intentionally blank file does not contain the expected comment');
215
}
216
}, 'python');
217
218
// This test currently always fails because the response hits the content filter
219
generateFileContentsPromptTest({
220
args: {
221
PROJECT_DESCRIPTION: PythonDjango.PROJECT_DESCRIPTION,
222
PROJECT_TREE_STRUCTURE: PythonDjango.PROJECT_TREE_STRUCTURE,
223
FILEPATH: 'myapp/manage.py',
224
PROJECT_SPECIFICATION: PythonDjango.PROJECT_SPECIFICATION
225
}
226
}, 'python');
227
// #endregion
228
229
// #region CPP
230
generateFileContentsPromptTest({
231
args: {
232
PROJECT_DESCRIPTION: CPP.PROJECT_DESCRIPTION,
233
PROJECT_TREE_STRUCTURE: CPP.PROJECT_TREE_STRUCTURE,
234
FILEPATH: 'src/fibModule.h',
235
PROJECT_SPECIFICATION: CPP.PROJECT_SPECIFICATION
236
},
237
validate: (response: string) => {
238
assert.ok(!response.startsWith('++'), 'C++ file was not correctly parsed');
239
}
240
}, 'cpp');
241
242
generateFileContentsPromptTest({
243
args: {
244
PROJECT_DESCRIPTION: CPP.PROJECT_DESCRIPTION,
245
PROJECT_TREE_STRUCTURE: CPP.PROJECT_TREE_STRUCTURE,
246
FILEPATH: 'src/fibModule.cpp',
247
PROJECT_SPECIFICATION: CPP.PROJECT_SPECIFICATION
248
},
249
validate: (response: string) => {
250
assert.ok(!response.startsWith('++'), 'C++ file was not correctly parsed');
251
}
252
}, 'cpp');
253
// #endregion
254
});
255
256