@@ -83,10 +83,12 @@ async def test_get_amount_and_label(
8383def _make_seat_price (
8484 tiers : list [dict [str , Any ]],
8585 seat_tier_type : SeatTierType = SeatTierType .volume ,
86+ product_name : str = "My Product" ,
8687) -> ProductPriceSeatUnit :
8788 return ProductPriceSeatUnit (
8889 seat_tiers = {"seat_tier_type" : seat_tier_type , "tiers" : tiers },
8990 price_currency = "usd" ,
91+ product = Product (name = product_name ),
9092 )
9193
9294
@@ -197,3 +199,120 @@ def test_free_first_tier_then_paid(self) -> None:
197199 assert price .calculate_amount (5 ) == 0
198200 assert price .calculate_amount (8 ) == 3 * 1000
199201 assert price .calculate_amount (15 ) == 10 * 1000
202+
203+
204+ class TestVolumePricingLabel :
205+ def test_single_tier_no_range_shown (self ) -> None :
206+ price = _make_seat_price (
207+ [{"min_seats" : 1 , "max_seats" : None , "price_per_seat" : 500 }],
208+ SeatTierType .volume ,
209+ )
210+ amount , label = price .get_amount_and_label (5 )
211+ assert amount == 2500
212+ assert label == "My Product (5 seats)\n 5 seats × $5.00/seat"
213+
214+ def test_singular_seat (self ) -> None :
215+ price = _make_seat_price (MULTI_TIER , SeatTierType .volume )
216+ amount , label = price .get_amount_and_label (1 )
217+ assert amount == 1000
218+ assert label == "My Product (1 seat)\n 1 seat × $10.00/seat (1–10 seats tier)"
219+
220+ def test_first_tier (self ) -> None :
221+ price = _make_seat_price (MULTI_TIER , SeatTierType .volume )
222+ amount , label = price .get_amount_and_label (5 )
223+ assert amount == 5000
224+ assert label == "My Product (5 seats)\n 5 seats × $10.00/seat (1–10 seats tier)"
225+
226+ def test_second_tier (self ) -> None :
227+ price = _make_seat_price (MULTI_TIER , SeatTierType .volume )
228+ amount , label = price .get_amount_and_label (25 )
229+ assert amount == 20_000
230+ assert (
231+ label == "My Product (25 seats)\n 25 seats × $8.00/seat (11–50 seats tier)"
232+ )
233+
234+ def test_open_ended_last_tier (self ) -> None :
235+ price = _make_seat_price (MULTI_TIER , SeatTierType .volume )
236+ amount , label = price .get_amount_and_label (60 )
237+ assert amount == 36_000
238+ assert label == "My Product (60 seats)\n 60 seats × $6.00/seat (51+ seats tier)"
239+
240+ def test_free_tier (self ) -> None :
241+ price = _make_seat_price (
242+ [{"min_seats" : 1 , "max_seats" : None , "price_per_seat" : 0 }],
243+ SeatTierType .volume ,
244+ )
245+ amount , label = price .get_amount_and_label (10 )
246+ assert amount == 0
247+ assert label == "My Product (10 seats)\n 10 seats × $0.00/seat"
248+
249+
250+ class TestGraduatedPricingLabel :
251+ def test_single_tier_no_range_shown (self ) -> None :
252+ price = _make_seat_price (
253+ [{"min_seats" : 1 , "max_seats" : None , "price_per_seat" : 500 }],
254+ SeatTierType .graduated ,
255+ )
256+ amount , label = price .get_amount_and_label (5 )
257+ assert amount == 2500
258+ assert label == "My Product (5 seats)\n 5 seats × $5.00/seat"
259+
260+ def test_singular_seat (self ) -> None :
261+ price = _make_seat_price (MULTI_TIER , SeatTierType .graduated )
262+ amount , label = price .get_amount_and_label (1 )
263+ assert amount == 1000
264+ assert label == "My Product (1 seat)\n 1 seat × $10.00/seat (1–10 seats tier)"
265+
266+ def test_within_first_tier (self ) -> None :
267+ price = _make_seat_price (MULTI_TIER , SeatTierType .graduated )
268+ amount , label = price .get_amount_and_label (5 )
269+ assert amount == 5000
270+ assert label == "My Product (5 seats)\n 5 seats × $10.00/seat (1–10 seats tier)"
271+
272+ def test_spans_two_tiers (self ) -> None :
273+ price = _make_seat_price (MULTI_TIER , SeatTierType .graduated )
274+ amount , label = price .get_amount_and_label (15 )
275+ assert amount == 10 * 1000 + 5 * 800
276+ assert label == (
277+ "My Product (15 seats)\n "
278+ "10 seats × $10.00/seat (1–10 seats tier)\n "
279+ "+ 5 seats × $8.00/seat (11–50 seats tier)"
280+ )
281+
282+ def test_spans_all_tiers (self ) -> None :
283+ price = _make_seat_price (MULTI_TIER , SeatTierType .graduated )
284+ amount , label = price .get_amount_and_label (100 )
285+ assert amount == 10 * 1000 + 40 * 800 + 50 * 600
286+ assert label == (
287+ "My Product (100 seats)\n "
288+ "10 seats × $10.00/seat (1–10 seats tier)\n "
289+ "+ 40 seats × $8.00/seat (11–50 seats tier)\n "
290+ "+ 50 seats × $6.00/seat (51+ seats tier)"
291+ )
292+
293+ def test_one_seat_into_last_tier (self ) -> None :
294+ price = _make_seat_price (MULTI_TIER , SeatTierType .graduated )
295+ amount , label = price .get_amount_and_label (51 )
296+ assert amount == 10 * 1000 + 40 * 800 + 1 * 600
297+ assert label == (
298+ "My Product (51 seats)\n "
299+ "10 seats × $10.00/seat (1–10 seats tier)\n "
300+ "+ 40 seats × $8.00/seat (11–50 seats tier)\n "
301+ "+ 1 seat × $6.00/seat (51+ seats tier)"
302+ )
303+
304+ def test_free_first_tier_then_paid (self ) -> None :
305+ price = _make_seat_price (
306+ [
307+ {"min_seats" : 1 , "max_seats" : 5 , "price_per_seat" : 0 },
308+ {"min_seats" : 6 , "max_seats" : None , "price_per_seat" : 1000 },
309+ ],
310+ SeatTierType .graduated ,
311+ )
312+ amount , label = price .get_amount_and_label (8 )
313+ assert amount == 3 * 1000
314+ assert label == (
315+ "My Product (8 seats)\n "
316+ "5 seats × $0.00/seat (1–5 seats tier)\n "
317+ "+ 3 seats × $10.00/seat (6+ seats tier)"
318+ )
0 commit comments