require_relative "../shared"

RSpec.shared_context "versioned scopes with defaults" do
  include_context "versioned"

  context "presentation occurs without use" do
    let :presenter do
      local_view_path = view_path

      Proc.new do
        presenter local_view_path do
          render do
            find(:post).present(posts)
          end
        end
      end
    end

    it "transforms" do |x|
      save_ui_case(x, path: "/posts") do
        call("/posts", method: :post, params: { post: { title: "foo" } })
      end
    end
  end

  context "implicitly using the default" do
    context "used and then further modified" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            render do
              find(:post).attrs[:style][:background] = "blue"
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end
    end

    context "used and then presented" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            render do
              find(:post).present(posts)
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end
    end

    context "used during presentation with no further action" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            render do
              find(:post).present(posts) do |post_view, post|
                unless post.published
                  post_view.use(:unpublished)
                end
              end
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end

      context "changed later" do
        it "transforms" do |x|
          call("/posts", method: :post, params: { post: { title: "foo" } })

          save_ui_case(x, path: "/posts") do
            expect(call("/posts/1", method: :patch, params: { post: { published: true } })[0]).to eq(200)
          end
        end
      end
    end

    context "used during presentation and then further modified" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            render do
              find(:post).present(posts) do |post_view, post|
                unless post.published
                  post_view.use(:unpublished)
                end

                post_view.attrs[:style] = { color: "red" }
              end
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end

      context "changed later" do
        it "transforms" do |x|
          call("/posts", method: :post, params: { post: { title: "foo" } })

          save_ui_case(x, path: "/posts") do
            expect(call("/posts/1", method: :patch, params: { post: { published: true } })[0]).to eq(200)
          end
        end
      end
    end
  end

  context "explicitly using the default" do
    context "used with no further action" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            render do
              find(:post).use(:default)
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end
    end

    context "used and then further modified" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            render do
              find(:post).use(:default).attrs[:style][:background] = "blue"
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end
    end

    context "used and then presented" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            def perform
              find(:post).use(:default).present(posts)
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end
    end

    context "used during presentation with no further action" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            def perform
              find(:post).present(posts) do |post_view, post|
                if post.published
                  post_view.use(:default)
                else
                  post_view.use(:unpublished)
                end
              end
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end

      context "changed later" do
        it "transforms" do |x|
          call("/posts", method: :post, params: { post: { title: "foo" } })

          save_ui_case(x, path: "/posts") do
            expect(call("/posts/1", method: :patch, params: { post: { published: true } })[0]).to eq(200)
          end
        end
      end
    end

    context "used during presentation and then further modified" do
      let :presenter do
        local_view_path = view_path

        Proc.new do
          presenter local_view_path do
            def perform
              find(:post).present(posts) do |post_view, post|
                if post.published
                  post_view.use(:default)
                else
                  post_view.use(:unpublished)
                end

                post_view.attrs[:style] = { color: "red" }
              end
            end
          end
        end
      end

      it "transforms" do |x|
        save_ui_case(x, path: "/posts") do
          call("/posts", method: :post, params: { post: { title: "foo" } })
        end
      end

      context "changed later" do
        it "transforms" do |x|
          call("/posts", method: :post, params: { post: { title: "foo" } })

          save_ui_case(x, path: "/posts") do
            expect(call("/posts/1", method: :patch, params: { post: { published: true } })[0]).to eq(200)
          end
        end
      end
    end
  end
end

RSpec.describe "versioned scopes with an explicit default" do
  include_context "versioned scopes with defaults"

  let :view_path do
    "/versioned/scopes/defaults"
  end
end

RSpec.describe "versioned scopes with an implicit default" do
  include_context "versioned scopes with defaults"

  let :view_path do
    "/versioned/scopes/defaults/implicit"
  end
end
