From 66735fb2d15453bc5b362b09596c4d8119ffaf59 Mon Sep 17 00:00:00 2001 From: kbukum1 Date: Tue, 7 Jan 2025 10:41:34 -0800 Subject: [PATCH] Update `npm_and_yarn` deprecation and unsupported checks for `npm`, `pnpm`, and `yarn` package managers (#11240) --- .../lib/dependabot/npm_and_yarn/helpers.rb | 6 +- .../npm_and_yarn/package_manager.rb | 76 ++++++--- .../npm_and_yarn/file_parser_spec.rb | 2 + .../file_updater/npm_lockfile_updater_spec.rb | 2 + .../npm_and_yarn/file_updater_spec.rb | 2 + .../dependabot/npm_and_yarn/helpers_spec.rb | 49 +++--- .../dependabot/npm_and_yarn/language_spec.rb | 9 +- .../npm_and_yarn/npm_package_manager_spec.rb | 36 +++-- .../package_manager_helper_spec.rb | 144 +++++++++++++++++- .../npm_and_yarn/pnpm_package_manager_spec.rb | 42 ++++- .../subdependency_version_resolver_spec.rb | 2 + .../update_checker/version_resolver_spec.rb | 2 + .../npm_and_yarn/update_checker_spec.rb | 2 + .../npm_and_yarn/yarn_package_manager_spec.rb | 43 +++++- 14 files changed, 342 insertions(+), 75 deletions(-) diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb index 5129d1d6d3..840f2ffec5 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb @@ -41,9 +41,7 @@ module Helpers # rubocop:disable Metrics/ModuleLength # Otherwise, we are going to use old versionining npm 6 sig { params(lockfile: T.nilable(DependencyFile)).returns(Integer) } def self.npm_version_numeric(lockfile) - if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn) - return npm_version_numeric_latest(lockfile) - end + return npm_version_numeric_latest(lockfile) if Dependabot::Experiments.enabled?(:npm_v6_deprecation_warning) fallback_version_npm8 = Dependabot::Experiments.enabled?(:npm_fallback_version_above_v6) @@ -174,7 +172,7 @@ def self.fetch_yarnrc_yml_value(key, default_value) def self.npm8?(package_lock) return true unless package_lock&.content - if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn) + if Dependabot::Experiments.enabled?(:npm_v6_deprecation_warning) return npm_version_numeric_latest(package_lock) >= NPM_V8 end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb index 98f5555ea1..e86198ec9c 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb @@ -72,14 +72,16 @@ class NpmPackageManager < Ecosystem::VersionManager sig do params( - raw_version: String, + detected_version: T.nilable(String), + raw_version: T.nilable(String), requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) ).void end - def initialize(raw_version, requirement: nil) + def initialize(detected_version: nil, raw_version: nil, requirement: nil) super( name: NAME, - version: Version.new(raw_version), + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, deprecated_versions: DEPRECATED_VERSIONS, supported_versions: SUPPORTED_VERSIONS, requirement: requirement @@ -88,17 +90,22 @@ def initialize(raw_version, requirement: nil) sig { override.returns(T::Boolean) } def deprecated? + return false unless detected_version + return false if unsupported? + return false unless Dependabot::Experiments.enabled?(:npm_v6_deprecation_warning) - deprecated_versions.include?(version) + deprecated_versions.include?(detected_version) end sig { override.returns(T::Boolean) } def unsupported? + return false unless detected_version + return false unless Dependabot::Experiments.enabled?(:npm_v6_unsupported_error) - supported_versions.all? { |supported| supported > version } + supported_versions.all? { |supported| supported > detected_version } end end @@ -123,14 +130,16 @@ class YarnPackageManager < Ecosystem::VersionManager sig do params( - raw_version: String, - requirement: T.nilable(Requirement) + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) ).void end - def initialize(raw_version, requirement: nil) + def initialize(detected_version: nil, raw_version: nil, requirement: nil) super( name: NAME, - version: Version.new(raw_version), + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, deprecated_versions: DEPRECATED_VERSIONS, supported_versions: SUPPORTED_VERSIONS, requirement: requirement @@ -168,14 +177,16 @@ class PNPMPackageManager < Ecosystem::VersionManager sig do params( - raw_version: String, - requirement: T.nilable(Requirement) + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) ).void end - def initialize(raw_version, requirement: nil) + def initialize(detected_version: nil, raw_version: nil, requirement: nil) super( name: NAME, - version: Version.new(raw_version), + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, deprecated_versions: DEPRECATED_VERSIONS, supported_versions: SUPPORTED_VERSIONS, requirement: requirement @@ -284,14 +295,16 @@ class Language < Ecosystem::VersionManager sig do params( + detected_version: T.nilable(String), raw_version: T.nilable(String), - requirement: T.nilable(Requirement) + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) ).void end - def initialize(raw_version, requirement: nil) + def initialize(detected_version: nil, raw_version: nil, requirement: nil) super( name: NAME, - version: Version.new(raw_version), + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, deprecated_versions: DEPRECATED_VERSIONS, supported_versions: SUPPORTED_VERSIONS, requirement: requirement @@ -349,7 +362,7 @@ def package_manager sig { returns(Ecosystem::VersionManager) } def language @language ||= Language.new( - Helpers.node_version, + raw_version: Helpers.node_version, requirement: language_requirement ) end @@ -458,6 +471,23 @@ def setup(name) # rubocop:enable Metrics/PerceivedComplexity # rubocop:enable Metrics/MethodLength + sig { params(name: String).returns(T.nilable(String)) } + def detect_version(name) + # we prioritize version mentioned in "packageManager" instead of "engines" + if @manifest_package_manager&.start_with?("#{name}@") + detected_version = @manifest_package_manager.split("@").last.to_s + end + + # if "packageManager" have no version specified, we check if we can extract "engines" information + detected_version = check_engine_version(name) if !detected_version || detected_version.empty? + + # if "packageManager" and "engines" both are not present, we check if we can infer the version + # from the manifest file lockfileVersion + detected_version = guessed_version(name) if !detected_version || detected_version.empty? + + detected_version&.to_s + end + sig { params(name: T.nilable(String)).returns(Ecosystem::VersionManager) } def package_manager_by_name(name) Dependabot.logger.info("Resolving package manager for: #{name || 'default'}") @@ -465,10 +495,13 @@ def package_manager_by_name(name) name = ensure_valid_package_manager(name) package_manager_class = T.must(PACKAGE_MANAGER_CLASSES[name]) - if name == NpmPackageManager::NAME - detected_version = Helpers.npm_version_numeric_latest(@lockfiles[:npm]) - package_manager = package_manager_class.new(detected_version.to_s) + detected_version = detect_version(name) + # if we have a detected version, we check if it is deprecated or unsupported + if detected_version + package_manager = package_manager_class.new( + detected_version: detected_version.to_s + ) return package_manager if package_manager.deprecated? || package_manager.unsupported? end @@ -483,7 +516,8 @@ def package_manager_by_name(name) end package_manager_class.new( - installed_version.to_s, + detected_version: detected_version.to_s, + raw_version: installed_version, requirement: package_manager_requirement ) rescue StandardError => e diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_parser_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_parser_spec.rb index cfdd667837..64e5d249fd 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_parser_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_parser_spec.rb @@ -44,6 +44,8 @@ .with(:enable_corepack_for_npm_and_yarn).and_return(enable_corepack_for_npm_and_yarn) allow(Dependabot::Experiments).to receive(:enabled?) .with(:enable_shared_helpers_command_timeout).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning).and_return(true) end after do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater_spec.rb index c5fe8dbaee..739cd770e5 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater_spec.rb @@ -74,6 +74,8 @@ .with(:enable_corepack_for_npm_and_yarn).and_return(enable_corepack_for_npm_and_yarn) allow(Dependabot::Experiments).to receive(:enabled?) .with(:enable_shared_helpers_command_timeout).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning).and_return(true) end after do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater_spec.rb index 3514c191af..a96a61038f 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater_spec.rb @@ -70,6 +70,8 @@ .with(:enable_corepack_for_npm_and_yarn).and_return(enable_corepack_for_npm_and_yarn) allow(Dependabot::Experiments).to receive(:enabled?) .with(:enable_shared_helpers_command_timeout).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning).and_return(true) end after do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/helpers_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/helpers_spec.rb index 6419a70df9..41c133c6af 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/helpers_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/helpers_spec.rb @@ -92,29 +92,29 @@ ) end - it "returns flattened list of dependencies populated with :all_versions metadata" do - dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new - dependency_set << foo_a << bar_a << foo_c << bar_c << foo_b << bar_b + context "when dependencies in set already have :all_versions metadata" do + it "returns flattened list of dependencies populated with :all_versions metadata" do + dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new + dependency_set << foo_a << bar_a << foo_c << bar_c << foo_b << bar_b - expect(described_class.dependencies_with_all_versions_metadata(dependency_set)).to eq([ - Dependabot::Dependency.new( - name: "foo", - version: "0.0.1", - requirements: (foo_a.requirements + foo_c.requirements + foo_b.requirements).uniq, - package_manager: "npm_and_yarn", - metadata: { all_versions: [foo_a, foo_c, foo_b] } - ), - Dependabot::Dependency.new( - name: "bar", - version: "0.2.1", - requirements: (bar_a.requirements + bar_c.requirements + bar_b.requirements).uniq, - package_manager: "npm_and_yarn", - metadata: { all_versions: [bar_a, bar_c, bar_b] } - ) - ]) - end + expect(described_class.dependencies_with_all_versions_metadata(dependency_set)).to eq([ + Dependabot::Dependency.new( + name: "foo", + version: "0.0.1", + requirements: (foo_a.requirements + foo_c.requirements + foo_b.requirements).uniq, + package_manager: "npm_and_yarn", + metadata: { all_versions: [foo_a, foo_c, foo_b] } + ), + Dependabot::Dependency.new( + name: "bar", + version: "0.2.1", + requirements: (bar_a.requirements + bar_c.requirements + bar_b.requirements).uniq, + package_manager: "npm_and_yarn", + metadata: { all_versions: [bar_a, bar_c, bar_b] } + ) + ]) + end - context "when dependencies in set already have :all_versions metadata" do it "correctly merges existing metadata into new metadata" do dependency_set = Dependabot::NpmAndYarn::FileParser::DependencySet.new dependency_set << foo_a @@ -338,6 +338,7 @@ context "when the feature flag :enable_corepack_for_npm_and_yarn is enabled" do before do allow(Dependabot::Experiments).to receive(:enabled?).with(:enable_corepack_for_npm_and_yarn).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?).with(:npm_v6_deprecation_warning).and_return(true) end it "returns true if lockfileVersion is 3 or higher" do @@ -360,11 +361,17 @@ context "when the feature flag :enable_corepack_for_npm_and_yarn is disabled" do before do allow(Dependabot::Experiments).to receive(:enabled?).with(:enable_corepack_for_npm_and_yarn).and_return(false) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning) + .and_return(true) end context "when :npm_fallback_version_above_v6 is enabled" do before do allow(Dependabot::Experiments).to receive(:enabled?).with(:npm_fallback_version_above_v6).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning) + .and_return(true) end it "returns true if lockfileVersion is 2 or higher" do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/language_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/language_spec.rb index 380e2ddb84..f6490bc3e8 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/language_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/language_spec.rb @@ -1,12 +1,17 @@ # typed: false # frozen_string_literal: true -require "dependabot/ecosystem" require "dependabot/npm_and_yarn/package_manager" +require "dependabot/ecosystem" require "spec_helper" RSpec.describe Dependabot::NpmAndYarn::Language do - let(:language) { described_class.new(raw_version, requirement: requirement) } + let(:language) do + described_class.new( + raw_version: raw_version, + requirement: requirement + ) + end let(:raw_version) { "16.13.1" } let(:requirement) { nil } diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb index f0e68da32a..8de1a03ed5 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb @@ -6,14 +6,24 @@ require "spec_helper" RSpec.describe Dependabot::NpmAndYarn::NpmPackageManager do - let(:package_manager) { described_class.new(version) } + let(:package_manager) do + described_class.new( + detected_version: detected_version, + raw_version: raw_version + ) + end + + let(:detected_version) { "8" } + let(:raw_version) { "9.5.1" } describe "#initialize" do context "when version is a String" do - let(:version) { "8" } + let(:detected_version) { "8" } + let(:raw_version) { "9.5.1" } it "sets the version correctly" do - expect(package_manager.version).to eq(Dependabot::Version.new(version)) + expect(package_manager.detected_version).to eq(Dependabot::Version.new(detected_version)) + expect(package_manager.version).to eq(Dependabot::Version.new(raw_version)) end it "sets the name correctly" do @@ -33,7 +43,8 @@ end describe "#deprecated?" do - let(:version) { "6" } + let(:detected_version) { "6" } + let(:raw_version) { "8.0.1" } it "returns false" do expect(package_manager.deprecated?).to be false @@ -59,7 +70,7 @@ end context "when npm_v6_deprecation_warning is enabled but version is not deprecated" do - let(:version) { "9" } + let(:detected_version) { "9" } let(:deprecation_enabled) { true } let(:unsupported_enabled) { false } @@ -89,7 +100,8 @@ end describe "#unsupported?" do - let(:version) { "5" } + let(:detected_version) { "5" } + let(:raw_version) { "8.0.1" } it "returns false for supported versions" do expect(package_manager.unsupported?).to be false @@ -103,7 +115,9 @@ end context "when npm_v6_unsupported_error is enabled and version is unsupported" do - let(:version) { "6" } + let(:detected_version) { "6" } + let(:raw_version) { "8.0.1" } + let(:unsupported_enabled) { true } it "returns true" do @@ -112,7 +126,9 @@ end context "when npm_v6_unsupported_error is enabled but version is supported" do - let(:version) { "7" } + let(:detected_version) { "7" } + let(:raw_version) { "8.0.1" } + let(:unsupported_enabled) { true } it "returns false" do @@ -138,7 +154,7 @@ end context "when npm_v6_unsupported_error is enabled and version is unsupported" do - let(:version) { "6" } + let(:detected_version) { "6" } let(:unsupported_enabled) { true } it "raises a ToolVersionNotSupported error" do @@ -147,7 +163,7 @@ end context "when npm_v6_unsupported_error is disabled" do - let(:version) { "6" } + let(:detected_version) { "6" } let(:unsupported_enabled) { false } it "does not raise an error" do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb index ded4733cb1..d6bb655cc5 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb @@ -158,11 +158,14 @@ allow(Dependabot::Experiments).to receive(:enabled?) .with(:npm_v6_unsupported_error) .and_return(false) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:enable_shared_helpers_command_timeout) + .and_return(true) end it "returns the deprecated package manager" do expect(package_manager.deprecated?).to be true - expect(package_manager.version.to_s).to eq "6" + expect(package_manager.detected_version.to_s).to eq "6" end end @@ -203,10 +206,13 @@ allow(Dependabot::Experiments).to receive(:enabled?) .with(:npm_v6_unsupported_error) .and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:enable_shared_helpers_command_timeout) + .and_return(true) end it "returns the unsupported package manager" do - expect(package_manager.version.to_s).to eq "6" + expect(package_manager.detected_version.to_s).to eq "6" expect(package_manager.unsupported?).to be true end end @@ -250,10 +256,142 @@ allow(Dependabot::Experiments).to receive(:enabled?) .with(:npm_v6_unsupported_error) .and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:enable_shared_helpers_command_timeout) + .and_return(true) end it "returns the deprecated version" do - expect(package_manager.version.to_s).to eq "6" + expect(package_manager.detected_version.to_s).to eq "6" + end + end + end + + describe "#detect_version" do + let(:helper) { described_class.new(package_json, lockfiles, register_config_files, []) } + + context "when packageManager field exists" do + let(:package_json) { { "packageManager" => "npm@7.5.2" } } + + context "with a selected engine" do + let(:package_json) do + { "packageManager" => "npm@7.5.2", "engines" => { "npm" => ">=7.0.0 <8.0.0" } } + end + + context "when package manager lockfile exists" do + let(:lockfiles) { { npm: npm_lockfile } } + + it "returns the packageManager field value version over engines and lockfile" do + expect(helper.detect_version("npm")).to eq("7.5.2") + end + end + + context "when package manager lockfile does not exist" do + let(:lockfiles) { {} } + + it "returns the packageManager field value version over engines" do + expect(helper.detect_version("npm")).to eq("7.5.2") + end + end + end + + context "with multiple engines including the selected one" do + let(:package_json) do + { + "packageManager" => "npm", + "engines" => { "npm" => "8.0.0", "yarn" => "2.0.0" } + } + end + + context "when package manager lockfile exists" do + let(:lockfiles) { { npm: npm_lockfile } } + + it "returns engines version over lockfile" do + expect(helper.detect_version("npm")).to eq("8.0.0") + end + end + + context "when package manager lockfile does not exist" do + let(:lockfiles) { {} } + + it "returns the engines version" do + expect(helper.detect_version("npm")).to eq("8.0.0") + end + end + end + + context "with no engine" do + context "when package manager lockfile exists" do + let(:lockfiles) { { npm: npm_lockfile } } + + it "returns the packageManager field version" do + expect(helper.detect_version("npm")).to eq("7.5.2") + end + end + + context "when package manager lockfile does not exist" do + let(:lockfiles) { {} } + + it "returns the packageManager field version" do + expect(helper.detect_version("npm")).to eq("7.5.2") + end + end + end + end + + context "when packageManager field does not exist" do + let(:package_json) { {} } + + context "with engines specifying the selected package manager" do + let(:package_json) { { "engines" => { "npm" => "8.0.0" } } } + + context "when package manager lockfile exists" do + let(:lockfiles) { { npm: npm_lockfile } } + + it "returns engines version over lockfile" do + expect(helper.detect_version("npm")).to eq("8.0.0") + end + end + + context "when package manager lockfile does not exist" do + let(:lockfiles) { {} } + + it "returns the engines version" do + expect(helper.detect_version("npm")).to eq("8.0.0") + end + end + end + + context "with no engines and no lockfile" do + let(:lockfiles) { {} } + + it "returns nil as no version can be detected" do + expect(helper.detect_version("npm")).to be_nil + end + end + + context "with no engines and a lockfile for the selected package manager" do + let(:lockfiles) { { npm: npm_lockfile } } + + it "returns the version inferred from the lockfile" do + expect(helper.detect_version("npm")).to eq("8") + end + end + + context "with no engines and a lockfile for a different package manager" do + let(:lockfiles) { { yarn: yarn_lockfile } } + + it "returns nil as no version can be detected for the selected package manager" do + expect(helper.detect_version("npm")).to be_nil + end + end + + context "with no engines and multiple lockfiles" do + let(:lockfiles) { { npm: npm_lockfile, yarn: yarn_lockfile } } + + it "returns the version inferred from the lockfile matching the selected package manager" do + expect(helper.detect_version("npm")).to eq("8") + end end end end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb index e613c8c566..d0e42c0f26 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb @@ -6,14 +6,24 @@ require "spec_helper" RSpec.describe Dependabot::NpmAndYarn::PNPMPackageManager do - let(:package_manager) { described_class.new(version) } + let(:package_manager) do + described_class.new( + detected_version: detected_version, + raw_version: raw_version + ) + end + + let(:detected_version) { "8" } + let(:raw_version) { "9.0.0" } describe "#initialize" do context "when version is a String" do - let(:version) { "9" } + let(:detected_version) { "9" } + let(:raw_version) { "9.0.0" } it "sets the version correctly" do - expect(package_manager.version).to eq(Dependabot::Version.new(version)) + expect(package_manager.detected_version).to eq(Dependabot::Version.new(detected_version)) + expect(package_manager.version).to eq(Dependabot::Version.new(raw_version)) end it "sets the name correctly" do @@ -33,18 +43,36 @@ end describe "#deprecated?" do - let(:version) { "7" } + let(:detected_version) { "7" } + let(:raw_version) { "8.0.0" } - it "returns false" do + it "always returns false" do expect(package_manager.deprecated?).to be false end end describe "#unsupported?" do - let(:version) { "6" } + let(:detected_version) { "6" } + let(:raw_version) { "7.0.0" } - it "returns true for unsupported versions" do + it "always returns false" do expect(package_manager.unsupported?).to be false end + + context "with supported versions" do + let(:detected_version) { "8" } + + it "still returns false" do + expect(package_manager.unsupported?).to be false + end + end + end + + describe "#raise_if_unsupported!" do + let(:detected_version) { "6" } + + it "does not raise an error" do + expect { package_manager.raise_if_unsupported! }.not_to raise_error + end end end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver_spec.rb index 10247cb171..290a2e6b4d 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver_spec.rb @@ -43,6 +43,8 @@ .with(:enable_corepack_for_npm_and_yarn).and_return(enable_corepack_for_npm_and_yarn) allow(Dependabot::Experiments).to receive(:enabled?) .with(:enable_shared_helpers_command_timeout).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning).and_return(true) end after do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/version_resolver_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/version_resolver_spec.rb index 05a001c0a4..778745eb63 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/version_resolver_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/version_resolver_spec.rb @@ -85,6 +85,8 @@ .with(:enable_corepack_for_npm_and_yarn).and_return(enable_corepack_for_npm_and_yarn) allow(Dependabot::Experiments).to receive(:enabled?) .with(:enable_shared_helpers_command_timeout).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning).and_return(true) end after do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker_spec.rb index 1af401cf5a..cb2f35b6e1 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker_spec.rb @@ -73,6 +73,8 @@ .with(:npm_fallback_version_above_v6).and_return(npm_fallback_version_above_v6_enabled) allow(Dependabot::Experiments).to receive(:enabled?) .with(:enable_shared_helpers_command_timeout).and_return(true) + allow(Dependabot::Experiments).to receive(:enabled?) + .with(:npm_v6_deprecation_warning).and_return(true) end after do diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb index d052bf9f2e..99e696b76a 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb @@ -6,14 +6,24 @@ require "spec_helper" RSpec.describe Dependabot::NpmAndYarn::YarnPackageManager do - let(:package_manager) { described_class.new(version) } + let(:package_manager) do + described_class.new( + detected_version: detected_version, + raw_version: raw_version + ) + end + + let(:detected_version) { "3" } + let(:raw_version) { "3.5.0" } describe "#initialize" do context "when version is a String" do - let(:version) { "2" } + let(:detected_version) { "2" } + let(:raw_version) { "2.8.0" } it "sets the version correctly" do - expect(package_manager.version).to eq(Dependabot::Version.new(version)) + expect(package_manager.detected_version).to eq(Dependabot::Version.new(detected_version)) + expect(package_manager.version).to eq(Dependabot::Version.new(raw_version)) end it "sets the name correctly" do @@ -33,18 +43,37 @@ end describe "#deprecated?" do - let(:version) { "1" } + let(:detected_version) { "1" } + let(:raw_version) { "1.22.10" } - it "returns false" do + it "always returns false" do expect(package_manager.deprecated?).to be false end end describe "#unsupported?" do - let(:version) { "4" } + let(:detected_version) { "4" } + let(:raw_version) { "4.0.0" } - it "returns false for supported versions" do + it "always returns false" do expect(package_manager.unsupported?).to be false end + + context "with supported versions" do + let(:detected_version) { "2" } + let(:raw_version) { "2.8.0" } + + it "still returns false" do + expect(package_manager.unsupported?).to be false + end + end + end + + describe "#raise_if_unsupported!" do + let(:detected_version) { "1" } + + it "does not raise an error" do + expect { package_manager.raise_if_unsupported! }.not_to raise_error + end end end