spec/unit/command/shell_init_spec.rb in chef-dk-2.4.17 vs spec/unit/command/shell_init_spec.rb in chef-dk-2.5.3

- old
+ new

@@ -1,339 +1,339 @@ -# -# Copyright:: Copyright (c) 2014 Chef Software Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require "spec_helper" -require "chef-dk/command/shell_init" - -describe ChefDK::Command::ShellInit do - - let(:expected_path) { [omnibus_bin_dir, user_bin_dir, omnibus_embedded_bin_dir, ENV["PATH"], git_bin_dir].join(File::PATH_SEPARATOR) } - let(:stdout_io) { StringIO.new } - let(:stderr_io) { StringIO.new } - - let(:command_instance) do - ChefDK::Command::ShellInit.new.tap do |c| - allow(c).to receive(:stdout).and_return(stdout_io) - allow(c).to receive(:stderr).and_return(stderr_io) - end - end - - shared_context "shell init script" do |shell| - let(:user_bin_dir) { File.expand_path(File.join(Gem.user_dir, "bin")) } - let(:expected_gem_root) { Gem.default_dir.to_s } - let(:expected_gem_home) { Gem.user_dir } - let(:expected_gem_path) { Gem.path.join(File::PATH_SEPARATOR) } - - before do - allow(::Dir).to receive(:exists?).and_call_original - end - - context "with no explicit omnibus directory" do - - let(:omnibus_bin_dir) { "/foo/bin" } - let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } - let(:git_bin_dir) { "/foo/gitbin" } - let(:argv) { [shell] } - - before do - allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) - allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) - allow(command_instance).to receive(:git_bin_dir).and_return(git_bin_dir) - allow(::Dir).to receive(:exists?).with(git_bin_dir).and_return(true) - end - - it "emits a script to add ChefDK's ruby to the shell environment" do - command_instance.run(argv) - expect(stdout_io.string).to include(expected_environment_commands) - end - - it "does not emit any empty lines", :if => %w{powershell posh}.include?(shell) do - command_instance.run(argv) - stdout_io.string.each_line do |s| - expect(s.strip).not_to be_empty - end - end - end - - context "with an explicit omnibus directory as an argument" do - - let(:omnibus_root) { File.join(fixtures_path, "eg_omnibus_dir/valid/") } - let(:omnibus_bin_dir) { File.join(omnibus_root, "bin") } - let(:omnibus_embedded_bin_dir) { File.join(omnibus_root, "embedded/bin") } - let(:git_bin_dir) { File.join(omnibus_root, "gitbin") } - - let(:argv) { [shell, "--omnibus-dir", omnibus_root] } - - before do - allow(::Dir).to receive(:exists?).with(git_bin_dir).and_return(true) - end - - it "emits a script to add ChefDK's ruby to the shell environment" do - command_instance.run(argv) - expect(stdout_io.string).to include(expected_environment_commands) - end - - it "does not emit any empty lines", :if => %w{powershell posh}.include?(shell) do - command_instance.run(argv) - stdout_io.string.each_line do |s| - expect(s.strip).not_to be_empty - end - end - end - end - - shared_examples "a posix shell script" do |shell| - before do - stub_const("File::PATH_SEPARATOR", ":") - end - - let(:expected_environment_commands) do - <<-EOH -export PATH="#{expected_path}" -export GEM_ROOT="#{expected_gem_root}" -export GEM_HOME="#{expected_gem_home}" -export GEM_PATH="#{expected_gem_path}" -EOH - end - include_context "shell init script", shell - end - - shared_examples "a powershell script" do |shell| - before do - stub_const("File::PATH_SEPARATOR", ";") - end - - let(:expected_environment_commands) do - <<-EOH -$env:PATH="#{expected_path}" -$env:GEM_ROOT="#{expected_gem_root}" -$env:GEM_HOME="#{expected_gem_home}" -$env:GEM_PATH="#{expected_gem_path}" -EOH - end - include_context "shell init script", shell - end - - context "for sh" do - it_behaves_like "a posix shell script", "sh" - end - - context "for bash" do - it_behaves_like "a posix shell script", "bash" - - describe "generating auto-complete" do - - let(:command_descriptions) do - { - "exec" => "Runs the command in context of the embedded ruby", - "env" => "Prints environment variables used by ChefDK", - "gem" => "Runs the `gem` command in context of the embedded ruby", - "generate" => "Generate a new app, cookbook, or component", - } - end - - let(:omnibus_bin_dir) { "/foo/bin" } - let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } - - let(:argv) { [ "bash" ] } - - let(:expected_completion_function) do - <<-END_COMPLETION -_chef_comp() { - local COMMANDS="exec env gem generate" - COMPREPLY=($(compgen -W "$COMMANDS" -- ${COMP_WORDS[COMP_CWORD]} )) -} -complete -F _chef_comp chef -END_COMPLETION - end - - before do - # Stub this or else we'd have to update the test every time a new command - # is added. - allow(command_instance.shell_completion_template_context).to receive(:commands). - and_return(command_descriptions) - - allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) - allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) - end - - it "generates a completion function for the chef command" do - command_instance.run(argv) - expect(stdout_io.string).to include(expected_completion_function) - end - - end - end - - context "for zsh" do - - it_behaves_like "a posix shell script", "zsh" - - describe "generating auto-complete" do - - let(:command_descriptions) do - { - "exec" => "Runs the command in context of the embedded ruby", - "env" => "Prints environment variables used by ChefDK", - "gem" => "Runs the `gem` command in context of the embedded ruby", - "generate" => "Generate a new app, cookbook, or component", - } - end - - let(:omnibus_bin_dir) { "/foo/bin" } - let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } - - let(:argv) { [ "zsh" ] } - - let(:expected_completion_function) do - <<-END_COMPLETION -function _chef() { - - local -a _1st_arguments - _1st_arguments=( - 'exec:Runs the command in context of the embedded ruby' - 'env:Prints environment variables used by ChefDK' - 'gem:Runs the `gem` command in context of the embedded ruby' - 'generate:Generate a new app, cookbook, or component' - ) - - _arguments \\ - '(-v --version)'{-v,--version}'[version information]' \\ - '*:: :->subcmds' && return 0 - - if (( CURRENT == 1 )); then - _describe -t commands "chef subcommand" _1st_arguments - return - fi -} - -compdef _chef chef - - END_COMPLETION - end - - before do - # Stub this or else we'd have to update the test every time a new command - # is added. - allow(command_instance.shell_completion_template_context).to receive(:commands). - and_return(command_descriptions) - - allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) - allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) - end - - it "generates a completion function for the chef command" do - command_instance.run(argv) - expect(stdout_io.string).to include(expected_completion_function) - end - end - end - - context "for fish" do - before do - stub_const("File::PATH_SEPARATOR", ":") - end - let(:expected_path) { [omnibus_bin_dir, user_bin_dir, omnibus_embedded_bin_dir, ENV["PATH"], git_bin_dir].join(":").split(":").join('" "') } - let(:expected_environment_commands) do - <<-EOH -set -gx PATH "#{expected_path}" 2>/dev/null; -set -gx GEM_ROOT "#{expected_gem_root}"; -set -gx GEM_HOME "#{expected_gem_home}"; -set -gx GEM_PATH "#{expected_gem_path}"; -EOH - end - - include_context "shell init script", "fish" - - describe "generating auto-complete" do - - let(:command_descriptions) do - { - "exec" => "Runs the command in context of the embedded ruby", - "env" => "Prints environment variables used by ChefDK", - "gem" => "Runs the `gem` command in context of the embedded ruby", - "generate" => "Generate a new app, cookbook, or component", - } - end - - let(:omnibus_bin_dir) { "/foo/bin" } - let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } - - let(:argv) { [ "fish" ] } - - let(:expected_completion_function) do - <<-END_COMPLETION -# Fish Shell command-line completions for ChefDK - -function __fish_chef_no_command --description 'Test if chef has yet to be given the main command' - set -l cmd (commandline -opc) - test (count $cmd) -eq 1 -end - -complete -c chef -f -n '__fish_chef_no_command' -a exec -d "Runs the command in context of the embedded ruby" -complete -c chef -f -n '__fish_chef_no_command' -a env -d "Prints environment variables used by ChefDK" -complete -c chef -f -n '__fish_chef_no_command' -a gem -d "Runs the `gem` command in context of the embedded ruby" -complete -c chef -f -n '__fish_chef_no_command' -a generate -d "Generate a new app, cookbook, or component" -END_COMPLETION - end - - before do - # Stub this or else we'd have to update the test every time a new command - # is added. - allow(command_instance.shell_completion_template_context).to receive(:commands). - and_return(command_descriptions) - - allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) - allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) - end - - it "generates a completion function for the chef command" do - command_instance.run(argv) - expect(stdout_io.string).to include(expected_completion_function) - end - end - end - - %w{powershell posh}.each do |shell| - context "for #{shell}" do - it_behaves_like "a powershell script", shell - end - end - - context "when no shell is specified" do - - let(:argv) { [] } - - it "exits with an error message" do - expect(command_instance.run(argv)).to eq(1) - expect(stderr_io.string).to include("Please specify what shell you are using") - end - - end - - context "when an unsupported shell is specified" do - - let(:argv) { ["nosuchsh"] } - - it "exits with an error message" do - expect(command_instance.run(argv)).to eq(1) - expect(stderr_io.string).to include("Shell `nosuchsh' is not currently supported") - expect(stderr_io.string).to include("Supported shells are: bash fish zsh sh powershell posh") - end - - end - -end +# +# Copyright:: Copyright (c) 2014 Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "spec_helper" +require "chef-dk/command/shell_init" + +describe ChefDK::Command::ShellInit do + + let(:expected_path) { [omnibus_bin_dir, user_bin_dir, omnibus_embedded_bin_dir, ENV["PATH"], git_bin_dir].join(File::PATH_SEPARATOR) } + let(:stdout_io) { StringIO.new } + let(:stderr_io) { StringIO.new } + + let(:command_instance) do + ChefDK::Command::ShellInit.new.tap do |c| + allow(c).to receive(:stdout).and_return(stdout_io) + allow(c).to receive(:stderr).and_return(stderr_io) + end + end + + shared_context "shell init script" do |shell| + let(:user_bin_dir) { File.expand_path(File.join(Gem.user_dir, "bin")) } + let(:expected_gem_root) { Gem.default_dir.to_s } + let(:expected_gem_home) { Gem.user_dir } + let(:expected_gem_path) { Gem.path.join(File::PATH_SEPARATOR) } + + before do + allow(::Dir).to receive(:exists?).and_call_original + end + + context "with no explicit omnibus directory" do + + let(:omnibus_bin_dir) { "/foo/bin" } + let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } + let(:git_bin_dir) { "/foo/gitbin" } + let(:argv) { [shell] } + + before do + allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) + allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) + allow(command_instance).to receive(:git_bin_dir).and_return(git_bin_dir) + allow(::Dir).to receive(:exists?).with(git_bin_dir).and_return(true) + end + + it "emits a script to add ChefDK's ruby to the shell environment" do + command_instance.run(argv) + expect(stdout_io.string).to include(expected_environment_commands) + end + + it "does not emit any empty lines", :if => %w{powershell posh}.include?(shell) do + command_instance.run(argv) + stdout_io.string.each_line do |s| + expect(s.strip).not_to be_empty + end + end + end + + context "with an explicit omnibus directory as an argument" do + + let(:omnibus_root) { File.join(fixtures_path, "eg_omnibus_dir/valid/") } + let(:omnibus_bin_dir) { File.join(omnibus_root, "bin") } + let(:omnibus_embedded_bin_dir) { File.join(omnibus_root, "embedded/bin") } + let(:git_bin_dir) { File.join(omnibus_root, "gitbin") } + + let(:argv) { [shell, "--omnibus-dir", omnibus_root] } + + before do + allow(::Dir).to receive(:exists?).with(git_bin_dir).and_return(true) + end + + it "emits a script to add ChefDK's ruby to the shell environment" do + command_instance.run(argv) + expect(stdout_io.string).to include(expected_environment_commands) + end + + it "does not emit any empty lines", :if => %w{powershell posh}.include?(shell) do + command_instance.run(argv) + stdout_io.string.each_line do |s| + expect(s.strip).not_to be_empty + end + end + end + end + + shared_examples "a posix shell script" do |shell| + before do + stub_const("File::PATH_SEPARATOR", ":") + end + + let(:expected_environment_commands) do + <<-EOH +export PATH="#{expected_path}" +export GEM_ROOT="#{expected_gem_root}" +export GEM_HOME="#{expected_gem_home}" +export GEM_PATH="#{expected_gem_path}" +EOH + end + include_context "shell init script", shell + end + + shared_examples "a powershell script" do |shell| + before do + stub_const("File::PATH_SEPARATOR", ";") + end + + let(:expected_environment_commands) do + <<-EOH +$env:PATH="#{expected_path}" +$env:GEM_ROOT="#{expected_gem_root}" +$env:GEM_HOME="#{expected_gem_home}" +$env:GEM_PATH="#{expected_gem_path}" +EOH + end + include_context "shell init script", shell + end + + context "for sh" do + it_behaves_like "a posix shell script", "sh" + end + + context "for bash" do + it_behaves_like "a posix shell script", "bash" + + describe "generating auto-complete" do + + let(:command_descriptions) do + { + "exec" => "Runs the command in context of the embedded ruby", + "env" => "Prints environment variables used by ChefDK", + "gem" => "Runs the `gem` command in context of the embedded ruby", + "generate" => "Generate a new app, cookbook, or component", + } + end + + let(:omnibus_bin_dir) { "/foo/bin" } + let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } + + let(:argv) { [ "bash" ] } + + let(:expected_completion_function) do + <<-END_COMPLETION +_chef_comp() { + local COMMANDS="exec env gem generate" + COMPREPLY=($(compgen -W "$COMMANDS" -- ${COMP_WORDS[COMP_CWORD]} )) +} +complete -F _chef_comp chef +END_COMPLETION + end + + before do + # Stub this or else we'd have to update the test every time a new command + # is added. + allow(command_instance.shell_completion_template_context).to receive(:commands). + and_return(command_descriptions) + + allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) + allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) + end + + it "generates a completion function for the chef command" do + command_instance.run(argv) + expect(stdout_io.string).to include(expected_completion_function) + end + + end + end + + context "for zsh" do + + it_behaves_like "a posix shell script", "zsh" + + describe "generating auto-complete" do + + let(:command_descriptions) do + { + "exec" => "Runs the command in context of the embedded ruby", + "env" => "Prints environment variables used by ChefDK", + "gem" => "Runs the `gem` command in context of the embedded ruby", + "generate" => "Generate a new app, cookbook, or component", + } + end + + let(:omnibus_bin_dir) { "/foo/bin" } + let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } + + let(:argv) { [ "zsh" ] } + + let(:expected_completion_function) do + <<-END_COMPLETION +function _chef() { + + local -a _1st_arguments + _1st_arguments=( + 'exec:Runs the command in context of the embedded ruby' + 'env:Prints environment variables used by ChefDK' + 'gem:Runs the `gem` command in context of the embedded ruby' + 'generate:Generate a new app, cookbook, or component' + ) + + _arguments \\ + '(-v --version)'{-v,--version}'[version information]' \\ + '*:: :->subcmds' && return 0 + + if (( CURRENT == 1 )); then + _describe -t commands "chef subcommand" _1st_arguments + return + fi +} + +compdef _chef chef + + END_COMPLETION + end + + before do + # Stub this or else we'd have to update the test every time a new command + # is added. + allow(command_instance.shell_completion_template_context).to receive(:commands). + and_return(command_descriptions) + + allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) + allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) + end + + it "generates a completion function for the chef command" do + command_instance.run(argv) + expect(stdout_io.string).to include(expected_completion_function) + end + end + end + + context "for fish" do + before do + stub_const("File::PATH_SEPARATOR", ":") + end + let(:expected_path) { [omnibus_bin_dir, user_bin_dir, omnibus_embedded_bin_dir, ENV["PATH"], git_bin_dir].join(":").split(":").join('" "') } + let(:expected_environment_commands) do + <<-EOH +set -gx PATH "#{expected_path}" 2>/dev/null; +set -gx GEM_ROOT "#{expected_gem_root}"; +set -gx GEM_HOME "#{expected_gem_home}"; +set -gx GEM_PATH "#{expected_gem_path}"; +EOH + end + + include_context "shell init script", "fish" + + describe "generating auto-complete" do + + let(:command_descriptions) do + { + "exec" => "Runs the command in context of the embedded ruby", + "env" => "Prints environment variables used by ChefDK", + "gem" => "Runs the `gem` command in context of the embedded ruby", + "generate" => "Generate a new app, cookbook, or component", + } + end + + let(:omnibus_bin_dir) { "/foo/bin" } + let(:omnibus_embedded_bin_dir) { "/foo/embedded/bin" } + + let(:argv) { [ "fish" ] } + + let(:expected_completion_function) do + <<-END_COMPLETION +# Fish Shell command-line completions for ChefDK + +function __fish_chef_no_command --description 'Test if chef has yet to be given the main command' + set -l cmd (commandline -opc) + test (count $cmd) -eq 1 +end + +complete -c chef -f -n '__fish_chef_no_command' -a exec -d "Runs the command in context of the embedded ruby" +complete -c chef -f -n '__fish_chef_no_command' -a env -d "Prints environment variables used by ChefDK" +complete -c chef -f -n '__fish_chef_no_command' -a gem -d "Runs the `gem` command in context of the embedded ruby" +complete -c chef -f -n '__fish_chef_no_command' -a generate -d "Generate a new app, cookbook, or component" +END_COMPLETION + end + + before do + # Stub this or else we'd have to update the test every time a new command + # is added. + allow(command_instance.shell_completion_template_context).to receive(:commands). + and_return(command_descriptions) + + allow(command_instance).to receive(:omnibus_embedded_bin_dir).and_return(omnibus_embedded_bin_dir) + allow(command_instance).to receive(:omnibus_bin_dir).and_return(omnibus_bin_dir) + end + + it "generates a completion function for the chef command" do + command_instance.run(argv) + expect(stdout_io.string).to include(expected_completion_function) + end + end + end + + %w{powershell posh}.each do |shell| + context "for #{shell}" do + it_behaves_like "a powershell script", shell + end + end + + context "when no shell is specified" do + + let(:argv) { [] } + + it "exits with an error message" do + expect(command_instance.run(argv)).to eq(1) + expect(stderr_io.string).to include("Please specify what shell you are using") + end + + end + + context "when an unsupported shell is specified" do + + let(:argv) { ["nosuchsh"] } + + it "exits with an error message" do + expect(command_instance.run(argv)).to eq(1) + expect(stderr_io.string).to include("Shell `nosuchsh' is not currently supported") + expect(stderr_io.string).to include("Supported shells are: bash fish zsh sh powershell posh") + end + + end + +end