From 823df84924cd3253c0edc261ca82ad8ec811b1fc Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Tue, 13 Jan 2015 09:44:13 -0800 Subject: [PATCH] Revert local storage change & refactor parser V1 * Revert the local storage change as it ties model objects to global state and makes testing impossible. It will be necessary to redo that feature differently * Refactor the parser versions to move V1 into its own set of files --- src/scripts/models/crafting_plan.coffee | 6 - src/scripts/models/mod_version.coffee | 8 - src/scripts/models/mod_version_parser.coffee | 217 +---------------- .../models/mod_version_parsers/v1.coffee | 228 ++++++++++++++++++ test/crafting_plan.test.coffee | 2 +- test/mod_pack.test.coffee | 6 +- test/mod_version.test.coffee | 2 +- test/mod_version_parser.test.coffee | 162 ------------- test/mod_version_parsers/v1.test.coffee | 160 ++++++++++++ test/test.coffee | 3 +- 10 files changed, 397 insertions(+), 397 deletions(-) create mode 100644 src/scripts/models/mod_version_parsers/v1.coffee delete mode 100644 test/mod_version_parser.test.coffee create mode 100644 test/mod_version_parsers/v1.test.coffee diff --git a/src/scripts/models/crafting_plan.coffee b/src/scripts/models/crafting_plan.coffee index bde0df73a..67864993b 100644 --- a/src/scripts/models/crafting_plan.coffee +++ b/src/scripts/models/crafting_plan.coffee @@ -13,8 +13,6 @@ Inventory = require './inventory' module.exports = class CraftingPlan extends BaseModel constructor: (attributes={}, options={})-> - options.storage ?= window.localStorage - if not attributes.modPack then throw new Error 'modPack is required' attributes.includingTools ?= false super attributes, options @@ -29,10 +27,6 @@ module.exports = class CraftingPlan extends BaseModel @want.on 'change', => @craft() @modPack.on 'change', => @craft() - value = options.storage.getItem('includingTools') - if value? then @includingTools = value is 'true' - @on 'change:includingTools', => @onIncludingToolsChanged() - @clear() # Public Methods ############################################################################### diff --git a/src/scripts/models/mod_version.coffee b/src/scripts/models/mod_version.coffee index 642443123..5e6d2eeba 100644 --- a/src/scripts/models/mod_version.coffee +++ b/src/scripts/models/mod_version.coffee @@ -25,14 +25,6 @@ module.exports = class ModVersion extends BaseModel attributes.slug ?= _.slugify attributes.name super attributes, options - enabled = options.storage.getItem("#{@slug}.enabled") - if enabled? - logger.debug "loading #{@slug}.enabled as #{@enabled}" - @enabled = enabled is 'true' - @on 'change:enabled', => - logger.debug "saving #{@slug}.enabled as #{@enabled}" - options.storage.setItem "#{@slug}.enabled", "#{@enabled}" - # Public Methods ############################################################################### addItem: (item)-> diff --git a/src/scripts/models/mod_version_parser.coffee b/src/scripts/models/mod_version_parser.coffee index 0e350524f..7f4755edd 100644 --- a/src/scripts/models/mod_version_parser.coffee +++ b/src/scripts/models/mod_version_parser.coffee @@ -5,11 +5,8 @@ Copyright (c) 2014-2015 by Redwood Labs All rights reserved. ### -Item = require './item' -Logger = require '../logger' -ModVersion = require './mod_version' -Recipe = require './recipe' -Stack = require './stack' +Logger = require '../logger' +V1 = require './mod_version_parsers/v1' ######################################################################################################################## @@ -42,213 +39,3 @@ module.exports = class ModVersionParser if not parser? then throw new Error "version #{dataVersion} is not supported" return parser.unparse modVersion - -######################################################################################################################## - -module.exports.V1 = class V1 - - constructor: -> - @_errorLocation = 'the header information' - - parse: (data)-> - return @_parseModVersion data - - unparse: (modVersion)-> - @modVersion = modVersion - text = @_unparseModVersion modVersion - @modVersion = null - return text - - # Private Methods ############################################################################## - - _findOrCreateItem: (name)-> - item = @modVersion.findItemByName name - if not item? - item = new Item name:name - @modVersion.addItem item - @modVersion.registerSlug item.slug, item.name - return item - - _parseModVersion: (data)-> - if not data? then throw new Error 'mod description data is missing' - if not data.name? then throw new Error 'name is required' - if not data.version? then throw new Error 'version is required' - if not _.isArray(data.recipes) then throw new Error 'recipes must be an array' - - @modVersion = modVersion = new ModVersion name:data.name, version:data.version - modVersion.description = data.description or '' - - @_parseRawMaterials data.raw_materials - - for index in [0...data.recipes.length] - @_errorLocation = "recipe #{index + 1}" - recipeData = data.recipes[index] - recipe = @_parseRecipe recipeData - recipe._originalIndex = index - - @modVersion = null - return modVersion - - _parseRawMaterials: (data)-> - return unless data? and data.length > 0 - - results = [] - for name in data - item = @_findOrCreateItem name - item.isGatherable = true - results.push item - - _parseRecipe: (data)-> - if not data? then throw new Error "recipe data is missing for #{@_errorLocation}" - if not data.output? then throw new Error "#{@_errorLocation} is missing output" - - data.output = if _.isArray(data.output) then data.output else [data.output] - names = (e for e in _.flatten(data.output) when _.isString(e)) - if names.length is 0 then throw new Error "#{@_errorLocation} has an empty output list" - - item = @_findOrCreateItem names[0] - @_errorLocation = "recipe for #{item.name}" - - if not data.input? then throw new Error "#{@_errorLocation} is missing input" - data.tools ?= [] - - attributes = - item: item, - output: @_parseStackList(data.output, field:'output', canBeEmpty:false) - input: @_parseStackList(data.input, field:'input', canBeEmpty:true) - tools: @_parseStackList(data.tools, field:'tools', canBeEmpty:true) - attributes.pattern = data.pattern if data.pattern? - - recipe = new Recipe attributes - item.addRecipe recipe - return recipe - - _parseStack: (data, options={})-> - errorBase = "#{options.field} element #{options.index} for #{@_errorLocation}" - if not data? then throw new Error "#{errorBase} is missing" - - if _.isString(data) then data = [1, data] - if not _.isArray(data) then throw new Error "#{errorBase} must be an array" - - if data.length is 1 then data.unshift 1 - if data.length isnt 2 then throw new Error "#{errorBase} must have at least one element" - if not _.isNumber(data[0]) then throw new Error "#{errorBase} must start with a number" - - name = data[1] - slug = _.slugify name - @modVersion.registerSlug slug, name - - return new Stack itemSlug:slug, quantity:data[0] - - _parseStackList: (data, options={})-> - if not data? then throw new Error "#{@_errorLocation} must have an #{options.field} field" - - if not _.isArray(data) then data = [data] - if data.length is 0 and not options.canBeEmpty - throw new Error "#{options.field} for #{@_errorLocation} cannot be empty" - - result = [] - for index in [0...data.length] - stackData = data[index] - result.push @_parseStack stackData, field:options.field, index:index - - return result - - # Un-parsing Methods ########################################################################### - - _unparseModVersion: (modVersion)-> - result = [] - result.push '{\n' - result.push ' "dataVersion": 1,\n' - result.push ' "name": "' + modVersion.name + '",\n' - result.push ' "version": "' + modVersion.version + '",\n' - if modVersion.description.length > 0 - result.push ' "description": "' + modVersion.description + '",\n' - - rawMaterials = (item.name for slug, item of modVersion.items when item.isGatherable) - rawMaterials.sort() - if rawMaterials.length > 0 - result.push ' "raw_materials": [\n' - firstItem = true - for material in rawMaterials - if not firstItem then result.push ',\n' - result.push ' "' + material + '"' - firstItem = false - result.push '\n ],\n' - - result.push ' "recipes": [\n' - - items = (item for slug, item of modVersion.items when item.isCraftable) - items.sort (a, b)-> a.compareTo b - - firstItem = true - for item in items - for recipe in item.recipes - result.push if firstItem then ' {\n' else ' }, {\n' - @_unparseRecipe recipe, result - firstItem = false - result.push ' }\n' - - result.push ' ]\n' - result.push '}' - - return result.join '' - - _unparseRecipe: (recipe, result=[])-> - result.push ' "output": ' - @_unparseStackList recipe.output, result, sort:false - - if recipe.input.length > 0 - result.push ',\n' - result.push ' "input": ' - @_unparseStackList recipe.input, result - - if recipe.pattern? - result.push ',\n' - result.push ' "pattern": "' - result.push recipe.pattern - result.push '"' - - if recipe.tools.length > 0 - result.push ',\n' - result.push ' "tools": ' - @_unparseStackList recipe.tools, result - - result.push '\n' - return result - - _unparseStackList: (stackList, result, options={})-> - options.sort ?= true - - if stackList.length is 0 - result.push '[]' - else if stackList.length is 1 - stack = stackList[0] - if stack.quantity is 1 - result.push '"' + @modVersion.findName(stack.itemSlug) + '"' - else - result.push '[[' + stack.quantity + ', "' + @modVersion.findName(stack.itemSlug) + '"]]' - else - result.push '[' - - stacks = stackList.slice() - if options.sort - stacks.sort (a, b)-> - if a.quantity isnt b.quantity - return if a.quantity > b.quantity then -1 else +1 - if a.itemSlug isnt b.itemSlug - return if a.itemSlug < b.itemSlug then -1 else +1 - return 0 - - firstItem = true - for stack in stacks - result.push ', ' if not firstItem - if stack.quantity is 1 - result.push '"' + @modVersion.findName(stack.itemSlug) + '"' - else - result.push '[' + stack.quantity + ', "' + @modVersion.findName(stack.itemSlug) + '"]' - firstItem = false - - result.push ']' - - return result diff --git a/src/scripts/models/mod_version_parsers/v1.coffee b/src/scripts/models/mod_version_parsers/v1.coffee new file mode 100644 index 000000000..dc68d1562 --- /dev/null +++ b/src/scripts/models/mod_version_parsers/v1.coffee @@ -0,0 +1,228 @@ +### +Crafting Guide - mod_version_parsers/v1.coffee + +Copyright (c) 2014-2015 by Redwood Labs +All rights reserved. +### + +Item = require '../item' +ModVersion = require '../mod_version' +Recipe = require '../recipe' +Stack = require '../stack' + +######################################################################################################################## + +module.exports = class V1 + + constructor: -> + @_errorLocation = 'the header information' + + parse: (data)-> + return @_parseModVersion data + + unparse: (modVersion)-> + @modVersion = modVersion + text = @_unparseModVersion modVersion + @modVersion = null + return text + + # Private Methods ############################################################################## + + _findOrCreateItem: (name)-> + item = @modVersion.findItemByName name + if not item? + item = new Item name:name + @modVersion.addItem item + @modVersion.registerSlug item.slug, item.name + return item + + _parseModVersion: (data)-> + if not data? then throw new Error 'mod description data is missing' + if not data.name? then throw new Error 'name is required' + if not data.version? then throw new Error 'version is required' + if not _.isArray(data.recipes) then throw new Error 'recipes must be an array' + + @modVersion = modVersion = new ModVersion name:data.name, version:data.version + modVersion.description = data.description or '' + + @_parseRawMaterials data.raw_materials + + for index in [0...data.recipes.length] + @_errorLocation = "recipe #{index + 1}" + recipeData = data.recipes[index] + recipe = @_parseRecipe recipeData + recipe._originalIndex = index + + @modVersion = null + return modVersion + + _parseRawMaterials: (data)-> + return unless data? and data.length > 0 + + results = [] + for name in data + item = @_findOrCreateItem name + item.isGatherable = true + results.push item + + _parseRecipe: (data)-> + if not data? then throw new Error "recipe data is missing for #{@_errorLocation}" + if not data.output? then throw new Error "#{@_errorLocation} is missing output" + + data.output = if _.isArray(data.output) then data.output else [data.output] + names = (e for e in _.flatten(data.output) when _.isString(e)) + if names.length is 0 then throw new Error "#{@_errorLocation} has an empty output list" + + item = @_findOrCreateItem names[0] + @_errorLocation = "recipe for #{item.name}" + + if not data.input? then throw new Error "#{@_errorLocation} is missing input" + data.tools ?= [] + + attributes = + item: item, + output: @_parseStackList(data.output, field:'output', canBeEmpty:false) + input: @_parseStackList(data.input, field:'input', canBeEmpty:true) + tools: @_parseStackList(data.tools, field:'tools', canBeEmpty:true) + attributes.pattern = data.pattern if data.pattern? + + recipe = new Recipe attributes + item.addRecipe recipe + return recipe + + _parseStack: (data, options={})-> + errorBase = "#{options.field} element #{options.index} for #{@_errorLocation}" + if not data? then throw new Error "#{errorBase} is missing" + + if _.isString(data) then data = [1, data] + if not _.isArray(data) then throw new Error "#{errorBase} must be an array" + + if data.length is 1 then data.unshift 1 + if data.length isnt 2 then throw new Error "#{errorBase} must have at least one element" + if not _.isNumber(data[0]) then throw new Error "#{errorBase} must start with a number" + + name = data[1] + slug = _.slugify name + @modVersion.registerSlug slug, name + + return new Stack itemSlug:slug, quantity:data[0] + + _parseStackList: (data, options={})-> + if not data? then throw new Error "#{@_errorLocation} must have an #{options.field} field" + + if not _.isArray(data) then data = [data] + if data.length is 0 and not options.canBeEmpty + throw new Error "#{options.field} for #{@_errorLocation} cannot be empty" + + result = [] + for index in [0...data.length] + stackData = data[index] + result.push @_parseStack stackData, field:options.field, index:index + + return result + + # Un-parsing Methods ########################################################################### + + _unparseModVersion: (modVersion)-> + result = [] + result.push '{\n' + result.push ' "dataVersion": 1,\n' + result.push ' "name": "' + modVersion.name + '",\n' + result.push ' "version": "' + modVersion.version + '",\n' + if modVersion.description.length > 0 + result.push ' "description": "' + modVersion.description + '",\n' + + rawMaterials = (item.name for slug, item of modVersion.items when item.isGatherable) + rawMaterials.sort() + if rawMaterials.length > 0 + result.push ' "raw_materials": [\n' + firstItem = true + for material in rawMaterials + if not firstItem then result.push ',\n' + result.push ' "' + material + '"' + firstItem = false + result.push '\n ],\n' + + result.push ' "recipes": [\n' + + items = (item for slug, item of modVersion.items when item.isCraftable) + items.sort (a, b)-> a.compareTo b + + firstItem = true + for item in items + for recipe in item.recipes + result.push if firstItem then ' {\n' else ' }, {\n' + @_unparseRecipe recipe, result + firstItem = false + result.push ' }\n' + + result.push ' ]\n' + result.push '}' + + return result.join '' + + _unparseRecipe: (recipe, result=[])-> + result.push ' "output": ' + @_unparseStackList recipe.output, result, sort:false + + if recipe.input.length > 0 + result.push ',\n' + result.push ' "input": ' + @_unparseStackList recipe.input, result + + if recipe.pattern? + result.push ',\n' + result.push ' "pattern": "' + result.push recipe.pattern + result.push '"' + + if recipe.tools.length > 0 + result.push ',\n' + result.push ' "tools": ' + @_unparseStackList recipe.tools, result + + result.push '\n' + return result + + _unparseStackList: (stackList, result, options={})-> + options.sort ?= true + + if stackList.length is 0 + result.push '[]' + else if stackList.length is 1 + stack = stackList[0] + if stack.quantity is 1 + result.push '"' + @modVersion.findName(stack.itemSlug) + '"' + else + result.push '[[' + stack.quantity + ', "' + @modVersion.findName(stack.itemSlug) + '"]]' + else + result.push '[' + + stacks = stackList.slice() + if options.sort + stacks.sort (a, b)-> + if a.quantity isnt b.quantity + return if a.quantity > b.quantity then -1 else +1 + if a.itemSlug isnt b.itemSlug + return if a.itemSlug < b.itemSlug then -1 else +1 + return 0 + + firstItem = true + for stack in stacks + result.push ', ' if not firstItem + if stack.quantity is 1 + result.push '"' + @modVersion.findName(stack.itemSlug) + '"' + else + result.push '[' + stack.quantity + ', "' + @modVersion.findName(stack.itemSlug) + '"]' + firstItem = false + + result.push ']' + + return result + +######################################################################################################################## + +module.exports.V2 = class V2 extends V1 + + constructor: -> + @_errorLocation = 'the header information' diff --git a/test/crafting_plan.test.coffee b/test/crafting_plan.test.coffee index 1d350a3c0..d25bf773e 100644 --- a/test/crafting_plan.test.coffee +++ b/test/crafting_plan.test.coffee @@ -32,7 +32,7 @@ describe 'CraftingPlan', -> ] } - plan = new CraftingPlan modPack:modPack + plan = new CraftingPlan modPack:modPack, includingTools:false describe 'craft', -> diff --git a/test/mod_pack.test.coffee b/test/mod_pack.test.coffee index 6bc7aa9d8..5eba34253 100644 --- a/test/mod_pack.test.coffee +++ b/test/mod_pack.test.coffee @@ -18,16 +18,16 @@ buildcraft = industrialCraft = minecraft = modPack = null describe 'ModPack', -> beforeEach -> - minecraft = new ModVersion name:'Minecraft', version:'1.7.10' + minecraft = new ModVersion name:'Minecraft', version:'1.7.10', enabled:true minecraft.addItem new Item name:'Wool' minecraft.addItem new Item name:'Bed', recipes:[''] minecraft.registerSlug 'iron_chestplate', 'Iron Chestplate' - buildcraft = new ModVersion name:'Buildcraft', version:'4.0' + buildcraft = new ModVersion name:'Buildcraft', version:'4.0', enabled:false buildcraft.addItem new Item name:'Stone Gear', recipes:[''] buildcraft.addItem new Item name:'Bed', recipes:[''] - industrialCraft = new ModVersion name:'Industrial Craft', version:'2.0' + industrialCraft = new ModVersion name:'Industrial Craft', version:'2.0', enabled:false industrialCraft.addItem new Item name:'Resin' industrialCraft.addItem new Item name:'Rubber', recipes:[''] diff --git a/test/mod_version.test.coffee b/test/mod_version.test.coffee index 838a4466a..392fa0853 100644 --- a/test/mod_version.test.coffee +++ b/test/mod_version.test.coffee @@ -29,7 +29,7 @@ describe 'ModVersion', -> it 'supplies default values', -> modVersion.description.should.equal '' modVersion.items.should.eql {} - modVersion.enabled.should.be.false + modVersion.enabled.should.be.true describe 'addItem', -> diff --git a/test/mod_version_parser.test.coffee b/test/mod_version_parser.test.coffee deleted file mode 100644 index 9b0983961..000000000 --- a/test/mod_version_parser.test.coffee +++ /dev/null @@ -1,162 +0,0 @@ -### -Crafting Guide - v1.test.coffee - -Copyright (c) 2014-2015 by Redwood Labs -All rights reserved. -### - -Item = require '../src/scripts/models/item' -ModVersion = require '../src/scripts/models/mod_version' -ModVersionParser = require '../src/scripts/models/mod_version_parser' - -######################################################################################################################## - -modVersion = parser = null - -######################################################################################################################## - -describe 'ModVersionParser', -> - - describe "V1", -> - - beforeEach -> - parser = new ModVersionParser.V1 - modVersion = parser.modVersion = new ModVersion name:'Test', version:'0.0' - - describe '_parseModVersion', -> - - it 'requires a mod_name', -> - data = version:'1.0', items:[] - expect(-> parser._parseModVersion data).to.throw Error, 'name is required' - - it 'requires a mod_version', -> - data = name:'Empty', items:[] - expect(-> parser._parseModVersion data).to.throw Error, 'version is required' - - it 'can parse an empty modVersion', -> - data = - name: 'Empty' - version: '1.0' - recipes: [] - modVersion = parser._parseModVersion data - modVersion.name.should.equal 'Empty' - modVersion.version.should.equal '1.0' - - it 'can parse a non-empty mod version', -> - data = - name: 'Minecraft' - version: '1.7.10' - recipes: [ - { input:'Sugar Cane', output:'Sugar' } - { input:[[3, 'Wool'], [3, 'Planks']], tools:'Crafting Table', output:'Bed' } - ] - modVersion = parser._parseModVersion data - modVersion.name.should.equal 'Minecraft' - modVersion.version.should.equal '1.7.10' - slugs = (slug for slug, item of modVersion.items).sort() - slugs.should.eql ['bed', 'sugar'] - - describe '_parseRawMaterials', -> - - it 'skips the section when missing', -> - parser._parseRawMaterials null - _.keys(modVersion._items).length.should.equal 0 - - it 'skips the section when empty', -> - parser._parseRawMaterials [] - _.keys(modVersion._items).length.should.equal 0 - - it 'adds items marked as gatherable', -> - parser._parseRawMaterials ['Wool'] - modVersion.items['wool'].isGatherable.should.be.true - - it 'marks an existing item as gatherable', -> - modVersion.addItem new Item name:'Wool' - modVersion.items['wool'].isGatherable.should.be.false - parser._parseRawMaterials ['Wool'] - modVersion.items['wool'].isGatherable.should.be.true - - it 'registers the names of the items', -> - parser._parseRawMaterials ['Wool'] - modVersion.names['wool'].should.equal 'Wool' - - describe '_parseRecipe', -> - - it 'requires output to be defined', -> - parser._errorLocation = 'boat' - test = -> parser._parseRecipe {input:'wool'} - expect(test).to.throw Error, 'boat is missing output' - - it 'requires input to be defined', -> - test = -> parser._parseRecipe {output:'wool'} - expect(test).to.throw Error, 'recipe for wool is missing input' - - it 'can parse a regular recipe', -> - data = - output: 'bed' - input: [[3, 'planks'], [3, 'wool']] - tools: 'crafting table' - recipe = parser._parseRecipe data - (stack.itemSlug for stack in recipe.output).should.eql ['bed'] - (stack.itemSlug for stack in recipe.input).sort().should.eql ['planks', 'wool'] - (stack.itemSlug for stack in recipe.tools).should.eql ['crafting_table'] - - it 'can parse a recipe without tools', -> - recipe = parser._parseRecipe {output:'sugar', input:'sugar cane'} - (stack.itemSlug for stack in recipe.output).should.eql ['sugar'] - (stack.itemSlug for stack in recipe.input).sort().should.eql ['sugar_cane'] - (stack.itemSlug for stack in recipe.tools).should.eql [] - - it 'registers all names', -> - data = - output: 'Bed' - input: [[3, 'Oak Wood Planks'], [3, 'Wool']] - tools: 'Crafting Table' - parser._parseRecipe data - _.keys(modVersion.names).sort().should.eql ['bed', 'crafting_table', 'oak_wood_planks', 'wool'] - - describe '_parseStack', -> - - it 'requires the array to have at least one element', -> - parser._errorLocation = 'boat' - options = index:1, field:'output' - expect(-> parser._parseStack([], options)).to.throw Error, - "output element 1 for boat must have at least one element" - - it 'can fill in a missing number', -> - stack = parser._parseStack 'boat' - stack.itemSlug.should.equal 'boat' - stack.quantity.should.equal 1 - - stack2 = parser._parseStack ['boat'] - stack2.itemSlug.should.equal 'boat' - stack2.quantity.should.equal 1 - - it 'requires the data to start with a number', -> - parser._errorLocation = 'boat' - options = index:1, field:'output' - expect(-> parser._parseStack(['2', 'wool'], options)).to.throw Error, - "output element 1 for boat must start with a number" - - it 'can parse a basic item', -> - stack = parser._parseStack [2, 'wool'] - stack.constructor.name.should.equal 'Stack' - - describe '_parseStackList', -> - - it 'can promote a single item to a list', -> - list = parser._parseStackList 'boat' - (stack.itemSlug for stack in list).should.eql ['boat'] - - it 'can require a list to be non-empty', -> - parser._errorLocation = 'boat' - options = field:'output', canBeEmpty:false - expect(-> parser._parseStackList [], options).to.throw Error, 'output for boat cannot be empty' - - it 'can allow an empty list', -> - list = parser._parseStackList [], canBeEmpty:true - list.length.should.equal 0 - - it 'can parse a non-empty list', -> - list = parser._parseStackList [[3, 'plank'], [3, 'wool']] - (stack.itemSlug for stack in list).sort().should.eql ['plank', 'wool'] diff --git a/test/mod_version_parsers/v1.test.coffee b/test/mod_version_parsers/v1.test.coffee new file mode 100644 index 000000000..5b69fd552 --- /dev/null +++ b/test/mod_version_parsers/v1.test.coffee @@ -0,0 +1,160 @@ +### +Crafting Guide - mod_version_parsers/v1.test.coffee + +Copyright (c) 2014-2015 by Redwood Labs +All rights reserved. +### + +Item = require '../../src/scripts/models/item' +ModVersion = require '../../src/scripts/models/mod_version' +V1 = require '../../src/scripts/models/mod_version_parsers/v1' + +######################################################################################################################## + +modVersion = parser = null + +######################################################################################################################## + +describe "V1", -> + + beforeEach -> + parser = new V1 + modVersion = parser.modVersion = new ModVersion name:'Test', version:'0.0' + + describe '_parseModVersion', -> + + it 'requires a mod_name', -> + data = version:'1.0', items:[] + expect(-> parser._parseModVersion data).to.throw Error, 'name is required' + + it 'requires a mod_version', -> + data = name:'Empty', items:[] + expect(-> parser._parseModVersion data).to.throw Error, 'version is required' + + it 'can parse an empty modVersion', -> + data = + name: 'Empty' + version: '1.0' + recipes: [] + modVersion = parser._parseModVersion data + modVersion.name.should.equal 'Empty' + modVersion.version.should.equal '1.0' + + it 'can parse a non-empty mod version', -> + data = + name: 'Minecraft' + version: '1.7.10' + recipes: [ + { input:'Sugar Cane', output:'Sugar' } + { input:[[3, 'Wool'], [3, 'Planks']], tools:'Crafting Table', output:'Bed' } + ] + modVersion = parser._parseModVersion data + modVersion.name.should.equal 'Minecraft' + modVersion.version.should.equal '1.7.10' + slugs = (slug for slug, item of modVersion.items).sort() + slugs.should.eql ['bed', 'sugar'] + + describe '_parseRawMaterials', -> + + it 'skips the section when missing', -> + parser._parseRawMaterials null + _.keys(modVersion._items).length.should.equal 0 + + it 'skips the section when empty', -> + parser._parseRawMaterials [] + _.keys(modVersion._items).length.should.equal 0 + + it 'adds items marked as gatherable', -> + parser._parseRawMaterials ['Wool'] + modVersion.items['wool'].isGatherable.should.be.true + + it 'marks an existing item as gatherable', -> + modVersion.addItem new Item name:'Wool' + modVersion.items['wool'].isGatherable.should.be.false + parser._parseRawMaterials ['Wool'] + modVersion.items['wool'].isGatherable.should.be.true + + it 'registers the names of the items', -> + parser._parseRawMaterials ['Wool'] + modVersion.names['wool'].should.equal 'Wool' + + describe '_parseRecipe', -> + + it 'requires output to be defined', -> + parser._errorLocation = 'boat' + test = -> parser._parseRecipe {input:'wool'} + expect(test).to.throw Error, 'boat is missing output' + + it 'requires input to be defined', -> + test = -> parser._parseRecipe {output:'wool'} + expect(test).to.throw Error, 'recipe for wool is missing input' + + it 'can parse a regular recipe', -> + data = + output: 'bed' + input: [[3, 'planks'], [3, 'wool']] + tools: 'crafting table' + recipe = parser._parseRecipe data + (stack.itemSlug for stack in recipe.output).should.eql ['bed'] + (stack.itemSlug for stack in recipe.input).sort().should.eql ['planks', 'wool'] + (stack.itemSlug for stack in recipe.tools).should.eql ['crafting_table'] + + it 'can parse a recipe without tools', -> + recipe = parser._parseRecipe {output:'sugar', input:'sugar cane'} + (stack.itemSlug for stack in recipe.output).should.eql ['sugar'] + (stack.itemSlug for stack in recipe.input).sort().should.eql ['sugar_cane'] + (stack.itemSlug for stack in recipe.tools).should.eql [] + + it 'registers all names', -> + data = + output: 'Bed' + input: [[3, 'Oak Wood Planks'], [3, 'Wool']] + tools: 'Crafting Table' + parser._parseRecipe data + _.keys(modVersion.names).sort().should.eql ['bed', 'crafting_table', 'oak_wood_planks', 'wool'] + + describe '_parseStack', -> + + it 'requires the array to have at least one element', -> + parser._errorLocation = 'boat' + options = index:1, field:'output' + expect(-> parser._parseStack([], options)).to.throw Error, + "output element 1 for boat must have at least one element" + + it 'can fill in a missing number', -> + stack = parser._parseStack 'boat' + stack.itemSlug.should.equal 'boat' + stack.quantity.should.equal 1 + + stack2 = parser._parseStack ['boat'] + stack2.itemSlug.should.equal 'boat' + stack2.quantity.should.equal 1 + + it 'requires the data to start with a number', -> + parser._errorLocation = 'boat' + options = index:1, field:'output' + expect(-> parser._parseStack(['2', 'wool'], options)).to.throw Error, + "output element 1 for boat must start with a number" + + it 'can parse a basic item', -> + stack = parser._parseStack [2, 'wool'] + stack.constructor.name.should.equal 'Stack' + + describe '_parseStackList', -> + + it 'can promote a single item to a list', -> + list = parser._parseStackList 'boat' + (stack.itemSlug for stack in list).should.eql ['boat'] + + it 'can require a list to be non-empty', -> + parser._errorLocation = 'boat' + options = field:'output', canBeEmpty:false + expect(-> parser._parseStackList [], options).to.throw Error, 'output for boat cannot be empty' + + it 'can allow an empty list', -> + list = parser._parseStackList [], canBeEmpty:true + list.length.should.equal 0 + + it 'can parse a non-empty list', -> + list = parser._parseStackList [[3, 'plank'], [3, 'wool']] + (stack.itemSlug for stack in list).sort().should.eql ['plank', 'wool'] diff --git a/test/test.coffee b/test/test.coffee index 76c29bbd6..c160ca3a2 100644 --- a/test/test.coffee +++ b/test/test.coffee @@ -31,7 +31,8 @@ require './inventory.test' require './inventory_parser.test' require './mod_pack.test' require './mod_version.test' -require './mod_version_parser.test' +require './mod_version_parsers/v1.test' mocha.checkLeaks() +mocha.globals ['LiveReload'] mocha.run()