Skip to content

Commit

Permalink
💚 Add build watcher spec
Browse files Browse the repository at this point in the history
  • Loading branch information
unhappychoice committed Jul 25, 2020
1 parent 6ed1ce4 commit 32715b9
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 7 deletions.
19 changes: 12 additions & 7 deletions lib/circleci/cli/command/watch_command/build_watcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class BuildWatcher
attr_reader :build

def initialize(build, verbose: false)
@client = Networking::CircleCIPusherClient.new.tap(&:connect)
@build = build
@verbose = verbose
@messages = Hash.new { |h, k| h[k] = [] }
Expand All @@ -19,30 +18,30 @@ def start
end

def stop(status)
@client.unsubscribe(@build.channel_name + '@0')
client.unsubscribe(@build.channel_name + '@0')
notify_stopped(status)
end

private

def bind_event_handling(channel) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@client.bind_event_json(channel, 'newAction') do |json|
client.bind_event_json(channel, 'newAction') do |json|
if @verbose
print_bordered json['log']['name']
else
print json['log']['name']
end
end

@client.bind_event_json(channel, 'appendAction') do |json|
client.bind_event_json(channel, 'appendAction') do |json|
if @verbose
Thor::Shell::Basic.new.say(json['out']['message'], nil, false)
else
@messages[json['step']] << json['out']['message']
end
end

@client.bind_event_json(channel, 'updateAction') do |json|
client.bind_event_json(channel, 'updateAction') do |json|
next if @verbose

case json['log']['status']
Expand All @@ -56,8 +55,10 @@ def bind_event_handling(channel) # rubocop:disable Metrics/AbcSize, Metrics/Meth
end

def notify_started
title = "👀 Start watching #{@build.project_name} ##{@build.build_number}"
say Printer::BuildPrinter.header_for(@build, title)
say Printer::BuildPrinter.header_for(
@build,
"👀 Start watching #{@build.project_name} ##{@build.build_number}"
)
end

def notify_stopped(status)
Expand All @@ -72,6 +73,10 @@ def notify_stopped(status)
def print_bordered(text)
say Terminal::Table.new(rows: [[text]], style: { width: 120 }).to_s
end

def client
@client ||= Networking::CircleCIPusherClient.new.tap(&:connect)
end
end
end
end
Expand Down
201 changes: 201 additions & 0 deletions spec/circleci/cli/command/watch_command/build_watcher_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# frozen_string_literal: true

require 'spec_helper'

describe CircleCI::CLI::Command::BuildWatcher do
let(:build) do
CircleCI::CLI::Response::Build.new(
{
'username' => 'unhappychoice',
'reponame' => 'default_reponame_from_api',
'status' => 'success',
'build_num' => 1234,
'branch' => 'master',
'author_name' => 'unhappychoice',
'subject' => 'Commit',
'build_time_millis' => 1000,
'start_time' => 100_000,
'steps' => [
{
'status' => 'success',
'actions' => [{ 'type' => 'build', 'name' => 'Build', 'status' => 'success', 'run_time_millis' => 1000 }]
},
{
'status' => 'success',
'actions' => [{ 'type' => 'test', 'name' => 'Test', 'status' => 'success', 'run_time_millis' => 1000 }]
}
]
}
)
end

describe '#start' do
subject { described_class.new(build, verbose: verbose).start }

before do
expect_any_instance_of(CircleCI::CLI::Networking::CircleCIPusherClient)
.to receive(:bind_event_json).with(build.channel_name, 'newAction')
expect_any_instance_of(CircleCI::CLI::Networking::CircleCIPusherClient)
.to receive(:bind_event_json).with(build.channel_name, 'appendAction')
expect_any_instance_of(CircleCI::CLI::Networking::CircleCIPusherClient)
.to receive(:bind_event_json).with(build.channel_name, 'updateAction')

expect_any_instance_of(described_class).to receive(:say).with(expected.strip)
end

context 'with verbose option' do
let(:verbose) { true }
let(:expected) do
<<~EXPECTED
+----------------------------------------------------------------------------------------------------------------------+
| 👀 Start watching unhappychoice/default_reponame_from_api #1234 |
+----------------------------------------------------------------------------------------------------------------------+
| Project: unhappychoice/default_reponame_from_api |
| Build: 1234 |
| Author: unhappychoice |
| Workflow: / |
+----------------------------------------------------------------------------------------------------------------------+
EXPECTED
end

it 'prints build information' do
subject
end
end

context 'without verbose option' do
let(:verbose) { false }
let(:expected) do
<<~EXPECTED
+----------------------------------------------------------------------------------------------------------------------+
| 👀 Start watching unhappychoice/default_reponame_from_api #1234 |
+----------------------------------------------------------------------------------------------------------------------+
| Project: unhappychoice/default_reponame_from_api |
| Build: 1234 |
| Author: unhappychoice |
| Workflow: / |
+----------------------------------------------------------------------------------------------------------------------+
EXPECTED
end

it 'prints build information' do
subject
end
end
end

describe '#stop' do
subject { described_class.new(build, verbose: verbose).stop(status) }

before do
expect_any_instance_of(CircleCI::CLI::Networking::CircleCIPusherClient)
.to receive(:unsubscribe).with(build.channel_name + '@0')
end

context 'with verbose option' do
let(:verbose) { true }

context 'when status is success' do
let(:status) { 'success' }

it 'prints message' do
expected = <<~EXPECTED
+----------------------------------------------------------------------------------------------------------------------+
| \e[0;32;49m🎉 unhappychoice/default_reponame_from_api #1234 has succeeded!\e[0m |
+----------------------------------------------------------------------------------------------------------------------+
EXPECTED
expect_any_instance_of(described_class).to receive(:say).with(expected.strip)

subject
end
end

context 'when status is failed' do
let(:status) { 'failed' }

it 'prints message' do
expected = <<~EXPECTED
+----------------------------------------------------------------------------------------------------------------------+
| \e[0;31;49m😥 unhappychoice/default_reponame_from_api #1234 has failed...\e[0m |
+----------------------------------------------------------------------------------------------------------------------+
EXPECTED
expect_any_instance_of(described_class).to receive(:say).with(expected.strip)

subject
end
end
end

context 'without verbose option' do
let(:verbose) { false }

context 'when status is success' do
let(:status) { 'success' }

it 'prints message' do
expect_any_instance_of(described_class)
.to receive(:say).with("\e[0;32;49m🎉 unhappychoice/default_reponame_from_api #1234 has succeeded!\e[0m")

subject
end
end

context 'when status is failed' do
let(:status) { 'failed' }

it 'prints message' do
expect_any_instance_of(described_class)
.to receive(:say).with("\e[0;31;49m😥 unhappychoice/default_reponame_from_api #1234 has failed...\e[0m")

subject
end
end
end
end

context 'with pusher events' do
subject { described_class.new(build, verbose: verbose).start }

let(:new_actions) { [{ 'log' => { 'name' => 'new action' } }] }
let(:append_actions) { [{ 'step' => 'step1', 'out' => { 'message' => 'append action' } }] }
let(:update_actions) { [{ 'step' => 'step1', 'log' => { 'status' => 'failed', 'name' => 'update action' } }] }

before do
allow_any_instance_of(described_class).to receive(:notify_started)

allow_any_instance_of(CircleCI::CLI::Networking::CircleCIPusherClient)
.to receive(:bind_event_json).with(build.channel_name, 'newAction').and_yield(*new_actions)
allow_any_instance_of(CircleCI::CLI::Networking::CircleCIPusherClient)
.to receive(:bind_event_json).with(build.channel_name, 'appendAction').and_yield(*append_actions)
allow_any_instance_of(CircleCI::CLI::Networking::CircleCIPusherClient)
.to receive(:bind_event_json).with(build.channel_name, 'updateAction').and_yield(*update_actions)
end

context 'with verbose option' do
let(:verbose) { true }

it 'prints log name' do
expected = <<~EXPECTED
+----------------------------------------------------------------------------------------------------------------------+
| new action |
+----------------------------------------------------------------------------------------------------------------------+
EXPECTED
allow_any_instance_of(described_class).to receive(:say).with(expected.strip)
allow_any_instance_of(Thor::Shell::Basic).to receive(:say).with('append action', nil, false)

subject
end
end

context 'without verbose option' do
let(:verbose) { false }

it 'prints log name' do
allow_any_instance_of(described_class).to receive(:print).with('new action')
allow_any_instance_of(described_class).to receive(:puts).with("\e[2K\r\e[0;31;49mupdate action\e[0m")
allow_any_instance_of(described_class).to receive(:say).with('append action')
subject
end
end
end
end

0 comments on commit 32715b9

Please sign in to comment.