123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- require 'rails_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
- allow_any_instance_of(Agents::EvernoteAgent).to receive(: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
- allow(en_note_store).to receive(: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"))
- allow(en_note_store).to receive(: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
- allow(en_note_store).to receive(: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) }
- allow(en_note_store).to receive(: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
- allow(en_note_store).to receive(: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)
- allow(en_note_store).to receive(: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
- allow(en_note_store).to receive(: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
- allow(en_note_store).to receive(: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
- allow(en_note_store).to receive(: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"]
- allow(en_note_store).to receive(: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
|