require 'test_helper' require 'docs' class DocsFileStoreTest < MiniTest::Spec let :store do Docs::FileStore.new(tmp_path) end after do FileUtils.rm_rf "#{tmp_path}/." end def expand_path(path) File.join(tmp_path, path) end def read(path) File.read expand_path(path) end def write(path, content) File.write expand_path(path), content end def exists?(path) File.exist? expand_path(path) end def touch(path) FileUtils.touch expand_path(path) end def mkpath(path) FileUtils.mkpath expand_path(path) end describe "#read" do it "reads a file" do write 'file', 'content' assert_equal 'content', store.read('file') end end describe "#write" do context "with a string" do it "creates the file when it doesn't exist" do store.write 'file', 'content' assert exists?('file') assert_equal 'content', read('file') end it "updates the file when it exists" do touch 'file' store.write 'file', 'content' assert_equal 'content', read('file') end end context "with a Tempfile" do let :file do Tempfile.new('tmp').tap do |file| file.write 'content' file.close end end it "creates the file when it doesn't exist" do store.write 'file', file assert exists?('file') assert_equal 'content', read('file') end it "updates the file when it exists" do touch 'file' store.write 'file', file assert_equal 'content', read('file') end end it "recursively creates directories" do store.write '1/2/file', '' assert exists?('1/2/file') end end describe "#delete" do it "deletes a file" do touch 'file' store.delete 'file' refute exists?('file') end it "deletes a directory" do mkpath '1/2' touch '1/2/file' store.delete '1' refute exists?('1/2/exist') refute exists?('1/2') refute exists?('1') end end describe "#exist?" do it "returns true when the file exists" do touch 'file' assert store.exist?('file') end it "returns false when the file doesn't exist" do refute store.exist?('file') end end describe "#mtime" do it "returns the file modification time" do touch 'file' created_at = Time.now.round - 86400 modified_at = created_at + 1 File.utime created_at, modified_at, expand_path('file') assert_equal modified_at, store.mtime('file') end end describe "#size" do it "returns the file's size" do write 'file', 'content' assert_equal File.size(expand_path('file')), store.size('file') end end describe "#each" do let :paths do paths = [] store.each { |path| paths << path.remove(tmp_path) } paths end it "yields file paths" do touch 'file' assert_equal ['/file'], paths end it "yields directory paths" do mkpath 'dir' assert_equal ['/dir'], paths end it "yields file paths recursively" do mkpath 'dir' touch 'dir/file' assert_includes paths, '/dir/file' end it "yields directory paths recursively" do mkpath 'dir/dir' assert_includes paths, '/dir/dir' end it "doesn't yield file paths that start with '.'" do touch '.file' assert_empty paths end it "doesn't yield directory paths that start with '.'" do mkpath '.dir' assert_empty paths end it "yields directories before what's inside them" do mkpath 'dir' touch 'dir/file' assert paths.index('/dir') < paths.index('/dir/file') end context "when the block deletes the directory" do it "stops yielding what was inside it" do mkpath 'dir' touch 'dir/file' store.each do |path| (@paths ||= []) << path FileUtils.rm_rf(path) if path == expand_path('dir') end refute_includes @paths, expand_path('dir/file') end end end end