Skip to content
Browse files

Initial commit

  • Loading branch information...
0 parents commit 6c9f673cfc338b23e20d683fc4c2b89d0cf714ee @mistydemeo committed Aug 11, 2012
4 .gitignore
@@ -0,0 +1,4 @@
+*.gem
+.bundle
+Gemfile.lock
+pkg/*
4 Gemfile
@@ -0,0 +1,4 @@
+source "http://rubygems.org"
+
+# Specify your gem's dependencies in preeventualist.gemspec
+gemspec
10 Rakefile
@@ -0,0 +1,10 @@
+require 'bundler'
+require 'cucumber/rake/task'
+require 'sinatra/activerecord/rake'
+require './app'
+
+Bundler::GemHelper.install_tasks
+
+Cucumber::Rake::Task.new(:features) do |t|
+ t.cucumber_opts = "--format pretty"
+end
91 app.rb
@@ -0,0 +1,91 @@
+$: << "."
+
+require 'sinatra'
+require 'sinatra/activerecord'
+require 'active_record'
+require 'json'
+
+require 'models/items'
+require 'helpers'
+
+set :database, "sqlite://db/preeventualist.db"
+
+get "/" do
+ erb :homepage
+end
+
+get "/lost" do
+ erb :lost
+end
+
+get "/lost/search" do
+ if not params["q"]
+ status 400
+ return invalid_query_response
+ end
+
+ validate_count
+
+ return search_response_for Items.where(:item => params["q"]).limit params["count"]
+end
+
+get "/lost/searchlost" do
+ if not params["q"]
+ status 400
+ return invalid_query_response
+ end
+
+ validate_count
+
+ return search_response_for Items.where(:kind => "lost", :item => params["q"]).limit params["count"]
+end
+
+get "/lost/searchfound" do
+ if not params["q"]
+ status 400
+ return invalid_query_response
+ end
+
+ validate_count
+
+ return search_response_for Items.where(:kind => "found", :item => params["q"]).limit params["count"]
+end
+
+# This should really be POST, but Poignant Guide's API didn't distinguish
+get "/lost/addlost" do
+ missing_inputs = input_errors :lost
+ if not missing_inputs.empty?
+ return invalid_input_response_for missing_inputs
+ end
+
+ item = Items.new do |i|
+ i.name = params["name"]
+ i.item = params["item"]
+ i.location = params["seen"]
+ i.description = params["desc"]
+ i.kind = "lost"
+ end
+
+ item.save
+
+ submission_confirmation
+end
+
+get "/lost/addfound" do
+ missing_inputs = input_errors :found
+ if not missing_inputs.empty?
+ return invalid_input_response_for missing_inputs
+ end
+
+ item = Items.new do |i|
+ i.name = params["name"]
+ i.item = params["item"]
+ i.location = params["at"]
+ i.description = params["desc"]
+ i.kind = "found"
+ end
+
+ item.save
+
+ submission_confirmation
+end
16 config/database.yml
@@ -0,0 +1,16 @@
+development:
+ adapter: sqlite3
+ encoding: utf8
+ database: db/development.db
+
+test:
+ adapter: sqlite3
+ encoding: utf8
+ database: db/test.db
+
+production:
+ adapter: mysql2
+ encoding: utf8
+ username: root
+ password:
+ database: sinatra-template
15 db/migrate/20120809042234_create_items.rb
@@ -0,0 +1,15 @@
+class CreateItems < ActiveRecord::Migration
+ def up
+ create_table :items do |t|
+ t.string :name
+ t.string :item
+ t.string :location
+ t.string :description
+ t.string :kind
+ end
+ end
+
+ def down
+ drop_table :items
+ end
+end
7 features/home.feature
@@ -0,0 +1,7 @@
+Feature: View pages
+My site has many pages
+And it would be most excellent to view them.
+
+ Scenario: Home page
+ Given I am on the home page
+ Then I should see "The Ashley Raymond Youth Study Clan homepage"
19 features/post.feature
@@ -0,0 +1,19 @@
+Feature: Submit items
+Many people lose items
+And other people find items
+It should be possible to submit items to the database.
+
+ Scenario: Submit some found skills
+ When "Why" submits a found "Ruby skills" found at "Wixl park" with the description:
+ """
+ I can give you Ruby skills!
+ Come visit poignantguide.net!
+ """
+ Then I should see "Thanks for submitting your Ruby skills!"
+
+ Scenario: Submit a lost ham
+ When "Elf" submits a lost "ham" seen in "Ambrose Caverns" with the description:
+ """
+ A bit leaky but very loving
+ """
+ Then I should see "Thanks for submitting your ham!"
38 features/search.feature
@@ -0,0 +1,38 @@
+Feature: Search items
+Many items are lost but they can also be found
+
+ # The final step of these two tests is currently failing; looks like a
+ # Capybara bug, since it recognizes the text to compare is identical
+ Scenario: Find a lost truck
+ Given a "truck" lost by "Fox Tall" in "Chapter 3 in a vast white expanse" is in the database with the description:
+ """
+ New T-1000 pickup truck last seen being driven by a porcupine
+ """
+ When I search for a lost "truck"
+ Then I should see:
+ """
+ Fox Tall
+ --
+ truck
+ --
+ Chapter 3 in a vast white expanse
+ --
+ New T-1000 pickup truck last seen being driven by a porcupine
+ """
+
+ Scenario: Find a found cup
+ Given a "cup" found by "Why" in "A hotel buffet lunch" is in the database with the description:
+ """
+ Probably belongs to a guy who wears seashell necklaces
+ """
+ When I search for a found "cup"
+ Then I should see:
+ """
+ Why
+ --
+ cup
+ --
+ A hotel buffet lunch
+ --
+ Probably belongs to a guy who wears seashell necklaces
+ """
42 features/step_definitions/lostfound_steps.rb
@@ -0,0 +1,42 @@
+require 'uri'
+
+Given /^a "([^\"]*)" (found|lost) by "([^\"]*)" in "([^\"]*)" is in the database with the description:$/ do |item, kind, name, location, description|
+ item = Items.new do |i|
+ i.name = name
+ i.item = item
+ i.location = location
+ i.description = description
+ i.kind = kind
+ end
+
+ item.save
+end
+
+When /^I search for a (\w+) "([^\"]*)"$/ do |mode, text|
+ p "/lost/search#{mode}?q=#{text}"
+ visit "/lost/search#{mode}?q=#{text}"
+end
+
+When /^"([^\"]*)" submits a (lost|found) "([^\"]*)" (seen in|found at) "([^\"]*)" with the description:$/ do |name, mode, item, _, location, description|
+ params = {
+ name: name,
+ item: item,
+ desc: description
+ }
+ if mode == "lost"
+ params[:seen] = location
+ else
+ params[:at] = location
+ end
+
+ query = params.map {|k,v| URI.escape("#{k}=#{v}")}.join("&")
+ visit "/lost/add#{mode}?" + query
+end
+
+Then /^I should see:$/ do |text|
+ if page.respond_to? :should
+ page.should have_content(text)
+ else
+ assert page.has_content?(text)
+ end
+end
219 features/step_definitions/web_steps.rb
@@ -0,0 +1,219 @@
+# Taken from the cucumber-rails project.
+# IMPORTANT: This file is generated by cucumber-sinatra - edit at your own peril.
+# It is recommended to regenerate this file in the future when you upgrade to a
+# newer version of cucumber-sinatra. Consider adding your own code to a new file
+# instead of editing this one. Cucumber will automatically load all features/**/*.rb
+# files.
+
+require 'uri'
+require 'cgi'
+require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
+
+module WithinHelpers
+ def with_scope(locator)
+ locator ? within(locator) { yield } : yield
+ end
+end
+World(WithinHelpers)
+
+Given /^(?:|I )am on (.+)$/ do |page_name|
+ visit path_to(page_name)
+end
+
+When /^(?:|I )go to (.+)$/ do |page_name|
+ visit path_to(page_name)
+end
+
+When /^(?:|I )press "([^\"]*)"(?: within "([^\"]*)")?$/ do |button, selector|
+ with_scope(selector) do
+ click_button(button)
+ end
+end
+
+When /^(?:|I )follow "([^\"]*)"(?: within "([^\"]*)")?$/ do |link, selector|
+ with_scope(selector) do
+ click_link(link)
+ end
+end
+
+When /^(?:|I )fill in "([^\"]*)" with "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, value, selector|
+ with_scope(selector) do
+ fill_in(field, :with => value)
+ end
+end
+
+When /^(?:|I )fill in "([^\"]*)" for "([^\"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
+ with_scope(selector) do
+ fill_in(field, :with => value)
+ end
+end
+
+# Use this to fill in an entire form with data from a table. Example:
+#
+# When I fill in the following:
+# | Account Number | 5002 |
+# | Expiry date | 2009-11-01 |
+# | Note | Nice guy |
+# | Wants Email? | |
+#
+# TODO: Add support for checkbox, select og option
+# based on naming conventions.
+#
+When /^(?:|I )fill in the following(?: within "([^\"]*)")?:$/ do |selector, fields|
+ with_scope(selector) do
+ fields.rows_hash.each do |name, value|
+ When %{I fill in "#{name}" with "#{value}"}
+ end
+ end
+end
+
+When /^(?:|I )select "([^\"]*)" from "([^\"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
+ with_scope(selector) do
+ select(value, :from => field)
+ end
+end
+
+When /^(?:|I )check "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, selector|
+ with_scope(selector) do
+ check(field)
+ end
+end
+
+When /^(?:|I )uncheck "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, selector|
+ with_scope(selector) do
+ uncheck(field)
+ end
+end
+
+When /^(?:|I )choose "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, selector|
+ with_scope(selector) do
+ choose(field)
+ end
+end
+
+When /^(?:|I )attach the file "([^\"]*)" to "([^\"]*)"(?: within "([^\"]*)")?$/ do |path, field, selector|
+ with_scope(selector) do
+ attach_file(field, path)
+ end
+end
+
+Then /^(?:|I )should see JSON:$/ do |expected_json|
+ require 'json'
+ expected = JSON.pretty_generate(JSON.parse(expected_json))
+ actual = JSON.pretty_generate(JSON.parse(response.body))
+ expected.should == actual
+end
+
+Then /^(?:|I )should see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, selector|
+ with_scope(selector) do
+ if page.respond_to? :should
+ page.should have_content(text)
+ else
+ assert page.has_content?(text)
+ end
+ end
+end
+
+Then /^(?:|I )should see \/([^\/]*)\/(?: within "([^\"]*)")?$/ do |regexp, selector|
+ regexp = Regexp.new(regexp)
+ with_scope(selector) do
+ if page.respond_to? :should
+ page.should have_xpath('//*', :text => regexp)
+ else
+ assert page.has_xpath?('//*', :text => regexp)
+ end
+ end
+end
+
+Then /^(?:|I )should not see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, selector|
+ with_scope(selector) do
+ if page.respond_to? :should
+ page.should have_no_content(text)
+ else
+ assert page.has_no_content?(text)
+ end
+ end
+end
+
+Then /^(?:|I )should not see \/([^\/]*)\/(?: within "([^\"]*)")?$/ do |regexp, selector|
+ regexp = Regexp.new(regexp)
+ with_scope(selector) do
+ if page.respond_to? :should
+ page.should have_no_xpath('//*', :text => regexp)
+ else
+ assert page.has_no_xpath?('//*', :text => regexp)
+ end
+ end
+end
+
+Then /^the "([^\"]*)" field(?: within "([^\"]*)")? should contain "([^\"]*)"$/ do |field, selector, value|
+ with_scope(selector) do
+ field = find_field(field)
+ field_value = (field.tag_name == 'textarea') ? field.text : field.value
+ if field_value.respond_to? :should
+ field_value.should =~ /#{value}/
+ else
+ assert_match(/#{value}/, field_value)
+ end
+ end
+end
+
+Then /^the "([^\"]*)" field(?: within "([^\"]*)")? should not contain "([^\"]*)"$/ do |field, selector, value|
+ with_scope(selector) do
+ field = find_field(field)
+ field_value = (field.tag_name == 'textarea') ? field.text : field.value
+ if field_value.respond_to? :should_not
+ field_value.should_not =~ /#{value}/
+ else
+ assert_no_match(/#{value}/, field_value)
+ end
+ end
+end
+
+Then /^the "([^\"]*)" checkbox(?: within "([^\"]*)")? should be checked$/ do |label, selector|
+ with_scope(selector) do
+ field_checked = find_field(label)['checked']
+ if field_checked.respond_to? :should
+ field_checked.should == 'checked'
+ else
+ assert_equal 'checked', field_checked
+ end
+ end
+end
+
+Then /^the "([^\"]*)" checkbox(?: within "([^\"]*)")? should not be checked$/ do |label, selector|
+ with_scope(selector) do
+ field_checked = find_field(label)['checked']
+ if field_checked.respond_to? :should_not
+ field_checked.should_not == 'checked'
+ else
+ assert_not_equal 'checked', field_checked
+ end
+ end
+end
+
+Then /^(?:|I )should be on (.+)$/ do |page_name|
+ current_path = URI.parse(current_url).path
+ if current_path.respond_to? :should
+ current_path.should == path_to(page_name)
+ else
+ assert_equal path_to(page_name), current_path
+ end
+end
+
+Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
+ query = URI.parse(current_url).query
+ actual_params = query ? CGI.parse(query) : {}
+ expected_params = {}
+ expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
+
+ if actual_params.respond_to? :should
+ actual_params.should == expected_params
+ else
+ assert_equal expected_params, actual_params
+ end
+end
+
+Then /^show me the page$/ do
+ save_and_open_page
+end
21 features/support/env.rb
@@ -0,0 +1,21 @@
+# Generated by cucumber-sinatra. (2012-07-31 22:33:07 -0300)
+
+ENV['RACK_ENV'] = 'test'
+
+require File.join(File.dirname(__FILE__), '..', '..', 'app.rb')
+
+require 'capybara'
+require 'capybara/cucumber'
+require 'rspec'
+
+Capybara.app = Sinatra::Application
+
+class PreeventualistWorld
+ include Capybara::DSL
+ include RSpec::Expectations
+ include RSpec::Matchers
+end
+
+World do
+ PreeventualistWorld.new
+end
32 features/support/paths.rb
@@ -0,0 +1,32 @@
+# Taken from the cucumber-rails project.
+
+module NavigationHelpers
+ # Maps a name to a path. Used by the
+ #
+ # When /^I go to (.+)$/ do |page_name|
+ #
+ # step definition in web_steps.rb
+ #
+ def path_to(page_name)
+ case page_name
+
+ when /the home\s?page/
+ '/'
+
+ # Add more mappings here.
+ # Here is an example that pulls values out of the Regexp:
+ #
+ # when /^(.*)'s profile page$/i
+ # user_profile_path(User.find_by_login($1))
+
+ when /lost and found/
+ '/lost'
+
+ else
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
+ "Now, go and add a mapping in #{__FILE__}"
+ end
+ end
+end
+
+World(NavigationHelpers)
74 helpers.rb
@@ -0,0 +1,74 @@
+helpers do
+ def json_requested?
+ params["json"] == "true"
+ end
+
+ def validate_count
+ if not (params["count"] && params["count"] < 100 && params["count"] > 0)
+ params["count"] = 10
+ end
+ end
+
+ def input_errors mode
+ if ![:found, :lost].include? mode
+ raise ArgumentError, "Invalid mode - only :found and :lost are valid"
+ end
+
+ required_fields = ["name", "desc", "item"]
+ if mode == :found
+ required_fields.concat ["at"]
+ elsif mode == :lost
+ required_fields.concat ["seen"]
+ end
+
+ required_fields.select do |field|
+ not params[field]
+ end
+ end
+
+ def invalid_query_response
+ if not json_requested?
+ "You need to specify a search query with \"?q=\"!"
+ else
+ {"errors" => [{"message" => "Missing input(s)", "code" => 400}, "missing" => ["q"]]}
+ end
+ end
+
+ def invalid_input_response_for errors
+ if not json_requested?
+ p errors
+ erb :error, :locals => {:errors => errors}
+ else
+ {"errors" => [{"message" => "Missing input(s)", "code" => 400, "missing" => errors}]}
+ end
+ end
+
+ def search_response_for results
+ if not json_requested?
+ # This doesn't return 404 since that would raise an exception
+ # for _why's client, which didn't have exception handling
+ return "No results found :(" if results.empty?
+
+ # _why's version didn't have a public "kind" value
+ result = results.first.to_hash
+ result.delete :kind
+
+ # _why's guide specifies only one result, with unnamed fields
+ # separated by "--\n"
+ content_type :text
+ result.values.join("\n--\n")
+ else
+ content_type :json
+ status 404 if results.empty?
+ results.map(&:to_hash).to_json
+ end
+ end
+
+ def submission_confirmation
+ status 200
+
+ if not json_requested?
+ "Thanks for submitting your #{params["item"]}!"
+ end
+ end
+end
17 models/items.rb
@@ -0,0 +1,17 @@
+class Items < ActiveRecord::Base
+ validates_presence_of :name
+ validates_presence_of :item
+ validates_presence_of :location
+ validates_presence_of :description
+ validates_presence_of :kind
+
+ def to_hash
+ {
+ :name => name,
+ :item => item,
+ :location => location,
+ :description => description,
+ :kind => kind
+ }
+ end
+end
25 preeventualist.gemspec
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+Gem::Specification.new do |s|
+ s.name = "preeventualist"
+ s.version = "0.0.1"
+ s.platform = Gem::Platform::RUBY
+ s.authors = ["Misty De Meo"]
+ s.email = ["mistydemeo@gmail.com"]
+ s.homepage = "https://github.com/mistydemeo/preeventualist"
+ s.summary = %q{TODO: Write a gem summary}
+ s.description = %q{TODO: Write a gem description}
+
+ s.files = `git ls-files`.split("\n")
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
+ s.require_paths = ["."]
+
+ s.add_runtime_dependency "sinatra"
+ s.add_runtime_dependency "sinatra-activerecord"
+ s.add_runtime_dependency "activerecord"
+ s.add_runtime_dependency "sqlite3"
+
+ s.add_development_dependency "cucumber"
+ s.add_development_dependency "rspec"
+ s.add_development_dependency "capybara"
+end
14 views/error.erb
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>What did you do??</title>
+ <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
+</head>
+<body>
+ <pre>
+You forgot to include the following fields:
+
+<%= errors.join("\n") %>
+ </pre>
+</body>
+</html>
16 views/homepage.erb
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Ashley Raymond Youth Study Clan homepage</title>
+ <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
+</head>
+<body>
+ <pre>
+Welcome to The Ashley Raymond Youth Study Clan homepage!
+
+This site is under construction! Maybe we'll have some information here someday??
+
+In the meantime, you may be interested in our <a href="lost">lost and found service</a>!
+ </pre>
+</body>
+</html>
62 views/lost.erb
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>LOSING AND FINDING REGISTRY</title>
+ <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
+</head>
+<body>
+ <pre>
+ THE PREEVENTUALIST'S LOSING AND FINDING REGISTRY
+ (a free service benefiting the ENLIGHTENED who have been LIGHTENED)
+
+ ---
+ updates are made daily, please check back!
+ ---
+
+ this service is commissioned and
+ subsidized in part by The Ashley Raymond
+ Youth Study Clan
+
+ ...
+ all seals and privileges have been filed
+ under the notable authorship of Perry W. L. Von Frowling,
+ Magistrate Polywaif of Dispossession. Also, Seventh Straight Winner
+ of the esteemed Persistent Beggar's Community Cup.
+ ...
+
+ ABOUT THE REGISTRY
+ ==================
+ Hello, if you are new, please stay with us. A brief explanation of our service will
+ follow. First, a bit of important news from our beloved magistrate. (The kids call
+ him Uncle Von Guffuncle. Tehe!)
+
+ USING THE L&amp;F SERVER
+ ====================
+ The L&amp;F is a free service. The acts of losing and finding are essential qualities in
+ building a preeventualist lifestyle. We hope to accomodate your belief.
+
+ We do not use HTML, in order to simplify our work here. Our guys are already working
+ fifteen hour days. (Thanks, Terk!! Thanks, Horace!!)
+
+ You may search our service for your lost items. Or you may add your lost (or found)
+ item to our registry. This is done by typing the proper address into your browser.
+
+ SEARCHING
+ =========
+ To search for lost items, use the following address:
+
+ http://preeventualist.org/lost/search?q={search word}
+
+ You may replace {search word} with your search term. For example, to search for "cup":
+
+ http://preeventualist.org/lost/search?q=cup
+
+ You will be given a list of cups which have been lost or found.
+
+ If you want to search for only lost cups or only found cups, use the `searchlost' and
+ `searchfound' pages:
+
+ http://preeventualist.org/lost/searchlost?q=cup
+ </pre>
+</body>
+</html>

0 comments on commit 6c9f673

Please sign in to comment.
Something went wrong with that request. Please try again.