def test_update_last_provider_id(): provider1 = offerers_factories.ProviderFactory() provider2 = offerers_factories.ProviderFactory() venue = VenueFactory() offer1_synced = OfferFactory(venue=venue, idAtProviders=1, lastProvider=provider1) offer2_manual = OfferFactory(venue=venue, idAtProviders=None) offer3_other_venue = OfferFactory(idAtProviders=2, lastProvider=provider1) api.update_last_provider_id(venue, provider2.id) assert offer1_synced.lastProvider == provider2 assert offer2_manual.idAtProviders is None assert offer3_other_venue.lastProvider == provider1
def test_can_edit_non_restricted_fields_if_provider_is_allocine(self): provider = offerers_factories.ProviderFactory(localClass="AllocineStocks") stock = factories.EventStockFactory( offer__lastProvider=provider, offer__idAtProviders="1", ) initial_beginning = stock.beginningDatetime # Change various attributes, but keep the same beginning # (which we are not allowed to change). new_booking_limit = datetime.datetime.now() + datetime.timedelta(days=1) changes = { "price": 5, "quantity": 20, # FIXME (dbaty, 2020-11-25): see comment in edit_stock, # this is to match what the frontend sends. "beginning": stock.beginningDatetime.replace(tzinfo=pytz.UTC), "booking_limit_datetime": new_booking_limit, } api.edit_stock(stock, **changes) stock = models.Stock.query.one() assert stock.price == 5 assert stock.quantity == 20 assert stock.beginningDatetime == initial_beginning assert stock.bookingLimitDatetime == new_booking_limit assert set(stock.fieldsUpdated) == {"price", "quantity", "bookingLimitDatetime"}
def test_success_on_imported_offer_on_accessibility_fields(self): provider = offerers_factories.ProviderFactory() offer = factories.OfferFactory( lastProvider=provider, name="Old name", audioDisabilityCompliant=True, visualDisabilityCompliant=False, motorDisabilityCompliant=False, mentalDisabilityCompliant=True, ) api.update_offer( offer, name="Old name", audioDisabilityCompliant=False, visualDisabilityCompliant=True, motorDisabilityCompliant=True, mentalDisabilityCompliant=False, ) offer = models.Offer.query.one() assert offer.name == "Old name" assert offer.audioDisabilityCompliant == False assert offer.visualDisabilityCompliant == True assert offer.motorDisabilityCompliant == True assert offer.mentalDisabilityCompliant == False
def test_does_not_update_existing_object_when_date_is_older_than_last_modified_date( self, next_function): # Given provider = offerers_factories.ProviderFactory( localClass="TestLocalProvider") providable_info = create_providable_info( date_modified=datetime(2018, 1, 1)) product = offers_factories.ThingProductFactory( dateModifiedAtLastProvider=datetime(2020, 1, 1), lastProvider=provider, idAtProviders=providable_info.id_at_providers, name="Old product name", type=str(ThingType.INSTRUMENT), ) local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[providable_info]] # When local_provider.updateObjects() # Then product = Product.query.one() assert product.name == "Old product name" assert product.type == str(ThingType.INSTRUMENT) assert product.dateModifiedAtLastProvider == datetime(2020, 1, 1)
def test_does_not_allow_edition_of_beginningDateTime_for_stocks_of_offers_synchronized_with_allocine( self, mock_update_confirmation_dates): # Given offer = factories.EventOfferFactory( lastProvider=offerers_factories.ProviderFactory( localClass="AllocineStocks")) date_in_the_future = datetime.utcnow() + timedelta(days=4) other_date_in_the_future = datetime.utcnow() + timedelta(days=6) existing_stock = factories.StockFactory( offer=offer, price=10, beginningDatetime=date_in_the_future) edited_stock_data = StockEditionBodyModel( id=existing_stock.id, beginningDatetime=other_date_in_the_future, bookingLimitDatetime=other_date_in_the_future, price=10, ) # When with pytest.raises(api_errors.ApiErrors) as error: api.upsert_stocks(offer_id=offer.id, stock_data_list=[edited_stock_data]) # Then assert error.value.errors == { "global": [ "Pour les offres importées, certains champs ne sont pas modifiables" ] }
def test_ok_if_stock_from_allocine(self): provider = offerers_factories.ProviderFactory( localClass="AllocineStocks") offer = factories.OfferFactory(lastProvider=provider, idAtProviders="1") stock = factories.StockFactory(offer=offer) validation.check_stock_is_deletable(stock) # should not raise
def test_raises_error_when_offer_is_not_editable(self): offerer = offerers_factories.ProviderFactory() offer = factories.OfferFactory(lastProvider=offerer, idAtProviders="1") with pytest.raises(ApiErrors) as error: validation.check_offer_is_editable(offer) assert error.value.errors["global"] == ["Les offres importées ne sont pas modifiables"]
def test_fail_if_offer_is_not_editable(self): provider = offerers_factories.ProviderFactory() offer = factories.ThingOfferFactory(lastProvider=provider) with pytest.raises(api_errors.ApiErrors) as error: api.create_stock(offer=offer, price=10, beginning=None, booking_limit_datetime=None) assert error.value.errors == {"global": ["Les offres importées ne sont pas modifiables"]}
def should_fail_when_offer_is_from_provider(self, app): provider = offerers_factories.ProviderFactory() offer = factories.OfferFactory(lastProvider=provider, idAtProviders="1") with pytest.raises(ApiErrors) as error: validation.check_stocks_are_editable_for_offer(offer) assert error.value.errors["global"] == ["Les offres importées ne sont pas modifiables"]
def test_raise_if_stock_from_provider_that_is_not_allocine(self): provider = offerers_factories.ProviderFactory() offer = factories.OfferFactory(lastProvider=provider, idAtProviders="1") stock = factories.StockFactory(offer=offer) with pytest.raises(ApiErrors) as error: validation.check_stock_is_deletable(stock) assert error.value.errors["global"] == ["Les offres importées ne sont pas modifiables"]
def test_can_delete_if_stock_from_allocine(self): provider = offerers_factories.ProviderFactory(localClass="AllocineStocks") offer = factories.OfferFactory(lastProvider=provider, idAtProviders="1") stock = factories.StockFactory(offer=offer) api.delete_stock(stock) stock = models.Stock.query.one() assert stock.isSoftDeleted
def test_success_on_allocine_offer(self): provider = offerers_factories.ProviderFactory(localClass="AllocineStocks") offer = factories.OfferFactory(lastProvider=provider, name="Old name") offer = api.update_offer(offer, name="Old name", isDuo=True) offer = models.Offer.query.one() assert offer.name == "Old name" assert offer.isDuo
def test_forbidden_on_imported_offer_if_not_allocine(self): provider = offerers_factories.ProviderFactory() offer = factories.OfferFactory(lastProvider=provider, name="Old name") with pytest.raises(models.ApiErrors) as error: offer = api.update_offer(offer, name="New name") assert error.value.errors == {"global": ["Les offres importées ne sont pas modifiables"]} assert models.Offer.query.one().name == "Old name"
def test_iterator_is_called_until_exhausted(self, next_function): # Given offerers_factories.ProviderFactory(localClass="TestLocalProvider") local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[], [], []] # When local_provider.updateObjects() # Then assert next_function.call_count == 4
def test_should_call_sync_venue_provider_for_expected_venue_provider( self, mock_synchronize_venue_provider): # Given provider = offerers_factories.ProviderFactory( localClass="TiteLiveStocks") vp1 = offerers_factories.VenueProviderFactory(provider=provider) vp2 = offerers_factories.VenueProviderFactory(provider=provider) offerers_factories.VenueProviderFactory(provider=provider, isActive=False) other_provider = offerers_factories.ProviderFactory() offerers_factories.VenueProviderFactory(provider=other_provider) # When update_venues_for_specific_provider(provider.id) # Then assert mock_synchronize_venue_provider.call_args_list == [ mock.call(vp1), mock.call(vp2), ]
def test_forbidden_on_allocine_offer_on_certain_fields(self): provider = offerers_factories.ProviderFactory(localClass="AllocineStocks") offer = factories.OfferFactory(lastProvider=provider, name="Old name") with pytest.raises(models.ApiErrors) as error: offer = api.update_offer(offer, name="New name", isDuo=True) assert error.value.errors == {"name": ["Vous ne pouvez pas modifier ce champ"]} offer = models.Offer.query.one() assert offer.name == "Old name" assert not offer.isDuo
def test_cannot_delete_if_stock_from_titelive(self): provider = offerers_factories.ProviderFactory(localClass="TiteLiveStocks") offer = factories.OfferFactory(lastProvider=provider, idAtProviders="1") stock = factories.StockFactory(offer=offer) with pytest.raises(api_errors.ApiErrors) as error: api.delete_stock(stock) msg = "Les offres importées ne sont pas modifiables" assert error.value.errors["global"][0] == msg stock = models.Stock.query.one() assert not stock.isSoftDeleted
def test_cannot_edit_if_provider_is_titelive(self): provider = offerers_factories.ProviderFactory(localClass="TiteLiveStocks") stock = factories.EventStockFactory(offer__lastProvider=provider, offer__idAtProviders="1") with pytest.raises(api_errors.ApiErrors) as error: api.edit_stock( stock, price=stock.price, quantity=stock.quantity, beginning=stock.beginningDatetime, booking_limit_datetime=stock.bookingLimitDatetime, ) msg = "Les offres importées ne sont pas modifiables" assert error.value.errors["global"][0] == msg
def test_does_not_create_new_object_when_can_create_is_false( self, next_function): # Given offerers_factories.ProviderFactory( localClass="TestLocalProviderNoCreation") providable_info = create_providable_info() local_provider = provider_test_utils.TestLocalProviderNoCreation() next_function.side_effect = [[providable_info]] # When local_provider.updateObjects() # Then assert Product.query.count() == 0
def test_returns_object_with_expected_attributes(self): # Given provider = offerers_factories.ProviderFactory( localClass="TestLocalProvider") providable_info = create_providable_info() local_provider = provider_test_utils.TestLocalProvider() # When product = local_provider._create_object(providable_info) # Then assert isinstance(product, Product) assert product.name == "New Product" assert product.type == str(ThingType.LIVRE_EDITION) assert product.lastProviderId == provider.id
def test_iterator_should_log_provider_event_from_start_to_stop( self, next_function): # Given offerers_factories.ProviderFactory(localClass="TestLocalProvider") local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[], []] # When local_provider.updateObjects() # Then provider_events = LocalProviderEvent.query.order_by( LocalProviderEvent.id.asc()).all() assert provider_events[0].type == LocalProviderEventType.SyncStart assert provider_events[1].type == LocalProviderEventType.SyncEnd
def test_creates_new_object_when_no_object_in_database( self, next_function): # Given offerers_factories.ProviderFactory(localClass="TestLocalProvider") providable_info = create_providable_info() local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[providable_info]] # When local_provider.updateObjects() # Then new_product = Product.query.one() assert new_product.name == "New Product" assert new_product.type == str(ThingType.LIVRE_EDITION)
def test_does_not_update_objects_when_provider_is_not_active( self, next_function): # Given offerers_factories.ProviderFactory(localClass="TestLocalProvider", isActive=False) providable_info = create_providable_info( date_modified=datetime(2018, 1, 1)) local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[providable_info]] # When local_provider.updateObjects() # Then assert Product.query.count() == 0
def test_creates_only_one_object_when_limit_is_one(self, next_function): # Given offerers_factories.ProviderFactory(localClass="TestLocalProvider") providable_info1 = create_providable_info() providable_info2 = create_providable_info(id_at_providers="2") local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[providable_info1], [providable_info2]] # When local_provider.updateObjects(limit=1) # Then new_product = Product.query.one() assert new_product.name == "New Product" assert new_product.type == str(ThingType.LIVRE_EDITION)
def test_success_on_imported_offer_on_external_ticket_office_url(self): provider = offerers_factories.ProviderFactory() offer = factories.OfferFactory( externalTicketOfficeUrl="http://example.org", lastProvider=provider, name="Old name", ) api.update_offer( offer, externalTicketOfficeUrl="https://example.com", ) offer = models.Offer.query.one() assert offer.name == "Old name" assert offer.externalTicketOfficeUrl == "https://example.com"
def test_does_not_allow_upsert_stocks_on_a_synchronized_offer( self, mock_update_confirmation_dates): # Given offer = factories.ThingOfferFactory( lastProvider=offerers_factories.ProviderFactory( localClass="TiteLiveStocks")) created_stock_data = StockCreationBodyModel(price=10) # When with pytest.raises(api_errors.ApiErrors) as error: api.upsert_stocks(offer_id=offer.id, stock_data_list=[created_stock_data]) # Then assert error.value.errors == { "global": ["Les offres importées ne sont pas modifiables"] }
def test_cannot_edit_restricted_fields_if_provider_is_allocine(self): provider = offerers_factories.ProviderFactory(localClass="AllocineStocks") stock = factories.EventStockFactory( offer__lastProvider=provider, offer__idAtProviders="1", ) # Try to change everything, including "beginningDatetime" which is forbidden. new_booking_limit = datetime.datetime.now() + datetime.timedelta(days=1) changes = { "price": 5, "quantity": 20, "beginning": datetime.datetime.now() + datetime.timedelta(days=2), "booking_limit_datetime": new_booking_limit, } with pytest.raises(api_errors.ApiErrors) as error: api.edit_stock(stock, **changes) msg = "Pour les offres importées, certains champs ne sont pas modifiables" assert error.value.errors["global"][0] == msg
def test_raises_api_errors_exception_when_errors_occur_on_model_and_log_error( self): # Given offerers_factories.ProviderFactory( localClass="TestLocalProviderWithApiErrors") providable_info = create_providable_info() local_provider = provider_test_utils.TestLocalProviderWithApiErrors() # When with pytest.raises(ApiErrors) as api_errors: local_provider._create_object(providable_info) # Then assert api_errors.value.errors["url"] == [ "Une offre de type Jeux (support physique) ne peut pas être numérique" ] assert Product.query.count() == 0 provider_event = LocalProviderEvent.query.one() assert provider_event.type == LocalProviderEventType.SyncError
def test_should_only_replace_image_at_specific_thumb_index_when_thumbCount_is_superior_to_thumbIndex( self): provider = offerers_factories.ProviderFactory( localClass="TestLocalProviderWithThumb") providable_info = create_providable_info() product = offers_factories.ThingProductFactory( idAtProviders=providable_info.id_at_providers, lastProvider=provider, thumbCount=4, ) local_provider = provider_test_utils.TestLocalProviderWithThumb() thumb = local_provider.get_object_thumb() # When thumb_index = 1 _save_same_thumb_from_thumb_count_to_index(product, thumb_index, thumb) repository.save(product) # Then assert product.thumbCount == 4
def when_stock_is_on_an_offer_from_titelive_provider( self, app, db_session): # given provider = offerers_factories.ProviderFactory( localClass="TiteLiveThings") offer = offers_factories.OfferFactory(lastProvider=provider, idAtProviders="1") stock = offers_factories.StockFactory(offer=offer) user = users_factories.UserFactory(isAdmin=True) # when client = TestClient(app.test_client()).with_auth(user.email) response = client.delete(f"/stocks/{humanize(stock.id)}") # then assert response.status_code == 400 assert response.json["global"] == [ "Les offres importées ne sont pas modifiables" ]