move to AR

This commit is contained in:
Rick Okin 2005-08-09 02:20:28 +00:00
parent c4b7b2d9f2
commit 26c046cdfa
51 changed files with 2345 additions and 516 deletions

202
Rakefile Normal file
View file

@ -0,0 +1,202 @@
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
$VERBOSE = nil
TEST_CHANGES_SINCE = Time.now - 600
desc "Run all the tests on a fresh test database"
task :default => [ :test_units, :test_functional ]
desc 'Require application environment.'
task :environment do
unless defined? RAILS_ROOT
require File.dirname(__FILE__) + '/config/environment'
end
end
desc "Generate API documentation, show coding stats"
task :doc => [ :appdoc, :stats ]
# Look up tests for recently modified sources.
def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
FileList[source_pattern].map do |path|
if File.mtime(path) > touched_since
test = "#{test_path}/#{File.basename(path, '.rb')}_test.rb"
test if File.exists?(test)
end
end.compact
end
desc 'Test recent changes.'
Rake::TestTask.new(:recent => [ :clone_structure_to_test ]) do |t|
since = TEST_CHANGES_SINCE
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
recent_tests('app/models/*.rb', 'test/unit', since) +
recent_tests('app/controllers/*.rb', 'test/functional', since)
t.libs << 'test'
t.verbose = true
t.test_files = touched.uniq
end
task :test_recent => [ :clone_structure_to_test ]
desc "Run the unit tests in test/unit"
Rake::TestTask.new("test_units") { |t|
t.libs << "test"
t.pattern = 'test/unit/**/*_test.rb'
t.verbose = true
}
task :test_units => [ :clone_structure_to_test ]
desc "Run the functional tests in test/functional"
Rake::TestTask.new("test_functional") { |t|
t.libs << "test"
t.pattern = 'test/functional/**/*_test.rb'
t.verbose = true
}
task :test_functional => [ :clone_structure_to_test ]
desc "Generate documentation for the application"
Rake::RDocTask.new("appdoc") { |rdoc|
rdoc.rdoc_dir = 'doc/app'
rdoc.title = "Rails Application Documentation"
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('doc/README_FOR_APP')
rdoc.rdoc_files.include('app/**/*.rb')
}
desc "Generate documentation for the Rails framework"
Rake::RDocTask.new("apidoc") { |rdoc|
rdoc.rdoc_dir = 'doc/api'
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
rdoc.title = "Rails Framework Documentation"
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
rdoc.rdoc_files.include('vendor/rails/activerecord/README')
rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
rdoc.rdoc_files.include('vendor/rails/actionpack/README')
rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/api/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/client/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/container/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/dispatcher/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/protocol/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/support/*.rb')
rdoc.rdoc_files.include('vendor/rails/activesupport/README')
rdoc.rdoc_files.include('vendor/rails/activesupport/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
}
desc "Report code statistics (KLOCs, etc) from the application"
task :stats => [ :environment ] do
require 'code_statistics'
CodeStatistics.new(
["Helpers", "app/helpers"],
["Controllers", "app/controllers"],
["APIs", "app/apis"],
["Components", "components"],
["Functionals", "test/functional"],
["Models", "app/models"],
["Units", "test/unit"]
).to_s
end
desc "Recreate the test databases from the development structure"
task :clone_structure_to_test => [ :db_structure_dump, :purge_test_database ] do
abcs = ActiveRecord::Base.configurations
case abcs["test"]["adapter"]
when "mysql"
ActiveRecord::Base.establish_connection(:test)
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
ActiveRecord::Base.connection.execute(table)
end
when "postgresql"
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
`psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
when "sqlite", "sqlite3"
`#{abcs[RAILS_ENV]["adapter"]} #{abcs["test"]["dbfile"]} < db/#{RAILS_ENV}_structure.sql`
when "sqlserver"
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
else
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
end
end
desc "Dump the database structure to a SQL file"
task :db_structure_dump => :environment do
abcs = ActiveRecord::Base.configurations
case abcs[RAILS_ENV]["adapter"]
when "mysql"
ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
when "postgresql"
ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
`pg_dump -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{abcs[RAILS_ENV]["database"]}`
when "sqlite", "sqlite3"
`#{abcs[RAILS_ENV]["adapter"]} #{abcs[RAILS_ENV]["dbfile"]} .schema > db/#{RAILS_ENV}_structure.sql`
when "sqlserver"
`scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
`scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
else
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
end
end
desc "Empty the test database"
task :purge_test_database => :environment do
abcs = ActiveRecord::Base.configurations
case abcs["test"]["adapter"]
when "mysql"
ActiveRecord::Base.establish_connection(:test)
ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
when "postgresql"
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
`dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
`createdb -T template0 -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
when "sqlite","sqlite3"
File.delete(abcs["test"]["dbfile"]) if File.exist?(abcs["test"]["dbfile"])
when "sqlserver"
dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
else
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
end
end
desc "Clears all *.log files in log/"
task :clear_logs => :environment do
FileList["log/*.log"].each do |log_file|
f = File.open(log_file, "w")
f.close
end
end
desc "Migrate the database according to the migrate scripts in db/migrate (only supported on PG/MySQL). A specific version can be targetted with VERSION=x"
task :migrate => :environment do
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/db/migrate/', ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
end

View file

@ -46,7 +46,6 @@ class AdminController < ApplicationController
end
def edit_web
system_password = @params['system_password']
if system_password
# form submitted
@ -67,6 +66,7 @@ class AdminController < ApplicationController
flash[:info] = "Web '#{@params['address']}' was successfully updated"
redirect_home(@params['address'])
rescue Instiki::ValidationError => e
logger.warn e.message
@error = e.message
# and re-render the same template again
end

View file

@ -10,12 +10,12 @@ class ApplicationController < ActionController::Base
# a global variable is used here because Rails reloads controller and model classes in the
# development environment; therefore, storing it as a class variable does not work
# class variable is, anyway, not much different from a global variable
$instiki_wiki_service = the_wiki
#$instiki_wiki_service = the_wiki
logger.debug("Wiki service: #{the_wiki.to_s}")
end
def self.wiki
$instiki_wiki_service
Wiki.new
end
protected
@ -146,7 +146,7 @@ class ApplicationController < ActionController::Base
end
def wiki
$instiki_wiki_service
self.class.wiki
end
def needs_authorization?(action)

View file

@ -78,7 +78,7 @@ class FileController < ApplicationController
return false
end
unless @web.allow_uploads
unless @web.allow_uploads?
render_text 'File uploads are blocked by the webmaster', '403 Forbidden'
return false
end

View file

@ -1,4 +1,3 @@
require 'application'
require 'fileutils'
require 'redcloth_for_tex'
require 'parsedate'
@ -156,7 +155,7 @@ class WikiController < ApplicationController
end
def published
if @web.published
if @web.published?
@page = wiki.read_page(@web_name, @page_name || 'HomePage')
else
redirect_home
@ -270,7 +269,7 @@ class WikiController < ApplicationController
end
def export_web_to_tex(file_path)
@tex_content = table_of_contents(@web.pages['HomePage'].content, render_tex_web)
@tex_content = table_of_contents(@web.page('HomePage').content, render_tex_web)
File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex_web')) }
end
@ -342,7 +341,7 @@ class WikiController < ApplicationController
end
def rss_with_content_allowed?
@web.password.nil? or @web.published
@web.password.nil? or @web.published?
end
def truncate(text, length = 30, truncate_string = '...')

View file

@ -1,4 +1,125 @@
class Page < ActiveRecord::Base
belongs_to :web
has_many :pages
end
has_many :revisions, :order => 'number'
has_one :current_revision, :class_name => 'Revision', :order => 'number DESC'
def revise(content, created_at, author)
revisions_size = new_record? ? 0 : revisions.size
if (revisions_size > 0) and content == current_revision.content
raise Instiki::ValidationError.new(
"You have tried to save page '#{name}' without changing its content")
end
author = Author.new(author.to_s) unless author.is_a?(Author)
# Try to render content to make sure that markup engine can take it,
# before addin a revision to the page
Revision.new(:page => self, :content => content, :created_at => created_at, :author => author).force_rendering
# A user may change a page, look at it and make some more changes - several times.
# Not to record every such iteration as a new revision, if the previous revision was done
# by the same author, not more than 30 minutes ago, then update the last revision instead of
# creating a new one
if (revisions_size > 0) && continous_revision?(created_at, author)
current_revision.update_attributes(:created_at => created_at, :content => content)
else
Revision.create(:page => self, :content => content, :created_at => created_at, :author => author)
end
self.created_at = created_at
save
web.refresh_pages_with_references(name) if revisions_size == 0
self
end
def rollback(revision_number, created_at, author_ip = nil)
roll_back_revision = Revision.find(:first, :conditions => ['page_id = ? AND number = ?', id, revision_number])
revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
end
def revisions?
revisions.size > 1
end
def revised_on
created_on
end
def in_category?(cat)
cat.nil? || cat.empty? || categories.include?(cat)
end
def categories
display_content.find_chunks(Category).map { |cat| cat.list }.flatten
end
def authors
revisions.collect { |rev| rev.author }
end
def references
web.select.pages_that_reference(name)
end
def linked_from
web.select.pages_that_link_to(name)
end
def included_from
web.select.pages_that_include(name)
end
# Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
def plain_name
web.brackets_only? ? name : WikiWords.separate(name)
end
# used to build chunk ids.
#def id
# @id ||= name.unpack('H*').first
#end
def link(options = {})
web.make_link(name, nil, options)
end
def author_link(options = {})
web.make_link(author, nil, options)
end
LOCKING_PERIOD = 30.minutes
def lock(time, locked_by)
update_attributes(:locked_at => time, :locked_by => locked_by)
end
def lock_duration(time)
((time - locked_at) / 60).to_i unless locked_at.nil?
end
def unlock
update_attribute(:locked_at, nil)
end
def locked?(comparison_time)
locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
end
private
def continous_revision?(created_at, author)
current_revision.author == author && current_revision.created_at + 30.minutes > created_at
end
# Forward method calls to the current revision, so the page responds to all revision calls
def method_missing(method_id, *args, &block)
method_name = method_id.to_s
# Perform a hand-off to AR::Base#method_missing
if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
super(method_id, *args, &block)
else
current_revision.send(method_id)
end
end
end

View file

@ -1,3 +1,122 @@
require 'diff'
class Revision < ActiveRecord::Base
belongs_to :page
end
composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
def created_on
created_at.to_date
end
def pretty_created_at
# Must use DateTime because Time doesn't support %e on at least some platforms
DateTime.new(
created_at.year, created_at.mon, created_at.day, created_at.hour, created_at.min
).strftime "%B %e, %Y %H:%M"
end
# todo: drop next_revision, previuous_revision and number from here - unused code
def next_revision
Revision.find_by_number_and_page_id(number+1, page_id)
end
def previous_revision
@previous_revions ||= number > 0 ? Revision.find_by_number_and_page_id(number-1, page_id) : nil
end
# Returns an array of all the WikiIncludes present in the content of this revision.
def wiki_includes
unless @wiki_includes_cache
chunks = display_content.find_chunks(Include)
@wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_includes_cache
end
# Returns an array of all the WikiReferences present in the content of this revision.
def wiki_references
unless @wiki_references_cache
chunks = display_content.find_chunks(WikiChunk::WikiReference)
@wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_references_cache
end
# Returns an array of all the WikiWords present in the content of this revision.
def wiki_words
unless @wiki_words_cache
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_words_cache
end
# Returns an array of all the WikiWords present in the content of this revision.
# that already exists as a page in the web.
def existing_pages
wiki_words.select { |wiki_word| page.web.page(wiki_word) }
end
# Returns an array of all the WikiWords present in the content of this revision
# that *doesn't* already exists as a page in the web.
def unexisting_pages
wiki_words - existing_pages
end
# Explicit check for new type of display cache with chunks_by_type method.
# Ensures new version works with older snapshots.
def display_content
unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
@display_cache = WikiContent.new(self)
@display_cache.render!
end
@display_cache
end
def display_diff
previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
end
def clear_display_cache
@wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
@wiki_references_cache = nil
end
def display_published
unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
@published_cache = WikiContent.new(self, {:mode => :publish})
@published_cache.render!
end
@published_cache
end
def display_content_for_export
WikiContent.new(self, {:mode => :export} ).render!
end
def force_rendering
begin
display_content.render!
rescue => e
logger.error "Failed rendering page #{@name}"
logger.error e
message = e.message
# substitute content with an error message
self.content = <<-EOL
<p>Markup engine has failed to render this page, raising the following error:</p>
<p>#{message}</p>
<pre>#{self.content}</pre>
EOL
clear_display_cache
raise e
end
end
protected
before_create :set_revision_number
after_create :force_rendering
after_save :clear_display_cache
def set_revision_number
self.number = self.class.count(['page_id = ?', page_id]) + 1
end
end

4
app/models/system.rb Normal file
View file

@ -0,0 +1,4 @@
class System < ActiveRecord::Base
set_table_name 'system'
validates_presence_of :password
end

View file

@ -1,3 +1,173 @@
require 'cgi'
class Web < ActiveRecord::Base
has_many :pages
end
has_many :pages#, :include => [:current_revision, :web]
def wiki
Wiki.new
end
def file_yard
@file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
end
def settings_changed?(markup, safe_mode, brackets_only)
self.markup != markup ||
self.safe_mode != safe_mode ||
self.brackets_only != brackets_only
end
def add_page(name, content, created_at, author)
page = page(name) || Page.new(:web => self, :name => name)
page.revise(content, created_at, author)
end
def authors
select.authors
end
def categories
select.map { |page| page.categories }.flatten.uniq.sort
end
def page(name)
pages.find(:first, :conditions => ['name = ?', name])
end
def has_page?(name)
Page.count(['web_id = ? AND name = ?', id, name]) > 0
end
def has_file?(name)
wiki.file_yard(self).has_file?(name)
end
def markup
read_attribute('markup').to_sym
end
def make_file_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode
when :export
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
else "<span class=\"newWikiWord\">#{text}</span>" end
when :publish
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{base_url}/published/#{link}\">#{text}</a>"
else "<span class=\"newWikiWord\">#{text}</span>" end
else
if has_file?(name)
"<a class=\"existingWikiWord\" href=\"#{base_url}/file/#{link}\">#{text}</a>"
else
"<span class=\"newWikiWord\">#{text}<a href=\"#{base_url}/file/#{link}\">?</a></span>"
end
end
end
# Create a link for the given page name and link text based
# on the render mode in options and whether the page exists
# in the this web.
# The links a relative, and will work only if displayed on another WikiPage.
# It should not be used in menus, templates and such - instead, use link_to_page helper
def make_link(name, text = nil, options = {})
text = CGI.escapeHTML(text || WikiWords.separate(name))
mode = options[:mode] || :show
base_url = options[:base_url] || '..'
link_type = options[:link_type] || :show
case link_type.to_sym
when :show
make_page_link(mode, name, text, base_url)
when :file
make_file_link(mode, name, text, base_url)
when :pic
make_pic_link(mode, name, text, base_url)
else
raise "Unknown link type: #{link_type}"
end
end
def make_page_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode.to_sym
when :export
if has_page?(name) then %{<a class="existingWikiWord" href="#{link}.html">#{text}</a>}
else %{<span class="newWikiWord">#{text}</span>} end
when :publish
if has_page?(name) then %{<a class="existingWikiWord" href="#{base_url}/published/#{link}">#{text}</a>}
else %{<span class="newWikiWord">#{text}</span>} end
else
if has_page?(name)
%{<a class="existingWikiWord" href="#{base_url}/show/#{link}">#{text}</a>}
else
%{<span class="newWikiWord">#{text}<a href="#{base_url}/show/#{link}">?</a></span>}
end
end
end
def make_pic_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode.to_sym
when :export
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
else %{<img alt="#{text}" src="no image" />} end
when :publish
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
else %{<span class="newWikiWord">#{text}</span>} end
else
if has_file?(name) then %{<img alt="#{text}" src="#{base_url}/pic/#{link}" />}
else %{<span class="newWikiWord">#{text}<a href="#{base_url}/pic/#{link}">?</a></span>} end
end
end
# Clears the display cache for all the pages with references to
def refresh_pages_with_references(page_name)
#select.pages_that_reference(page_name).each { |page|
# page.revisions.each { |revision| revision.clear_display_cache }
#}
end
def refresh_revisions
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
end
def remove_pages(pages_to_be_removed)
pages_to_be_removed.each { |p| p.destroy }
end
def revised_on
select.most_recent_revision
end
def select(&condition)
PageSet.new(self, pages, condition)
end
private
# Returns an array of all the wiki words in any current revision
def wiki_words
pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
end
# Returns an array of all the page names on this web
def page_names
pages.map { |p| p.name }
end
protected
before_save :sanitize_markup
before_validation :validate_address
validates_uniqueness_of :address
validates_length_of :color, :in => 3..6
def sanitize_markup
self.markup = markup.to_s
end
def validate_address
unless address == CGI.escape(address)
self.errors.add(:address, 'should contain only valid URI characters')
raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
end
end
end

View file

@ -17,7 +17,7 @@
</li>
<% end %></ul>
<% if @web.count_pages %>
<% if @web.count_pages? %>
<% total_chars = @pages_in_category.characters %>
<p><small>All content: <%= total_chars %> chars / <%= sprintf("%-.1f", (total_chars / 2275 )) %> pages</small></p>
<% end %>

View file

@ -25,7 +25,7 @@
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
by <%= @page.author_link %>
<%= "(#{@page.author.ip})" if @page.author.respond_to?(:ip) %>
<% if @web.count_pages %>
<% if @web.count_pages? %>
<% total_chars = @page.content.length %>
(<%= total_chars %> characters / <%= sprintf("%-.1f", (total_chars / 2275 rescue 0)) %> pages)
<% end %>

View file

@ -1,30 +1,65 @@
# SQLite is enabled by default. Remember to change the dbfile path.
production:
adapter: sqlite3
dbfile: /tmp/instiki_prod.db
# Uncomment this section for MySQL:
# production:
# adapter: mysql
# host: localhost
# database: instiki
# username: instiki
# password: pass
# Uncomment this section for PostgreSQL:
# production:
# adapter: postgresql
# host: localhost
# database: instiki
# username: instiki
# password: pass
# The following settings are only used for testing and development.
dbfile: db/prod.db
development:
adapter: sqlite3
dbfile: /tmp/instiki_dev.db
dbfile: db/dev.db
test:
adapter: sqlite3
dbfile: /tmp/instiki_test.db
dbfile: db/test.db
# Sample Sqlite 2 Config
#production:
# adapter: sqlite
# dbfile: db/prod.db
#development:
# adapter: sqlite
# dbfile: db/dev.db
#test:
# adapter: sqlite
# dbfile: db/test.db
# Sample Postgresql Config
#production:
# adapter: postgresql
# host: localhost
# database: instiki_prod
# username: user
# password: pass
#
#development:
# adapter: postgresql
# host: localhost
# database: instiki_dev
# username: user
# password: pass
#
#test:
# adapter: postgresql
# host: localhost
# database: instiki_test
# username: user
# password: pass
# Sample MySQL Config
#production:
# adapter: mysql
# host: localhost
# database: instiki_prod
# username: user
# password: pass
#
#development:
# adapter: mysql
# host: localhost
# database: instiki_dev
# username: user
# password: pass
#
#test:
# adapter: mysql
# host: localhost
# database: instiki_test
# username: user
# password: pass

View file

@ -60,6 +60,8 @@ require 'rubygems' unless File.directory?("#{RAILS_ROOT}/vendor/rails")
require 'active_support'
require 'active_record'
require 'action_controller'
require 'action_mailer'
require 'action_web_service'
# Environment-specific configuration.
require_dependency "environments/#{RAILS_ENV}"

View file

@ -2,4 +2,3 @@ Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = true
ActionController::Base.perform_caching = false
BREAKPOINT_SERVER_PORT = 42531
$instiki_debug_logging = true

View file

@ -1,15 +1,4 @@
Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = true
ActionController::Base.perform_caching = false
require 'fileutils'
FileUtils.mkdir_p(RAILS_ROOT + "/log")
unless defined? TEST_LOGGER
timestamp = Time.now.strftime('%Y%m%d%H%M%S')
log_name = RAILS_ROOT + "/log/instiki_test.#{timestamp}.log"
$stderr.puts "To see the Rails log:\n less #{log_name}"
TEST_LOGGER = ActionController::Base.logger = Logger.new(log_name)
$instiki_debug_logging = true
end
FileYard.restrict_upload_access = false

View file

@ -0,0 +1,40 @@
CREATE TABLE pages (
id INTEGER PRIMARY KEY,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
web_id INTEGER NOT NULL,
locked_by VARCHAR(60),
name VARCHAR(60),
locked_at DATETIME
);
CREATE TABLE revisions (
id INTEGER PRIMARY KEY,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
page_id INTEGER NOT NULL,
content TEXT NOT NULL,
author VARCHAR(60),
ip VARCHAR(60),
number INTEGER
);
CREATE TABLE system (
id INTEGER PRIMARY KEY,
'password' VARCHAR(60)
);
CREATE TABLE webs (
id INTEGER PRIMARY KEY,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
name VARCHAR(60) NOT NULL,
address VARCHAR(60) NOT NULL,
'password' VARCHAR(60),
additional_style VARCHAR(255),
allow_uploads INTEGER DEFAULT '1',
published INTEGER DEFAULT '0',
count_pages INTEGER DEFAULT '0',
markup VARCHAR(50) DEFAULT 'textile',
color VARCHAR(6) DEFAULT '008B26',
max_upload_size INTEGER DEFAULT 100,
safe_mode INTEGER DEFAULT '0',
brackets_only INTEGER DEFAULT '0'
);

View file

@ -2,5 +2,8 @@ CREATE TABLE pages (
id <%= @pk %>,
created_at <%= @datetime %> NOT NULL,
updated_at <%= @datetime %> NOT NULL,
web_id INTEGER NOT NULL
) <%= create_options %>;
web_id INTEGER NOT NULL,
locked_by VARCHAR(60),
name VARCHAR(60),
locked_at <%= @datetime %>
) <%= create_options %>;

View file

@ -1,7 +1,10 @@
CREATE TABLE revisions (
id <%= @pk %>,
created_at <%= @datetime %> NOT NULL,
updated_at <%= @datetime %> NOT NULL,
page_id INTEGER NOT NULL,
content TEXT NOT NULL
) <%= create_options %>;
id <%= @pk %>,
created_at <%= @datetime %> NOT NULL,
updated_at <%= @datetime %> NOT NULL,
page_id INTEGER NOT NULL,
content TEXT NOT NULL,
author VARCHAR(60),
ip VARCHAR(60),
number INTEGER
) <%= create_options %>;

43
db/schema.postgre.sql Normal file
View file

@ -0,0 +1,43 @@
CREATE TABLE pages (
id serial primary key,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
web_id integer NOT NULL,
locked_by character varying(60),
name character varying(60),
locked_at timestamp without time zone
);
CREATE TABLE revisions (
id serial primary key,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
page_id integer NOT NULL,
content text NOT NULL,
author character varying(60),
ip character varying(60),
number integer
);
CREATE TABLE system (
id serial primary key,
"password" character varying(60)
);
CREATE TABLE webs (
id serial primary key,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
name character varying(60) NOT NULL,
address character varying(60) NOT NULL,
"password" character varying(60),
additional_style character varying(255),
allow_uploads boolean DEFAULT true,
published boolean DEFAULT false,
count_pages boolean DEFAULT false,
markup character varying(50) DEFAULT 'textile'::character varying,
color character varying(6) DEFAULT '008B26'::character varying,
max_upload_size integer DEFAULT 100,
safe_mode boolean DEFAULT false,
brackets_only boolean DEFAULT false
);

4
db/system.erbsql Normal file
View file

@ -0,0 +1,4 @@
CREATE TABLE system (
id <%= @pk %>,
<%= db_quote('password') %> VARCHAR(60)
) <%= create_options %>;

View file

@ -3,5 +3,15 @@ CREATE TABLE webs (
created_at <%= @datetime %> NOT NULL,
updated_at <%= @datetime %> NOT NULL,
name VARCHAR(60) NOT NULL,
address VARCHAR(60) NOT NULL
) <%= create_options %>;
address VARCHAR(60) NOT NULL,
<%= db_quote('password') %> VARCHAR(60),
additional_style VARCHAR(255),
allow_uploads <%= @boolean %> DEFAULT '1',
published <%= @boolean %> DEFAULT '0',
count_pages <%= @boolean %> DEFAULT '0',
markup VARCHAR(50) DEFAULT 'textile',
color VARCHAR(6) DEFAULT '008B26',
max_upload_size INTEGER DEFAULT 100,
safe_mode <%= @boolean %> DEFAULT '0',
brackets_only <%= @boolean %> DEFAULT '0'
) <%= create_options %>;

18
lib/author.rb Normal file
View file

@ -0,0 +1,18 @@
class Author < String
attr_accessor :ip
attr_reader :name
def initialize(name, ip = nil)
@ip = ip
super(name)
end
def name=(value)
self.gsub!(/.+/, value)
end
alias_method :name, :to_s
def <=>(other)
name <=> other.to_s
end
end

View file

@ -4,7 +4,7 @@ class ChunkTest < Test::Unit::TestCase
# Asserts a number of tests for the given type and text.
def match(type, test_text, expected)
pattern = type.pattern
pattern = type.pattern
assert_match(pattern, test_text)
pattern =~ test_text # Previous assertion guarantees match
chunk = type.new($~)

View file

@ -6,6 +6,17 @@ def create_options
end
end
def db_quote(column)
case @db
when 'postgresql'
return "\"#{column}\""
when 'sqlite', 'sqlite3'
return "'#{column}'"
when 'mysql'
return "`#{column}`"
end
end
def db_structure(db)
db.downcase!
@db = db
@ -13,12 +24,15 @@ def db_structure(db)
when 'postgresql'
@pk = 'SERIAL PRIMARY KEY'
@datetime = 'TIMESTAMP'
@boolean = "BOOLEAN"
when 'sqlite', 'sqlite3'
@pk = 'INTEGER PRIMARY KEY'
@datetime = 'DATETIME'
@boolean = "INTEGER"
when 'mysql'
@pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
@datetime = 'DATETIME'
@boolean = "TINYINT"
@mysql_engine = 'InnoDB'
else
raise "Unknown db type #{db}"

59
lib/file_yard.rb Normal file
View file

@ -0,0 +1,59 @@
require 'fileutils'
require 'instiki_errors'
class FileYard
cattr_accessor :restrict_upload_access
restrict_upload_access = true
attr_reader :files_path
def initialize(files_path, max_upload_size)
@files_path, @max_upload_size = files_path, max_upload_size
FileUtils.mkdir_p(@files_path) unless File.exist?(@files_path)
@files = Dir["#{@files_path}/*"].collect{|path| File.basename(path) if File.file?(path) }.compact
end
def upload_file(name, io)
sanitize_file_name(name)
if io.kind_of?(Tempfile)
io.close
check_upload_size(io.size)
File.chmod(600, file_path(name)) if File.exists? file_path(name)
FileUtils.mv(io.path, file_path(name))
else
content = io.read
check_upload_size(content.length)
File.open(file_path(name), 'wb') { |f| f.write(content) }
end
# just in case, restrict read access and prohibit write access to the uploaded file
FileUtils.chmod(0440, file_path(name)) if restrict_upload_access
end
def files
Dir["#{files_path}/*"].collect{|path| File.basename(path) if File.file?(path)}.compact
end
def has_file?(name)
files.include?(name)
end
def file_path(name)
"#{files_path}/#{name}"
end
SANE_FILE_NAME = /[a-zA-Z0-9\-_\. ]{1,255}/
def sanitize_file_name(name)
unless name =~ SANE_FILE_NAME or name == '.' or name == '..'
raise Instiki::ValidationError.new("Invalid file name: '#{name}'.\n" +
"Only latin characters, digits, dots, underscores, dashes and spaces are accepted.")
end
end
def check_upload_size(actual_upload_size)
if actual_upload_size > @max_upload_size.kilobytes
raise Instiki::ValidationError.new("Uploaded file size (#{actual_upload_size / 1024} " +
"kbytes) exceeds the maximum (#{@max_upload_size} kbytes) set for this wiki")
end
end
end

89
lib/page_set.rb Normal file
View file

@ -0,0 +1,89 @@
# Container for a set of pages with methods for manipulation.
class PageSet < Array
attr_reader :web
def initialize(web, pages = nil, condition = nil)
@web = web
# if pages is not specified, make a list of all pages in the web
if pages.nil?
super(web.pages)
# otherwise use specified pages and condition to produce a set of pages
elsif condition.nil?
super(pages)
else
super(pages.select { |page| condition[page] })
end
end
def most_recent_revision
self.map { |page| page.created_at }.max || Time.at(0)
end
def by_name
PageSet.new(@web, sort_by { |page| page.name })
end
alias :sort :by_name
def by_revision
PageSet.new(@web, sort_by { |page| page.created_at }).reverse
end
def pages_that_reference(page_name)
self.select { |page| page.wiki_references.include?(page_name) }
end
def pages_that_link_to(page_name)
self.select { |page| page.wiki_words.include?(page_name) }
end
def pages_that_include(page_name)
self.select { |page| page.wiki_includes.include?(page_name) }
end
def pages_authored_by(author)
self.select { |page| page.authors.include?(author) }
end
def characters
self.inject(0) { |chars,page| chars += page.content.size }
end
# Returns all the orphaned pages in this page set. That is,
# pages in this set for which there is no reference in the web.
# The HomePage and author pages are always assumed to have
# references and so cannot be orphans
# Pages that refer to themselves and have no links from outside are oprphans.
def orphaned_pages
never_orphans = web.select.authors + ['HomePage']
self.select { |page|
if never_orphans.include? page.name
false
else
references = pages_that_reference(page.name)
references.empty? or references == [page]
end
}
end
# Returns all the wiki words in this page set for which
# there are no pages in this page set's web
def wanted_pages
wiki_words - web.select.names
end
def names
self.map { |page| page.name }
end
def wiki_words
self.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
end
def authors
self.inject([]) { |authors, page| authors << page.authors }.flatten.uniq.sort
end
end

96
lib/wiki.rb Normal file
View file

@ -0,0 +1,96 @@
class Wiki
cattr_accessor :storage_path, :logger
self.storage_path = "#{RAILS_ROOT}/storage/"
self.logger = RAILS_DEFAULT_LOGGER
def authenticate(password)
password == (system.password || 'instiki')
end
def create_web(name, address, password = nil)
@webs = nil
Web.create(:name => name, :address => address, :password => password)
end
def delete_web(address)
web = Web.find_by_address(address)
unless web.nil?
web.destroy
@webs = nil
end
end
def file_yard(web)
web.file_yard
end
def edit_web(old_address, new_address, name, markup, color, additional_style, safe_mode = false,
password = nil, published = false, brackets_only = false, count_pages = false,
allow_uploads = true, max_upload_size = nil)
if not (web = Web.find_by_address(old_address))
raise Instiki::ValidationError.new("Web with address '#{old_address}' does not exist")
end
web.refresh_revisions if web.settings_changed?(markup, safe_mode, brackets_only)
web.update_attributes(:address => new_address, :name => name, :markup => markup, :color => color,
:additional_style => additional_style, :safe_mode => safe_mode, :password => password, :published => published,
:brackets_only => brackets_only, :count_pages => count_pages, :allow_uploads => allow_uploads, :max_upload_size => max_upload_size)
@webs = nil
raise Instiki::ValidationError.new("There is already a web with address '#{new_address}'") unless web.errors.on(:address).nil?
web
end
def read_page(web_address, page_name)
self.class.logger.debug "Reading page '#{page_name}' from web '#{web_address}'"
web = Web.find_by_address(web_address)
if web.nil?
self.class.logger.debug "Web '#{web_address}' not found"
return nil
else
page = web.pages.find(:first, :conditions => ['name = ?', page_name])
self.class.logger.debug "Page '#{page_name}' #{page.nil? ? 'not' : ''} found"
return page
end
end
def remove_orphaned_pages(web_address)
web = Web.find_by_address(web_address)
web.remove_pages(web.select.orphaned_pages)
end
def revise_page(web_address, page_name, content, revised_on, author)
page = read_page(web_address, page_name)
page.revise(content, revised_on, author)
end
def rollback_page(web_address, page_name, revision_number, created_at, author_id = nil)
page = read_page(web_address, page_name)
page.rollback(revision_number, created_at, author_id)
end
def setup(password, web_name, web_address)
system.update_attribute(:password, password)
create_web(web_name, web_address)
end
def system
@system ||= (System.find(:first) || System.create)
end
def setup?
Web.count > 0
end
def webs
@webs ||= Web.find(:all).inject({}) { |webs, web| webs.merge(web.address => web) }
end
def storage_path
self.class.storage_path
end
def write_page(web_address, page_name, content, written_on, author)
Web.find_by_address(web_address).add_page(page_name, content, written_on, author)
end
end

206
lib/wiki_content.rb Normal file
View file

@ -0,0 +1,206 @@
require 'cgi'
require 'chunks/engines'
require 'chunks/category'
require 'chunks/include'
require 'chunks/wiki'
require 'chunks/literal'
require 'chunks/uri'
require 'chunks/nowiki'
# Wiki content is just a string that can process itself with a chain of
# actions. The actions can modify wiki content so that certain parts of
# it are protected from being rendered by later actions.
#
# When wiki content is rendered, it can be interrogated to find out
# which chunks were rendered. This means things like categories, wiki
# links, can be determined.
#
# Exactly how wiki content is rendered is determined by a number of
# settings that are optionally passed in to a constructor. The current
# options are:
# * :engine
# => The structural markup engine to use (Textile, Markdown, RDoc)
# * :engine_opts
# => A list of options to pass to the markup engines (safe modes, etc)
# * :pre_engine_actions
# => A list of render actions or chunks to be processed before the
# markup engine is applied. By default this is:
# Category, Include, URIChunk, WikiChunk::Link, WikiChunk::Word
# * :post_engine_actions
# => A list of render actions or chunks to apply after the markup
# engine. By default these are:
# Literal::Pre, Literal::Tags
# * :mode
# => How should the content be rendered? For normal display (show),
# publishing (:publish) or export (:export)?
module ChunkManager
attr_reader :chunks_by_type, :chunks_by_id, :chunks, :chunk_id
ACTIVE_CHUNKS = [ NoWiki, Category, WikiChunk::Link, URIChunk, LocalURIChunk,
WikiChunk::Word ]
HIDE_CHUNKS = [ Literal::Pre, Literal::Tags ]
MASK_RE = {
ACTIVE_CHUNKS => Chunk::Abstract.mask_re(ACTIVE_CHUNKS),
HIDE_CHUNKS => Chunk::Abstract.mask_re(HIDE_CHUNKS)
}
def init_chunk_manager
@chunks_by_type = Hash.new
Chunk::Abstract::derivatives.each{|chunk_type|
@chunks_by_type[chunk_type] = Array.new
}
@chunks_by_id = Hash.new
@chunks = []
@chunk_id = 0
end
def add_chunk(c)
@chunks_by_type[c.class] << c
@chunks_by_id[c.id] = c
@chunks << c
@chunk_id += 1
end
def delete_chunk(c)
@chunks_by_type[c.class].delete(c)
@chunks_by_id.delete(c.id)
@chunks.delete(c)
end
def merge_chunks(other)
other.chunks.each{|c| add_chunk(c)}
end
def scan_chunkid(text)
text.scan(MASK_RE[ACTIVE_CHUNKS]){|a| yield a[0] }
end
def find_chunks(chunk_type)
@chunks.select { |chunk| chunk.kind_of?(chunk_type) and chunk.rendered? }
end
# for testing and WikiContentStub; we need a page_id even if we have no page
def page_id
0
end
end
# A simplified version of WikiContent. Useful to avoid recursion problems in
# WikiContent.new
class WikiContentStub < String
attr_reader :options
include ChunkManager
def initialize(content, options)
super(content)
@options = options
init_chunk_manager
end
# Detects the mask strings contained in the text of chunks of type chunk_types
# and yields the corresponding chunk ids
# example: content = "chunk123categorychunk <pre>chunk456categorychunk</pre>"
# inside_chunks(Literal::Pre) ==> yield 456
def inside_chunks(chunk_types)
chunk_types.each{|chunk_type| chunk_type.apply_to(self) }
chunk_types.each{|chunk_type| @chunks_by_type[chunk_type].each{|hide_chunk|
scan_chunkid(hide_chunk.text){|id| yield id }
}
}
end
end
class WikiContent < String
include ChunkManager
DEFAULT_OPTS = {
:active_chunks => ACTIVE_CHUNKS,
:engine => Engines::Textile,
:engine_opts => [],
:mode => :show
}.freeze
attr_reader :web, :options, :revision, :not_rendered, :pre_rendered
# Create a new wiki content string from the given one.
# The options are explained at the top of this file.
def initialize(revision, options = {})
@revision = revision
@web = @revision.page.web
@options = DEFAULT_OPTS.dup.merge(options)
@options[:engine] = Engines::MAP[@web.markup]
@options[:engine_opts] = [:filter_html, :filter_styles] if @web.safe_mode?
@options[:active_chunks] = (ACTIVE_CHUNKS - [WikiChunk::Word] ) if @web.brackets_only?
@not_rendered = @pre_rendered = nil
super(@revision.content)
init_chunk_manager
build_chunks
@not_rendered = String.new(self)
end
# Call @web.page_link using current options.
def page_link(name, text, link_type)
@options[:link_type] = (link_type || :show)
@web.make_link(name, text, @options)
end
def build_chunks
# create and mask Includes and "active_chunks" chunks
Include.apply_to(self)
@options[:active_chunks].each{|chunk_type| chunk_type.apply_to(self)}
# Handle hiding contexts like "pre" and "code" etc..
# The markup (textile, rdoc etc) can produce such contexts with its own syntax.
# To reveal them, we work on a copy of the content.
# The copy is rendered and used to detect the chunks that are inside protecting context
# These chunks are reverted on the original content string.
copy = WikiContentStub.new(self, @options)
@options[:engine].apply_to(copy)
copy.inside_chunks(HIDE_CHUNKS) do |id|
@chunks_by_id[id].revert
end
end
def pre_render!
unless @pre_rendered
@chunks_by_type[Include].each{|chunk| chunk.unmask }
@pre_rendered = String.new(self)
end
@pre_rendered
end
def render!
pre_render!
@options[:engine].apply_to(self)
# unmask in one go. $~[1] is the chunk id
gsub!(MASK_RE[ACTIVE_CHUNKS]){
if chunk = @chunks_by_id[$~[1]]
chunk.unmask_text
# if we match a chunkmask that existed in the original content string
# just keep it as it is
else
$~[0]
end}
self
end
def page_name
@revision.page.name
end
def page_id
@revision.page.id
end
end

23
lib/wiki_words.rb Normal file
View file

@ -0,0 +1,23 @@
# Contains all the methods for finding and replacing wiki words
module WikiWords
# In order of appearance: Latin, greek, cyrillian, armenian
I18N_HIGHER_CASE_LETTERS =
"À<EFBFBD>?ÂÃÄÅĀĄĂÆÇĆČĈĊĎ<C48A>?ÈÉÊËĒĘĚĔĖĜĞĠĢĤĦÌ<C4A6><>?ĪĨĬĮİIJĴĶ<C4B4>?ĽĹĻĿÑŃŇŅŊÒÓÔÕÖØŌ<C398>?ŎŒŔŘŖŚŠŞŜȘŤŢŦȚÙÚÛÜŪŮŰŬŨŲŴ<C5B2>?ŶŸŹŽŻ" +
"ΑΒΓΔΕΖΗΘΙΚΛΜ<EFBFBD>?ΞΟΠΡΣΤΥΦΧΨΩ" +
"ΆΈΉΊΌΎ<EFBFBD>?ѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎ<D28C>?ҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾ<D2BC>?ӃӅӇӉӋ<D389>?<3F>?ӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӸЖ" +
"ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀ<EFBFBD>?ՂՃՄՅՆՇՈՉՊՋՌ<D58B>?<3F>?<3F>?ՑՒՓՔՕՖ"
I18N_LOWER_CASE_LETTERS =
"àáâãäå<EFBFBD>?ąăæçć<C3A7>?ĉċ<C489>?đèéêëēęěĕėƒ<C497>?ğġģĥħìíîïīĩĭįıijĵķĸłľĺļŀñńňņʼnŋòóôõöø<C3B6><>?œŕřŗśšş<C5A1>?șťţŧțùúûüūůűŭũųŵýÿŷžżźÞþßſ<C39F>" +
"άέήίΰαβγδεζηθικλμνξοπ<EFBFBD>στυφχψωϊϋό<CF8B><>?" +
"абвгдежзийклмнопр<EFBFBD>уфхцчшщъыь<D18B><>?<3F>?ёђѓєѕіїјљћќ<D19B>?ўџѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿ<D1BD><>?<3F>?ґғҕҗҙқ<D299>?ҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӀӂӄӆӈӊӌӎӑӓӕӗәӛ<D399>?ӟӡӣӥӧөӫӭӯӱӳӵӹ" +
"աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտր<EFBFBD>?ւփքօֆև"
WIKI_WORD_PATTERN = '[A-Z' + I18N_HIGHER_CASE_LETTERS + '][a-z' + I18N_LOWER_CASE_LETTERS + ']+[A-Z' + I18N_HIGHER_CASE_LETTERS + ']\w+'
CAMEL_CASED_WORD_BORDER = /([a-z#{I18N_LOWER_CASE_LETTERS}])([A-Z#{I18N_HIGHER_CASE_LETTERS}])/u
def self.separate(wiki_word)
wiki_word.gsub(CAMEL_CASED_WORD_BORDER, '\1 \2')
end
end

View file

@ -1,134 +0,0 @@
require 'rake'
require 'rake/clean'
require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
$VERBOSE = nil
# Standard Rails tasks
desc 'Run all tests'
task :default => [:test_units, :test_functional]
desc 'Require application environment.'
task :environment do
unless defined? RAILS_ROOT
require File.dirname(__FILE__) + '/config/environment'
end
end
desc 'Generate API documentatio, show coding stats'
task :doc => [ :appdoc, :stats ]
desc 'Run the unit tests in test/unit'
Rake::TestTask.new('test_units') { |t|
t.libs << 'test'
t.pattern = 'test/unit/**/*_test.rb'
t.verbose = true
}
desc 'Run the functional tests in test/functional'
Rake::TestTask.new('test_functional') { |t|
t.libs << 'test'
t.pattern = 'test/functional/**/*_test.rb'
t.verbose = true
}
desc 'Generate documentation for the application'
Rake::RDocTask.new('appdoc') { |rdoc|
rdoc.rdoc_dir = 'doc/app'
rdoc.title = 'Rails Application Documentation'
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('doc/README_FOR_APP')
rdoc.rdoc_files.include('app/**/*.rb')
}
desc 'Generate documentation for the Rails framework'
Rake::RDocTask.new("apidoc") { |rdoc|
rdoc.rdoc_dir = 'doc/api'
rdoc.title = 'Rails Framework Documentation'
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
rdoc.rdoc_files.include('vendor/rails/activerecord/README')
rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
rdoc.rdoc_files.include('vendor/rails/actionpack/README')
rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/ChangeLog')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/activesupport/README')
rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
}
desc 'Report code statistics (KLOCs, etc) from the application'
task :stats => [ :environment ] do
require 'code_statistics'
CodeStatistics.new(
['Helpers', 'app/helpers'],
['Controllers', 'app/controllers'],
['Functionals', 'test/functional'],
['Models', 'app/models'],
['Units', 'test/unit'],
['Miscellaneous (lib)', 'lib']
).to_s
end
# Additional tasks (not standard Rails)
CLEAN << 'pkg' << 'storage' << 'doc' << 'html'
begin
require 'rubygems'
require 'rake/gempackagetask'
rescue Exception => e
nil
end
if defined? Rake::GemPackageTask
gemspec = eval(File.read('instiki.gemspec'))
Rake::GemPackageTask.new(gemspec) do |p|
p.gem_spec = gemspec
p.need_tar = true
p.need_zip = true
end
Rake::PackageTask.new('instiki', gemspec.version) do |p|
p.need_tar = true
p.need_zip = true
# the list of glob expressions for files comes from instiki.gemspec
p.package_files.include($__instiki_source_patterns)
end
# Create a task to build the RDOC documentation tree.
rd = Rake::RDocTask.new("rdoc") { |rdoc|
rdoc.rdoc_dir = 'html'
rdoc.title = 'Instiki -- The Wiki'
rdoc.options << '--line-numbers --inline-source --main README'
rdoc.rdoc_files.include(gemspec.files)
rdoc.main = 'README'
}
else
puts 'Warning: without Rubygems packaging tasks are not available'
end
# Shorthand aliases
desc 'Shorthand for test_units'
task :tu => :test_units
desc 'Shorthand for test_units'
task :ut => :test_units
desc 'Shorthand for test_functional'
task :tf => :test_functional
desc 'Shorthand for test_functional'
task :ft => :test_functional

23
script/console Normal file
View file

@ -0,0 +1,23 @@
#!/usr/local/bin/ruby
irb = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
require 'optparse'
options = { :sandbox => false, :irb => irb }
OptionParser.new do |opt|
opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |options[:sandbox]| }
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |options[:irb]| }
opt.parse!(ARGV)
end
libs = " -r irb/completion"
libs << " -r #{File.dirname(__FILE__)}/../config/environment"
libs << " -r console_sandbox" if options[:sandbox]
ENV['RAILS_ENV'] = ARGV.first || 'development'
if options[:sandbox]
puts "Loading #{ENV['RAILS_ENV']} environment in sandbox."
puts "Any modifications you make will be rolled back on exit."
else
puts "Loading #{ENV['RAILS_ENV']} environment."
end
exec "#{options[:irb]} #{libs} --prompt-mode simple"

View file

@ -12,7 +12,7 @@ config = ActiveRecord::Base.configurations
ENV['RAILS_ENV'] = target
load APP_ROOT + 'config/environment.rb'
puts "Creating tables for #{target}..."
db_structure(config[target]['adapter']).split(/\s*;\s*/).each do |sql|
ActiveRecord::Base.connection.execute(sql)
end

View file

@ -1,93 +1,49 @@
#!/usr/bin/ruby
#!/usr/local/bin/ruby
require 'webrick'
require 'optparse'
require 'fileutils'
pwd = File.expand_path(File.dirname(__FILE__) + "/..")
OPTIONS = {
# Overridable options
:port => 2500,
:ip => '0.0.0.0',
:environment => 'production',
:server_root => File.expand_path(File.dirname(__FILE__) + '/../public/'),
:server_type => WEBrick::SimpleServer,
:storage => "#{File.expand_path(FileUtils.pwd)}/storage",
:port => 3000,
:ip => "0.0.0.0",
:environment => "development",
:server_root => File.expand_path(File.dirname(__FILE__) + "/../public/"),
:server_type => WEBrick::SimpleServer
}
ARGV.options do |opts|
script_name = File.basename($0)
opts.banner = "Usage: ruby #{script_name} [options]"
opts.separator ''
opts.separator ""
opts.on('-p', '--port=port', Integer,
'Runs Instiki on the specified port.',
'Default: 2500') { |OPTIONS[:port]| }
opts.on('-b', '--binding=ip', String,
'Binds Rails to the specified ip.',
'Default: 0.0.0.0') { |OPTIONS[:ip]| }
opts.on('-e', '--environment=name', String,
'Specifies the environment to run this server under (test/development/production).',
'Default: production') { |OPTIONS[:environment]| }
opts.on('-d', '--daemon',
'Make Instiki run as a Daemon (only works if fork is available -- meaning on *nix).'
opts.on("-p", "--port=port", Integer,
"Runs Rails on the specified port.",
"Default: 3000") { |OPTIONS[:port]| }
opts.on("-b", "--binding=ip", String,
"Binds Rails to the specified ip.",
"Default: 0.0.0.0") { |OPTIONS[:ip]| }
opts.on("-e", "--environment=name", String,
"Specifies the environment to run this server under (test/development/production).",
"Default: development") { |OPTIONS[:environment]| }
opts.on("-d", "--daemon",
"Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
) { OPTIONS[:server_type] = WEBrick::Daemon }
opts.on('-s', '--simple', '--simple-server',
'[deprecated] Forces Instiki not to run as a Daemon if fork is available.',
'Since version 0.10.0 this option is ignored.'
) { puts "Warning: -s (--simple) option is deprecated. See instiki --help for details." }
opts.on('-t', '--storage=storage', String,
'Makes Instiki use the specified directory for storage.',
'Default: ./storage/[port]') { |OPTIONS[:storage]| }
opts.on('-x', '--notex',
'Blocks wiki exports to TeX and PDF, even when pdflatex is available.'
) { |OPTIONS[:notex]| }
opts.on('-v', '--verbose',
'Enables debug-level logging'
) { OPTIONS[:verbose] = true }
opts.separator ''
opts.separator ""
opts.on('-h', '--help',
'Show this help message.') { puts opts; exit }
opts.on("-h", "--help",
"Show this help message.") { puts opts; exit }
opts.parse!
end
if OPTIONS[:environment] == 'production'
storage_path = "#{OPTIONS[:storage]}/#{OPTIONS[:port]}"
else
storage_path = "#{OPTIONS[:storage]}/#{OPTIONS[:environment]}/#{OPTIONS[:port]}"
end
FileUtils.mkdir_p(storage_path)
ENV["RAILS_ENV"] = OPTIONS[:environment]
require File.dirname(__FILE__) + "/../config/environment"
require 'webrick_server'
ENV['RAILS_ENV'] = OPTIONS[:environment]
$instiki_debug_logging = OPTIONS[:verbose]
require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
WikiService.storage_path = storage_path
OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
if OPTIONS[:notex]
OPTIONS[:pdflatex] = false
else
begin
OPTIONS[:pdflatex] = system "pdflatex -version"
rescue Errno::ENOENT
OPTIONS[:pdflatex] = false
end
end
if defined? INSTIKI_BATCH_JOB
require 'application'
else
puts "=> Starting Instiki on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
puts "=> Data files are stored in #{storage_path}"
require 'webrick_server'
require_dependency 'application'
OPTIONS[:index_controller] = 'wiki'
ApplicationController.wiki = WikiService.instance
DispatchServlet.dispatch(OPTIONS)
end
puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
DispatchServlet.dispatch(OPTIONS)

View file

@ -1,5 +1,55 @@
home_page:
id: 1
created_at: 2004-08-01
updated_at: 2005-08-01
web_id: 1
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
web_id: 1
name: HomePage
my_way:
id: 2
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
web_id: 1
name: MyWay
smart_engine:
id: 3
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
web_id: 1
name: SmartEngine
that_way:
id: 4
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
web_id: 1
name: ThatWay
no_wiki_word:
id: 5
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
web_id: 1
name: NoWikiWord
first_page:
id: 6
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
web_id: 1
name: FirstPage
oak:
id: 7
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
web_id: 1
name: Oak
elephant:
id: 8
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
web_id: 1
name: Elephant

View file

@ -1,6 +1,84 @@
home_page_first_revision:
id: 1
created_at: 2004-08-01
updated_at: 2005-08-01
created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
page_id: 1
content: some text
number: 1
content: First revision of the HomePage end
author: AnAuthor
ip: 127.0.0.1
my_way_first_revision:
id: 2
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
page_id: 2
number: 1
content: MyWay
author: Me
smart_engine_first_revision:
id: 3
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
page_id: 3
number: 1
content: SmartEngine
author: Me
that_way_first_revision:
id: 4
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
page_id: 4
number: 1
content: ThatWay
author: Me
no_wiki_word_first_revision:
id: 5
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
page_id: 5
number: 1
content: hey you
author: Me
home_page_second_revision:
id: 6
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
page_id: 1
number: 2
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
author: DavidHeinemeierHansson
first_page_first_revision:
id: 7
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
page_id: 6
number: 1
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
author: DavidHeinemeierHansson
oak_first_revision:
id: 8
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
page_id: 7
number: 1
content: "All about oak.\ncategory: trees"
author: TreeHugger
ip: 127.0.0.2
elephant_first_revision:
id: 9
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
page_id: 8
number: 1
content: "All about elephants.\ncategory: animals"
author: Guest
ip: 127.0.0.2

2
test/fixtures/system.yml vendored Normal file
View file

@ -0,0 +1,2 @@
system:
password: test_password

View file

@ -2,5 +2,14 @@ test_wiki:
id: 1
created_at: 2004-08-01
updated_at: 2005-08-01
name: wiki
address: wiki
name: wiki1
address: wiki1
markup: textile
instiki:
id: 2
created_at: 2004-08-01
updated_at: 2005-08-01
name: Instiki
address: instiki
markup: textile

View file

@ -1,70 +1,73 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
require 'admin_controller'
# Raise errors beyond the default web-based presentation
class AdminController; def rescue_action(e) logger.error(e); raise e end; end
class AdminControllerTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
setup_test_wiki
setup_controller_test
@controller = AdminController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@wiki = Wiki.new
@oak = pages(:oak)
@elephant = pages(:elephant)
@web = webs(:test_wiki)
@home = @page = pages(:home_page)
end
def tear_down
tear_down_wiki
end
def test_create_system_form_displayed
ApplicationController.wiki = WikiServiceWithNoPersistence.new
use_blank_wiki
process('create_system')
assert_success
assert_response :success
end
def test_create_system_form_submitted
ApplicationController.wiki = WikiServiceWithNoPersistence.new
assert !ApplicationController.wiki.setup?
use_blank_wiki
assert !@wiki.setup?
process('create_system', 'password' => 'a_password', 'web_name' => 'My Wiki',
'web_address' => 'my_wiki')
assert_redirected_to :web => 'my_wiki', :controller => 'wiki', :action => 'new',
:id => 'HomePage'
assert ApplicationController.wiki.setup?
assert_equal 'a_password', ApplicationController.wiki.system[:password]
assert_equal 1, ApplicationController.wiki.webs.size
new_web = ApplicationController.wiki.webs['my_wiki']
assert @wiki.setup?
assert_equal 'a_password', @wiki.system[:password]
assert_equal 1, @wiki.webs.size
new_web = @wiki.webs['my_wiki']
assert_equal 'My Wiki', new_web.name
assert_equal 'my_wiki', new_web.address
end
def test_create_system_form_submitted_and_wiki_already_initialized
wiki_before = ApplicationController.wiki
assert ApplicationController.wiki.setup?
wiki_before = @wiki
old_size = @wiki.webs.size
assert @wiki.setup?
process 'create_system', 'password' => 'a_password', 'web_name' => 'My Wiki',
'web_address' => 'my_wiki'
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
assert_equal wiki_before, ApplicationController.wiki
assert_redirected_to :web => @wiki.webs.keys.first, :action => 'show', :id => 'HomePage'
assert_equal wiki_before, @wiki
# and no new web should be created either
assert_equal 1, ApplicationController.wiki.webs.size
assert_equal old_size, @wiki.webs.size
assert_flash_has :error
end
def test_create_system_no_form_and_wiki_already_initialized
assert @wiki.setup?
process('create_system')
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
assert_redirected_to :web => @wiki.webs.keys.first, :action => 'show', :id => 'HomePage'
assert_flash_has :error
end
def test_create_web
@wiki.system[:password] = 'pswd'
@wiki.system.update_attribute(:password, 'pswd')
process 'create_web', 'system_password' => 'pswd', 'name' => 'Wiki Two', 'address' => 'wiki2'
@ -76,7 +79,7 @@ class AdminControllerTest < Test::Unit::TestCase
end
def test_create_web_default_password
@wiki.system[:password] = nil
@wiki.system.update_attribute(:password, nil)
process 'create_web', 'system_password' => 'instiki', 'name' => 'Wiki Two', 'address' => 'wiki2'
@ -84,7 +87,7 @@ class AdminControllerTest < Test::Unit::TestCase
end
def test_create_web_failed_authentication
@wiki.system[:password] = 'pswd'
@wiki.system.update_attribute(:password, 'pswd')
process 'create_web', 'system_password' => 'wrong', 'name' => 'Wiki Two', 'address' => 'wiki2'
@ -93,20 +96,20 @@ class AdminControllerTest < Test::Unit::TestCase
end
def test_create_web_no_form_submitted
@wiki.system[:password] = 'pswd'
@wiki.system.update_attribute(:password, 'pswd')
process 'create_web'
assert_success
assert_response :success
end
def test_edit_web_no_form
process 'edit_web', 'web' => 'wiki1'
# this action simply renders a form
assert_success
assert_response :success
end
def test_edit_web_form_submitted
@wiki.system[:password] = 'pswd'
@wiki.system.update_attribute(:password, 'pswd')
process('edit_web', 'system_password' => 'pswd',
'web' => 'wiki1', 'address' => 'renamed_wiki1', 'name' => 'Renamed Wiki1',
@ -116,21 +119,22 @@ class AdminControllerTest < Test::Unit::TestCase
'max_upload_size' => '300')
assert_redirected_to :web => 'renamed_wiki1', :action => 'show', :id => 'HomePage'
@web = Web.find(@web.id)
assert_equal 'renamed_wiki1', @web.address
assert_equal 'Renamed Wiki1', @web.name
assert_equal :markdown, @web.markup
assert_equal 'blue', @web.color
assert @web.safe_mode
assert @web.safe_mode?
assert_equal 'new_password', @web.password
assert @web.published
assert @web.brackets_only
assert @web.count_pages
assert @web.allow_uploads
assert @web.published?
assert @web.brackets_only?
assert @web.count_pages?
assert @web.allow_uploads?
assert_equal 300, @web.max_upload_size
end
def test_edit_web_opposite_values
@wiki.system[:password] = 'pswd'
@wiki.system.update_attribute(:password, 'pswd')
process('edit_web', 'system_password' => 'pswd',
'web' => 'wiki1', 'address' => 'renamed_wiki1', 'name' => 'Renamed Wiki1',
@ -140,11 +144,12 @@ class AdminControllerTest < Test::Unit::TestCase
# and should become false
assert_redirected_to :web => 'renamed_wiki1', :action => 'show', :id => 'HomePage'
assert !@web.safe_mode
assert !@web.published
assert !@web.brackets_only
assert !@web.count_pages
assert !@web.allow_uploads
@web = Web.find(@web.id)
assert !@web.safe_mode?
assert !@web.published?
assert !@web.brackets_only?
assert !@web.count_pages?
assert !@web.allow_uploads?
end
def test_edit_web_wrong_password
@ -154,12 +159,12 @@ class AdminControllerTest < Test::Unit::TestCase
'password' => 'new_password')
#returns to the same form
assert_success
assert_response :success
assert @response.has_template_object?('error')
end
def test_edit_web_rename_to_already_existing_web_name
@wiki.system[:password] = 'pswd'
@wiki.system.update_attribute(:password, 'pswd')
@wiki.create_web('Another', 'another')
process('edit_web', 'system_password' => 'pswd',
@ -168,7 +173,7 @@ class AdminControllerTest < Test::Unit::TestCase
'password' => 'new_password')
#returns to the same form
assert_success
assert_response :success
assert @response.has_template_object?('error')
end
@ -179,15 +184,15 @@ class AdminControllerTest < Test::Unit::TestCase
'password' => 'new_password')
#returns to the same form
assert_success
assert_response :success
assert @response.has_template_object?('error')
end
def test_remove_orphaned_pages
setup_wiki_with_three_pages
@wiki.system[:password] = 'pswd'
orhan_page_linking_to_oak = @wiki.write_page('wiki1', 'Pine',
@wiki.system.update_attribute(:password, 'pswd')
page_order = [@home, pages(:my_way), @oak, pages(:smart_engine), pages(:that_way)]
orphan_page_linking_to_oak = @wiki.write_page('wiki1', 'Pine',
"Refers to [[Oak]].\n" +
"category: trees",
Time.now, Author.new('TreeHugger', '127.0.0.2'))
@ -195,25 +200,28 @@ class AdminControllerTest < Test::Unit::TestCase
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
assert_redirected_to :controller => 'wiki', :web => 'wiki1', :action => 'list'
assert_equal [@home, @oak], @web.select.sort,
@web.pages(true)
assert_equal page_order, @web.select.sort,
"Pages are not as expected: #{@web.select.sort.map {|p| p.name}.inspect}"
# Oak is now orphan, second pass should remove it
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
assert_redirected_to :controller => 'wiki', :web => 'wiki1', :action => 'list'
assert_equal [@home], @web.select.sort,
@web.pages(true)
page_order.delete(@oak)
assert_equal page_order, @web.select.sort,
"Pages are not as expected: #{@web.select.sort.map {|p| p.name}.inspect}"
# third pass does not destroy HomePage
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
assert_redirected_to :action => 'list'
assert_equal [@home], @web.select.sort,
@web.pages(true)
assert_equal page_order, @web.select.sort,
"Pages are not as expected: #{@web.select.sort.map {|p| p.name}.inspect}"
end
def test_remove_orphaned_pages_empty_or_wrong_password
setup_wiki_with_three_pages
@wiki.system[:password] = 'pswd'
process('remove_orphaned_pages', 'web' => 'wiki1')
@ -224,5 +232,4 @@ class AdminControllerTest < Test::Unit::TestCase
assert_redirected_to(:controller => 'admin', :action => 'edit_web', :web => 'wiki1')
assert @response.flash[:error]
end
end

View file

@ -8,24 +8,23 @@ require 'rexml/document'
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
class ApplicationTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
setup_test_wiki
setup_controller_test(WikiController)
@controller = WikiController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@wiki = Wiki.new
end
def tear_down
tear_down_wiki
end
def test_utf8_header
r = process('show', 'web' => 'wiki1', 'id' => 'HomePage')
assert_equal 'text/html; charset=UTF-8', r.headers['Content-Type']
get :show, :web => 'wiki1', :id => 'HomePage'
assert_equal 'text/html; charset=UTF-8', @response.headers['Content-Type']
end
def test_connect_to_model_unknown_wiki
r = process('show', 'web' => 'unknown_wiki', 'id' => 'HomePage')
assert_equal 404, r.response_code
get :show, :web => 'unknown_wiki', :id => 'HomePage'
assert_response :missing
end
end

View file

@ -1,4 +1,4 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require 'file_controller'
@ -8,24 +8,26 @@ require 'fileutils'
class FileController; def rescue_action(e) logger.error(e); raise e end; end
class FileControllerTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
FILE_AREA = RAILS_ROOT + '/storage/test/wiki1'
Wiki.storage_path += "test/"
FILE_AREA = Wiki.storage_path + 'wiki1'
FileUtils.mkdir_p(FILE_AREA) unless File.directory?(FILE_AREA)
FileUtils.rm(Dir["#{FILE_AREA}/*"])
def setup
setup_test_wiki
setup_controller_test
end
def tear_down
tear_down_wiki
@controller = FileController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@wiki = Wiki.new
@web = webs(:test_wiki)
@home = @page = pages(:home_page)
end
def test_file
process 'file', 'web' => 'wiki1', 'id' => 'foo.tgz'
assert_success
assert_response :success
assert_rendered_file 'file/file'
end
@ -34,7 +36,7 @@ class FileControllerTest < Test::Unit::TestCase
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.txt'
assert_success
assert_response :success
assert_equal "aaa\nbbb\n", r.binary_content
assert_equal 'text/plain', r.headers['Content-Type']
end
@ -44,7 +46,7 @@ class FileControllerTest < Test::Unit::TestCase
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.pdf'
assert_success
assert_response :success
assert_equal "aaa\nbbb\n", r.binary_content
assert_equal 'application/pdf', r.headers['Content-Type']
end
@ -54,14 +56,14 @@ class FileControllerTest < Test::Unit::TestCase
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails.gif'
assert_success
assert_response :success
assert_equal File.size("#{FILE_AREA}/rails.gif"), r.binary_content.size
end
def test_pic_unknown_pic
r = process 'pic', 'web' => 'wiki1', 'id' => 'non-existant.gif'
assert_success
assert_response :success
assert_rendered_file 'file/file'
end
@ -74,7 +76,7 @@ class FileControllerTest < Test::Unit::TestCase
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif'
assert_success
assert_response :success
assert_rendered_file 'file/file'
# User uploads the picture
@ -98,7 +100,7 @@ class FileControllerTest < Test::Unit::TestCase
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt'
assert_success
assert_response :success
assert_rendered_file 'file/file'
# User uploads the picture
@ -109,17 +111,18 @@ class FileControllerTest < Test::Unit::TestCase
assert_equal(file, File.read("#{RAILS_ROOT}/storage/test/wiki1/instiki-e2e.txt"))
# this should refresh the page display content (cached)
@home = Page.find(@home.id)
assert_equal "<p><a class=\"existingWikiWord\" href=\"../file/instiki-e2e.txt\">" +
"instiki-e2e.txt</a></p>",
@home.display_content
end
def test_uploads_blocking
@web.allow_uploads = true
set_web_property :allow_uploads, true
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
assert_success
assert_response :success
@web.allow_uploads = false
set_web_property :allow_uploads, false
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
assert_equal '403 Forbidden', r.headers['Status']
end

View file

@ -1,4 +1,4 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'

View file

@ -1,10 +1,10 @@
#!/bin/env ruby -w
#!/bin/env ruby
# Uncomment the line below to enable pdflatex tests; don't forget to comment them again
# commiting to SVN
# $INSTIKI_TEST_PDFLATEX = true
require File.dirname(__FILE__) + '/../test_helper'
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
require 'wiki_controller'
require 'rexml/document'
require 'tempfile'
@ -14,63 +14,60 @@ require 'zip/zipfilesystem'
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
class WikiControllerTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
setup_test_wiki
setup_controller_test
@controller = WikiController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@wiki = Wiki.new
@web = webs(:test_wiki)
@home = @page = pages(:home_page)
@oak = pages(:oak)
@elephant = pages(:elephant)
end
def tear_down
tear_down_wiki
end
def test_authenticate
@web.password = 'pswd'
set_web_property :password, 'pswd'
r = process('authenticate', 'web' => 'wiki1', 'password' => 'pswd')
get :authenticate, :web => 'wiki1', :password => 'pswd'
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
assert_equal ['pswd'], r.cookies['web_address']
assert_equal ['pswd'], @response.cookies['web_address']
end
def test_authenticate_wrong_password
@web.password = 'pswd'
set_web_property :password, 'pswd'
r = process('authenticate', 'web' => 'wiki1', 'password' => 'wrong password')
assert_redirected_to :action => 'login', :web => 'wiki1'
assert_nil r.cookies['web_address']
end
def test_authors
setup_wiki_with_three_pages
@wiki.write_page('wiki1', 'BreakSortingOrder',
"This page breaks the accidentally correct sorting order of authors",
Time.now, Author.new('BreakingTheOrder', '127.0.0.2'))
r = process('authors', 'web' => 'wiki1')
assert_success
assert_equal ['AnAuthor', 'BreakingTheOrder', 'Guest', 'TreeHugger'],
assert_response :success
assert_equal %w(AnAuthor BreakingTheOrder DavidHeinemeierHansson Guest Me TreeHugger),
r.template_objects['authors']
end
def test_cancel_edit
setup_wiki_with_three_pages
@oak.lock(Time.now, 'Locky')
assert @oak.locked?(Time.now)
r = process('cancel_edit', 'web' => 'wiki1', 'id' => 'Oak')
assert_redirected_to :action => 'show', :id => 'Oak'
assert !@oak.locked?(Time.now)
assert !Page.find(@oak.id).locked?(Time.now)
end
def test_edit
r = process 'edit', 'web' => 'wiki1', 'id' => 'HomePage'
assert_success
assert_response :success
assert_equal @wiki.read_page('wiki1', 'HomePage'), r.template_objects['page']
end
@ -83,7 +80,8 @@ class WikiControllerTest < Test::Unit::TestCase
def test_edit_page_break_lock
@home.lock(Time.now, 'Locky')
process 'edit', 'web' => 'wiki1', 'id' => 'HomePage', 'break_lock' => 'y'
assert_success
assert_response :success
@home = Page.find(@home.id)
assert @home.locked?(Time.now)
end
@ -99,19 +97,17 @@ class WikiControllerTest < Test::Unit::TestCase
Time.now, Author.new('Special', '127.0.0.3'))
r = process 'edit', 'web' => 'wiki1', 'id' => 'With : Special /> symbols'
assert_success
assert_response :success
xml = REXML::Document.new(r.body)
form = REXML::XPath.first(xml, '//form')
assert_equal '/wiki1/save/With+%3A+Special+%2F%3E+symbols', form.attributes['action']
end
def test_export_html
setup_wiki_with_three_pages
@home.rollback(1, Time.now, 'Rick') # much simpler regex statement to match
r = process 'export_html', 'web' => 'wiki1'
assert_success
assert_response :success
assert_equal 'application/zip', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
r.headers['Content-Disposition']
@ -124,7 +120,7 @@ class WikiControllerTest < Test::Unit::TestCase
begin
File.open(@tempfile_path, 'wb') { |f| f.write(content); @exported_file = f.path }
Zip::ZipFile.open(@exported_file) do |zip|
assert_equal %w(Elephant.html HomePage.html Oak.html index.html), zip.dir.entries('.').sort
assert_equal %w(Elephant.html FirstPage.html HomePage.html MyWay.html NoWikiWord.html Oak.html SmartEngine.html ThatWay.html index.html), zip.dir.entries('.').sort
assert_match /.*<html .*All about elephants.*<\/html>/,
zip.file.read('Elephant.html').gsub(/\s+/, ' ')
assert_match /.*<html .*All about oak.*<\/html>/,
@ -138,12 +134,10 @@ class WikiControllerTest < Test::Unit::TestCase
end
end
def test_export_html_no_layout
setup_wiki_with_three_pages
def test_export_html_no_layout
r = process 'export_html', 'web' => 'wiki1', 'layout' => 'no'
assert_success
assert_response :success
assert_equal 'application/zip', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
r.headers['Content-Disposition']
@ -155,7 +149,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_export_markup
r = process 'export_markup', 'web' => 'wiki1'
assert_success
assert_response :success
assert_equal 'application/zip', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-textile-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
r.headers['Content-Disposition']
@ -168,7 +162,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_export_pdf
r = process 'export_pdf', 'web' => 'wiki1'
assert_success
assert_response :success
assert_equal 'application/pdf', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.pdf"/,
r.headers['Content-Disposition']
@ -183,13 +177,10 @@ class WikiControllerTest < Test::Unit::TestCase
puts ' $INSTIKI_TEST_PDFLATEX to enable them.'
end
def test_export_tex
setup_wiki_with_three_pages
def test_export_tex
r = process 'export_tex', 'web' => 'wiki1'
assert_success
assert_response :success
assert_equal 'application/octet-stream', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.tex"/,
r.headers['Content-Disposition']
@ -202,6 +193,8 @@ class WikiControllerTest < Test::Unit::TestCase
end
def test_index
# delete extra web fixture
webs(:instiki).destroy
process('index')
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
end
@ -219,41 +212,39 @@ class WikiControllerTest < Test::Unit::TestCase
end
def test_index_wiki_not_initialized
ApplicationController.wiki = WikiServiceWithNoPersistence.new
use_blank_wiki
process('index')
assert_redirected_to :controller => 'admin', :action => 'create_system'
end
def test_list
setup_wiki_with_three_pages
r = process('list', 'web' => 'wiki1')
assert_equal ['animals', 'trees'], r.template_objects['categories']
assert_nil r.template_objects['category']
assert_equal [@elephant, @home, @oak], r.template_objects['pages_in_category']
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category']
end
def test_locked
@home.lock(Time.now, 'Locky')
r = process('locked', 'web' => 'wiki1', 'id' => 'HomePage')
assert_success
assert_response :success
assert_equal @home, r.template_objects['page']
end
def test_login
r = process 'login', 'web' => 'wiki1'
assert_success
assert_response :success
# this action goes straight to the templates
end
def test_new
r = process('new', 'id' => 'NewPage', 'web' => 'wiki1')
assert_success
assert_response :success
assert_equal 'AnonymousCoward', r.template_objects['author']
assert_equal 'NewPage', r.template_objects['page_name']
end
@ -264,7 +255,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_pdf
assert RedClothForTex.available?, 'Cannot do test_pdf when pdflatex is not available'
r = process('pdf', 'web' => 'wiki1', 'id' => 'HomePage')
assert_success
assert_response :success
content = r.binary_content
@ -282,23 +273,23 @@ class WikiControllerTest < Test::Unit::TestCase
def test_print
r = process('print', 'web' => 'wiki1', 'id' => 'HomePage')
assert_success
assert_response :success
assert_equal :show, r.template_objects['link_mode']
end
def test_published
@web.published = true
set_web_property :published, true
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
assert_success
assert_response :success
assert_equal @home, r.template_objects['page']
end
def test_published_web_not_published
@web.published = false
set_web_property :published, false
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
@ -308,11 +299,11 @@ class WikiControllerTest < Test::Unit::TestCase
def test_recently_revised
r = process('recently_revised', 'web' => 'wiki1')
assert_success
assert_response :success
assert_equal [], r.template_objects['categories']
assert_equal %w(animals trees), r.template_objects['categories']
assert_nil r.template_objects['category']
assert_equal [@home], r.template_objects['pages_in_category']
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category']
assert_equal 'the web', r.template_objects['set_name']
end
@ -323,37 +314,33 @@ class WikiControllerTest < Test::Unit::TestCase
Time.now, Author.new('AnotherAuthor', '127.0.0.2'))
r = process('recently_revised', 'web' => 'wiki1')
assert_success
assert_response :success
assert_equal ['categorized'], r.template_objects['categories']
assert_equal %w(animals categorized trees), r.template_objects['categories']
# no category is specified in params
assert_nil r.template_objects['category']
assert_equal [@home, page2], r.template_objects['pages_in_category'],
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, page2, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
"Pages are not as expected: " +
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
assert_equal 'the web', r.template_objects['set_name']
end
def test_recently_revised_with_categorized_page_multiple_categories
setup_wiki_with_three_pages
r = process('recently_revised', 'web' => 'wiki1')
assert_success
assert_response :success
assert_equal ['animals', 'trees'], r.template_objects['categories']
# no category is specified in params
assert_nil r.template_objects['category']
assert_equal [@elephant, @home, @oak], r.template_objects['pages_in_category'],
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
"Pages are not as expected: " +
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
assert_equal 'the web', r.template_objects['set_name']
end
def test_recently_revised_with_specified_category
setup_wiki_with_three_pages
r = process('recently_revised', 'web' => 'wiki1', 'category' => 'animals')
assert_success
assert_response :success
assert_equal ['animals', 'trees'], r.template_objects['categories']
# no category is specified in params
@ -366,7 +353,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_revision
r = process 'revision', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '0'
assert_success
assert_response :success
assert_equal @home, r.template_objects['page']
assert_equal @home.revisions[0], r.template_objects['revision']
end
@ -377,27 +364,24 @@ class WikiControllerTest < Test::Unit::TestCase
# its assigns the same as or revision
r = process 'rollback', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '0'
assert_success
assert_response :success
assert_equal @home, r.template_objects['page']
assert_equal @home.revisions[0], r.template_objects['revision']
end
def test_rss_with_content
setup_wiki_with_three_pages
r = process 'rss_with_content', 'web' => 'wiki1'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal [@home, @oak, @elephant], pages,
assert_equal [@elephant, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages,
"Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
assert !r.template_objects['hide_description']
end
def test_rss_with_content_when_blocked
setup_wiki_with_three_pages
@web.password = 'aaa'
@web.published = false
@web.update_attributes(:password => 'aaa', :published => false)
@web = Web.find(@web.id)
r = process 'rss_with_content', 'web' => 'wiki1'
@ -406,7 +390,6 @@ class WikiControllerTest < Test::Unit::TestCase
def test_rss_with_headlines
setup_wiki_with_three_pages
@title_with_spaces = @wiki.write_page('wiki1', 'Title With Spaces',
'About spaces', 1.hour.ago, Author.new('TreeHugger', '127.0.0.2'))
@ -415,19 +398,24 @@ class WikiControllerTest < Test::Unit::TestCase
r = process 'rss_with_headlines', 'web' => 'wiki1'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal [@home, @oak, @elephant, @title_with_spaces], pages,
"Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
assert_equal [@elephant, @title_with_spaces, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages, "Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
assert r.template_objects['hide_description']
xml = REXML::Document.new(r.body)
expected_page_links =
['http://localhost:8080/wiki1/show/HomePage',
['http://localhost:8080/wiki1/show/Elephant',
'http://localhost:8080/wiki1/show/Title+With+Spaces',
'http://localhost:8080/wiki1/show/Oak',
'http://localhost:8080/wiki1/show/Elephant',
'http://localhost:8080/wiki1/show/Title+With+Spaces']
'http://localhost:8080/wiki1/show/NoWikiWord',
'http://localhost:8080/wiki1/show/ThatWay',
'http://localhost:8080/wiki1/show/SmartEngine',
'http://localhost:8080/wiki1/show/MyWay',
'http://localhost:8080/wiki1/show/FirstPage',
'http://localhost:8080/wiki1/show/HomePage',
]
assert_template_xpath_match '/rss/channel/link',
'http://localhost:8080/wiki1/show/HomePage'
@ -436,22 +424,26 @@ class WikiControllerTest < Test::Unit::TestCase
end
def test_rss_switch_links_to_published
setup_wiki_with_three_pages
@web.password = 'aaa'
@web.published = true
@web.update_attributes(:password => 'aaa', :published => true)
@web = Web.find(@web.id)
@request.host = 'foo.bar.info'
@request.port = 80
r = process 'rss_with_headlines', 'web' => 'wiki1'
assert_success
assert_response :success
xml = REXML::Document.new(r.body)
expected_page_links =
['http://foo.bar.info/wiki1/published/HomePage',
['http://foo.bar.info/wiki1/published/Elephant',
'http://foo.bar.info/wiki1/published/Oak',
'http://foo.bar.info/wiki1/published/Elephant']
'http://foo.bar.info/wiki1/published/NoWikiWord',
'http://foo.bar.info/wiki1/published/ThatWay',
'http://foo.bar.info/wiki1/published/SmartEngine',
'http://foo.bar.info/wiki1/published/MyWay',
'http://foo.bar.info/wiki1/published/FirstPage',
'http://foo.bar.info/wiki1/published/HomePage']
assert_template_xpath_match '/rss/channel/link',
'http://foo.bar.info/wiki1/published/HomePage'
@ -463,45 +455,43 @@ class WikiControllerTest < Test::Unit::TestCase
setup_wiki_with_30_pages
r = process 'rss_with_headlines', 'web' => 'wiki1'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 15, pages.size, 15
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => '5'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 5, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => '25'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 25, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => 'all'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 31, pages.size
assert_equal 38, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-16'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 16, pages.size
assert_equal 23, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'end' => '1976-10-16'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 15, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-01', 'end' => '1976-10-06'
assert_success
assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 5, pages.size
end
def test_rss_title_with_ampersand
# was ticket:143
setup_wiki_with_three_pages
# was ticket:143
@wiki.write_page('wiki1', 'Title&With&Ampersands',
'About spaces', 1.hour.ago, Author.new('NitPicker', '127.0.0.3'))
@ -511,15 +501,12 @@ class WikiControllerTest < Test::Unit::TestCase
assert r.body.include?('<title>Title&amp;With&amp;Ampersands</title>')
end
def test_rss_timestamp
setup_wiki_with_three_pages
def test_rss_timestamp
new_page = @wiki.write_page('wiki1', 'PageCreatedAtTheBeginningOfCtime',
'Created on 1 Jan 1970 at 0:00:00 Z', Time.at(0), Author.new('NitPicker', '127.0.0.3'))
r = process 'rss_with_headlines', 'web' => 'wiki1'
assert_template_xpath_match '/rss/channel/item/pubDate[4]', "Thu, 01 Jan 1970 00:00:00 Z"
assert_template_xpath_match '/rss/channel/item/pubDate[9]', "Thu, 01 Jan 1970 00:00:00 Z"
end
def test_save
@ -535,6 +522,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_save_new_revision_of_existing_page
@home.lock(Time.now, 'Batman')
current_revisions = @home.revisions.size
r = process 'save', 'web' => 'wiki1', 'id' => 'HomePage', 'content' => 'Revised HomePage',
'author' => 'Batman'
@ -542,8 +530,7 @@ class WikiControllerTest < Test::Unit::TestCase
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
assert_equal ['Batman'], r.cookies['author'].value
home_page = @wiki.read_page('wiki1', 'HomePage')
assert_equal [home_page], @web.pages.values
assert_equal 2, home_page.revisions.size
assert_equal current_revisions+1, home_page.revisions.size
assert_equal 'Revised HomePage', home_page.content
assert_equal 'Batman', home_page.author
assert !home_page.locked?(Time.now)
@ -563,57 +550,47 @@ class WikiControllerTest < Test::Unit::TestCase
revisions_after = @home.revisions.size
assert_equal revisions_before, revisions_after
@home = Page.find(@home.id)
assert !@home.locked?(Time.now), 'HomePage should be unlocked if an edit was unsuccessful'
end
def test_search
setup_wiki_with_three_pages
r = process 'search', 'web' => 'wiki1', 'query' => '\s[A-Z]ak'
assert_redirected_to :action => 'show', :id => 'Oak'
end
def test_search_multiple_results
setup_wiki_with_three_pages
r = process 'search', 'web' => 'wiki1', 'query' => 'All about'
assert_success
assert_response :success
assert_equal 'All about', r.template_objects['query']
assert_equal [@elephant, @oak], r.template_objects['results']
assert_equal [], r.template_objects['title_results']
end
def test_search_by_content_and_title
setup_wiki_with_three_pages
r = process 'search', 'web' => 'wiki1', 'query' => '(Oak|Elephant)'
assert_success
assert_response :success
assert_equal '(Oak|Elephant)', r.template_objects['query']
assert_equal [@elephant, @oak], r.template_objects['results']
assert_equal [@elephant, @oak], r.template_objects['title_results']
end
def test_search_zero_results
setup_wiki_with_three_pages
r = process 'search', 'web' => 'wiki1', 'query' => 'non-existant text'
assert_success
assert_response :success
assert_equal [], r.template_objects['results']
assert_equal [], r.template_objects['title_results']
end
def test_show_page
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
assert_success
assert_match /First revision of the <a.*HomePage.*<\/a> end/, r.body
r = process('show', 'id' => 'Oak', 'web' => 'wiki1')
assert_response :success
assert_tag :content => /All about oak/
end
def test_show_page_with_multiple_revisions
@ -622,7 +599,7 @@ class WikiControllerTest < Test::Unit::TestCase
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
assert_success
assert_response :success
assert_match /Second revision of the <a.*HomePage.*<\/a> end/, r.body
end
@ -633,24 +610,25 @@ class WikiControllerTest < Test::Unit::TestCase
def test_show_no_page
r = process('show', 'id' => '', 'web' => 'wiki1')
assert_equal 404, r.response_code
assert_response :missing
r = process('show', 'web' => 'wiki1')
assert_equal 404, r.response_code
assert_response :missing
end
def test_tex
r = process('tex', 'web' => 'wiki1', 'id' => 'HomePage')
assert_success
assert_response :success
assert_equal "\\documentclass[12pt,titlepage]{article}\n\n\\usepackage[danish]{babel} " +
"%danske tekster\n\\usepackage[OT1]{fontenc} %rigtige danske bogstaver...\n" +
"\\usepackage{a4}\n\\usepackage{graphicx}\n\\usepackage{ucs}\n\\usepackage[utf8x]" +
"{inputenc}\n\\input epsf \n\n%----------------------------------------------------" +
"---------------\n\n\\begin{document}\n\n\\sloppy\n\n%-----------------------------" +
"--------------------------------------\n\n\\section*{HomePage}\n\nFirst revision of " +
"the HomePage end\n\n\\end{document}", r.body
"--------------------------------------\n\n\\section*{HomePage}\n\nHisWay would be " +
"MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that " +
"SmartEngineGUI\n\n\\end{document}", r.body
end
@ -659,8 +637,8 @@ class WikiControllerTest < Test::Unit::TestCase
r = process('web_list')
assert_success
assert_equal [another_wiki, @web], r.template_objects['webs']
assert_response :success
assert_equal [another_wiki, webs(:instiki), @web], r.template_objects['webs']
end
end

View file

@ -10,17 +10,97 @@ require 'active_record/fixtures'
require 'action_controller/test_process'
require 'action_web_service/test_invoke'
require 'breakpoint'
require 'wiki_content'
# Uncomment these and hang on, because the tests will be FAST
#Test::Unit::TestCase.pre_loaded_fixtures = false
#Test::Unit::TestCase.use_transactional_fixtures = true
Test::Unit::TestCase.use_instantiated_fixtures = false
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
class Test::Unit::TestCase
# Turn these on to use transactional fixtures with table_name(:fixture_name) instantiation of fixtures
# self.use_transactional_fixtures = true
# self.use_instantiated_fixtures = false
def create_fixtures(*table_names)
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
end
# Add more helper methods to be used by all tests here...
end
def set_web_property(property, value)
@web.update_attribute(property, value)
@page = Page.find(@page.id)
@wiki.webs[@web.name] = @web
end
def setup_wiki_with_30_pages
ActiveRecord::Base.silence do
(1..30).each do |i|
@wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
end
end
@web = Web.find(@web.id)
end
def use_blank_wiki
Revision.destroy_all
Page.destroy_all
Web.destroy_all
end
end
# This module is to be included in unit tests that involve matching chunks.
# It provides a easy way to test whether a chunk matches a particular string
# and any the values of any fields that should be set after a match.
class ContentStub < String
include ChunkManager
def initialize(str)
super
init_chunk_manager
end
def page_link(*); end
end
module ChunkMatch
# Asserts a number of tests for the given type and text.
def match(chunk_type, test_text, expected_chunk_state)
if chunk_type.respond_to? :pattern
assert_match(chunk_type.pattern, test_text)
end
content = ContentStub.new(test_text)
chunk_type.apply_to(content)
# Test if requested parts are correct.
expected_chunk_state.each_pair do |a_method, expected_value|
assert content.chunks.last.kind_of?(chunk_type)
assert_respond_to(content.chunks.last, a_method)
assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
"Wrong #{a_method} value")
end
end
# Asserts that test_text doesn't match the chunk_type
def no_match(chunk_type, test_text)
if chunk_type.respond_to? :pattern
assert_no_match(chunk_type.pattern, test_text)
end
end
end
if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
module Test
module Unit
module Assertions
unless method_defined? :__assert_success_before_override_by_instiki
alias :__assert_success_before_override_by_instiki :assert_success
end
def assert_success
__assert_success_before_override_by_instiki
if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
end
end
end
end
end

View file

@ -1,6 +1,6 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
require 'diff'
include Diff

View file

@ -1,4 +1,4 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require 'fileutils'
@ -67,4 +67,4 @@ class FileYardTest < Test::Unit::TestCase
"#{RAILS_ROOT}/storage/test/instiki"
end
end
end

View file

@ -1,7 +1,78 @@
require File.dirname(__FILE__) + '/../test_helper'
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class PageTest < Test::Unit::TestCase
fixtures 'webs', 'pages', 'revisions'
fixtures :webs, :pages, :revisions, :system
def setup
@page = pages(:first_page)
end
def test_lock
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
@page.unlock
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
end
def test_lock_duration
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
end
def test_plain_name
assert_equal "First Page", @page.plain_name
end
def test_revise
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
assert_equal 2, @page.revisions(true).length, 'Should have two revisions'
assert_equal 'MarianneSyhler', @page.current_revision(true).author.to_s, 'Mary should be the author now'
assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
end
def test_revise_continous_revision
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
assert_equal 2, @page.revisions(true).length
@page.current_revision(true)
@page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
assert_equal 2, @page.revisions(true).length
assert_equal 'HisWay would be MyWay in kinda update', @page.revisions.last.content
assert_equal Time.local(2004, 4, 4, 16, 57), @page.revisions.last.created_at
@page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
assert_equal 3, @page.revisions(true).length
assert_equal 'HisWay would be MyWay in the house', @page.revisions.last.content
@page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
assert_equal 4, @page.revisions(true).length
end
def test_revise_content_unchanged
last_revision_before = @page.current_revision
revisions_number_before = @page.revisions.size
assert_raises(Instiki::ValidationError) {
@page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
}
assert_equal last_revision_before, @page.current_revision(true)
assert_equal revisions_number_before, @page.revisions.size
end
def test_rollback
@page.revise("spot two", Time.now, "David")
@page.revise("spot three", Time.now + 2000, "David")
assert_equal 3, @page.revisions(true).length, "Should have three revisions"
@page.current_revision(true)
@page.rollback(1, Time.now)
assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
end
end

View file

@ -1,4 +1,4 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require 'redcloth_for_tex'
@ -66,4 +66,4 @@ EOL
def test_subsection_depth
assert_equal "\\subsubsection*{Hello}", RedClothForTex.new("h4. Hello").to_tex
end
end
end

View file

@ -1,7 +1,315 @@
require File.dirname(__FILE__) + '/../test_helper'
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class RevisionTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
fixtures 'webs', 'pages', 'revisions'
def setup
@wiki = Wiki.new
@web = webs(:test_wiki)
@page = pages(:home_page)
@revision = revisions(:home_page_second_revision)
end
def test_wiki_words
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
end
def test_existing_pages
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
end
def test_unexisting_pages
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
end
def test_content_with_wiki_links
assert_equal '<p><span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
'would be <a class="existingWikiWord" href="../show/MyWay">My Way</a> in kinda ' +
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere&#8212;see ' +
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
'<span class="newWikiWord">Smart Engine GUI' +
'<a href="../show/SmartEngineGUI">?</a></span></p>',
@revision.display_content
end
def test_markdown
set_web_property :markup, :markdown
assert_markup_parsed_as(
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
"My Headline\n===========\n\nthat SmartEngineGUI")
code_block = [
'This is a code block:',
'',
' def a_method(arg)',
' return ThatWay',
'',
'Nice!'
].join("\n")
assert_markup_parsed_as(
%{<p>This is a code block:</p>\n\n<pre><code>def a_method(arg)\n} +
%{return ThatWay\n</code></pre>\n\n<p>Nice!</p>},
code_block)
end
def test_markdown_hyperlink_with_slash
# in response to a bug, see http://dev.instiki.org/attachment/ticket/177
set_web_property :markup, :markdown
assert_markup_parsed_as(
'<p><a href="http://example/with/slash">text</a></p>',
'[text](http://example/with/slash)')
end
def test_mixed_formatting
textile_and_markdown = [
'Markdown heading',
'================',
'',
'h2. Textile heading',
'',
'*some* **text** _with_ -styles-',
'',
'* list 1',
'* list 2'
].join("\n")
set_web_property :markup, :markdown
assert_markup_parsed_as(
"<h1>Markdown heading</h1>\n\n" +
"<p>h2. Textile heading</p>\n\n" +
"<p><em>some</em> <strong>text</strong> <em>with</em> -styles-</p>\n\n" +
"<ul>\n<li>list 1</li>\n<li>list 2</li>\n</ul>",
textile_and_markdown)
set_web_property :markup, :textile
assert_markup_parsed_as(
"<p>Markdown heading<br />================</p>\n\n\n\t<h2>Textile heading</h2>" +
"\n\n\n\t<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>" +
"\n\n\n\t<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
textile_and_markdown)
set_web_property :markup, :mixed
assert_markup_parsed_as(
"<h1>Markdown heading</h1>\n\n\n\t<h2>Textile heading</h2>\n\n\n\t" +
"<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>\n\n\n\t" +
"<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
textile_and_markdown)
end
def test_rdoc
set_web_property :markup, :rdoc
@revision = Revision.new(:page => @page, :content => '+hello+ that SmartEngineGUI',
:author => Author.new('DavidHeinemeierHansson'))
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
end
def test_content_with_auto_links
assert_markup_parsed_as(
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
end
def test_content_with_aliased_links
assert_markup_parsed_as(
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
'</a> go by any other name?</p>',
'Would a [[SmartEngine|clever motor]] go by any other name?')
end
def test_content_with_wikiword_in_em
assert_markup_parsed_as(
'<p><em>should we go <a class="existingWikiWord" href="../show/ThatWay">' +
'That Way</a> or <span class="newWikiWord">This Way<a href="../show/ThisWay">?</a>' +
'</span> </em></p>',
'_should we go ThatWay or ThisWay _')
end
def test_content_with_wikiword_in_tag
assert_markup_parsed_as(
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
'That is some <em style="WikiWord">Stylish Emphasis</em>')
end
def test_content_with_escaped_wikiword
# there should be no wiki link
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
end
def test_content_with_pre_blocks
assert_markup_parsed_as(
'<p>A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre></p>',
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
end
def test_content_with_autolink_in_parentheses
assert_markup_parsed_as(
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
'http://www.w3c.org</a>) sets web standards</p>',
'The W3C body (http://www.w3c.org) sets web standards')
end
def test_content_with_link_in_parentheses
assert_markup_parsed_as(
'<p>(<a href="http://wiki.org/wiki.cgi?WhatIsWiki">What is a wiki?</a>)</p>',
'("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
end
def test_content_with_image_link
assert_markup_parsed_as(
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is a Textile image link.</p>',
'This !http://hobix.com/sample.jpg! is a Textile image link.')
end
def test_content_with_inlined_img_tag
assert_markup_parsed_as(
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.</p>',
'This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.')
assert_markup_parsed_as(
'<p>This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.</p>',
'This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.')
end
def test_nowiki_tag
assert_markup_parsed_as(
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
'or <nowiki>http://www.thislink.com</nowiki>.')
end
def test_multiline_nowiki_tag
assert_markup_parsed_as(
"<p>Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
'<span class="newWikiWord">this<a href="../show/this">?</a></span></p>',
"Do not <nowiki>mark \n up [[this text]] \n" +
"and http://this.url.com </nowiki> but markup [[this]]")
end
def test_content_with_bracketted_wiki_word
set_web_property :brackets_only, true
assert_markup_parsed_as(
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
end
def test_content_for_export
assert_equal '<p><span class="newWikiWord">His Way</span> would be ' +
'<a class="existingWikiWord" href="MyWay.html">My Way</a> in kinda ' +
'<a class="existingWikiWord" href="ThatWay.html">That Way</a> in ' +
'<span class="newWikiWord">His Way</span> though ' +
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere&#8212;see ' +
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
'<span class="newWikiWord">Smart Engine GUI</span></p>',
@revision.display_content_for_export
end
def test_double_replacing
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
assert_equal '<p><span class="newWikiWord">Version History' +
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
'</span></p>',
@revision.display_content
@revision.clear_display_cache
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
assert_equal "<p>f<br /><span class=\"newWikiWord\">Version History" +
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
"</span></p>",
@revision.display_content
end
def test_difficult_wiki_words
@revision.content = "[[It's just awesome GUI!]]"
assert_equal "<p><span class=\"newWikiWord\">It's just awesome GUI!" +
"<a href=\"../show/It%27s+just+awesome+GUI%21\">?</a></span></p>",
@revision.display_content
end
def test_revisions_diff
Revision.create(:page => @page, :content => 'What a blue and lovely morning', :author => Author.new('DavidHeinemeierHansson'))
Revision.create(:page => @page, :content => 'What a red and lovely morning today', :author => Author.new('DavidHeinemeierHansson'))
assert_equal "<p>What a <del class=\"diffmod\">blue </del><ins class=\"diffmod\">red " +
"</ins>and lovely <del class=\"diffmod\">morning</del><ins class=\"diffmod\">morning " +
"today</ins></p>", @page.revisions.last.display_diff
end
def test_link_to_file
assert_markup_parsed_as(
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
'[[doc.pdf:file]]')
end
def test_link_to_pic
FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1"
FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"])
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
assert_markup_parsed_as(
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
'[[square.jpg|Square:pic]]')
assert_markup_parsed_as(
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
'[[square.jpg:pic]]')
end
def test_link_to_non_existant_pic
assert_markup_parsed_as(
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
'</span></p>',
'[[NonExistant.jpg|NonExistant:pic]]')
assert_markup_parsed_as(
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
'</span></p>',
'[[NonExistant.jpg:pic]]')
end
def test_wiki_link_with_colon
assert_markup_parsed_as(
'<p><span class="newWikiWord">With:Colon<a href="../show/With%3AColon">?</a></span></p>',
'[[With:Colon]]')
end
# TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
# also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
def test_list_with_tildas
list_with_tildas = <<-EOL
* "a":~b
* c~ d
EOL
assert_markup_parsed_as(
"<ul>\n\t<li><a href=\"~b\">a</a></li>\n\t\t<li>c~ d</li>\n\t</ul>",
list_with_tildas)
end
def test_textile_image_in_mixed_wiki
set_web_property :markup, :mixed
assert_markup_parsed_as(
"<p><img src=\"http://google.com\" alt=\"\" />\nss</p>",
"!http://google.com!\r\nss")
end
def assert_markup_parsed_as(expected_output, input)
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
end
end

View file

@ -1,4 +1,4 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require 'chunks/uri'

View file

@ -1,7 +1,158 @@
require File.dirname(__FILE__) + '/../test_helper'
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class WebTest < Test::Unit::TestCase
fixtures 'webs', 'pages', 'revisions'
fixtures :webs, :pages, :revisions, :system
def setup
@web = webs(:instiki)
end
def test_wiki_word_linking
@web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated',
Time.now, 'DavidHeinemeierHansson')
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
'<a href="../show/EverBeenHated">?</a></span></p>',
@web.page("SecondPage").display_content)
@web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
'DavidHeinemeierHansson')
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
@web.page("SecondPage").display_content)
end
def test_pages_by_revision
add_sample_pages
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
end
def test_pages_by_match
add_sample_pages
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
end
def test_references
add_sample_pages
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
end
def test_delete
add_sample_pages
assert_equal 2, @web.pages.length
@web.remove_pages([ @web.page('EverBeenInLove') ])
assert_equal 1, @web.pages(true).length
end
def test_make_link
add_sample_pages
existing_page_wiki_url =
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
existing_page_published_url =
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
existing_page_static_url =
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
new_page_wiki_url =
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
new_page_published_url =
new_page_static_url =
'<span class="newWikiWord">Unknown Word</span>'
# no options
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
# :mode => :export
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
# :mode => :publish
assert_equal existing_page_published_url,
@web.make_link('EverBeenInLove', nil, :mode => :publish)
# new page, no options
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
# new page, :mode => :export
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
# new page, :mode => :publish
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
# Escaping special characters in the name
assert_equal(
'<span class="newWikiWord">Smith &amp; Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
@web.make_link('Smith & Wesson'))
# optionally using text as the link text
assert_equal(
existing_page_published_url.sub(/>Ever Been In Love</, ">Haven't you ever been in love?<"),
@web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
end
def test_initialize
web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123')
assert_equal 'Wiki2', web.name
assert_equal 'wiki2', web.address
assert_equal '123', web.password
# new web should be set for maximum features enabled
assert_equal :textile, web.markup
assert_equal '008B26', web.color
assert !web.safe_mode?
assert_equal([], web.pages)
assert web.allow_uploads?
assert_nil web.additional_style
assert !web.published?
assert !web.brackets_only?
assert !web.count_pages?
assert_equal 100, web.max_upload_size
end
def test_initialize_invalid_name
assert_raises(Instiki::ValidationError) {
Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123')
}
end
def test_new_page_linked_from_mother_page
# this was a bug in revision 204
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
@web.add_page('AnotherPage', 'This is \AnotherPage',
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
@web.pages(true)
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
end
def test_orphaned_pages
add_sample_pages
home = @web.add_page('HomePage',
'This is a home page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
author = @web.add_page('AlexeyVerkhovsky',
'This is an author page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
self_linked = @web.add_page('SelfLinked',
'I am me SelfLinked and link to EverBeenInLove',
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
# page that links to itself, and nobody else links to it must be an orphan
assert_equal ['EverBeenHated', 'SelfLinked'],
@web.select.orphaned_pages.collect{ |page| page.name }.sort
end
private
def add_sample_pages
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
end
end

View file

@ -1,6 +1,6 @@
#!/bin/env ruby -w
#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
require 'wiki_words'
class WikiWordsTest < Test::Unit::TestCase