~singpolyma/jmp-pay

a529fc21b9a89247831ae1077351e5d1b30b4a96 — Stephen Paul Weber 1 year, 8 months ago fc43c79
Initial test suite and helpers
6 files changed, 164 insertions(+), 1 deletions(-)

M .builds/debian-stable.yml
M Gemfile
A Rakefile
M config.ru
A test/test_electrum.rb
A test/test_helper.rb
M .builds/debian-stable.yml => .builds/debian-stable.yml +4 -1
@@ 13,7 13,10 @@ environment:
tasks:
- dependencies: |
    cd jmp-pay
    bundle install --path=.gems
    bundle install --without=development --path=.gems
- lint: |
    cd jmp-pay
    rubocop
- test: |
    cd jmp-pay
    RANTLY_COUNT=100 bundle exec rake test

M Gemfile => Gemfile +9 -0
@@ 12,5 12,14 @@ gem "roda"
gem "slim"

group(:development) do
	gem "pry-reload"
	gem "pry-rescue"
	gem "pry-stack_explorer"
	gem "roda-bin"
end

group(:test) do
	gem "minitest"
	gem "rantly"
	gem "webmock"
end

A Rakefile => Rakefile +22 -0
@@ 0,0 1,22 @@
# frozen_string_literal: true

require "rake/testtask"
require "rubocop/rake_task"

Rake::TestTask.new(:test) do |t|
	ENV["RANTLY_VERBOSE"] = "0" unless ENV["RANTLY_VERBOSE"]
	ENV["RANTLY_COUNT"] = "10" unless ENV["RANTLY_COUNT"]

	t.libs << "test"
	t.libs << "lib"
	t.test_files = FileList["test/**/test_*.rb"]
	t.warning = false
end

RuboCop::RakeTask.new(:lint)

task :entr do
	sh "sh", "-c", "git ls-files | entr -s 'rubocop && rake test'"
end

task default: :test

M config.ru => config.ru +5 -0
@@ 7,6 7,11 @@ require "pg"
require "redis"
require "roda"

if ENV["RACK_ENV"] == "development"
	require "pry-rescue"
	use PryRescue::Rack
end

require_relative "lib/electrum"

REDIS = Redis.new

A test/test_electrum.rb => test/test_electrum.rb +102 -0
@@ 0,0 1,102 @@
# frozen_string_literal: true

require "test_helper"
require "electrum"

class ElectrumTest < Minitest::Test
	RPC_URI = "http://example.com"

	def setup
		@electrum = Electrum.new(
			rpc_uri: RPC_URI,
			rpc_username: "username",
			rpc_password: "password"
		)
	end

	def stub_rpc(method, params)
		stub_request(:post, RPC_URI).with(
			headers: {"Content-Type" => "application/json"},
			basic_auth: ["username", "password"],
			body: hash_including(
				method: method,
				params: params
			)
		)
	end

	property(:getaddresshistory) { string(:alnum) }
	def getaddresshistory(address)
		req =
			stub_rpc("getaddresshistory", address: address)
			.to_return(body: {result: "result"}.to_json)
		assert_equal "result", @electrum.getaddresshistory(address)
		assert_requested(req)
	end

	property(:get_tx_status) { string(:alnum) }
	def get_tx_status(tx_hash)
		req =
			stub_rpc("get_tx_status", txid: tx_hash)
			.to_return(body: {result: "result"}.to_json)
		assert_equal "result", @electrum.get_tx_status(tx_hash)
		assert_requested(req)
	end

	property(:gettransaction) { [string(:alnum), string(:xdigit)] }
	def gettransaction(tx_hash, dummy_tx)
		req1 =
			stub_rpc("gettransaction", txid: tx_hash)
			.to_return(body: {result: dummy_tx}.to_json)
		req2 =
			stub_rpc("deserialize", [dummy_tx])
			.to_return(body: {result: {outputs: []}}.to_json)
		assert_kind_of Electrum::Transaction, @electrum.gettransaction(tx_hash)
		assert_requested(req1)
		assert_requested(req2)
	end

	class TransactionTest < Minitest::Test
		def transaction(outputs=[])
			electrum_mock = Minitest::Mock.new("Electrum")
			[
				electrum_mock,
				Electrum::Transaction.new(
					electrum_mock,
					"txhash",
					"outputs" => outputs
				)
			]
		end

		def test_confirmations
			electrum_mock, tx = transaction
			electrum_mock.expect(
				:get_tx_status,
				{"confirmations" => 1234},
				["txhash"]
			)
			assert_equal 1234, tx.confirmations
		end

		def test_amount_for_empty
			_, tx = transaction
			assert_equal 0, tx.amount_for
		end

		def test_amount_for_address_not_present
			_, tx = transaction([{"address" => "address", "value_sats" => 1}])
			assert_equal 0, tx.amount_for("other_address")
		end

		def test_amount_for_address_present
			_, tx = transaction([{"address" => "address", "value_sats" => 1}])
			assert_equal 0.00000001, tx.amount_for("address")
		end

		def test_amount_for_one_of_address_present
			_, tx = transaction([{"address" => "address", "value_sats" => 1}])
			assert_equal 0.00000001, tx.amount_for("boop", "address", "lol")
		end
	end
end

A test/test_helper.rb => test/test_helper.rb +22 -0
@@ 0,0 1,22 @@
# frozen_string_literal: true

require "minitest/autorun"
require "rantly/minitest_extensions"
require "webmock/minitest"
begin
	require "pry-rescue/minitest"
	require "pry-reload"
rescue LoadError
	# Just helpers for dev, no big deal if missing
	nil
end

module Minitest
	class Test
		def self.property(m, &block)
			define_method("test_#{m}") do
				property_of(&block).check { |args| send(m, *args) }
			end
		end
	end
end