1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
# frozen_string_literal: true
require 'spec_helper'
require 'tty/prompt/test'
require_relative '../../../scripts/internal_events/cli'
# See spec/support/shared_contexts/internal_events_cli_shared_context.rb for debugging tips
RSpec.describe Cli, feature_category: :service_ping do
include_context 'when running the Internal Events Cli'
let_it_be(:event1_filepath) { 'config/events/internal_events_cli_used.yml' }
let_it_be(:event1_content) { internal_event_fixture('events/event_with_identifiers.yml') }
let_it_be(:event2_filepath) { 'ee/config/events/internal_events_cli_opened.yml' }
let_it_be(:event2_content) { internal_event_fixture('events/ee_event_without_identifiers.yml') }
let_it_be(:event3_filepath) { 'config/events/internal_events_cli_closed.yml' }
let_it_be(:event3_content) { internal_event_fixture('events/secondary_event_with_identifiers.yml') }
shared_examples 'definition fixtures are valid' do |directory, schema_path|
let(:schema) { ::JSONSchemer.schema(Pathname(schema_path)) }
# The generator can return an invalid definition if the user skips the MR link
let(:expected_errors) { a_hash_including('data_pointer' => '/introduced_by_url', 'data' => 'TODO') }
it "for #{directory}", :aggregate_failures do
Dir[Rails.root.join('spec', 'fixtures', 'scripts', 'internal_events', directory, '*.yml')].each do |filepath|
attributes = YAML.safe_load(File.read(filepath))
errors = schema.validate(attributes).to_a
error_message = <<~TEXT
Unexpected validation errors in: #{filepath}
#{errors.map { |e| JSONSchemer::Errors.pretty(e) }.join("\n")}
TEXT
if attributes['introduced_by_url'] == 'TODO'
expect(errors).to contain_exactly(expected_errors), error_message
else
expect(errors).to be_empty, error_message
end
end
end
end
it_behaves_like 'definition fixtures are valid', 'events', 'config/events/schema.json'
it_behaves_like 'definition fixtures are valid', 'metrics', 'config/metrics/schema/base.json'
context 'when offline' do
before do
stub_product_groups(nil)
end
it_behaves_like 'creates the right definition files',
'Creates a new event with product stage/section/group input manually' do
let(:keystrokes) do
[
"1\n", # Enum-select: New Event -- start tracking when an action or scenario occurs on gitlab instances
"Internal Event CLI is opened\n", # Submit description
"internal_events_cli_opened\n", # Submit action name
"7\n", # Select: None
"\n", # Select: None! Continue to next section!
"\n", # Skip MR URL
"analytics_instrumentation\n", # Input group
"2\n", # Select [premium, ultimate]
"y\n", # Create file
"4\n" # Exit
]
end
let(:output_files) { [{ 'path' => event2_filepath, 'content' => event2_content }] }
end
it_behaves_like 'creates the right definition files',
'Creates a new metric with product stage/section/group input manually' do
let(:keystrokes) do
[
"2\n", # Enum-select: New Metric -- calculate how often one or more existing events occur over time
"2\n", # Enum-select: Multiple events -- count occurrences of several separate events or interactions
'internal_events_cli', # Filters to the relevant events
' ', # Multi-select: internal_events_cli_closed
"\e[B", # Arrow down to: internal_events_cli_used
' ', # Multi-select: internal_events_cli_used
"\n", # Submit selections
"\e[B", # Arrow down to: Weekly count of unique projects
"\n", # Select: Weekly count of unique projects
"where a defition file was created with the CLI\n", # Input description
"\n", # Submit weekly description for monthly
"2\n", # Select: Modify attributes
"\n", # Accept group
"\n", # Skip URL
"1\n", # Select: [free, premium, ultimate]
"y\n", # Create file
"y\n", # Create file
"5\n" # Exit
]
end
let(:input_files) do
[
{ 'path' => event1_filepath, 'content' => event1_content },
{ 'path' => event3_filepath, 'content' => event3_content }
]
end
let(:output_files) do
# rubocop:disable Layout/LineLength -- Long filepaths read better unbroken
[{
'path' => 'config/metrics/counts_28d/count_distinct_project_id_from_internal_events_cli_closed_and_internal_events_cli_used_monthly.yml',
'content' => 'spec/fixtures/scripts/internal_events/metrics/project_id_28d_multiple_events.yml'
}, {
'path' => 'config/metrics/counts_7d/count_distinct_project_id_from_internal_events_cli_closed_and_internal_events_cli_used_weekly.yml',
'content' => 'spec/fixtures/scripts/internal_events/metrics/project_id_7d_multiple_events.yml'
}]
# rubocop:enable Layout/LineLength
end
end
end
context 'when window size is unavailable' do
before do
# `tput <cmd>` returns empty string on error
stub_helper(:fetch_window_size, '')
stub_helper(:fetch_window_height, '')
end
it_behaves_like 'creates the right definition files',
'Terminal size does not prevent file creation' do
let(:keystrokes) do
[
"1\n", # Enum-select: New Event -- start tracking when an action or scenario occurs on gitlab instances
"Internal Event CLI is opened\n", # Submit description
"internal_events_cli_opened\n", # Submit action name
"7\n", # Select: None
"\n", # Select: None! Continue to next section!
"\n", # Skip MR URL
"instrumentation\n", # Filter & select group
"2\n", # Select [premium, ultimate]
"y\n", # Create file
"4\n" # Exit
]
end
let(:output_files) { [{ 'path' => event2_filepath, 'content' => event2_content }] }
end
end
end
|