diff --git a/spec/fixtures/colors.yml b/spec/fixtures/colors.yml index 2404832d..42589873 100644 --- a/spec/fixtures/colors.yml +++ b/spec/fixtures/colors.yml @@ -1,9 +1,18 @@ blue: id: 8 name: blue + basic: true +green: + id: 34 + name: green + basic: true purple: id: 57 name: purple +red: + id: 61 + name: red + basic: true robot: id: 62 name: robot diff --git a/spec/fixtures/items.yml b/spec/fixtures/items.yml new file mode 100644 index 00000000..f2d3e93c --- /dev/null +++ b/spec/fixtures/items.yml @@ -0,0 +1,14 @@ +straw_hat: + id: 58 + name: Straw Hat + description: "This straw hat will keep the sun out of your pets eyes in + bright sunlight." + thumbnail_url: https://images.neopets.com/items/straw-hat.gif + type: Clothes + category: Clothes + rarity: Very Rare + rarity_index: 90 + price: 376 + weight_lbs: 1 + zones_restrict: 0000000000000000000000000001000000001010000000000000 + species_support_ids: "35" diff --git a/spec/models/item_spec.rb b/spec/models/item_spec.rb new file mode 100644 index 00000000..b8434aae --- /dev/null +++ b/spec/models/item_spec.rb @@ -0,0 +1,93 @@ +require_relative '../rails_helper' + +RSpec.describe Item do + fixtures :items, :colors, :species, :zones + + context "modeling status:" do + # Rather than using fixtures of real-world data, we create very specific + # pet types, to be able to create small encapsulated test cases where there + # are only a few bodies. + before do + PetType.destroy_all # Make sure no leftovers from e.g. PetType's spec! + build_pt(colors(:blue), species(:acara), body_id: 1).save! + build_pt(colors(:red), species(:acara), body_id: 1).save! + build_pt(colors(:green), species(:blumaroo), body_id: 2).save! + build_pt(colors(:red), species(:chia), body_id: 3).save! + end + + def build_pt(color, species, body_id:) + PetType.new(color:, species:, body_id:) + end + + def build_item_asset(zone, body_id:) + @remote_id = (@remote_id || 0) + 1 + @url = "https://images.neopets.example/#{@remote_id}.swf" + SwfAsset.new(type: "object", remote_id: @remote_id, url: @url, + zones_restrict: "", zone:, body_id:) + end + + describe "an item without any modeling data" do + subject(:item) { items(:straw_hat) } + + pending("is not fully modeled") { should_not be_predicted_fully_modeled } + it("has no compatible body IDs") do + expect(item.compatible_body_ids).to be_empty + end + pending("predicts all standard bodies are compatible") do + expect(item.predicted_missing_body_ids).to contain_exactly(1, 2, 3) + end + end + + describe "an item with one species modeled" do + subject(:item) { items(:straw_hat) } + + before do + item.swf_assets << build_item_asset(zones(:wings), body_id: 1) + end + + it("is considered fully modeled") { should be_predicted_fully_modeled } + it("has one compatible body ID") do + expect(item.compatible_body_ids).to contain_exactly(1) + end + it("predicts no more compatible bodies") do + expect(item.predicted_missing_body_ids).to be_empty + end + end + + describe "an item with two species modeled" do + subject(:item) { items(:straw_hat) } + + before do + item.swf_assets << build_item_asset(zones(:wings), body_id: 1) + item.swf_assets << build_item_asset(zones(:wings), body_id: 2) + # HACK: I don't understand why the first asset is triggering the hooks + # for cached fields, but the second isn't? Idk, force an update. + item.update_cached_fields + end + + it("is not fully modeled") { should_not be_predicted_fully_modeled } + it("has two compatible body IDs") do + expect(item.compatible_body_ids).to contain_exactly(1, 2) + end + it("predicts remaining standard bodies are compatible") do + expect(item.predicted_missing_body_ids).to contain_exactly(3) + end + end + + describe "an item that fits all pets the same" do + subject(:item) { items(:straw_hat) } + + before do + item.swf_assets << build_item_asset(zones(:background), body_id: 0) + end + + it("is fully modeled") { should be_predicted_fully_modeled } + it("is compatible with all bodies (body ID = 0)") do + expect(item.compatible_body_ids).to contain_exactly(0) + end + it("predicts no more compatible bodies") do + expect(item.predicted_missing_body_ids).to be_empty + end + end + end +end