browsing_history 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.rubocop.yml +89 -0
- data/.rubocop_todo.yml +28 -0
- data/.ruby-version +1 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +180 -0
- data/LICENSE +21 -0
- data/MIT-LICENSE +20 -0
- data/README.md +2 -0
- data/README.rdoc +3 -0
- data/Rakefile +28 -0
- data/browsing_history.gemspec +34 -0
- data/dump.rdb +1 -0
- data/lib/browsing_history/browser.rb +66 -0
- data/lib/browsing_history/configuration.rb +38 -0
- data/lib/browsing_history/error.rb +2 -0
- data/lib/browsing_history/historizable.rb +26 -0
- data/lib/browsing_history/history.rb +85 -0
- data/lib/browsing_history/storage.rb +44 -0
- data/lib/browsing_history/storages/active_record.rb +12 -0
- data/lib/browsing_history/storages/base.rb +40 -0
- data/lib/browsing_history/storages/redis.rb +113 -0
- data/lib/browsing_history/version.rb +3 -0
- data/lib/browsing_history.rb +12 -0
- data/lib/generators/active_record/migration_generator.rb +12 -0
- data/lib/generators/active_record/templates/migration.rb +15 -0
- data/lib/tasks/browsing_history_tasks.rake +4 -0
- data/spec/browsing_history/browser_spec.rb +156 -0
- data/spec/browsing_history/configration_spec.rb +16 -0
- data/spec/browsing_history/fixtures/article.rb +10 -0
- data/spec/browsing_history/fixtures/user.rb +10 -0
- data/spec/browsing_history/historizable_spec.rb +27 -0
- data/spec/browsing_history/history_spec.rb +273 -0
- data/spec/browsing_history/storage_spec.rb +45 -0
- data/spec/browsing_history/storages/base_spec.rb +35 -0
- data/spec/browsing_history/storages/redis_spec.rb +141 -0
- data/spec/browsing_history_spec.rb +4 -0
- data/spec/generator_spec.rb +34 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/test_app/README.rdoc +28 -0
- data/spec/test_app/Rakefile +6 -0
- data/spec/test_app/app/assets/images/.keep +0 -0
- data/spec/test_app/app/assets/javascripts/application.js +13 -0
- data/spec/test_app/app/assets/stylesheets/application.css +15 -0
- data/spec/test_app/app/controllers/application_controller.rb +10 -0
- data/spec/test_app/app/controllers/articles_controller.rb +17 -0
- data/spec/test_app/app/controllers/concerns/.keep +0 -0
- data/spec/test_app/app/helpers/application_helper.rb +2 -0
- data/spec/test_app/app/mailers/.keep +0 -0
- data/spec/test_app/app/models/.keep +0 -0
- data/spec/test_app/app/models/concerns/.keep +0 -0
- data/spec/test_app/app/views/layouts/application.html.erb +14 -0
- data/spec/test_app/bin/bundle +3 -0
- data/spec/test_app/bin/rails +4 -0
- data/spec/test_app/bin/rake +4 -0
- data/spec/test_app/bin/setup +29 -0
- data/spec/test_app/config/application.rb +19 -0
- data/spec/test_app/config/boot.rb +5 -0
- data/spec/test_app/config/database.yml +12 -0
- data/spec/test_app/config/environment.rb +5 -0
- data/spec/test_app/config/environments/development.rb +18 -0
- data/spec/test_app/config/environments/test.rb +21 -0
- data/spec/test_app/config/initializers/assets.rb +11 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/cookies_serializer.rb +3 -0
- data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/test_app/config/initializers/inflections.rb +16 -0
- data/spec/test_app/config/initializers/mime_types.rb +4 -0
- data/spec/test_app/config/initializers/session_store.rb +3 -0
- data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/test_app/config/locales/en.yml +23 -0
- data/spec/test_app/config/routes.rb +2 -0
- data/spec/test_app/config/secrets.yml +5 -0
- data/spec/test_app/config.ru +4 -0
- data/spec/test_app/db/development.sqlite3 +0 -0
- data/spec/test_app/db/test.sqlite3 +0 -0
- data/spec/test_app/lib/assets/.keep +0 -0
- data/spec/test_app/log/.keep +0 -0
- data/spec/test_app/log/development.log +0 -0
- data/spec/test_app/log/test.log +0 -0
- data/spec/test_app/public/404.html +67 -0
- data/spec/test_app/public/422.html +67 -0
- data/spec/test_app/public/500.html +66 -0
- data/spec/test_app/public/favicon.ico +0 -0
- metadata +342 -0
| @@ -0,0 +1,273 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'fixtures/user'
         | 
| 3 | 
            +
            require 'fixtures/article'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe BrowsingHistory::History do
         | 
| 6 | 
            +
              let(:user)    { User.new }
         | 
| 7 | 
            +
              let(:article) { Article.new }
         | 
| 8 | 
            +
              let(:articles) { Array.new(50) { |i| Article.new(i) } }
         | 
| 9 | 
            +
              let(:history) { described_class.new(browser: user, historizable: article) }
         | 
| 10 | 
            +
              let(:invalid_object) { Struct.new(:_).new }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              describe 'responses' do
         | 
| 13 | 
            +
                describe 'instance_methods' do
         | 
| 14 | 
            +
                  subject { history }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  it { is_expected.to respond_to(:browser) }
         | 
| 17 | 
            +
                  it { is_expected.to respond_to(:historizable) }
         | 
| 18 | 
            +
                  it { is_expected.to respond_to(:save) }
         | 
| 19 | 
            +
                  it { is_expected.to respond_to(:save!) }
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                describe 'instance_methods' do
         | 
| 23 | 
            +
                  subject { described_class }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  it { is_expected.to respond_to(:create) }
         | 
| 26 | 
            +
                  it { is_expected.to respond_to(:create!) }
         | 
| 27 | 
            +
                  it { is_expected.to respond_to(:where) }
         | 
| 28 | 
            +
                  it { is_expected.to respond_to(:count) }
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              describe '#save' do
         | 
| 33 | 
            +
                let(:new_history_with_valid_objects) do
         | 
| 34 | 
            +
                  described_class.new(
         | 
| 35 | 
            +
                    browser: user,
         | 
| 36 | 
            +
                    historizable: article
         | 
| 37 | 
            +
                  )
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                let(:new_history_with_invalid_browser) do
         | 
| 41 | 
            +
                  described_class.new(
         | 
| 42 | 
            +
                    browser: invalid_object,
         | 
| 43 | 
            +
                    historizable: article
         | 
| 44 | 
            +
                  )
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                let(:new_history_with_invalid_historizable) do
         | 
| 48 | 
            +
                  described_class.new(
         | 
| 49 | 
            +
                    browser: user,
         | 
| 50 | 
            +
                    historizable: invalid_object
         | 
| 51 | 
            +
                  )
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                context 'when save with valid objects' do
         | 
| 55 | 
            +
                  it "should return #{described_class} instance" do
         | 
| 56 | 
            +
                    expect(
         | 
| 57 | 
            +
                      new_history_with_valid_objects.save
         | 
| 58 | 
            +
                    ).to be(true)
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    expect(
         | 
| 61 | 
            +
                      new_history_with_valid_objects.save!
         | 
| 62 | 
            +
                    ).to be(true)
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                context 'when save with invalid object' do
         | 
| 67 | 
            +
                  it 'should return nil' do
         | 
| 68 | 
            +
                    expect(
         | 
| 69 | 
            +
                      new_history_with_invalid_browser.save
         | 
| 70 | 
            +
                    ).to be_falsey
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    expect(
         | 
| 73 | 
            +
                      new_history_with_invalid_historizable.save
         | 
| 74 | 
            +
                    ).to be_falsey
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                context 'when save! with invalid object' do
         | 
| 79 | 
            +
                  it 'should raise error' do
         | 
| 80 | 
            +
                    expect do
         | 
| 81 | 
            +
                      new_history_with_invalid_browser.save!
         | 
| 82 | 
            +
                    end.to raise_error(BrowsingHistory::History::ArgumentError)
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    expect do
         | 
| 85 | 
            +
                      new_history_with_invalid_historizable.save!
         | 
| 86 | 
            +
                    end.to raise_error(BrowsingHistory::History::ArgumentError)
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                context 'after save hitorizables' do
         | 
| 91 | 
            +
                  before(:each) do
         | 
| 92 | 
            +
                    articles.each do |article|
         | 
| 93 | 
            +
                      described_class.new(browser: user, historizable: article).save
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  let(:saved_articles) do
         | 
| 98 | 
            +
                    described_class.where(
         | 
| 99 | 
            +
                      browser: user,
         | 
| 100 | 
            +
                      historizable: article
         | 
| 101 | 
            +
                    )
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  it 'should equal original historizable' do
         | 
| 105 | 
            +
                    saved_articles.each_with_index do |saved_article, i|
         | 
| 106 | 
            +
                      original = articles.reverse[i]
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                      expect(saved_article.id).to eq(original.id)
         | 
| 109 | 
            +
                      expect(saved_article.title).to eq(original.title)
         | 
| 110 | 
            +
                    end
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                context 'after save! hitorizables' do
         | 
| 115 | 
            +
                  before(:each) do
         | 
| 116 | 
            +
                    articles.each do |article|
         | 
| 117 | 
            +
                      described_class.new(browser: user, historizable: article).save!
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  let(:saved_articles) do
         | 
| 122 | 
            +
                    described_class.where(
         | 
| 123 | 
            +
                      browser: user,
         | 
| 124 | 
            +
                      historizable: article
         | 
| 125 | 
            +
                    )
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  it 'should equal original historizable' do
         | 
| 129 | 
            +
                    saved_articles.each_with_index do |saved_article, i|
         | 
| 130 | 
            +
                      original = articles.reverse[i]
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                      expect(saved_article.id).to eq(original.id)
         | 
| 133 | 
            +
                      expect(saved_article.title).to eq(original.title)
         | 
| 134 | 
            +
                    end
         | 
| 135 | 
            +
                  end
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
              end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
              describe '.create' do
         | 
| 140 | 
            +
                context 'when create with valid objects' do
         | 
| 141 | 
            +
                  subject do
         | 
| 142 | 
            +
                    described_class.create(
         | 
| 143 | 
            +
                      browser: user,
         | 
| 144 | 
            +
                      historizable: article
         | 
| 145 | 
            +
                    )
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
                  it { is_expected.to be_a(described_class) }
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  subject do
         | 
| 150 | 
            +
                    described_class.create!(
         | 
| 151 | 
            +
                      browser: user,
         | 
| 152 | 
            +
                      historizable: article
         | 
| 153 | 
            +
                    )
         | 
| 154 | 
            +
                  end
         | 
| 155 | 
            +
                  it { is_expected.to be_a(described_class) }
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                context 'when create with invalid object' do
         | 
| 159 | 
            +
                  it 'should return nil' do
         | 
| 160 | 
            +
                    expect(
         | 
| 161 | 
            +
                      described_class.create(
         | 
| 162 | 
            +
                        browser: invalid_object,
         | 
| 163 | 
            +
                        historizable: article
         | 
| 164 | 
            +
                      )
         | 
| 165 | 
            +
                    ).to be_falsey
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                    expect(
         | 
| 168 | 
            +
                      described_class.create(
         | 
| 169 | 
            +
                        browser: user,
         | 
| 170 | 
            +
                        historizable: invalid_object
         | 
| 171 | 
            +
                      )
         | 
| 172 | 
            +
                    ).to be_falsey
         | 
| 173 | 
            +
                  end
         | 
| 174 | 
            +
                end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                context 'when create! with invalid object' do
         | 
| 177 | 
            +
                  it 'should raise error' do
         | 
| 178 | 
            +
                    expect do
         | 
| 179 | 
            +
                      described_class.create!(
         | 
| 180 | 
            +
                        browser: invalid_object,
         | 
| 181 | 
            +
                        historizable: article
         | 
| 182 | 
            +
                      )
         | 
| 183 | 
            +
                    end.to raise_error(BrowsingHistory::History::ArgumentError)
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                    expect do
         | 
| 186 | 
            +
                      described_class.create!(
         | 
| 187 | 
            +
                        browser: user,
         | 
| 188 | 
            +
                        historizable: invalid_object
         | 
| 189 | 
            +
                      )
         | 
| 190 | 
            +
                    end.to raise_error(BrowsingHistory::History::ArgumentError)
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
                end
         | 
| 193 | 
            +
              end
         | 
| 194 | 
            +
             | 
| 195 | 
            +
              describe '.count' do
         | 
| 196 | 
            +
                subject { described_class.current_storage.count(user, article) }
         | 
| 197 | 
            +
                it { is_expected.to eq(0) }
         | 
| 198 | 
            +
              end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
              describe '.where' do
         | 
| 201 | 
            +
                it 'should default empty' do
         | 
| 202 | 
            +
                  expect(
         | 
| 203 | 
            +
                    BrowsingHistory::History.where(
         | 
| 204 | 
            +
                      browser: user,
         | 
| 205 | 
            +
                      historizable: article
         | 
| 206 | 
            +
                    )
         | 
| 207 | 
            +
                  ).to be_empty
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                context 'with limit option' do
         | 
| 211 | 
            +
                  before do
         | 
| 212 | 
            +
                    5.times do |i|
         | 
| 213 | 
            +
                      described_class.create(browser: user, historizable: Article.new(i))
         | 
| 214 | 
            +
                    end
         | 
| 215 | 
            +
                  end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                  let(:historizables) do
         | 
| 218 | 
            +
                    described_class.where(
         | 
| 219 | 
            +
                      browser: user,
         | 
| 220 | 
            +
                      historizable: article,
         | 
| 221 | 
            +
                      limit: 3
         | 
| 222 | 
            +
                    )
         | 
| 223 | 
            +
                  end
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                  let(:historizables_excess_limit) do
         | 
| 226 | 
            +
                    described_class.where(
         | 
| 227 | 
            +
                      browser: user,
         | 
| 228 | 
            +
                      historizable: article,
         | 
| 229 | 
            +
                      limit: 100
         | 
| 230 | 
            +
                    )
         | 
| 231 | 
            +
                  end
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                  it { expect(historizables).to be_a(Array) }
         | 
| 234 | 
            +
                  it { expect(historizables.size).to eq(3) }
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                  it { expect(historizables_excess_limit).to be_a(Array) }
         | 
| 237 | 
            +
                  it { expect(historizables_excess_limit.size).to eq(5) }
         | 
| 238 | 
            +
                end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                context 'with between option' do
         | 
| 241 | 
            +
                  before do
         | 
| 242 | 
            +
                    5.times.map.with_index(1) do |i|
         | 
| 243 | 
            +
                      described_class.create(browser: user, historizable: Article.new(i))
         | 
| 244 | 
            +
                    end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                    sleep(6)
         | 
| 247 | 
            +
                    described_class.create(browser: user, historizable: Article.new(100))
         | 
| 248 | 
            +
                  end
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                  let(:historizables) do
         | 
| 251 | 
            +
                    described_class.where(
         | 
| 252 | 
            +
                      browser: user,
         | 
| 253 | 
            +
                      historizable: article,
         | 
| 254 | 
            +
                      between: Time.now..5.seconds.ago
         | 
| 255 | 
            +
                    )
         | 
| 256 | 
            +
                  end
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                  let(:historizables_unhit) do
         | 
| 259 | 
            +
                    described_class.where(
         | 
| 260 | 
            +
                      browser: user,
         | 
| 261 | 
            +
                      historizable: article,
         | 
| 262 | 
            +
                      between: 1.day.ago..2.days.ago
         | 
| 263 | 
            +
                    )
         | 
| 264 | 
            +
                  end
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                  it { expect(historizables).to be_a(Array) }
         | 
| 267 | 
            +
                  it { expect(historizables.size).to eq(1) }
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                  it { expect(historizables_unhit).to be_a(Array) }
         | 
| 270 | 
            +
                  it { expect(historizables_unhit.size).to eq(0) }
         | 
| 271 | 
            +
                end
         | 
| 272 | 
            +
              end
         | 
| 273 | 
            +
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe BrowsingHistory::Storage do
         | 
| 4 | 
            +
              describe '#attach_storage' do
         | 
| 5 | 
            +
                let(:default_storage) { :redis }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                let(:include_class) do
         | 
| 8 | 
            +
                  Struct.new(:_) do
         | 
| 9 | 
            +
                    include BrowsingHistory::Storage
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                let(:include_class_attached_activerecord) do
         | 
| 14 | 
            +
                  Struct.new(:_) do
         | 
| 15 | 
            +
                    include BrowsingHistory::Storage
         | 
| 16 | 
            +
                    attach_storage :active_record
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                let(:include_class_invalid_storage) do
         | 
| 21 | 
            +
                  Struct.new(:_) do
         | 
| 22 | 
            +
                    include BrowsingHistory::Storage
         | 
| 23 | 
            +
                    attach_storage :invalid_storage
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it 'should be attached redis storage default' do
         | 
| 28 | 
            +
                  expect(include_class.current_storage_type).to eql(default_storage)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                it 'should attached activerecord' do
         | 
| 32 | 
            +
                  expect(
         | 
| 33 | 
            +
                    include_class_attached_activerecord.current_storage_type
         | 
| 34 | 
            +
                  ).to eql(:active_record)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                context 'when passed invalid storage' do
         | 
| 38 | 
            +
                  it 'should raise error' do
         | 
| 39 | 
            +
                    expect do
         | 
| 40 | 
            +
                      include_class_invalid_storage
         | 
| 41 | 
            +
                    end.to raise_error(BrowsingHistory::Storage::InvalidStorage)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'fixtures/user'
         | 
| 3 | 
            +
            require 'fixtures/article'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe BrowsingHistory::Storages::Base do
         | 
| 6 | 
            +
              let(:user)     { User.new }
         | 
| 7 | 
            +
              let(:article)  { Article.new }
         | 
| 8 | 
            +
              let(:described_instance) { described_class.new(user, article) }
         | 
| 9 | 
            +
              let(:test_options) { Hash.new }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              before do
         | 
| 12 | 
            +
                described_class.connect
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe 'io_methods' do
         | 
| 16 | 
            +
                it 'should be defined on class' do
         | 
| 17 | 
            +
                  BrowsingHistory::Storages::IOMethods.each do |method|
         | 
| 18 | 
            +
                    expect(
         | 
| 19 | 
            +
                      described_class.respond_to?(method)
         | 
| 20 | 
            +
                    ).to be(true)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                it 'should raise not overide error' do
         | 
| 25 | 
            +
                  BrowsingHistory::Storages::IOMethods.each do |method|
         | 
| 26 | 
            +
                    expect do
         | 
| 27 | 
            +
                      described_instance.send(method)
         | 
| 28 | 
            +
                    end.to raise_error(BrowsingHistory::Storages::NotOverideError)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              describe '.connect' do
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,141 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'fixtures/user'
         | 
| 3 | 
            +
            require 'fixtures/article'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe BrowsingHistory::Storages::Redis do
         | 
| 6 | 
            +
              articles_size = 5
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              let(:user)    { User.new }
         | 
| 9 | 
            +
              let(:articles) do
         | 
| 10 | 
            +
                articles_size.times.map.with_index(1) { |i| Article.new(i) }
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
              let(:article) { articles.first }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              let(:storage) do
         | 
| 15 | 
            +
                Struct.new(:_) do
         | 
| 16 | 
            +
                  include BrowsingHistory::Storage
         | 
| 17 | 
            +
                  attach_storage :redis
         | 
| 18 | 
            +
                end.current_storage
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              describe 'method_defined?' do
         | 
| 22 | 
            +
                describe 'public_instance_methods' do
         | 
| 23 | 
            +
                  subject { storage.new(user, article) }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  it { is_expected.to respond_to(:fetch) }
         | 
| 26 | 
            +
                  it { is_expected.to respond_to(:add) }
         | 
| 27 | 
            +
                  it { is_expected.to respond_to(:update) }
         | 
| 28 | 
            +
                  it { is_expected.to respond_to(:clear) }
         | 
| 29 | 
            +
                  it { is_expected.to respond_to(:interface) }
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                describe 'private_instance_methods' do
         | 
| 33 | 
            +
                  subject { storage.private_instance_methods }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  it { is_expected.to include(:history) }
         | 
| 36 | 
            +
                  it { is_expected.to include(:fetch_between) }
         | 
| 37 | 
            +
                  it { is_expected.to include(:clear_all) }
         | 
| 38 | 
            +
                  it { is_expected.to include(:clear_expiration) }
         | 
| 39 | 
            +
                  it { is_expected.to include(:score) }
         | 
| 40 | 
            +
                  it { is_expected.to include(:parse_between) }
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                describe 'singleton_methods' do
         | 
| 44 | 
            +
                  subject { storage }
         | 
| 45 | 
            +
                  it { is_expected.to respond_to(:connect) }
         | 
| 46 | 
            +
                  it { is_expected.to respond_to(:default_options) }
         | 
| 47 | 
            +
                  it { is_expected.to respond_to(:default_connect_options) }
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  it { is_expected.to respond_to(:redis) }
         | 
| 50 | 
            +
                  it { is_expected.to respond_to(:set) }
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              describe '#fetch' do
         | 
| 55 | 
            +
                context 'when add 1 object' do
         | 
| 56 | 
            +
                  it 'should return articles' do
         | 
| 57 | 
            +
                    expect { storage.add(user, article) }
         | 
| 58 | 
            +
                      .to change { storage.fetch(user, article).size }.by(1)
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                context "when add #{articles_size} object" do
         | 
| 63 | 
            +
                  it 'should return articles' do
         | 
| 64 | 
            +
                    expect do
         | 
| 65 | 
            +
                      articles.each { |article| storage.add(user, article) }
         | 
| 66 | 
            +
                    end.to change { storage.fetch(user, article).size }.by(articles_size)
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              describe '#add' do
         | 
| 72 | 
            +
                let(:history_key) do
         | 
| 73 | 
            +
                  %(\
         | 
| 74 | 
            +
                    #{user.browser_type}/\
         | 
| 75 | 
            +
                    #{user.browser_id}/\
         | 
| 76 | 
            +
                    #{article.historizable_type}\
         | 
| 77 | 
            +
                  ).delete(' ')
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                context 'when add 1 object' do
         | 
| 81 | 
            +
                  before { storage.add(user, article) }
         | 
| 82 | 
            +
                  it { expect(storage.redis.exists(history_key)).to be(true) }
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              describe '#update' do
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              describe '#clear' do
         | 
| 90 | 
            +
                before(:each) { articles.each { |article| storage.add(user, article) } }
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                it 'should clear 1 historizable' do
         | 
| 93 | 
            +
                  expect { storage.clear(user, article, article) }
         | 
| 94 | 
            +
                    .to change { storage.fetch(user, article).size }.by(-1)
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                it 'should celar all historizables' do
         | 
| 98 | 
            +
                  expect { storage.clear(user, article, all: true) }
         | 
| 99 | 
            +
                    .to change { storage.fetch(user, article).size }.to(0)
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                context 'and add 1 historizable after 6 seconds' do
         | 
| 103 | 
            +
                  before do
         | 
| 104 | 
            +
                    sleep(6)
         | 
| 105 | 
            +
                    storage.add(user, Article.new(100))
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  it 'should celar 5 historizables' do
         | 
| 109 | 
            +
                    expect { storage.clear(user, article, expiration: 5.seconds.ago) }
         | 
| 110 | 
            +
                      .to change { storage.fetch(user, article).size }.to(1)
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              describe '#count' do
         | 
| 116 | 
            +
                before(:each) { articles.each { |article| storage.add(user, article) } }
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                context "when exist #{articles_size} historizable" do
         | 
| 119 | 
            +
                  subject { storage.count(user, article) }
         | 
| 120 | 
            +
                  it { is_expected.to be(articles_size) }
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                context 'and add 1 historizable after 6 seconds' do
         | 
| 124 | 
            +
                  before do
         | 
| 125 | 
            +
                    sleep(6)
         | 
| 126 | 
            +
                    storage.add(user, Article.new(100))
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                  subject { storage.count(user, article, between: Time.now..5.seconds.ago) }
         | 
| 130 | 
            +
                  it { is_expected.to be(1) }
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
              end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
              describe '#interface' do
         | 
| 135 | 
            +
                subject { storage.set }
         | 
| 136 | 
            +
                it { is_expected.to be(Redis::SortedSet) }
         | 
| 137 | 
            +
              end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
              describe '.connect' do
         | 
| 140 | 
            +
              end
         | 
| 141 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'generator_spec'
         | 
| 3 | 
            +
            require 'generator_spec/test_case'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'generators/active_record/migration_generator'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            describe BrowsingHistory::MigrationGenerator, type: :generator do
         | 
| 8 | 
            +
              include GeneratorSpec::TestCase
         | 
| 9 | 
            +
              destination File.expand_path('tmp', __dir__)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              after(:all) { prepare_destination } # cleanup the tmp directory
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              describe 'no options' do
         | 
| 14 | 
            +
                before(:all) do
         | 
| 15 | 
            +
                  prepare_destination
         | 
| 16 | 
            +
                  run_generator
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                it 'generates a migration for creating browsing_histories table' do
         | 
| 20 | 
            +
                  expect(destination_root).to have_structure do
         | 
| 21 | 
            +
                    directory 'db' do
         | 
| 22 | 
            +
                      directory 'migrate' do
         | 
| 23 | 
            +
                        migration 'create_browsing_histories' do
         | 
| 24 | 
            +
                          contains 'class CreateBrowsingHistories'
         | 
| 25 | 
            +
                          contains 'def up'
         | 
| 26 | 
            +
                          contains 'create_table :browsing_histories'
         | 
| 27 | 
            +
                          contains 'def down'
         | 
| 28 | 
            +
                        end
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            ENV['RAILS_ENV'] ||= 'test'
         | 
| 2 | 
            +
            ENV['DB']        ||= 'sqlite'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'pry'
         | 
| 5 | 
            +
            require 'rails/all'
         | 
| 6 | 
            +
            require 'rspec/rails'
         | 
| 7 | 
            +
            require 'database_cleaner'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require 'browsing_history'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            $LOAD_PATH.unshift File.expand_path(__dir__)
         | 
| 12 | 
            +
            $LOAD_PATH.unshift File.expand_path('browsing_history', __dir__)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            require File.expand_path('test_app/config/environment', __dir__)
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            RSpec.configure do |config|
         | 
| 17 | 
            +
              redis = BrowsingHistory::History.storages[:redis].redis
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              config.mock_with :rspec
         | 
| 20 | 
            +
              config.before(:suite) do
         | 
| 21 | 
            +
                DatabaseCleaner[:redis].db = redis.client.id
         | 
| 22 | 
            +
                DatabaseCleaner.strategy = :truncation
         | 
| 23 | 
            +
                DatabaseCleaner.clean_with(:truncation)
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              config.before(:each) do
         | 
| 27 | 
            +
                DatabaseCleaner.start
         | 
| 28 | 
            +
                DatabaseCleaner.clean
         | 
| 29 | 
            +
                redis.flushdb
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              config.after(:each) do
         | 
| 33 | 
            +
                DatabaseCleaner.clean
         | 
| 34 | 
            +
                redis.redis.quit
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            def random_string(length = 8)
         | 
| 39 | 
            +
              (0...length).map { (65 + rand(26)).chr }.join
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            == README
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            This README would normally document whatever steps are necessary to get the
         | 
| 4 | 
            +
            application up and running.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Things you may want to cover:
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            * Ruby version
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            * System dependencies
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            * Configuration
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            * Database creation
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            * Database initialization
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            * How to run the test suite
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            * Services (job queues, cache servers, search engines, etc.)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            * Deployment instructions
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            * ...
         | 
| 25 | 
            +
             | 
| 26 | 
            +
             | 
| 27 | 
            +
            Please feel free to use a different markup language if you do not plan to run
         | 
| 28 | 
            +
            <tt>rake doc:app</tt>.
         | 
| 
            File without changes
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            // This is a manifest file that'll be compiled into application.js, which will include all the files
         | 
| 2 | 
            +
            // listed below.
         | 
| 3 | 
            +
            //
         | 
| 4 | 
            +
            // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
         | 
| 5 | 
            +
            // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
         | 
| 6 | 
            +
            //
         | 
| 7 | 
            +
            // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
         | 
| 8 | 
            +
            // compiled file.
         | 
| 9 | 
            +
            //
         | 
| 10 | 
            +
            // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
         | 
| 11 | 
            +
            // about supported directives.
         | 
| 12 | 
            +
            //
         | 
| 13 | 
            +
            //= require_tree .
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            /*
         | 
| 2 | 
            +
             * This is a manifest file that'll be compiled into application.css, which will include all the files
         | 
| 3 | 
            +
             * listed below.
         | 
| 4 | 
            +
             *
         | 
| 5 | 
            +
             * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
         | 
| 6 | 
            +
             * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
         | 
| 7 | 
            +
             *
         | 
| 8 | 
            +
             * You're free to add application-wide styles to this file and they'll appear at the bottom of the
         | 
| 9 | 
            +
             * compiled file so the styles you add here take precedence over styles defined in any styles
         | 
| 10 | 
            +
             * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
         | 
| 11 | 
            +
             * file per style scope.
         | 
| 12 | 
            +
             *
         | 
| 13 | 
            +
             *= require_tree .
         | 
| 14 | 
            +
             *= require_self
         | 
| 15 | 
            +
             */
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |