pwn 0.5.613 → 0.5.617
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +10 -10
- data/README.md +117 -17
- data/bin/pwn +47 -2
- data/bin/pwn_gqrx_scanner +75 -18
- data/documentation/AI-Integration.md +36 -0
- data/documentation/BurpSuite.md +26 -0
- data/documentation/Contributing.md +31 -0
- data/documentation/Diagrams.md +140 -0
- data/documentation/Drivers.md +25 -0
- data/documentation/General-PWN-Usage.md +60 -0
- data/documentation/Home.md +78 -0
- data/documentation/How-PWN-Works.md +62 -0
- data/documentation/Installation.md +75 -0
- data/documentation/NmapIt.md +18 -0
- data/documentation/Plugins.md +59 -0
- data/documentation/Reporting.md +28 -0
- data/documentation/SAST.md +32 -0
- data/documentation/Skills-Memory-Learning.md +44 -0
- data/documentation/Transparent-Browser.md +32 -0
- data/documentation/Troubleshooting.md +38 -0
- data/documentation/What-is-PWN.md +53 -0
- data/documentation/Why-PWN.md +48 -0
- data/documentation/diagrams/ai-integration-tool-calling.svg +172 -0
- data/documentation/diagrams/build.sh +20 -0
- data/documentation/diagrams/burp-vs-zap-preference.svg +69 -0
- data/documentation/diagrams/code-scanning-sast.svg +172 -0
- data/documentation/diagrams/dot/_THEME.md +27 -0
- data/documentation/diagrams/dot/agent-tool-registry.dot +59 -0
- data/documentation/diagrams/dot/ai-integration-tool-calling.dot +50 -0
- data/documentation/diagrams/dot/aws-cloud-security.dot +48 -0
- data/documentation/diagrams/dot/burp-vs-zap-preference.dot +26 -0
- data/documentation/diagrams/dot/code-scanning-sast.dot +49 -0
- data/documentation/diagrams/dot/cron-scheduling.dot +40 -0
- data/documentation/diagrams/dot/driver-framework.dot +39 -0
- data/documentation/diagrams/dot/extrospection-world-awareness.dot +55 -0
- data/documentation/diagrams/dot/fuzzing-workflow.dot +47 -0
- data/documentation/diagrams/dot/history-to-drivers.dot +34 -0
- data/documentation/diagrams/dot/memory-skills-detailed.dot +60 -0
- data/documentation/diagrams/dot/network-infra-testing.dot +54 -0
- data/documentation/diagrams/dot/overall-pwn-architecture.dot +115 -0
- data/documentation/diagrams/dot/penetration-testing-workflow.dot +60 -0
- data/documentation/diagrams/dot/plugin-ecosystem.dot +45 -0
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +98 -0
- data/documentation/diagrams/dot/pwn-repl-prototyping.dot +56 -0
- data/documentation/diagrams/dot/reporting-pipeline.dot +46 -0
- data/documentation/diagrams/dot/reverse-engineering-flow.dot +43 -0
- data/documentation/diagrams/dot/sdr-radio-flow.dot +45 -0
- data/documentation/diagrams/dot/sessions-cron-automation.dot +44 -0
- data/documentation/diagrams/dot/swarm-multi-agent.dot +70 -0
- data/documentation/diagrams/dot/web-application-testing.dot +49 -0
- data/documentation/diagrams/dot/zero-day-research-flow.dot +49 -0
- data/documentation/diagrams/driver-framework.svg +111 -0
- data/documentation/diagrams/fuzzing-workflow.svg +160 -0
- data/documentation/diagrams/history-to-drivers.svg +119 -0
- data/documentation/diagrams/memory-skills-detailed.svg +202 -0
- data/documentation/diagrams/network-infra-testing.svg +183 -0
- data/documentation/diagrams/overall-pwn-architecture.svg +405 -0
- data/documentation/diagrams/penetration-testing-workflow.svg +201 -0
- data/documentation/diagrams/plugin-ecosystem.svg +276 -0
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +306 -0
- data/documentation/diagrams/pwn-repl-prototyping.svg +168 -0
- data/documentation/diagrams/reporting-pipeline.svg +151 -0
- data/documentation/diagrams/reverse-engineering-flow.svg +134 -0
- data/documentation/diagrams/sessions-cron-automation.svg +136 -0
- data/documentation/diagrams/web-application-testing.svg +173 -0
- data/documentation/diagrams/zero-day-research-flow.svg +153 -0
- data/documentation/pwn-REPL.md +33 -0
- data/documentation/pwn-ai-Agent.md +43 -0
- data/git_commit.sh +1 -1
- data/lib/pwn/ai/agent/assembly.rb +1 -1
- data/lib/pwn/ai/agent/btc.rb +1 -1
- data/lib/pwn/ai/agent/burp_suite.rb +1 -1
- data/lib/pwn/ai/agent/extrospection.rb +618 -0
- data/lib/pwn/ai/agent/gqrx.rb +2 -2
- data/lib/pwn/ai/agent/hacker_one.rb +1 -1
- data/lib/pwn/ai/agent/introspection.rb +91 -0
- data/lib/pwn/ai/agent/learning.rb +379 -0
- data/lib/pwn/ai/agent/loop.rb +33 -3
- data/lib/pwn/ai/agent/metrics.rb +155 -0
- data/lib/pwn/ai/agent/prompt_builder.rb +32 -3
- data/lib/pwn/ai/agent/sast.rb +1 -1
- data/lib/pwn/ai/agent/swarm.rb +437 -0
- data/lib/pwn/ai/agent/tools/cron.rb +163 -0
- data/lib/pwn/ai/agent/tools/extrospection.rb +280 -0
- data/lib/pwn/ai/agent/tools/learning.rb +221 -0
- data/lib/pwn/ai/agent/tools/memory.rb +27 -0
- data/lib/pwn/ai/agent/tools/metrics.rb +61 -0
- data/lib/pwn/ai/agent/tools/sessions.rb +139 -0
- data/lib/pwn/ai/agent/tools/skills.rb +124 -8
- data/lib/pwn/ai/agent/tools/swarm.rb +229 -0
- data/lib/pwn/ai/agent/transparent_browser.rb +1 -1
- data/lib/pwn/ai/agent/vuln_gen.rb +2 -2
- data/lib/pwn/ai/agent.rb +5 -0
- data/lib/pwn/ai/anthropic.rb +19 -4
- data/lib/pwn/ai/grok.rb +249 -106
- data/lib/pwn/ai.rb +0 -1
- data/lib/pwn/config.rb +96 -36
- data/lib/pwn/cron.rb +16 -7
- data/lib/pwn/plugins/monkey_patch.rb +2 -2
- data/lib/pwn/plugins/repl.rb +158 -284
- data/lib/pwn/sdr/decoder/base.rb +251 -0
- data/lib/pwn/sdr/decoder/gsm.rb +84 -185
- data/lib/pwn/sdr/decoder/pocsag.rb +62 -217
- data/lib/pwn/sdr/decoder.rb +1 -0
- data/lib/pwn/sdr/gqrx.rb +446 -65
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/extrospection_spec.rb +15 -0
- data/spec/lib/pwn/ai/agent/introspection_spec.rb +15 -0
- data/spec/lib/pwn/ai/agent/learning_spec.rb +68 -0
- data/spec/lib/pwn/ai/agent/metrics_spec.rb +27 -0
- data/spec/lib/pwn/ai/agent/swarm_spec.rb +34 -0
- data/spec/lib/pwn/ai/agent/tools/cron_spec.rb +40 -0
- data/spec/lib/pwn/ai/agent/tools/extrospection_spec.rb +40 -0
- data/spec/lib/pwn/ai/agent/tools/learning_spec.rb +30 -0
- data/spec/lib/pwn/ai/agent/tools/metrics_spec.rb +20 -0
- data/spec/lib/pwn/ai/agent/tools/sessions_spec.rb +35 -0
- data/spec/lib/pwn/ai/agent/tools/swarm_spec.rb +17 -0
- data/spec/lib/pwn/{ai/introspection_spec.rb → sdr/decoder/base_spec.rb} +3 -3
- data/third_party/pwn_rdoc.jsonl +178 -33
- metadata +110 -36
- data/documentation/PWN.png +0 -0
- data/documentation/PWN_Contributors_and_Users.png +0 -0
- data/documentation/fax-spectrogram.png +0 -0
- data/documentation/fax-waveform.png +0 -0
- data/documentation/frozen_string_literal_files_changed_from_false_to_true.txt +0 -54
- data/documentation/lifecycle_authz_replay.example.yaml +0 -27
- data/documentation/pwn_android_war_dialer_session.png +0 -0
- data/documentation/pwn_install.png +0 -0
- data/documentation/pwn_wallpaper.jpg +0 -0
- data/documentation/ringing-spectrogram.png +0 -0
- data/documentation/ringing-waveform.png +0 -0
- data/documentation/vulnerability_report_template.md +0 -37
- data/lib/pwn/ai/introspection.rb +0 -76
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe PWN::AI::Agent::Metrics do
|
|
6
|
+
it 'should display information for authors' do
|
|
7
|
+
authors_response = PWN::AI::Agent::Metrics
|
|
8
|
+
expect(authors_response).to respond_to :authors
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should display information for existing help method' do
|
|
12
|
+
help_response = PWN::AI::Agent::Metrics
|
|
13
|
+
expect(help_response).to respond_to :help
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'records tool telemetry and summarises effectiveness' do
|
|
17
|
+
stub_const('PWN::AI::Agent::Metrics::METRICS_FILE', File.join(Dir.mktmpdir, 'metrics.json'))
|
|
18
|
+
PWN::AI::Agent::Metrics.reset
|
|
19
|
+
PWN::AI::Agent::Metrics.record(name: 'shell', success: true, duration: 0.10)
|
|
20
|
+
PWN::AI::Agent::Metrics.record(name: 'shell', success: false, duration: 0.20, error: 'boom')
|
|
21
|
+
rows = PWN::AI::Agent::Metrics.summary
|
|
22
|
+
row = rows.find { |r| r[:name] == 'shell' }
|
|
23
|
+
expect(row[:calls]).to eq 2
|
|
24
|
+
expect(row[:success_rate]).to eq 0.5
|
|
25
|
+
expect(PWN::AI::Agent::Metrics.to_context).to include('shell')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe PWN::AI::Agent::Swarm do
|
|
6
|
+
it 'should display information for authors' do
|
|
7
|
+
authors_response = PWN::AI::Agent::Swarm
|
|
8
|
+
expect(authors_response).to respond_to :authors
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should display information for existing help method' do
|
|
12
|
+
help_response = PWN::AI::Agent::Swarm
|
|
13
|
+
expect(help_response).to respond_to :help
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'exposes the core orchestration API' do
|
|
17
|
+
%i[personas spawn retire create list ask debate broadcast bus_append bus_tail].each do |m|
|
|
18
|
+
expect(PWN::AI::Agent::Swarm).to respond_to m
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'normalizes personas loaded from AGENTS_FILE without raising' do
|
|
23
|
+
expect { PWN::AI::Agent::Swarm.personas }.not_to raise_error
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'enforces the recursion depth guard' do
|
|
27
|
+
Thread.current[:pwn_swarm_depth] = 999
|
|
28
|
+
expect do
|
|
29
|
+
PWN::AI::Agent::Swarm.ask(name: PWN::AI::Agent::Swarm.personas.keys.first || :__none, request: 'x')
|
|
30
|
+
end.to raise_error(StandardError)
|
|
31
|
+
ensure
|
|
32
|
+
Thread.current[:pwn_swarm_depth] = nil
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'PWN::AI::Agent::Tools cron' do
|
|
6
|
+
it 'registers the cron_list tool' do
|
|
7
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
8
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'cron_list')).not_to be_nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'registers the cron_create tool' do
|
|
12
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
13
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'cron_create')).not_to be_nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'registers the cron_run tool' do
|
|
17
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
18
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'cron_run')).not_to be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'registers the cron_enable tool' do
|
|
22
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
23
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'cron_enable')).not_to be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'registers the cron_disable tool' do
|
|
27
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
28
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'cron_disable')).not_to be_nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'registers the cron_remove tool' do
|
|
32
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
33
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'cron_remove')).not_to be_nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'exposes the cron toolset in the registry' do
|
|
37
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
38
|
+
expect(PWN::AI::Agent::Registry.toolsets).to include('cron')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'PWN::AI::Agent::Tools extrospection' do
|
|
6
|
+
it 'registers the extro_snapshot tool' do
|
|
7
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
8
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'extro_snapshot')).not_to be_nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'registers the extro_drift tool' do
|
|
12
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
13
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'extro_drift')).not_to be_nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'registers the extro_observe tool' do
|
|
17
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
18
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'extro_observe')).not_to be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'registers the extro_observations tool' do
|
|
22
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
23
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'extro_observations')).not_to be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'registers the extro_intel tool' do
|
|
27
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
28
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'extro_intel')).not_to be_nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'registers the extro_correlate tool' do
|
|
32
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
33
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'extro_correlate')).not_to be_nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'exposes the extrospection toolset in the registry' do
|
|
37
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
38
|
+
expect(PWN::AI::Agent::Registry.toolsets).to include('extrospection')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'PWN::AI::Agent::Tools learning' do
|
|
6
|
+
it 'registers the learning_note_outcome tool' do
|
|
7
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
8
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'learning_note_outcome')).not_to be_nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'registers the learning_reflect tool' do
|
|
12
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
13
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'learning_reflect')).not_to be_nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'registers the learning_distill_skill tool' do
|
|
17
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
18
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'learning_distill_skill')).not_to be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'registers the learning_stats tool' do
|
|
22
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
23
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'learning_stats')).not_to be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'exposes the learning toolset in the registry' do
|
|
27
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
28
|
+
expect(PWN::AI::Agent::Registry.toolsets).to include('learning')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'PWN::AI::Agent::Tools metrics' do
|
|
6
|
+
it 'registers the metrics_summary tool' do
|
|
7
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
8
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'metrics_summary')).not_to be_nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'registers the metrics_reset tool' do
|
|
12
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
13
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'metrics_reset')).not_to be_nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'exposes the metrics toolset in the registry' do
|
|
17
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
18
|
+
expect(PWN::AI::Agent::Registry.toolsets).to include('metrics')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'PWN::AI::Agent::Tools sessions' do
|
|
6
|
+
it 'registers the sessions_list tool' do
|
|
7
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
8
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'sessions_list')).not_to be_nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'registers the sessions_view tool' do
|
|
12
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
13
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'sessions_view')).not_to be_nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'registers the sessions_delete tool' do
|
|
17
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
18
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'sessions_delete')).not_to be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'registers the sessions_stats tool' do
|
|
22
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
23
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'sessions_stats')).not_to be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'registers the sessions_current tool' do
|
|
27
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
28
|
+
expect(PWN::AI::Agent::Registry.lookup(name: 'sessions_current')).not_to be_nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'exposes the sessions toolset in the registry' do
|
|
32
|
+
PWN::AI::Agent::Registry.discover(force: true)
|
|
33
|
+
expect(PWN::AI::Agent::Registry.toolsets).to include('sessions')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'PWN::AI::Agent::Tools swarm' do
|
|
6
|
+
before(:all) { PWN::AI::Agent::Registry.discover(force: true) }
|
|
7
|
+
|
|
8
|
+
%w[agent_list agent_spawn agent_ask agent_debate agent_broadcast swarm_bus swarm_list].each do |tool|
|
|
9
|
+
it "registers the #{tool} tool" do
|
|
10
|
+
expect(PWN::AI::Agent::Registry.lookup(name: tool)).not_to be_nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'exposes the swarm toolset in the registry' do
|
|
15
|
+
expect(PWN::AI::Agent::Registry.toolsets).to include('swarm')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
describe PWN::
|
|
5
|
+
describe PWN::SDR::Decoder::Base do
|
|
6
6
|
it 'should display information for authors' do
|
|
7
|
-
authors_response = PWN::
|
|
7
|
+
authors_response = PWN::SDR::Decoder::Base
|
|
8
8
|
expect(authors_response).to respond_to :authors
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
it 'should display information for existing help method' do
|
|
12
|
-
help_response = PWN::
|
|
12
|
+
help_response = PWN::SDR::Decoder::Base
|
|
13
13
|
expect(help_response).to respond_to :help
|
|
14
14
|
end
|
|
15
15
|
end
|