flavour_saver 0.3.9 → 2.0.1
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 +5 -5
- data/.github/workflows/ci.yml +47 -0
- data/CHANGELOG.md +46 -0
- data/Gemfile.lock +34 -62
- data/README.md +3 -10
- data/flavour_saver.gemspec +14 -9
- data/lib/flavour_saver/helpers.rb +28 -16
- data/lib/flavour_saver/lexer.rb +1 -1
- data/lib/flavour_saver/parser.rb +14 -8
- data/lib/flavour_saver/runtime.rb +7 -7
- data/lib/flavour_saver/version.rb +1 -1
- data/spec/acceptance/backtrack_spec.rb +1 -1
- data/spec/acceptance/comment_spec.rb +1 -1
- data/spec/acceptance/custom_block_helper_spec.rb +2 -2
- data/spec/acceptance/custom_helper_spec.rb +1 -1
- data/spec/acceptance/ensure_no_rce_spec.rb +2 -2
- data/spec/acceptance/handlebars_qunit_spec.rb +297 -219
- data/spec/acceptance/if_else_spec.rb +37 -6
- data/spec/acceptance/multi_level_with_spec.rb +1 -1
- data/spec/acceptance/one_character_identifier_spec.rb +2 -2
- data/spec/acceptance/raw_block_spec.rb +1 -1
- data/spec/acceptance/runtime_run_spec.rb +1 -1
- data/spec/acceptance/sections_spec.rb +3 -3
- data/spec/acceptance/segment_literals_spec.rb +3 -3
- data/spec/acceptance/simple_expression_spec.rb +3 -3
- data/spec/acceptance/subexpression_spec.rb +4 -5
- data/spec/acceptance/unless_spec.rb +48 -0
- data/spec/fixtures/if_else.hbs +3 -3
- data/spec/fixtures/unless.hbs +5 -0
- data/spec/lib/flavour_saver/lexer_spec.rb +67 -36
- data/spec/lib/flavour_saver/parser_spec.rb +91 -91
- data/spec/lib/flavour_saver/runtime_spec.rb +37 -37
- metadata +25 -72
- data/.travis.yml +0 -18
- data/Guardfile +0 -12
| @@ -5,18 +5,18 @@ describe FlavourSaver::Parser do | |
| 5 5 | 
             
              let (:items) { subject.items }
         | 
| 6 6 |  | 
| 7 7 | 
             
              it 'is a RLTK::Parser' do
         | 
| 8 | 
            -
                subject. | 
| 8 | 
            +
                expect(subject).to be_a(RLTK::Parser)
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 11 | 
             
              describe 'HTML template' do
         | 
| 12 12 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('<html><h1>Hello world!</h1></html>')) }
         | 
| 13 13 |  | 
| 14 14 | 
             
                it 'is an output node' do
         | 
| 15 | 
            -
                  items.first. | 
| 15 | 
            +
                  expect(items.first).to be_a(FlavourSaver::OutputNode)
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 18 | 
             
                it 'has the correct contents' do
         | 
| 19 | 
            -
                  items.first.value. | 
| 19 | 
            +
                  expect(items.first.value).to eq '<html><h1>Hello world!</h1></html>'
         | 
| 20 20 | 
             
                end
         | 
| 21 21 | 
             
              end
         | 
| 22 22 |  | 
| @@ -24,7 +24,7 @@ describe FlavourSaver::Parser do | |
| 24 24 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('<html>{{foo}}</html>')) }
         | 
| 25 25 |  | 
| 26 26 | 
             
                it 'has template output either side of the expression' do
         | 
| 27 | 
            -
                  items.map(&:class). | 
| 27 | 
            +
                  expect(items.map(&:class)).to eq [FlavourSaver::OutputNode, FlavourSaver::ExpressionNode, FlavourSaver::OutputNode]
         | 
| 28 28 | 
             
                end
         | 
| 29 29 | 
             
              end
         | 
| 30 30 |  | 
| @@ -32,14 +32,14 @@ describe FlavourSaver::Parser do | |
| 32 32 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo}}')) }
         | 
| 33 33 |  | 
| 34 34 | 
             
                it 'contains an expression node' do
         | 
| 35 | 
            -
                  items.first. | 
| 35 | 
            +
                  expect(items.first).to be_a(FlavourSaver::ExpressionNode)
         | 
| 36 36 | 
             
                end
         | 
| 37 37 |  | 
| 38 38 | 
             
                it 'calls the method "foo" with no arguments' do
         | 
| 39 | 
            -
                  items.first.method. | 
| 40 | 
            -
                  items.first.method.first. | 
| 41 | 
            -
                  items.first.method.first.name. | 
| 42 | 
            -
                  items.first.method.first.arguments. | 
| 39 | 
            +
                  expect(items.first.method).to be_one
         | 
| 40 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 41 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 42 | 
            +
                  expect(items.first.method.first.arguments).to be_empty
         | 
| 43 43 | 
             
                end
         | 
| 44 44 | 
             
              end
         | 
| 45 45 |  | 
| @@ -47,19 +47,19 @@ describe FlavourSaver::Parser do | |
| 47 47 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo.bar}}')) }
         | 
| 48 48 |  | 
| 49 49 | 
             
                it 'calls two methods' do
         | 
| 50 | 
            -
                  items.first.method.size. | 
| 50 | 
            +
                  expect(items.first.method.size).to eq 2
         | 
| 51 51 | 
             
                end
         | 
| 52 52 |  | 
| 53 53 | 
             
                it 'calls the method "foo" with no arguments first' do
         | 
| 54 | 
            -
                  items.first.method.first. | 
| 55 | 
            -
                  items.first.method.first.name. | 
| 56 | 
            -
                  items.first.method.first.arguments. | 
| 54 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 55 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 56 | 
            +
                  expect(items.first.method.first.arguments).to be_empty
         | 
| 57 57 | 
             
                end
         | 
| 58 58 |  | 
| 59 59 | 
             
                it 'calls the method "bar" with no arguments second' do
         | 
| 60 | 
            -
                  items.first.method[1]. | 
| 61 | 
            -
                  items.first.method[1].name. | 
| 62 | 
            -
                  items.first.method[1].arguments. | 
| 60 | 
            +
                  expect(items.first.method[1]).to be_a(FlavourSaver::CallNode)
         | 
| 61 | 
            +
                  expect(items.first.method[1].name).to eq 'bar'
         | 
| 62 | 
            +
                  expect(items.first.method[1].arguments).to be_empty
         | 
| 63 63 | 
             
                end
         | 
| 64 64 | 
             
              end
         | 
| 65 65 |  | 
| @@ -67,25 +67,25 @@ describe FlavourSaver::Parser do | |
| 67 67 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo.[&@^$*].bar}}')) }
         | 
| 68 68 |  | 
| 69 69 | 
             
                it 'calls three methods' do
         | 
| 70 | 
            -
                  items.first.method.size. | 
| 70 | 
            +
                  expect(items.first.method.size).to eq 3
         | 
| 71 71 | 
             
                end
         | 
| 72 72 |  | 
| 73 73 | 
             
                it 'calls the method "foo" with no arguments first' do
         | 
| 74 | 
            -
                  items.first.method.first. | 
| 75 | 
            -
                  items.first.method.first.name. | 
| 76 | 
            -
                  items.first.method.first.arguments. | 
| 74 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 75 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 76 | 
            +
                  expect(items.first.method.first.arguments).to be_empty
         | 
| 77 77 | 
             
                end
         | 
| 78 78 |  | 
| 79 79 | 
             
                it 'calls the method "&@^$*" with no arguments second' do
         | 
| 80 | 
            -
                  items.first.method[1]. | 
| 81 | 
            -
                  items.first.method[1].name. | 
| 82 | 
            -
                  items.first.method[1].arguments. | 
| 80 | 
            +
                  expect(items.first.method[1]).to be_a(FlavourSaver::CallNode)
         | 
| 81 | 
            +
                  expect(items.first.method[1].name).to eq '&@^$*'
         | 
| 82 | 
            +
                  expect(items.first.method[1].arguments).to be_empty
         | 
| 83 83 | 
             
                end
         | 
| 84 84 |  | 
| 85 85 | 
             
                it 'calls the method "bar" with no arguments third' do
         | 
| 86 | 
            -
                  items.first.method[2]. | 
| 87 | 
            -
                  items.first.method[2].name. | 
| 88 | 
            -
                  items.first.method[2].arguments. | 
| 86 | 
            +
                  expect(items.first.method[2]).to be_a(FlavourSaver::CallNode)
         | 
| 87 | 
            +
                  expect(items.first.method[2].name).to eq 'bar'
         | 
| 88 | 
            +
                  expect(items.first.method[2].arguments).to be_empty
         | 
| 89 89 | 
             
                end
         | 
| 90 90 | 
             
              end
         | 
| 91 91 |  | 
| @@ -93,12 +93,12 @@ describe FlavourSaver::Parser do | |
| 93 93 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar}}')) }
         | 
| 94 94 |  | 
| 95 95 | 
             
                it 'calls the method "foo" with a method argument of "bar"' do
         | 
| 96 | 
            -
                  items.first.method. | 
| 97 | 
            -
                  items.first.method.first. | 
| 98 | 
            -
                  items.first.method.first.name. | 
| 99 | 
            -
                  items.first.method.first.arguments. | 
| 100 | 
            -
                  items.first.method.first.arguments.first.first. | 
| 101 | 
            -
                  items.first.method.first.arguments.first.first.name. | 
| 96 | 
            +
                  expect(items.first.method).to be_one
         | 
| 97 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 98 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 99 | 
            +
                  expect(items.first.method.first.arguments).to be_one
         | 
| 100 | 
            +
                  expect(items.first.method.first.arguments.first.first).to be_a(FlavourSaver::CallNode)
         | 
| 101 | 
            +
                  expect(items.first.method.first.arguments.first.first.name).to eq 'bar'
         | 
| 102 102 | 
             
                end
         | 
| 103 103 | 
             
              end
         | 
| 104 104 |  | 
| @@ -106,12 +106,12 @@ describe FlavourSaver::Parser do | |
| 106 106 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo "bar" }}')) }
         | 
| 107 107 |  | 
| 108 108 | 
             
                it 'calls the method "foo" with a string argument of "bar"' do
         | 
| 109 | 
            -
                  items.first.method. | 
| 110 | 
            -
                  items.first.method.first. | 
| 111 | 
            -
                  items.first.method.first.name. | 
| 112 | 
            -
                  items.first.method.first.arguments. | 
| 113 | 
            -
                  items.first.method.first.arguments.first. | 
| 114 | 
            -
                  items.first.method.first.arguments.first.value. | 
| 109 | 
            +
                  expect(items.first.method).to be_one
         | 
| 110 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 111 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 112 | 
            +
                  expect(items.first.method.first.arguments).to be_one
         | 
| 113 | 
            +
                  expect(items.first.method.first.arguments.first).to be_a(FlavourSaver::StringNode)
         | 
| 114 | 
            +
                  expect(items.first.method.first.arguments.first.value).to eq 'bar'
         | 
| 115 115 | 
             
                end
         | 
| 116 116 | 
             
              end
         | 
| 117 117 |  | 
| @@ -119,9 +119,9 @@ describe FlavourSaver::Parser do | |
| 119 119 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo    bar  "baz" }}')) }
         | 
| 120 120 |  | 
| 121 121 | 
             
                it 'calls the method "foo"' do
         | 
| 122 | 
            -
                  items.first.method. | 
| 123 | 
            -
                  items.first.method.first. | 
| 124 | 
            -
                  items.first.method.first.name. | 
| 122 | 
            +
                  expect(items.first.method).to be_one
         | 
| 123 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 124 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 125 125 | 
             
                end
         | 
| 126 126 |  | 
| 127 127 | 
             
                describe 'with arguments' do
         | 
| @@ -129,15 +129,15 @@ describe FlavourSaver::Parser do | |
| 129 129 |  | 
| 130 130 | 
             
                  describe '[0]' do
         | 
| 131 131 | 
             
                    it 'is the method call "bar" with no arguments' do
         | 
| 132 | 
            -
                      subject.first.first. | 
| 133 | 
            -
                      subject.first.first.name. | 
| 132 | 
            +
                      expect(subject.first.first).to be_a(FlavourSaver::CallNode)
         | 
| 133 | 
            +
                      expect(subject.first.first.name).to eq 'bar'
         | 
| 134 134 | 
             
                    end
         | 
| 135 135 | 
             
                  end
         | 
| 136 136 |  | 
| 137 137 | 
             
                  describe '[1]' do
         | 
| 138 138 | 
             
                    it 'is the string "baz"' do
         | 
| 139 | 
            -
                      subject[1]. | 
| 140 | 
            -
                      subject[1].value. | 
| 139 | 
            +
                      expect(subject[1]).to be_a(FlavourSaver::StringNode)
         | 
| 140 | 
            +
                      expect(subject[1].value).to eq 'baz'
         | 
| 141 141 | 
             
                    end
         | 
| 142 142 | 
             
                  end
         | 
| 143 143 | 
             
                end
         | 
| @@ -147,9 +147,9 @@ describe FlavourSaver::Parser do | |
| 147 147 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo (bar "baz") }}')) }
         | 
| 148 148 |  | 
| 149 149 | 
             
                it 'calls the method "foo"' do
         | 
| 150 | 
            -
                  items.first.method. | 
| 151 | 
            -
                  items.first.method.first. | 
| 152 | 
            -
                  items.first.method.first.name. | 
| 150 | 
            +
                  expect(items.first.method).to be_one
         | 
| 151 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 152 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 153 153 | 
             
                end
         | 
| 154 154 |  | 
| 155 155 | 
             
                describe 'with arguments' do
         | 
| @@ -157,8 +157,8 @@ describe FlavourSaver::Parser do | |
| 157 157 |  | 
| 158 158 | 
             
                  describe '[0]' do
         | 
| 159 159 | 
             
                    it 'is a subexpression' do
         | 
| 160 | 
            -
                      subject.first.first. | 
| 161 | 
            -
                      subject.first.first.name. | 
| 160 | 
            +
                      expect(subject.first.first).to be_a(FlavourSaver::CallNode)
         | 
| 161 | 
            +
                      expect(subject.first.first.name).to eq 'bar'
         | 
| 162 162 | 
             
                    end
         | 
| 163 163 | 
             
                  end
         | 
| 164 164 |  | 
| @@ -169,10 +169,10 @@ describe FlavourSaver::Parser do | |
| 169 169 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz"}}')) }
         | 
| 170 170 |  | 
| 171 171 | 
             
                it 'calls the method "foo" with the hash {:bar => "baz"} as arguments' do
         | 
| 172 | 
            -
                  items.first.method.first. | 
| 173 | 
            -
                  items.first.method.first.name. | 
| 174 | 
            -
                  items.first.method.first.arguments.first. | 
| 175 | 
            -
                  items.first.method.first.arguments.first. | 
| 172 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 173 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 174 | 
            +
                  expect(items.first.method.first.arguments.first).to be_a(Hash)
         | 
| 175 | 
            +
                  expect(items.first.method.first.arguments.first).to eq({ :bar => FlavourSaver::StringNode.new('baz') })
         | 
| 176 176 | 
             
                end
         | 
| 177 177 | 
             
              end
         | 
| 178 178 |  | 
| @@ -180,10 +180,10 @@ describe FlavourSaver::Parser do | |
| 180 180 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar=(baz "qux")}}')) }
         | 
| 181 181 |  | 
| 182 182 | 
             
                it 'calls the method "foo" with the hash {:bar => (baz "qux")} as arguments' do
         | 
| 183 | 
            -
                  items.first.method.first. | 
| 184 | 
            -
                  items.first.method.first.name. | 
| 185 | 
            -
                  items.first.method.first.arguments.first. | 
| 186 | 
            -
                  items.first.method.first.arguments.first[:bar].first. | 
| 183 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 184 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 185 | 
            +
                  expect(items.first.method.first.arguments.first).to be_a(Hash)
         | 
| 186 | 
            +
                  expect(items.first.method.first.arguments.first[:bar].first).to be_a(FlavourSaver::CallNode)
         | 
| 187 187 | 
             
                end
         | 
| 188 188 | 
             
              end
         | 
| 189 189 |  | 
| @@ -191,14 +191,14 @@ describe FlavourSaver::Parser do | |
| 191 191 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{foo bar=1}}")) }
         | 
| 192 192 |  | 
| 193 193 | 
             
                it "doesn't throw a NotInLanguage exception" do
         | 
| 194 | 
            -
                   | 
| 194 | 
            +
                  expect { subject }.to_not raise_error
         | 
| 195 195 | 
             
                end
         | 
| 196 196 |  | 
| 197 197 | 
             
                it 'calls the method "foo" with the hash {:bar => 1} as arguments' do
         | 
| 198 | 
            -
                  items.first.method.first. | 
| 199 | 
            -
                  items.first.method.first.name. | 
| 200 | 
            -
                  items.first.method.first.arguments.first. | 
| 201 | 
            -
                  items.first.method.first.arguments.first. | 
| 198 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 199 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 200 | 
            +
                  expect(items.first.method.first.arguments.first).to be_a(Hash)
         | 
| 201 | 
            +
                  expect(items.first.method.first.arguments.first).to eq({ :bar => FlavourSaver::NumberNode.new('1') })
         | 
| 202 202 | 
             
                end
         | 
| 203 203 | 
             
              end
         | 
| 204 204 |  | 
| @@ -206,10 +206,10 @@ describe FlavourSaver::Parser do | |
| 206 206 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz" fred="wilma"}}')) }
         | 
| 207 207 |  | 
| 208 208 | 
             
                it 'calls the method "foo" with the hash {:bar => "baz", :fred => "wilma"} as arguments' do
         | 
| 209 | 
            -
                  items.first.method.first. | 
| 210 | 
            -
                  items.first.method.first.name. | 
| 211 | 
            -
                  items.first.method.first.arguments.first. | 
| 212 | 
            -
                  items.first.method.first.arguments.first. | 
| 209 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 210 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 211 | 
            +
                  expect(items.first.method.first.arguments.first).to be_a(Hash)
         | 
| 212 | 
            +
                  expect(items.first.method.first.arguments.first).to eq({ :bar => FlavourSaver::StringNode.new('baz'), :fred => FlavourSaver::StringNode.new('wilma') })
         | 
| 213 213 | 
             
                end
         | 
| 214 214 | 
             
              end
         | 
| 215 215 |  | 
| @@ -217,7 +217,7 @@ describe FlavourSaver::Parser do | |
| 217 217 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz" fred "wilma"}}')) }
         | 
| 218 218 |  | 
| 219 219 | 
             
                it 'raises an exception' do
         | 
| 220 | 
            -
                   | 
| 220 | 
            +
                  expect { subject }.to raise_exception(RLTK::NotInLanguage)
         | 
| 221 221 | 
             
                end
         | 
| 222 222 | 
             
              end
         | 
| 223 223 |  | 
| @@ -225,7 +225,7 @@ describe FlavourSaver::Parser do | |
| 225 225 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{{foo}}}')) }
         | 
| 226 226 |  | 
| 227 227 | 
             
                it 'returns a safe expression node' do
         | 
| 228 | 
            -
                  items.first. | 
| 228 | 
            +
                  expect(items.first).to be_a(FlavourSaver::SafeExpressionNode)
         | 
| 229 229 | 
             
                end
         | 
| 230 230 | 
             
              end
         | 
| 231 231 |  | 
| @@ -233,7 +233,7 @@ describe FlavourSaver::Parser do | |
| 233 233 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{../foo}}')) }
         | 
| 234 234 |  | 
| 235 235 | 
             
                it 'returns a parent call node' do
         | 
| 236 | 
            -
                  items.first.method.first. | 
| 236 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::ParentCallNode)
         | 
| 237 237 | 
             
                end
         | 
| 238 238 | 
             
              end
         | 
| 239 239 |  | 
| @@ -241,7 +241,7 @@ describe FlavourSaver::Parser do | |
| 241 241 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{! comment}}')) }
         | 
| 242 242 |  | 
| 243 243 | 
             
                it 'returns a comment node' do
         | 
| 244 | 
            -
                  items.first. | 
| 244 | 
            +
                  expect(items.first).to be_a(FlavourSaver::CommentNode)
         | 
| 245 245 | 
             
                end
         | 
| 246 246 | 
             
              end
         | 
| 247 247 |  | 
| @@ -249,14 +249,14 @@ describe FlavourSaver::Parser do | |
| 249 249 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}hello{{/foo}}')) }
         | 
| 250 250 |  | 
| 251 251 | 
             
                it 'has a block start and end' do
         | 
| 252 | 
            -
                  items.map(&:class). | 
| 252 | 
            +
                  expect(items.map(&:class)).to eq [ FlavourSaver::BlockExpressionNode ]
         | 
| 253 253 | 
             
                end
         | 
| 254 254 |  | 
| 255 255 | 
             
                describe '#contents' do
         | 
| 256 256 | 
             
                  it 'contains a single output node' do
         | 
| 257 | 
            -
                    items.first.contents.items.size. | 
| 258 | 
            -
                    items.first.contents.items.first. | 
| 259 | 
            -
                    items.first.contents.items.first.value. | 
| 257 | 
            +
                    expect(items.first.contents.items.size).to eq 1
         | 
| 258 | 
            +
                    expect(items.first.contents.items.first).to be_a(FlavourSaver::OutputNode)
         | 
| 259 | 
            +
                    expect(items.first.contents.items.first.value).to eq 'hello'
         | 
| 260 260 | 
             
                  end
         | 
| 261 261 | 
             
                end
         | 
| 262 262 | 
             
              end
         | 
| @@ -265,7 +265,7 @@ describe FlavourSaver::Parser do | |
| 265 265 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{/foo}}')) }
         | 
| 266 266 |  | 
| 267 267 | 
             
                it 'raises a syntax error' do
         | 
| 268 | 
            -
                   | 
| 268 | 
            +
                  expect { subject }.to raise_error(RLTK::NotInLanguage)
         | 
| 269 269 | 
             
                end
         | 
| 270 270 | 
             
              end
         | 
| 271 271 |  | 
| @@ -273,7 +273,7 @@ describe FlavourSaver::Parser do | |
| 273 273 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}')) }
         | 
| 274 274 |  | 
| 275 275 | 
             
                it 'raises a syntax error' do
         | 
| 276 | 
            -
                   | 
| 276 | 
            +
                  expect { subject }.to raise_error(RLTK::NotInLanguage)
         | 
| 277 277 | 
             
                end
         | 
| 278 278 | 
             
              end
         | 
| 279 279 |  | 
| @@ -281,7 +281,7 @@ describe FlavourSaver::Parser do | |
| 281 281 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{foo}}\n")) }
         | 
| 282 282 |  | 
| 283 283 | 
             
                it 'has a block start and end' do
         | 
| 284 | 
            -
                  items.map(&:class). | 
| 284 | 
            +
                  expect(items.map(&:class)).to eq [ FlavourSaver::ExpressionNode, FlavourSaver::OutputNode ]
         | 
| 285 285 | 
             
                end
         | 
| 286 286 | 
             
              end
         | 
| 287 287 |  | 
| @@ -289,7 +289,7 @@ describe FlavourSaver::Parser do | |
| 289 289 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}{{#bar}}{{/foo}}')) }
         | 
| 290 290 |  | 
| 291 291 | 
             
                it 'raises a syntax error' do
         | 
| 292 | 
            -
                   | 
| 292 | 
            +
                  expect { subject }.to raise_error(FlavourSaver::Parser::UnbalancedBlockError)
         | 
| 293 293 | 
             
                end
         | 
| 294 294 | 
             
              end
         | 
| 295 295 |  | 
| @@ -297,7 +297,7 @@ describe FlavourSaver::Parser do | |
| 297 297 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo}}\n{{/foo}}")) }
         | 
| 298 298 |  | 
| 299 299 | 
             
                it "doesn't throw a NotInLanguage exception" do
         | 
| 300 | 
            -
                   | 
| 300 | 
            +
                  expect { subject }.to_not raise_error
         | 
| 301 301 | 
             
                end
         | 
| 302 302 | 
             
              end
         | 
| 303 303 |  | 
| @@ -308,8 +308,8 @@ describe FlavourSaver::Parser do | |
| 308 308 | 
             
                  let(:block) { subject.items.first }
         | 
| 309 309 |  | 
| 310 310 | 
             
                  it 'should contain another block' do
         | 
| 311 | 
            -
                    block.contents.items.size. | 
| 312 | 
            -
                    block.contents.items.first. | 
| 311 | 
            +
                    expect(block.contents.items.size).to eq 1
         | 
| 312 | 
            +
                    expect(block.contents.items.first).to be_a(FlavourSaver::BlockExpressionNode)
         | 
| 313 313 | 
             
                  end
         | 
| 314 314 | 
             
                end
         | 
| 315 315 | 
             
              end
         | 
| @@ -318,7 +318,7 @@ describe FlavourSaver::Parser do | |
| 318 318 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo bar 'baz'}}{{/foo}}")) }
         | 
| 319 319 |  | 
| 320 320 | 
             
                it "doesn't throw a NotInLanguage exception" do
         | 
| 321 | 
            -
                   | 
| 321 | 
            +
                  expect { subject }.to_not raise_error
         | 
| 322 322 | 
             
                end
         | 
| 323 323 | 
             
              end
         | 
| 324 324 |  | 
| @@ -326,25 +326,25 @@ describe FlavourSaver::Parser do | |
| 326 326 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo bar 'baz' }}{{/foo}}")) }
         | 
| 327 327 |  | 
| 328 328 | 
             
                it "doesn't throw a NotInLanguage exception" do
         | 
| 329 | 
            -
                   | 
| 329 | 
            +
                  expect { subject }.to_not raise_error
         | 
| 330 330 | 
             
                end
         | 
| 331 331 | 
             
              end
         | 
| 332 332 | 
             
              describe '' do
         | 
| 333 333 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('')) }
         | 
| 334 334 |  | 
| 335 335 | 
             
                it 'returns an empty template' do
         | 
| 336 | 
            -
                  items. | 
| 336 | 
            +
                  expect(items).to be_empty
         | 
| 337 337 | 
             
                end
         | 
| 338 338 | 
             
              end
         | 
| 339 339 | 
             
              describe '{{foo "bar" fred="wilma"}}' do
         | 
| 340 340 | 
             
                subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo "bar" fred="wilma"}}')) }
         | 
| 341 341 | 
             
                it 'calls the method "foo" with the "bar" and {:fred => "wilma"} as arguments' do
         | 
| 342 | 
            -
                  items.first.method.first. | 
| 343 | 
            -
                  items.first.method.first.name. | 
| 344 | 
            -
                  items.first.method.first.arguments.first. | 
| 345 | 
            -
                  items.first.method.first.arguments.first.value. | 
| 346 | 
            -
                  items.first.method.first.arguments.last. | 
| 347 | 
            -
                  items.first.method.first.arguments.last. | 
| 342 | 
            +
                  expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
         | 
| 343 | 
            +
                  expect(items.first.method.first.name).to eq 'foo'
         | 
| 344 | 
            +
                  expect(items.first.method.first.arguments.first).to be_a(FlavourSaver::StringNode)
         | 
| 345 | 
            +
                  expect(items.first.method.first.arguments.first.value).to eq 'bar'
         | 
| 346 | 
            +
                  expect(items.first.method.first.arguments.last).to be_a(Hash)
         | 
| 347 | 
            +
                  expect(items.first.method.first.arguments.last).to eq({ :fred => FlavourSaver::StringNode.new('wilma') })
         | 
| 348 348 | 
             
                end
         | 
| 349 349 | 
             
              end
         | 
| 350 350 | 
             
            end
         | 
| @@ -12,7 +12,7 @@ describe FlavourSaver::Runtime do | |
| 12 12 | 
             
                  let(:template) { "hello world" }
         | 
| 13 13 |  | 
| 14 14 | 
             
                  it "concatenates all the nodes items together" do
         | 
| 15 | 
            -
                    subject.evaluate_node(ast). | 
| 15 | 
            +
                    expect(subject.evaluate_node(ast)).to eq 'hello world'
         | 
| 16 16 | 
             
                  end
         | 
| 17 17 | 
             
                end
         | 
| 18 18 |  | 
| @@ -21,7 +21,7 @@ describe FlavourSaver::Runtime do | |
| 21 21 |  | 
| 22 22 | 
             
                  it "returns the value of OutputNodes" do
         | 
| 23 23 | 
             
                    node = ast.items.first
         | 
| 24 | 
            -
                    subject.evaluate_node(node). | 
| 24 | 
            +
                    expect(subject.evaluate_node(node)).to eq 'hello world'
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| @@ -30,7 +30,7 @@ describe FlavourSaver::Runtime do | |
| 30 30 | 
             
                  let(:node)     { ast.items.select { |n| n.class == FlavourSaver::ExpressionNode }.first.method.first.arguments.first }
         | 
| 31 31 |  | 
| 32 32 | 
             
                  it 'returns the value of the string' do
         | 
| 33 | 
            -
                    subject.evaluate_node(node). | 
| 33 | 
            +
                    expect(subject.evaluate_node(node)).to eq 'WAT'
         | 
| 34 34 | 
             
                  end
         | 
| 35 35 | 
             
                end
         | 
| 36 36 |  | 
| @@ -39,13 +39,13 @@ describe FlavourSaver::Runtime do | |
| 39 39 | 
             
                  let (:template) { "{{foo}}" }
         | 
| 40 40 |  | 
| 41 41 | 
             
                  it 'calls evaluate_node with the node' do
         | 
| 42 | 
            -
                    subject. | 
| 42 | 
            +
                    expect(subject).to receive(:evaluate_expression).with(node)
         | 
| 43 43 | 
             
                    subject.evaluate_node(node)
         | 
| 44 44 | 
             
                  end
         | 
| 45 45 |  | 
| 46 46 | 
             
                  it 'should HTML escape the output' do
         | 
| 47 | 
            -
                    context. | 
| 48 | 
            -
                    subject.evaluate_node(node). | 
| 47 | 
            +
                    expect(context).to receive(:foo).and_return("<html>LOL</html>")
         | 
| 48 | 
            +
                    expect(subject.evaluate_node(node)).to eq '<html>LOL</html>'
         | 
| 49 49 | 
             
                  end
         | 
| 50 50 | 
             
                end
         | 
| 51 51 |  | 
| @@ -54,8 +54,8 @@ describe FlavourSaver::Runtime do | |
| 54 54 | 
             
                  let (:template) { "{{{foo}}}" }
         | 
| 55 55 |  | 
| 56 56 | 
             
                  it 'should not HTML escape the output' do
         | 
| 57 | 
            -
                    context. | 
| 58 | 
            -
                    subject.evaluate_node(node). | 
| 57 | 
            +
                    expect(context).to receive(:foo).and_return("<html>LOL</html>")
         | 
| 58 | 
            +
                    expect(subject.evaluate_node(node)).to eq '<html>LOL</html>'
         | 
| 59 59 | 
             
                  end
         | 
| 60 60 | 
             
                end
         | 
| 61 61 |  | 
| @@ -64,7 +64,7 @@ describe FlavourSaver::Runtime do | |
| 64 64 | 
             
                  let(:node)     { ast.items.select { |n| n.class == FlavourSaver::CommentNode }.first }
         | 
| 65 65 |  | 
| 66 66 | 
             
                  it 'should return zilch' do
         | 
| 67 | 
            -
                    subject.evaluate_node(node). | 
| 67 | 
            +
                    expect(subject.evaluate_node(node)).to eq ''
         | 
| 68 68 | 
             
                  end
         | 
| 69 69 | 
             
                end
         | 
| 70 70 |  | 
| @@ -72,8 +72,8 @@ describe FlavourSaver::Runtime do | |
| 72 72 | 
             
                  let(:template) { "{{#foo}}bar{{/foo}}baz" }
         | 
| 73 73 |  | 
| 74 74 | 
             
                  it 'snatches up the block contents and skips them from evaluation' do
         | 
| 75 | 
            -
                    context. | 
| 76 | 
            -
                    subject.evaluate_node(ast). | 
| 75 | 
            +
                    allow(context).to receive(:foo)
         | 
| 76 | 
            +
                    expect(subject.evaluate_node(ast)).to eq 'baz'
         | 
| 77 77 | 
             
                  end
         | 
| 78 78 | 
             
                end
         | 
| 79 79 | 
             
              end
         | 
| @@ -86,8 +86,8 @@ describe FlavourSaver::Runtime do | |
| 86 86 | 
             
                  let (:template) { "{{foo}}" }
         | 
| 87 87 |  | 
| 88 88 | 
             
                  it 'calls the method and return the result' do
         | 
| 89 | 
            -
                    context. | 
| 90 | 
            -
                    subject.evaluate_expression(expr). | 
| 89 | 
            +
                    expect(context).to receive(:foo).and_return('foo result')
         | 
| 90 | 
            +
                    expect(subject.evaluate_expression(expr)).to eq 'foo result'
         | 
| 91 91 | 
             
                  end
         | 
| 92 92 | 
             
                end
         | 
| 93 93 |  | 
| @@ -95,8 +95,8 @@ describe FlavourSaver::Runtime do | |
| 95 95 | 
             
                  let(:template) { "{{hello \"world\"}}" }
         | 
| 96 96 |  | 
| 97 97 | 
             
                  it 'calls the method with the arguments and return the result' do
         | 
| 98 | 
            -
                    context. | 
| 99 | 
            -
                    subject.evaluate_expression(expr). | 
| 98 | 
            +
                    expect(context).to receive(:hello).with("world").and_return("hello world")
         | 
| 99 | 
            +
                    expect(subject.evaluate_expression(expr)).to eq 'hello world'
         | 
| 100 100 | 
             
                  end
         | 
| 101 101 | 
             
                end
         | 
| 102 102 |  | 
| @@ -104,9 +104,9 @@ describe FlavourSaver::Runtime do | |
| 104 104 | 
             
                  let(:template) { "{{hello world}}" }
         | 
| 105 105 |  | 
| 106 106 | 
             
                  it 'calls hello & world on the context and return the result' do
         | 
| 107 | 
            -
                    context. | 
| 108 | 
            -
                    context. | 
| 109 | 
            -
                    subject.evaluate_expression(expr). | 
| 107 | 
            +
                    expect(context).to receive(:world).and_return('world')
         | 
| 108 | 
            +
                    expect(context).to receive(:hello).with('world').and_return('hello world')
         | 
| 109 | 
            +
                    expect(subject.evaluate_expression(expr)).to eq 'hello world'
         | 
| 110 110 | 
             
                  end
         | 
| 111 111 | 
             
                end
         | 
| 112 112 |  | 
| @@ -114,10 +114,10 @@ describe FlavourSaver::Runtime do | |
| 114 114 | 
             
                  let(:template) { "{{hello (there world)}}" }
         | 
| 115 115 |  | 
| 116 116 | 
             
                  it 'calls there & world first, then passes off to hello' do
         | 
| 117 | 
            -
                    context. | 
| 118 | 
            -
                    context. | 
| 119 | 
            -
                    context. | 
| 120 | 
            -
                    subject.evaluate_expression(expr). | 
| 117 | 
            +
                    expect(context).to receive(:world).and_return('world')
         | 
| 118 | 
            +
                    expect(context).to receive(:there).with('world').and_return('there world')
         | 
| 119 | 
            +
                    expect(context).to receive(:hello).with('there world').and_return('hello there world')
         | 
| 120 | 
            +
                    expect(subject.evaluate_expression(expr)).to eq 'hello there world'
         | 
| 121 121 | 
             
                  end
         | 
| 122 122 | 
             
                end
         | 
| 123 123 |  | 
| @@ -125,8 +125,8 @@ describe FlavourSaver::Runtime do | |
| 125 125 | 
             
                  let(:template) { "{{hello.world}}" }
         | 
| 126 126 |  | 
| 127 127 | 
             
                  it 'calls world on the result of hello' do
         | 
| 128 | 
            -
                    context. | 
| 129 | 
            -
                    subject.evaluate_expression(expr). | 
| 128 | 
            +
                    allow(context).to receive_message_chain(:hello, :world).and_return('hello world')
         | 
| 129 | 
            +
                    expect(subject.evaluate_expression(expr)).to eq 'hello world'
         | 
| 130 130 | 
             
                  end
         | 
| 131 131 | 
             
                end
         | 
| 132 132 |  | 
| @@ -134,8 +134,8 @@ describe FlavourSaver::Runtime do | |
| 134 134 | 
             
                  let(:template) { "{{[WAT]}}" }
         | 
| 135 135 |  | 
| 136 136 | 
             
                  it 'indexes the context with WAT' do
         | 
| 137 | 
            -
                    context. | 
| 138 | 
            -
                    subject.evaluate_expression(expr). | 
| 137 | 
            +
                    expect(context).to receive(:[]).with('WAT').and_return 'w00t'
         | 
| 138 | 
            +
                    expect(subject.evaluate_expression(expr)).to eq 'w00t'
         | 
| 139 139 | 
             
                  end
         | 
| 140 140 | 
             
                end
         | 
| 141 141 |  | 
| @@ -144,11 +144,11 @@ describe FlavourSaver::Runtime do | |
| 144 144 |  | 
| 145 145 | 
             
                  it 'indexes the result of hello and calls world on it' do
         | 
| 146 146 | 
             
                    world = double(:world)
         | 
| 147 | 
            -
                    world. | 
| 147 | 
            +
                    expect(world).to receive(:world).and_return('vr00m')
         | 
| 148 148 | 
             
                    hash = double(:hash)
         | 
| 149 | 
            -
                    hash. | 
| 150 | 
            -
                    context. | 
| 151 | 
            -
                    subject.evaluate_expression(expr). | 
| 149 | 
            +
                    expect(hash).to receive(:[]).with('WAT').and_return(world)
         | 
| 150 | 
            +
                    expect(context).to receive(:hello).and_return(hash)
         | 
| 151 | 
            +
                    expect(subject.evaluate_expression(expr)).to eq 'vr00m'
         | 
| 152 152 | 
             
                  end
         | 
| 153 153 | 
             
                end
         | 
| 154 154 |  | 
| @@ -156,7 +156,7 @@ describe FlavourSaver::Runtime do | |
| 156 156 | 
             
                  let (:template) { "{{../foo}}" }
         | 
| 157 157 |  | 
| 158 158 | 
             
                  it 'raises an error' do
         | 
| 159 | 
            -
                     | 
| 159 | 
            +
                    expect { subject.evaluate_expression(expr) }.to raise_error(FlavourSaver::UnknownContextException)
         | 
| 160 160 | 
             
                  end
         | 
| 161 161 | 
             
                end
         | 
| 162 162 |  | 
| @@ -164,7 +164,7 @@ describe FlavourSaver::Runtime do | |
| 164 164 | 
             
                  let (:template) { '{{foo bar="baz"}}' }
         | 
| 165 165 |  | 
| 166 166 | 
             
                  it 'receives the argument as a hash' do
         | 
| 167 | 
            -
                    context. | 
| 167 | 
            +
                    expect(context).to receive(:foo).with({:bar => 'baz'})
         | 
| 168 168 | 
             
                    subject.evaluate_expression(expr)
         | 
| 169 169 | 
             
                  end
         | 
| 170 170 | 
             
                end
         | 
| @@ -173,8 +173,8 @@ describe FlavourSaver::Runtime do | |
| 173 173 | 
             
                  let (:template) { "{{foo bar=baz}}" }
         | 
| 174 174 |  | 
| 175 175 | 
             
                  it 'calls the value and returns it\'s result in the hash' do
         | 
| 176 | 
            -
                    context. | 
| 177 | 
            -
                    context. | 
| 176 | 
            +
                    expect(context).to receive(:baz).and_return('OMGLOLWAT')
         | 
| 177 | 
            +
                    expect(context).to receive(:foo).with({:bar => 'OMGLOLWAT'})
         | 
| 178 178 | 
             
                    subject.evaluate_expression(expr)
         | 
| 179 179 | 
             
                  end
         | 
| 180 180 | 
             
                end
         | 
| @@ -186,15 +186,15 @@ describe FlavourSaver::Runtime do | |
| 186 186 | 
             
                let(:block)    { ast.items.first }
         | 
| 187 187 |  | 
| 188 188 | 
             
                it 'creates a new runtime' do
         | 
| 189 | 
            -
                  subject. | 
| 190 | 
            -
                  context. | 
| 189 | 
            +
                  expect(subject).to receive(:create_child_runtime)
         | 
| 190 | 
            +
                  allow(context).to receive(:foo)
         | 
| 191 191 | 
             
                  subject.evaluate_block(block, context)
         | 
| 192 192 | 
             
                end
         | 
| 193 193 | 
             
              end
         | 
| 194 194 |  | 
| 195 195 | 
             
              describe '#create_child_runtime' do
         | 
| 196 196 | 
             
                it 'creates a new runtime' do
         | 
| 197 | 
            -
                  subject.create_child_runtime([]). | 
| 197 | 
            +
                  expect(subject.create_child_runtime([])).to be_a(FlavourSaver::Runtime)
         | 
| 198 198 | 
             
                end
         | 
| 199 199 | 
             
              end
         | 
| 200 200 |  |