ingreedy 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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