royw-read_page_cache 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/README.rdoc +43 -0
- data/Rakefile +48 -0
- data/VERSION.yml +4 -0
- data/lib/file_extensions.rb +18 -0
- data/lib/module_extensions.rb +27 -0
- data/lib/read_page_cache.rb +89 -0
- data/spec/read_page_cache_spec.rb +85 -0
- data/spec/spec_helper.rb +9 -0
- metadata +63 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2009 Roy Wright
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
= read_page_cache
|
2
|
+
|
3
|
+
== Synopsis
|
4
|
+
The purpose of the module is to cache web pages used for testing by overriding
|
5
|
+
the classes' read_page method and replacing it with one that will cache pages.
|
6
|
+
|
7
|
+
== Usage
|
8
|
+
Your main code needs to have a read_page(page) instance method(s). Here's an
|
9
|
+
example:
|
10
|
+
|
11
|
+
class ClassName
|
12
|
+
def read_page(page)
|
13
|
+
open(page).read
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Then your test code should include:
|
18
|
+
|
19
|
+
# default directory is '/tmp'
|
20
|
+
directory = '/path/to/cache/files'
|
21
|
+
|
22
|
+
require 'cache_extensions'
|
23
|
+
ReadPageCache.attach_to ClassName, directory
|
24
|
+
|
25
|
+
You may attach_to however many classes that you need to.
|
26
|
+
|
27
|
+
If you want to override all the read_page(page) methods in your application,
|
28
|
+
then your test code can instead use:
|
29
|
+
|
30
|
+
# default directory is '/tmp'
|
31
|
+
directory = '/path/to/cache/files'
|
32
|
+
|
33
|
+
require 'cache_extensions'
|
34
|
+
ReadPageCache.attach_to_classes directory
|
35
|
+
|
36
|
+
That's it. The first time you run your tests, the web pages your application
|
37
|
+
accesses with read_page will be cached, then the cached files will be used by
|
38
|
+
all subsequent accesses. You may want to review the cache and add any files
|
39
|
+
you want to your version control system.
|
40
|
+
|
41
|
+
== Copyright
|
42
|
+
|
43
|
+
Copyright (c) 2009 Roy Wright. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "read_page_cache"
|
8
|
+
gem.summary = %Q{TODO}
|
9
|
+
gem.email = "roy@wright.org"
|
10
|
+
gem.homepage = "http://github.com/royw/read_page_cache"
|
11
|
+
gem.authors = ["Roy Wright"]
|
12
|
+
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'spec/rake/spectask'
|
20
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
21
|
+
spec.libs << 'lib' << 'spec'
|
22
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
23
|
+
end
|
24
|
+
|
25
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
26
|
+
spec.libs << 'lib' << 'spec'
|
27
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
28
|
+
spec.rcov = true
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
task :default => :spec
|
33
|
+
|
34
|
+
require 'rake/rdoctask'
|
35
|
+
Rake::RDocTask.new do |rdoc|
|
36
|
+
if File.exist?('VERSION.yml')
|
37
|
+
config = YAML.load(File.read('VERSION.yml'))
|
38
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
39
|
+
else
|
40
|
+
version = ""
|
41
|
+
end
|
42
|
+
|
43
|
+
rdoc.rdoc_dir = 'rdoc'
|
44
|
+
rdoc.title = "read_page_cache #{version}"
|
45
|
+
rdoc.rdoc_files.include('README*')
|
46
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
47
|
+
end
|
48
|
+
|
data/VERSION.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# == Synopsis
|
2
|
+
# add a mkdirs method to the File class
|
3
|
+
class File
|
4
|
+
class << self
|
5
|
+
my_extension("mkdirs") do
|
6
|
+
##
|
7
|
+
# make directories including any missing in the path
|
8
|
+
#
|
9
|
+
# @param [String] dirspec the path to make sure exists
|
10
|
+
def File.mkdirs(dirspec)
|
11
|
+
unless File.exists?(dirspec)
|
12
|
+
mkdirs(File.dirname(dirspec))
|
13
|
+
Dir.mkdir(dirspec)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
######################################################################
|
2
|
+
# my extensions to Module. (taken from rake, named changed to not clash
|
3
|
+
# when rake is used for this rails project.
|
4
|
+
#
|
5
|
+
class Module
|
6
|
+
# Check for an existing method in the current class before extending. IF
|
7
|
+
# the method already exists, then a warning is printed and the extension is
|
8
|
+
# not added. Otherwise the block is yielded and any definitions in the
|
9
|
+
# block will take effect.
|
10
|
+
#
|
11
|
+
# Usage:
|
12
|
+
#
|
13
|
+
# class String
|
14
|
+
# rake_extension("xyz") do
|
15
|
+
# def xyz
|
16
|
+
# ...
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
def my_extension(method)
|
22
|
+
unless instance_methods.include?(method.to_s) || instance_methods.include?(method.to_sym)
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end # module Module
|
27
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'module_extensions'
|
2
|
+
require 'file_extensions'
|
3
|
+
|
4
|
+
# == Synopsis
|
5
|
+
# The purpose of the module is to cache web pages used for
|
6
|
+
# testing by overriding the classes' read_page method and
|
7
|
+
# replacing it with one that will cache pages.
|
8
|
+
#
|
9
|
+
# == Usage
|
10
|
+
# Your main code needs to have a read_page(page) instance
|
11
|
+
# method(s). Here's an example:
|
12
|
+
#
|
13
|
+
# class ClassName
|
14
|
+
# def read_page(page)
|
15
|
+
# open(page).read
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Then your test code should include:
|
20
|
+
#
|
21
|
+
# # default directory is '/tmp'
|
22
|
+
# directory = '/path/to/cache/files'
|
23
|
+
# require 'cache_extensions'
|
24
|
+
# ReadPageCache.attach_to ClassName, directory
|
25
|
+
#
|
26
|
+
# You may attach_to however many classes that you need to.
|
27
|
+
#
|
28
|
+
# If you want to override all the read_page(page) methods
|
29
|
+
# in your application, then your test code can instead use:
|
30
|
+
#
|
31
|
+
# # default directory is '/tmp'
|
32
|
+
# directory = '/path/to/cache/files'
|
33
|
+
# require 'cache_extensions'
|
34
|
+
# ReadPageCache.attach_to_classes directory
|
35
|
+
#
|
36
|
+
# That's it. The first time you run your tests, the pages
|
37
|
+
# your application accesses with read_page will be cached,
|
38
|
+
# then the cached files will be used by all subsequent accesses.
|
39
|
+
#
|
40
|
+
module ReadPageCache
|
41
|
+
# == Synopsis
|
42
|
+
# Attach the read_page and cache_file methods to the given
|
43
|
+
# class (cls) and use the given directory for the cache files
|
44
|
+
def self.attach_to(cls, directory='/tmp')
|
45
|
+
|
46
|
+
# define the read_page(page) method on the given class: cls
|
47
|
+
cls.send('define_method', "read_page") do |page|
|
48
|
+
data = nil
|
49
|
+
filespec = page.gsub(/^http:\//, directory).gsub(/\/$/, '.html')
|
50
|
+
if File.exist?(filespec)
|
51
|
+
data = open(filespec).read
|
52
|
+
else
|
53
|
+
data = open(page).read
|
54
|
+
_cache_file(page, data)
|
55
|
+
end
|
56
|
+
data
|
57
|
+
end
|
58
|
+
|
59
|
+
# define the cache_file(page, data) method on the given class: cls
|
60
|
+
cls.send('define_method', "_cache_file") do |page, data|
|
61
|
+
begin
|
62
|
+
filespec = page.gsub(/^http:\//, directory).gsub(/\/$/, '.html')
|
63
|
+
unless File.exist?(filespec)
|
64
|
+
puts "caching #{filespec}"
|
65
|
+
File.mkdirs(File.dirname(filespec))
|
66
|
+
File.open(filespec, 'w') { |f| f.puts data }
|
67
|
+
end
|
68
|
+
rescue Exception => eMsg
|
69
|
+
puts eMsg.to_s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# == Synopsis
|
75
|
+
# Find all classes that have a read_page instance method and
|
76
|
+
# then overwrite that read_page method with one that handles
|
77
|
+
# the caching. Use the given directory for the cache files.
|
78
|
+
def self.attach_to_classes(directory='/tmp')
|
79
|
+
ObjectSpace.each_object(Class) do |cls|
|
80
|
+
# need to check all scopes for read_page instance method
|
81
|
+
if(cls.public_instance_methods(false).include?("read_page") ||
|
82
|
+
cls.protected_instance_methods(false).include?("read_page") ||
|
83
|
+
cls.private_instance_methods(false).include?("read_page"))
|
84
|
+
ReadPageCache.attach_to(cls, directory)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ruby-debug'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
TMPDIR = File.join(File.dirname(__FILE__), '../tmp')
|
6
|
+
Dir.mkdir(TMPDIR) unless File.exist?(TMPDIR)
|
7
|
+
|
8
|
+
TEST_DATA = "Testing cache read"
|
9
|
+
|
10
|
+
describe "ReadPageCache" do
|
11
|
+
|
12
|
+
after(:each) do
|
13
|
+
Dir.glob(File.join(TMPDIR, '*')).each {|f| File.delete(f) if File.exist?(f)}
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should add read_page method to a class' do
|
17
|
+
class A
|
18
|
+
end
|
19
|
+
# attach to the class then create instance
|
20
|
+
ReadPageCache.attach_to A, TMPDIR
|
21
|
+
a = A.new
|
22
|
+
a.respond_to?('read_page').should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should add read_page method to a class not the instance' do
|
26
|
+
class A
|
27
|
+
end
|
28
|
+
# create instance then attach to the class
|
29
|
+
a = A.new
|
30
|
+
ReadPageCache.attach_to A, TMPDIR
|
31
|
+
a.respond_to?('read_page').should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
# this is not nice but we make a web access to www.example.com
|
35
|
+
# just to get a response to cache. There probably is a better
|
36
|
+
# website to do this to.
|
37
|
+
it 'should override the read_page method in a class' do
|
38
|
+
class A
|
39
|
+
def read_page(page)
|
40
|
+
open(page).read
|
41
|
+
end
|
42
|
+
end
|
43
|
+
ReadPageCache.attach_to A, TMPDIR
|
44
|
+
a = A.new
|
45
|
+
a.read_page('http://www.example.com/')
|
46
|
+
filespec = File.join(TMPDIR, 'www.example.com.html')
|
47
|
+
(File.exist?(filespec).should be_true) && (File.size(filespec).should > 0)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should read from the cache' do
|
51
|
+
filespec = File.join(TMPDIR, 'www.example.com.html')
|
52
|
+
File.open(filespec, "w") {|f| f.puts TEST_DATA}
|
53
|
+
|
54
|
+
class A
|
55
|
+
def read_page(page)
|
56
|
+
open(page).read
|
57
|
+
end
|
58
|
+
end
|
59
|
+
ReadPageCache.attach_to A, TMPDIR
|
60
|
+
a = A.new
|
61
|
+
data = a.read_page('http://www.example.com/').strip
|
62
|
+
data.should == TEST_DATA
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should replace all read_page methods in all classes' do
|
66
|
+
# create two classes with read_page methods
|
67
|
+
class A
|
68
|
+
def read_page(page)
|
69
|
+
open(page).read
|
70
|
+
end
|
71
|
+
end
|
72
|
+
class B
|
73
|
+
def read_page(page)
|
74
|
+
open(page).read
|
75
|
+
end
|
76
|
+
end
|
77
|
+
# when we attach to the class, ReadPageCache also puts a _cache_file method
|
78
|
+
# into the class, so we can simply test for it's presence.
|
79
|
+
ReadPageCache.attach_to_classes(TMPDIR)
|
80
|
+
a = A.new
|
81
|
+
b = B.new
|
82
|
+
(a.respond_to?('_cache_file').should be_true) && (b.respond_to?('_cache_file').should be_true)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: royw-read_page_cache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roy Wright
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-04-20 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: roy@wright.org
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- Rakefile
|
29
|
+
- VERSION.yml
|
30
|
+
- lib/file_extensions.rb
|
31
|
+
- lib/module_extensions.rb
|
32
|
+
- lib/read_page_cache.rb
|
33
|
+
- spec/read_page_cache_spec.rb
|
34
|
+
- spec/spec_helper.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/royw/read_page_cache
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --charset=UTF-8
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.2.0
|
58
|
+
signing_key:
|
59
|
+
specification_version: 2
|
60
|
+
summary: TODO
|
61
|
+
test_files:
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/read_page_cache_spec.rb
|