require 'spec_helper'

require 'digest/sha1'

RSpec.describe "Inkan" do
  describe '.legitimate?' do
    context "without a hashbang" do
      let(:content) { 'foo bar baz' }

      it "returns true if the file contents match the SHA" do
        open('/tmp/spec.txt', 'w') do |file|
          file.puts "# Generated by Inkan: #{Digest::SHA1.hexdigest(content)}"
          file.print content
        end

        expect(Inkan.legitimate?('/tmp/spec.txt')).to be_truthy
      end

      it "returns false if the file contents don't match the SHA" do
        open('/tmp/spec.txt', 'w') do |file|
          file.puts "# Generated by Inkan: #{Digest::SHA1.hexdigest(content)}"
          file.puts content
        end

        expect(Inkan.legitimate?('/tmp/spec.txt')).to be_falsey
      end

      it "returns false if there is no SHA" do
        open('/tmp/spec.txt', 'w') do |file|
          file.print content
        end

        expect(Inkan.legitimate?('/tmp/spec.txt')).to be_falsey
      end
    end
    context "with a hashbang" do
      let(:content) { "#!/bin/sh\nfoo bar baz" }

      it "returns true if the file contents match the SHA" do
        open('/tmp/spec.txt', 'w') do |file|
          file.puts '#!/bin/sh'
          file.puts "# Generated by Inkan: #{Digest::SHA1.hexdigest(content)}"
          file.print 'foo bar baz'
        end

        expect(Inkan.legitimate?('/tmp/spec.txt')).to be_truthy
      end

      it "returns false if the file contents don't match the SHA" do
        open('/tmp/spec.txt', 'w') do |file|
          file.puts '#!/bin/sh'
          file.puts "# Generated by Inkan: #{Digest::SHA1.hexdigest(content)}"
          file.puts 'foo bar baz'
        end

        expect(Inkan.legitimate?('/tmp/spec.txt')).to be_falsey
      end

      it "returns false if there is no SHA" do
        open('/tmp/spec.txt', 'w') do |file|
          file.print content
        end

        expect(Inkan.legitimate?('/tmp/spec.txt')).to be_falsey
      end
    end
  end

  describe '.seal' do
    it "should write the file after closing the block" do
      Inkan.seal('/tmp/spec.txt') do |inkan|
        inkan.print 'foo bar baz'
      end

      contents = open('/tmp/spec.txt').read
      expect(contents).to match(/foo bar baz$/)
      expect(contents).to match(/^# Generated by Inkan/)
    end
  end

  describe '.render' do
    it "should return the result after closing the block" do
      result = Inkan.render do |inkan|
        inkan.print 'foo bar baz'
      end

      expect(result).to match(/foo bar baz$/)
      expect(result).to match(/^# Generated by Inkan/)
    end
  end

  describe '#seal' do
    let(:inkan) { Inkan.new('/tmp/spec.txt') }

    it "writes out the contents of the buffer" do
      inkan.print "foo bar baz"
      inkan.seal

      expect(open('/tmp/spec.txt').read).to match(/foo bar baz$/)
    end

    it "adds the credit line to the top of the file" do
      inkan.print "foo bar baz"
      inkan.seal

      expect(open('/tmp/spec.txt').read).to match(/^# Generated by Inkan/)
    end

    it "adds the SHA to the top of the file" do
      inkan.print "foo bar baz"
      inkan.seal

      sha = Digest::SHA1.hexdigest("foo bar baz")

      expect(open('/tmp/spec.txt').read).to match(/#{sha}/)
    end
  end

  describe '#render' do
    let(:inkan) { Inkan.new(nil) }

    before { Babushka::ShellHelpers.shell "rm -f /tmp/spec.txt" }

    it "writes out the contents of the buffer" do
      inkan.print "foo bar baz"
      expect(inkan.render).to match(/foo bar baz$/)
    end

    context "when there is no hashbang" do
      before { inkan.print "foo bar baz" }
      it "adds the credit line to the top of the output" do
        expect(inkan.render.split("\n").first).to match(/^# Generated by Inkan/)
      end
      it "adds the SHA to the top of the output" do
        sha = Digest::SHA1.hexdigest("foo bar baz")
        expect(inkan.render.split("\n").first).to match(/#{sha}/)
      end
    end

    context "when there is a hashbang" do
      before { inkan.print "#!/bin/sh\nfoo bar baz" }
      it "leaves the hashbang at the top of the file" do
        expect(inkan.render.split("\n")[0]).to eq('#!/bin/sh')
      end
      it "adds the credit line to the top of the output below the hashbang" do
        expect(inkan.render.split("\n")[1]).to match(/^# Generated by Inkan/)
      end
      it "adds the SHA to the top of the output below the hashbang" do
        sha = Digest::SHA1.hexdigest("#!/bin/sh\nfoo bar baz")
        expect(inkan.render.split("\n")[1]).to match(/#{sha}/)
      end
    end

    it "doesn't write the file" do
      inkan.print "foo bar baz"
      inkan.render
      expect(File.exists?('/tmp/spec.txt')).to be_falsey
    end
  end

  describe '#puts' do
    let(:inkan) { Inkan.new('/tmp/spec.txt') }

    it "adds an extra new line to the output" do
      inkan.puts "foo bar baz"
      inkan.seal

      expect(open('/tmp/spec.txt').read).to match(/foo bar baz\n$/)
    end
  end

  describe '#credit' do
    let(:inkan) { Inkan.new('/tmp/spec.txt') }

    it "defaults to 'Generated by Inkan'" do
      expect(inkan.credit).to eq('Generated by Inkan')
    end

    it "should pass through changes to the file comment" do
      inkan.credit = "Pat's Magic Code"
      inkan.print "foo bar baz"
      inkan.seal

      expect(open('/tmp/spec.txt').read).to match(/^# Pat's Magic Code/)
    end
  end

  describe '#comment' do
    let(:inkan) { Inkan.new('/tmp/spec.txt') }

    it "defaults to a hash symbol" do
      expect(inkan.comment).to eq('#')
    end

    it "should pass through changes to the file credit" do
      inkan.comment = "//"
      inkan.print "foo bar baz"
      inkan.seal

      expect(open('/tmp/spec.txt').read).to match(/^\/\/ Generated by Inkan/)
    end
  end

  describe '#comment_suffix' do
    let(:inkan) { Inkan.new('/tmp/spec.txt') }

    it "defaults to a blank string" do
      expect(inkan.comment_suffix).to eq('')
    end

    it "should pass through changes to the file comment" do
      inkan.comment_suffix = "*/"
      inkan.print "foo bar baz"
      inkan.seal

      expect(open('/tmp/spec.txt').read).to match(/\*\/\n/)
    end
  end
end
