|
require 'spec_helper'
describe Agents::EvernoteAgent do
class FakeEvernoteNoteStore
attr_accessor :notes, :tags, :notebooks
def initialize
@notes, @tags, @notebooks = [], [], []
end
def createNote(note)
note.attributes = OpenStruct.new(source: nil, sourceURL: nil)
note.guid = @notes.length + 1
@notes << note
note
end
def updateNote(note)
note.attributes = OpenStruct.new(source: nil, sourceURL: nil)
old_note = @notes.find {|en_note| en_note.guid == note.guid}
@notes[@notes.index(old_note)] = note
note
end
def getNote(guid, *other_args)
@notes.find {|note| note.guid == guid}
end
def createNotebook(notebook)
notebook.guid = @notebooks.length + 1
@notebooks << notebook
notebook
end
def createTag(tag)
tag.guid = @tags.length + 1
@tags << tag
tag
end
def listNotebooks; @notebooks; end
def listTags; @tags; end
def getNoteTagNames(guid)
getNote(guid).try(:tagNames) || []
end
def findNotesMetadata(*args); end
end
let(:en_note_store) do
FakeEvernoteNoteStore.new
end
before do
stub.any_instance_of(Agents::EvernoteAgent).evernote_note_store { en_note_store }
end
describe "#receive" do
context "when mode is set to 'update'" do
before do
@options = {
:mode => "update",
:include_xhtml_content => "false",
:expected_update_period_in_days => "2",
:note => {
:title => "{{title}}",
:content => "{{content}}",
:notebook => "{{notebook}}",
:tagNames => "{{tag1}}, {{tag2}}"
}
}
@agent = Agents::EvernoteAgent.new(:name => "evernote updater", :options => @options)
@agent.service = services(:generic)
@agent.user = users(:bob)
@agent.save!
@event = Event.new
@event.agent = agents(:bob_website_agent)
@event.payload = { :title => "xkcd Survey",
:content => "The xkcd Survey: Big Data for a Big Planet",
:notebook => "xkcd",
:tag1 => "funny",
:tag2 => "data" }
@event.save!
tag1 = OpenStruct.new(name: "funny")
tag2 = OpenStruct.new(name: "data")
[tag1, tag2].each { |tag| en_note_store.createTag(tag) }
end
it "adds a note for any payload it receives" do
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: []) }
Agents::EvernoteAgent.async_receive(@agent.id, [@event.id])
expect(en_note_store.notes.size).to eq(1)
expect(en_note_store.notes.first.title).to eq("xkcd Survey")
expect(en_note_store.notebooks.size).to eq(1)
expect(en_note_store.tags.size).to eq(2)
expect(@agent.events.count).to eq(1)
expect(@agent.events.first.payload).to eq({
"title" => "xkcd Survey",
"notebook" => "xkcd",
"tags" => ["funny", "data"],
"source" => nil,
"source_url" => nil
})
end
context "a note with the same title and notebook exists" do
before do
note1 = OpenStruct.new(title: "xkcd Survey", notebookGuid: 1)
note2 = OpenStruct.new(title: "Footprints", notebookGuid: 1)
[note1, note2].each { |note| en_note_store.createNote(note) }
en_note_store.createNotebook(OpenStruct.new(name: "xkcd"))
stub(en_note_store).findNotesMetadata {
OpenStruct.new(notes: [note1]) }
end
it "updates the existing note" do
Agents::EvernoteAgent.async_receive(@agent.id, [@event.id])
expect(en_note_store.notes.size).to eq(2)
expect(en_note_store.getNote(1).tagNames).to eq(["funny", "data"])
expect(@agent.events.count).to eq(1)
end
end
context "include_xhtml_content is set to 'true'" do
before do
@agent.options[:include_xhtml_content] = "true"
@agent.save!
end
it "creates an event with note content wrapped in ENML" do
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: []) }
Agents::EvernoteAgent.async_receive(@agent.id, [@event.id])
payload = @agent.events.first.payload
expect(payload[:content]).to eq(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
"<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">" \
"<en-note>The xkcd Survey: Big Data for a Big Planet</en-note>"
)
end
end
end
end
describe "#check" do
context "when mode is set to 'read'" do
before do
@options = {
:mode => "read",
:include_xhtml_content => "false",
:expected_update_period_in_days => "2",
:note => {
:title => "",
:content => "",
:notebook => "xkcd",
:tagNames => "funny, comic"
}
}
@checker = Agents::EvernoteAgent.new(:name => "evernote reader", :options => @options)
@checker.service = services(:generic)
@checker.user = users(:bob)
@checker.schedule = "every_2h"
@checker.save!
@checker.created_at = 1.minute.ago
en_note_store.createNote(
OpenStruct.new(title: "xkcd Survey",
notebookGuid: 1,
updated: 2.minutes.ago.to_i * 1000,
tagNames: ["funny", "comic"])
)
en_note_store.createNotebook(OpenStruct.new(name: "xkcd"))
tag1 = OpenStruct.new(name: "funny")
tag2 = OpenStruct.new(name: "comic")
[tag1, tag2].each { |tag| en_note_store.createTag(tag) }
stub(en_note_store).findNotesMetadata {
notes = en_note_store.notes.select do |note|
note.notebookGuid == 1 &&
%w(funny comic).all? { |tag_name| note.tagNames.include?(tag_name) }
end
OpenStruct.new(notes: notes)
}
end
context "the first time it checks" do
it "returns only notes created/updated since it was created" do
expect { @checker.check }.to change { Event.count }.by(0)
end
end
context "on subsequent checks" do
it "returns notes created/updated since the last time it checked" do
expect { @checker.check }.to change { Event.count }.by(0)
future_time = (Time.now + 1.minute).to_i * 1000
en_note_store.createNote(
OpenStruct.new(title: "Footprints",
notebookGuid: 1,
tagNames: ["funny", "comic", "recent"],
updated: future_time))
en_note_store.createNote(
OpenStruct.new(title: "something else",
notebookGuid: 2,
tagNames: ["funny", "comic"],
updated: future_time))
expect { @checker.check }.to change { Event.count }.by(1)
end
it "returns notes tagged since the last time it checked" do
en_note_store.createNote(
OpenStruct.new(title: "Footprints",
notebookGuid: 1,
tagNames: [],
created: Time.now.to_i * 1000,
updated: Time.now.to_i * 1000))
@checker.check
en_note_store.getNote(2).tagNames = ["funny", "comic"]
expect { @checker.check }.to change { Event.count }.by(1)
end
end
end
end
describe "#validation" do
before do
@options = {
:mode => "update",
:include_xhtml_content => "false",
:expected_update_period_in_days => "2",
:note => {
:title => "{{title}}",
:content => "{{content}}",
:notebook => "{{notebook}}",
:tagNames => "{{tag1}}, {{tag2}}"
}
}
@agent = Agents::EvernoteAgent.new(:name => "evernote updater", :options => @options)
@agent.service = services(:generic)
@agent.user = users(:bob)
@agent.save!
expect(@agent).to be_valid
end
it "requires the mode to be 'update' or 'read'" do
@agent.options[:mode] = ""
expect(@agent).not_to be_valid
end
context "mode is set to 'update'" do
before do
@agent.options[:mode] = "update"
end
it "requires some note parameter to be present" do
@agent.options[:note].keys.each { |k| @agent.options[:note][k] = "" }
expect(@agent).not_to be_valid
end
it "requires schedule to be 'never'" do
@agent.schedule = 'never'
expect(@agent).to be_valid
@agent.schedule = 'every_1m'
expect(@agent).not_to be_valid
end
end
context "mode is set to 'read'" do
before do
@agent.options[:mode] = "read"
end
it "requires a schedule to be set" do
@agent.schedule = 'every_1m'
expect(@agent).to be_valid
@agent.schedule = 'never'
expect(@agent).not_to be_valid
end
end
end
# api wrapper classes
describe Agents::EvernoteAgent::NoteStore do
let(:note_store) { Agents::EvernoteAgent::NoteStore.new(en_note_store) }
let(:note1) { OpenStruct.new(title: "first note") }
let(:note2) { OpenStruct.new(title: "second note") }
before do
en_note_store.createNote(note1)
en_note_store.createNote(note2)
end
describe "#create_note" do
it "creates a note with given params in evernote note store" do
note_store.create_note(title: "third note")
expect(en_note_store.notes.size).to eq(3)
expect(en_note_store.notes.last.title).to eq("third note")
end
it "returns a note" do
expect(note_store.create_note(title: "third note")).to be_a(Agents::EvernoteAgent::Note)
end
end
describe "#update_note" do
it "updates an existing note with given params" do
note_store.update_note(guid: 1, content: "some words")
expect(en_note_store.notes.first.content).not_to be_nil
expect(en_note_store.notes.size).to eq(2)
end
it "returns a note" do
expect(note_store.update_note(guid: 1, content: "some words")).to be_a(Agents::EvernoteAgent::Note)
end
end
describe "#find_note" do
it "gets a note with the given guid" do
note = note_store.find_note(2)
expect(note.title).to eq("second note")
expect(note).to be_a(Agents::EvernoteAgent::Note)
end
end
describe "#find_tags" do
let(:tag1) { OpenStruct.new(name: "tag1") }
let(:tag2) { OpenStruct.new(name: "tag2") }
let(:tag3) { OpenStruct.new(name: "tag3") }
before do
[tag1, tag2, tag3].each { |tag| en_note_store.createTag(tag) }
end
it "finds tags with the given guids" do
expect(note_store.find_tags([1,3])).to eq([tag1, tag3])
end
end
describe "#find_notebook" do
let(:notebook1) { OpenStruct.new(name: "notebook1") }
let(:notebook2) { OpenStruct.new(name: "notebook2") }
before do
[notebook1, notebook2].each {|notebook| en_note_store.createNotebook(notebook)}
end
it "finds a notebook with given name" do
expect(note_store.find_notebook(name: "notebook1")).to eq(notebook1)
expect(note_store.find_notebook(name: "notebook3")).to be_nil
end
it "finds a notebook with a given guid" do
expect(note_store.find_notebook(guid: 2)).to eq(notebook2)
expect(note_store.find_notebook(guid: 3)).to be_nil
end
end
describe "#create_or_update_note" do
let(:notebook1) { OpenStruct.new(name: "first notebook")}
before do
en_note_store.createNotebook(notebook1)
end
context "a note with given title and notebook does not exist" do
before do
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: []) }
end
it "creates a note" do
result = note_store.create_or_update_note(title: "third note", notebook: "first notebook")
expect(result).to be_a(Agents::EvernoteAgent::Note)
expect(en_note_store.getNote(3)).to_not be_nil
end
it "also creates the notebook if it does not exist" do
note_store.create_or_update_note(title: "third note", notebook: "second notebook")
expect(note_store.find_notebook(name: "second notebook")).to_not be_nil
end
end
context "such a note does exist" do
let(:note) { OpenStruct.new(title: "a note", notebookGuid: 1) }
before do
en_note_store.createNote(note)
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: [note]) }
end
it "updates the note" do
prior_note_count = en_note_store.notes.size
result = note_store.create_or_update_note(
title: "a note", notebook: "first notebook", content: "test content")
expect(result).to be_a(Agents::EvernoteAgent::Note)
expect(en_note_store.notes.size).to eq(prior_note_count)
expect(en_note_store.getNote(3).content).to include("test content")
end
end
end
end
describe Agents::EvernoteAgent::NoteStore::Search do
let(:note_store) { Agents::EvernoteAgent::NoteStore.new(en_note_store) }
let(:note1) {
OpenStruct.new(title: "first note", notebookGuid: 1, tagNames: ["funny", "comic"], updated: Time.now) }
let(:note2) {
OpenStruct.new(title: "second note", tagNames: ["funny", "comic"], updated: Time.now) }
let(:note3) {
OpenStruct.new(title: "third note", notebookGuid: 1, updated: Time.now - 2.minutes) }
let(:search) do
Agents::EvernoteAgent::NoteStore::Search.new(note_store,
{ tagNames: ["funny", "comic"], notebook: "xkcd" })
end
let(:search_with_time) do
Agents::EvernoteAgent::NoteStore::Search.new(note_store,
{ notebook: "xkcd", last_checked_at: Time.now - 1.minute })
end
let(:search_with_time_and_tags) do
Agents::EvernoteAgent::NoteStore::Search.new(note_store,
{ notebook: "xkcd", tagNames: ["funny", "comic"], notes_with_tags: [1], last_checked_at: Time.now - 1.minute })
end
before do
en_note_store.createTag(OpenStruct.new(name: "funny"))
en_note_store.createTag(OpenStruct.new(name: "comic"))
en_note_store.createNotebook(OpenStruct.new(name: "xkcd"))
[note1, note2, note3].each { |note| en_note_store.createNote(note) }
end
describe "#note_guids" do
it "returns the guids of notes satisfying search options" do
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: [note1]) }
result = search.note_guids
expect(result.size).to eq(1)
expect(result.first).to eq(1)
end
end
describe "#notes" do
context "last_checked_at is not set" do
it "returns notes satisfying the search options" do
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: [note1]) }
result = search.notes
expect(result.size).to eq(1)
expect(result.first.title).to eq("first note")
expect(result.first).to be_a(Agents::EvernoteAgent::Note)
end
end
context "last_checked_at is set" do
context "notes_with_tags is not set" do
it "only returns notes updated since then" do
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: [note1, note3]) }
result = search_with_time.notes
expect(result.size).to eq(1)
expect(result.first.title).to eq("first note")
end
end
context "notes_with_tags is set" do
it "returns notes updated since then or notes with recently added tags" do
note3.tagNames = ["funny", "comic"]
stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: [note1, note3]) }
result = search_with_time_and_tags.notes
expect(result.size).to eq(2)
expect(result.last.title).to eq("third note")
end
end
end
end
describe "#create_filter" do
it "builds an evernote search filter using search grammar" do
filter = search.create_filter
expect(filter.words).to eq("notebook:\"xkcd\" tag:funny tag:comic")
end
end
end
describe Agents::EvernoteAgent::Note do
let(:resource) {
OpenStruct.new(mime: "image/png",
attributes: OpenStruct.new(sourceURL: "http://imgs.xkcd.com/comics/xkcd_survey.png", fileName: "xkcd_survey.png"))
}
let(:en_note_attributes) {
OpenStruct.new(source: "web.clip", sourceURL: "http://xkcd.com/1572/")
}
let(:en_note) {
OpenStruct.new(title: "xkcd Survey",
tagNames: ["funny", "data"],
content: "The xkcd Survey: Big Data for a Big Planet",
attributes: en_note_attributes,
resources: [resource])
}
describe "#attr" do
let(:note) {
Agents::EvernoteAgent::Note.new(en_note, "xkcd", ["funny", "data"])
}
context "when no option is set" do
it "returns a hash with title, tags, notebook, source and source url" do
expect(note.attr).to eq(
{
title: en_note.title,
notebook: "xkcd",
tags: ["funny", "data"],
source: en_note.attributes.source,
source_url: en_note.attributes.sourceURL
}
)
end
end
context "when include_content is set to true" do
it "includes content" do
note_attr = note.attr(include_content: true)
expect(note_attr[:content]).to eq(
"The xkcd Survey: Big Data for a Big Planet"
)
end
end
context "when include_resources is set to true" do
it "includes resources" do
note_attr = note.attr(include_resources: true)
expect(note_attr[:resources].first).to eq(
{
url: resource.attributes.sourceURL,
name: resource.attributes.fileName,
mime_type: resource.mime
}
)
end
end
end
end
end
|