Skip to content

Commit b001565

Browse files
committed
adding validation tests
1 parent 90fb693 commit b001565

9 files changed

+349
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
*.swp
2+
node_modules
3+
*~

.npmignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ajax/
2+
test/

.travis.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
language: node_js
2+
node_js:
3+
- 0.4
4+
- 0.6
5+
- 0.7

package.json

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"author": "Ryan Kirkman (http://ryankirkman.com)",
3+
"name": "cdnjs",
4+
"description": "Our goal is to operate this CDN in a peer reviewed fashion.",
5+
"version": "0.0.1",
6+
"homepage": "http://www.cdnjs.com/",
7+
"repository": {
8+
"type": "git",
9+
"url": "git://github.com/cdnjs/cdnjs.git"
10+
},
11+
"scripts": {
12+
"test": "node test/*-test.js"
13+
},
14+
"dependencies": {},
15+
"devDependencies": {
16+
"glob": "3.1.9",
17+
"jslint": "0.1.8",
18+
"vows": "0.6.2",
19+
"JSV": "4.0.1"
20+
},
21+
"optionalDependencies": {},
22+
"engines": {
23+
"node": "*"
24+
}
25+
}

test/schemata/README.markdown

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
The schemata against which a cdnjs `package.json` will be validated.
2+
3+
These schemata (may) have been copied from:
4+
5+
https://github.com/exavolt/onde/tree/master/samples/schemas
6+
7+
They need to be updated to be accurate as per the current specs.
8+
9+
All .json files in this directory will be run against all of the
10+
`package.json` files in the ajax/libs directory, though only one
11+
will have to be successful: satisfying multiple schema may not
12+
be possible!
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
"type": "object",
3+
"name": "CommonJS Package Descriptor File 1.0",
4+
"description": "Note that this is incomplete. See http://wiki.commonjs.org/wiki/Packages/1.0 for the complete spec.",
5+
"summaryProperties": ["name", "version"],
6+
"properties": {
7+
"name": {
8+
"type": "string",
9+
"required": true,
10+
"description": "The name of the package. This must be a unique, lowercase alpha-numeric name without spaces. It may include \".\" or \"_\" or \"-\" characters. It is otherwise opaque."
11+
},
12+
"description": {
13+
"type": "string",
14+
"required": true,
15+
"format": "multiline",
16+
"description": "A brief description of the package. By convention, the first sentence (up to the first \". \") should be usable as a package title in listings."
17+
},
18+
"version": {
19+
"type": "string",
20+
"required": true,
21+
"format": "semver",
22+
"description": "Version string conforming to the Semantic Versioning requirements (http://semver.org/)."
23+
},
24+
"keywords": {
25+
"type": "array",
26+
"required": true,
27+
"items": { "type": "string" },
28+
"description": "An Array of string keywords to assist users searching for the package in catalogs."
29+
},
30+
"maintainers": {
31+
"type": "array",
32+
"required": true,
33+
"items": {
34+
"type": "object",
35+
"name": "person",
36+
"properties": {
37+
"name": { "type": "string", "required": true },
38+
"email": { "type": "string" },
39+
"web": { "type": "string" }
40+
}
41+
},
42+
"description": "Array of maintainers of the package. Each maintainer is a hash which must have a \"name\" property and may optionally provide \"email\" and \"web\" properties."
43+
},
44+
"contributors": {
45+
"type": "array",
46+
"required": true,
47+
"items": [{ "type": "string", "name": "person-name" }, {
48+
"type": "object",
49+
"name": "person",
50+
"properties": {
51+
"name": { "type": "string", "required": true },
52+
"email": { "type": "string" },
53+
"web": { "type": "string" }
54+
}
55+
}],
56+
"description": "An Array of hashes each containing the details of a contributor. Format is the same as for author. By convention, the first contributor is the original author of the package."
57+
},
58+
"bugs": {
59+
"type": "object",
60+
"additionalProperties": "string",
61+
"required": true,
62+
"description": "URL for submitting bugs. Can be mailto or http."
63+
},
64+
"licenses": {
65+
"type": "array",
66+
"required": true,
67+
"items": {
68+
"type": "object",
69+
"properties": {
70+
"type": { "type": "string", "required": true },
71+
"url": { "type": "string" }
72+
}
73+
},
74+
"description": "Array of licenses under which the package is provided."
75+
},
76+
"repositories": {
77+
"required": true,
78+
"description": "Array of repositories where the package can be located.",
79+
"type": "array",
80+
"items": {
81+
"type": "object",
82+
"summaryProperties": ["type", "url"],
83+
"properties": {
84+
"type": { "type": "string", "required": true },
85+
"url": { "type": "string", "required": true },
86+
"path": { "type": "string", "description": "Specified to locate the package in the repository if it does not reside at the root." }
87+
}
88+
}
89+
},
90+
"dependencies": {
91+
"required": true,
92+
"description": "Prerequisite packages on which this package depends in order to install and run.",
93+
"type": "object",
94+
"additionalProperties": [
95+
"string",
96+
{
97+
"type": "object",
98+
"name": "depgroups",
99+
"additionalProperties": ["string", { "type": "array", "name": "verlist", "items": "string" }]
100+
}
101+
]
102+
}
103+
}
104+
}

test/schemata/jquery-package.json

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"type": "object",
3+
"name": "jQuery Plugins Site package.json",
4+
"description": "Package manifest file for jQuery plugins. https://github.com/jquery/plugins.jquery.com/blob/master/docs/package.md",
5+
"primaryProperty": "name",
6+
"properties": {
7+
"name": {
8+
"type": "string",
9+
"required": true,
10+
"description": "The most important things in your package.json are the name and version fields. The name and version together form an identifier that is assumed to be completely unique."
11+
},
12+
"version": {
13+
"type": "string",
14+
"required": true,
15+
"description": "Version number must be a valid semantic version number per semver.org."
16+
},
17+
"title": {
18+
"type": "string",
19+
"required": true,
20+
"description": "A nice complete and pretty title of your plugin. This will be used for the page title and top-level heading on your plugin's page. Include jQuery (if you want) and spaces and mixed case, unlike name."
21+
},
22+
"author": {
23+
"required": true,
24+
"type": "object",
25+
"name": "person",
26+
"properties": {
27+
"name": { "type": "string", "required": true },
28+
"email": { "type": "string" },
29+
"url": { "type": "string" }
30+
}
31+
},
32+
"licenses": {
33+
"type": "array",
34+
"required": true,
35+
"items": {
36+
"type": "object",
37+
"properties": {
38+
"type": { "type": "string", "required": true },
39+
"url": { "type": "string" }
40+
}
41+
}
42+
},
43+
"dependencies": {
44+
"type": "object",
45+
"required": true,
46+
"description": "Use package name as the property name and its version as the value. You must list at least one dependency, jquery (note that it's lower-case).",
47+
"additionalProperties": "string"
48+
},
49+
"description": {
50+
"type": "string",
51+
"format": "multiline"
52+
},
53+
"keywords": {
54+
"type": "array",
55+
"items": "string",
56+
"description": "This helps people discover your plugin as it's listed on the jQuery Plugins Site."
57+
},
58+
"homepage": {
59+
"type": "string",
60+
"format": "url",
61+
"description": "The URL to the plugin homepage."
62+
},
63+
"contributors": {
64+
"type": "array",
65+
"items": {
66+
"type": "object",
67+
"name": "person",
68+
"properties": {
69+
"name": { "type": "string", "required": true },
70+
"email": { "type": "string" },
71+
"url": { "type": "string" }
72+
}
73+
}
74+
},
75+
"files": {
76+
"description": "List of files that make up your plugin. This should be a file path relative to the root of your plugin folder.",
77+
"type": "array",
78+
"items": { "type": "string", "format": "url.path" }
79+
}
80+
}
81+
}

test/schemata/npm-package.json

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"type": "object",
3+
"name": "NPM package.json",
4+
"description": "Package manifest file for Node.JS modules. Note that this is incomplete. http://npmjs.org/doc/json.html",
5+
"properties": {
6+
"name": {
7+
"type": "string",
8+
"required": true,
9+
"description": "The name and version together form an identifier that is assumed to be completely unique."
10+
},
11+
"version": {
12+
"type": "string",
13+
"required": true,
14+
"description": "Version must be parseable by node-semver, which is bundled with npm as a dependency."
15+
},
16+
"description": {
17+
"type": "string",
18+
"format": "multiline"
19+
},
20+
"keywords": {
21+
"type": "array",
22+
"items": "string"
23+
},
24+
"homepage": {
25+
"type": "string",
26+
"format": "url"
27+
},
28+
"bugs": {
29+
"type": "string"
30+
},
31+
"dependencies": {
32+
"type": "object",
33+
"additionalProperties": "string"
34+
},
35+
"private": {
36+
"type": "boolean"
37+
}
38+
}
39+
}

test/valid-packages-test.js

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"use strict";
2+
3+
var assert = require("assert"),
4+
path = require("path"),
5+
fs = require("fs"),
6+
glob = require("glob"),
7+
vows = require("vows"),
8+
jsv = require("JSV").JSV.createEnvironment();
9+
10+
function parse(json_file, ignore_missing, ignore_parse_fail) {
11+
var content;
12+
13+
try {
14+
content = fs.readFileSync(json_file, 'utf8');
15+
} catch (err1) {
16+
if (!ignore_missing) {
17+
assert.ok(0, json_file + " doesn't exist!");
18+
}
19+
return null;
20+
}
21+
try {
22+
return JSON.parse(content);
23+
} catch (err2) {
24+
if (!ignore_parse_fail) {
25+
assert.ok(0, json_file + " failed to parse");
26+
}
27+
return null;
28+
}
29+
}
30+
31+
function pkg_name(json_file) {
32+
return json_file.split("/")[3];
33+
}
34+
35+
// load up those files
36+
var packages = glob.sync("./ajax/libs/*/").map(function (pkg) {
37+
return pkg + "package.json";
38+
}),
39+
schemata = glob.sync("./test/schemata/*.json").map(function (schema) {
40+
return jsv.createSchema(parse(schema));
41+
}),
42+
suite = vows.describe('Package structure');
43+
44+
packages.map(function (pkg) {
45+
var package_vows = {"topic": pkg},
46+
pname = pkg_name(pkg);
47+
package_vows[pname + " has package.json"] = function (pkg) {
48+
assert.ok(path.existsSync(pkg), pkg_name(pkg) + " missing!");
49+
};
50+
package_vows[pname + " package.json is well-formed"] = function (pkg) {
51+
assert.ok(parse(pkg, true),
52+
pkg_name(pkg) + " malformed!");
53+
};
54+
package_vows[pname + " package.json is valid"] = function (pkg) {
55+
var pkg_obj = parse(pkg, true, true),
56+
valid = false,
57+
errors;
58+
if (pkg_obj === null) {
59+
// we already know about the problem
60+
return;
61+
}
62+
errors = schemata.map(function (schema) {
63+
var schema_errors = schema.validate(pkg_obj).errors;
64+
if (!schema_errors.length) {
65+
valid = true;
66+
} else {
67+
return schema_errors;
68+
}
69+
return [];
70+
});
71+
assert.ok(valid,
72+
pkg_name(pkg) + " didn't parse as any known format");
73+
// + JSON.stringify(errors, null, "\t"));
74+
};
75+
suite.addBatch({pname: package_vows});
76+
});
77+
78+
suite.run();
79+

0 commit comments

Comments
 (0)