thunderer 0.9.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f06c6d86a7fb9ab91ccc695100d1bb38522a09e1
4
- data.tar.gz: ed2ecd2a1364b28d2fa8a7352fc108766c2020e1
3
+ metadata.gz: 67917833bd7bdb8962664293c6659eabda202252
4
+ data.tar.gz: 6aba43d84bda05ded6eec74460b310fbcac968d4
5
5
  SHA512:
6
- metadata.gz: a0eedfda8684dd26ce682ab4746c48c8dfdf5238b1d841dfb1ef933d3c82112bb851285c5b57200c9d33ee678c230ff12094eb53622da9ca80abf27976090317
7
- data.tar.gz: 41b061f20bce2aad21520d7661a8fd8ff3a64d44781a84c80515cd36bf981d213596143a8661547091c5a4895e0c734379691a34ab2f7dbd2a33704e4a0ee07f
6
+ metadata.gz: 95cd9c98d64d08426cf6ec9b7bbc3d37948a4f4417ef4d936afcca591fffdff5b63d4eaeeafb78010b2097efebcabaaec4fe131dd6c2f81fcd00a118950c2bcf
7
+ data.tar.gz: 3ab00dba836fbb7dc3eead43756f15ef0fa935c7d6e613987598b07316bb52ab7bc33e3f2578c7baa0a96aadd38f17cde4a355383f3b1891c947fb77275f41d2
data/.travis.yml CHANGED
@@ -3,7 +3,7 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  - 2.1.0
6
+ - 2.1.2
6
7
  addons:
7
8
  code_climate:
8
- repo_token:
9
- secure: kQfmRpllfvpVjss75SRQKDJ70j72doORRsr8EQyY3cJsoAnwfu8E25/JZ+ZoG25AS+Z6dNYpSH0unrsqzbaSGucFfnQD0TiGINJhs36svHhtrP+JDSxwE38PyKu3tX07TMDxfZ0ig8OfuEuB3RB+E/1/1fy4RrrDn+ZIQN0dIHs=
9
+ repo_token: c277309738ed74f1285b9724c26528315c67b45850f09892970bad596fc15882
data/Gemfile CHANGED
@@ -13,4 +13,5 @@ end
13
13
  group :test do
14
14
  gem 'rspec'
15
15
  gem 'codeclimate-test-reporter', require: nil
16
+ gem 'timecop'
16
17
  end
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  [![Build Status](https://travis-ci.org/chubarovNick/thunderer.svg?branch=master)](https://travis-ci.org/chubarovNick/thunderer)
2
- [![Code Climate](https://codeclimate.com/github/chubarovNick/thunderer.png)](https://codeclimate.com/github/chubarovNick/thunderer)
2
+ [![Code Climate](https://codeclimate.com/github/chubarovNick/thunderer/badges/gpa.svg)](https://codeclimate.com/github/chubarovNick/thunderer)
3
3
  [![Dependency Status](https://gemnasium.com/chubarovNick/thunderer.svg)](https://gemnasium.com/chubarovNick/thunderer)
4
+ [![Test Coverage](https://codeclimate.com/github/chubarovNick/thunderer/badges/coverage.svg)](https://codeclimate.com/github/chubarovNick/thunderer)
4
5
  # Thunderer
5
6
 
6
7
  Thunderer is gem for publishing messages through [Faye](http://faye.jcoglan.com/). It allows you to easily provide real-time updates through an open socket without tying
data/Rakefile CHANGED
@@ -7,6 +7,6 @@ RSpec::Core::RakeTask.new do |t|
7
7
  t.verbose = false
8
8
  end
9
9
 
10
- task default: :spec
10
+ task default: [:spec, "jasmine:ci"]
11
11
  require 'jasmine'
12
12
  load 'jasmine/tasks/jasmine.rake'
@@ -4,8 +4,8 @@ require 'thunderer/controller_additions'
4
4
  module Thunderer
5
5
  class Engine < ::Rails::Engine
6
6
 
7
- initializer "thunderer.config" do
8
- path = Rails.root.join("config/thunderer.yml")
7
+ initializer 'thunderer.config' do
8
+ path = Rails.root.join('config/thunderer.yml')
9
9
  Thunderer.load_config(path, Rails.env) if path.exist?
10
10
  end
11
11
 
@@ -14,7 +14,7 @@ module Thunderer
14
14
  Gem.loaded_specs['faye'].full_gem_path, 'lib')
15
15
  end
16
16
 
17
- initializer "thunderer.view_helpers" do
17
+ initializer 'thunderer.view_helpers' do
18
18
  ActionView::Base.send :include, ViewHelpers
19
19
  end
20
20
 
@@ -5,9 +5,9 @@ module Thunderer
5
5
  # Callback to handle incoming Faye messages. This authenticates both
6
6
  # subscribe and publish calls.
7
7
  def incoming(message, callback)
8
- if message["channel"] == "/meta/subscribe"
8
+ if message['channel'] == '/meta/subscribe'
9
9
  authenticate_subscribe(message)
10
- elsif message["channel"] !~ %r{^/meta/}
10
+ elsif message['channel'] !~ %r{^/meta/}
11
11
  authenticate_publish(message)
12
12
  end
13
13
  callback.call(message)
@@ -17,23 +17,23 @@ module Thunderer
17
17
 
18
18
  # Ensure the subscription signature is correct and that it has not expired.
19
19
  def authenticate_subscribe(message)
20
- subscription = Thunderer.subscription(:channel => message["subscription"], :timestamp => message["ext"]["thunderer_timestamp"])
21
- if message["ext"]["thunderer_signature"] != subscription[:signature]
22
- message["error"] = "Incorrect signature."
23
- elsif Thunderer.signature_expired? message["ext"]["thunderer_timestamp"].to_i
24
- message["error"] = "Signature has expired."
20
+ subscription = Thunderer.subscription(:channel => message['subscription'], :timestamp => message['ext']['thunderer_timestamp'])
21
+ if message['ext']['thunderer_signature'] != subscription[:signature]
22
+ message['error'] = 'Incorrect signature.'
23
+ elsif Thunderer.signature_expired? message['ext']['thunderer_timestamp'].to_i
24
+ message['error'] = 'Signature has expired.'
25
25
  end
26
26
  end
27
27
 
28
28
  # Ensures the secret token is correct before publishing.
29
29
  def authenticate_publish(message)
30
30
  if Thunderer.config[:secret_token].nil?
31
- raise Error, "No secret_token config set, ensure thunderer.yml is loaded properly."
32
- elsif message["ext"]["thunderer_secret_token"] != Thunderer.config[:secret_token]
31
+ raise Error, 'No secret_token config set, ensure thunderer.yml is loaded properly.'
32
+ elsif message['ext']['thunderer_secret_token'] != Thunderer.config[:secret_token]
33
33
 
34
- message["error"] = "Incorrect token."
34
+ message['error'] = 'Incorrect token.'
35
35
  else
36
- message["ext"]["thunderer_secret_token"] = nil
36
+ message['ext']['thunderer_secret_token'] = nil
37
37
  end
38
38
  end
39
39
  end
@@ -16,12 +16,12 @@ module Thunderer
16
16
  @config['use_ssl'] = uri.scheme == 'https'
17
17
  end
18
18
 
19
- def post message
19
+ def post( message )
20
20
  raise ConfigurationError if not_configured?
21
21
 
22
22
  form = build_form
23
23
  form.set_form_data(:message => message.to_json)
24
- protocol.start {|h| h.request(form)}
24
+ protocol.start { |h| h.request(form) }
25
25
  end
26
26
 
27
27
  private
@@ -1,3 +1,3 @@
1
1
  module Thunderer
2
- VERSION = '0.9.1'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -14,7 +14,7 @@ module Thunderer
14
14
  # options.
15
15
  def subscribe_to(channel)
16
16
  subscription = Thunderer.subscription(:channel => channel)
17
- content_tag "script", :type => "text/javascript" do
17
+ content_tag 'script', :type => 'text/javascript' do
18
18
  raw("Thunderer.sign(#{subscription.to_json});")
19
19
  end
20
20
  end
data/lib/thunderer.rb CHANGED
@@ -1,10 +1,10 @@
1
- require "thunderer/version"
1
+ require 'thunderer/version'
2
2
  require 'thunderer/parser'
3
3
  require 'thunderer/messanger'
4
4
  require 'thunderer/faye_extension'
5
- require "digest/sha1"
5
+ require 'digest/sha1'
6
6
  require 'yaml'
7
- require "thunderer/engine" if defined? Rails
7
+ require 'thunderer/engine' if defined? Rails
8
8
 
9
9
  module Thunderer
10
10
  class Error < StandardError; end
@@ -22,7 +22,7 @@ module Thunderer
22
22
  config_yaml = YAML.load_file(filename)[environment]
23
23
  raise ArgumentError, "The #{environment} environment dose not exist" unless config_yaml
24
24
  config_yaml.each { |k,v| config[k.to_sym] = v }
25
- Thunderer::Messanger.configure(config[:server])
25
+ Thunderer::Messanger.configure( config[:local_server_url] || config[:server])
26
26
  @messanger = Thunderer::Messanger
27
27
 
28
28
  end
@@ -32,7 +32,7 @@ module Thunderer
32
32
  end
33
33
 
34
34
  def publish_message(message)
35
- raise Error, "No server specified, ensure private_pub.yml was loaded properly." unless config[:server]
35
+ raise Error, 'No server specified, ensure thunderer.yml was loaded properly.' unless config[:server]
36
36
  url = URI.parse(config[:server])
37
37
  messanger.post(message)
38
38
  end
@@ -0,0 +1,6 @@
1
+ dummy:
2
+ name : Joe
3
+ id : 1
4
+ created_at: 1999-02-19 08:00
5
+ updated_at: 1999-02-19 08:00
6
+
@@ -0,0 +1,9 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ create_table "dummy_classes", :force => true do |t|
4
+ t.string "name"
5
+ t.datetime "created_at", :null => false
6
+ t.datetime "updated_at", :null => false
7
+ end
8
+
9
+ end
@@ -0,0 +1,10 @@
1
+ development:
2
+ server: http://dev.local:9292/faye
3
+ secret_token: DEVELOPMENT_SECRET_TOKEN
4
+ signature_expiration: 600
5
+ production:
6
+ server: http://example.com/faye
7
+ local_server_url: http://localhost:3000
8
+ secret_token: PRODUCTION_SECRET_TOKEN
9
+ signature_expiration: 600
10
+
@@ -1,7 +1,16 @@
1
1
  describe('Thunderer', function () {
2
2
  var doc;
3
3
  beforeEach(function () {
4
- Faye = {};
4
+ Faye = {
5
+ Client: function () {
6
+ return {
7
+ addExtension: function () {
8
+ }
9
+ }
10
+
11
+ }
12
+
13
+ };
5
14
  doc = {};
6
15
  });
7
16
 
@@ -110,8 +119,11 @@ describe('Thunderer', function () {
110
119
  });
111
120
 
112
121
  it("adds fayeCallback when client and server aren't available", function() {
113
- Thunderer.faye("callback");
114
- expect(Thunderer.fayeCallbacks[0]).toEqual("callback");
122
+ Thunderer.faye(function () {
123
+ return 'callback';
124
+ });
125
+ expect(Thunderer.fayeCallbacks[0]).toEqual(jasmine.any(Function));
126
+ expect(Thunderer.fayeCallbacks[0]()).toEqual('callback')
115
127
  });
116
128
 
117
129
 
data/spec/spec_helper.rb CHANGED
@@ -10,20 +10,34 @@ require 'bundler/setup'
10
10
  require 'support/matchers/have_filter'
11
11
  require 'json'
12
12
  require 'faye'
13
+ require 'active_record'
13
14
  require 'support/controller_macros'
15
+ require 'active_record/fixtures'
14
16
  Bundler.setup
15
17
 
16
18
  require 'thunderer'
17
19
  RSpec.configure do |config|
18
- config.treat_symbols_as_metadata_keys_with_true_values = true
20
+ FIXTURES_PATH = File.join(File.dirname(__FILE__), 'fixtures')
21
+
22
+
23
+ ActiveRecord::Base.establish_connection(
24
+ adapter: 'sqlite3',
25
+ database: ':memory:'
26
+ )
19
27
  config.run_all_when_everything_filtered = true
20
28
  config.filter_run :focus
21
-
29
+ config.raise_errors_for_deprecations!
22
30
  config.include ControllerMacros
23
31
 
24
- # Run specs in random order to surface order dependencies. If you find an
25
- # order dependency and want to debug it, you can fix the order by providing
26
- # the seed, which is printed after each run.
27
- # --seed 1234
32
+ dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
33
+ dep.autoload_paths.unshift FIXTURES_PATH
34
+
35
+ ActiveRecord::Base.quietly do
36
+ ActiveRecord::Migration.verbose = false
37
+ load File.join(FIXTURES_PATH, 'schema.rb')
38
+ end
39
+
40
+ ActiveRecord::Fixtures.create_fixtures(FIXTURES_PATH, ActiveRecord::Base.connection.tables)
41
+
28
42
  config.order = 'random'
29
43
  end
@@ -17,32 +17,35 @@ describe Thunderer::ControllerAdditions do
17
17
  let(:controller_class) { MyController }
18
18
 
19
19
  describe '#thunderer_channels' do
20
+ let(:config_file_path) { 'spec/fixtures/thunderer.yml' }
21
+ let(:environment) { 'production' }
22
+ before { Thunderer.load_config(config_file_path, environment) }
20
23
 
21
- it 'should affect channels class variable' do
22
- controller_class.thunderer_channels('hello')
23
- expect(controller_class.channels).to include('hello')
24
- end
25
-
26
- it 'should affect interpolation_object of class' do
27
- controller_class.thunderer_channels(object: 'hello')
28
- expect(controller_class.interpolation_object).to include('hello')
29
- end
24
+ it 'should affect channels class variable' do
25
+ controller_class.thunderer_channels('hello')
26
+ expect(controller_class.channels).to include('hello')
27
+ end
30
28
 
31
- it 'should setup before filter for setting headers' do
32
- expect(controller_class).to have_filters(:before, :add_channels_header)
33
- end
29
+ it 'should affect interpolation_object of class' do
30
+ controller_class.thunderer_channels(object: 'hello')
31
+ expect(controller_class.interpolation_object).to include('hello')
32
+ end
34
33
 
35
- context 'for instance of controller' do
36
- subject(:controller) { controller_class.new }
34
+ it 'should setup before filter for setting headers' do
35
+ expect(controller_class).to have_filters(:before, :add_channels_header)
36
+ end
37
37
 
38
- # it 'should add special header for index response' do
39
- # controller_class.thunderer_channels('hello')
40
- # allow(controller).to receive(:headers)
41
- # controller.send(:add_channels_header)
42
- # end
38
+ context 'for instance of controller' do
39
+ subject(:controller) { controller_class.new }
43
40
 
41
+ it 'should add special header for index response' do
42
+ controller_class.thunderer_channels('hello')
43
+ allow(controller).to receive(:headers) { {} }
44
+ controller.send(:add_channels_header)
44
45
  end
45
46
 
47
+ end
48
+
46
49
  end
47
50
 
48
51
  end
@@ -13,17 +13,41 @@ describe Thunderer::Messanger do
13
13
  expect(messanger.config['use_ssl']).to eq(nil)
14
14
  end
15
15
 
16
- context 'with default config' do
16
+ describe '#post' do
17
+ subject { messanger.post(message) }
18
+
19
+ context 'with default config' do
20
+ let(:message) { double(:message) }
21
+
22
+ specify do
23
+ expect { subject }.to raise_error Thunderer::Messanger::ConfigurationError
24
+ end
17
25
 
18
- it 'should raise error when you try post message' do
19
- message = double(:message)
20
- expect {
21
- messanger.post(message)
22
- }.to raise_error Thunderer::Messanger::ConfigurationError
23
26
  end
24
27
 
28
+ context 'with correct config' do
29
+ before { Thunderer::Messanger.configure('http://localhost:3000') }
30
+ let(:http_form) { double(:form) }
31
+ let(:http) { double(:http) }
32
+ let(:message) { 'Hello world' }
33
+ before { allow(Net::HTTP::Post).to receive(:new).with('/').and_return(http_form) }
34
+ before { allow(Net::HTTP).to receive(:new).with('localhost', 3000).and_return(http) }
35
+ before { allow(http).to receive(:use_ssl=) }
36
+
37
+
38
+ specify do
39
+ expect(http_form).to receive(:set_form_data).with(message: message.to_json)
40
+ expect(http).to receive(:start).and_yield(http)
41
+ expect(http).to receive(:request).with(http_form).and_return(:result)
42
+ expect(subject).to eq(:result)
43
+ end
44
+
45
+ end
46
+
47
+
25
48
  end
26
49
 
50
+
27
51
  describe '#configure' do
28
52
 
29
53
  it 'parse url and set configuration' do
@@ -11,22 +11,22 @@ describe Thunderer::Parser do
11
11
  context 'when channel have no interpolation' do
12
12
  let(:channel) { 'without interpolation string' }
13
13
 
14
- it { should == channel }
14
+ it { is_expected.to eq(channel) }
15
15
  end
16
16
 
17
17
  context 'when channel have one interpolation sequence' do
18
18
  let(:channel) { '/hello/:first' }
19
19
 
20
- it { should include('1') }
20
+ it { is_expected.to include('1') }
21
21
 
22
22
  end
23
23
 
24
24
  context 'when channel have two interpolations' do
25
25
  let(:channel) { '/hello/:first/world/:second' }
26
26
 
27
- it { should include('1') }
27
+ it { is_expected.to include('1') }
28
28
 
29
- it { should include('2') }
29
+ it { is_expected.to include('2') }
30
30
  end
31
31
 
32
32
 
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+ require 'thunderer/publish_changes'
3
+
4
+ class DummyClass < ActiveRecord::Base
5
+ include Thunderer::PublishChanges
6
+ end
7
+
8
+ describe Thunderer::PublishChanges do
9
+ let(:dummy_class) { DummyClass }
10
+ let(:dummy) { DummyClass.new }
11
+
12
+ context 'when notify_client_to_channels with only channel' do
13
+ before do
14
+ dummy_class.notify_client_to_channels('/channel')
15
+ end
16
+
17
+ context 'channels' do
18
+ subject { dummy_class.channels }
19
+
20
+ it { is_expected.to eq(['/channel']) }
21
+
22
+ end
23
+
24
+ context 'callback' do
25
+ before { expect(Thunderer).to receive(:publish_to).with('/channel', dummy) }
26
+ subject { dummy.save }
27
+
28
+ it { is_expected.to eq(true) }
29
+
30
+ end
31
+
32
+ end
33
+
34
+ context 'when notify_client_to_channels message_root' do
35
+ before do
36
+ dummy_class.notify_client_to_channels('/channel', message_root: 'root')
37
+ end
38
+
39
+ context 'channels' do
40
+ subject { dummy_class.channels }
41
+
42
+ it { is_expected.to eq(['/channel']) }
43
+
44
+ end
45
+
46
+ context 'callback' do
47
+ before { expect(Thunderer).to receive(:publish_to).with('/channel', Hash['root', dummy]) }
48
+ subject { dummy.save }
49
+
50
+ it { is_expected.to eq(true) }
51
+
52
+ end
53
+ end
54
+
55
+ context 'when notify_client_to_channels block' do
56
+ let(:dummy) { DummyClass.find(1)}
57
+ before do
58
+ dummy_class.notify_client_to_channels '/channel' do |object|
59
+ {id: object.id}
60
+ end
61
+ end
62
+
63
+ context 'channels' do
64
+ subject { dummy_class.channels }
65
+
66
+ it { is_expected.to eq(['/channel']) }
67
+
68
+ end
69
+
70
+ context 'callback' do
71
+ before { expect(Thunderer).to receive(:publish_to).with('/channel', {id: dummy.id}) }
72
+ subject { dummy.save }
73
+
74
+ it { is_expected.to eq(true) }
75
+
76
+ end
77
+ end
78
+
79
+ end
@@ -2,107 +2,183 @@ require 'spec_helper'
2
2
 
3
3
  describe Thunderer do
4
4
  before { Thunderer.reset_config }
5
+ let(:config_file_path) { 'spec/fixtures/thunderer.yml' }
6
+ let(:environment) { 'production' }
7
+ let(:load_config) { Thunderer.load_config(config_file_path, environment) }
5
8
 
6
- it "defaults server to nil" do
7
- Thunderer.config[:server].should be_nil
8
- end
9
+ describe 'default state' do
10
+ describe '#config' do
11
+ subject { Thunderer.config }
9
12
 
10
- it "defaults signature_expiration to nil" do
11
- Thunderer.config[:signature_expiration].should be_nil
12
- end
13
+ it { is_expected.to eq({}) }
13
14
 
14
- it "defaults subscription timestamp to current time in milliseconds" do
15
- time = Time.now
16
- Time.stub(:now).and_return(time)
17
- Thunderer.subscription[:timestamp].should eq((time.to_f * 1000).round)
15
+ end
18
16
  end
19
17
 
20
- it "loads a simple configuration file via load_config" do
21
- Thunderer.load_config("spec/fixtures/thunderer.yml", "production")
22
- Thunderer.config[:server].should eq("http://example.com/faye")
23
- Thunderer.config[:secret_token].should eq("PRODUCTION_SECRET_TOKEN")
24
- Thunderer.config[:signature_expiration].should eq(600)
25
- end
18
+ describe '#load_config' do
26
19
 
27
- it 'also configure Thunderer::Messanger when load config' do
28
- Thunderer.load_config("spec/fixtures/thunderer.yml", "production")
29
- # expect(Thunderer.messanger).to be_kind_of(Thunderer::Messanger)
30
- expect(Thunderer.messanger.config).not_to be_nil
31
- end
20
+ subject { Thunderer.config }
32
21
 
33
- it "raises an exception if an invalid environment is passed to load_config" do
34
- expect {
35
- Thunderer.load_config("spec/fixtures/thunderer.yml", :test)
36
- }.to raise_error ArgumentError
37
- end
22
+ context 'when config environment was exists' do
23
+ before { load_config }
38
24
 
25
+ it { is_expected.to include(:server => 'http://example.com/faye') }
39
26
 
40
- it "includes channel, server, and custom time in subscription" do
41
- Thunderer.config[:server] = "server"
42
- subscription = Thunderer.subscription(:timestamp => 123, :channel => "hello")
43
- subscription[:timestamp].should eq(123)
44
- subscription[:channel].should eq("hello")
45
- subscription[:server].should eq("server")
46
- end
27
+ it { is_expected.to include(:secret_token => 'PRODUCTION_SECRET_TOKEN') }
47
28
 
48
- it "does a sha1 digest of channel, timestamp, and secret token" do
49
- Thunderer.config[:secret_token] = "token"
50
- subscription = Thunderer.subscription(:timestamp => 123, :channel => "channel")
51
- subscription[:signature].should eq(Digest::SHA1.hexdigest("tokenchannel123"))
52
- end
29
+ it { is_expected.to include(:signature_expiration => 600) }
30
+ end
53
31
 
54
- it "formats a message hash given a channel and a hash" do
55
- Thunderer.config[:secret_token] = "token"
56
- Thunderer.message("chan", :foo => "bar").should eq(
57
- :ext => {:thunderer_secret_token => "token"},
58
- :channel => "chan",
59
- :data => {
60
- :channel => "chan",
61
- :data => {:foo => "bar"}
62
- }
63
- )
64
- end
32
+ context 'when config environment was not exists' do
33
+ let(:environment) { 'test' }
34
+
35
+ specify do
36
+ expect {
37
+ load_config
38
+ }.to raise_error ArgumentError
39
+ end
40
+
41
+ end
42
+
43
+ describe 'Thunderer::Messanger configuration' do
44
+ subject { Thunderer::Messanger.config }
45
+
46
+ it { is_expected.not_to eq({}) }
47
+
48
+ context 'when config have local_server_url' do
49
+ let(:config_file_path) { 'spec/fixtures/thunderer_local_server.yml' }
50
+ let(:environment) { 'production' }
65
51
 
66
- it "publish message as json to server using Net::HTTP" do
67
- message = 'foo'
68
- Thunderer.load_config("spec/fixtures/thunderer.yml", "production")
52
+ before { load_config }
53
+
54
+ it { is_expected.to include('uri'=>URI.parse('http://localhost:3000')) }
55
+
56
+ end
57
+
58
+ end
69
59
 
70
- expect(Thunderer::Messanger).to receive(:post)
71
- Thunderer.publish_message(message)
72
60
  end
73
61
 
74
-
75
- it "raises an exception if no server is specified when calling publish_message" do
76
- lambda {
77
- Thunderer.publish_message("foo")
78
- }.should raise_error(Thunderer::Error)
62
+ describe '#subscription' do
63
+ before { load_config }
64
+ let!(:time_mock) { Time.now }
65
+ before { allow(Time).to receive(:now) { time_mock } }
66
+ before { Thunderer.config[:server] = 'server' }
67
+ subject { Thunderer.subscription }
68
+
69
+ it { is_expected.to include(:timestamp => (time_mock.to_f * 1000).round) }
70
+
71
+ context 'when #subscription pass params' do
72
+ subject { Thunderer.subscription(:timestamp => 123, :channel => 'hello') }
73
+
74
+ it { is_expected.to include(:timestamp => 123) }
75
+ it { is_expected.to include(:channel => 'hello') }
76
+ it { is_expected.to include(:server => 'server') }
77
+ end
78
+
79
+ describe 'signature' do
80
+ before { Thunderer.config[:secret_token] = 'token' }
81
+ subject { Thunderer.subscription(:timestamp => 123, :channel => 'channel') }
82
+
83
+ it { is_expected.to include(:signature => Digest::SHA1.hexdigest('tokenchannel123')) }
84
+
85
+ end
86
+
87
+
79
88
  end
80
89
 
81
- it "publish_to passes message to publish_message call" do
82
- Thunderer.should_receive(:message).with("chan", "foo").and_return("message")
83
- Thunderer.should_receive(:publish_message).with("message").and_return(:result)
84
- Thunderer.publish_to("chan", "foo").should eq(:result)
90
+ describe '#message' do
91
+
92
+ describe 'formatting' do
93
+ let(:secret_token) { 'token' }
94
+ before { Thunderer.config[:secret_token] = secret_token }
95
+
96
+ subject { Thunderer.message('chan', :foo => 'bar') }
97
+
98
+ it do
99
+ expect(subject).to eq(:ext => {:thunderer_secret_token => 'token'},
100
+ :channel => 'chan',
101
+ :data => {
102
+ :channel => 'chan',
103
+ :data => {:foo => 'bar'}
104
+ })
105
+ end
106
+
107
+ end
108
+
85
109
  end
86
110
 
87
- it "has a Faye rack app instance" do
88
- Thunderer.faye_app.should be_kind_of(Faye::RackAdapter)
111
+ describe '#publish_message' do
112
+ let(:message) { 'foo' }
113
+ subject { Thunderer.publish_message(message) }
114
+
115
+ context 'when config are loaded' do
116
+ before { load_config }
117
+
118
+ specify do
119
+ expect(Thunderer::Messanger).to receive(:post)
120
+ subject
121
+ end
122
+ end
123
+
124
+ context 'when config are not loaded' do
125
+ specify do
126
+ expect { subject }.to raise_error(Thunderer::Error)
127
+ end
128
+ end
129
+
130
+
89
131
  end
90
132
 
91
- it "says signature has expired when time passed in is greater than expiration" do
92
- Thunderer.config[:signature_expiration] = 30*60
93
- time = Thunderer.subscription[:timestamp] - 31*60*1000
94
- Thunderer.signature_expired?(time).should be_true
133
+ describe '#publish_to' do
134
+ let(:message) { 'foo' }
135
+ let(:channel) { 'channel' }
136
+ subject { Thunderer.publish_to(channel, message) }
137
+ before do
138
+ allow(Thunderer).to receive(:message).with( channel, message) { 'message' }
139
+ allow(Thunderer).to receive(:publish_message).with('message') { :result }
140
+ end
141
+
142
+ it { is_expected.to eq(:result)}
143
+
144
+
95
145
  end
96
146
 
97
- it "says signature has not expired when time passed in is less than expiration" do
98
- Thunderer.config[:signature_expiration] = 30*60
99
- time = Thunderer.subscription[:timestamp] - 29*60*1000
100
- Thunderer.signature_expired?(time).should be_false
147
+ describe '#faye_app' do
148
+ subject { Thunderer.faye_app }
149
+
150
+ it { is_expected.to be_kind_of(Faye::RackAdapter) }
151
+
101
152
  end
102
153
 
103
- it "says signature has not expired when expiration is nil" do
104
- Thunderer.config[:signature_expiration] = nil
105
- Thunderer.signature_expired?(0).should be_false
154
+
155
+ describe 'signature_expired?' do
156
+ let(:expiration) { 30*60 }
157
+ before { Thunderer.config[:signature_expiration] = expiration }
158
+ subject { Thunderer.signature_expired?(time) }
159
+
160
+ context 'when time greater than expiration ' do
161
+ let(:time) { Thunderer.subscription[:timestamp] - 31*60*1000 }
162
+
163
+ it { is_expected.to eq(true) }
164
+
165
+ end
166
+
167
+ context 'when time less than expiration' do
168
+ let(:time) { Thunderer.subscription[:timestamp] - 29*60*1000 }
169
+
170
+ it { is_expected.to eq(false) }
171
+
172
+ end
173
+
174
+ context 'when expiration is nil' do
175
+ let(:expiration) { nil }
176
+ let(:time) { 0 }
177
+
178
+ it { is_expected.to eq(nil) }
179
+
180
+ end
181
+
106
182
  end
107
183
 
108
184
  end
data/thunderer.gemspec CHANGED
@@ -17,8 +17,9 @@ Gem::Specification.new do |spec|
17
17
 
18
18
  spec.add_runtime_dependency 'activesupport'
19
19
  spec.add_development_dependency 'rails'
20
- spec.add_development_dependency 'rspec', '~> 2.14.1'
20
+ spec.add_development_dependency 'rspec'
21
21
  spec.add_development_dependency 'jasmine'
22
+ spec.add_development_dependency 'sqlite3'
22
23
 
23
24
  spec.files = `git ls-files -z`.split("\x0")
24
25
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thunderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Chubarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-02 00:00:00.000000000 Z
11
+ date: 2014-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 2.14.1
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 2.14.1
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: jasmine
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +151,10 @@ files:
137
151
  - lib/thunderer/publish_changes.rb
138
152
  - lib/thunderer/version.rb
139
153
  - lib/thunderer/view_helpers.rb
154
+ - spec/fixtures/dummy_classes.yml
155
+ - spec/fixtures/schema.rb
140
156
  - spec/fixtures/thunderer.yml
157
+ - spec/fixtures/thunderer_local_server.yml
141
158
  - spec/javascripts/helpers/.gitkeep
142
159
  - spec/javascripts/helpers/jasmine_examples/SpecHelper.js
143
160
  - spec/javascripts/support/jasmine.yml
@@ -179,7 +196,10 @@ signing_key:
179
196
  specification_version: 4
180
197
  summary: pub/sub messaging in Rails application
181
198
  test_files:
199
+ - spec/fixtures/dummy_classes.yml
200
+ - spec/fixtures/schema.rb
182
201
  - spec/fixtures/thunderer.yml
202
+ - spec/fixtures/thunderer_local_server.yml
183
203
  - spec/javascripts/helpers/.gitkeep
184
204
  - spec/javascripts/helpers/jasmine_examples/SpecHelper.js
185
205
  - spec/javascripts/support/jasmine.yml
@@ -195,3 +215,4 @@ test_files:
195
215
  - spec/thunderer/parser_spec.rb
196
216
  - spec/thunderer/publish_changes_spec.rb
197
217
  - spec/thunderer_spec.rb
218
+ has_rdoc: