File: integration_spec.rb

package info (click to toggle)
ruby-asciidoctor-include-ext 0.4.0%2Bgh-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 184 kB
  • sloc: ruby: 407; makefile: 3; ml: 1
file content (187 lines) | stat: -rw-r--r-- 5,052 bytes parent folder | download
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
require_relative 'spec_helper'
require 'asciidoctor/include_ext/include_processor'
require 'webrick'

FIXTURES_DIR = File.expand_path('fixtures', __dir__)

describe 'Integration tests' do

  subject(:output) { Asciidoctor.convert(input, options) }

  let(:input) { '' }  # this is modified in #given
  let(:processor) { Asciidoctor::IncludeExt::IncludeProcessor.new }

  let(:options) {
    processor_ = processor
    {
      safe: :safe,
      header_footer: false,
      base_dir: FIXTURES_DIR,
      extensions: proc { include_processor processor_ },
    }
  }

  before do
    # XXX: Ugly hack to get rid of rspec-mocks' warnings about resetting
    # frozen object; https://github.com/rspec/rspec-mocks/issues/1190.
    processor.define_singleton_method(:freeze) { self }

    # Make sure that Asciidoctor really calls our processor.
    expect(processor).to receive(:process).at_least(:once).and_call_original
  end

  describe 'include::[] directive' do

    it 'is replaced by a link when safe mode is default' do
      given 'include::include-file.adoc[]', safe: nil

      should match /<a[^>]+href="include-file.adoc"/
      should_not match /included content/
    end

    it 'is resolved when safe mode is less than SECURE' do
      given 'include::include-file.adoc[]'

      should match /included content/
      should_not match /<a[^>]+href="include-file\.adoc"/
    end

    it 'nested includes are resolved with relative paths' do
      given 'include::a/include-1.adoc[]'

      expect( output.scan(/[^>]*include \w+/) ).to eq [
        'begin of include 1', 'include 2a', 'begin of include 2b', 'include 3',
        'end of include 2b', 'end of include 1'
      ]
    end

    it 'is replaced by a warning when target is not found' do
      given <<~ADOC
        include::no-such-file.adoc[]

        trailing content
      ADOC

      should match /unresolved/i
      should match /trailing content/
    end

    it 'is skipped when target is not found and optional option is set' do
      given <<~ADOC
        include::no-such-file.adoc[opts=optional]

        trailing content
      ADOC

      should match /trailing content/
      should_not match /unresolved/i
    end

    it 'is replaced by a link when target is an URI and attribute allow-uri-read is not set' do
      using_test_webserver do |host, port|
        target = "http://#{host}:#{port}/hello.json"
        given "include::#{target}[]"

        should match /<a[^>]*href="#{target}"/
        should_not match /\{"message": "Hello, world!"\}/
      end
    end

    it 'retrieves content from URI target when allow-uri-read is set' do
      using_test_webserver do |host, port|
        given "include::http://#{host}:#{port}/hello.json[]",
              attributes: { 'allow-uri-read' => '' }

        should match /\{"message": "Hello, world!"\}/
        should_not match /unresolved/i
      end
    end

    it 'supports line selection' do
      given 'include::include-file.adoc[lines=1;3..4;6..-1]'

      %w[1 3 4 6 7 8].each do |n|
        should match /line #{n} of included content/
      end
      should match /last line/

      should_not match /line 2/
      should_not match /line 5/
    end

    it 'supports tagged selection' do
      given 'include::include-file.adoc[tag=snippet-a]'

      should match /snippet-a content/
      should_not match /snippet-b content/
      should_not match /non-tagged content/
      should_not match /included content/
    end

    it 'supports multiple tagged selection' do
      given 'include::include-file.adoc[tags="snippet-a,snippet-b"]'

      should match /snippet-a content/
      should match /snippet-b content/
      should_not match /non-tagged content/
      should_not match /included content/
    end

    it 'supports tagged selection in language that uses circumfix comments' do
      given <<~ADOC
        [source, ml]
        ----
        include::include-file.ml[tag=snippet]
        ----
      ADOC

      should match /let s = SS.empty;;/
      should_not match /(?:tag|end)::snippet\[\]/
    end

    it 'does not allow execution of system command when allow-uri-read is set' do
      options.merge!(attributes: { 'allow-uri-read' => '' })
      given <<~ADOC
        :app-name: |cat LICENSE # + \\
        http://test.com

        include::{app-name}[]
      ADOC

      should match /unresolved/i
      should_not match /The MIT License/
    end

  end


  #----------  Helpers  ----------

  def given(str, opts = {})
    input.replace(str)
    options.merge!(opts)
  end

  def using_test_webserver
    started = false
    server = WEBrick::HTTPServer.new(
      BindAddress: '127.0.0.1',
      Port: 0,
      StartCallback: -> { started = true },
      AccessLog: [],
    )

    server.mount_proc '/hello.json' do |_, res|
      res.body = '{"message": "Hello, world!"}'
    end

    Thread.new { server.start }
    Timeout.timeout(1) { :wait until started }

    begin
      yield server.config[:BindAddress], server.config[:Port]
    ensure
      server.shutdown
    end
  end
end