| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const fs = require("fs"); | 
					
						
							|  |  |  | const path = require("path"); | 
					
						
							|  |  |  | const glob = require("glob"); | 
					
						
							|  |  |  | const rootDir = path.resolve(__dirname, ".."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe("Schemas", () => { | 
					
						
							| 
									
										
										
										
											2017-11-19 04:03:45 +08:00
										 |  |  | 	const schemas = glob.sync("schemas/**/*.json", { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 		cwd: rootDir | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	schemas.forEach(filename => { | 
					
						
							|  |  |  | 		describe(filename, () => { | 
					
						
							|  |  |  | 			let content; | 
					
						
							|  |  |  | 			let fileContent; | 
					
						
							|  |  |  | 			let errorWhileParsing; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				fileContent = fs.readFileSync(path.resolve(rootDir, filename), "utf-8"); | 
					
						
							|  |  |  | 				content = JSON.parse(fileContent); | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 			} catch (e) { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 				errorWhileParsing = e; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			it("should be parse-able", () => { | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 				if (errorWhileParsing) throw errorWhileParsing; | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 			if (content) { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 				const arrayProperties = ["oneOf", "anyOf", "allOf"]; | 
					
						
							|  |  |  | 				const allowedProperties = [ | 
					
						
							|  |  |  | 					"definitions", | 
					
						
							|  |  |  | 					"$ref", | 
					
						
							| 
									
										
										
										
											2018-09-20 16:12:48 +08:00
										 |  |  | 					"$id", | 
					
						
							|  |  |  | 					"title", | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 					"items", | 
					
						
							|  |  |  | 					"properties", | 
					
						
							|  |  |  | 					"additionalProperties", | 
					
						
							|  |  |  | 					"type", | 
					
						
							|  |  |  | 					"oneOf", | 
					
						
							|  |  |  | 					"anyOf", | 
					
						
							|  |  |  | 					"absolutePath", | 
					
						
							|  |  |  | 					"description", | 
					
						
							|  |  |  | 					"enum", | 
					
						
							|  |  |  | 					"minLength", | 
					
						
							|  |  |  | 					"minimum", | 
					
						
							|  |  |  | 					"required", | 
					
						
							|  |  |  | 					"uniqueItems", | 
					
						
							|  |  |  | 					"minItems", | 
					
						
							|  |  |  | 					"minProperties", | 
					
						
							| 
									
										
										
										
											2018-09-18 21:17:44 +08:00
										 |  |  | 					"instanceof", | 
					
						
							|  |  |  | 					"tsType" | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 				]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				const validateProperty = property => { | 
					
						
							|  |  |  | 					it("should have description set", () => { | 
					
						
							| 
									
										
										
										
											2018-01-24 23:00:43 +08:00
										 |  |  | 						expect(typeof property.description).toBe("string"); | 
					
						
							|  |  |  | 						expect(property.description.length).toBeGreaterThan(1); | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				const walker = item => { | 
					
						
							|  |  |  | 					it("should only use allowed schema properties", () => { | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 						const otherProperties = Object.keys(item).filter( | 
					
						
							|  |  |  | 							p => allowedProperties.indexOf(p) < 0 | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 						if (otherProperties.length > 0) { | 
					
						
							|  |  |  | 							throw new Error( | 
					
						
							|  |  |  | 								`The properties ${otherProperties.join( | 
					
						
							|  |  |  | 									", " | 
					
						
							|  |  |  | 								)} are not allowed to use`
 | 
					
						
							|  |  |  | 							); | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 							// When allowing more properties make sure to add nice error messages for them in WebpackOptionsValidationError
 | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 14:39:15 +08:00
										 |  |  | 					if ("$ref" in item) { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 						it("should not have other properties next to $ref", () => { | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 							const otherProperties = Object.keys(item).filter( | 
					
						
							|  |  |  | 								p => p !== "$ref" | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 							if (otherProperties.length > 0) { | 
					
						
							|  |  |  | 								throw new Error( | 
					
						
							|  |  |  | 									`When using $ref not other properties are possible (${otherProperties.join( | 
					
						
							|  |  |  | 										", " | 
					
						
							|  |  |  | 									)})`
 | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 14:39:15 +08:00
										 |  |  | 					if ("instanceof" in item) { | 
					
						
							|  |  |  | 						it("should have tsType specified when using instanceof", () => { | 
					
						
							|  |  |  | 							if (!("tsType" in item)) { | 
					
						
							|  |  |  | 								throw new Error("When using instanceof, tsType is required"); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 17:00:44 +08:00
										 |  |  | 					if ("absolutePath" in item) { | 
					
						
							|  |  |  | 						it("should have type: 'string' specified when using absolutePath", () => { | 
					
						
							|  |  |  | 							if (item.type !== "string") { | 
					
						
							|  |  |  | 								throw new Error( | 
					
						
							|  |  |  | 									"When using absolutePath, type must be 'string'" | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if ("properties" in item || "additionalProperties" in item) { | 
					
						
							|  |  |  | 						it("should have type: 'object' specified when using properties or additionalProperties", () => { | 
					
						
							|  |  |  | 							if (item.type !== "object") { | 
					
						
							|  |  |  | 								throw new Error( | 
					
						
							|  |  |  | 									"When using properties or additionalProperties, type must be 'object'" | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 					arrayProperties.forEach(prop => { | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 						if (prop in item) { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 							describe(prop, () => { | 
					
						
							|  |  |  | 								item[prop].forEach(walker); | 
					
						
							|  |  |  | 							}); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 					if ("items" in item) { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 						describe("items", () => { | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 							if (Object.keys(item).join() !== "$ref") { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 								validateProperty(item.items); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							walker(item.items); | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 					if ("definitions" in item) { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 						Object.keys(item.definitions).forEach(name => { | 
					
						
							|  |  |  | 							describe(`#${name}`, () => { | 
					
						
							|  |  |  | 								walker(item.definitions[name]); | 
					
						
							|  |  |  | 							}); | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 					if ("properties" in item) { | 
					
						
							| 
									
										
										
										
											2018-02-26 10:27:40 +08:00
										 |  |  | 						it("should have additionalProperties set to some value when describing properties", () => { | 
					
						
							| 
									
										
										
										
											2018-04-11 04:52:22 +08:00
										 |  |  | 							expect(item.additionalProperties).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 						}); | 
					
						
							|  |  |  | 						Object.keys(item.properties).forEach(name => { | 
					
						
							|  |  |  | 							describe(`> '${name}'`, () => { | 
					
						
							|  |  |  | 								const property = item.properties[name]; | 
					
						
							|  |  |  | 								validateProperty(property); | 
					
						
							|  |  |  | 								walker(property); | 
					
						
							|  |  |  | 							}); | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-02-25 18:46:17 +08:00
										 |  |  | 					if (typeof item.additionalProperties === "object") { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | 						describe("properties", () => { | 
					
						
							|  |  |  | 							validateProperty(item.additionalProperties); | 
					
						
							|  |  |  | 							walker(item.additionalProperties); | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				walker(content); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2017-11-17 23:03:46 +08:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2017-11-16 15:59:22 +08:00
										 |  |  | }); |