mirror of https://github.com/Calamitous/iris.git
Begin building out test suite
- Minor code shuffling - Privatization of some methods - Readline script doesn't kick off if running from a test
This commit is contained in:
parent
22372906cd
commit
3b6ad0d3d3
146
iris.rb
146
iris.rb
|
@ -63,7 +63,60 @@ class Config
|
||||||
AUTHOR = "#{USER}@#{HOSTNAME}"
|
AUTHOR = "#{USER}@#{HOSTNAME}"
|
||||||
|
|
||||||
def self.find_files
|
def self.find_files
|
||||||
@@message_corpus ||= (`ls /home/**/.iris.messages`).split("\n")
|
(`ls /home/**/.iris.messages`).split("\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Corpus
|
||||||
|
def self.load
|
||||||
|
@@corpus = Config.find_files.map { |filepath| IrisFile.load_messages(filepath) }.flatten.sort_by(&:timestamp)
|
||||||
|
@@topics = @@corpus.select{ |m| m.parent == nil }
|
||||||
|
@@my_corpus = IrisFile.load_messages.sort_by(&:timestamp)
|
||||||
|
@@all_hash_to_index = @@corpus.reduce({}) { |agg, msg| agg[msg.hash] = @@corpus.index(msg); agg }
|
||||||
|
@@all_parent_hash_to_index = @@corpus.reduce({}) do |agg, msg|
|
||||||
|
agg[msg.parent] ||= []
|
||||||
|
agg[msg.parent] << @@corpus.index(msg)
|
||||||
|
agg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.all
|
||||||
|
@@corpus
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.topics
|
||||||
|
@@topics
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.mine
|
||||||
|
@@my_corpus
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_message_by_hash(hash)
|
||||||
|
return nil unless hash
|
||||||
|
index = @@all_hash_to_index[hash]
|
||||||
|
return nil unless index
|
||||||
|
all[index]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_all_by_parent_hash(hash)
|
||||||
|
return [] unless hash
|
||||||
|
indexes = @@all_parent_hash_to_index[hash]
|
||||||
|
return [] unless indexes
|
||||||
|
indexes.map{ |idx| all[idx] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_topic(topic_lookup)
|
||||||
|
return nil unless topic_lookup
|
||||||
|
if topic_id.to_i == 0
|
||||||
|
# This must be a hash, handle appropriately
|
||||||
|
msg = find_message_by_hash(topic_id)
|
||||||
|
msg
|
||||||
|
else
|
||||||
|
# This must be an index, handle appropriately
|
||||||
|
index = topic_id.to_i - 1
|
||||||
|
return topics[index] if index >= 0 && index < topics.length
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -125,59 +178,6 @@ class IrisFile
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Corpus
|
|
||||||
def self.load
|
|
||||||
@@corpus = Config.find_files.map { |filepath| IrisFile.load_messages(filepath) }.flatten.sort_by(&:timestamp)
|
|
||||||
@@topics = @@corpus.select{ |m| m.parent == nil }
|
|
||||||
@@my_corpus = IrisFile.load_messages.sort_by(&:timestamp)
|
|
||||||
@@all_hash_to_index = @@corpus.reduce({}) { |agg, msg| agg[msg.hash] = @@corpus.index(msg); agg }
|
|
||||||
@@all_parent_hash_to_index = @@corpus.reduce({}) do |agg, msg|
|
|
||||||
agg[msg.parent] ||= []
|
|
||||||
agg[msg.parent] << @@corpus.index(msg)
|
|
||||||
agg
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.all
|
|
||||||
@@corpus
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.topics
|
|
||||||
@@topics
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.mine
|
|
||||||
@@my_corpus
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.find_message_by_hash(hash)
|
|
||||||
return nil unless hash
|
|
||||||
index = @@all_hash_to_index[hash]
|
|
||||||
return nil unless index
|
|
||||||
all[index]
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.find_all_by_parent_hash(hash)
|
|
||||||
return [] unless hash
|
|
||||||
indexes = @@all_parent_hash_to_index[hash]
|
|
||||||
return [] unless indexes
|
|
||||||
indexes.map{ |idx| all[idx] }
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.find_topic(topic_id)
|
|
||||||
if topic_id.to_i == 0
|
|
||||||
# This must be a hash, handle appropriately
|
|
||||||
msg = find_message_by_hash(topic_id)
|
|
||||||
puts 'WARNING: Expected a topic but got a reply!' unless msg.is_topic?
|
|
||||||
msg
|
|
||||||
else
|
|
||||||
# This must be an index, handle appropriately
|
|
||||||
index = topic_id.to_i - 1
|
|
||||||
return topics[index] if index >= 0 && index < topics.length
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Message
|
class Message
|
||||||
FILE_FORMAT = 'v2'
|
FILE_FORMAT = 'v2'
|
||||||
|
|
||||||
|
@ -223,6 +223,10 @@ class Message
|
||||||
@errors.empty?
|
@errors.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def topic?
|
||||||
|
parent.nil?
|
||||||
|
end
|
||||||
|
|
||||||
def save!
|
def save!
|
||||||
new_corpus = Corpus.mine << self
|
new_corpus = Corpus.mine << self
|
||||||
IrisFile.write_corpus(new_corpus.to_json)
|
IrisFile.write_corpus(new_corpus.to_json)
|
||||||
|
@ -250,14 +254,6 @@ class Message
|
||||||
[head, message_stub].join(' | ')
|
[head, message_stub].join(' | ')
|
||||||
end
|
end
|
||||||
|
|
||||||
def leader_text
|
|
||||||
is_topic? ? '***' : ' === REPLY==='
|
|
||||||
end
|
|
||||||
|
|
||||||
def verb_text
|
|
||||||
is_topic? ? 'posted' : 'replied'
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_display
|
def to_display
|
||||||
error_marker = valid? ? nil : '### THIS MESSAGE HAS THE FOLLOWING ERRORS ###'
|
error_marker = valid? ? nil : '### THIS MESSAGE HAS THE FOLLOWING ERRORS ###'
|
||||||
error_follower = valid? ? nil : '### THIS MESSAGE MAY BE CORRUPT OR TAMPERED WITH ###'
|
error_follower = valid? ? nil : '### THIS MESSAGE MAY BE CORRUPT OR TAMPERED WITH ###'
|
||||||
|
@ -277,14 +273,6 @@ class Message
|
||||||
[to_display] + replies.map(&:to_display)
|
[to_display] + replies.map(&:to_display)
|
||||||
end
|
end
|
||||||
|
|
||||||
def replies
|
|
||||||
Corpus.find_all_by_parent_hash(hash)
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_topic?
|
|
||||||
parent.nil?
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_json(*args)
|
def to_json(*args)
|
||||||
{
|
{
|
||||||
hash: hash,
|
hash: hash,
|
||||||
|
@ -293,6 +281,20 @@ class Message
|
||||||
}.to_json
|
}.to_json
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def leader_text
|
||||||
|
topic? ? '***' : ' === REPLY==='
|
||||||
|
end
|
||||||
|
|
||||||
|
def verb_text
|
||||||
|
topic? ? 'posted' : 'replied'
|
||||||
|
end
|
||||||
|
|
||||||
|
def replies
|
||||||
|
Corpus.find_all_by_parent_hash(hash)
|
||||||
|
end
|
||||||
|
|
||||||
def unconfirmed_payload
|
def unconfirmed_payload
|
||||||
{
|
{
|
||||||
author: author,
|
author: author,
|
||||||
|
@ -312,7 +314,7 @@ class Display
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.topic_author_width
|
def self.topic_author_width
|
||||||
Corpus.topics.map(&:author).map(&:length).max
|
Corpus.topics.map(&:author).map(&:length).max || 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.print_index(index)
|
def self.print_index(index)
|
||||||
|
@ -604,4 +606,4 @@ class Startupper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Startupper.new(ARGV)
|
Startupper.new(ARGV) if __FILE__==$0
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
require 'minitest/autorun'
|
||||||
|
require 'mocha/mini_test'
|
||||||
|
|
||||||
|
# Setting this before loading the main code file so that the Config contants
|
||||||
|
# load correctly. This will allows the test to pretend that user "jerryberry"
|
||||||
|
# is logged in.
|
||||||
|
ENV.stubs(:[]).returns('jerryberry')
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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 '.all' do
|
||||||
|
it 'returns the entire corpus of messages'
|
||||||
|
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
|
||||||
|
Corpus.find_message_by_hash(nil).must_equal nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns nil if the hash is not found in the corpus' do
|
||||||
|
skip
|
||||||
|
Corpus.find_message_by_hash('NoofMcGoof').must_equal nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the message associated with the hash if it is found'
|
||||||
|
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
|
||||||
|
skip
|
||||||
|
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' do
|
||||||
|
it 'returns nil if a nil is passed in' do
|
||||||
|
Corpus.find_topic(nil).must_equal 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
|
||||||
|
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
describe IrisFile do
|
||||||
|
describe '.load_messages' do; end
|
||||||
|
describe '.create_message_file' do; end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Message do
|
||||||
|
it 'has a file version' do
|
||||||
|
Message::FILE_FORMAT.must_match /v\d/
|
||||||
|
end
|
||||||
|
|
||||||
|
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 the calculated screen width'
|
||||||
|
|
||||||
|
describe '#topic_index_width' do
|
||||||
|
it 'returns the length in characters of the longest topic index' do
|
||||||
|
Corpus.stubs(:topics).returns(%w{a bc def})
|
||||||
|
Display.topic_index_width.must_equal 1
|
||||||
|
|
||||||
|
Corpus.stubs(:topics).returns(%w{a b c d e f g h i j k})
|
||||||
|
Display.topic_index_width.must_equal 2
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns 1 if there are no topics' do
|
||||||
|
Corpus.stubs(:topics).returns([])
|
||||||
|
Display.topic_index_width.must_equal 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#topic_author_width' do
|
||||||
|
it 'returns the length in characters of the longest author\'s name'
|
||||||
|
it 'returns 1 if there are no topics' do
|
||||||
|
Corpus.stubs(:topics).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; end
|
||||||
|
describe 'perform_startup_checks' do; end
|
||||||
|
end
|
|
@ -0,0 +1,6 @@
|
||||||
|
echo "Watching..."
|
||||||
|
find . -name "*.rb" | entr sh -c 'clear; ruby iris_test.rb'
|
||||||
|
|
||||||
|
# while inotifywait -r -e modify ./spec; do
|
||||||
|
# SKIP_PRECOMPILE=TRUE SKIP_LINT=TRUE ./test.sh $1
|
||||||
|
# done
|
Loading…
Reference in New Issue