kono_epp_client 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +2 -0
  3. data/lib/epp/epp_command/check_contacts.rb +17 -0
  4. data/lib/epp/epp_command/create_contact.rb +87 -0
  5. data/lib/epp/epp_command/create_domain.rb +44 -0
  6. data/lib/epp/epp_command/delete_contact.rb +15 -0
  7. data/lib/epp/epp_command/delete_domain.rb +14 -0
  8. data/lib/epp/epp_command/hello.rb +13 -0
  9. data/lib/epp/epp_command/info_contact.rb +15 -0
  10. data/lib/epp/epp_command/info_domain.rb +14 -0
  11. data/lib/epp/epp_command/kono_epp_check_domains.rb +18 -0
  12. data/lib/epp/epp_command/login.rb +79 -0
  13. data/lib/epp/epp_command/logout.rb +10 -0
  14. data/lib/epp/epp_command/poll.rb +16 -0
  15. data/lib/epp/epp_command/transfer_domain.rb +36 -0
  16. data/lib/epp/epp_command/update_contact.rb +115 -0
  17. data/lib/epp/epp_command/update_domain.rb +104 -0
  18. data/lib/epp/epp_command.rb +15 -0
  19. data/lib/epp/exceptions.rb +28 -0
  20. data/lib/epp/server.rb +295 -0
  21. data/lib/epp/transport/http.rb +71 -0
  22. data/lib/epp/transport/tcp.rb +93 -0
  23. data/lib/epp/transport.rb +13 -0
  24. data/lib/kono_epp_client.rb +5 -14
  25. data/lib/require_parameters.rb +14 -0
  26. data/spec/epp/epp_command/kono_epp_check_contacts_spec.rb +25 -0
  27. data/spec/epp/epp_command/kono_epp_check_domains_spec.rb +16 -0
  28. data/spec/epp/epp_command/kono_epp_create_domain_spec.rb +37 -0
  29. data/spec/epp/epp_command/kono_epp_transfer_domain_spec.rb +33 -0
  30. data/spec/epp/epp_command/kono_epp_update_domain_spec.rb +125 -0
  31. data/spec/epp/kono_epp_command_spec.rb +16 -0
  32. data/spec/fixtures/snapshots/kono_epp_check_contacts/_construct.xml.snap +13 -0
  33. data/spec/fixtures/snapshots/kono_epp_check_domains/_construct.xml.snap +11 -0
  34. data/spec/fixtures/snapshots/kono_epp_create_domain/_create.xml.snap +29 -0
  35. data/spec/fixtures/snapshots/kono_epp_transfer_domain/_con_extension_construct.xml.snap +23 -0
  36. data/spec/fixtures/snapshots/kono_epp_transfer_domain/_construct.xml.snap +13 -0
  37. data/spec/fixtures/snapshots/kono_epp_update_domain/_restore_esiste_l'estensione_di_restore.xml.snap +15 -0
  38. data/spec/fixtures/snapshots/kono_epp_update_domain/_update_auth_info_cambia_AUTH_INFO.xml.snap +15 -0
  39. data/spec/fixtures/snapshots/kono_epp_update_domain/_update_auth_info_con_nuovo_registrant_cambia_REGISTRANT.xml.snap +16 -0
  40. data/spec/fixtures/snapshots/kono_epp_update_domain/_update_contacts_cambia_ADMIN_TECH.xml.snap +18 -0
  41. data/spec/fixtures/snapshots/kono_epp_update_domain/_update_nameservers_aggiunge_e_rimuove_ns.xml.snap +28 -0
  42. data/spec/fixtures/snapshots/kono_epp_update_domain/_update_status_cambia_status.xml.snap +16 -0
  43. data/spec/spec_helper.rb +111 -0
  44. data/spec/support/context.rb +15 -0
  45. data/spec/support/matchers.rb +6 -0
  46. data/spec/support/snapshot.rb +20 -0
  47. metadata +157 -6
data/lib/epp/server.rb ADDED
@@ -0,0 +1,295 @@
1
+ module KonoEppClient #:nodoc:
2
+ class Server
3
+ include REXML
4
+ include RequiresParameters
5
+
6
+ require 'nokogiri'
7
+
8
+ attr_accessor :tag, :password, :server, :port, :ssl_version, :old_server, :services, :lang, :extensions, :version, :credit, :timeout
9
+
10
+ # ==== Required Attrbiutes
11
+ #
12
+ # * <tt>:server</tt> - The EPP server to connect to
13
+ # * <tt>:tag</tt> - The tag or username used with <tt><login></tt> requests.
14
+ # * <tt>:password</tt> - The password used with <tt><login></tt> requests.
15
+ #
16
+ # ==== Optional Attributes
17
+ #
18
+ # * <tt>:port</tt> - The EPP standard port is 700. However, you can choose a different port to use.
19
+ # * <tt>:clTRID</tt> - The client transaction identifier is an element that EPP specifies MAY be used to uniquely identify the command to the server. You are responsible for maintaining your own transaction identifier space to ensure uniqueness. Defaults to "ABC-12345"
20
+ # * <tt>:old_server</tt> - Set to true to read and write frames in a way that is compatible with older EPP servers. Default is false.
21
+ # * <tt>:lang</tt> - Set custom language attribute. Default is 'en'.
22
+ # * <tt>:services</tt> - Use custom EPP services in the <login> frame. The defaults use the EPP standard domain, contact and host 1.0 services.
23
+ # * <tt>:extensions</tt> - URLs to custom extensions to standard EPP. Use these to extend the standard EPP (e.g., Nominet uses extensions). Defaults to none.
24
+ # * <tt>:version</tt> - Set the EPP version. Defaults to "1.0".
25
+ # * <tt>:transport</tt> - Type of connection (http or tcp). Default to "tcp"
26
+ # * <tt>:timeout</tt> - Timeou for connections in seconds. Default to "30"
27
+ # * <tt>:ssl_version</tt> - Version of the ssl protocol versione. Default to TLSv1
28
+ # * <tt>:ssl_version</tt> - Version of the ssl protocol versione. Default to TLSv1
29
+ #
30
+ def initialize(attributes = {})
31
+ requires!(attributes, :tag, :password, :server)
32
+
33
+ @tag = attributes[:tag]
34
+ @password = attributes[:password]
35
+ @server = attributes[:server]
36
+ @port = attributes[:port] || 700
37
+ @old_server = attributes[:old_server] || false
38
+ @lang = attributes[:lang] || "en"
39
+ @services = attributes[:services] || ["urn:ietf:params:xml:ns:domain-1.0", "urn:ietf:params:xml:ns:contact-1.0", "urn:ietf:params:xml:ns:host-1.0"]
40
+ @extensions = attributes[:extensions] || []
41
+ @version = attributes[:version] || "1.0"
42
+ @transport = attributes[:transport] || :tcp
43
+ @timeout = attributes[:timeout] || 30
44
+ @ssl_version = attributes[:ssl_version] || :TLSv1
45
+
46
+ @logged_in = false
47
+ end
48
+
49
+ def connect_and_hello
50
+ open_connection
51
+
52
+ hello
53
+ end
54
+
55
+ # Closes the connection to the EPP server.
56
+ def close_connection
57
+ @connection.close
58
+ end
59
+
60
+ # Sends an XML request to the EPP server, and receives an XML response.
61
+ # <tt><login></tt> and <tt><logout></tt> requests are also wrapped
62
+ # around the request, so we can close the socket immediately after
63
+ # the request is made.
64
+ def request( xml )
65
+ # open_connection
66
+
67
+ # @logged_in = true if login
68
+
69
+ begin
70
+ @response = send_request( xml )
71
+ ensure
72
+ if @logged_in && !old_server
73
+ @logged_in = false if logout
74
+ end
75
+ end
76
+
77
+ return @response
78
+ end
79
+
80
+ # Sends a standard login request to the EPP server.
81
+ def login
82
+ login = KonoEppLogin.new( tag, password )
83
+
84
+ # FIXME: Order matters
85
+ login.version = version
86
+ login.lang = lang
87
+
88
+ login.services = services
89
+ login.extensions = extensions
90
+
91
+ send_command( login )
92
+ end
93
+
94
+ def change_password( new_password )
95
+ login = KonoEppLogin.new( tag, password )
96
+
97
+ # FIXME: Order matters
98
+ login.new_password = new_password
99
+
100
+ login.version = version
101
+ login.lang = lang
102
+
103
+ login.services = services
104
+ login.extensions = extensions
105
+
106
+ send_command( login )
107
+ end
108
+
109
+ def logged_in?
110
+ begin
111
+ poll
112
+ rescue
113
+ return false
114
+ end
115
+
116
+ return true
117
+ end
118
+
119
+ # FIXME: Remove command wrappers?
120
+ def hello
121
+ send_request( KonoEppHello.new.to_s )
122
+ end
123
+
124
+ def poll( id = nil )
125
+ poll = KonoEppPoll.new( id ? :ack : :req )
126
+
127
+ poll.ack_id = id if id
128
+
129
+ send_command( poll )
130
+ end
131
+
132
+ def create_contact( options )
133
+ contact = KonoEppCreateContact.new options
134
+ send_command( contact )
135
+ end
136
+
137
+ def check_contacts(ids)
138
+ send_command( KonoEppCheckContacts.new(ids) )
139
+ end
140
+
141
+ def delete_contact( id )
142
+ contact = KonoEppDeleteContact.new id
143
+ send_command( contact )
144
+ end
145
+
146
+ def update_contact( options )
147
+ contact = KonoEppUpdateContact.new options
148
+ send_command( contact )
149
+ end
150
+
151
+ def create_domain( options )
152
+ domain = KonoEppCreateDomain.new options
153
+ send_command( domain )
154
+ end
155
+
156
+ def check_domains( *domains )
157
+ send_command( KonoEppCheckDomains.new *domains )
158
+ end
159
+
160
+ def update_domain( options )
161
+ domain = KonoEppUpdateDomain.new options
162
+ send_command( domain )
163
+ end
164
+
165
+ def delete_domain( name )
166
+ domain = KonoEppDeleteDomain.new name
167
+ send_command( domain )
168
+ end
169
+
170
+ def info_contact( id )
171
+ contact = KonoEppInfoContact.new id
172
+ send_command( contact )
173
+ end
174
+
175
+ def info_domain( name )
176
+ info = KonoEppInfoDomain.new name
177
+ send_command( info )
178
+ end
179
+
180
+ def transfer_domain(name, authinfo, op, extension: nil)
181
+ send_command(KonoEppTransferDomain.new( name, authinfo, op, extension: extension))
182
+ end
183
+
184
+ # Sends a standard logout request to the EPP server.
185
+ def logout
186
+ send_command( KonoEppLogout.new, 1500 )
187
+ end
188
+
189
+ # private
190
+ # Wrapper which sends XML to the server, and receives
191
+ # the response in return.
192
+ def send_request( xml )
193
+ write( xml )
194
+ read
195
+ end
196
+
197
+ def send_command( command, expected_result = 1000..1999 )
198
+ namespaces = { 'extepp' => 'http://www.nic.it/ITNIC-EPP/extepp-2.0',
199
+ 'xmlns' => "urn:ietf:params:xml:ns:epp-1.0" }
200
+
201
+ xml = Nokogiri.XML( send_request( command.to_s ) )
202
+
203
+ # TODO: multiple <response> RFC 3730 §2.6
204
+ result = xml.at_xpath( "/xmlns:epp/xmlns:response[1]/xmlns:result",
205
+ namespaces )
206
+ raise KonoEppErrorResponse.new( :message => 'Malformed response' ) if result.nil?
207
+
208
+ xmlns_code = result.at_xpath( "@code" )
209
+ raise KonoEppErrorResponse.new( :message => 'Malformed response' ) if xmlns_code.nil?
210
+
211
+ response_code = xmlns_code.value.to_i
212
+
213
+ xmlns_msg = result.xpath( "xmlns:msg/text ()",
214
+ namespaces )
215
+ raise KonoEppErrorResponse.new( :message => 'Malformed response' ) if xmlns_msg.empty?
216
+
217
+ result_message = xmlns_msg.text.strip
218
+
219
+ # TODO: value
220
+
221
+ xmlns_ext_reason = result.xpath( "xmlns:extValue/xmlns:reason",
222
+ namespaces)
223
+ result_message += ": #{xmlns_ext_reason.text.strip}" unless xmlns_ext_reason.empty?
224
+
225
+ xmlns_reason_code = result.xpath( "xmlns:extValue/xmlns:value/extepp:reasonCode",
226
+ namespaces )
227
+ reason_code = xmlns_reason_code.text.strip.to_i unless xmlns_reason_code.empty?
228
+
229
+ credit_msg = xml.xpath( "//extepp:credit/text ()",
230
+ namespaces )
231
+ @credit = credit_msg.text.to_f unless credit_msg.empty?
232
+
233
+ if expected_result === response_code
234
+ return xml
235
+ end
236
+
237
+ args = { :xml => xml,
238
+ :response_code => response_code,
239
+ :reason_code => reason_code,
240
+ :message => result_message }
241
+
242
+ case [ response_code, reason_code ]
243
+ when [2200, 6004]
244
+ raise KonoEppAuthenticationPasswordExpired.new( args )
245
+ when [2002, 4015]
246
+ raise KonoEppLoginNeeded.new( args )
247
+ when [2304, 9022]
248
+ raise KonoEppDomainHasStatusCliTransProhibited.new(args)
249
+ when [2304, 9026]
250
+ raise KonoEppDomainHasStatusClientUpdateProhibited.new(args)
251
+ else
252
+ raise KonoEppErrorResponse.new( args )
253
+ end
254
+ end
255
+
256
+ # Establishes the connection to the server. If the connection is
257
+ # established, then this method will call read and return
258
+ # the EPP <tt><greeting></tt> which is sent by the
259
+ # server upon connection.
260
+ def open_connection
261
+ # FIXME il timeout serve solamente nella versione tcp
262
+ # FIXME perchè utilizzare un'istanza di classe? non sarebbe meglio avere un metodo che genera il transport
263
+ # e successivamente viene utilizzato sempre quello?
264
+ Timeout.timeout @timeout do
265
+ case @transport
266
+ when :tcp
267
+ @connection = KonoEppClient::Transport::TcpTransport.new(server, port)
268
+ when :http
269
+ @connection = KonoEppClient::Transport::HttpTransport.new(server, port,
270
+ ssl_version: ssl_version,
271
+ cookie_file: "#{@tag.downcase}.cookies.pstore"
272
+ )
273
+ end
274
+ end
275
+ end
276
+
277
+ # Receive an EPP response from the server. Since the connection is blocking,
278
+ # this method will wait until the connection becomes available for use. If
279
+ # the connection is broken, a SocketError will be raised. Otherwise,
280
+ # it will return a string containing the XML from the server.
281
+ def read
282
+ Timeout.timeout @timeout do
283
+ @connection.read
284
+ end
285
+ end
286
+
287
+ # Send XML to the server. If the socket returns EOF,
288
+ # the connection has closed and a SocketError is raised.
289
+ def write( xml )
290
+ Timeout.timeout @timeout do
291
+ @connection.write( xml )
292
+ end
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,71 @@
1
+ require 'net/http'
2
+
3
+ module KonoEppClient::Transport
4
+ class HttpTransport
5
+ include KonoEppClient::Transport
6
+
7
+ require 'pstore'
8
+
9
+ # @param [String] server
10
+ # @param [Integer] port
11
+ # @param [Symbol] ssl_version -> Versione ssl
12
+ # @param [String] cookie_file -> identifica il nome del file del cookie-store
13
+ def initialize(server, port, ssl_version: :TLSv1, cookie_file: "cookies.pstore")
14
+ @net_http = Net::HTTP.new( server, port )
15
+
16
+ @net_http.use_ssl = true
17
+ @net_http.ssl_version = ssl_version
18
+ @net_http.verify_mode = OpenSSL::SSL::VERIFY_PEER
19
+
20
+ #FIXME: Commented because not work on MacOS (dev machine), is necessary for Linux machine?
21
+ #@net_http.ca_path = '/etc/ssl/certs'
22
+
23
+ # @net_http.set_debug_output $stderr
24
+ #@net_http.set_debug_output File.open( "/tmp/net.log", "a")
25
+
26
+ @store = PStore.new( cookie_file )
27
+ end
28
+
29
+ def read
30
+ #puts @response.body
31
+ @response.body
32
+ end
33
+
34
+ def write( xml )
35
+ @store.transaction do
36
+ cookie_str = '$Version="1"'
37
+ @store[:cookies].each do |c|
38
+ cookie_str += "; #{c[:name]}=#{c[:value]}"
39
+ end if @store[:cookies]
40
+
41
+ header = { "Cookie" => cookie_str }
42
+
43
+ @response = @net_http.post( "/", xml, header )
44
+
45
+ @store[:cookies] = parse_set_cookie( @response["Set-Cookie"] ) if @response["Set-Cookie"]
46
+ end
47
+ end
48
+
49
+ def close
50
+ FileUtils.rm_rf(@store.path)
51
+ end
52
+
53
+ private
54
+ def parse_set_cookie( string )
55
+ cookies = []
56
+
57
+ string.split( "," ).each do |cookie|
58
+ tokens = cookie.split ";"
59
+
60
+ name, value = tokens[0].split( "=", 2 )
61
+ # TODO: complete parsing. Maybe encapsulate the cookie as well.
62
+ cookies << { :name => name, :value => value }
63
+ end
64
+
65
+ return cookies
66
+ end
67
+
68
+ def http_post
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,93 @@
1
+ module KonoEppClient::Transport
2
+ class TcpTransport
3
+ include KonoEppClient::Transport
4
+
5
+ def initialize( server, port )
6
+ @connection = TCPSocket.new( server, port )
7
+ @socket = OpenSSL::SSL::SSLSocket.new( @connection )
8
+
9
+ # Synchronously close the connection & socket
10
+ @socket.sync_close
11
+
12
+ # Connect
13
+ @socket.connect
14
+
15
+ # Get the initial frame
16
+ read
17
+ end
18
+
19
+ def read
20
+ if old_server
21
+ data = ""
22
+ first_char = @socket.read(1)
23
+
24
+ if first_char.nil? and @socket.eof?
25
+ raise SocketError.new("Connection closed by remote server")
26
+ elsif first_char.nil?
27
+ raise SocketError.new("Error reading frame from remote server")
28
+ else
29
+ data << first_char
30
+
31
+ while char = @socket.read(1)
32
+ data << char
33
+
34
+ return data if data =~ %r|<\/epp>\n$|mi # at end
35
+ end
36
+ end
37
+ else
38
+ header = @socket.read(4)
39
+
40
+ if header.nil? and @socket.eof?
41
+ raise SocketError.new("Connection closed by remote server")
42
+ elsif header.nil?
43
+ raise SocketError.new("Error reading frame from remote server")
44
+ else
45
+ unpacked_header = header.unpack("N")
46
+ length = unpacked_header[0]
47
+
48
+ if length < 5
49
+ raise SocketError.new("Got bad frame header length of #{length} bytes from the server")
50
+ else
51
+ response = @socket.read(length - 4)
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def write
58
+ if defined?( @socket ) and @socket.is_a?( OpenSSL::SSL::SSLSocket )
59
+ @socket.close
60
+ @socket = nil
61
+ end
62
+
63
+ if defined?( @connection ) and @connection.is_a?( TCPSocket )
64
+ @connection.close
65
+ @connection = nil
66
+ end
67
+
68
+ return true if @connection.nil? and @socket.nil?
69
+ end
70
+
71
+ def close
72
+ if defined?( @socket ) and @socket.is_a?( OpenSSL::SSL::SSLSocket )
73
+ @socket.close
74
+ @socket = nil
75
+ end
76
+
77
+ if defined?( @connection ) and @connection.is_a?( TCPSocket )
78
+ @connection.close
79
+ @connection = nil
80
+ end
81
+
82
+ return true if @connection.nil? and @socket.nil?
83
+ end
84
+ private
85
+ # Receive an EPP frame from the server. Since the connection is blocking,
86
+ # this method will wait until the connection becomes available for use. If
87
+ # the connection is broken, a SocketError will be raised. Otherwise,
88
+ # it will return a string containing the XML from the server.
89
+ def get_frame
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,13 @@
1
+ module KonoEppClient::Transport
2
+ def read
3
+ raise NotImplemented.new
4
+ end
5
+
6
+ def write
7
+ raise NotImplemented.new
8
+ end
9
+
10
+ def close
11
+ raise NotImplemented.new
12
+ end
13
+ end
@@ -4,7 +4,6 @@ require 'openssl'
4
4
  require 'socket'
5
5
  require 'active_support'
6
6
  require 'rexml/document'
7
- require 'hpricot'
8
7
 
9
8
  # Package files
10
9
  require File.dirname(__FILE__) + '/require_parameters.rb'
@@ -16,19 +15,11 @@ require File.dirname(__FILE__) + '/epp/transport/tcp.rb'
16
15
  require File.dirname(__FILE__) + '/epp/transport/http.rb'
17
16
 
18
17
  require File.dirname(__FILE__) + '/epp/epp_command.rb'
19
- require File.dirname(__FILE__) + '/epp/epp_command/hello.rb'
20
- require File.dirname(__FILE__) + '/epp/epp_command/login.rb'
21
- require File.dirname(__FILE__) + '/epp/epp_command/logout.rb'
22
- require File.dirname(__FILE__) + '/epp/epp_command/poll.rb'
23
- require File.dirname(__FILE__) + '/epp/epp_command/create_contact.rb'
24
- require File.dirname(__FILE__) + '/epp/epp_command/create_domain.rb'
25
- require File.dirname(__FILE__) + '/epp/epp_command/info_contact.rb'
26
- require File.dirname(__FILE__) + '/epp/epp_command/info_domain.rb'
27
- require File.dirname(__FILE__) + '/epp/epp_command/delete_contact.rb'
28
- require File.dirname(__FILE__) + '/epp/epp_command/delete_domain.rb'
29
- require File.dirname(__FILE__) + '/epp/epp_command/transfer_domain.rb'
30
- require File.dirname(__FILE__) + '/epp/epp_command/update_contact.rb'
31
- require File.dirname(__FILE__) + '/epp/epp_command/update_domain.rb'
18
+
19
+ # load di tutti i comandi presenti in epp_command
20
+ Dir.glob(File.dirname(__FILE__) + '/epp/epp_command/*.rb').each do |f|
21
+ require f
22
+ end
32
23
 
33
24
  module KonoEppClient #:nodoc:
34
25
  end
@@ -0,0 +1,14 @@
1
+ module RequiresParameters #:nodoc:
2
+ def requires!(hash, *params)
3
+ params.each do |param|
4
+ if param.is_a?(Array)
5
+ raise ArgumentError.new("Missing required parameter: #{param.first}") unless hash.has_key?(param.first)
6
+
7
+ valid_options = param[1..-1]
8
+ raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(:connector => 'or')}") unless valid_options.include?(hash[param.first])
9
+ else
10
+ raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ RSpec.describe KonoEppCheckContacts do
3
+
4
+ let(:ids){
5
+ ["mm001",
6
+ "mb001",
7
+ "cl001",
8
+ "bb001"]
9
+ }
10
+
11
+ include_context "like epp command"
12
+
13
+ let(:instance) {
14
+ described_class.new(ids)
15
+ }
16
+
17
+ it "construct", snapshot: 'xml' do
18
+ expect(rendered.to_s).to have_tag("epp>command>check>check") do
19
+ ids.each do |t|
20
+ with_tag("id", text: t)
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe KonoEppCheckDomains do
4
+ include_context "like epp command"
5
+
6
+ let(:instance) do
7
+ described_class.new("test.it","wow.it")
8
+ end
9
+
10
+ it "construct", snapshot: "xml" do
11
+ expect(rendered.to_s).to have_tag("epp>command>check>check") do
12
+ with_tag("name", text: "test.it")
13
+ with_tag("name", text: "wow.it")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe KonoEppCreateDomain do
4
+ include_context "like epp command"
5
+
6
+ let(:instance) {
7
+ KonoEppCreateDomain.new(
8
+ {name: 'architest.it',
9
+ period: 1,
10
+ nameservers:
11
+ [["ns.test.it", "192.168.100.10"],
12
+ ["ns2.test.it", "192.168.100.20"],
13
+ ["ns3.foo.com"]],
14
+ # contacts
15
+ registrant: "RRR12",
16
+ admin: "AAAA12",
17
+ tech: "TTT12",
18
+ authinfo: "WWW-test-it"
19
+ }
20
+ )
21
+ }
22
+
23
+ it "create", snapshot: "xml" do
24
+ expect(rendered.to_s).to have_tag("ns")
25
+ expect(rendered.to_s.downcase).to have_tag("hostattr")
26
+ expect(rendered.to_s.downcase).to have_tag("ns hostattr" ) do
27
+ with_tag("hostname",text:"ns2.test.it")
28
+ with_tag("hostaddr",text:"192.168.100.20",with:{ip:"v4"})
29
+ end
30
+ expect(rendered.to_s.downcase).to have_tag("ns hostattr" ) do
31
+ with_tag("hostname",text:"ns.test.it")
32
+ with_tag("hostaddr",text:"192.168.100.10",with:{ip:"v4"})
33
+ end
34
+ expect(rendered.to_s.downcase).not_to have_tag("ns hostaddr", with: {ip: 'v4'},text:"" )
35
+ end
36
+
37
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe KonoEppTransferDomain do
4
+
5
+ include_context "like epp command"
6
+
7
+ let(:instance) do
8
+ described_class.new("test.it", "wee-12-sd", 'request')
9
+ end
10
+
11
+ it "construct", snapshot: 'xml' do
12
+ expect(rendered.to_s).to have_tag("epp>command>transfer", with: {op: "request"}, count: 1) do
13
+ with_tag("transfer>name", text: "test.it")
14
+ with_tag("transfer>authinfo>pw", text: "wee-12-sd")
15
+ end
16
+ end
17
+
18
+ context "con extension" do
19
+
20
+ let(:instance) do
21
+ described_class.new("test.it", "wee-12-sd", 'request',
22
+ extension: {new_registrant: "xx123fd", new_auth_info: "abc-sd934-sd"})
23
+ end
24
+
25
+ it "construct", snapshot: 'xml' do
26
+ expect(rendered.to_s).to have_tag("epp>command>extension>trade>transfertrade") do
27
+ with_tag("newregistrant", text: "xx123fd")
28
+ with_tag("newauthinfo>pw", text: "abc-sd934-sd")
29
+ end
30
+ end
31
+ end
32
+
33
+ end