dotnet_sdk/spec/dependabot/dotnet_sdk/file_parser_spec.rb
# typed: false
# frozen_string_literal: true

require "spec_helper"
require "dependabot/dependency_file"
require "dependabot/source"
require "dependabot/dotnet_sdk/file_parser"
require "dependabot/dotnet_sdk/requirement"
require_common_spec "file_parsers/shared_examples_for_file_parsers"

RSpec.describe Dependabot::DotnetSdk::FileParser do
  let(:dependencies) { parser.parse }
  let(:repo_contents_path) { build_tmp_repo(project_name, path: "projects") }
  let(:files) do
    project_dependency_files(project_name, directory: directory)
  end
  let(:source) do
    Dependabot::Source.new(
      provider: "github",
      repo: "mona/dotnet-sdk-example",
      directory: directory
    )
  end
  let(:parser) do
    described_class.new(dependency_files: files, source: source, repo_contents_path: repo_contents_path)
  end

  it_behaves_like "a dependency file parser"

  shared_examples_for "parse" do
    it "parses dependencies fine" do
      expect(dependencies.size).to eq(expectations.size)

      expectations.each do |expected|
        version = expected[:version]
        name = expected[:name]
        requirements = expected[:requirements]
        metadata = expected[:metadata]

        dependency = dependencies.find { |dep| dep.name == name }
        expect(dependency).to have_attributes(
          name: name,
          version: version,
          requirements: requirements,
          metadata: metadata
        )
      end

      ecosystem = parser.ecosystem

      expect(ecosystem.name).to eq("dotnet-sdk")
      expect(ecosystem.package_manager.name).to eq("dotnet_sdk")
      expect(ecosystem.language.name).to eq("DotnetSDK")
    end
  end

  context "with a global.json in repo root" do
    let(:project_name) { "config_in_root" }
    let(:directory) { "/" }

    let(:expectations) do
      [
        {
          name: "dotnet-sdk",
          version: "8.0.300",
          requirements: [{
            file: "global.json",
            groups: [],
            requirement: "8.0.300",
            source: nil
          }],
          metadata: {
            allow_prerelease: false,
            roll_forward: "latestPatch"
          }
        }
      ].freeze
    end

    it_behaves_like "parse"
  end

  context "with a global.json containing UTF-8 BOM" do
    let(:project_name) { "config_in_root" }
    let(:directory) { "/" }
    let(:files) do
      [
        Dependabot::DependencyFile.new(
          name: "global.json",
          content: "\uFEFF" + <<~JSON,
            {
              "sdk": {
                "version": "8.0.300",
                "rollForward": "latestMinor",
                "allowPrerelease": true
              }
            }
          JSON
          directory: directory
        )
      ]
    end

    let(:expectations) do
      [
        {
          name: "dotnet-sdk",
          version: "8.0.300",
          requirements: [{
            file: "global.json",
            groups: [],
            requirement: "8.0.300",
            source: nil
          }],
          metadata: {
            allow_prerelease: true,
            roll_forward: "latestMinor"
          }
        }
      ].freeze
    end

    it_behaves_like "parse"

    it "handles UTF-8 BOM correctly" do
      expect { dependencies }.not_to raise_error
      expect(dependencies.size).to eq(1)

      dependency = dependencies.first
      expect(dependency.name).to eq("dotnet-sdk")
      expect(dependency.version).to eq("8.0.300")
      expect(dependency.metadata[:allow_prerelease]).to be true
      expect(dependency.metadata[:roll_forward]).to eq("latestMinor")
    end
  end
end
