licensed/test/configuration_test.rb

608 строки
22 KiB
Ruby

# frozen_string_literal: true
require "test_helper"
describe Licensed::Configuration do
let(:options) { { } }
let(:config) { Licensed::Configuration.new(options) }
let(:fixtures) { File.expand_path("../fixtures/config", __FILE__) }
describe "load_from" do
let(:config) { Licensed::Configuration.load_from(load_path) }
let(:app) { config.apps.first }
describe "a relative directory path" do
let(:load_path) { Pathname.new(fixtures).relative_path_from(Pathname.pwd) }
it "loads the configuration" do
assert_equal "licensed-yml", app["name"]
end
end
describe "an absolute directory path" do
let(:load_path) { fixtures }
it "loads a config from an absolute directory path" do
assert_equal "licensed-yml", app["name"]
end
end
describe "a relative file path" do
let(:load_path) do
file = File.join(fixtures, "config.yml")
Pathname.new(file).relative_path_from(Pathname.pwd)
end
it "loads a config from a relative file path" do
assert_equal "config-yml", app["name"]
end
end
describe "an absolute file path" do
let(:load_path) { File.join(fixtures, "config.yml") }
it "loads a config from an absolute file path" do
assert_equal "config-yml", app["name"]
end
end
describe "a json configuration file" do
let(:load_path) { File.join(fixtures, ".licensed.json") }
it "loads json configurations" do
assert_equal "licensed-json", app["name"]
end
end
it "raises an error if a default config file is not found" do
Dir.mktmpdir do |dir|
assert_raises ::Licensed::Configuration::LoadError do
Licensed::Configuration.load_from(dir)
end
end
end
it "raises an error if the config file type is not understood" do
file = File.join(fixtures, ".licensed.unknown")
assert_raises ::Licensed::Configuration::LoadError do
Licensed::Configuration.load_from(file)
end
end
end
describe "apps" do
let(:apps) do
[
{
"name" => "app1",
"override" => "override",
"cache_path" => "app1/vendor/licenses",
"source_path" => File.expand_path("../../", __FILE__)
},
{
"name" => "app2",
"cache_path" => "app2/vendor/licenses",
"source_path" => File.expand_path("../../", __FILE__)
}
]
end
let(:options) { { "apps" => apps } }
let(:config) { Licensed::Configuration.new(options) }
it "returns a default app if apps not specified in configuration" do
options.delete "apps"
assert_equal 1, config.apps.size
app = config.apps.first
assert_equal Pathname.pwd, app.source_path
assert_equal app.root.join(Licensed::AppConfiguration::DEFAULT_CACHE_PATH),
app.cache_path
assert_equal File.basename(Dir.pwd), app["name"]
end
it "expands source_path patterns in default app" do
options.delete "apps"
options["source_path"] = File.expand_path("../fixtures/*", __FILE__)
expected_source_paths = Dir.glob(options["source_path"]).select { |p| File.directory?(p) }
expected_source_paths.each do |source_path|
app = config.apps.find { |a| a["source_path"] == source_path }
assert app
dir_name = File.basename(source_path)
assert_equal app.root.join(Licensed::AppConfiguration::DEFAULT_CACHE_PATH, dir_name),
app.cache_path
assert_equal dir_name, app["name"]
end
end
it "returns configured apps" do
assert_equal 2, config.apps.size
assert_equal "app1", config.apps[0]["name"]
assert_equal "app2", config.apps[1]["name"]
config.apps.each do |app|
assert_equal File.expand_path("../../", __FILE__), app["source_path"]
end
end
it "includes default options" do
options["default"] = "default"
config.apps.each do |app|
assert_equal "default", app["default"]
end
end
it "can override default options" do
options["default"] = "default"
apps[0]["default"] = "override"
assert_equal "override", config.apps[0]["default"]
end
it "expands patterns in configured apps" do
apps.clear
apps << { "source_path" => File.expand_path("../fixtures/*", __FILE__) }
expected_source_paths = Dir.glob(apps[0]["source_path"]).select { |p| File.directory?(p) }
expected_source_paths.each do |source_path|
app = config.apps.find { |a| a["source_path"] == source_path }
assert app
dir_name = File.basename(source_path)
assert_equal app.root.join(Licensed::AppConfiguration::DEFAULT_CACHE_PATH, dir_name),
app.cache_path
assert_equal dir_name, app["name"]
end
end
it "expands source_path patterns that result in a single path" do
apps.clear
apps << { "source_path" => File.expand_path("../../lib/*", __FILE__) }
expected_source_paths = Dir.glob(apps[0]["source_path"]).select { |p| File.directory?(p) }
expected_source_paths.each do |source_path|
app = config.apps.find { |a| a["source_path"] == source_path }
assert app
dir_name = File.basename(source_path)
assert_equal app.root.join(Licensed::AppConfiguration::DEFAULT_CACHE_PATH, dir_name),
app.cache_path
assert_equal dir_name, app["name"]
end
end
it "assigns uniqueness to explicitly configured values" do
cache_path = ".test_licenses"
name = "test"
apps.clear
apps << {
"source_path" => File.expand_path("../fixtures/*", __FILE__),
"cache_path" => cache_path,
"name" => name
}
expected_source_paths = Dir.glob(apps[0]["source_path"]).select { |p| File.directory?(p) }
expected_source_paths.each do |source_path|
app = config.apps.find { |a| a["source_path"] == source_path }
assert app
dir_name = File.basename(source_path)
assert_equal app.root.join(cache_path, dir_name), app.cache_path
assert_equal "#{name}-#{dir_name}", app["name"]
end
end
it "does not assign unique cache paths if shared_cache is true" do
cache_path = ".test_licenses"
apps.clear
apps << {
"source_path" => File.expand_path("../fixtures/*", __FILE__),
"cache_path" => cache_path,
"shared_cache" => true
}
expected_source_paths = Dir.glob(apps[0]["source_path"]).select { |p| File.directory?(p) }
expected_source_paths.each do |source_path|
app = config.apps.find { |a| a["source_path"] == source_path }
assert app
assert_equal app.root.join(cache_path), app.cache_path
end
end
it "does not apply an inherited shared_cache setting to an app-configured cache path" do
cache_path = ".test_licenses"
apps.clear
apps << {
"source_path" => File.expand_path("../fixtures/*", __FILE__),
"cache_path" => cache_path
}
options["shared_cache"] = true
expected_source_paths = Dir.glob(apps[0]["source_path"]).select { |p| File.directory?(p) }
expected_source_paths.each do |source_path|
app = config.apps.find { |a| a["source_path"] == source_path }
assert app
dir_name = File.basename(source_path)
assert_equal app.root.join(cache_path, dir_name), app.cache_path
end
end
end
describe "with an array of source_paths" do
it "handles empty arrays" do
options["source_path"] = []
assert_equal 1, config.apps.count
assert_equal Licensed::AppConfiguration.root_for(options), config.apps.first.source_path.to_s
end
it "handles arrays with nil values" do
options["source_path"] = [
File.expand_path("../fixtures/bundler", __FILE__),
nil
]
assert_equal 1, config.apps.count
assert_equal File.expand_path("../fixtures/bundler", __FILE__), config.apps.first.source_path.to_s
end
it "handles absolute paths" do
options["source_path"] = [
File.expand_path("../fixtures/bundler", __FILE__),
File.expand_path("../fixtures/go", __FILE__)
]
options["source_path"].each do |source_path|
assert config.apps.find { |a| a.source_path.to_s == source_path }
end
end
it "handles paths relative to the application root directory" do
options["source_path"] = [
"test/fixtures/bundler",
"test/fixtures/go",
]
options["source_path"].each do |relative_path|
expected_source_path = File.join(Licensed::AppConfiguration.root_for(options), relative_path)
assert config.apps.find { |a| a.source_path.to_s == expected_source_path }
end
end
it "handles glob patterns" do
excluded_path = File.expand_path("../fixtures/bundler", __FILE__)
options["source_path"] = [
File.expand_path("../fixtures/*", __FILE__),
"!#{excluded_path}"
]
refute config.apps.find { |a| a.source_path.to_s == excluded_path }
assert config.apps.find { |a| a.source_path.to_s == File.expand_path("../fixtures/go", __FILE__) }
end
end
end
describe Licensed::AppConfiguration do
let(:options) { { "source_path" => Dir.pwd } }
let(:config) { Licensed::AppConfiguration.new(options) }
let(:fixtures) { File.expand_path("../fixtures/config", __FILE__) }
it "raises an error if source_path is not set" do
assert_raises ::Licensed::Configuration::LoadError do
Licensed::AppConfiguration.new
end
end
describe "ignore" do
let(:package) { { "type" => "go", "name" => "github.com/github/licensed/package" } }
it "marks the dependency as ignored" do
refute config.ignored?(package)
config.ignore package
assert config.ignored?(package)
end
describe "with glob patterns" do
it "does not match trailing ** to multiple path segments" do
refute config.ignored?(package)
config.ignore package.merge("name" => "github.com/github/**")
refute config.ignored?(package)
end
it "matches internal ** to multiple path segments" do
refute config.ignored?(package)
config.ignore package.merge("name" => "github.com/**/package")
assert config.ignored?(package)
end
it "matches trailing * to single path segment" do
refute config.ignored?(package)
config.ignore package.merge("name" => "github.com/github/licensed/*")
assert config.ignored?(package)
end
it "maches internal * to single path segment" do
refute config.ignored?(package)
config.ignore package.merge("name" => "github.com/*/licensed/package")
assert config.ignored?(package)
end
it "matches multiple globstars in a pattern" do
refute config.ignored?(package)
config.ignore package.merge("name" => "**/licensed/*")
assert config.ignored?(package)
end
it "does not match * to multiple path segments" do
refute config.ignored?(package)
config.ignore package.merge("name" => "github.com/github/*")
refute config.ignored?(package)
end
it "is case insensitive" do
refute config.ignored?(package)
config.ignore package.merge("name" => "GITHUB.com/github/**")
refute config.ignored?(package)
end
end
end
describe "review" do
let(:package) { { "type" => "go", "name" => "github.com/github/licensed/package" } }
it "marks the dependency as reviewed" do
refute config.reviewed?(package)
config.review package
assert config.reviewed?(package)
end
describe "with glob patterns" do
it "does not match trailing ** to multiple path segments" do
refute config.reviewed?(package)
config.review package.merge("name" => "github.com/github/**")
refute config.reviewed?(package)
end
it "matches internal ** to multiple path segments" do
refute config.reviewed?(package)
config.review package.merge("name" => "github.com/**/package")
assert config.reviewed?(package)
end
it "matches trailing * to single path segment" do
refute config.reviewed?(package)
config.review package.merge("name" => "github.com/github/licensed/*")
assert config.reviewed?(package)
end
it "maches internal * to single path segment" do
refute config.reviewed?(package)
config.review package.merge("name" => "github.com/*/licensed/package")
assert config.reviewed?(package)
end
it "matches multiple globstars in a pattern" do
refute config.reviewed?(package)
config.review package.merge("name" => "**/licensed/*")
assert config.reviewed?(package)
end
it "does not match * to multiple path segments" do
refute config.reviewed?(package)
config.review package.merge("name" => "github.com/github/*")
refute config.reviewed?(package)
end
it "is case insensitive" do
refute config.reviewed?(package)
config.review package.merge("name" => "GITHUB.com/github/**")
refute config.reviewed?(package)
end
end
describe "with version" do
it "sets the dependency reviewed at the specific version" do
config.review package
assert config.reviewed?(package)
package["version"] = "1.2.3"
assert config.reviewed?(package)
refute config.reviewed?(package, match_version: true)
config.review package, at_version: true
refute config.reviewed?(package.merge("version" => "1.0.0"), match_version: true)
assert config.reviewed?(package, match_version: true)
assert_equal ["#{package["name"]}@#{package["version"]}"], config.reviewed_versions(package)
end
it "reviewing dependencies at version will not match dependencies without version" do
package = { "type" => "bundler", "name" => "licensed", "version" => "1.0.0" }
config.review(package, at_version: true)
refute config.reviewed?(package, match_version: false)
end
it "matches glob patterns for specified versions" do
config.review({ "type" => "go", "name" => "github.com/github/**/*", "version" => "1.2.3" }, at_version: true)
assert_equal ["github.com/github/**/*@1.2.3"], config.reviewed_versions(package)
refute config.reviewed?(package.merge("version" => "1.0.0"), match_version: true)
assert config.reviewed?(package.merge("version" => "1.2.3"), match_version: true)
end
it "does not treat leading @ symbols as version separators when listing versions" do
package = { "type" => "npm", "name" => "@github/package" }
config.review(package)
assert_empty config.reviewed_versions(package)
config.review(package.merge("version" => "1.2.3"), at_version: true)
assert_equal ["@github/package@1.2.3"], config.reviewed_versions(package)
end
end
end
describe "allow" do
it "marks the license as allowed" do
refute config.allowed?("mit")
config.allow "mit"
assert config.allowed?("mit")
end
end
describe "enabled?" do
it "returns true if source type is enabled" do
config["sources"]["npm"] = true
assert config.enabled?("npm")
end
it "returns false if source type is disabled" do
config["sources"]["npm"] = false
refute config.enabled?("npm")
end
it "returns true if no source types are configured" do
Licensed::Sources::Source.sources.each do |source|
assert config.enabled?(source.type)
end
end
it "returns true for source types that are not disabled, if no sources are configured enabled" do
config["sources"]["npm"] = false
Licensed::Sources::Source.sources - [Licensed::Sources::NPM].each do |source_type|
assert config.enabled?(source_type)
end
end
it "returns false for source types that are not enabled, if any sources are configured enabled" do
config["sources"]["npm"] = true
Licensed::Sources::Source.sources - [Licensed::Sources::NPM].each do |source_type|
refute config.enabled?(source_type)
end
end
end
describe "root" do
it "can be set to a path from a configuration file" do
file = File.join(fixtures, "root.yml")
config = Licensed::Configuration.load_from(file).apps.first
assert_equal File.expand_path("../..", fixtures), config.root.to_s
end
it "can be set to true in a configuration file" do
file = File.join(fixtures, "root_at_configuration.yml")
config = Licensed::Configuration.load_from(file).apps.first
assert_equal fixtures, config.root.to_s
end
it "defaults to the git repository root" do
assert_equal Licensed::Git.repository_root, config.root.to_s
end
end
describe "name" do
it "raises an error if name.generator is not an allowed value" do
options["name"] = { "generator" => true }
options["source_path"] = "lib/licensed/sources"
error = assert_raises Licensed::Configuration::LoadError do
config
end
assert_includes error.message, "Invalid value configured for name.generator: true"
end
it "uses the source path directory name when a name value is not set" do
assert_equal "licensed", config["name"]
end
it "uses the source path directory name when name.generator is not set" do
options["name"] = {}
assert_equal "licensed", config["name"]
end
describe "with directory_name generator" do
it "uses the source path directory name" do
options["name"] = { "generator" => "directory_name" }
assert_equal "licensed", config["name"]
end
end
describe "with relative_path generator" do
it "generates a name from relative source path parts" do
options["name"] = { "generator" => "relative_path" }
options["source_path"] = "lib/licensed/sources"
assert_equal "lib-licensed-sources", config["name"]
end
it "uses a configured separator when creating a name from relative source path parts" do
options["name"] = { "generator" => "relative_path", "separator" => "." }
options["source_path"] = "lib/licensed/sources"
assert_equal "lib.licensed.sources", config["name"]
end
it "uses a configured path depth when creating a name from relative source path parts" do
options["name"] = { "generator" => "relative_path", "depth" => 2 }
options["source_path"] = "lib/licensed/sources"
assert_equal "licensed-sources", config["name"]
end
it "handles equivalent root and source paths" do
options["name"] = { "generator" => "relative_path" }
options["root"] = Licensed::Git.repository_root
options["source_path"] = Licensed::Git.repository_root
assert_equal config["name"], "licensed"
end
it "uses all path parts when depth is larger than the number of path parts" do
options["name"] = { "generator" => "relative_path", "depth" => 4 }
options["source_path"] = "lib/licensed/sources"
assert_equal "lib-licensed-sources", config["name"]
end
it "raises an error when generating a relative path name if source_path is not a descendant of the app root" do
options["name"] = { "generator" => "relative_path" }
options["root"] = Licensed::Git.repository_root
options["source_path"] = "/bad/test/path"
error = assert_raises Licensed::Configuration::LoadError do
config
end
assert_equal error.message,
"source_path must be a descendent of the app root to generate an app name from the relative source_path"
end
it "raises an error when the configuration value is less than 0" do
options["name"] = { "generator" => "relative_path", "depth" => -1 }
options["source_path"] = "lib/licensed/sources"
error = assert_raises Licensed::Configuration::LoadError do
config
end
assert_equal error.message,
"name.depth configuration value cannot be less than -1"
end
end
end
describe "cache_path" do
it "sets a default cache path with the app name if not configured" do
assert_equal config.root.join(Licensed::AppConfiguration::DEFAULT_CACHE_PATH, config["name"]),
config.cache_path
end
it "appends the app name to an inherited cache path" do
config = Licensed::AppConfiguration.new(
{ "source_path" => Dir.pwd },
{ "cache_path" => "vendor/cache" }
)
assert_equal config.root.join("vendor/cache", config["name"]), config.cache_path
end
it "does not append the app name to an explicit cache path" do
config = Licensed::AppConfiguration.new(
{ "source_path" => Dir.pwd, "cache_path" => "vendor/cache" }
)
assert_equal config.root.join("vendor/cache"), config.cache_path
refute config.cache_path.to_s.end_with? config["name"]
end
it "applies an inherited shared_cache setting to an inherited cache path" do
config = Licensed::AppConfiguration.new(
{ "source_path" => Dir.pwd },
{ "shared_cache" => true, "cache_path" => "vendor/cache" }
)
assert_equal config.root.join("vendor/cache"), config.cache_path
refute config.cache_path.to_s.end_with? config["name"]
end
it "does not apply an inherited shared_cache setting to the default cache path" do
config = Licensed::AppConfiguration.new(
{ "source_path" => Dir.pwd },
{ "shared_cache" => true }
)
assert_equal config.root.join(Licensed::AppConfiguration::DEFAULT_CACHE_PATH, config["name"]),
config.cache_path
end
end
end