예제 #1
0
    def test_description_discard(self):
        """ Tests that the single description changes are not discarded when a user starts editing a new one
        """
        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        row = bp.listing_row('First something 1234 (1)')
        description = row.find_element_by_css_selector(
            'div.body span.description')
        assert description.text == 'invisible gloves'
        click(description)
        sleep(1)

        form = row.find_element_by_css_selector('div.body form > textarea')
        click(form)
        send_keys(form, ' Test')

        # click on the second description
        row2 = bp.listing_row('Second something 1235 (2)')
        description2 = row2.find_element_by_css_selector(
            'div.body span.description')
        click(description2)

        # check the 1st description is saved
        row = bp.listing_row('First something 1234 (1)')
        description = row.find_element_by_css_selector(
            'div.body span.description')
        assert description.text == 'invisible gloves Test'
예제 #2
0
def select_listings_to_edit(driver, operation='Add Before'):
    mp = MainPage(driver)
    bp = BulkPage(driver)

    mp.select_listings_to_edit()
    click(bp.edit_part('Description'))
    bp.select_operation(operation)
예제 #3
0
    def test_sync_description(self):
        """ Tests that data is written to the database when [Sync Updates] is clicked
        """
        expected_data = [['1', 'invisible gloves New Description']]

        d = self.driver
        select_listings_to_edit(d)

        bp = BulkPage(d)

        row = bp.listing_row('First something 1234 (1)')
        description = row.find_element_by_css_selector(
            'div.body span.description')

        click(description)
        sleep(1)

        form = row.find_element_by_css_selector('div.body form > textarea')
        click(form)
        send_keys(form, ' New Description')
        click(
            d.find_element_by_css_selector('bulk-edit-dashboard-op-container'))
        sleep(1)

        click(bp.sync_updates_button())

        wait_for_assert(
            expected_data,
            lambda: run_sql('HIVE', 'select_description_modified', True),
            'Unexpected data in DB')
예제 #4
0
    def test_single_description_required(self):
        """ Tests that single description cannot be changed to empty
        """
        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        row = bp.listing_row('First something 1234 (1)')
        description = row.find_element_by_css_selector(
            'div.body span.description')
        click(description)
        sleep(1)

        # delete description and check error message
        form = row.find_element_by_css_selector('div.body form > textarea')
        click(form)
        send_keys(form, BACKSPACE_KEYS * 4)
        sleep(1)

        error_text = bp.error_baloon_texts(row)
        assert error_text == ['Description is required']

        # click away and check that description was not changed
        click(
            d.find_element_by_css_selector('bulk-edit-dashboard-op-container'))
        description_text = row.find_element_by_css_selector(
            'div.body span.description').text
        assert description_text == 'invisible gloves'
예제 #5
0
    def test_edit_single_description(self):
        """ Tests that single description can be edited, including special characters
        """
        select_listings_to_edit(self.driver)
        d = self.driver
        mp = MainPage(d)
        bp = BulkPage(d)

        row = bp.listing_row('First something 1234 (1)')
        description = row.find_element_by_css_selector(
            'div.body span.description')
        assert description.text == 'invisible gloves'
        click(description)
        sleep(1)

        form = row.find_element_by_css_selector('div.body form > textarea')
        click(form)
        send_keys(form, ' Hello<b> &amp; > 1')
        click(
            d.find_element_by_css_selector('bulk-edit-dashboard-op-container'))
        sleep(1)

        description_text = row.find_element_by_css_selector(
            'div.body span.description').text
        assert description_text == 'invisible gloves Hello<b> &amp; > 1'
예제 #6
0
def select_listings_to_edit(driver, operation='Add'):
    mp = MainPage(driver)
    bp = BulkPage(driver)

    mp.select_listings_to_edit()
    click(bp.edit_part('Tags'))
    bp.select_operation(operation)
예제 #7
0
def select_listings_to_edit(request):
    """
    select listings for bulk,
      - self.listings_to_select is on of:
            None -> use default
            ["listing1", "listin2"...] -> use this
            "ALL" -> select all
      - self.listing_status  -> e.g. 'Draft'
      - choose `self.bulk_tab`

    """
    self = request.node.parent.obj

    mp = MainPage(self.driver)
    bp = BulkPage(self.driver)

    try:
        listing_status = self.listing_status
    except AttributeError:
        listing_status = None

    try:
        listings_to_select = self.listings_to_select
    except AttributeError:
        listings_to_select = None

    try:
        bulk_tab = self.bulk_tab
    except AttributeError:
        bulk_tab = None

    mp.select_listings_to_edit(listings_to_select, status=listing_status)
    if bulk_tab:
        click(bp.edit_part(bulk_tab))
예제 #8
0
    def test_bulk_edit_view_listings_checked(self):
        """ Tests that the bulk edit view shows the listings checked on all pages
        """
        d = self.driver
        pg = MainPage(d)
        bp = BulkPage(d)

        pg.select_filter_tab('Active')
        sleep(1)

        # check all
        click(pg.listing_select_all_checkbox())
        assert pg.edit_listings_button().text == 'Edit 102 Listings'

        # clck the Edit Listings
        click(pg.edit_listings_button())
        sleep(1)

        # check the listings 1st page
        listing_rows = bp.listing_rows()
        assert len(listing_rows) == 25
        for listing_row in listing_rows:
            row_class = listing_row.get_attribute('class')
            assert 'selected' in row_class.split(' ')

        click(bp.next_page_button())
        sleep(2)

        # check the listings 2nd page
        listing_rows = bp.listing_rows()
        assert len(listing_rows) == 50
        for listing_row in listing_rows:
            row_class = listing_row.get_attribute('class')
            assert 'selected' in row_class.split(' ')
예제 #9
0
def select_listings_to_edit(driver, holiday=None):
    mp = MainPage(driver)
    bp = BulkPage(driver)

    mp.select_listings_to_edit(checked_listings='ALL')
    click(bp.edit_part('Holiday'))
    if holiday is not None:
        bp.select_holiday(holiday)
예제 #10
0
    def select_listings_to_edit(self, operation=None):
        mp = MainPage(self.driver)
        bp = BulkPage(self.driver)

        mp.select_listings_to_edit()
        click(bp.edit_part('Quantity'))
        if operation is not None:
            bp.select_operation(operation)
예제 #11
0
def select_listings_to_edit(driver, occasion=None):
    mp = MainPage(driver)
    bp = BulkPage(driver)

    mp.select_listings_to_edit(checked_listings='ALL')
    click(bp.edit_part('Occasion'))
    if occasion is not None:
        bp.select_occasion(occasion)
예제 #12
0
    def setup_method(self, method):
        super().setup_method(method)
        lpg = LoginPage(self.driver)
        lpg.login(page=self.login_url_http)

        mp = MainPage(self.driver)
        bp = BulkPage(self.driver)
        mp.select_listings_to_edit()
        click(bp.edit_part('Photos'))
예제 #13
0
    def test_create_tag_too_long(self):
        """ Tests that a tag cannot be longer than 20 characters
        """
        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        send_keys(bp.operation_input(), 'AAAAABBBBBCCCCCDDDDDE')
        err = bp.error_baloon()
        assert err == "Maximum length of tag is 20"
예제 #14
0
    def test_bulk_category_variations_validation(self):
        """ Test verifies that error message is shown when attempting to change Category to incompatible
        with existing Variation property / scale on the listing, and that Category is not changed for such listing
        """

        expected_categories = [
            ['Jewelry', 'Brooches'],
            ['Jewelry', 'Brooches'],
            ['Clothing', 'Women\'s Clothing', 'Dresses']
        ]

        category = ['Jewelry', 'Brooches']

        bp = BulkPage(self.driver)
        # change to incompatible category (3rd listing)
        bp.select_category(category)

        row = bp.listing_row('Product #3 with two variations with quantity on both and pricing on both')

        # check that error is shown
        assert bp.error_baloon_texts(row) ==\
            ['The selected category is not compatible with the variations of this listing'],\
            'Incorrect validation error message for listing #3'

        # Apply and check that category was set for 1st and 2nd listings, for 3rd it hasn't changed
        click(bp.operation_apply())
        for i, row in enumerate(bp.listing_rows()):
            category_names = bp.category_names(row)
            assert category_names == expected_categories[i]
예제 #15
0
    def test_title_replace(self):
        """ Tests title replace - basic test
        """

        expected_listings_1 = [
            'Prvni something 1234 (1)\n116 characters remaining',
            'Second something 1235 (2)\n115 characters remaining',
            'Third something LG-512a (3)\n113 characters remaining'
        ]

        select_listings_to_edit(self.driver, 'Find & Replace')
        d = self.driver
        bp = BulkPage(d)

        input_find_field = bp.operation_input_find()
        input_replace_field = bp.operation_input_replace()

        # Normal Replace
        send_keys(input_find_field, 'First')
        send_keys(input_replace_field, 'Prvni')
        listings = bp.listing_rows_texts_sorted()
        assert listings == expected_listings_1

        # Apply (client only)
        click(bp.operation_apply())
        sleep(1)
        listings = bp.listing_rows_texts_sorted()
        assert listings == expected_listings_1

        apply_class = bp.operation_apply().get_attribute('class')
        assert 'inactive' in apply_class.split(' ')
예제 #16
0
    def test_create_category(self):
        """ Tests that a category can be created in bulk edit
        """
        expected_listings_01 = [
            'First something 1234 (1)\nClothing\nMen\'s Clothing\nSocks\nChoose Category',
            'Second something 1235 (2)\nClothing\nMen\'s Clothing\nSocks\nChoose Category',
            'Third something LG-512a (3)\nClothing\nMen\'s Clothing\nPants'
        ]

        expected_listings_02 = [
            'First something 1234 (1)\nAccessories\nCostume Accessories\nCostume Tails & Ears\nCostume Ears',
            'Second something 1235 (2)\nAccessories\nCostume Accessories\nCostume Tails & Ears\nCostume Ears',
            'Third something LG-512a (3)\nAccessories\nCostume Accessories\nCostume Tails & Ears\nCostume Ears'
        ]

        self.select_listings_to_edit()
        d = self.driver
        bp = BulkPage(d)

        actual_listings = bp.listing_rows_texts_sorted()
        assert actual_listings == expected_listings_01

        bp.select_category(['Accessories', 'Costume Accessories', 'Costume Tails & Ears', 'Costume Ears'])


            # Apply changes
        click(bp.operation_apply())
        actual_listings = bp.listing_rows_texts_sorted()
        assert actual_listings == expected_listings_02

        apply_class = bp.operation_apply().get_attribute('class')
        assert 'inactive' in apply_class.split(' ')
예제 #17
0
    def test_create_tag_special_chars(self):
        """ Tests that a tag can be created in bulk edit with czech chars, but not special chars
        """
        expected_tags = [
            ['Tag01', 'žvýkačky'],
            ['Tag01', 'žvýkačky'],
            ['Tag01', 'žvýkačky'],
        ]

        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        send_keys(bp.operation_input(), 'žvýkačky')
        click(bp.operation_apply())

        apply_class = bp.operation_apply().get_attribute('class')
        assert 'inactive' in apply_class.split(' ')

        tag_names = bp.tag_names()
        assert tag_names == expected_tags

        send_keys(bp.operation_input(), 'me@site')
        err = bp.error_baloon()
        assert err == "Tag can only include spaces, letters, hyphens, and numbers"
예제 #18
0
    def test_inline_section_remove(self):
        """ Tests removing section from a single listing
        """

        expected_section_names = ['Summer Sale', 'Choose Section']

        expected_api_calls = [{
            'PUT': '/v2/listings/100002?shop_section_id=0',
            'body': {
                'listing_id': 100002,
                'state': 'active'
            }
        }]

        bp = BulkPage(self.driver)
        bp.select_single_section('Second something 1235', 'None')

        # Check listings
        assert bp.section_names() == expected_section_names

        # Check that sync button is enabled after clicking on Apply
        wait_for_web_assert(True,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not enabled')

        # Sync changes
        click(bp.sync_updates_button())

        # Check that sync button is disabled after clicking on Sync
        wait_for_web_assert(False,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not disabled')

        # Check API calls to Etsy emulator - section should be set to None on one listing
        check_etsy_emulator_requests(expected_api_calls)
예제 #19
0
    def test_inline_occasion_delete(self):
        """ Tests deleting occasion from a listing using inline edit
        """

        self.custom_setup('listings_delete_occasion')

        expected_listings = [
            'Four\nThe category of this listing does not support occasion',
            'One\nChoose Occasion', 'Three\nChoose Occasion',
            'Two\nChoose Occasion'
        ]

        expected_occasion_db = []

        expected_api_calls = [{
            'DELETE': '/v2/listings/100001/attributes/46803063641',
            'body': {}
        }]

        select_listings_to_edit(self.driver)
        bp = BulkPage(self.driver)

        # Delete occasion from listing
        bp.select_single_occasion('One', 'None')

        # Check listings
        actual_listings = bp.listing_rows_texts_sorted()
        assert actual_listings == expected_listings

        # Check that sync button is enabled and blue dot is displayed after clicking on Apply
        wait_for_web_assert(True,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not enabled')
        assert bp.is_part_modified(
            'Occasion') is True, 'Blue dot didn\'t show up'

        # Sync changes
        click(bp.sync_updates_button())

        # Check that sync button is disabled and blue dot is not displayed after clicking on Sync
        wait_for_web_assert(False,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not disabled')
        assert bp.is_part_modified(
            'Occasion') is False, 'Blue dot is still shown'

        # Check Etsy requests and occasion data in DB after resync
        check_etsy_emulator_requests(expected_api_calls)
        check_db_state(expected_occasion_db)
예제 #20
0
 def select_single(self, row, position, new_value):
     d = self.driver
     bp = BulkPage(d)
     element = bp.category_elements(row)[position]
     click(element)
     sleep(2)
     category_found = False
     for item in element.find_elements_by_css_selector('div.bulk-edit-dropdown ul li'):
         if item.text == new_value:
             d.execute_script("arguments[0].scrollIntoView(true);", item);
             click(item)
             sleep(1)
             category_found = True
             break
     if not category_found:
         raise Exception("Error: select_single: " + new_value + " not found")
예제 #21
0
    def test_bulk_holiday_delete(self):
        """ Tests deleting holiday from listings using bulk
        """

        self.custom_setup('listings_delete_holiday_bulk')

        expected_listings = [
            'Four\nThe category of this listing does not support holiday',
            'One\nChoose Holiday', 'Three\nChoose Holiday',
            'Two\nChoose Holiday'
        ]

        expected_holiday_db = []

        expected_api_calls = [{
            'DELETE': '/v2/listings/100002/attributes/46803063659',
            'body': {}
        }, {
            'DELETE': '/v2/listings/100003/attributes/46803063659',
            'body': {}
        }]

        # Delete holiday from listings using bulk
        select_listings_to_edit(self.driver, 'None')
        bp = BulkPage(self.driver)

        # Apply changes and check listings
        click(bp.operation_apply())
        actual_listings = bp.listing_rows_texts_sorted()
        assert actual_listings == expected_listings

        # Check that sync button is enabled and blue dot is displayed after clicking on Apply
        wait_for_web_assert(True,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not enabled')
        assert bp.is_part_modified(
            'Holiday') is True, 'Blue dot didn\'t show up'

        # Sync changes
        click(bp.sync_updates_button())

        # Check that sync button is disabled and blue dot is not displayed after clicking on Sync
        wait_for_web_assert(False,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not disabled')
        assert bp.is_part_modified(
            'Holiday') is False, 'Blue dot is still shown'

        # Check Etsy requests and holiday data in DB after resync
        check_etsy_emulator_requests(expected_api_calls)
        check_db_state(expected_holiday_db)
예제 #22
0
    def test_bulk_holiday_set(self):
        """ Tests setting/changing holiday using bulk on listings
        """

        self.custom_setup('listings_push_attributes')

        expected_listings = [
            'Four\nThe category of this listing does not support holiday',
            'One\nChristmas', 'Three\nChristmas', 'Two\nChristmas'
        ]

        expected_api_calls = [{
            'PUT': '/v2/listings/100001/attributes/46803063659?value_ids=35',
            'body': {}
        }, {
            'PUT': '/v2/listings/100002/attributes/46803063659?value_ids=35',
            'body': {}
        }, {
            'PUT': '/v2/listings/100003/attributes/46803063659?value_ids=35',
            'body': {}
        }]

        # Set/change holiday using bulk
        select_listings_to_edit(self.driver, 'Christmas')
        bp = BulkPage(self.driver)

        # Apply changes and check listings
        click(bp.operation_apply())
        actual_listings = bp.listing_rows_texts_sorted()
        assert actual_listings == expected_listings

        # Check that sync button is enabled and blue dot is displayed after clicking on Apply
        wait_for_web_assert(True,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not enabled')
        assert bp.is_part_modified(
            'Holiday') is True, 'Blue dot didn\'t show up'

        # Sync changes
        click(bp.sync_updates_button())

        # Check that sync button is disabled and blue dot is not displayed after clicking on Sync
        wait_for_web_assert(False,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not disabled')
        assert bp.is_part_modified(
            'Holiday') is False, 'Blue dot is still shown'

        # Check holiday data in DB and Etsy requests
        check_etsy_emulator_requests(expected_api_calls)
예제 #23
0
    def test_edit_single_category(self):
        """ Tests that a single category can be edited
        """
        expected_listings_01 = [
            'First something 1234 (1)\nClothing\nMen\'s Clothing\nSocks\nChoose Category',
            'Second something 1235 (2)\nClothing\nMen\'s Clothing\nSocks\nChoose Category',
            'Third something LG-512a (3)\nClothing\nMen\'s Clothing\nPants'
        ]

        expected_data = [['1', '1761']]

        self.select_listings_to_edit()
        d = self.driver
        bp = BulkPage(d)

        actual_listings = bp.listing_rows_texts_sorted()
        assert actual_listings == expected_listings_01

        # update category of the 1st listing
        row = bp.listing_row('First something 1234 (1)')
        bp.select_category(['Accessories', 'Costume Accessories', 'Costume Tails & Ears', 'Costume Ears'], row, True)

        click(bp.sync_updates_button())

        wait_for_assert(expected_data,
                        lambda: run_sql('HIVE', 'select_taxonomy_id_modified', True),
                        'Unexpected taxonomy ID in DB')
예제 #24
0
    def test_title_add_before_length(self):
        """ Tests add before where length limit is exceeded
        """

        long_text = 'Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong'
        expected_listings_1 = [
            long_text + 'First something 1234 (1)\n2 characters remaining',
            long_text + 'Second something 1235 (2)\n1 character remaining',
            long_text + 'Third something LG-512a (3)\n1 character over limit'
        ]
        expected_listings_2 = [
            long_text + 'First something 1234 (1)\n2 characters remaining',
            long_text + 'Second something 1235 (2)\n1 character remaining',
            'Third something LG-512a (3)\n113 characters remaining'
        ]

        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        input_field = bp.operation_input()

        # Test long text
        send_keys(input_field, long_text)
        listings = bp.listing_rows_texts_sorted()
        assert listings == expected_listings_1

        # Apply (client only)
        click(bp.operation_apply())
        sleep(1)
        listings = bp.listing_rows_texts_sorted()
        assert listings == expected_listings_2

        apply_class = bp.operation_apply().get_attribute('class')
        assert 'inactive' in apply_class.split(' ')
예제 #25
0
    def test_title_delete(self):
        """ Tests tile delete basic
        """

        expected_listings_1 = [
            'First something 1234 (1)\n122 characters remaining',
            'Second something 1235 (2)\n115 characters remaining',
            'Third something LG-512a (3)\n113 characters remaining'
        ]

        expected_listings_2 = [
            'Second something 1235 (2)\n115 characters remaining',
            'Third something LG-512a (3)\n113 characters remaining',
            'something 1234 (1)\n122 characters remaining'
        ]

        select_listings_to_edit(self.driver, 'Delete')
        d = self.driver
        bp = BulkPage(d)

        input_field = bp.operation_input()

        # Normal Delete
        send_keys(input_field, 'First ')
        listings = bp.listing_rows_texts_sorted()
        assert listings == expected_listings_1

        # Apply (client only)
        click(bp.operation_apply())
        sleep(1)
        listings = bp.listing_rows_texts_sorted()
        assert listings == expected_listings_2

        apply_class = bp.operation_apply().get_attribute('class')
        assert 'inactive' in apply_class.split(' ')
예제 #26
0
    def test_title_add_before_starting_chars(self):
        """ Tests that add before title starts with valid chars
        """
        expected_listings_1 = [
            '123First something 1234 (1)\n113 characters remaining',
            '123Second something 1235 (2)\n112 characters remaining',
            '123Third something LG-512a (3)\n110 characters remaining'
        ]

        expected_listings_2 = [
            '@ First something 1234 (1)\nMust begin with alphanumerical character',
            '@ Second something 1235 (2)\nMust begin with alphanumerical character',
            '@ Third something LG-512a (3)\nMust begin with alphanumerical character'
        ]

        expected_listings_3 = [
            'á First something 1234 (1)\n114 characters remaining',
            'á Second something 1235 (2)\n113 characters remaining',
            'á Third something LG-512a (3)\n111 characters remaining'
        ]

        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        input_field = bp.operation_input()

        # Test 123 prefix - OK
        send_keys(input_field, '123')
        listings = bp.listing_rows_texts_sorted()
        error_msg = bp.error_baloon()
        assert error_msg == ''
        assert listings == expected_listings_1

        # Test @ prefix - show error, temp title does not contain it
        send_keys(input_field, BACKSPACE_KEYS)
        send_keys(input_field, '@ ')
        sleep(2)
        listings = bp.listing_rows_texts_sorted()
        error_msg = bp.error_baloon()
        assert error_msg == 'Must begin with alphanumerical character'
        assert listings == expected_listings_2

        # Test á prefix - no error, temp title contains it
        send_keys(input_field, BACKSPACE_KEYS)
        send_keys(input_field, 'á ')
        listings = bp.listing_rows_texts_sorted()
        error_msg = bp.error_baloon()
        assert error_msg == ''
        assert listings == expected_listings_3
예제 #27
0
    def test_create_material_multi_basic(self):
        """ Tests that multiple materials can be created in bulk edit
        """
        expected_materials = [
            ['cotton', 'AAA', 'BBB', 'CCC'],
            ['cotton', 'AAA', 'BBB', 'CCC'],
            ['wool', 'AAA', 'BBB', 'CCC'],
        ]

        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        send_keys(bp.operation_input(), 'AAA,BBB   ,CCC')
        click(bp.operation_apply())

        material_names = bp.material_names()
        assert material_names == expected_materials
예제 #28
0
    def test_delete_material(self):
        """ Tests that materials can be deleted in bulk
        """
        expected_materials = [
            [],
            ['cotton'],
            ['cotton'],
        ]

        select_listings_to_edit(self.driver, 'Delete')
        d = self.driver
        bp = BulkPage(d)

        send_keys(bp.operation_input(), 'wool')
        click(bp.operation_apply())

        material_names = bp.material_names()
        assert material_names == expected_materials
예제 #29
0
    def test_title_add_before_correct(self):
        """ Tests that correct text can be added before
        """
        expected_listings = [
            'hello First something 1234 (1)\n110 characters remaining',
            'hello Second something 1235 (2)\n109 characters remaining',
            'hello Third something LG-512a (3)\n107 characters remaining'
        ]

        select_listings_to_edit(self.driver)
        d = self.driver
        bp = BulkPage(d)

        input_field = bp.operation_input()
        send_keys(input_field, 'hello ')

        listings = bp.listing_rows_texts_sorted()
        assert listings == expected_listings
예제 #30
0
    def test_bulk_section_add(self):
        """ Tests adding a new section and setting it to listings using bulk operation
        """

        new_section_name = 'New section'

        expected_section_names = [new_section_name] * 2

        expected_api_calls = [{
            'POST': '/v2/shops/14458117/sections?title=New%20section',
            'body': {}
        }, {
            'PUT': '/v2/listings/100001',
            'body': {
                'listing_id': 100001,
                'shop_section_id': '66666666',
                'state': 'active'
            }
        }, {
            'PUT': '/v2/listings/100002',
            'body': {
                'listing_id': 100002,
                'shop_section_id': '66666666',
                'state': 'active'
            }
        }]

        bp = BulkPage(self.driver)
        bp.add_new_section(new_section_name)

        # Apply changes and check listings
        click(bp.operation_apply())
        assert bp.section_names() == expected_section_names

        # Check that sync button is enabled after clicking on Apply
        wait_for_web_assert(True,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not enabled')

        # Sync changes
        click(bp.sync_updates_button())

        # Check that sync button is disabled after clicking on Sync
        wait_for_web_assert(False,
                            bp.sync_updates_button().is_enabled,
                            'Sync button is not disabled')

        # Check API calls to Etsy emulator - new section should be created and two listings updated
        check_etsy_emulator_requests(expected_api_calls)