ingreedy 0.0.7 → 0.0.8

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.
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe Ingreedy::Rationalizer do
5
+ subject { described_class }
6
+
7
+ context "with an integer and a fraction" do
8
+ it "gives back an improper rational" do
9
+ rational = subject.rationalize(integer: "1", fraction: "1/2")
10
+ expect(rational).to eq("3/2".to_r)
11
+ end
12
+ end
13
+
14
+ context "with a fraction" do
15
+ it "gives back a rational" do
16
+ expect(subject.rationalize(fraction: "1/2")).to eq("1/2".to_r)
17
+ end
18
+ end
19
+
20
+ context "with a vulgar fraction" do
21
+ it "gives back a rational" do
22
+ expect(subject.rationalize(fraction: "¼")).to eq("1/4".to_r)
23
+ end
24
+ end
25
+
26
+ context "with an integer" do
27
+ it "gives back a rational" do
28
+ expect(subject.rationalize(integer: "2")).to eq("2".to_r)
29
+ end
30
+ end
31
+
32
+ context "with a float" do
33
+ it "gives back a rational" do
34
+ expect(subject.rationalize(float: "0.3")).to eq("3/10".to_r)
35
+ end
36
+ end
37
+
38
+ context "with a european float" do
39
+ it "gives back a rational" do
40
+ expect(subject.rationalize(float: "0,4")).to eq("4/10".to_r)
41
+ end
42
+ end
43
+
44
+ context "with an english digit" do
45
+ it "gives back a rational" do
46
+ expect(subject.rationalize(word: "one")).to eq("1".to_r)
47
+ end
48
+ end
49
+
50
+ context "with the word a or an" do
51
+ it "gives back a rational" do
52
+ expect(subject.rationalize(word: "a")).to eq("1".to_r)
53
+ expect(subject.rationalize(word: "AN")).to eq("1".to_r)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe Ingreedy::UnitVariationMapper do
4
+ subject { described_class }
5
+
6
+ describe ".unit_from_variation" do
7
+ context "uppercased variation" do
8
+ it "gives back the correct unit as a symbol" do
9
+ expect(subject.unit_from_variation("TSP")).to eq(:teaspoon)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,378 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe Ingreedy do
5
+ context "amount parsing" do
6
+ {
7
+ "1 cup flour" => 1,
8
+ "one cup flour" => 1,
9
+ "1 1/2 cups flour" => "3/2",
10
+ "¼ cups flour" => "1/4",
11
+ "1 ½ cups flour" => "3/2",
12
+ "1½ cups flour" => "3/2",
13
+ "1.0 cup flour" => 1,
14
+ "1.5 cups flour" => "3/2",
15
+ "1,5 cups flour" => "3/2",
16
+ "1 2/3 cups flour" => "5/3",
17
+ "1 (28 ounce) can crushed tomatoes" => 1,
18
+ "2 (28 ounce) can crushed tomatoes" => 2,
19
+ "3 28 ounce can crushed tomatoes" => 3,
20
+ "one 28 ounce can crushed tomatoes" => 1,
21
+ "two five-ounce can crushed tomatoes" => 2,
22
+ "two 28 ounce cans crushed tomatoes" => 2,
23
+ "three 28 ounce cans crushed tomatoes" => 3,
24
+ "1/2 cups flour" => "1/2",
25
+ ".25 cups flour" => "1/4",
26
+ "12oz tequila" => 12,
27
+ "1 banana" => 1,
28
+ }.each do |query, expected|
29
+ it "parses the correct amount as a rational" do
30
+ expect(Ingreedy.parse(query)).to parse_the_amount(expected.to_r)
31
+ end
32
+ end
33
+ end
34
+
35
+ context "unit parsing" do
36
+ context "(english)" do
37
+ end
38
+ context "(metric)" do
39
+ end
40
+ context "(nonstandard)" do
41
+ end
42
+ end
43
+
44
+ it "parses a simple example correctly" do
45
+ result = Ingreedy.parse("1 lb potatoes")
46
+
47
+ expect(result.amount).to eq(1)
48
+ expect(result.unit).to eq(:pound)
49
+ expect(result.ingredient).to eq("potatoes")
50
+ end
51
+ end
52
+
53
+ describe "english units" do
54
+ context "abbreviated" do
55
+ {
56
+ "1 c flour" => :cup,
57
+ "1 c. flour" => :cup,
58
+ "1 fl oz flour" => :fluid_ounce,
59
+ "1 fl. oz. flour" => :fluid_ounce,
60
+ "2 gal flour" => :gallon,
61
+ "2 gal. flour" => :gallon,
62
+ "1 ounce flour" => :ounce,
63
+ "2 ounces flour" => :ounce,
64
+ "1 oz flour" => :ounce,
65
+ "1 oz. flour" => :ounce,
66
+ "2 pt flour" => :pint,
67
+ "2 pt. flour" => :pint,
68
+ "1 lb flour" => :pound,
69
+ "1 lb. flour" => :pound,
70
+ "1 pound flour" => :pound,
71
+ "2 pounds flour" => :pound,
72
+ "2 qt flour" => :quart,
73
+ "2 qt. flour" => :quart,
74
+ "2 qts flour" => :quart,
75
+ "2 qts. flour" => :quart,
76
+ "2 tbsp flour" => :tablespoon,
77
+ "2 tbsp. flour" => :tablespoon,
78
+ "2 Tbs flour" => :tablespoon,
79
+ "2 Tbs. flour" => :tablespoon,
80
+ "2 T flour" => :tablespoon,
81
+ "2 T. flour" => :tablespoon,
82
+ "2 tsp flour" => :teaspoon,
83
+ "2 tsp. flour" => :teaspoon,
84
+ "2 t flour" => :teaspoon,
85
+ "2 t. flour" => :teaspoon,
86
+ "12oz tequila" => :ounce,
87
+ "2 TSP flour" => :teaspoon,
88
+ "1 LB flour" => :pound,
89
+ "1 tSP sugar" => :teaspoon,
90
+ }.each do |query, expected|
91
+ it "parses the units correctly" do
92
+ expect(Ingreedy.parse(query)).to parse_the_unit(expected)
93
+ end
94
+ end
95
+ end
96
+
97
+ context "long form" do
98
+ {
99
+ "1 cup flour" => :cup,
100
+ "2 cups flour" => :cup,
101
+ "1 fluid ounce flour" => :fluid_ounce,
102
+ "2 fluid ounces flour" => :fluid_ounce,
103
+ "2 gallon flour" => :gallon,
104
+ "2 gallons flour" => :gallon,
105
+ "2 pint flour" => :pint,
106
+ "2 pints flour" => :pint,
107
+ "1 quart flour" => :quart,
108
+ "2 quarts flour" => :quart,
109
+ "2 tablespoon flour" => :tablespoon,
110
+ "2 tablespoons flour" => :tablespoon,
111
+ "2 teaspoon flour" => :teaspoon,
112
+ "2 teaspoons flour" => :teaspoon,
113
+ }.each do |query, expected|
114
+ it "parses the units correctly" do
115
+ expect(Ingreedy.parse(query)).to parse_the_unit(expected)
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ describe "metric units" do
122
+ context "abbreviated" do
123
+ {
124
+ "1 g flour" => :gram,
125
+ "1 g. flour" => :gram,
126
+ "1 gr flour" => :gram,
127
+ "1 gr. flour" => :gram,
128
+ "1 kg flour" => :kilogram,
129
+ "1 kg. flour" => :kilogram,
130
+ "1 l water" => :liter,
131
+ "1 l. water" => :liter,
132
+ "1 mg water" => :milligram,
133
+ "1 mg. water" => :milligram,
134
+ "1 ml water" => :milliliter,
135
+ "1 ml. water" => :milliliter,
136
+ }.each do |query, expected|
137
+ it "parses the units correctly" do
138
+ expect(Ingreedy.parse(query)).to parse_the_unit(expected)
139
+ end
140
+ end
141
+ end
142
+
143
+ context "long form" do
144
+ {
145
+ "1 gram flour" => :gram,
146
+ "2 grams flour" => :gram,
147
+ "1 kilogram flour" => :kilogram,
148
+ "2 kilograms flour" => :kilogram,
149
+ "1 liter water" => :liter,
150
+ "2 liters water" => :liter,
151
+ "1 milligram water" => :milligram,
152
+ "2 milligrams water" => :milligram,
153
+ "1 milliliter water" => :milliliter,
154
+ "2 milliliters water" => :milliliter,
155
+ }.each do |query, expected|
156
+ it "parses the units correctly" do
157
+ expect(Ingreedy.parse(query)).to parse_the_unit(expected)
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ describe "nonstandard units" do
164
+ {
165
+ "1 pinch pepper" => :pinch,
166
+ "2 pinches pepper" => :pinch,
167
+ "1 dash salt" => :dash,
168
+ "2 dashes salt" => :dash,
169
+ "1 touch hot sauce" => :touch,
170
+ "2 touches hot sauce" => :touch,
171
+ "1 handful rice" => :handful,
172
+ "2 handfuls rice" => :handful,
173
+ "1 stick of butter" => :stick,
174
+ "2 cloves of garlic" => :clove,
175
+ "1 can of tomatoes" => :can,
176
+ }.each do |query, expected|
177
+ it "parses the units correctly" do
178
+ expect(Ingreedy.parse(query)).to parse_the_unit(expected)
179
+ end
180
+ end
181
+ end
182
+
183
+ describe "without units" do
184
+ it "parses correctly" do
185
+ result = Ingreedy.parse "3 eggs, lightly beaten"
186
+
187
+ expect(result.amount).to eq(3)
188
+ expect(result.unit).to be_nil
189
+ expect(result.ingredient).to eq("eggs, lightly beaten")
190
+ end
191
+ end
192
+
193
+ describe "container as part of quantity" do
194
+ it "parses correctly" do
195
+ result = Ingreedy.parse "160g (2 cans) of tomatoes"
196
+
197
+ expect(result.amount).to eq(160)
198
+ expect(result.unit).to eq(:gram)
199
+ expect(result.container_amount).to eq(2)
200
+ expect(result.container_unit).to eq(:can)
201
+ expect(result.ingredient).to eq("tomatoes")
202
+ end
203
+
204
+ context "on language without preposition" do
205
+ before(:all) do
206
+ Ingreedy.dictionaries[:id] = {
207
+ units: {
208
+ can: ["kaleng"],
209
+ gram: ["g"],
210
+ to_taste: ["secukupnya"],
211
+ },
212
+ }
213
+ Ingreedy.locale = :id
214
+ end
215
+
216
+ after(:all) do
217
+ Ingreedy.locale = nil
218
+ end
219
+
220
+ it "parses correctly" do
221
+ result = Ingreedy.parse "160g (2 kaleng) tomat"
222
+
223
+ expect(result.amount).to eq(160)
224
+ expect(result.unit).to eq(:gram)
225
+ expect(result.container_amount).to eq(2)
226
+ expect(result.container_unit).to eq(:can)
227
+ expect(result.ingredient).to eq("tomat")
228
+ end
229
+ end
230
+ end
231
+
232
+ describe "with 'a' as quantity and preposition 'of'" do
233
+ it "parses correctly" do
234
+ result = Ingreedy.parse "a dash of ginger"
235
+
236
+ expect(result.amount).to eq(1)
237
+ expect(result.unit).to eq(:dash)
238
+ expect(result.ingredient).to eq("ginger")
239
+ end
240
+ end
241
+
242
+ describe "with 'reverse format'" do
243
+ it "works with words containing a 'word digit'" do
244
+ result = Ingreedy.parse "salt 200g"
245
+
246
+ expect(result.amount).to eq(200)
247
+ expect(result.unit).to eq(:gram)
248
+ expect(result.ingredient).to eq("salt")
249
+ end
250
+
251
+ it "works with words ending on a 'word digit'" do
252
+ result = Ingreedy.parse "quinoa 200g"
253
+
254
+ expect(result.amount).to eq(200)
255
+ expect(result.unit).to eq(:gram)
256
+ expect(result.ingredient).to eq("quinoa")
257
+ end
258
+
259
+ it "works with approximate quantities" do
260
+ result = Ingreedy.parse "salt to taste"
261
+
262
+ expect(result.ingredient).to eq("salt")
263
+ expect(result.amount).to be_nil
264
+ expect(result.unit).to eq(:to_taste)
265
+ end
266
+ end
267
+
268
+ describe "Given a range" do
269
+ it "works with simple ranges" do
270
+ result = Ingreedy.parse "1-2 tbsp salt"
271
+
272
+ expect(result.amount).to eq([1, 2])
273
+ expect(result.unit).to eq(:tablespoon)
274
+ expect(result.ingredient).to eq("salt")
275
+ end
276
+
277
+ it "works with spaces" do
278
+ result = Ingreedy.parse "1 - 2 tbsp salt"
279
+
280
+ expect(result.amount).to eq([1, 2])
281
+ expect(result.unit).to eq(:tablespoon)
282
+ expect(result.ingredient).to eq("salt")
283
+ end
284
+ end
285
+
286
+ describe "parsing in language with no prepositions" do
287
+ before(:all) do
288
+ Ingreedy.dictionaries[:id] = {
289
+ units: {
290
+ gram: ["g"],
291
+ to_taste: ["secukupnya"],
292
+ },
293
+ }
294
+ Ingreedy.locale = :id
295
+ end
296
+
297
+ after(:all) do
298
+ Ingreedy.locale = nil
299
+ end
300
+
301
+ it "parses correctly" do
302
+ result = Ingreedy.parse "garam secukupnya"
303
+
304
+ expect(result.amount).to be_nil
305
+ expect(result.unit).to eq(:to_taste)
306
+ expect(result.ingredient).to eq("garam")
307
+ end
308
+ end
309
+
310
+ describe "custom dictionaries" do
311
+ context "using Ingreedy.locale=" do
312
+ before(:all) do
313
+ Ingreedy.dictionaries[:fr] = {
314
+ numbers: { "une" => 1 },
315
+ prepositions: ["de"],
316
+ units: { dash: ["pincee"] },
317
+ }
318
+ Ingreedy.locale = :fr
319
+ end
320
+
321
+ after(:all) do
322
+ Ingreedy.locale = nil
323
+ end
324
+
325
+ it "parses correctly" do
326
+ result = Ingreedy.parse "une pincee de sucre"
327
+
328
+ expect(result.amount).to eq(1)
329
+ expect(result.unit).to eq(:dash)
330
+ expect(result.ingredient).to eq("sucre")
331
+ end
332
+ end
333
+
334
+ context "using I18n.locale" do
335
+ before(:each) do
336
+ Ingreedy.dictionaries[:de] = { units: { dash: ["prise"] } }
337
+ stub_const "I18n", double("I18n", locale: :de)
338
+ end
339
+
340
+ it "parses correctly" do
341
+ result = Ingreedy.parse "1 Prise Zucker"
342
+
343
+ expect(result.amount).to eq(1)
344
+ expect(result.unit).to eq(:dash)
345
+ expect(result.ingredient).to eq("Zucker")
346
+ end
347
+ end
348
+
349
+ context "unknown locale" do
350
+ before(:all) do
351
+ Ingreedy.locale = :da
352
+ end
353
+
354
+ after(:all) do
355
+ Ingreedy.locale = nil
356
+ end
357
+
358
+ it "raises an informative exception" do
359
+ expect do
360
+ Ingreedy.parse "1 tsk salt"
361
+ end.to raise_exception("No dictionary found for :da locale")
362
+ end
363
+ end
364
+
365
+ context "Dictionary with no units" do
366
+ it "raises an informative exception" do
367
+ expect do
368
+ Ingreedy.dictionaries[:da] = {}
369
+ end.to raise_exception("No units found in dictionary")
370
+ end
371
+ end
372
+ end
373
+
374
+ describe "ingredient formatting" do
375
+ it "strips preceding or trailing whitespace" do
376
+ expect(Ingreedy.parse("1 cup flour ").ingredient).to eq("flour")
377
+ end
378
+ end
@@ -0,0 +1,34 @@
1
+ if ENV["CI"]
2
+ require "coveralls"
3
+ Coveralls.wear!
4
+ end
5
+
6
+ require "ingreedy"
7
+ require "parslet/rig/rspec"
8
+ require "pry"
9
+
10
+ RSpec::Matchers.define :parse_the_unit do |unit|
11
+ match do |ingreedy_output|
12
+ ingreedy_output.unit == unit
13
+ end
14
+ failure_message do |ingreedy_output|
15
+ <<-MSG
16
+ expected to parse the unit #{unit} from the query
17
+ '#{ingreedy_output.original_query}.'
18
+ got '#{ingreedy_output.unit}' instead
19
+ MSG
20
+ end
21
+ end
22
+
23
+ RSpec::Matchers.define :parse_the_amount do |amount|
24
+ match do |ingreedy_output|
25
+ ingreedy_output.amount == amount
26
+ end
27
+ failure_message do |ingreedy_output|
28
+ <<-MSG
29
+ expected to parse the amount #{amount} from the query
30
+ '#{ingreedy_output.original_query}.'
31
+ got '#{ingreedy_output.amount}' instead
32
+ MSG
33
+ end
34
+ end