def test_checkout_update_shipping_method(api_client, checkout_with_digital_item, address, shipping_method): """Test updating the shipping method of a digital order throws an error.""" checkout = checkout_with_digital_item checkout_id = Node.to_global_id("Checkout", checkout.pk) method_id = Node.to_global_id("ShippingMethod", shipping_method.pk) variables = {"checkoutId": checkout_id, "shippingMethodId": method_id} # Put a shipping address, to ensure it is still handled properly checkout.shipping_address = address checkout.save(update_fields=["shipping_address"]) response = api_client.post_graphql(MUTATION_UPDATE_SHIPPING_METHOD, variables) content = get_graphql_content(response) data = content["data"]["checkoutShippingMethodUpdate"] assert data["errors"] == [{ "field": "shippingMethod", "message": "This checkout doesn't need shipping" }] # Ensure the shipping method was unchanged checkout.refresh_from_db(fields=["shipping_method"]) assert checkout.shipping_method is None
def test_save_pipeline_schedules_nonadmin( graphql_client, pipeline_sequence_3, pipeline_sequence_1, pipeline_sequence_2, pipeline_sequence_4, pipeline_sequence_5, ): ps_id_2 = Node.to_global_id('PipelineSequence', pipeline_sequence_2.id) ps_id_3 = Node.to_global_id('PipelineSequence', pipeline_sequence_3.id) res = graphql_client.post(save_pipeline_schedules_query, variables={ 'input': { 'clientMutationId': 'testmutation', 'pipelineSchedules': [ { 'id': ps_id_3, 'isFullActive': False, 'isUpdateActive': True, }, { 'id': ps_id_2, 'isFullActive': True, 'isUpdateActive': False, }, ], }, }) assert res['data']['savePipelineSchedules'] is None assert '401 Unauthorized' in res['errors'][0]['message']
def test_update_checkout_lines( api_client, checkout_with_items, stock, product_with_default_variant, product_with_single_variant, product_with_two_variants, count_queries, ): variables = { "token": checkout_with_items.token, "lines": [ { "quantity": 1, "variantId": Node.to_global_id("ProductVariant", stock.product_variant.pk), }, { "quantity": 2, "variantId": Node.to_global_id( "ProductVariant", product_with_default_variant.variants.first().pk, ), }, { "quantity": 10, "variantId": Node.to_global_id( "ProductVariant", product_with_single_variant.variants.first().pk, ), }, { "quantity": 3, "variantId": Node.to_global_id( "ProductVariant", product_with_two_variants.variants.first().pk, ), }, { "quantity": 2, "variantId": Node.to_global_id( "ProductVariant", product_with_two_variants.variants.last().pk, ), }, ], } response = get_graphql_content( api_client.post_graphql(MUTATION_CHECKOUT_LINES_UPDATE, variables)) assert not response["data"]["checkoutLinesUpdate"]["errors"]
def test_add_shipping_to_checkout( api_client, checkout_with_shipping_address, shipping_method, count_queries, ): query = ( FRAGMENT_CHECKOUT + """ mutation updateCheckoutShippingOptions( $checkoutId: ID!, $shippingMethodId: ID! ) { checkoutShippingMethodUpdate( checkoutId: $checkoutId, shippingMethodId: $shippingMethodId ) { errors { field message } checkout { ...Checkout } } } """ ) variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_shipping_address.pk), "shippingMethodId": Node.to_global_id("ShippingMethod", shipping_method.pk), } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutShippingMethodUpdate"]["errors"]
def test_create_checkout_for_cc( api_client, graphql_address_data, channel_USD, stocks_for_cc, product_variant_list, count_queries, ): query = ( FRAGMENT_CHECKOUT_FOR_CC + """ mutation CreateCheckout($checkoutInput: CheckoutCreateInput!) { checkoutCreate(input: $checkoutInput) { errors { field message } checkout { ...Checkout } } } """ ) checkout_counts = Checkout.objects.count() variables = { "checkoutInput": { "channel": channel_USD.slug, "email": "*****@*****.**", "shippingAddress": graphql_address_data, "lines": [ { "quantity": 1, "variantId": Node.to_global_id( "ProductVariant", stocks_for_cc[0].product_variant.pk ), }, { "quantity": 2, "variantId": Node.to_global_id( "ProductVariant", product_variant_list[0].pk, ), }, { "quantity": 5, "variantId": Node.to_global_id( "ProductVariant", product_variant_list[1].pk, ), }, ], } } get_graphql_content(api_client.post_graphql(query, variables)) assert checkout_counts + 1 == Checkout.objects.count()
def test_create_checkout( api_client, graphql_address_data, stock, channel_USD, product_with_default_variant, product_with_single_variant, product_with_two_variants, count_queries, ): checkout_counts = Checkout.objects.count() variables = { "checkoutInput": { "channel": channel_USD.slug, "email": "*****@*****.**", "shippingAddress": graphql_address_data, "lines": [ { "quantity": 1, "variantId": Node.to_global_id( "ProductVariant", stock.product_variant.pk ), }, { "quantity": 2, "variantId": Node.to_global_id( "ProductVariant", product_with_default_variant.variants.first().pk, ), }, { "quantity": 10, "variantId": Node.to_global_id( "ProductVariant", product_with_single_variant.variants.first().pk, ), }, { "quantity": 3, "variantId": Node.to_global_id( "ProductVariant", product_with_two_variants.variants.first().pk, ), }, { "quantity": 2, "variantId": Node.to_global_id( "ProductVariant", product_with_two_variants.variants.last().pk, ), }, ], } } get_graphql_content(api_client.post_graphql(MUTATION_CHECKOUT_CREATE, variables)) assert checkout_counts + 1 == Checkout.objects.count()
def test_pipeline_sequence_list_order_by_end_time_desc( graphql_client_admin, pipeline_sequence_3, pipeline_sequence_1, pipeline_sequence_2, pipeline_sequence_4, pipeline_sequence_5, ): ps_id_1 = pipeline_sequence_1.id ps_id_3 = pipeline_sequence_3.id ps_id_4 = pipeline_sequence_4.id res = graphql_client_admin.post(pipeline_sequence_list_query, variables={ 'offset': 1, 'first': 3, 'sort': 'end_time_desc', }) expected = {'data': {'scheduleManagement': {'pipelineSequences': {'edges': [ {'node': {'comments': 'comments1', 'id': Node.to_global_id('PipelineSequence', ps_id_1), 'source': {'name': 'source_1'}, 'isActive': True, 'isFullActive': True, 'isUpdateActive': False, 'isFullInProgress': False, 'isUpdateInProgress': False, 'startTime': '2018-01-15T21:30:13.000155', 'endTime': '2018-01-15T21:30:16.000295', 'state': 'state1'}}, {'node': {'comments': 'comments4', 'id': Node.to_global_id('PipelineSequence', ps_id_4), 'source': {'name': 'source_source_4'}, 'isActive': True, 'isFullActive': True, 'isUpdateActive': False, 'isFullInProgress': False, 'isUpdateInProgress': False, 'startTime': '2018-01-14T21:30:13.000155', 'endTime': '2018-01-14T21:30:16.000295', 'state': 'ready'}}, {'node': {'comments': 'comments3', 'id': Node.to_global_id('PipelineSequence', ps_id_3), 'source': {'name': 'source_3'}, 'isActive': True, 'isFullActive': True, 'isUpdateActive': False, 'isFullInProgress': True, 'isUpdateInProgress': False, 'startTime': '2018-01-13T21:33:13.000153', 'endTime': '2018-01-13T21:33:16.000235', 'state': 'queued'}}, ], 'totalCount': 5}}}} assert res == expected
def test_pipeline_sequence_list_default_order( graphql_client_admin, pipeline_sequence_3, pipeline_sequence_1, pipeline_sequence_2, pipeline_sequence_4, pipeline_sequence_5, ): ps_id_2 = pipeline_sequence_2.id ps_id_3 = pipeline_sequence_3.id ps_id_5 = pipeline_sequence_5.id res = graphql_client_admin.post(pipeline_sequence_list_query, variables={ 'offset': 1, 'first': 3, }) expected = {'data': {'scheduleManagement': {'pipelineSequences': {'edges': [ {'node': {'comments': 'comments2', 'id': Node.to_global_id('PipelineSequence', ps_id_2), 'source': {'name': 'source_2'}, 'isActive': False, 'isFullActive': False, 'isUpdateActive': False, 'isFullInProgress': False, 'isUpdateInProgress': False, 'startTime': '2018-02-15T21:30:13.000155', 'endTime': '2018-02-15T21:30:16.000295', 'state': 'error'}}, {'node': {'comments': 'comments3', 'id': Node.to_global_id('PipelineSequence', ps_id_3), 'source': {'name': 'source_3'}, 'isActive': True, 'isFullActive': True, 'isUpdateActive': False, 'isFullInProgress': True, 'isUpdateInProgress': False, 'startTime': '2018-01-13T21:33:13.000153', 'endTime': '2018-01-13T21:33:16.000235', 'state': 'queued'}}, {'node': {'comments': 'comments5', 'id': Node.to_global_id('PipelineSequence', ps_id_5), 'source': {'name': 'source_no_shipping'}, 'isActive': False, 'isFullActive': False, 'isUpdateActive': False, 'isFullInProgress': False, 'isUpdateInProgress': False, 'startTime': '2017-01-15T21:30:13.000155', 'endTime': '2017-01-15T21:30:16.000295', 'state': 'ready'}}, ], 'totalCount': 5}}}} assert res == expected
def test_checkout_payment_charge(api_client, checkout_with_billing_address, count_queries): query = """ mutation createPayment($input: PaymentInput!, $checkoutId: ID!) { checkoutPaymentCreate(input: $input, checkoutId: $checkoutId) { errors { field message } } } """ lines = fetch_checkout_lines(checkout_with_billing_address) checkout_info = fetch_checkout_info(checkout_with_billing_address, lines, []) manager = get_plugins_manager() total = calculations.checkout_total( manager=manager, checkout_info=checkout_info, lines=lines, address=checkout_with_billing_address.shipping_address, ) variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_billing_address.pk), "input": { "amount": total.gross.amount, "gateway": "mirumee.payments.dummy", "token": "charged", }, } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutPaymentCreate"]["errors"]
def test_save_pipeline_sequence( graphql_client_admin, pipeline_sequence_3, pipeline_sequence_1, pipeline_sequence_2, pipeline_sequence_4, pipeline_sequence_5, ): ps_id_3 = Node.to_global_id('PipelineSequence', pipeline_sequence_3.id) res = graphql_client_admin.post(save_pipeline_sequence_query, variables={ 'input': { 'clientMutationId': 'testmutation', 'id': ps_id_3, 'isFullActive': False, 'isUpdateActive': True, }, }) expected = {'data': {'savePipelineSequence': { 'clientMutationId': 'testmutation', 'pipelineSequence': {'comments': 'comments3', 'id': ps_id_3, 'source': {'name': 'source_3'}, 'isActive': False, 'isFullActive': False, 'isUpdateActive': False, 'isFullInProgress': True, 'isUpdateInProgress': False, 'startTime': '2018-01-13T21:33:13.000153', 'endTime': '2018-01-13T21:33:16.000235', 'state': 'queued'}}}} assert res == expected
def test_checkout_payment_charge( api_client, checkout_with_billing_address, count_queries ): query = """ mutation createPayment($input: PaymentInput!, $checkoutId: ID!) { checkoutPaymentCreate(input: $input, checkoutId: $checkoutId) { errors { field message } } } """ variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_billing_address.pk), "input": { "amount": calculations.checkout_total( checkout=checkout_with_billing_address, lines=list(checkout_with_billing_address), ).gross.amount, "gateway": "mirumee.payments.dummy", "token": "charged", }, } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutPaymentCreate"]["errors"]
def test_add_delivery_to_checkout( api_client, checkout_with_shipping_address_for_cc, warehouses_for_cc, count_queries, ): query = (FRAGMENT_CHECKOUT + """ mutation updateCheckoutDeliveryOptions( $token: UUID, $deliveryMethodId: ID ) { checkoutDeliveryMethodUpdate( token: $token, deliveryMethodId: $deliveryMethodId ) { errors { field message } checkout { ...Checkout } } } """) variables = { "token": checkout_with_shipping_address_for_cc.token, "deliveryMethodId": Node.to_global_id("Warehouse", warehouses_for_cc[1].pk), } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutDeliveryMethodUpdate"]["errors"]
def test_retrieve_variant_list(product_variant_list, api_client, count_queries): query = """ fragment BasicProductFields on Product { id name thumbnail { url alt } thumbnail2x: thumbnail(size: 510) { url } } fragment ProductVariantFields on ProductVariant { id sku name stockQuantity isAvailable price { currency amount localized } attributes { attribute { id name } value { id name value: name } } } query VariantList($ids: [ID!]) { productVariants(ids: $ids, first: 100) { edges { node { ...ProductVariantFields stockQuantity product { ...BasicProductFields } } } } } """ variables = { "ids": [ Node.to_global_id("ProductVariant", variant.pk) for variant in product_variant_list ] } get_graphql_content(api_client.post_graphql(query, variables))
def test_complete_checkout(api_client, checkout_with_charged_payment, count_queries): query = """ mutation completeCheckout($checkoutId: ID!, $redirectUrl: String) { checkoutComplete(checkoutId: $checkoutId, redirectUrl: $redirectUrl) { errors { field message } order { id token } } } """ variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_charged_payment.pk), "redirectUrl": "https://www.example.com", } get_graphql_content(api_client.post_graphql(query, variables))
def test_tracking_number_updated_already_captured( mocked_report_fulfillment, mocked_notify_dashboard, np_atobarai_plugin, payment_np, fulfillment, caplog, ): # given plugin = np_atobarai_plugin() result = ([], True) mocked_report_fulfillment.return_value = result order = fulfillment.order order.payments.add(payment_np) # when plugin.tracking_number_updated(fulfillment, None) # then payment_graphql_id = Node.to_global_id("Payment", payment_np.id) mocked_notify_dashboard.assert_called_once_with( order, f"Error: Payment with id {payment_graphql_id} was already captured", ) assert len(caplog.records) == 1 assert caplog.records[0].levelno == logging.WARNING assert ( caplog.records[0].message == f"Payment with id {payment_graphql_id} was already captured" )
def test_checkout_update_shipping_address(api_client, checkout_with_digital_item, graphql_address_data): """Test updating the shipping address of a digital order throws an error.""" checkout = checkout_with_digital_item checkout_id = Node.to_global_id("Checkout", checkout.pk) variables = { "checkoutId": checkout_id, "shippingAddress": graphql_address_data } response = api_client.post_graphql( MUTATION_CHECKOUT_SHIPPING_ADDRESS_UPDATE, variables) content = get_graphql_content(response) data = content["data"]["checkoutShippingAddressUpdate"] assert data["errors"] == [{ "field": "shippingAddress", "message": "This checkout doesn't need shipping" }] assert data["checkoutErrors"] == [{ "field": "shippingAddress", "message": "This checkout doesn't need shipping", "code": CheckoutErrorCode.SHIPPING_NOT_REQUIRED.name, }] # Ensure the address was unchanged checkout.refresh_from_db(fields=["shipping_address"]) assert checkout.shipping_address is None
def test_checkout_complete(api_client, checkout_with_digital_item, address, payment_dummy): """Ensure it is possible to complete a digital checkout without shipping.""" order_count = Order.objects.count() checkout = checkout_with_digital_item checkout_id = Node.to_global_id("Checkout", checkout.pk) variables = {"checkoutId": checkout_id} # Set a billing address checkout.billing_address = address checkout.save(update_fields=["billing_address"]) # Create a dummy payment to charge total = checkout.get_total() total = TaxedMoney(total, total) payment = payment_dummy payment.is_active = True payment.order = None payment.total = total.gross.amount payment.currency = total.gross.currency payment.checkout = checkout payment.save() assert not payment.transactions.exists() # Send the creation request response = api_client.post_graphql(MUTATION_CHECKOUT_COMPLETE, variables) content = get_graphql_content(response)["data"]["checkoutComplete"] assert not content["errors"] # Ensure the order was actually created assert (Order.objects.count() == order_count + 1), "The order should have been created"
def test_checkout_email_update(api_client, checkout_with_variants, count_queries): query = ( FRAGMENT_CHECKOUT + """ mutation UpdateCheckoutEmail( $checkoutId: ID!, $email: String! ) { checkoutEmailUpdate(checkoutId: $checkoutId, email: $email) { checkout { ...Checkout } errors { field message } } } """ ) variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_variants.pk), "email": "*****@*****.**", } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutEmailUpdate"]["errors"]
def test_customer_complete_checkout( api_client, checkout_with_charged_payment, count_queries, customer_user ): query = """ mutation completeCheckout($checkoutId: ID!) { checkoutComplete(checkoutId: $checkoutId) { errors { field message } order { id token } } } """ checkout = checkout_with_charged_payment checkout.user = customer_user checkout.save() variables = { "checkoutId": Node.to_global_id("Checkout", checkout.pk), } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutComplete"]["errors"]
def test_checkout_voucher_code( api_client, checkout_with_billing_address, voucher, count_queries ): query = ( FRAGMENT_CHECKOUT + """ mutation AddCheckoutPromoCode($checkoutId: ID!, $promoCode: String!) { checkoutAddPromoCode(checkoutId: $checkoutId, promoCode: $promoCode) { checkout { ...Checkout } errors { field message } checkoutErrors { field message code } } } """ ) variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_billing_address.pk), "promoCode": voucher.code, } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutAddPromoCode"]["errors"]
def test_checkout_shipping_address_update( api_client, graphql_address_data, checkout_with_variants, count_queries ): query = ( FRAGMENT_CHECKOUT + """ mutation UpdateCheckoutShippingAddress( $checkoutId: ID!, $shippingAddress: AddressInput! ) { checkoutShippingAddressUpdate( checkoutId: $checkoutId, shippingAddress: $shippingAddress ) { errors { field message } checkout { ...Checkout } } } """ ) variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_variants.pk), "shippingAddress": graphql_address_data, } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutShippingAddressUpdate"]["errors"]
def test_tracking_number_updated_errors( mocked_report_fulfillment, mocked_notify_dashboard, np_atobarai_plugin, payment_np, fulfillment, caplog, ): # given errors = ["error1", "error2"] plugin = np_atobarai_plugin() result = (errors, False) mocked_report_fulfillment.return_value = result order = fulfillment.order order.payments.add(payment_np) # when plugin.tracking_number_updated(fulfillment, None) # then payment_graphql_id = Node.to_global_id("Payment", payment_np.id) error = ", ".join(errors) mocked_notify_dashboard.assert_called_once_with( order, f"Error: Cannot capture payment with id {payment_graphql_id} ({error})" ) assert len(caplog.records) == 1 assert caplog.records[0].levelno == logging.WARNING assert caplog.records[0].message == ( f"Could not capture payment with id {payment_graphql_id} " f"in NP Atobarai: {error}" )
def test__filter_casts(self): num_instances = 4 offset = 0 limit = 3 aclass_id = 6666 aclass_global_id = Node.to_global_id('AClass', aclass_id) filters = {'aclass': aclass_global_id} order_by = None expected_instances = [Mock() for _ in range(num_instances)] # mock entities with row numbers mock_results = [(instance, index + 1) for index, instance in enumerate(expected_instances)] mock_query = Mock() mock_session = Mock() mock_query.add_columns.return_value = mock_query def apply_filter(criteria): # check that AClass id has been decoded correctly self.assertEqual(str(aclass_id), criteria.right.value) return mock_query mock_query.filter.side_effect = apply_filter mock_query.count.return_value = len(mock_results) def apply_offset(): del mock_results[0:offset] del expected_instances[0:offset] return mock_query mock_query.from_self.side_effect = apply_offset def apply_limit(num_results): del mock_results[num_results:] del expected_instances[num_results:] return mock_query mock_query.limit.side_effect = apply_limit mock_query.order_by.return_value = mock_query mock_query.all.return_value = mock_results mock_session.query.return_value = mock_query context = {'request': {'session': mock_session}} args = {} if offset: args['after'] = offset_to_cursor(offset) if limit: args['first'] = limit if filters: args['filters'] = filters if order_by: args['orderBy'] = order_by info = TestConnection.InfoFixture(context) instances = areferring_connection_field.resolver(None, info, **args)
def test_complete_checkout(api_client, checkout_with_charged_payment, count_queries): query = COMPLETE_CHECKOUT_MUTATION variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_charged_payment.pk), } response = get_graphql_content(api_client.post_graphql(query, variables)) assert not response["data"]["checkoutComplete"]["errors"]
def mutate_and_get_payload(cls, root, info, user_id, name, client_mutation_id=None): user = Node.get_node_from_global_id(info, user_id) name = name account = Account.objects.filter(user=user, name=name).first() assert account is None, 'Account exists: {0}'.format( Node.to_global_id('AccountNode', account.id)) account = Account.objects.create(user=user, name=name) success = True return CreateAccountMutation(account=account, success=success)
def mutate_and_get_payload(cls, root, info, account_id, name, client_mutation_id=None): account = Node.get_node_from_global_id(info, account_id) name = name cashier = Cashier.objects.filter(account=account, name=name).first() assert cashier is None, 'Cashier exists: {0}'.format( Node.to_global_id('CashierNode', cashier.id)) cashier = Cashier.objects.create(account=account, name=name) success = True return CreateCashierMutation(cashier=cashier, success=success)
def mutate_and_get_payload(cls, root, info, account_id, name, client_mutation_id=None): account = Node.get_node_from_global_id(info, account_id) name = name clasification = Clasification.objects.filter(account=account, name=name).first() assert clasification is None, 'Clasification exists: {0}'.format( Node.to_global_id('ClasificationNode', clasification.id)) clasification = Clasification.objects.create(account=account, name=name) success = True return CreateClasificationMutation(clasification=clasification, success=success)
def test_complete_checkout(api_client, checkout_with_charged_payment, count_queries): query = """ mutation completeCheckout($checkoutId: ID!) { checkoutComplete(checkoutId: $checkoutId) { errors { field message } order { id token } } } """ variables = { "checkoutId": Node.to_global_id("Checkout", checkout_with_charged_payment.pk) } get_graphql_content(api_client.post_graphql(query, variables))
def test_run_pipeline_sequence_nonadmin( requests_m, graphql_client, pipeline_sequence_3, pipeline_sequence_1, pipeline_sequence_2, pipeline_sequence_4, pipeline_sequence_5, ): ps_id_3 = Node.to_global_id('PipelineSequence', pipeline_sequence_3.id) res = graphql_client.post(run_pipeline_sequence_query, variables={ 'input': { 'clientMutationId': 'testmutation', 'id': ps_id_3, }, }) assert res['data']['runPipelineSequence'] is None assert '401 Unauthorized' in res['errors'][0]['message'] requests_m.get.assert_not_called()
def test_run_pipeline_sequence( requests_m, graphql_client_admin, pipeline_sequence_3, pipeline_sequence_1, pipeline_sequence_2, pipeline_sequence_4, pipeline_sequence_5, ): requests_m.get.side_effect = _run_pipeline_sequence_requests_get_mock ps_id_4 = Node.to_global_id('PipelineSequence', pipeline_sequence_4.id) ps_source_id_4 = pipeline_sequence_4.source_id res = graphql_client_admin.post(run_pipeline_sequence_query, variables={ 'input': { 'clientMutationId': 'testmutation', 'id': ps_id_4, }, }) requests_m.get.assert_called_once_with( f'https://m3-integration-test.com/api/1/source/{ps_source_id_4}/sync/' ) expected = {'data': {'runPipelineSequence': { 'clientMutationId': 'testmutation', 'pipelineSequence': {'comments': 'comments4', 'id': ps_id_4, 'source': {'name': 'source_source_4'}, 'isActive': True, 'isFullActive': True, 'isUpdateActive': False, 'isFullInProgress': True, 'isUpdateInProgress': False, 'startTime': '2018-01-14T21:30:13.000155', 'endTime': '2018-01-14T21:30:16.000295', 'state': 'queued'}}}} assert res == expected