thunderer 0.9.1 → 1.0.0
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 +4 -4
- data/.travis.yml +2 -2
- data/Gemfile +1 -0
- data/README.md +2 -1
- data/Rakefile +1 -1
- data/lib/thunderer/engine.rb +3 -3
- data/lib/thunderer/faye_extension.rb +11 -11
- data/lib/thunderer/messanger.rb +2 -2
- data/lib/thunderer/version.rb +1 -1
- data/lib/thunderer/view_helpers.rb +1 -1
- data/lib/thunderer.rb +5 -5
- data/spec/fixtures/dummy_classes.yml +6 -0
- data/spec/fixtures/schema.rb +9 -0
- data/spec/fixtures/thunderer_local_server.yml +10 -0
- data/spec/javascripts/thunderer_spec.js +15 -3
- data/spec/spec_helper.rb +20 -6
- data/spec/thunderer/controller_aditions_spec.rb +22 -19
- data/spec/thunderer/messanger_spec.rb +30 -6
- data/spec/thunderer/parser_spec.rb +4 -4
- data/spec/thunderer/publish_changes_spec.rb +79 -0
- data/spec/thunderer_spec.rb +152 -76
- data/thunderer.gemspec +2 -1
- metadata +27 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67917833bd7bdb8962664293c6659eabda202252
|
4
|
+
data.tar.gz: 6aba43d84bda05ded6eec74460b310fbcac968d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
[](https://travis-ci.org/chubarovNick/thunderer)
|
2
|
-
[](https://codeclimate.com/github/chubarovNick/thunderer)
|
3
3
|
[](https://gemnasium.com/chubarovNick/thunderer)
|
4
|
+
[](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
data/lib/thunderer/engine.rb
CHANGED
@@ -4,8 +4,8 @@ require 'thunderer/controller_additions'
|
|
4
4
|
module Thunderer
|
5
5
|
class Engine < ::Rails::Engine
|
6
6
|
|
7
|
-
initializer
|
8
|
-
path = Rails.root.join(
|
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
|
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[
|
8
|
+
if message['channel'] == '/meta/subscribe'
|
9
9
|
authenticate_subscribe(message)
|
10
|
-
elsif message[
|
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[
|
21
|
-
if message[
|
22
|
-
message[
|
23
|
-
elsif Thunderer.signature_expired? message[
|
24
|
-
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.'
|
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,
|
32
|
-
elsif message[
|
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[
|
34
|
+
message['error'] = 'Incorrect token.'
|
35
35
|
else
|
36
|
-
message[
|
36
|
+
message['ext']['thunderer_secret_token'] = nil
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/lib/thunderer/messanger.rb
CHANGED
@@ -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
|
data/lib/thunderer/version.rb
CHANGED
@@ -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
|
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
|
1
|
+
require 'thunderer/version'
|
2
2
|
require 'thunderer/parser'
|
3
3
|
require 'thunderer/messanger'
|
4
4
|
require 'thunderer/faye_extension'
|
5
|
-
require
|
5
|
+
require 'digest/sha1'
|
6
6
|
require 'yaml'
|
7
|
-
require
|
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,
|
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,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(
|
114
|
-
|
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
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
39
|
-
|
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
|
-
|
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 {
|
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 {
|
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 {
|
27
|
+
it { is_expected.to include('1') }
|
28
28
|
|
29
|
-
it {
|
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
|
data/spec/thunderer_spec.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
8
|
-
|
9
|
+
describe 'default state' do
|
10
|
+
describe '#config' do
|
11
|
+
subject { Thunderer.config }
|
9
12
|
|
10
|
-
|
11
|
-
Thunderer.config[:signature_expiration].should be_nil
|
12
|
-
end
|
13
|
+
it { is_expected.to eq({}) }
|
13
14
|
|
14
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
34
|
-
|
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
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
88
|
-
|
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
|
-
|
92
|
-
|
93
|
-
|
94
|
-
Thunderer.
|
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
|
-
|
98
|
-
Thunderer.
|
99
|
-
|
100
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
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'
|
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.
|
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-
|
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:
|
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:
|
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:
|