require 'spec_helper'

RSpec.describe Prawn::SVG::CSS::Stylesheets do
  describe "typical usage" do
    let(:svg) { <<-SVG }
      <svg>
        <style>
          #inner rect { fill: #0000ff; }
          #outer { fill: #220000; }
          .hero > rect { fill: #00ff00; }
          rect { fill: #ff0000; }
          rect ~ rect { fill: #330000; }
          rect + rect { fill: #440000; }
          rect:first-child:last-child { fill: #441234; }

          circle:first-child { fill: #550000; }
          circle:nth-child(2) { fill: #660000; }
          circle:last-child { fill: #770000; }

          square[chocolate] { fill: #880000; }
          square[abc=def] { fill: #990000; }
          square[abc^=ghi] { fill: #aa0000; }
          square[abc$=jkl] { fill: #bb0000; }
          square[abc*=mno] { fill: #cc0000; }
          square[abc~=pqr] { fill: #dd0000; }
          square[abc|=stu] { fill: #ee0000; }
        </style>

        <rect width="1" height="1" />
        <rect width="2" height="2" id="outer" />

        <g class="hero large">
          <rect width="3" height="3" />
          <rect width="4" height="4" style="fill: #777777;" />
          <rect width="5" height="5" />

          <g id="inner">
            <rect width="6" height="6" />
          </g>

          <circle width="100" />

          <g id="circles">
            <circle width="7" />
            <circle width="8" />
            <circle width="9" />
          </g>
        </g>

        <square width="10" chocolate="hi there" />
        <square width="11" abc="def" />
        <square width="12" abc="ghidef" />
        <square width="13" abc="aghidefjkl" />
        <square width="14" abc="agmnohidefjklx" />
        <square width="15" abc="aeo cnj pqr" />
        <square width="16" abc="eij-stu-asd" />
      </svg>
    SVG

    it "associates styles with elements" do
      result = Prawn::SVG::CSS::Stylesheets.new(CssParser::Parser.new, REXML::Document.new(svg)).load
      width_and_styles = result.map { |k, v| [k.attributes["width"].to_i, v] }.sort_by(&:first)

      expected = [
        [1, [["fill", "#ff0000", false]]],
        [2, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#440000", false], ["fill", "#220000", false]]],
        [3, [["fill", "#ff0000", false], ["fill", "#00ff00", false]]],
        [4, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#440000", false], ["fill", "#00ff00", false]]],
      ]

      #
      # Under ruby < 2.6, a bug in REXML causes the /following-sibling selector to
      # only pick the first matching sibling.  This means the + CSS combinator behaves
      # incorrectly in the following example:
      #
      # <a>
      #   <b a="1" />
      #   <b a="2" />
      #   <b a="3" />
      # </a>
      #
      # The css selector `a b + b` will only pick the second <b>, whereas it should
      # pick both the second and third <b> elements.
      #
      if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
        expected << [5, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#330000", false], ["fill", "#00ff00", false]]]
      else
        expected << [5, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#330000", false], ["fill", "#440000", false], ["fill", "#00ff00", false]]]
      end

      expected.concat [
        [6, [["fill", "#ff0000", false], ["fill", "#441234", false], ["fill", "#0000ff", false]]],
        [7, [["fill", "#550000", false]]],
        [8, [["fill", "#660000", false]]],
        [9, [["fill", "#770000", false]]],
        [10, [["fill", "#880000", false]]],
        [11, [["fill", "#990000", false]]],
        [12, [["fill", "#aa0000", false]]],
        [13, [["fill", "#bb0000", false]]],
        [14, [["fill", "#cc0000", false]]],
        [15, [["fill", "#dd0000", false]]],
        [16, [["fill", "#ee0000", false]]],
      ]

      expect(width_and_styles).to eq(expected)
    end
  end

  describe "style tag parsing" do
    let(:svg) do
      <<-SVG
<svg>
  <some-tag>
    <style>a
  before&gt;
  x <![CDATA[ y
  inside <>&gt;
  k ]]> j
  after
z</style>
  </some-tag>

  <other-tag>
    <more-tag>
      <style>hello</style>
    </more-tag>
  </other-tag>
</svg>
      SVG
    end

    it "scans the document for style tags and adds the style information to the css parser" do
      css_parser = instance_double(CssParser::Parser)

      expect(css_parser).to receive(:add_block!).with("a\n  before>\n  x  y\n  inside <>&gt;\n  k  j\n  after\nz")
      expect(css_parser).to receive(:add_block!).with("hello")
      allow(css_parser).to receive(:each_rule_set)

      Prawn::SVG::CSS::Stylesheets.new(css_parser, REXML::Document.new(svg)).load
    end
  end
end
