tane 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +14 -0
- data/README.md +22 -0
- data/Rakefile +10 -0
- data/bin/tane +18 -0
- data/lib/tane.rb +64 -0
- data/lib/tane/commands/app.rb +5 -0
- data/lib/tane/commands/base.rb +15 -0
- data/lib/tane/commands/claim.rb +26 -0
- data/lib/tane/commands/create.rb +46 -0
- data/lib/tane/commands/email.rb +50 -0
- data/lib/tane/commands/event.rb +21 -0
- data/lib/tane/commands/exec.rb +37 -0
- data/lib/tane/commands/help.rb +33 -0
- data/lib/tane/commands/init.rb +25 -0
- data/lib/tane/commands/login.rb +91 -0
- data/lib/tane/commands/logout.rb +25 -0
- data/lib/tane/commands/refresh.rb +26 -0
- data/lib/tane/commands/signup.rb +43 -0
- data/lib/tane/commands/support.rb +37 -0
- data/lib/tane/helpers.rb +168 -0
- data/lib/tane/helpers/bushido_helper.rb +50 -0
- data/lib/tane/helpers/init_helper.rb +116 -0
- data/lib/tane/parser.rb +52 -0
- data/lib/tane/version.rb +3 -0
- data/spec/commands/base_spec.rb +26 -0
- data/spec/commands/claim_spec.rb +31 -0
- data/spec/commands/email_spec.rb +71 -0
- data/spec/commands/event_spec.rb +20 -0
- data/spec/commands/exec_spec.rb +18 -0
- data/spec/commands/help_spec.rb +12 -0
- data/spec/commands/init_spec.rb +27 -0
- data/spec/commands/login_spec.rb +81 -0
- data/spec/commands/support_spec.rb +59 -0
- data/spec/executable_spec.rb +11 -0
- data/spec/fixtures/credentials.yml +2 -0
- data/spec/helpers/bushido_helper_spec.rb +87 -0
- data/spec/helpers/init_helper_spec.rb +127 -0
- data/spec/helpers_spec.rb +223 -0
- data/spec/spec_helper.rb +15 -0
- data/tane.gemspec +29 -0
- data/tasks/spec.rake +10 -0
- data/tasks/tane.rake +11 -0
- metadata +188 -0
data/lib/tane/parser.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Tane
|
2
|
+
class Parser
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def global_options
|
6
|
+
@global_options ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def global_option(name, *args)
|
10
|
+
self.global_options << {:name => name, :args => args}
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse(args)
|
14
|
+
# The options specified on the command line will be collected in *options*.
|
15
|
+
# We set default values here.
|
16
|
+
options = OpenStruct.new
|
17
|
+
options.scheme = "http"
|
18
|
+
options.host = "localhost"
|
19
|
+
options.port = 3000
|
20
|
+
options.inplace = false
|
21
|
+
options.encoding = "utf8"
|
22
|
+
options.transfer_type = :auto
|
23
|
+
options.verbose = false
|
24
|
+
|
25
|
+
global_option :port, '-p', '--port PORT', Integer, "The port your local Bushido app is running on"
|
26
|
+
global_option :host, '-n', '--host HOST', String, "The hostname where your local Bushido app is running"
|
27
|
+
global_option :scheme, '-s', '--scheme SCHEME', String, "Either http or https, whichever protocol your local Bushido app is using"
|
28
|
+
global_option :verbose, '-V', '--verbose', "Output a lot of noise"
|
29
|
+
|
30
|
+
opts = OptionParser.new do |opts|
|
31
|
+
banner = "Usage: tane command [options]\n"
|
32
|
+
banner += Tane::Commands.command_list_and_help
|
33
|
+
|
34
|
+
opts.banner = banner
|
35
|
+
|
36
|
+
opts.separator ""
|
37
|
+
opts.separator "Specific options:"
|
38
|
+
|
39
|
+
# Mandatory argument.
|
40
|
+
global_options.each do |option|
|
41
|
+
opts.on(option[:name].to_s, *option[:args]) do |value|
|
42
|
+
options.send("#{option[:name]}=", value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
options.send("help_text=", opts.help())
|
46
|
+
opts.parse!(args)
|
47
|
+
return options
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/tane/version.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Base do
|
4
|
+
it "should include Tane::Helpers" do
|
5
|
+
Tane::Commands::Base.include?(Tane::Helpers).should be_true
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".fire" do
|
9
|
+
before :each do
|
10
|
+
@opts = {:foo => "bar"}
|
11
|
+
@args = ["foo", "bar"]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should process the arguments passed" do
|
15
|
+
Tane::Commands::Base.should_receive(:process).with(@args)
|
16
|
+
Tane::Commands::Base.fire(@opts, @args)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should set the options" do
|
20
|
+
Tane::Commands::Base.should_receive(:process).with(@args)
|
21
|
+
Tane::Commands::Base.fire(@opts, @args)
|
22
|
+
|
23
|
+
Tane::Commands::Base.instance_variable_get("@opts").should == @opts
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Claim do
|
4
|
+
|
5
|
+
describe ".process" do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@args = ["valid_email", "valid_ido_id"]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should notify the local app about an App.claimed event" do
|
12
|
+
Time.should_receive(:now).at_least(1).and_return("valid_time")
|
13
|
+
|
14
|
+
event = {
|
15
|
+
'category' => 'app',
|
16
|
+
'event' => 'claimed',
|
17
|
+
'data' => {
|
18
|
+
'time' => Time.now,
|
19
|
+
'ido_id' => @args.last,
|
20
|
+
'email' => @args.first
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
Tane::Commands::Claim.should_receive(:post).
|
25
|
+
with(Tane::Commands::Claim.data_url, event)
|
26
|
+
|
27
|
+
Tane::Commands::Claim.process(@args)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Email do
|
4
|
+
|
5
|
+
describe ".process" do
|
6
|
+
it "should send email if command is 'tane email template_name'" do
|
7
|
+
args = ["valid_template"]
|
8
|
+
Tane::Commands::Email.should_receive(:send_email).with("valid_template")
|
9
|
+
|
10
|
+
Tane::Commands::Email.process(args)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should list email if commad is 'tane email'" do
|
14
|
+
args = []
|
15
|
+
Tane::Commands::Email.should_receive(:list_email_templates)
|
16
|
+
|
17
|
+
Tane::Commands::Email.process(args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ".send_email" do
|
22
|
+
|
23
|
+
describe "if email template is not available" do
|
24
|
+
it "should display a message and exit " do
|
25
|
+
Tane::Commands::Email.should_receive(:render_email).and_return(nil)
|
26
|
+
Tane::Commands::Email.term.should_receive(:say).at_least(1)
|
27
|
+
|
28
|
+
expect {
|
29
|
+
Tane::Commands::Email.send_email('invalid_email_template')
|
30
|
+
}.to raise_error(SystemExit)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should list available email templates" do
|
34
|
+
Tane::Commands::Email.should_receive(:render_email).and_return(nil)
|
35
|
+
Tane::Commands::Email.term.should_receive(:say).at_least(1)
|
36
|
+
Tane::Commands::Email.should_receive(:list_email_templates)
|
37
|
+
|
38
|
+
expect {
|
39
|
+
Tane::Commands::Email.send_email('invalid_email_template')
|
40
|
+
}.to raise_error(SystemExit)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should post to mail url of the local app if email template is available" do
|
45
|
+
email_template_name = "valid_email_template_name"
|
46
|
+
email_template = "valid_email_template"
|
47
|
+
bushido_mail_url = Tane::Commands::Email.mail_url
|
48
|
+
|
49
|
+
Tane::Commands::Email.should_receive(:render_email)
|
50
|
+
.with(email_template_name)
|
51
|
+
.and_return(email_template)
|
52
|
+
|
53
|
+
Tane::Commands::Email.should_receive(:post)
|
54
|
+
.with(bushido_mail_url, email_template)
|
55
|
+
|
56
|
+
Tane::Commands::Email.send_email(email_template_name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe ".render_email" do
|
61
|
+
it "should load the email template specified" do
|
62
|
+
valid_email_template_name = "valid_email_template"
|
63
|
+
File.should_receive(:read).
|
64
|
+
with(Tane::Commands::Email.email_template_file_path(valid_email_template_name)).
|
65
|
+
and_return("valid_email_template: this is a dummy template")
|
66
|
+
|
67
|
+
Tane::Commands::Email.render_email(valid_email_template_name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Event do
|
4
|
+
|
5
|
+
describe ".process" do
|
6
|
+
it "should post data to the local apps /bushido/data with the event" do
|
7
|
+
args = ["Test", "received", "{'foo' => 'bar'}"]
|
8
|
+
event = {
|
9
|
+
'category' => args.first,
|
10
|
+
'event' => args[1],
|
11
|
+
'data' => eval(args[2])
|
12
|
+
}
|
13
|
+
|
14
|
+
Tane::Commands::Event.should_receive(:post).
|
15
|
+
with(Tane::Commands::Event.data_url, event)
|
16
|
+
|
17
|
+
Tane::Commands::Event.process(args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Exec do
|
4
|
+
|
5
|
+
describe ".process" do
|
6
|
+
it "should call exec to replace the current process with the arguments passed" do
|
7
|
+
args = ['foo', 'bar']
|
8
|
+
|
9
|
+
Tane::Commands::Exec.should_receive(:authenticate_user).and_return(true)
|
10
|
+
Tane::Commands::Exec.should_receive(:bushido_envs).
|
11
|
+
and_return({})
|
12
|
+
|
13
|
+
Tane::Commands::Exec.should_receive(:exec).with(args.join(' '))
|
14
|
+
Tane::Commands::Exec.process(args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Help do
|
4
|
+
|
5
|
+
describe ".process" do
|
6
|
+
it "should display the OptParse's help section's banner" do
|
7
|
+
Tane::Commands::Help.opts.should_receive(:help_text)
|
8
|
+
Tane::Commands::Help.process([])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Init do
|
4
|
+
|
5
|
+
describe ".process" do
|
6
|
+
it "should initialize an app if it's a rails project" do
|
7
|
+
Tane::Commands::Init.should_receive(:authenticate_user).and_return(true)
|
8
|
+
Tane::Commands::Init.should_receive(:in_rails_dir?).and_return(true)
|
9
|
+
Tane::Helpers::Init.should_receive(:initialize_app)
|
10
|
+
|
11
|
+
Tane::Commands::Init.process([])
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should display a message and exit if the current dir isn't a rails project" do
|
15
|
+
Tane::Commands::Init.should_receive(:authenticate_user).and_return(true)
|
16
|
+
Tane::Commands::Init.should_receive(:in_rails_dir?).
|
17
|
+
and_return(false)
|
18
|
+
|
19
|
+
Tane::Commands::Init.term.should_receive(:say)
|
20
|
+
|
21
|
+
expect {
|
22
|
+
Tane::Commands::Init.process([])
|
23
|
+
}.to raise_error(SystemExit)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Login do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@valid_email = "valid_email"
|
7
|
+
@valid_password = "valid_password"
|
8
|
+
@valid_auth_token = "valid_auth_token"
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".process" do
|
12
|
+
it "should save credentials if they are valid" do
|
13
|
+
Tane::Commands::Login.
|
14
|
+
should_receive(:warn_if_credentials_and_prompt).
|
15
|
+
and_return([@valid_email, @valid_password])
|
16
|
+
|
17
|
+
Tane::Commands::Login.should_receive(:verify_or_signup).
|
18
|
+
with(@valid_email, @valid_password).
|
19
|
+
and_return([@valid_auth_token, nil])
|
20
|
+
|
21
|
+
Tane::Commands::Login.should_receive(:save_credentials)
|
22
|
+
|
23
|
+
Tane::Commands::Login.process([])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
describe ".verify_or_signup" do
|
29
|
+
it "should return the auth_token if the credentials are valid" do
|
30
|
+
Tane::Helpers::Bushido.should_receive(:verify_credentials).
|
31
|
+
and_return([@valid_auth_token, nil])
|
32
|
+
Tane::Commands::Login.verify_or_signup(@valid_email, @valid_password).should == @valid_auth_token
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should prompt for signup if the credentials are not valid" do
|
36
|
+
Tane::Helpers::Bushido.should_receive(:verify_credentials).
|
37
|
+
and_return([nil, "foobar errors"])
|
38
|
+
Tane::Commands::Login.should_receive(:signup_and_notify)
|
39
|
+
Tane::Commands::Login.term.should_receive(:agree).and_return(true)
|
40
|
+
|
41
|
+
Tane::Commands::Login.verify_or_signup(@valid_email, @valid_password)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should display error messages and exit if user says no to signup" do
|
45
|
+
Tane::Helpers::Bushido.should_receive(:verify_credentials).
|
46
|
+
and_return([nil, "foobar errors"])
|
47
|
+
Tane::Commands::Login.term.should_receive(:agree).and_return(false)
|
48
|
+
|
49
|
+
expect {
|
50
|
+
Tane::Commands::Login.verify_or_signup(@valid_email, @valid_password)
|
51
|
+
}.to raise_error(SystemExit)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
describe ".display_errors_and_exit" do
|
57
|
+
it "should display errors passed to it and exit" do
|
58
|
+
errors = [
|
59
|
+
["foo", ["error1", "error2"]],
|
60
|
+
["bar", ["error1", "error2"]]
|
61
|
+
]
|
62
|
+
|
63
|
+
Tane::Commands::Login.term.should_receive(:say).at_least(errors.count)
|
64
|
+
|
65
|
+
expect {
|
66
|
+
Tane::Commands::Login.display_errors_and_exit(errors)
|
67
|
+
}.to raise_error(SystemExit)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
describe ".display_help_messages_and_exit" do
|
73
|
+
it "should display the help messages and exit" do
|
74
|
+
Tane::Commands::Login.term.should_receive(:say).at_least(1)
|
75
|
+
|
76
|
+
expect {
|
77
|
+
Tane::Commands::Login.display_help_messages_and_exit
|
78
|
+
}.to raise_error(SystemExit)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Commands::Support do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@message = "user_entered_message"
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".process" do
|
10
|
+
it "should prompt the user for the message and send it to Bushido" do
|
11
|
+
Tane::Commands::Support.term.should_receive(:ask).and_return(@message)
|
12
|
+
Tane::Commands::Support.should_receive(:send_message_to_bushido).with(@message)
|
13
|
+
|
14
|
+
Tane::Commands::Support.process([])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
describe ".send_message_to_bushido" do
|
20
|
+
|
21
|
+
before :each do
|
22
|
+
Tane::Commands::Support.should_receive(:email_from_credentials_or_prompt).and_return("valid_username")
|
23
|
+
|
24
|
+
RestClient.should_receive(:post).
|
25
|
+
with(Tane::Commands::Support.support_url, {
|
26
|
+
:source => "tane",
|
27
|
+
:email => "valid_username",
|
28
|
+
:message => @message
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should display the message being sent" do
|
33
|
+
Tane::Commands::Support.term.should_receive(:say).at_least(3)
|
34
|
+
Tane::Commands::Support.send_message_to_bushido(@message)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should send a message to Bushido team" do
|
38
|
+
Tane::Commands::Support.send_message_to_bushido(@message)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ".get_email_or_prompt" do
|
44
|
+
it "should return the username if the user is logged in" do
|
45
|
+
Tane::Commands::Support.should_receive(:logged_in?).and_return(true)
|
46
|
+
Tane::Commands::Support.should_receive(:username).and_return("valid_username")
|
47
|
+
|
48
|
+
Tane::Commands::Support.email_from_credentials_or_prompt.should == "valid_username"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should return the input from prompt if the user is not logged in" do
|
52
|
+
Tane::Commands::Support.should_receive(:logged_in?).and_return(false)
|
53
|
+
Tane::Commands::Support.term.should_receive(:ask).and_return("valid_username")
|
54
|
+
|
55
|
+
Tane::Commands::Support.email_from_credentials_or_prompt.should == "valid_username"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tane::Helpers::Bushido do
|
4
|
+
|
5
|
+
describe "bushido_url" do
|
6
|
+
it "should return the http://bushid.do by default" do
|
7
|
+
# To make sure it's overridden if set in tachi
|
8
|
+
ENV['BUSHIDO_URL'] = nil
|
9
|
+
Tane::Helpers::Bushido.bushido_url.should == "http://bushi.do"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return the env variable's value if it is set" do
|
13
|
+
ENV['BUSHIDO_URL'] = "http://noshido.com"
|
14
|
+
Tane::Helpers::Bushido.bushido_url.should == "http://noshido.com"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ".verify_credentials" do
|
19
|
+
before :each do
|
20
|
+
@params = {:params => {:email => "email", :password => "password" }}
|
21
|
+
@bushido_verify_url = "#{Tane::Helpers::Bushido.bushido_url}/users/verify.json"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return an authentication_token if the verification was a success" do
|
25
|
+
result_with_auth_token = {
|
26
|
+
:errors => nil,
|
27
|
+
:authentication_token => "valid_auth_token"
|
28
|
+
}
|
29
|
+
|
30
|
+
RestClient.should_receive(:get).
|
31
|
+
with(@bushido_verify_url, @params).and_return(result_with_auth_token.to_json)
|
32
|
+
|
33
|
+
Tane::Helpers::Bushido.verify_credentials("email", "password").should == [result_with_auth_token[:authentication_token] ,nil]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return false if the verification returned false" do
|
37
|
+
result_with_error = {
|
38
|
+
:errors => "Sample error",
|
39
|
+
:authentication_token => nil
|
40
|
+
}
|
41
|
+
|
42
|
+
RestClient.should_receive(:get).
|
43
|
+
with(@bushido_verify_url, @params).and_return(result_with_error.to_json)
|
44
|
+
|
45
|
+
Tane::Helpers::Bushido.verify_credentials("email", "password").should == [nil, result_with_error[:errors]]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ".signup" do
|
50
|
+
before :each do
|
51
|
+
@params = {:params => {:email => "email", :password => "password" }}
|
52
|
+
@bushido_create_url = "#{Tane::Helpers::Bushido.bushido_url}/users/create.json"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should signup a user when provided with email and password" do
|
56
|
+
result_with_auth_token = {
|
57
|
+
:errors => nil,
|
58
|
+
:authentication_token => "valid_auth_token"
|
59
|
+
}
|
60
|
+
|
61
|
+
RestClient.should_receive(:get).
|
62
|
+
with(@bushido_create_url, @params).
|
63
|
+
and_return(result_with_auth_token.to_json)
|
64
|
+
|
65
|
+
Tane::Helpers::Bushido.signup("email", "password").should == [result_with_auth_token[:authentication_token], nil]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should not signup a user and return errors if any" do
|
69
|
+
result_with_error = {
|
70
|
+
:errors => "Sample error",
|
71
|
+
:authentication_token => nil
|
72
|
+
}
|
73
|
+
|
74
|
+
RestClient.should_receive(:get).
|
75
|
+
with(@bushido_create_url, @params).and_return(result_with_error.to_json)
|
76
|
+
|
77
|
+
Tane::Helpers::Bushido.signup("email", "password").should == [nil, result_with_error[:errors]]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "authenticate_user" do
|
82
|
+
it "should warn the user if credentials already exist" do
|
83
|
+
Tane::Helpers::Bushido.should_receive(:warn_if_credentials)
|
84
|
+
Tane::Helpers::Bushido.authenticate_user("email", "password")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|