Bläddra i källkod

add unit tests for nested classes

Ben Cornelis 9 år sedan
förälder
incheckning
ac6492f57f
2 ändrade filer med 356 tillägg och 73 borttagningar
  1. 14 10
      app/models/agents/evernote_agent.rb
  2. 342 63
      spec/models/agents/evernote_agent_spec.rb

+ 14 - 10
app/models/agents/evernote_agent.rb

@@ -40,7 +40,8 @@ module Agents
             If a note with the above title and notebook did note exist already, one would be created.
 
           - When `mode` is `read` the values are search parameters.
-            Note: The `content` parameter is not used for searching.
+            Note: The `content` parameter is not used for searching. Setting `title` only filters
+            notes whose titles contain `title` as a substring, not as the exact title.
 
             For example, to find all notes with tag 'CS' in the notebook 'xkcd', use:
 
@@ -190,9 +191,11 @@ module Agents
 
       def create_or_update_note(params)
         search = Search.new(self, {title: params[:title], notebook: params[:notebook]})
+
         # evernote search can only filter notes with titles containing a substring;
         # this finds a note with the exact title
         note = search.notes.detect {|note| note.title == params[:title]}
+
         if note
           # a note with specified title and notebook exists, so update it
           update_note(params.merge(guid: note.guid, notebookGuid: note.notebookGuid))
@@ -218,6 +221,7 @@ module Agents
         params = with_wrapped_content(params)
 
         # append specified tags instead of replacing current tags
+        # evernote will create any new tags
         tags = getNoteTagNames(params[:guid])
         tags.each { |tag|
           params[:tagNames] << tag unless params[:tagNames].include?(tag) }
@@ -234,7 +238,7 @@ module Agents
       end
 
       def build_note(en_note)
-        notebook = find_notebook(guid: en_note.notebookGuid).name
+        notebook = find_notebook(guid: en_note.notebookGuid).try(:name)
         tags = en_note.tagNames || find_tags(en_note.tagGuids.to_a).map(&:name)
         Note.new(en_note, notebook, tags)
       end
@@ -276,11 +280,6 @@ module Agents
           @opts = opts
         end
 
-        def filtered_metadata
-          filter, spec = create_filter, create_spec
-          metadata = note_store.findNotesMetadata(filter, 0, 100, spec).notes
-        end
-
         def note_guids
           filtered_metadata.map(&:guid)
         end
@@ -295,7 +294,7 @@ module Agents
             # and notes that recently had the specified tags added
             metadata.select! do |note_data|
               note_data.updated > opts[:last_checked_at] ||
-              (!opts[:notes_with_tags].include?(note_data.guid) && note_data.created > opts[:agent_created_at])
+              !opts[:notes_with_tags].include?(note_data.guid)
             end
 
           elsif opts[:last_checked_at]
@@ -306,8 +305,6 @@ module Agents
           metadata
         end
 
-        private
-
         def create_filter
           filter = Evernote::EDAM::NoteStore::NoteFilter.new
 
@@ -323,6 +320,13 @@ module Agents
           filter
         end
 
+        private
+
+        def filtered_metadata
+          filter, spec = create_filter, create_spec
+          metadata = note_store.findNotesMetadata(filter, 0, 100, spec).notes
+        end
+
         def create_spec
           Evernote::EDAM::NoteStore::NotesMetadataResultSpec.new(
             includeTitle: true,

+ 342 - 63
spec/models/agents/evernote_agent_spec.rb

@@ -1,58 +1,59 @@
 require 'spec_helper'
 
 describe Agents::EvernoteAgent do
+  class FakeEvernoteNoteStore
+    attr_accessor :notes, :tags, :notebooks
+    def initialize
+      @notes, @tags, @notebooks = [], [], []
+    end
 
-  let(:note_store) 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 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 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 getNote(guid, *other_args)
-        @notes.find {|note| note.guid == guid}
-      end
+    def createNotebook(notebook)
+      notebook.guid = @notebooks.length + 1
+      @notebooks << notebook
+      notebook
+    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 createTag(tag)
-        tag.guid = @tags.length + 1
-        @tags << tag
-        tag
-      end
+    def listNotebooks; @notebooks; end
 
-      def listNotebooks; @notebooks; end
+    def listTags; @tags; end
 
-      def listTags; @tags; end
+    def getNoteTagNames(guid)
+      getNote(guid).try(:tagNames) || []
+    end
 
-      def getNoteTagNames(guid)
-        getNote(guid).try(:tagNames) || []
-      end
+    def findNotesMetadata(*args); end
+  end
 
-      def findNotesMetadata(*args); end
-    end
+  let(:en_note_store) do
+    FakeEvernoteNoteStore.new
+  end
 
-    note_store = FakeEvernoteNoteStore.new
-    stub.any_instance_of(Agents::EvernoteAgent).evernote_note_store { note_store }
-    note_store
+  before do
+    stub.any_instance_of(Agents::EvernoteAgent).evernote_note_store { en_note_store }
   end
 
   describe "#receive" do
@@ -85,18 +86,18 @@ describe Agents::EvernoteAgent do
 
         tag1 = OpenStruct.new(name: "funny")
         tag2 = OpenStruct.new(name: "data")
-        [tag1, tag2].each { |tag| note_store.createTag(tag) }
+        [tag1, tag2].each { |tag| en_note_store.createTag(tag) }
       end
 
       it "adds a note for any payload it receives" do
-        stub(note_store).findNotesMetadata { OpenStruct.new(notes: []) }
+        stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: []) }
         Agents::EvernoteAgent.async_receive(@agent.id, [@event.id])
 
-        expect(note_store.notes.size).to eq(1)
-        expect(note_store.notes.first.title).to eq("xkcd Survey")
-        expect(note_store.notebooks.size).to eq(1)
-        expect(note_store.tags.size).to eq(2)
-        
+        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",
@@ -111,18 +112,18 @@ describe Agents::EvernoteAgent do
         before do
           note1 = OpenStruct.new(title: "xkcd Survey", notebookGuid: 1)
           note2 = OpenStruct.new(title: "Footprints", notebookGuid: 1)
-          [note1, note2].each { |note| note_store.createNote(note) }
-          note_store.createNotebook(OpenStruct.new(name: "xkcd"))
+          [note1, note2].each { |note| en_note_store.createNote(note) }
+          en_note_store.createNotebook(OpenStruct.new(name: "xkcd"))
 
-          stub(note_store).findNotesMetadata {
+          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(note_store.notes.size).to eq(2)
-          expect(note_store.getNote(1).tagNames).to eq(["funny", "data"])
+          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
@@ -134,7 +135,7 @@ describe Agents::EvernoteAgent do
         end
 
         it "creates an event with note content wrapped in ENML" do
-          stub(note_store).findNotesMetadata { OpenStruct.new(notes: []) }
+          stub(en_note_store).findNotesMetadata { OpenStruct.new(notes: []) }
           Agents::EvernoteAgent.async_receive(@agent.id, [@event.id])
 
           payload = @agent.events.first.payload
@@ -172,19 +173,19 @@ describe Agents::EvernoteAgent do
         @checker.save!
         @checker.created_at = 1.minute.ago
 
-        note_store.createNote(
+        en_note_store.createNote(
           OpenStruct.new(title: "xkcd Survey",
                          notebookGuid: 1,
                          updated: 2.minutes.ago.to_i * 1000,
                          tagNames: ["funny", "comic"])
         )
-        note_store.createNotebook(OpenStruct.new(name: "xkcd"))
+        en_note_store.createNotebook(OpenStruct.new(name: "xkcd"))
         tag1 = OpenStruct.new(name: "funny")
         tag2 = OpenStruct.new(name: "comic")
-        [tag1, tag2].each { |tag| note_store.createTag(tag) }
+        [tag1, tag2].each { |tag| en_note_store.createTag(tag) }
 
-        stub(note_store).findNotesMetadata {
-          notes = note_store.notes.select do |note|
+        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
@@ -203,13 +204,13 @@ describe Agents::EvernoteAgent do
           expect { @checker.check }.to change { Event.count }.by(0)
 
           future_time = (Time.now + 1.minute).to_i * 1000
-          note_store.createNote(
+          en_note_store.createNote(
             OpenStruct.new(title: "Footprints",
                            notebookGuid: 1,
                            tagNames: ["funny", "comic", "recent"],
                            updated: future_time))
 
-          note_store.createNote(
+          en_note_store.createNote(
             OpenStruct.new(title: "something else",
                            notebookGuid: 2,
                            tagNames: ["funny", "comic"],
@@ -219,7 +220,7 @@ describe Agents::EvernoteAgent do
         end
 
         it "returns notes tagged since the last time it checked" do
-          note_store.createNote(
+          en_note_store.createNote(
             OpenStruct.new(title: "Footprints",
                            notebookGuid: 1,
                            tagNames: [],
@@ -227,7 +228,7 @@ describe Agents::EvernoteAgent do
                            updated: Time.now.to_i * 1000))
           @checker.check
 
-          note_store.getNote(2).tagNames = ["funny", "comic"]
+          en_note_store.getNote(2).tagNames = ["funny", "comic"]
 
           expect { @checker.check }.to change { Event.count }.by(1)
         end
@@ -294,4 +295,282 @@ describe Agents::EvernoteAgent do
       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