Skip to content

Commit daec8b6

Browse files
committed
Extract validation to its own file
1 parent 3df94b9 commit daec8b6

File tree

6 files changed

+99
-57
lines changed

6 files changed

+99
-57
lines changed

extensions/ql-vscode/package-lock.json

Lines changed: 7 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,7 @@
12991299
"@primer/react": "^35.0.0",
13001300
"@vscode/codicons": "^0.0.31",
13011301
"@vscode/webview-ui-toolkit": "^1.0.1",
1302+
"ajv": "^8.11.0",
13021303
"child-process-promise": "^2.2.1",
13031304
"chokidar": "^3.5.3",
13041305
"classnames": "~2.2.6",
@@ -1389,7 +1390,6 @@
13891390
"@typescript-eslint/eslint-plugin": "^4.26.0",
13901391
"@typescript-eslint/parser": "^4.26.0",
13911392
"@vscode/test-electron": "^2.2.0",
1392-
"ajv": "^8.11.0",
13931393
"ansi-colors": "^4.1.1",
13941394
"applicationinsights": "^2.3.5",
13951395
"babel-loader": "^8.2.5",
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { DbConfig } from './db-config';
2+
import Ajv from 'ajv';
3+
4+
export function validateDbConfig(dbConfig: DbConfig): string[] {
5+
const ajv = new Ajv({ allErrors: true });
6+
7+
const schema = {
8+
type: 'object',
9+
properties: {
10+
remote: {
11+
type: 'object',
12+
properties: {
13+
repositoryLists: {
14+
type: 'array',
15+
items: {
16+
type: 'object',
17+
properties: {
18+
name: {
19+
type: 'string'
20+
},
21+
repositories: {
22+
type: 'array',
23+
items: {
24+
type: 'string',
25+
pattern: '^[a-zA-Z0-9-_\\.]+/[a-zA-Z0-9-_\\.]+$'
26+
}
27+
}
28+
},
29+
required: ['name', 'repositories'],
30+
additionalProperties: false
31+
}
32+
},
33+
owners: {
34+
type: 'array',
35+
items: {
36+
type: 'string',
37+
pattern: '^[a-zA-Z0-9-_\\.]+$'
38+
}
39+
},
40+
repositories: {
41+
type: 'array',
42+
items: {
43+
type: 'string',
44+
pattern: '^[a-zA-Z0-9-_\\.]+/[a-zA-Z0-9-_\\.]+$'
45+
}
46+
}
47+
},
48+
required: ['repositoryLists', 'owners', 'repositories'],
49+
additionalProperties: false
50+
}
51+
},
52+
required: ['remote'],
53+
additionalProperties: false
54+
};
55+
56+
ajv.validate(schema, dbConfig);
57+
58+
if (ajv.errors) {
59+
return ajv.errors.map((error) => `${error.instancePath} ${error.message}`);
60+
}
61+
62+
return [];
63+
}

extensions/ql-vscode/test/pure-tests/databases/corruptedData/workspace-databases.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

extensions/ql-vscode/test/pure-tests/databases/db-config-store.test.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { expect } from 'chai';
66
describe('db config store', async () => {
77
const tempWorkspaceStoragePath = path.join(__dirname, 'test-workspace');
88
const testDataStoragePath = path.join(__dirname, 'data');
9-
const corruptedTestDataStoragePath = path.join(__dirname, 'corruptedData');
109

1110
beforeEach(async () => {
1211
await fs.ensureDir(tempWorkspaceStoragePath);
@@ -54,28 +53,4 @@ describe('db config store', async () => {
5453
const reRetrievedConfig = configStore.getConfig();
5554
expect(reRetrievedConfig.remote.repositoryLists).to.have.length(1);
5655
});
57-
58-
it('should return error when file is not valid', async () => {
59-
const configStore = new DbConfigStore(corruptedTestDataStoragePath);
60-
await configStore.initialize();
61-
62-
const validationOutput = configStore.validateConfig();
63-
expect(validationOutput).to.have.length(2);
64-
if (validationOutput) {
65-
expect(validationOutput[0]).to.deep.equal({
66-
'instancePath': '/remote',
67-
'keyword': 'required',
68-
'message': 'must have required property \'owners\'',
69-
'params': { 'missingProperty': 'owners' },
70-
'schemaPath': '#/properties/remote/required'
71-
});
72-
expect(validationOutput[1]).to.deep.equal({
73-
'instancePath': '/remote',
74-
'keyword': 'additionalProperties',
75-
'message': 'must NOT have additional properties',
76-
'params': { 'additionalProperty': 'somethingElse' },
77-
'schemaPath': '#/properties/remote/additionalProperties'
78-
});
79-
}
80-
});
8156
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { validateDbConfig } from '../../../src/databases/db-config-validation';
2+
import { DbConfig } from '../../../src/databases/db-config';
3+
4+
describe.only('db config validation', async () => {
5+
it('should return error when file is not valid', async () => {
6+
// We're intentionally bypassing the type check because we'd
7+
// like to make sure validation errors are highlighted.
8+
const dbConfig = {
9+
'remote': {
10+
'repositoryLists': [
11+
{
12+
'name': 'repoList1',
13+
'repositories': ['foo/bar', 'foo/baz']
14+
}
15+
],
16+
'repositories': ['owner/repo1', 'owner/repo2', 'owner/repo3'],
17+
'somethingElse': 'bar'
18+
}
19+
} as any as DbConfig;
20+
21+
const validationOutput = validateDbConfig(dbConfig);
22+
23+
expect(validationOutput).to.have.length(2);
24+
25+
expect(validationOutput[0]).to.deep.equal('/remote must have required property \'owners\'');
26+
expect(validationOutput[1]).to.deep.equal('/remote must NOT have additional properties');
27+
});
28+
});

0 commit comments

Comments
 (0)