card/spec/card/fetch_spec.rb
# -*- encoding : utf-8 -*-
RSpec.describe Card::Fetch do
describe "#fetch" do
it "returns and caches existing cards" do
card_double = class_double("Card")
expect(Card.fetch("A")).to be_instance_of(Card)
expect(Card.cache.read("a")).to be_instance_of(Card)
expect(card_double).not_to receive(:find_by_key)
expect(Card.fetch("A")).to be_instance_of(Card)
end
it "returns nil and caches missing cards" do
expect(Card.fetch("Zork")).to be_nil
expect(Card.cache.read("zork")).to be_new_card
end
it "returns nil and caches trash cards", as_bot: true do
card_double = class_double("Card")
Card.fetch("A").delete!
expect(Card.fetch("A")).to be_nil
expect(card_double).not_to receive(:find_by_key_and_trash)
expect(Card.fetch("A")).to be_nil
end
it "returns and caches builtin cards" do
expect(Card.fetch("*head")).to be_instance_of(Card)
expect(Card.cache.read("*head")).not_to be_nil
end
it "returns virtual cards and caches them as missing", as_bot: true do
card = Card.fetch("Joe User+*email")
expect(card).to be_a(Card).and have_name "Joe User+*email"
expect(card.format.render_raw).to eq("joe@user.com")
end
it "fetches virtual cards after skipping them" do
expect(Card["A+*self"]).to be_nil
expect(Card.fetch("A+*self")).not_to be_nil
end
it "fetches newly virtual cards", as_bot: true do
expect(Card.fetch("A+virtual")).to be_nil
create "virtual+*right+*structure"
expect(Card.fetch("A+virtual")).not_to be_nil
end
it "fetches virtual set cards" do
aself = Card.fetch("A+*self")
Card::Cache.reset_all
Card.fetch "A+*self"
expect(aself.set_names).to include("Set+*type")
end
it "fetches structured cards" do
Card::Auth.as_bot do
Card.create! name: "y+*right+*structure", content: "Formatted Content"
Card.create! name: "a+y", content: "DB Content"
end
card = Card.fetch("a+y")
expect(card)
.to be_real
.and have_content("Formatted Content")
.and have_db_content("DB Content")
end
it "handles name variants of cached cards" do
expect(Card.fetch("yomama+*self").name).to eq("yomama+*self")
expect(Card.fetch("YOMAMA+*self").name).to eq("YOMAMA+*self")
expect(Card.fetch("yomama", new: {}).name).to eq("yomama")
expect(Card.fetch("YOMAMA", new: {}).name).to eq("YOMAMA")
expect(Card.fetch("yomama!", new: { name: "Yomama" }).name).to eq("Yomama")
end
it "fetches junction of names" do
card = Card.fetch "A", "B"
expect(card).to be_instance_of(Card)
expect(card.name).to eq "A+B"
end
it "fetches junction of string, id, and codename" do
card = Card.fetch "Book", Card.id(:type), :structure
expect(card).to be_instance_of(Card)
expect(card.name).to eq "Book+*type+*structure"
end
it "fetches junction of name, card object, and codename" do
card = Card.fetch "Book".to_name, Card.fetch(:type), :structure
expect(card).to be_instance_of(Card)
expect(card.name).to eq "Book+*type+*structure"
end
it "does not recurse infinitely on template templates" do
expect(Card.fetch("*structure+*right+*structure")).to be_nil
end
it "expires card and dependencies on save" do
# Card.cache.dump # should be empty
Card.cache.temp.reset
Cardio.delaying!
Card::Auth.as_bot do
a = Card.fetch("A")
expect(a).to be_instance_of(Card)
# expires the saved card
expect(a).to receive(:expire).and_call_original
# expect().to receive(:delete).with('a#SUBCARDS#').and_call_original
# expires plus cards
# expect(Card.cache).to receive(:delete).with('c+a')
# expect(Card.cache).to receive(:delete).with('d+a')
# expect(Card.cache).to receive(:delete).with('f+a')
# expect(Card.cache).to receive(:delete).with('a+b')
# expect(Card.cache).to receive(:delete).with('a+c')
# expect(Card.cache).to receive(:delete).with('a+d')
# expect(Card.cache).to receive(:delete).with('a+e')
# expect(Card.cache).to receive(:delete).with('a+b+c')
# expired including? cards
# expect(Card.cache).to receive(:delete).with('x').exactly(2).times
# expect(Card.cache).to receive(:delete).with('y').exactly(2).times
a.save!
Cardio.delaying!
end
end
describe "default option" do
context "when card doesn't exist" do
it "initializes new cards" do
card = Card.fetch "non-existent",
new: { default_content: "default content" }
expect(card.db_content).to eq "default content"
end
end
context "when new card exist" do
it "doesn't change anything" do
Card.new name: "new card",
"+sub" => { content: "some content" }
card = Card.fetch "new card+sub",
new: { default_content: "new content" }
expect(card.db_content).to eq "some content"
end
end
end
describe "preferences" do
before do
Card::Auth.signin Card::WagnBotID
end
it "prefers db cards to pattern virtual cards" do
Card.create! name: "y+*right+*structure",
content: "Formatted Content"
Card.create! name: "a+y", content: "DB Content"
card = Card.fetch("a+y")
expect(card).to be_not_virtual.and have_db_content "DB Content"
expect(card.rule(:structure)).to eq("Formatted Content")
end
it "prefers a pattern virtual card to trash cards" do
Card.create!(name: "y+*right+*structure", content: "Formatted Content")
Card.create!(name: "a+y", content: "DB Content")
Card.fetch("a+y").delete!
card = Card.fetch("a+y")
expect(card).to be_virtual.and have_content "Formatted Content"
end
it "recognizes pattern overrides" do
# ~~~ create right rule
Card.create!(name: "y+*right+*structure", content: "Right Content")
card = Card.fetch("a+y")
expect(card).to be_virtual.and have_content "Right Content"
# warn 'creating template'
tpr = Card.create! name: "RichText+y+*type plus right+*structure",
content: "Type Plus Right Content"
card = Card.fetch("a+y")
expect(card).to be_virtual.and have_content "Type Plus Right Content"
# ~~~ delete type plus right rule
tpr.delete!
card = Card.fetch("a+y")
expect(card).to be_virtual.and have_content "Right Content"
end
it "does not hit the database for every fetch_virtual lookup" do
card_double = class_double("Card")
Card.create!(name: "y+*right+*structure", content: "Formatted Content")
Card.fetch("a+y")
expect(card_double).not_to receive(:find_by_key)
Card.fetch("a+y")
end
it "does not be a new_record after being saved" do
Card.create!(name: "growing up")
card = Card.fetch("growing up")
expect(card).not_to be_new_record
end
end
describe "default_content option" do
context "when card doesn't exist" do
it "initializes card with default content" do
card = Card.fetch "non-existent", new: { default_content: "default content" }
expect(card).to have_db_content "default content"
end
end
context "when new card exist" do
it "doesn't change content" do
Card.new name: "new card", "+sub" => { content: "some content" }
card = Card.fetch "new card+sub", new: { default_content: "new content" }
expect(card).to have_db_content "some content"
end
end
end
end
describe "#fetch new: { ... }" do
it "returns a new card if it doesn't find one" do
new_card = Card.fetch "Never Seen Me Before", new: {}
expect(new_card).to be_a(Card).and be_a_new_record
expect { new_card.save! }.to increase_card_count.by(1)
end
it "returns a card if it finds one" do
new_card = Card.fetch "A+B", new: {}
expect(new_card).to be_a(Card).and be_real
expect { new_card.save! }.not_to increase_card_count
end
it "takes a second hash of options as new card options" do
new_card = Card.fetch "Never Before", new: { type: "Image" }
expect(new_card)
.to be_a(Card)
.and be_a_new_record
.and have_type(:image)
expect(Card.fetch("Never Before", new: {})).to have_type(:basic)
end
end
describe "#fetch_virtual" do
before do
Card::Auth.as_bot do
Card.create! name: "testsearch+*right+*structure",
content: '{"right_plus":"_self"}', type: "Search"
end
end
it "finds cards with *right+*structure specified" do
expect(Card.fetch("A+testsearch".to_name))
.to be_virtual
.and have_type(:search_type)
.and have_content '{"right_plus":"_self"}'
end
context "with new args" do
it "fetchs the virtual card with type set in patterns" do
Card.fetch "+testsearch", new: { name: "+testsearch", supercard: Card["home"] }
c = Card.fetch("Home+testsearch".to_name)
expect(c).to be_virtual
.and have_type(:search_type)
.and have_content('{"right_plus":"_self"}')
patterns = c.instance_variable_get("@patterns").map(&:to_s)
expect(patterns).to include("Search+*type")
end
end
end
end