Merge branch 'master' into registry-790

This commit is contained in:
Artur Beljajev 2018-08-20 21:20:52 +03:00
commit c48cdf68b6
16 changed files with 918 additions and 56 deletions

View file

@ -186,7 +186,7 @@ GEM
thor (~> 0.14)
globalid (0.4.1)
activesupport (>= 4.2.0)
grape (1.0.3)
grape (1.1.0)
activesupport
builder
mustermann-grape (~> 1.0.0)

View file

@ -0,0 +1,57 @@
module Api
module V1
module Registrant
class ContactsController < BaseController
before_action :set_contacts_pool
def index
limit = params[:limit] || 200
offset = params[:offset] || 0
if limit.to_i > 200 || limit.to_i < 1
render(json: { errors: [{ limit: ['parameter is out of range'] }] },
status: :bad_request) && return
end
if offset.to_i.negative?
render(json: { errors: [{ offset: ['parameter is out of range'] }] },
status: :bad_request) && return
end
@contacts = @contacts_pool.limit(limit).offset(offset)
render json: @contacts
end
def show
@contact = @contacts_pool.find_by(uuid: params[:uuid])
if @contact
render json: @contact
else
render json: { errors: [{ base: ['Contact not found'] }] }, status: :not_found
end
end
private
def set_contacts_pool
country_code, ident = current_user.registrant_ident.to_s.split '-'
associated_domain_ids = begin
BusinessRegistryCache.fetch_by_ident_and_cc(ident, country_code).associated_domain_ids
end
available_contacts_ids = begin
DomainContact.where(domain_id: associated_domain_ids).pluck(:contact_id) |
Domain.where(id: associated_domain_ids).pluck(:registrant_id)
end
@contacts_pool = Contact.where(id: available_contacts_ids)
rescue Soap::Arireg::NotAvailableError => error
Rails.logger.fatal("[EXCEPTION] #{error}")
render json: { errors: [{ base: ['Business Registry not available'] }] },
status: :service_unavailable and return
end
end
end
end
end

View file

@ -1,5 +1,3 @@
require 'rails5_api_controller_backport'
module Api
module V1
module Registrant

View file

@ -10,12 +10,12 @@ class Registrar
@deposit = Deposit.new(deposit_params.merge(registrar: current_user.registrar))
@invoice = @deposit.issue_prepayment_invoice
if @invoice&.persisted?
if @invoice
flash[:notice] = t(:please_pay_the_following_invoice)
redirect_to [:registrar, @invoice]
else
flash.now[:alert] = t(:failed_to_create_record)
render 'new'
flash[:alert] = @deposit.errors.full_messages.join(', ')
redirect_to new_registrar_deposit_path
end
end

View file

@ -4,13 +4,17 @@ class Deposit
extend ActiveModel::Naming
include DisableHtml5Validation
attr_accessor :amount, :description, :registrar, :registrar_id
attr_accessor :description, :registrar, :registrar_id
attr_writer :amount
validates :amount, :registrar, presence: true
validate :validate_amount
def validate_amount
return if BigDecimal.new(amount) >= Setting.minimum_deposit
errors.add(:amount, I18n.t(:is_too_small_minimum_deposit_is, amount: Setting.minimum_deposit, currency: 'EUR'))
minimum_allowed_amount = [0.01, Setting.minimum_deposit].max
return if amount >= minimum_allowed_amount
errors.add(:amount, I18n.t(:is_too_small_minimum_deposit_is, amount: minimum_allowed_amount,
currency: 'EUR'))
end
def initialize(attributes = {})
@ -24,10 +28,12 @@ class Deposit
end
def amount
BigDecimal.new(@amount.to_s.sub(/,/, '.'))
return BigDecimal('0.0') if @amount.blank?
BigDecimal(@amount.to_s.tr(',', '.'), 10)
end
def issue_prepayment_invoice
valid? && registrar.issue_prepayment_invoice(amount, description)
return unless valid?
registrar.issue_prepayment_invoice(amount, description)
end
end

View file

@ -23,7 +23,8 @@ Rails.application.routes.draw do
namespace :registrant do
post 'auth/eid', to: 'auth#eid'
resources :domains, only: [:index, :show], param: :uuid
resources :domains, only: %i[index show], param: :uuid
resources :contacts, only: %i[index show], param: :uuid
end
end
end

11
doc/registrant-api.md Normal file
View file

@ -0,0 +1,11 @@
# Registrant API integration specification
Test API endpoint: TBA
Production API endpoint: TBA
Main communication specification through Registrant API:
[Authentication](registrant-api/v1/authentication.md)
[Domains](registrant-api/v1/domain.md)
[Domain Lock](registrant-api/v1/domain_lock.md)
[Contacts](registrant-api/v1/contact.md)

View file

@ -0,0 +1,109 @@
# Authentication
## Authenticating with mobileID or ID-card
For specified partners the API allows for use of data from mobile ID for
authentication. API client should perform authentication with eID according to
the approriate documentation, and then pass on values from the webserver's
certificate to the API server.
## POST /api/v1/registrant/auth/eid
Returns a bearer token to be used for further API requests. Tokens are valid for 2 hours since their creation.
#### Paramaters
Values in brackets represent values that come from the id card certificate.
| Field name | Required | Type | Allowed values | Description |
| ----------------- | -------- | ---- | -------------- | ----------- |
| ident | true | String | | Identity code of the user (`serialNumber`) |
| first_name | true | String | | Name of the customer (`GN`) |
| last_name | true | String | | Name of the customer (`SN`) |
#### Request
```
POST /api/v1/auth/token HTTP/1.1
Accept: application/json
Content-type: application/json
{
"ident": "30110100103",
"first_name": "Jan",
"last_name": "Tamm",
}
```
#### Response
```
HTTP/1.1 201
Content-Type: application.json
{
"access_token": "<SOME TOKEN>",
"expires_at": "2018-07-13 11:30:51 UTC",
"type": "Bearer"
}
```
## POST /api/v1/auth/username -- NOT IMPLEMENTED
#### Paramaters
Values in brackets represent values that come from the id card certificate
| Field name | Required | Type | Allowed values | Description |
| ----------------- | -------- | ---- | -------------- | ----------- |
| username | true | String | Username as provided by the user | |
| password | true | String | Password as provided by the user | |
#### Request
```
POST /api/v1/auth/token HTTP/1.1
Accept: application/json
Content-type: application/json
```
#### Response
```
HTTP/1.1 201
Content-Type: application.json
{
"access_token": "<SOME TOKEN>",
"expires_at": "2018-07-13 11:30:51 UTC",
"type": "Bearer"
}
```
## Implementation notes:
We do not need to store the session data at all, instead we can levarage AES encryption and use
Rails secret as the key. General approximation:
```ruby
class AuthenticationToken
def initialize(secret = Rails.application.config.secret_key_base, values = {})
end
def create_token_hash
data = values.to_s
cipher = OpenSSL::Cipher::AES.new(256, :CBC)
cipher.encrypt
encrypted = cipher.update(data) + cipher.final
base64_encoded = Base64.encode64(encrypted)
{
token: base64_encoded,
expires_in = values[:expires_in]
type: "Bearer"
}
end
end
```

View file

@ -0,0 +1,194 @@
## GET /api/v1/registrant/contacts
Returns contacts of the current registrar.
#### Parameters
| Field name | Required | Type | Allowed values | Description |
| ---------- | -------- | ---- | -------------- | ----------- |
| limit | false | Integer | [1..200] | How many contacts to show |
| offset | false | Integer | | Contact number to start at |
#### Request
```
GET /api/v1/registrant/contacts?limit=1 HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response
```
HTTP/1.1 200
Content-Type: application/json
{
"contacts": [
{
"uuid": "84c62f3d-e56f-40fa-9ca4-dc0137778949",
"domain_names": ["example.com"],
"code": "REGISTRAR2:SH022086480",
"phone": "+372.12345678",
"email": "hoyt@deckowbechtelar.net",
"fax": null,
"created_at": "2015-09-09T09:11:14.130Z",
"updated_at": "2015-09-09T09:11:14.130Z",
"ident": "37605030299",
"ident_type": "priv",
"auth_info": "password",
"name": "Karson Kessler0",
"org_name": null,
"registrar_id": 2,
"creator_str": null,
"updator_str": null,
"ident_country_code": "EE",
"city": "Tallinn",
"street": "Short street 11",
"zip": "11111",
"country_code": "EE",
"state": null,
"legacy_id": null,
"statuses": [
"ok"
],
"status_notes": {
}
}
],
"total_number_of_records": 2
}
```
## GET /api/v1/registrant/contacts/$UUID
Returns contacts of the current registrar.
#### Request
```
GET /api/v1/registrant/contacts/84c62f3d-e56f-40fa-9ca4-dc0137778949 HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response
```
HTTP/1.1 200
Content-Type: application/json
{
"uuid": "84c62f3d-e56f-40fa-9ca4-dc0137778949",
"domain_names": ["example.com"],
"code": "REGISTRAR2:SH022086480",
"phone": "+372.12345678",
"email": "hoyt@deckowbechtelar.net",
"fax": null,
"created_at": "2015-09-09T09:11:14.130Z",
"updated_at": "2015-09-09T09:11:14.130Z",
"ident": "37605030299",
"ident_type": "priv",
"auth_info": "password",
"name": "Karson Kessler0",
"org_name": null,
"registrar_id": 2,
"creator_str": null,
"updator_str": null,
"ident_country_code": "EE",
"city": "Tallinn",
"street": "Short street 11",
"zip": "11111",
"country_code": "EE",
"state": null,
"legacy_id": null,
"statuses": [
"ok"
],
"status_notes": {}
}
```
## PATCH /api/v1/registrant/contacts/$UUID
Update contact details for a contact.
#### Parameters
| Field name | Required | Type | Allowed values | Description |
| ---- | --- | --- | --- | --- |
| email | false | String | | New email address |
| phone | false | String | | New phone number |
| fax | false | String | | New fax number |
| city | false | String | | New city name |
| street | false | String | | New street name |
| zip | false | String | | New zip code |
| country_code | false | String | | New country code in 2 letter format ('EE', 'LV') |
| state | false | String | | New state name |
#### Request
```
PATCH /api/v1/registrant/contacts/84c62f3d-e56f-40fa-9ca4-dc0137778949 HTTP/1.1
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Accept: application/json
Content-type: application/json
{
"email": "foo@bar.baz",
"phone": "+372.12345671",
"fax": "+372.12345672",
"city": "New City",
"street": "Main Street 123",
"zip": "22222",
"country_code": "LV",
"state": "New state"
}
```
#### Response on success
```
HTTP/1.1 200
Content-Type: application.json
{
"uuid": "84c62f3d-e56f-40fa-9ca4-dc0137778949",
"domain_names": ["example.com"],
"code": "REGISTRAR2:SH022086480",
"phone": "+372.12345671",
"email": "foo@bar.baz",
"fax": "+372.12345672",
"created_at": "2015-09-09T09:11:14.130Z",
"updated_at": "2018-09-09T09:11:14.130Z",
"ident": "37605030299",
"ident_type": "priv",
"auth_info": "password",
"name": "Karson Kessler0",
"org_name": null,
"registrar_id": 2,
"creator_str": null,
"updator_str": null,
"ident_country_code": "EE",
"city": "New City",
"street": "Main Street 123",
"zip": "22222",
"country_code": "LV",
"state": "New state"
"legacy_id": null,
"statuses": [
"ok"
],
"status_notes": {}
}
```
### Response on failure
```
HTTP/1.1 400
Content-Type: application.json
{
"errors": [
{ "phone": "Phone nr is invalid" }
]
}
```

View file

@ -0,0 +1,161 @@
# Domain related actions
## GET /api/v1/registrant/domains
Returns domains of the current registrant.
#### Parameters
| Field name | Required | Type | Allowed values | Description |
| ---------- | -------- | ---- | -------------- | ----------- |
| limit | false | Integer | [1..200] | How many domains to show |
| offset | false | Integer | | Domain number to start at |
| details | false | String | ["true", "false"] | Whether to include details |
#### Request
```
GET api/v1/registrant/domains?limit=1&details=true HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response
```
HTTP/1.1 200
Content-Type: application/json
{
"domains": [
{
"uuid": "98d1083a-8863-4153-93e4-caee4a013535",
"name": "domain0.ee",
"registrar_id": 2,
"registered_at": "2015-09-09T09:11:14.861Z",
"status": null,
"valid_from": "2015-09-09T09:11:14.861Z",
"valid_to": "2016-09-09T09:11:14.861Z",
"registrant_id": 1,
"transfer_code": "98oiewslkfkd",
"created_at": "2015-09-09T09:11:14.861Z",
"updated_at": "2015-09-09T09:11:14.860Z",
"name_dirty": "domain0.ee",
"name_puny": "domain0.ee",
"period": 1,
"period_unit": "y",
"creator_str": null,
"updator_str": null,
"legacy_id": null,
"legacy_registrar_id": null,
"legacy_registrant_id": null,
"outzone_at": "2016-09-24T09:11:14.861Z",
"delete_at": "2016-10-24T09:11:14.861Z",
"registrant_verification_asked_at": null,
"registrant_verification_token": null,
"pending_json": {
},
"force_delete_at": null,
"statuses": [
"ok"
],
"reserved": false,
"status_notes": {
},
"statuses_backup": [
]
}
],
"total_number_of_records": 2
}
```
## GET api/v1/registrant/domains
Returns domain names with offset.
#### Request
```
GET api/v1/registrant/domains?offset=1 HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response
```
HTTP/1.1 200
Content-Type: application/json
{
"domains": [
"domain1.ee"
],
"total_number_of_records": 2
}
```
## GET api/v1/registrant/domains/$UUID
Returns a single domain object.
#### Request
```
GET api/v1/registrant/domains/98d1083a-8863-4153-93e4-caee4a013535 HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response for success
```
HTTP/1.1 200
Content-Type: application/json
{
"uuid": "98d1083a-8863-4153-93e4-caee4a013535",
"name": "domain0.ee",
"registrar_id": 2,
"registered_at": "2015-09-09T09:11:14.861Z",
"status": null,
"valid_from": "2015-09-09T09:11:14.861Z",
"valid_to": "2016-09-09T09:11:14.861Z",
"registrant_id": 1,
"transfer_code": "98oiewslkfkd",
"created_at": "2015-09-09T09:11:14.861Z",
"updated_at": "2015-09-09T09:11:14.860Z",
"name_dirty": "domain0.ee",
"name_puny": "domain0.ee",
"period": 1,
"period_unit": "y",
"creator_str": null,
"updator_str": null,
"legacy_id": null,
"legacy_registrar_id": null,
"legacy_registrant_id": null,
"outzone_at": "2016-09-24T09:11:14.861Z",
"delete_at": "2016-10-24T09:11:14.861Z",
"registrant_verification_asked_at": null,
"registrant_verification_token": null,
"pending_json": {},
"force_delete_at": null,
"statuses": [
"ok"
],
"reserved": false,
"status_notes": {},
"statuses_backup": []
}
```
#### Response for failure
```
HTTP/1.1 404
Content-Type: application/json
{ "errors": ["Domain not found"] }
```

View file

@ -0,0 +1,163 @@
# Domain locks
## POST api/v1/registrant/domains/$UUID/registry_lock
Set a registry lock on a domain.
#### Request
```
POST api/v1/registrant/domains/98d1083a-8863-4153-93e4-caee4a013535/registry_lock HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response for success
```
HTTP/1.1 200
Content-Type: application/json
{
"uuid": "98d1083a-8863-4153-93e4-caee4a013535",
"name": "domain0.ee",
"registrar_id": 2,
"registered_at": "2015-09-09T09:11:14.861Z",
"status": null,
"valid_from": "2015-09-09T09:11:14.861Z",
"valid_to": "2016-09-09T09:11:14.861Z",
"registrant_id": 1,
"transfer_code": "98oiewslkfkd",
"created_at": "2015-09-09T09:11:14.861Z",
"updated_at": "2015-09-09T09:11:14.860Z",
"name_dirty": "domain0.ee",
"name_puny": "domain0.ee",
"period": 1,
"period_unit": "y",
"creator_str": null,
"updator_str": null,
"legacy_id": null,
"legacy_registrar_id": null,
"legacy_registrant_id": null,
"outzone_at": "2016-09-24T09:11:14.861Z",
"delete_at": "2016-10-24T09:11:14.861Z",
"registrant_verification_asked_at": null,
"registrant_verification_token": null,
"pending_json": {},
"force_delete_at": null,
"statuses": [
"serverUpdateProhibited",
"serverDeleteProhibited",
"serverTransferProhibited"
],
"reserved": false,
"status_notes": {},
"statuses_backup": []
}
```
#### Response for failure
```
HTTP/1.1 400
Content-Type: application/json
{
"errors": [
{ "base": "domain cannot be locked" }
]
}
```
```
HTTP/1.1 404
Content-Type: application/json
{
"errors": [
{ "base": "domain does not exist" }
]
}
```
## DELETE api/v1/registrant/domains/$UUID/registry_lock
Remove a registry lock.
#### Request
```
DELETE api/v1/registrant/domains/98d1083a-8863-4153-93e4-caee4a013535/registry_lock HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response for success
```
HTTP/1.1 200
Content-Type: application/json
{
"uuid": "98d1083a-8863-4153-93e4-caee4a013535",
"name": "domain0.ee",
"registrar_id": 2,
"registered_at": "2015-09-09T09:11:14.861Z",
"status": null,
"valid_from": "2015-09-09T09:11:14.861Z",
"valid_to": "2016-09-09T09:11:14.861Z",
"registrant_id": 1,
"transfer_code": "98oiewslkfkd",
"created_at": "2015-09-09T09:11:14.861Z",
"updated_at": "2015-09-09T09:11:14.860Z",
"name_dirty": "domain0.ee",
"name_puny": "domain0.ee",
"period": 1,
"period_unit": "y",
"creator_str": null,
"updator_str": null,
"legacy_id": null,
"legacy_registrar_id": null,
"legacy_registrant_id": null,
"outzone_at": "2016-09-24T09:11:14.861Z",
"delete_at": "2016-10-24T09:11:14.861Z",
"registrant_verification_asked_at": null,
"registrant_verification_token": null,
"pending_json": {},
"force_delete_at": null,
"statuses": [
"ok"
],
"reserved": false,
"status_notes": {},
"statuses_backup": []
}
```
#### Response for failure
```
HTTP/1.1 400
Content-Type: application/json
{
"errors": [
{ "base": "domain cannot be unlocked" }
]
}
```
```
HTTP/1.1 404
Content-Type: application/json
{
"errors": [
{ "base": "domain does not exist" }
]
}
```

View file

@ -1,39 +0,0 @@
require 'rails_helper'
describe Deposit do
context 'with invalid attribute' do
before :all do
@deposit = Deposit.new
end
it 'should not be valid' do
@deposit.valid?
@deposit.errors.full_messages.should match_array([
"Registrar is missing"
])
end
it 'should have 0 amount' do
@deposit.amount.should == 0
end
it 'should not be presisted' do
@deposit.persisted?.should == false
end
it 'should replace comma with point for 0' do
@deposit.amount = '0,0'
@deposit.amount.should == 0.0
end
it 'should replace comma with points' do
@deposit.amount = '10,11'
@deposit.amount.should == 10.11
end
it 'should work with float as well' do
@deposit.amount = 0.123
@deposit.amount.should == 0.123
end
end
end

View file

@ -0,0 +1,117 @@
require 'test_helper'
require 'auth_token/auth_token_creator'
class RegistrantApiContactsTest < ApplicationIntegrationTest
def setup
super
@original_registry_time = Setting.days_to_keep_business_registry_cache
Setting.days_to_keep_business_registry_cache = 1
travel_to Time.zone.parse('2010-07-05')
@user = users(:registrant)
@auth_headers = { 'HTTP_AUTHORIZATION' => auth_token }
end
def teardown
super
Setting.days_to_keep_business_registry_cache = @original_registry_time
travel_back
end
def test_root_returns_domain_list
get '/api/v1/registrant/contacts', {}, @auth_headers
assert_equal(200, response.status)
json_body = JSON.parse(response.body, symbolize_names: true)
assert_equal(5, json_body.count)
array_of_contact_codes = json_body.map { |x| x[:code] }
assert(array_of_contact_codes.include?('william-001'))
assert(array_of_contact_codes.include?('jane-001'))
end
def test_root_accepts_limit_and_offset_parameters
get '/api/v1/registrant/contacts', { 'limit' => 1, 'offset' => 0 }, @auth_headers
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal(200, response.status)
assert_equal(1, response_json.count)
get '/api/v1/registrant/contacts', {}, @auth_headers
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal(5, response_json.count)
end
def test_get_contact_details_by_uuid
get '/api/v1/registrant/contacts/0aa54704-d6f7-4ca9-b8ca-2827d9a4e4eb', {}, @auth_headers
assert_equal(200, response.status)
contact = JSON.parse(response.body, symbolize_names: true)
assert_equal('william@inbox.test', contact[:email])
end
def test_root_returns_503_when_business_registry_is_not_available
raise_not_available = -> (a, b) { raise Soap::Arireg::NotAvailableError.new({}) }
BusinessRegistryCache.stub :fetch_by_ident_and_cc, raise_not_available do
get '/api/v1/registrant/contacts', {}, @auth_headers
assert_equal(503, response.status)
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal({ errors: [base: ['Business Registry not available']] }, response_json)
end
end
def test_get_contact_details_by_uuid_returns_404_for_non_existent_contact
get '/api/v1/registrant/contacts/nonexistent-uuid', {}, @auth_headers
assert_equal(404, response.status)
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal({ errors: [{ base: ['Contact not found'] }] }, response_json)
end
def test_root_does_not_accept_limit_higher_than_200
get '/api/v1/registrant/contacts', { 'limit' => 400, 'offset' => 0 }, @auth_headers
assert_equal(400, response.status)
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal({ errors: [{ limit: ['parameter is out of range'] }] }, response_json)
end
def test_root_does_not_accept_offset_lower_than_0
get '/api/v1/registrant/contacts', { 'limit' => 200, 'offset' => "-10" }, @auth_headers
assert_equal(400, response.status)
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal({ errors: [{ offset: ['parameter is out of range'] }] }, response_json)
end
def test_root_returns_401_without_authorization
get '/api/v1/registrant/contacts', {}, {}
assert_equal(401, response.status)
json_body = JSON.parse(response.body, symbolize_names: true)
assert_equal({ errors: [base: ['Not authorized']] }, json_body)
end
def test_details_returns_401_without_authorization
get '/api/v1/registrant/contacts/c0a191d5-3793-4f0b-8f85-491612d0293e', {}, {}
assert_equal(401, response.status)
json_body = JSON.parse(response.body, symbolize_names: true)
assert_equal({ errors: [base: ['Not authorized']] }, json_body)
end
def test_details_returns_404_for_non_existent_contact
get '/api/v1/registrant/contacts/some-random-uuid', {}, @auth_headers
assert_equal(404, response.status)
json_body = JSON.parse(response.body, symbolize_names: true)
assert_equal({ errors: [base: ['Contact not found']] }, json_body)
end
private
def auth_token
token_creator = AuthTokenCreator.create_with_defaults(@user)
hash = token_creator.token_in_hash
"Bearer #{hash[:access_token]}"
end
end

View file

@ -0,0 +1,59 @@
require 'test_helper'
class DepositTest < ActiveSupport::TestCase
def setup
super
@deposit = Deposit.new(registrar: registrars(:bestnames))
@minimum_deposit = Setting.minimum_deposit
Setting.minimum_deposit = 1.00
end
def teardown
super
Setting.minimum_deposit = @minimum_deposit
end
def test_validate_amount_cannot_be_lower_than_0_01
Setting.minimum_deposit = 0.0
@deposit.amount = -10
refute(@deposit.valid?)
assert(@deposit.errors.full_messages.include?("Amount is too small. Minimum deposit is 0.01 EUR"))
end
def test_validate_amount_cannot_be_lower_than_minimum_deposit
@deposit.amount = 0.10
refute(@deposit.valid?)
assert(@deposit.errors.full_messages.include?("Amount is too small. Minimum deposit is 1.0 EUR"))
end
def test_registrar_must_be_set
deposit = Deposit.new(amount: 120)
refute(deposit.valid?)
assert(deposit.errors.full_messages.include?("Registrar is missing"))
end
def test_amount_is_converted_from_string
@deposit.amount = "12.00"
assert_equal(BigDecimal.new("12.00"), @deposit.amount)
@deposit.amount = "12,11"
assert_equal(BigDecimal.new("12.11"), @deposit.amount)
end
def test_amount_is_converted_from_float
@deposit.amount = 12.0044
assert_equal(BigDecimal.new("12.0044"), @deposit.amount)
@deposit.amount = 12.0144
assert_equal(BigDecimal.new("12.0144"), @deposit.amount)
end
def test_amount_is_converted_from_nil
@deposit.amount = nil
assert_equal(BigDecimal.new("0.00"), @deposit.amount)
end
end

View file

@ -29,11 +29,10 @@ class NewInvoiceTest < ApplicationSystemTestCase
assert_text 'Pay invoice'
end
# This test case should fail once issue #651 gets fixed
def test_create_new_invoice_with_amount_0_goes_through
def test_create_new_invoice_with_comma_in_number
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '0.00'
fill_in 'Amount', with: '200,00'
fill_in 'Description', with: 'My first invoice'
assert_difference 'Invoice.count', 1 do
@ -42,7 +41,33 @@ class NewInvoiceTest < ApplicationSystemTestCase
assert_text 'Please pay the following invoice'
assert_text 'Invoice no. 131050'
assert_text 'Subtotal 0,00 €'
assert_text 'Subtotal 200,00 €'
assert_text 'Pay invoice'
end
def test_create_new_invoice_fails_when_amount_is_0
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '0.00'
fill_in 'Description', with: 'My first invoice'
assert_no_difference 'Invoice.count' do
click_link_or_button 'Add'
end
assert_text 'Amount is too small. Minimum deposit is 0.01 EUR'
end
def test_create_new_invoice_fails_when_amount_is_negative
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '-120.00'
fill_in 'Description', with: 'My first invoice'
assert_no_difference 'Invoice.count' do
click_link_or_button 'Add'
end
assert_text 'Amount is too small. Minimum deposit is 0.01 EUR'
end
end