From bcc47d1f411c3e1b1700110255844ff0aa8e443b Mon Sep 17 00:00:00 2001 From: Daan Verstraten Date: Thu, 6 Oct 2022 21:32:49 +0200 Subject: [PATCH] Fixing/item descriptors (#122) * Adding correct samples, but know to fail * Renamed * Updated validator --- .github/workflows/pull-request.yml | 2 +- source/general/item/descriptor.json | 24 ++--- .../data_bp/entities/behavior_tempt.json | 23 +++++ .../correct/data_bp/entities/equippable.json | 28 ++++++ test/src/Github.ts | 26 ++++++ test/src/Validator.test.ts | 93 ++++++++++++------- test/src/files/correct.test.ts | 46 +++++---- test/src/files/incorrect.test.ts | 44 ++++----- 8 files changed, 193 insertions(+), 93 deletions(-) create mode 100644 test/files/correct/data_bp/entities/behavior_tempt.json create mode 100644 test/files/correct/data_bp/entities/equippable.json create mode 100644 test/src/Github.ts diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 87a965bb..306ced75 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -1,7 +1,7 @@ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages -name: Unit Test +name: Pull Request on: push: diff --git a/source/general/item/descriptor.json b/source/general/item/descriptor.json index e3cd888b..810220e0 100644 --- a/source/general/item/descriptor.json +++ b/source/general/item/descriptor.json @@ -1,21 +1,16 @@ { "$id": "blockception.minecraft.item.descriptor", - "oneOf": [ - { - "$ref": "./identifier.json" - }, - { - "$ref": "#/definitions/object_item_descriptor" - }, + "anyOf": [ + { "$ref": "./identifier.json" }, + { "$ref": "#/definitions/object_item_descriptor" }, { "type": "object", "properties": { "item": { "oneOf": [ + { "type": "string", "$ref": "./identifier.json" }, { - "$ref": "./identifier.json" - }, - { + "type": "object", "$ref": "#/definitions/object_item_descriptor" } ] @@ -25,19 +20,26 @@ ], "definitions": { "object_item_descriptor": { + "title": "Item Descriptor", + "description": "An object that describes an item.", "type": "object", + "additionalProperties": false, "properties": { "tags": { + "type": "string", "$ref": "../../molang/string.json", "description": "[UNDOCUMENTED] A Molang expression ran against item or block to match.", + "$comment": "UNDOCUMENTED", "examples": ["query.any_tag('minecraft:is_tool')"] }, "item_tag": { "type": "string", "description": "[UNDOCUMENTED] A tag to lookup item or block by.", + "$comment": "UNDOCUMENTED", "examples": ["minecraft:is_tool"] } - } + }, + "examples": [{ "tags": "query.any_tag('minecraft:is_tool')" }, { "item_tag": "minecraft:is_tool" }] } } } diff --git a/test/files/correct/data_bp/entities/behavior_tempt.json b/test/files/correct/data_bp/entities/behavior_tempt.json new file mode 100644 index 00000000..d5554c21 --- /dev/null +++ b/test/files/correct/data_bp/entities/behavior_tempt.json @@ -0,0 +1,23 @@ +{ + "format_version": "1.13.0", + "minecraft:entity": { + "description": { + "identifier": "minecraft:sheep", + "is_spawnable": true, + "is_summonable": true, + "is_experimental": false + }, + "components": { + "minecraft:behavior.tempt": { + "priority": 4, + "speed_multiplier": 1.25, + "items": [ + "wheat", + { + "tags": "query.any_tag('minecraft:is_tool')" + } + ] + } + } + } +} diff --git a/test/files/correct/data_bp/entities/equippable.json b/test/files/correct/data_bp/entities/equippable.json new file mode 100644 index 00000000..6eac1864 --- /dev/null +++ b/test/files/correct/data_bp/entities/equippable.json @@ -0,0 +1,28 @@ +{ + "format_version": "1.13.0", + "minecraft:entity": { + "description": { + "identifier": "minecraft:sheep", + "is_spawnable": true, + "is_summonable": true, + "is_experimental": false + }, + "components": { + "minecraft:equippable": { + "slots": [ + { + "accepted_items": [ + { + "tags": "query.any_tag('minecraft:is_tool')" + } + ], + "item": { + "tags": "query.any_tag('minecraft:is_tool')" + }, + "slot": 0 + } + ] + } + } + } +} diff --git a/test/src/Github.ts b/test/src/Github.ts new file mode 100644 index 00000000..839d039d --- /dev/null +++ b/test/src/Github.ts @@ -0,0 +1,26 @@ +export interface ErrorAnnotation { + file?: string; + line?: number; + column?: number; + endLine?: number; + title?: string; +} + +export namespace Github { + export function createError(message: string, error: ErrorAnnotation = {}): void { + const data = Object.entries(error) + .filter(([key, value]) => value !== undefined) + .map(([key, value]) => `${key}=${value}`) + .join(","); + + console.log(`::error ${data}::${message}`); + } + + export function startGroup(title: string): void { + console.log(`::group::${title}`); + } + + export function endGroup(): void { + console.log(`::endgroup::`); + } +} diff --git a/test/src/Validator.test.ts b/test/src/Validator.test.ts index 70a92e71..e62c76f5 100644 --- a/test/src/Validator.test.ts +++ b/test/src/Validator.test.ts @@ -3,6 +3,7 @@ import { Files } from "./Utillity"; import * as fs from "fs"; import * as JSONC from "comment-json"; import { expect } from "chai"; +import { ErrorAnnotation, Github } from "./Github"; describe("Validate", function () { const folder = path.join(Files.TestFolder(), "..", "source"); @@ -12,31 +13,22 @@ describe("Validate", function () { files.forEach((filepath) => { const filename = filepath.slice(folder.length); - describe(filename, function () { + it(`Validating schema parts: ${filename}`, function () { let object: JsonSchema | undefined = undefined; let data: string; - it("Can read file", function () { - data = fs.readFileSync(filepath, "utf8"); - }); + data = fs.readFileSync(filepath, "utf8"); + object = JSONC.parse(data); + expect(object).to.not.be.undefined; + expect(object).to.not.be.null; - it("Can parse to json", function () { - object = JSONC.parse(data); - }); + if (!object) { + this.skip(); + return; + } - it("Not Undefined or null", function () { - expect(object).to.not.be.undefined; - expect(object).to.not.be.null; - }); - - it("Check refs", function () { - if (!object) { - this.skip(); - return; - } - - explore_refs(object, path.dirname(filepath)); - }); + const explorer = new Explorer(data, filepath); + explorer.explore_refs(object, path.dirname(filepath)); }); }); }); @@ -46,24 +38,61 @@ interface JsonSchema { [key: string]: any; } -function explore_refs(data: JsonSchema, folder: string): void { - if (data.$ref) { - const ref = data.$ref; +class Explorer { + text: string; + filepath: string; - if (!ref.startsWith("#")) { - const filepath = path.isAbsolute(ref) ? ref : path.join(folder, ref); + constructor(text: string, filepath: string) { + this.text = text; + this.filepath = filepath; + } - expect(fs.existsSync(filepath), `ref ${ref} exists`).to.be.true; + public explore_refs(data: JsonSchema, folder: string): void { + if (data.$ref) { + const ref = data.$ref; + + if (!ref.startsWith("#")) { + const filepath = path.isAbsolute(ref) ? ref : path.join(folder, ref); + + if (!fs.existsSync(filepath)) { + const anno = this.find(ref); + anno.title = "Ref not found"; + anno.file = this.filepath; + + Github.createError(`Ref not found: ${ref}`, anno); + expect.fail(`ref ${ref} does not exists`); + } + } + } + + for (const key in data) { + const element = data[key]; + + switch (typeof element) { + case "object": + this.explore_refs(element, folder); + break; + } } } - for (const key in data) { - const element = data[key]; + find(data: string): ErrorAnnotation { + const index = this.text.indexOf(data); + let lines = 1; + let lastindex = 0; - switch (typeof element) { - case "object": - explore_refs(element, folder); - break; + for (let i = lastindex; i < index; i++) { + const char = this.text[i]; + + if (char === "\n") { + lastindex = i; + lines++; + } } + + return { + line: lines, + column: index - lastindex, + }; } } diff --git a/test/src/files/correct.test.ts b/test/src/files/correct.test.ts index d3dd7826..c2ee5d90 100644 --- a/test/src/files/correct.test.ts +++ b/test/src/files/correct.test.ts @@ -1,4 +1,5 @@ import { expect } from "chai"; +import { Github } from "../Github"; import { Schema } from "../SchemaTester"; import { Files } from "../Utillity"; @@ -14,34 +15,29 @@ describe("test correct files", function () { .forEach((file) => { const testfolder = file.replace(folder + "/", ""); - describe(testfolder, function () { + it(`File should have a schema & validate correctly: ${testfolder}`, async function () { const result = validator.ValidateFile(file); const schemas = validator.ls.getMatchingSchemas(result.doc, result.jdoc); - it("validation", function () { - result.promise.then( - (succes) => { - expect(succes.length, "Expected no errors got: " + succes.length).to.equal(0); - succes.forEach((item) => console.log(item.message)); - }, - (fail) => { - expect.fail("Failed to validate"); - } - ); - - return result.promise; - }); - - it("schemas", function () { - return schemas.then( - (success) => { - expect(success.length, "Expected schemas to be returned").to.greaterThan(0); - }, - (fail) => { - expect.fail("failed on retrieving schemas"); - } - ); - }); + result.promise.then( + (succes) => { + expect(succes.length, "Expected no errors got: " + succes.length).to.equal(0); + succes.forEach((item) => console.log(item.message)); + }, + (fail) => { + Github.createError("Failed on validating", { file: file }); + expect.fail("Failed to validate"); + } + ); + schemas.then( + (success) => { + expect(success.length, "Expected schemas to be returned").to.greaterThan(0); + }, + (fail) => { + Github.createError("Failed on retrieving schemas", { file: file }); + expect.fail("failed on retrieving schemas"); + } + ); return Promise.all([result.promise, schemas]); }); diff --git a/test/src/files/incorrect.test.ts b/test/src/files/incorrect.test.ts index a74df48d..4faf6d42 100644 --- a/test/src/files/incorrect.test.ts +++ b/test/src/files/incorrect.test.ts @@ -1,4 +1,5 @@ import { expect } from "chai"; +import { Github } from "../Github"; import { Schema } from "../SchemaTester"; import { Files } from "../Utillity"; @@ -14,33 +15,28 @@ describe("test incorrect files", function () { .forEach((file) => { const testfolder = file.replace(folder + "/", ""); - describe(testfolder, function () { + it(`File should invalidate & have a schema: ${testfolder}`, async function () { const result = validator.ValidateFile(file); const schemas = validator.ls.getMatchingSchemas(result.doc, result.jdoc); - it("schemas", function () { - return schemas.then( - (success) => { - expect(success.length, "Expected schemas to be returned").to.greaterThan(0); - }, - (fail) => { - expect.fail("failed on retrieving schemas"); - } - ); - }); - - it("validation", function () { - result.promise.then( - (succes) => { - expect(succes.length, "Expected errors! but had none").to.greaterThan(0); - }, - (fail) => { - expect.fail("Failed to validate"); - } - ); - - return result.promise; - }); + result.promise.then( + (succes) => { + expect(succes.length, "Expected errors! but had none").to.greaterThan(0); + }, + (fail) => { + Github.createError("No errors where found", { file: file }); + expect.fail("Failed to validate"); + } + ); + schemas.then( + (success) => { + expect(success.length, "Expected schemas to be returned").to.greaterThan(0); + }, + (fail) => { + Github.createError("Found no schema", { file: file }); + expect.fail("failed on retrieving schemas"); + } + ); return Promise.all([schemas, result]); });