iris/tests/iris_test.rb

415 lines
15 KiB
Ruby

require 'minitest/autorun'
require 'mocha/minitest'
# This allows the test to pretend that user "jerryberry" is logged in.
ENV['USER'] = 'jerryberry'
# Set this before loading the code so that the Config constants load correctly.
$test_corpus_file = "./tests/iris.messages.json"
require './iris.rb'
describe Config do
it 'has the Iris semantic version number' do
_(Config::VERSION).must_match /^\d\.\d\.\d+$/
end
it 'has the message file location' do
_(Config::MESSAGE_FILE).must_match /\/\.iris\.messages$/
end
it 'has the readline history file location' do
_(Config::HISTORY_FILE).must_match /\/\.iris\.history$/
end
it 'has the username' do
_(Config::USER).must_equal 'jerryberry'
end
it 'has a hostname' do
_(Config::HOSTNAME).wont_be_nil
end
it 'has the author' do
_(Config::AUTHOR).must_equal "#{Config::USER}@#{Config::HOSTNAME}"
end
describe '.find_files' do
it 'looks up all the Iris message files on the system' do
# I am so sorry about this `expects` clause
Config.expects(:`).with('ls /home/**/.iris.messages').returns('')
Config.find_files
end
it 'returns a list of Iris message files' do
Config.stubs(:`).returns("foo\nbar\n")
_(Config.find_files).must_equal ['foo', 'bar']
end
it 'returns an empty array if no Iris message files are found' do
Config.stubs(:`).returns('')
_(Config.find_files).must_equal []
end
end
end
describe Corpus do
before do
Corpus.load
end
describe '.load' do
it 'loads all the message files'
it 'sets the corpus class variable'
it 'sets the topics class variable'
it 'creates a hash index'
it 'creates parent-hash-to-child-indexes index'
end
describe '.topics' do
it 'returns all the messages which are topics'
it 'does not return reply messages'
end
describe '.mine' do
it 'returns all messages composed by the current user'
it 'does not return any messages not composed by the current user'
end
describe '.find_message_by_hash' do
it 'returns nil if a nil is passed in' do
assert_nil Corpus.find_message_by_hash(nil)
end
it 'returns nil if the hash is not found in the corpus' do
assert_nil Corpus.find_message_by_hash('NoofMcGoof')
end
it 'returns the message associated with the hash if it is found' do
message = Corpus.find_message_by_hash("gpY2WW/jGcH+BODgySCwDANJlIM=\n")
_(message.message).must_equal "Test"
end
end
describe '.find_all_by_parent_hash' do
it 'returns an empty array if a nil is passed in' do
_(Corpus.find_all_by_parent_hash(nil)).must_equal []
end
it 'returns an empty array if the hash is not a parent of any other messages' do
_(Corpus.find_all_by_parent_hash('GoofMcDoof')).must_equal []
end
it 'returns an empty array if the hash is not found in the corpus'
it 'returns the messages associated with the parent hash'
end
describe '.find_topic_by_id' do
it 'returns nil if a nil is passed in' do
assert_nil Corpus.find_topic_by_id(nil)
end
describe 'when an index string is passed in' do
it 'returns nil if the topic is not found'
it 'returns the associated topic'
end
end
describe '.find_topic_by_hash' do
it 'returns nil if a nil is passed in' do
assert_nil Corpus.find_topic_by_hash(nil)
end
describe 'when a hash string is passed in' do
it 'returns nil if the topic is not found'
it 'returns the associated topic'
end
end
end
describe IrisFile do
describe '.load_messages' do; end
describe '.create_message_file' do; end
end
describe Message do
it 'exposes all its data attributes for reading'
it 'is #valid? if it has no errors'
it 'is #topic? if it has no parent'
describe 'creation' do; end
describe 'validation' do; end
describe '#save!' do
it 'adds itself to the user\'s corpus'
it 'writes out the user\'s message file'
it 'reloads all message files'
end
describe '#hash' do; end
describe '#truncated_message' do; end
describe '#to_topic_line' do; end
describe '#to_display' do; end
describe '#to_topic_display' do; end
describe '#to_json' do; end
end
describe Display do
it 'has a setting for a minimum width of 80' do
_(Display::MIN_WIDTH).must_equal 80
end
it 'has a setting for a minimum height of 8' do
_(Display::MIN_HEIGHT).must_equal 8
end
it 'has settings for the calculated screen geometry' do
_(Display::WIDTH).wont_equal nil
_(Display::HEIGHT).wont_equal nil
end
describe '#topic_index_width' do
it 'returns the a minimun length of 2' do
Corpus.stubs(:topics).returns(%w{a})
_(Display.topic_index_width).must_equal 2
end
it 'returns the length in characters of the longest topic index' do
Corpus.stubs(:topics).returns((0..1000).to_a)
_(Display.topic_index_width).must_equal 4
end
it 'returns 2 if there are no topics' do
Corpus.stubs(:topics).returns([])
_(Display.topic_index_width).must_equal 2
end
end
describe '#topic_author_width' do
it 'returns the length in characters of the longest author\'s name' do
Corpus.stubs(:authors).returns(['jerryberry@ctrl-c.club'])
_(Display.topic_author_width).must_equal 22
end
it 'returns 1 if there are no topics' do
Corpus.stubs(:authors).returns([])
_(Display.topic_author_width).must_equal 1
end
end
describe '.print_index' do; end
describe '.print_author' do; end
end
describe Interface do
it 'has a map of all single-word commands'
it 'has a map of all shortcuts and commands'
describe '#start' do; end
describe 'creation' do; end
describe '#reset_display' do; end
describe '#reply' do; end
describe '#show_topic' do; end
describe '#quit' do; end
describe '.start' do; end
describe '#compose' do; end
describe '#topics' do; end
describe '#help' do; end
describe '#freshen' do; end
describe '#readline (maybe?)' do; end
end
describe CLI do
describe '#start' do; end
describe 'creation' do; end
describe '--version or -v' do; end
describe '--stats or -s' do; end
describe '--help or -h' do; end
describe 'junk parameters' do; end
end
describe Startupper do
describe 'creation' do
let(:message_file_path) { 'jerryberry/.iris.messages' }
let(:read_file_path) { 'jerryberry/.iris.read' }
let(:data_file_stat) { a = mock; a.stubs(:mode).returns(33188); a }
let(:script_file_stat) { a = mock; a.stubs(:mode).returns(33261); a }
let(:bad_file_stat) { a = mock; a.stubs(:mode).returns(2); a }
before do
Config.stubs(:find_files).returns([])
IrisFile.stubs(:load_messages).returns([])
IrisFile.stubs(:load_reads).returns([])
Config.send(:remove_const, 'MESSAGE_FILE') if Config.const_defined? 'MESSAGE_FILE'
Config.send(:remove_const, 'READ_FILE') if Config.const_defined? 'READ_FILE'
Config.send(:remove_const, 'IRIS_SCRIPT') if Config.const_defined? 'IRIS_SCRIPT'
Config::MESSAGE_FILE = message_file_path
Config::READ_FILE = read_file_path
Config.stubs(:messagefile_filename).returns(message_file_path)
Config.stubs(:readfile_filename).returns(read_file_path)
Config::IRIS_SCRIPT = 'doots'
File.stubs(:exists?).returns(true)
File.stubs(:stat).with(Config::IRIS_SCRIPT).returns(script_file_stat)
File.stubs(:stat).with(message_file_path).returns(data_file_stat)
File.stubs(:stat).with(read_file_path).returns(data_file_stat)
Interface.stubs(:start)
end
it 'starts the Interface if no command-line arguments are provided' do
Interface.expects(:start).with([])
Startupper.new([])
end
it 'starts the Interface if "-i" is provided at the command-line' do
Interface.expects(:start).with(['-i'])
Startupper.new(['-i'])
end
it 'starts the Interface if "--interactive" is provided at the command-line' do
Interface.expects(:start).with(['--interactive'])
Startupper.new(['--interactive'])
end
it 'starts the CLI if any non-interactive parameters are provided at the command-line' do
CLI.expects(:start).with(['-h'])
Startupper.new(['-h'])
end
it 'offers to create a message file if the user doesn\'t have one' do
File.stubs(:exists?).with(message_file_path).returns(false)
Display.stubs(:say)
Readline.expects(:readline).with('Would you like me to create it for you? (y/n) ', true).returns('y')
IrisFile.expects(:create_message_file)
Startupper.new([])
end
it 'creates a read file if the user doesn\'t have one' do
File.stubs(:exists?).with(read_file_path).returns(false)
IrisFile.expects(:create_read_file)
Startupper.new([])
end
it 'warns the user if the message file permissions are wrong' do
File.expects(:stat).with(message_file_path).returns(bad_file_stat)
Display.stubs(:say)
message_lines = [
"Your message file has incorrect permissions! Should be \"-rw-r--r--\".",
"You can change this from the command line with:",
" chmod 644 jerryberry/.iris.messages",
"Leaving your file with incorrect permissions could allow unauthorized edits!"
]
Display.expects(:say).with(message_lines)
Startupper.new([])
end
it 'warns the user if the read file permissions are wrong' do
File.stubs(:stat).with(read_file_path).returns(bad_file_stat)
Display.stubs(:say)
message_lines = [
"Your read file has incorrect permissions! Should be \"-rw-r--r--\".",
"You can change this from the command line with:",
" chmod 644 jerryberry/.iris.read"
]
Display.expects(:say).with(message_lines)
Startupper.new([])
end
it 'warns the user if the script file permissions are wrong' do
File.expects(:stat).with(Config::IRIS_SCRIPT).returns(bad_file_stat)
Display.stubs(:say)
message_lines = [
"Your Iris file has incorrect permissions! Should be \"-rwxr-xr-x\".",
"You can change this from the command line with:",
" chmod 755 doots", "If this file has the wrong permissions the program may be tampered with!"
]
Display.expects(:say).with(message_lines)
Startupper.new([])
end
end
end
describe 'String#colorize' do
let(:color_strings) {
"
RED {r normal}\t{ri intense}\t{ru underline}\t{riu intense underline}
{rv reverse}\t{riv intense}\t{ruv underline}\t{riuv intense underline}
GREEN {g normal}\t{gi intense}\t{ug underline}\t{uig intense underline}
{gv reverse}\t{giv intense}\t{ugv underline}\t{uigv intense underline}
YELLOW {y normal}\t{yi intense}\t{yu underline}\t{yiu intense underline}
{yv reverse}\t{yiv intense}\t{yuv underline}\t{yiuv intense underline}
BLUE {b normal}\t{bi intense}\t{bu underline}\t{biu intense underline}
{bv reverse}\t{biv intense}\t{buv underline}\t{biuv intense underline}
MAGENTA {m normal}\t{mi intense}\t{mu underline}\t{miu intense underline}
{mv reverse}\t{miv intense}\t{muv underline}\t{miuv intense underline}
CYAN {c normal}\t{ci intense}\t{cu underline}\t{ciu intense underline}
{cv reverse}\t{civ intense}\t{cuv underline}\t{ciuv intense underline}
WHITE {w normal}\t{wi intense}\t{wu underline}\t{wiu intense underline}
{wv reverse}\t{wiv intense}\t{wuv underline}\t{wiuv intense underline}
".split("\n")[1..-2]
}
it 'produces the expected output' do
lead = "\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m "
lines = [
"RED \e[31mnormal\e[0m\t\e[1;31mintense\e[0m\t\e[31;4munderline\e[0m\t\e[1;31;4mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
" \e[31;7mreverse\e[0m\t\e[1;31;7mintense\e[0m\t\e[31;4;7munderline\e[0m\t\e[1;31;4;7mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
"GREEN \e[32mnormal\e[0m\t\e[1;32mintense\e[0m\t\e[32;4munderline\e[0m\t\e[1;32;4mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
" \e[32;7mreverse\e[0m\t\e[1;32;7mintense\e[0m\t\e[32;4;7munderline\e[0m\t\e[1;32;4;7mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
"YELLOW \e[33mnormal\e[0m\t\e[1;33mintense\e[0m\t\e[33;4munderline\e[0m\t\e[1;33;4mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
" \e[33;7mreverse\e[0m\t\e[1;33;7mintense\e[0m\t\e[33;4;7munderline\e[0m\t\e[1;33;4;7mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
"BLUE \e[34mnormal\e[0m\t\e[1;34mintense\e[0m\t\e[34;4munderline\e[0m\t\e[1;34;4mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
" \e[34;7mreverse\e[0m\t\e[1;34;7mintense\e[0m\t\e[34;4;7munderline\e[0m\t\e[1;34;4;7mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
"MAGENTA \e[35mnormal\e[0m\t\e[1;35mintense\e[0m\t\e[35;4munderline\e[0m\t\e[1;35;4mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
" \e[35;7mreverse\e[0m\t\e[1;35;7mintense\e[0m\t\e[35;4;7munderline\e[0m\t\e[1;35;4;7mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
"CYAN \e[36mnormal\e[0m\t\e[1;36mintense\e[0m\t\e[36;4munderline\e[0m\t\e[1;36;4mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
" \e[36;7mreverse\e[0m\t\e[1;36;7mintense\e[0m\t\e[36;4;7munderline\e[0m\t\e[1;36;4;7mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
"WHITE \e[37mnormal\e[0m\t\e[1;37mintense\e[0m\t\e[37;4munderline\e[0m\t\e[1;37;4mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
" \e[37;7mreverse\e[0m\t\e[1;37;7mintense\e[0m\t\e[37;4;7munderline\e[0m\t\e[1;37;4;7mintense underline\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m\e[0m",
]
_(color_strings[0].colorize).must_equal lead + lines[0]
_(color_strings[1].colorize).must_equal lead + lines[1]
_(color_strings[2].colorize).must_equal lead + lines[2]
_(color_strings[3].colorize).must_equal lead + lines[3]
_(color_strings[4].colorize).must_equal lead + lines[4]
_(color_strings[5].colorize).must_equal lead + lines[5]
_(color_strings[6].colorize).must_equal lead + lines[6]
_(color_strings[7].colorize).must_equal lead + lines[7]
_(color_strings[8].colorize).must_equal lead + lines[8]
_(color_strings[9].colorize).must_equal lead + lines[9]
_(color_strings[10].colorize).must_equal lead + lines[10]
_(color_strings[11].colorize).must_equal lead + lines[11]
_(color_strings[12].colorize).must_equal lead + lines[12]
_(color_strings[13].colorize).must_equal lead + lines[13]
end
it 'returns an empty string wrapped with resets when provided an empty string' do
_(''.colorize).must_equal "\e[0m\e[0m"
end
it 'allows curly brackets to be escaped' do
_('I want \{no color\}'.colorize).must_equal "\e[0m\e[0mI want {no color}\e[0m\e[0m\e[0m"
end
end
describe 'String#decolorize' do
it 'returns the string with the coloring tags stripped' do
_("{b colorful}".decolorize).must_equal "colorful"
end
it 'allows curly brackets to be escaped' do
_('I want \{no color\}'.decolorize).must_equal "I want {no color}"
end
end