"""Test Film Transparency data utilities.""" from copy import copy from datetime import date from decimal import Decimal from unittest.mock import patch from api.utils import data as data_utils def test_round_data_amounts(): """Test round_data_amounts function.""" data = { 'foo': Decimal('123.4567890'), 'bar': Decimal('0.500')} # (precision, expected result) cases = [ (0, {'foo': Decimal('123'), 'bar': Decimal('0')}), (1, {'foo': Decimal('123.5'), 'bar': Decimal('0.5')}), (2, {'foo': Decimal('123.46'), 'bar': Decimal('0.50')})] for precision, expected_result in cases: input_data = copy(data) result = data_utils.round_data_amounts(input_data, precision) assert result == expected_result def test_round_data_amount(): """Test round_data_amount function.""" assert data_utils.round_data_amount( Decimal('123.4567890'), 2) == Decimal('123.46') assert data_utils.round_data_amount( Decimal('123.4567890'), 0) == Decimal('123') # passthrough assert data_utils.round_data_amount('123.4567890', 2) == '123.4567890' def test_process_amounts(): """Test process_amounts function.""" data = { 'foo': Decimal('123.4567890'), 'bar': Decimal('0.500'), 'total': Decimal('1')} # to test for expected overwriting # (precision, expected result) cases = [ (0, { 'foo': Decimal('123'), 'bar': Decimal('0'), 'total': Decimal('123')}), (1, { 'foo': Decimal('123.5'), 'bar': Decimal('0.5'), 'total': Decimal('124')}), (2, { 'foo': Decimal('123.46'), 'bar': Decimal('0.50'), 'total': Decimal('123.96')})] for precision, expected_result in cases: input_data = copy(data) result = data_utils.process_amounts(input_data, precision) assert result == expected_result def test_find_date_range(): """Test search for series data min and max date.""" params = { 'foo': { 'bucket 1': { date(11, 2, 3): None, date(14, 2, 3): None, date(15, 2, 3): None}, 'bucket 2': { date(15, 4, 3): None}, 'bucket 3': {}}, 'bar': { 'bucket 4': {date(20, 1, 2): None}}} expected = date(11, 2, 3), date(20, 1, 2) assert data_utils.find_date_range(params) == expected def test_find_date_range_no_data(): """Test search for series data min and max date if no series available.""" params = { 'foo': { 'bucket 1': {}, 'bucket 2': {}, 'bucket 3': {}}, 'bar': { 'bucket 4': {}}} expected = None assert data_utils.find_date_range(params) == expected def test_merge_bucket_series(): """Test merging a bucket's serial data to a dict.""" params = [ {'data_point': date(1, 2, 3), 'amount': Decimal(100)}, {'data_point': date(1, 2, 3), 'amount': Decimal(200)}, {'data_point': date(1, 2, 3), 'amount': Decimal(300)}, {'data_point': date(2, 2, 3), 'amount': Decimal(200)}, {'data_point': date(3, 2, 3), 'amount': Decimal(300)}, {'data_point': date(4, 2, 3), 'amount': Decimal(400)}, {'data_point': date(5, 2, 3), 'amount': Decimal(500)}, {'data_point': date(5, 2, 4), 'amount': None}] expected = { date(1, 2, 3): Decimal(600), date(2, 2, 3): Decimal(200), date(3, 2, 3): Decimal(300), date(4, 2, 3): Decimal(400), date(5, 2, 3): Decimal(500), date(5, 2, 4): Decimal(0)} assert data_utils.merge_bucket_series(params) == expected def test_hydrate_bucket(): """Test hydrating (filling in missing dates) of a bucket.""" params = { date(1, 1, 1): Decimal(600), date(1, 1, 3): Decimal(200), date(1, 1, 4): Decimal(300)} expected = [ {'date': date(1, 1, 1), 'amount': Decimal(600)}, {'date': date(1, 1, 2), 'amount': Decimal(0)}, {'date': date(1, 1, 3), 'amount': Decimal(200)}, {'date': date(1, 1, 4), 'amount': Decimal(300)}, {'date': date(1, 1, 5), 'amount': Decimal(0)}, {'date': date(1, 1, 6), 'amount': Decimal(0)}] results = list( data_utils.hydrate_bucket(params, date(1, 1, 1), date(1, 1, 6))) assert results == expected def test_accumulate_bucket_amounts(): """Test accumulating amounts in a series.""" params = [ {'date': date(1, 1, 1), 'amount': Decimal(600)}, {'date': date(1, 1, 2), 'amount': Decimal(0)}, {'date': date(1, 1, 3), 'amount': Decimal(200)}, {'date': date(1, 1, 4), 'amount': Decimal(300)}, {'date': date(1, 1, 5), 'amount': Decimal(0)}, {'date': date(1, 1, 6), 'amount': Decimal(0)}] expected = [ {'date': date(1, 1, 1), 'amount': Decimal(600)}, {'date': date(1, 1, 2), 'amount': Decimal(600)}, {'date': date(1, 1, 3), 'amount': Decimal(800)}, {'date': date(1, 1, 4), 'amount': Decimal(1100)}, {'date': date(1, 1, 5), 'amount': Decimal(1100)}, {'date': date(1, 1, 6), 'amount': Decimal(1100)}] results = list(data_utils.accumulate_bucket_amounts(params)) assert results == expected def test_sum_series_buckets(): """Test weaving serie's buckets data together into a list.""" params = { 'foo': iter([ {'date': date(1, 1, 1), 'amount': Decimal(600)}, {'date': date(1, 1, 2), 'amount': Decimal(600)}, {'date': date(1, 1, 3), 'amount': Decimal(800)}, {'date': date(1, 1, 4), 'amount': Decimal(1100)}, {'date': date(1, 1, 5), 'amount': Decimal(1200)}, {'date': date(1, 1, 6), 'amount': Decimal(1200)}]), 'bar': iter([ {'date': date(1, 1, 1), 'amount': Decimal(6000)}, {'date': date(1, 1, 2), 'amount': Decimal(6000)}, {'date': date(1, 1, 3), 'amount': Decimal(8000)}, {'date': date(1, 1, 4), 'amount': Decimal(11000)}, {'date': date(1, 1, 5), 'amount': Decimal(13000)}, {'date': date(1, 1, 6), 'amount': Decimal(15000)}])} expected = [ { 'date': date(1, 1, 1), 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, { 'date': date(1, 1, 2), 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, { 'date': date(1, 1, 3), 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}, { 'date': date(1, 1, 4), 'foo': Decimal(1100), 'bar': Decimal(11000), 'total': Decimal(12100)}, { 'date': date(1, 1, 5), 'foo': Decimal(1200), 'bar': Decimal(13000), 'total': Decimal(14200)}, { 'date': date(1, 1, 6), 'foo': Decimal(1200), 'bar': Decimal(15000), 'total': Decimal(16200)}] results = list(data_utils.sum_series_buckets(params)) assert results == expected def test_combine_series(): """Test combining revenue and projection into a single series.""" params = { 'revenue': iter([ { 'date': date(1, 1, 1), 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, { 'date': date(1, 1, 2), 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, { 'date': date(1, 1, 3), 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}]), 'projection': iter([ { 'date': date(1, 1, 1), 'baz': Decimal(1234), 'total': Decimal(1234)}, { 'date': date(1, 1, 2), 'baz': Decimal(2345), 'total': Decimal(2345)}, { 'date': date(1, 1, 3), 'baz': Decimal(3456), 'total': Decimal(3456)}])} expected = [ { 'date': date(1, 1, 1), 'revenue': { 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, 'projection': { 'baz': Decimal(1234), 'total': Decimal(1234)}}, { 'date': date(1, 1, 2), 'revenue': { 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, 'projection': { 'baz': Decimal(2345), 'total': Decimal(2345)}}, { 'date': date(1, 1, 3), 'revenue': { 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}, 'projection': { 'baz': Decimal(3456), 'total': Decimal(3456)}}] results = list(data_utils.combine_series(params)) assert results == expected def test_combine_series_none_value(): """Test combining revenue and projection into series with none value.""" params = { 'revenue': iter([ { 'date': date(1, 1, 1), 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, { 'date': date(1, 1, 2), 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}, { 'date': date(1, 1, 3), 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}]), 'projection': {}} expected = [ { 'date': date(1, 1, 1), 'revenue': { 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}}, { 'date': date(1, 1, 2), 'revenue': { 'foo': Decimal(600), 'bar': Decimal(6000), 'total': Decimal(6600)}}, { 'date': date(1, 1, 3), 'revenue': { 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}}] results = list(data_utils.combine_series(params)) assert results == expected def test_breakdown_day(): """Test getting a breakdown view from a single day's data.""" params = { 'date': date(1, 1, 3), 'expenses': { 'this': Decimal(100), 'that': Decimal(300), 'total': Decimal(400)}, 'revenue': { 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}, 'projection': { 'baz': Decimal(3456), 'total': Decimal(3456)}} expected = { 'actuals': { 'foo': Decimal(800), 'bar': Decimal(8000)}, 'expenses': { 'this': Decimal(100), 'that': Decimal(300)}, 'projected': { 'baz': Decimal(3456)}} results = data_utils.breakdown_day(params) assert results == expected @patch('api.utils.data.constants') def test_series_day(constants): """Test converting series' buckets data into the final endpoint format.""" constants.TERM_LICENSE_SERIES_KEY = 'foo' params = { 'date': date(1, 1, 3), 'revenue': { 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}, 'projection': { 'baz': Decimal(3456), 'total': Decimal(3456)}} expected = { 'date': date(1, 1, 3), 'revenue': { 'foo': Decimal(800), 'bar': Decimal(8000), 'total': Decimal(8800)}, 'projection': Decimal(11456)} results = data_utils.series_day(params) assert results == expected def test_sum_breakdown_buckets(): """Test sum calculation for breakdown tables.""" params = { 'foo': { 'this': Decimal(10), 'that': Decimal(20)}, 'bar': { 'john': Decimal(11), 'jane': Decimal(22)}} expected = { 'foo': { 'this': Decimal(10), 'that': Decimal(20), 'total': Decimal(30)}, 'bar': { 'john': Decimal(11), 'jane': Decimal(22), 'total': Decimal(33)}} assert data_utils.sum_breakdown_buckets(params) == expected def test_sum_breakdown_buckets_default(): """Test sum calculation for breakdown tables when total already exists.""" params = { 'foo': { 'this': Decimal(10), 'that': Decimal(20), 'total': Decimal(30)}, 'bar': { 'john': Decimal(11), 'jane': Decimal(22)}} expected = { 'foo': { 'this': Decimal(10), 'that': Decimal(20), 'total': Decimal(30)}, 'bar': { 'john': Decimal(11), 'jane': Decimal(22), 'total': Decimal(33)}} assert data_utils.sum_breakdown_buckets(params) == expected def test_sum_breakdown_buckets_empty(): """Test sum calculation for empty sets return 0.""" params = { 'foo': {}, 'bar': { 'john': Decimal(11), 'jane': Decimal(22)}} expected = { 'foo': { 'total': Decimal(0)}, 'bar': { 'john': Decimal(11), 'jane': Decimal(22), 'total': Decimal(33)}} assert data_utils.sum_breakdown_buckets(params) == expected def test_dailify_week_raw_rows(): """Test dailify smoothing function.""" rows = [ {'data_point': date(2016, 1, 1), 'amount': 7}, {'data_point': date(2016, 1, 8), 'amount': 14}] expected = [ {'data_point': date(2016, 1, 1), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 2), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 3), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 4), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 5), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 6), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 7), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 8), 'amount': Decimal(2)}, {'data_point': date(2016, 1, 9), 'amount': Decimal(2)}, {'data_point': date(2016, 1, 10), 'amount': Decimal(2)}, {'data_point': date(2016, 1, 11), 'amount': Decimal(2)}, {'data_point': date(2016, 1, 12), 'amount': Decimal(2)}, {'data_point': date(2016, 1, 13), 'amount': Decimal(2)}, {'data_point': date(2016, 1, 14), 'amount': Decimal(2)}] results = list(data_utils.dailify_week_raw_rows(rows)) assert results == expected def test_dailify_week_raw_rows_missing(): """Test dailify smoothing function when certain weeks are missing.""" rows = [ {'data_point': date(2016, 1, 1), 'amount': 7}, {'data_point': date(2016, 1, 8), 'amount': None}, {'data_point': date(2016, 1, 15), 'amount': 21}] expected = [ {'data_point': date(2016, 1, 1), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 2), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 3), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 4), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 5), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 6), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 7), 'amount': Decimal(1)}, {'data_point': date(2016, 1, 8), 'amount': Decimal(0)}, {'data_point': date(2016, 1, 9), 'amount': Decimal(0)}, {'data_point': date(2016, 1, 10), 'amount': Decimal(0)}, {'data_point': date(2016, 1, 11), 'amount': Decimal(0)}, {'data_point': date(2016, 1, 12), 'amount': Decimal(0)}, {'data_point': date(2016, 1, 13), 'amount': Decimal(0)}, {'data_point': date(2016, 1, 14), 'amount': Decimal(0)}, {'data_point': date(2016, 1, 15), 'amount': Decimal(3)}, {'data_point': date(2016, 1, 16), 'amount': Decimal(3)}, {'data_point': date(2016, 1, 17), 'amount': Decimal(3)}, {'data_point': date(2016, 1, 18), 'amount': Decimal(3)}, {'data_point': date(2016, 1, 19), 'amount': Decimal(3)}, {'data_point': date(2016, 1, 20), 'amount': Decimal(3)}, {'data_point': date(2016, 1, 21), 'amount': Decimal(3)}] results = list(data_utils.dailify_week_raw_rows(rows)) assert results == expected def test_convert_to_buckets(revenue_all_time_buckets): """Test convert_to_buckets function.""" mapping = {'evens': {2, 4, 6}, 'odds': {1, 3, 5}} results = data_utils.convert_to_buckets( revenue_all_time_buckets['raw'], mapping) assert results == revenue_all_time_buckets['bucket'] def test_convert_to_buckets_missing(revenue_all_time_buckets): """Text convert_to_buckets with wrong mapping.""" mapping = {'foo': {44, 444}, 'bar': {55, 555}} expected = {'foo': {}, 'bar': {}} results = data_utils.convert_to_buckets( revenue_all_time_buckets['raw'], mapping) assert results == expected