em-irc 0.0.1 → 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.
@@ -1,5 +1,5 @@
1
1
  module EventMachine
2
2
  module IRC
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
  end
5
5
  end
@@ -0,0 +1,22 @@
1
+ module DslAccessor
2
+ def self.included(base)
3
+ base.extend Macros
4
+ end
5
+
6
+ module Macros
7
+ def dsl_accessor(*keys)
8
+ keys.map(&:to_s).each do |k|
9
+ class_eval <<-ACCESSORS
10
+ attr_writer :#{k}
11
+ def #{k}(v = nil)
12
+ if v
13
+ @#{k} = v
14
+ else
15
+ @#{k}
16
+ end
17
+ end
18
+ ACCESSORS
19
+ end
20
+ end
21
+ end
22
+ end
@@ -19,11 +19,16 @@ end
19
19
 
20
20
  shared_examples_for "integration" do
21
21
  it 'should work' do
22
- dan = client(nick: 'dan')
23
- bob = client(nick: 'bob')
22
+ dan = client
23
+ bob = client
24
+ ace = client
24
25
 
25
- dan.on(:connect) {dan.join('#americano-test')}
26
- bob.on(:connect) {bob.join('#americano-test')}
26
+ dan.on(:connect) {dan.nick('dan')}
27
+ bob.on(:connect) {bob.nick('bob')}
28
+ ace.on(:connect) {ace.nick('bob')}
29
+
30
+ dan.on(:nick) {dan.join('#americano-test')}
31
+ bob.on(:nick) {bob.join('#americano-test')}
27
32
 
28
33
  bob.on(:join) do |who, channel|
29
34
  bob.message(channel, "dan: hello bob")
@@ -31,19 +36,34 @@ shared_examples_for "integration" do
31
36
  # dan.quit
32
37
  end
33
38
 
39
+ dan.on(:message) do |who, channel, message|
40
+ @who = who
41
+ @channel = channel
42
+ @message = message
43
+ end
44
+
34
45
  EM.run {
35
46
  dan.connect
36
- EM::add_timer(2) {bob.connect}
37
- EM::add_timer(5) {EM::stop}
47
+ bob.connect
48
+ ace.connect
49
+ EM::add_timer(2) {EM::stop}
38
50
  }
39
51
 
40
52
  # TODO: matchers for commands
53
+ dan.nick.should == 'dan'
41
54
  dan.history.should =~ /Welcome/
42
55
  dan.history.should =~ /JOIN :#americano-test/
43
- dan.history.should =~ /dan: hello bob/
44
56
 
57
+ @who.should == "bob"
58
+ @channel.should == "#americano-test"
59
+ @message.should == "dan: hello bob"
60
+
61
+ bob.nick.should == 'bob'
45
62
  bob.history.should =~ /Welcome/
46
63
  bob.history.should =~ /JOIN :#americano-test/
64
+
65
+ ace.nick.should == nil
66
+ ace.history.should =~ /Nickname already in use/
47
67
  end
48
68
  end
49
69
 
@@ -51,8 +71,8 @@ end
51
71
  describe EventMachine::IRC::Client, :integration => true do
52
72
  let(:options) do
53
73
  {
54
- host: '127.0.0.1',
55
- port: '16667'
74
+ :host => '127.0.0.1',
75
+ :port => '16667'
56
76
  }.merge(@options || {})
57
77
  end
58
78
 
@@ -71,8 +91,8 @@ describe EventMachine::IRC::Client, :integration => true do
71
91
  before :all do
72
92
  raise "encrypted ircd not on :16697" unless `lsof -i :16697`.chomp.size > 1
73
93
  @options = {
74
- port: '16697',
75
- ssl: true
94
+ :port => '16697',
95
+ :ssl => true
76
96
  }
77
97
  end
78
98
  it_behaves_like "integration"
@@ -26,16 +26,23 @@ describe EventMachine::IRC::Client do
26
26
  subject.should_not be_connected
27
27
  end
28
28
 
29
- it 'should default a nick' do
30
- subject.nick.should_not be_blank
29
+ it 'should have blank nick' do
30
+ subject.nick.should be_blank
31
31
  end
32
32
 
33
- it 'should yield self' do
34
- client = described_class.new do |c|
33
+ it 'should optionally yield self' do
34
+ described_class.new do |c|
35
35
  c.should be_kind_of(described_class)
36
36
  end
37
37
  end
38
38
 
39
+ it 'should optionally instance eval' do
40
+ client = described_class.new do
41
+ host 'stella.net'
42
+ end
43
+ client.host.should == 'stella.net'
44
+ end
45
+
39
46
  it 'should allow a custom logger' do
40
47
  subject.logger = Logger.new(STDOUT)
41
48
  subject.logger = nil
@@ -43,15 +50,15 @@ describe EventMachine::IRC::Client do
43
50
  end
44
51
 
45
52
  context 'connect' do
46
- it 'should create an EM TCP connection with host, port, handler, and self' do
47
- EventMachine.should_receive(:connect).with('irc.net', '9999', EventMachine::IRC::Dispatcher, parent: subject)
53
+ it 'should create an EM TCP connection with host, port, handler, and ssl' do
54
+ EventMachine.should_receive(:connect).with('irc.net', '9999', EventMachine::IRC::Dispatcher, :parent => subject, :ssl => subject.ssl)
48
55
  subject.host = 'irc.net'
49
56
  subject.port = '9999'
50
57
  subject.connect
51
58
  end
52
59
 
53
60
  it 'should be idempotent' do
54
- EventMachine.stub(connect: mock('Connection'))
61
+ EventMachine.stub(:connect => mock('Connection'))
55
62
  EventMachine.should_receive(:connect).exactly(1).times
56
63
  subject.connect
57
64
  subject.connect
@@ -61,17 +68,17 @@ describe EventMachine::IRC::Client do
61
68
  context 'send_data' do
62
69
  before do
63
70
  @connection = mock('Connection')
64
- subject.stub(conn: @connection)
65
- subject.stub(connected?: true)
71
+ subject.stub(:conn => @connection)
72
+ subject.stub(:connected? => true)
66
73
  end
67
74
 
68
75
  it 'should return false if not connected' do
69
- subject.stub(connected?: nil)
76
+ subject.stub(:connected? => nil)
70
77
  subject.send_data("NICK jch").should be_false
71
78
  end
72
79
 
73
80
  it 'should send message to irc server' do
74
- subject.stub(conn: @connection)
81
+ subject.stub(:conn => @connection)
75
82
  @connection.should_receive(:send_data).with("NICK jch\r\n")
76
83
  subject.send_data("NICK jch")
77
84
  end
@@ -79,7 +86,7 @@ describe EventMachine::IRC::Client do
79
86
 
80
87
  context 'ready' do
81
88
  before do
82
- subject.stub(conn: mock.as_null_object)
89
+ subject.stub(:conn => mock.as_null_object)
83
90
  end
84
91
 
85
92
  it 'should call :connect callback' do
@@ -122,48 +129,49 @@ describe EventMachine::IRC::Client do
122
129
  parsed = subject.parse_message('PING :irc.net')
123
130
  parsed[:params] =~ ['irc.net']
124
131
  end
132
+
133
+ it 'should return strings as a single param' do
134
+ parsed = subject.parse_message(":irc.the.net 001 jessie :Welcome to the Internet Relay Network jessie!~jessie@localhost")
135
+ parsed[:params] =~ ['jessie', 'Welcome to the Internet Relay Network jessie!~jessie@localhost']
136
+ end
125
137
  end
126
138
  end
127
139
 
128
140
  context 'receive_data' do
129
- before do
130
- subject.stub(:parse_message).and_return(mock.as_null_object)
131
- subject.stub(:handle_parsed_message).and_return(mock.as_null_object)
132
- end
133
-
134
- it 'should parse messages separated by \r\n' do
135
- data = [
141
+ let(:data) {
142
+ [
136
143
  ":irc.the.net 001 jessie :Welcome to the Internet Relay Network jessie!~jessie@localhost",
137
144
  ":irc.the.net 002 jessie :Your host is irc.the.net, running version ngircd-17.1 (i386/apple/darwin11.2.0)",
138
145
  ":irc.the.net 003 jessie :This server has been started Fri Feb 03 2012 at 14:42:38 (PST)"
139
146
  ].join("\r\n")
147
+ }
148
+ let(:parsed_message) {mock.as_null_object}
149
+
150
+ before do
151
+ subject.stub(:parse_message).and_return(parsed_message)
152
+ subject.stub(:handle_parsed_message)
153
+ end
140
154
 
155
+ it 'should parse messages separated by \r\n' do
141
156
  subject.should_receive(:parse_message).exactly(3).times
142
- subject.should_receive(:handle_parsed_message).exactly(3).times
143
157
  subject.receive_data(data)
144
158
  end
145
159
 
146
160
  it 'should handle parsed messages' do
161
+ subject.should_receive(:handle_parsed_message).exactly(3).times
162
+ subject.receive_data(data)
147
163
  end
148
- end
149
164
 
150
- context 'handle_parsed_message' do
151
- it 'should respond to pings' do
152
- subject.should_receive(:pong).with("irc.net")
153
- subject.handle_parsed_message({prefix: 'irc.net', command: 'PING', params: ['irc.net']})
165
+ it 'should trigger :raw callbacks' do
166
+ subject.should_receive(:trigger).with(:raw, parsed_message).exactly(3).times
167
+ subject.receive_data(data)
154
168
  end
169
+ end
155
170
 
156
- # TODO: do we want a delegate object and callbacks?
157
- # it 'should call optional delegate' do
158
- # subject.stub(delegate: mock('Delegate'))
159
- # subject.delegate.should_receive(:message)
160
- # subject.handle_parsed_message({prefix: 'jessie!jessie@localhost', command: 'PRIVMSG', params: ['#general', 'hello world'])
161
- # end
162
-
163
- it 'should trigger :raw callbacks' do
164
- m = mock('Parsed Response').as_null_object
165
- subject.should_receive(:trigger).with(:raw, m)
166
- subject.handle_parsed_message(m)
171
+ context 'handle_parsed_message' do
172
+ it 'should trigger error for messages 400-599' do
173
+ subject.should_receive(:trigger).with(:error, 'ERR_NICKNAMEINUSE')
174
+ subject.handle_parsed_message(:command => '433', :params => ['ERR_NICKNAMEINUSE'])
167
175
  end
168
176
  end
169
177
 
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ describe EventMachine::IRC::Commands do
4
+ subject {EventMachine::IRC::Client.new}
5
+
6
+ context "nick" do
7
+ it 'should set nick' do
8
+ subject.should_receive(:send_data).with("NICK jch")
9
+ subject.nick('jch')
10
+ end
11
+
12
+ it 'should get nick' do
13
+ subject.instance_eval {@nick = 'jch'}
14
+ subject.nick.should == 'jch'
15
+ end
16
+ end
17
+
18
+ context "join" do
19
+ it 'should join single channel' do
20
+ subject.should_receive(:send_data).with("JOIN #general")
21
+ subject.join("#general")
22
+ end
23
+
24
+ it 'should join multiple channels' do
25
+ subject.should_receive(:send_data).with("JOIN #general,#foo")
26
+ subject.join('#general', '#foo')
27
+ end
28
+
29
+ it 'should join channels with keys' do
30
+ subject.should_receive(:send_data).with("JOIN #foo,&bar fubar,bazly")
31
+ subject.join(['#foo', 'fubar'], ['&bar', 'bazly'])
32
+ end
33
+
34
+ it 'should join channels with and without keys' do
35
+ subject.should_receive(:send_data).with("JOIN #foo,#cat,&bar fubar,dog")
36
+ subject.join(['#foo', 'fubar'], '&bar', ["#cat", "dog"])
37
+ end
38
+
39
+ it 'should leave all currently joined channels' do
40
+ subject.should_receive(:join).with('0')
41
+ subject.join('0')
42
+ end
43
+ end
44
+
45
+ context "part_all" do
46
+ it 'should leave all currently joined channels' do
47
+ subject.should_receive(:join).with('0')
48
+ subject.part_all
49
+ end
50
+ end
51
+
52
+ context "part" do
53
+ it 'should part single' do
54
+ subject.should_receive(:send_data).with('PART #general :Leaving...')
55
+ subject.part('#general')
56
+ end
57
+
58
+ it 'should part single with custom message' do
59
+ subject.should_receive(:send_data).with('PART #general :Goodbye everybody!')
60
+ subject.part('#general', 'Goodbye everybody!')
61
+ end
62
+
63
+ it 'should part multiple' do
64
+ subject.should_receive(:send_data).with('PART #general,#foo :Leaving...')
65
+ subject.part('#general', '#foo')
66
+ end
67
+
68
+ it 'should part multiple with custom message' do
69
+ subject.should_receive(:send_data).with('PART #general,#foo :Goodbye everybody!')
70
+ subject.part('#general', '#foo', 'Goodbye everybody!')
71
+ end
72
+ end
73
+
74
+ context "topic" do
75
+ it 'should get topic' do
76
+ subject.should_receive(:send_data).with("TOPIC #foo")
77
+ subject.topic('#foo')
78
+ end
79
+
80
+ it 'should set topic' do
81
+ subject.should_receive(:send_data).with("TOPIC #foo :awesome channel")
82
+ subject.topic('#foo', "awesome channel")
83
+ end
84
+
85
+ it 'should unset topic' do
86
+ subject.should_receive(:send_data).with("TOPIC #foo :")
87
+ subject.topic('#foo', '')
88
+ end
89
+ end
90
+
91
+ context "names" do
92
+ it 'should list names for a single channel' do
93
+ subject.should_receive(:send_data).with("NAMES #foo")
94
+ subject.names("#foo")
95
+ end
96
+
97
+ it 'should list names for multiple channels' do
98
+ subject.should_receive(:send_data).with("NAMES #foo,&bar")
99
+ subject.names("#foo", "&bar")
100
+ end
101
+
102
+ it 'should list names with a target server' do
103
+ subject.should_receive(:send_data).with("NAMES #foo,&bar irc.net")
104
+ subject.names("#foo", "&bar", :target => 'irc.net')
105
+ end
106
+ end
107
+
108
+ context "list" do
109
+ it 'should list channel and topic' do
110
+ subject.should_receive(:send_data).with("LIST #foo")
111
+ subject.list("#foo")
112
+ end
113
+
114
+ it 'should list channels and topics for multiple channels' do
115
+ subject.should_receive(:send_data).with("LIST #foo,&bar")
116
+ subject.list("#foo", "&bar")
117
+ end
118
+
119
+ it 'should list names with a target server' do
120
+ subject.should_receive(:send_data).with("LIST #foo,&bar irc.net")
121
+ subject.list("#foo", "&bar", :target => 'irc.net')
122
+ end
123
+ end
124
+
125
+ context 'invite' do
126
+ it 'should invite user to a channel' do
127
+ subject.should_receive(:send_data).with("INVITE jch #foo")
128
+ subject.invite("jch", "#foo")
129
+ end
130
+ end
131
+
132
+ context 'kick' do
133
+ it 'should kick user from channel' do
134
+ subject.should_receive(:send_data).with("KICK #general jch")
135
+ subject.kick("#general", "jch")
136
+ end
137
+
138
+ it 'should kick multiple users from channels' do
139
+ subject.should_receive(:send_data).with("KICK #general,&bar jch,wcc")
140
+ subject.kick("#general", "&bar", "jch", "wcc")
141
+ end
142
+
143
+ it 'should raise error if no channels' do
144
+ expect {
145
+ subject.kick('jch')
146
+ }.to raise_error(ArgumentError)
147
+ end
148
+ end
149
+
150
+ context 'whois' do
151
+ it 'should query user' do
152
+ subject.should_receive(:send_data).with("WHOIS jch")
153
+ subject.whois('jch')
154
+ end
155
+
156
+ it 'should query users' do
157
+ subject.should_receive(:send_data).with("WHOIS jch,bar")
158
+ subject.whois('jch', 'bar')
159
+ end
160
+
161
+ it 'should query user from a target server' do
162
+ subject.should_receive(:send_data).with("WHOIS irc.net jch,bar")
163
+ subject.whois('jch', 'bar', :target => 'irc.net')
164
+ end
165
+ end
166
+ end
@@ -2,12 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  shared_examples_for 'dispatcher' do
4
4
  it 'should delegate connection methods to parent' do
5
- parent = Class.new do
6
- attr_accessor :conn
7
- def ssl
8
- $ssl
5
+ module TestServer
6
+ def post_init
7
+ send_data "message"
9
8
  end
9
+ end
10
10
 
11
+ parent = Class.new do
12
+ attr_accessor :conn
11
13
  def receive_data(data)
12
14
  EventMachine::stop_event_loop
13
15
  raise "Didn't get expected message" unless data == 'message'
@@ -16,11 +18,9 @@ shared_examples_for 'dispatcher' do
16
18
  parent.should_receive(:ready)
17
19
  parent.should_receive(:unbind)
18
20
  EventMachine.run {
19
- EventMachine::start_server('127.0.0.1', '198511', described_class, parent: parent)
20
- EventMachine::connect('127.0.0.1', '198511') do |conn|
21
- conn.send_data("message")
22
- end
23
- EventMachine::add_timer(2) {
21
+ EventMachine::start_server('127.0.0.1', '198511', TestServer)
22
+ EventMachine::connect('127.0.0.1', '198511', EventMachine::IRC::Dispatcher, :parent => parent, :ssl => ssl)
23
+ EventMachine::add_timer(3) {
24
24
  EventMachine::stop_event_loop
25
25
  raise "Never reached receive_data or took too long"
26
26
  }
@@ -30,15 +30,15 @@ end
30
30
 
31
31
  describe EventMachine::IRC::Dispatcher do
32
32
  context 'ssl integration' do
33
- before {$ssl = true}
34
- it 'behaves like dispatcher' do
35
- pending "not sure how to test ssl"
36
- end
37
- # it_behaves_like "dispatcher"
33
+ it "how to test ssl?"
34
+ # it_behaves_like "dispatcher" do
35
+ # let(:ssl) {true}
36
+ # end
38
37
  end
39
38
 
40
39
  context 'non-ssl integration' do
41
- before {$ssl = false}
42
- it_behaves_like "dispatcher"
40
+ it_behaves_like "dispatcher" do
41
+ let(:ssl) {false}
42
+ end
43
43
  end
44
44
  end