Пример #1
0
def test_add_creative_without_site(client, fill_db):
    '''
    Checks if when we save advert without custom landing page,
    no Site object related to advert is saved to db.
    '''
    utils.go_to_step(client, 'creatives', existing=True)

    client.click_on_button('add')

    container = client.find_elements_by_class_name('-t-creatives-widget')[-1]
    add_creative_btn = container.find_element_by_class_name('-t-button-creative-storage')
    client.click(add_creative_btn)

    client.wait_for_tray('trayCreatives')
    creatives = client.find_elements_by_css_selector('.-creatives-list li')

    # check random creative from tray
    creative = choice(creatives)
    creative.click()

    creative_name = creative.text

    # save strategy and return to the creatives
    utils.save_and_return_to_step(client)

    # check db if advert without Site object is created
    strategy = Strategy.objects.all()[0]

    adverts = strategy.advert_set.filter(
        is_deleted=False,
        creative__name=creative_name,
        landing_site__isnull=True
    )

    assert adverts.count() == 1
Пример #2
0
def test_audiences_widget(client, fill_db):
    '''
        Tests adding and removing audiences from targeting, both in UI and DB
    '''

    def get_audiences_from_widget(client):
        return client.find_elements_by_css_selector('.-t-audience-list li')

    def get_audiences_from_tray(client):
        return client.find_elements_by_css_selector('.-t-audience-tray-list li')

    utils.go_to_step(client, 'targeting', existing=True)

    # Set default timeout for this test.
    client.implicitly_wait(1)

    # Check if widget is created empty
    display_widget(client, 'Audiences')
    widget_class = '-t-widget-%s-%s' % ('include', 'Audiences')

    audiences_included = get_audiences_from_widget(client)

    assert len(audiences_included) == 0

    # Check if audiences in tray are displayed
    client.click_on_class('add-audience')
    client.wait_for_tray('trayAudiences')
    audiences_in_tray = get_audiences_from_tray(client)
    audiences_tray_names = [a.text for a in audiences_in_tray]
    audiences_from_db = Audience.objects.values_list('name', flat=True)

    assert sorted(audiences_tray_names) == sorted(audiences_from_db)

    # Check selecting an audience
    selected_audience = audiences_in_tray[0]
    selected_name = selected_audience.text
    client.click(selected_audience)

    audiences_included = get_audiences_from_widget(client)
    assert len(audiences_included) == 1
    assert audiences_included[0].text == selected_name

    # Check saving audience
    utils.save_and_return_to_step(client)

    audiences_included = get_audiences_from_widget(client)
    assert len(audiences_included) == 1
    assert audiences_included[0].text == selected_name

    # Check removing audience
    audiences_included = get_audiences_from_widget(client)
    remove_button = audiences_included[0].find_element_by_class_name('remove')
    client.click(remove_button)

    audiences_included = get_audiences_from_widget(client)
    assert len(audiences_included) == 0

    utils.save_and_return_to_step(client)

    assert client.is_present_in_DOM(widget_class) is False
Пример #3
0
def test_creative_delete(client, fill_db):
    REMOVED_CREATIVE = {}

    utils.go_to_step(client, 'creatives', existing=True)
    client.wait_until_displayed('-t-creatives-container')

    # Store info about first add in strategy
    REMOVED_CREATIVE['name'] = client.get_input('creative-name').get_attribute('value')
    REMOVED_CREATIVE['landing_site'] = client.get_input('landing-site').get_attribute('value')
    REMOVED_CREATIVE['js-code'] = client.get_input('js-code').get_attribute('value')

    # Remove first ad
    client.click_on_class('remove-ad')

    # Save strategy
    utils.save_and_return_to_step(client)

    # Check UI and db
    adverts_data = get_adverts_data(client)

    assert REMOVED_CREATIVE not in adverts_data

    strategy = Strategy.objects.all()[0]

    removed_adverts = strategy.advert_set.filter(
        is_deleted=True,
        creative__name=REMOVED_CREATIVE['name'],
        landing_site__url=REMOVED_CREATIVE['landing_site'],
        js_code=REMOVED_CREATIVE['js-code']
    )

    assert removed_adverts.count() == 1
Пример #4
0
def test_landing_pages_correct(client, fill_db):
    '''
        Inserts valid landing pages data,
        checks if they are saved and displayed correctly
    '''

    correct_landing_pages = [
        {'url': 'http://www.wykop.pl', 'weight': 10},
        {'url': 'http://www.gazeta.pl', 'weight': 30},
    ]
    utils.go_to_step(client, 'landing', existing=True)

    client.implicitly_wait(1)

    # Remove all lading pages and test if validation error is raised on save
    input_row_class = '-t-landing-page-row'
    input_rows = client.find_elements_by_class_name(input_row_class)
    for row in input_rows:
        client.click(client.find_element_by_class_name('remove'))

    for index in range(0, len(correct_landing_pages)):
        client.click_on_button('add')

    input_rows = client.find_elements_by_class_name(input_row_class)
    page_class = '-t-input-landing-page'
    weight_class = '-t-input-weight'
    for i, page in enumerate(correct_landing_pages):
        row = input_rows[i]
        url_input = row.find_element_by_class_name(page_class)
        weight_input = row.find_element_by_class_name(weight_class)
        url_input.clear()
        weight_input.clear()
        url_input.send_keys(page['url'])
        weight_input.send_keys(page['weight'])

    utils.save_and_return_to_step(client)

    strategy = Strategy.objects.all()[0]
    landing_pages = strategy.landing_sites.all()

    assert len(landing_pages) == len(correct_landing_pages)

    # Check sites in DB
    for page in correct_landing_pages:
        match_url_and_ratio = lambda el: (el.site.url == page['url']) and (el.ratio == page['weight'])
        matched_sites = filter(match_url_and_ratio, landing_pages)
        assert len(matched_sites) == 1

    # Check sites in UI
    input_rows = client.find_elements_by_class_name(input_row_class)
    for row in input_rows:
        displayed_url = row.find_element_by_class_name(page_class).get_attribute('value')
        displayed_weight = row.find_element_by_class_name(weight_class).get_attribute('value')
        match_url_and_ratio = lambda el: (el['url'] == displayed_url) and (str(el['weight']) == displayed_weight)
        matched_sites = filter(match_url_and_ratio, correct_landing_pages)
        assert len(matched_sites) == 1
Пример #5
0
def test_creative_edit(client, fill_db):
    CREATIVE = {
        'landing_site': 'http://test.site.com',
        'JSCode': 'console.log("no code tehre")',
    }

    utils.go_to_step(client, 'creatives', existing=True)

    # Edit first of creatives (choose one from storage)
    client.click_on_button('creative-storage')
    client.wait_for_tray('trayCreatives')
    creatives = client.find_elements_by_css_selector('.-creatives-list li')

    # check random creative from tray
    creative = choice(creatives)
    creative.click()

    CREATIVE['name'] = creative.text

    # Try to type invalid site
    client.send_keys('landing-site', 'not a site in fact', clear=True)
    client.click_on_class('button-save-changes')

    client.wait_for_modal()

    assert SITE_ERROR in client.get_modal_errors()

    client.close_modal()

    # Change landing site and jscode for proper ones
    client.send_keys('landing-site', CREATIVE['landing_site'], clear=True)
    # Show custom tracker
    client.click_on_class('show-js-code-input')
    client.send_keys('js-code', CREATIVE['JSCode'], clear=True, focus_css_selector=False)

    # save strategy and return to the creatives
    utils.save_and_return_to_step(client)

    # check UI and DB
    assert CREATIVE['name'] == client.get_input('creative-name').get_attribute('value')
    assert CREATIVE['landing_site'] == client.get_input('landing-site').get_attribute('value')
    assert CREATIVE['JSCode'] == client.get_input('js-code').get_attribute('value')

    strategy = Strategy.objects.all()[0]

    adverts = strategy.advert_set.filter(
        is_deleted=False,
        creative__name=CREATIVE['name'],
        landing_site__url=CREATIVE['landing_site'],
        js_code=CREATIVE['JSCode']
    )

    assert adverts.count() == 1
Пример #6
0
def test_strategy_overall(client, fill_db):
    '''
    Tries to save strategy without required fields,
    Check errors and fill inputs with proper data.
    Saves strategy and checks UI and DB.
    '''
    EDITED_STRATEGY = {
        'name': 'Strategy Edited',
        'budget': '50',
        'budget-daily': '20',
    }

    ERRORS = {
        'name_required': 'Strategy name: This field is required.',
        'budget_required': 'Total strategy budget: This field is required.',
    }

    INPUTS = ['name', 'budget', 'budget-daily']

    utils.go_to_step(client, 'overall', existing=True)

    # Clear all inputs
    for input_name in INPUTS:
        client.get_input(input_name).clear()

    # Try to save and check if correct errors are displayed
    client.click_on_class('button-save-changes')
    client.wait_for_modal()
    modal_errors = client.get_modal_errors()

    assert len(modal_errors) == len(ERRORS)
    for key in ERRORS.keys():
        assert ERRORS[key] in modal_errors

    client.close_modal()

    # Fill inputs with proper data
    for input_name in INPUTS:
        client.send_keys(input_name, EDITED_STRATEGY[input_name])

    # Save again and check UI and DB
    utils.save_and_return_to_step(client)

    for input_name in INPUTS:
        assert client.get_input_val(input_name) == EDITED_STRATEGY[input_name]

    strategy = Strategy.objects.all()[0]

    assert strategy.name == EDITED_STRATEGY['name']
    assert strategy.budget_total == Decimal(EDITED_STRATEGY['budget'])
    assert strategy.budget_daily == Decimal(EDITED_STRATEGY['budget-daily'])
Пример #7
0
def test_add_video_creative(client, video_db):
    """Checks saving strategy with video creative"""
    VIDEO_CREATIVE_NAME = 'creative_video_1'
    utils.go_to_step(client, 'creatives', existing=True)

    creative_edit = StrategyPage(client)

    # Check if both trackers are hidden
    creative_edit.assert_both_textareas_hidden()

    # Add a custom JS tracker
    creative_edit.show_js_code()
    creative_edit.js_code.send_keys('console.log("some tracker")')

    # Choose video creative from storage, check if its name is displayed in input
    creative_edit.remove_button.click()
    creative_edit.select_creative_from_tray(VIDEO_CREATIVE_NAME)
    creative_edit.check_name(VIDEO_CREATIVE_NAME)

    # Custom JS tracker should be cleared and disabled
    creative_edit.show_js_code(should_fail=True)
    assert creative_edit.js_code.get_attribute('value') == ''

    # Save and check if changes have been saved
    utils.save_and_return_to_step(client)

    creative_edit.refresh()
    creative_edit.check_name(VIDEO_CREATIVE_NAME)

    strategy_name = client.find_element_by_class_name('-t-name').text
    strategy = Strategy.objects.get(name=strategy_name)

    adverts = strategy.advert_set.filter(
        is_deleted=False,
        creative__name=VIDEO_CREATIVE_NAME
    )

    assert adverts.count() == 1
Пример #8
0
def test_upload_creative(client, fill_db, creative_name, creative_type):
    """Upload creative from strategy edit"""
    CREATIVE_PATH = os.path.abspath(os.path.join(
        os.path.dirname(__file__), '..', 'uploads', creative_name
    ))
    utils.go_to_step(client, 'creatives', existing=True)

    strategy_name = client.find_element_by_class_name('-t-name').text
    strategy = Strategy.objects.get(name=strategy_name)

    # Creative with this name should not exist
    with pytest.raises(Advert.DoesNotExist):
        strategy.advert_set.get(
            is_deleted=False,
            creative__name=creative_name
        )

    creative_edit = StrategyPage(client)
    creative_edit.remove_button.click()

    # Upload file and check if its name is displayed in form
    creative_edit.upload_file(CREATIVE_PATH)

    def file_name_updated():
        return creative_edit.file_name.get_attribute('value') == creative_name
    client.wait_until(file_name_updated)

    # Save and check if creative has been created
    utils.save_and_return_to_step(client)

    creative_edit.refresh()
    creative_edit.check_name(creative_name)

    advert = strategy.advert_set.get(
        is_deleted=False,
        creative__name=creative_name
    )
    assert advert.creative.type == creative_type
Пример #9
0
def test_automatic_bidding(client, bidding_db):
    """Check automatic bidding behaviour."""

    utils.go_to_step(client, 'bidding', existing=True)

    # Check automatic bid price
    client.click_on_class('automatic-bid-price')

    utils.save_and_return_to_step(client)

    strategy = Strategy.objects.all()[0]
    strategy_pk = strategy.pk
    assert strategy.is_automatically_bidded is True
    assert strategy.optimized_metric == CPC.__name__

    # move default metric to the end.
    metrics = list(OPTIMIZATION_METRICS)
    if metrics[0][0] == strategy.optimized_metric:
        cpc_metric = metrics.pop(0)
        metrics.append(cpc_metric)

    for metric, description in metrics:
        # let us check description first if correct
        element_description = client.get_content_elem('-metric-description-' + metric.lower())
        assert client.get_by_tagname(element_description, 'span').text == description
        assert client.get_by_tagname(element_description, 'strong').text == metric

        # first metric will be set up, we'll go to others first to check,
        # and first should be checked last one
        control_element = client.get_content_elem('-controls-' + metric.lower())
        client.click(client.get_by_tagname(control_element, 'span'))
        utils.save_and_return_to_step(client)

        strategy = Strategy.objects.get(pk=strategy_pk)
        assert strategy.is_automatically_bidded is True
        assert strategy.optimized_metric == metric
Пример #10
0
def test_audience_validation(client, fill_db):
    '''
        Tests if Django validation rejects the same audience
        in includes and exludes section
    '''
    def add_audience_to_widget(client, widget):
        add_button = widget.find_element_by_class_name('-t-add-audience')
        client.click(add_button)
        client.wait_for_tray('trayAudiences')
        audiences = client.find_elements_by_css_selector('.-t-audience-tray-list li')
        selected_audience = audiences[0]
        client.click(selected_audience)
        client.wait_for_tray('trayAudiences', hide=True)

    utils.go_to_step(client, 'targeting', existing=True)
    include_widget = display_widget(client, 'Audiences')
    exclude_widget = display_widget(client, 'Audiences', section="exclude")

    add_audience_to_widget(client, include_widget)
    add_audience_to_widget(client, exclude_widget)
    client.click_on_class('button-save-changes')

    modal = client.find_element_by_id('modal')
    assert client.has_class(modal, 'in') is True
Пример #11
0
def test_landing_pages_incorrect(client, fill_db):
    '''
        Inserts invalid or none landing pages,
        checks if validation errors are raised
    '''
    def get_row_count():
        return len(client.find_elements_by_class_name('-t-landing-page-row'))

    ERRORS = {
        'landing_page_invalid_format': 'Landing pages: some landing pages are in incorrect format.'
    }

    empty_page_count = 2

    utils.go_to_step(client, 'landing', existing=True)

    client.implicitly_wait(1)

    # Remove all lading pages
    input_row_class = '-t-landing-page-row'
    input_rows = client.find_elements_by_class_name(input_row_class)
    for row in input_rows:
        row_count_before = get_row_count()
        client.click(client.find_element_by_class_name('remove'))
        row_count_after = get_row_count()

    # Add empty landing pages and check if they are saved correctly
    for index in range(0, empty_page_count):
        row_count_before = get_row_count()
        client.click_on_button('add')
        row_count_after = get_row_count()
        assert row_count_after == row_count_before + 1

    # Check if validation rejects empty urls
    modal_errors = utils.save_with_errors(client)
    assert ERRORS['landing_page_invalid_format'] in modal_errors
Пример #12
0
def test_userprofile_widget(client, fill_db):
    '''
    Tries to save data using checkboxes in User Profile widget.
    Checks if checkbox and tags are correctly saved in UI and
    if data are stored in DB.
    Then tries if when we remove widget data is also removed from DB.
    '''
    # Representant values
    AGE_GROUPS = [t.value for t in TargetValue.objects.representants().filter(category=dimensions.age_group)]
    GENDERS = [t.value for t in TargetValue.objects.representants().filter(category=dimensions.gender)]

    utils.go_to_step(client, 'targeting', existing=True)

    widget = display_widget(client, 'UserProfile')

    # Checked values are stored here
    checked_age_groups = []
    checked_genders = []

    # Test both groups in widget
    for group_name, representants, checked in [
            ('Age Group', AGE_GROUPS, checked_age_groups),
            ('Gender', GENDERS, checked_genders)]:

        group = get_group(widget, group_name)
        checkboxes = group.find_elements_by_class_name('-t-checkbox')

        # Check if labels text comes from representants
        for checkbox in checkboxes:
            checkbox.location_once_scrolled_into_view
            label = checkbox.find_element_by_css_selector('span')
            assert label.text in representants

        # Click random checkboxes
        labels_to_check = sample(representants, randrange(1, len(representants) + 1))
        checked.extend(labels_to_check)

        for label in labels_to_check:
            click_checkbox(group, label)

    # Check if tags are correct
    all_checked = checked_age_groups + checked_genders
    tags = get_tags(widget)
    assert sorted(tags) == sorted(all_checked)

    utils.save_and_return_to_step(client)

    # Check if widget is displayed
    client.wait_until_displayed('-t-widget-include-UserProfile')
    widget = client.find_element_by_class_name('-t-widget-include-UserProfile')
    assert widget.is_displayed() is True

    strategy = Strategy.objects.all()[0]

    # Check displayed data and tags
    for group_name, category, checked in [
            ('Age Group', dimensions.age_group, checked_age_groups),
            ('Gender', dimensions.gender, checked_genders)]:
        group = get_group(widget, group_name)

        for checkbox in group.find_elements_by_class_name('-t-checkbox'):
            checkbox.location_once_scrolled_into_view
            label = checkbox.find_element_by_css_selector('span')
            if label.text in checked:
                client.has_class(checkbox, 'checked') is True
            else:
                client.has_not_class(checkbox, 'checked') is True

        # Check database
        saved_tvalues = [tv.value for tv in strategy.targeting_values.filter(category=category)]
        assert sorted(checked) == sorted(saved_tvalues)

    tags = get_tags(widget)
    assert sorted(tags) == sorted(all_checked)

    client.click_on_class('widget-include-UserProfile-remove')

    utils.save_and_return_to_step(client)

    # Check if widget is not displayed and data is not in DB
    assert client.is_present_in_DOM('-t-widget-include-UserProfile') is False

    strategy = Strategy.objects.all()[0]
    assert strategy.targeting_values.representants().count() == 0
Пример #13
0
def test_bidding_step(client, bidding_db):
    OVERLAP_ERROR = "Bidding: bidding periods can't overlap each other."
    END_BEFORE_START_ERROR = "Bidding: period start can't be later than end."
    QUARTERS_ERROR = 'Bidding: Minutes must be multiples of quarter of an hour.'
    BID_REQUIRED_ERROR = 'Default CPM bid: This field is required.'

    BID_PRICE = '0.50'
    BID_PERIODS = ['08:00:00 - 12:00:00', '12:45:00 - 13:15:00', '13:15:00 - 13:30:00']

    BID_MAPPING = {
        'Creative Default': {
            'type': 'default'
        },
        'Creative Custom': {
            'type': 'custom',
            'value': '2'
        },
        'Creative Parted': {
            'type': 'day_parting',
            'value': '1.50'
        }
    }

    utils.go_to_step(client, 'bidding', existing=True)

    client.wait_until_displayed('-t-bidding-container')
    client.get_input('bid').clear()
    client.click_on_class('enable-dayparting')

    add_bid_periods(client, [
        ('08:00', '12:00'),
        ('12:45', '13:15'),
        ('13:00', '13:15'),  # Overlapping periods
        ('13:15', '13:30'),
        ('14:00', '14:59'),  # Minutes not multiple of 15
        ('17:00', '00:00')  # End before start
    ])

    client.click_on_class('button-save')

    client.wait_for_modal()
    # Check if notification about default bid is shown
    assert BID_REQUIRED_ERROR in client.get_modal_errors()
    # Check if overlapping is detected
    assert OVERLAP_ERROR in client.get_modal_errors()
    # Check if end before start is detected
    assert END_BEFORE_START_ERROR in client.get_modal_errors()
    # Check if not quarter multiple minutes are detected
    assert QUARTERS_ERROR in client.get_modal_errors()
    client.close_modal()

    # Set default bid
    client.send_keys('bid', BID_PRICE)

    # Remove invalid periods
    remove_bid_period(client, '13:00 - 13:15')
    remove_bid_period(client, '14:00 - 14:59')
    remove_bid_period(client, '17:00 - 00:00')

    set_creative_bid_values(client, BID_MAPPING)

    # save strategy
    utils.save_and_return_to_step(client)

    check_creative_bid_values(client, BID_MAPPING)

    # check database
    strategy = Strategy.objects.all()[0]
    adverts = strategy.advert_set.all()
    check_strategy_adverts_in_database(
        strategy, adverts, BID_MAPPING, BID_PERIODS
    )

    # check if creative prated value is zero
    # is should be zero.
    BID_MAPPING["Creative Parted"]["value"] = '0'

    set_creative_bid_values(client, BID_MAPPING)

    # save strategy
    utils.save_and_return_to_step(client)

    check_creative_bid_values(client, BID_MAPPING)

    # check database
    strategy = Strategy.objects.all()[0]
    adverts = strategy.advert_set.all()
    assert strategy.budget_bid_CPM == Decimal(BID_PRICE)
    assert strategy.is_automatically_bidded is False
    assert strategy.optimized_metric is None
    check_strategy_adverts_in_database(
        strategy, adverts, BID_MAPPING, BID_PERIODS
    )
Пример #14
0
def test_text_search_widgets(client, fill_db_mobile_strategies, representants):
    '''
    Tries to select all available text search widgets, make manipulation
    with them (choosing/removing options) and saving strategy.
    Then it removes widgets and tests if they are not present in UI and
    if values are not stored in db.
    '''
    def check_tags_boxes(widget, widget_data):
        tags = get_tags(widget)
        boxes = get_tags(widget, from_box=True)

        assert sorted(tags) == sorted(widget_data['checked'])
        assert sorted(boxes) == sorted(widget_data['checked'])

    SEARCH_WIDGETS = {
        # KANARY-2206
        # 'Device': {
        #     'category': dimensions.g_device,
        #     'checked': [],
        # },
        'Location': {
            'category': dimensions.g_location,
            'checked': [],
        },
        'Os': {
            'category': dimensions.g_os,
            'checked': [],
        },
        'Carrier': {
            'category': dimensions.carrier,
            'checked': [],
        },
    }

    utils.go_to_step(client, 'targeting', existing=True)

    # Set default timeout for this test.
    client.implicitly_wait(1)

    include_target_btn = client.find_element_by_class_name('-t-include-target')

    for widget_name, widget_data in SEARCH_WIDGETS.iteritems():
        include_target_btn.click()
        client.click_on_class('-t-include-%s' % widget_name, bare=True)
        client.wait_until_displayed('-t-widget-include-%s' % widget_name)

        # Scroll down to the button to make sure suggestions are visible
        include_target_btn.location_once_scrolled_into_view

        widget = client.find_element_by_class_name(
            '-t-widget-include-%s' % widget_name
        )

        target_values = TargetValue.objects.representants()\
            .filter(category=widget_data['category'])\
            .order_by('value')\
            .distinct('value')

        values_count = target_values.count()

        # pick some random values from representants (we will type them in widget)
        random_values = sample(target_values, randrange(2, values_count))

        input_field = client.find_element_by_class_name(
            '-t-input-include-%s' % widget_name
        )

        for tv in random_values:
            # Scroll down to the button to make sure suggestions are visible
            include_target_btn.location_once_scrolled_into_view

            # type in input
            lowest_hierarchy = tv.value_list[-1]
            value_to_type = lowest_hierarchy[:3].lower()
            input_field.send_keys(value_to_type)

            # wait for dropdown appearance
            client.wait_until_displayed('tt-dataset-%s' % widget_name)

            # click in dropdown first suggestion
            client.click_on_class('value-%s' % widget_name)

            widget_data['checked'].append(lowest_hierarchy)

        check_tags_boxes(widget, widget_data)

    utils.save_and_return_to_step(client)

    # Check all widgets data and remove each widget
    for widget_name, widget_data in SEARCH_WIDGETS.iteritems():
        client.wait_until_displayed('-t-widget-include-%s' % widget_name)

        widget = client.find_element_by_class_name(
            '-t-widget-include-%s' % widget_name
        )

        assert widget.is_displayed()

        check_tags_boxes(widget, widget_data)

        # check database
        strategy = Strategy.objects.all()[0]
        saved_repr = [tv.value_list[-1] for tv in strategy.targeting_values.representants().filter(
                      category=widget_data['category'])]

        assert sorted(saved_repr) == sorted(widget_data['checked'])

        # remove widget
        client.click_on_class('widget-include-%s-remove' % widget_name)

    utils.save_and_return_to_step(client)

    # for each widget check if db is empty and if it is not displayed
    for widget_name, widget_data in SEARCH_WIDGETS.iteritems():

        assert client.is_present_in_DOM('-t-widget-include-%s' % widget_name) is False

        strategy = Strategy.objects.all()[0]

        assert strategy.targeting_values.representants().filter(category=widget_data['category']).count() == 0
Пример #15
0
def test_add_creative_custom_tracker_tracking_pixel(client, fill_db):
    '''
    Test Custom Pixel and JS Code textareas' states interaction and validation of
    Custom Pixel URL.
    Both textareas are hidden by default.
    '''
    JS_CODE = '   (function(){     }());   '
    PIXEL_URL = ' http://pixel.example.com   '

    utils.go_to_step(client, 'creatives', existing=True)
    creative_edit = StrategyPage(client)

    # The labels should have default values for empty textareas.
    assert creative_edit.js_code_label.text == 'Add tracking'
    assert creative_edit.custom_pixel_label.text == 'Add tracking'
    creative_edit.assert_both_textareas_hidden()

    creative_edit.check_toggling()  # No input - should toggle freely.

    # 1. Add whitespace to both inputs. It should be ignored. Test label text (Add/Hide).
    creative_edit.show_js_code()
    creative_edit.js_code.send_keys(' \n\n ')
    creative_edit.show_custom_pixel()  # Close JS code textarea and open custom pixel.
    creative_edit.custom_pixel.send_keys(' \n\n ')
    creative_edit.hide_custom_pixel()

    creative_edit.check_toggling()  # Whitespace-only input should be ignored and toggling should be possible.

    # 2. Add some non-whitespace chars to the custom pixel input. It should not be possible to
    # switch the textarea now. It should be possible to hide it.
    creative_edit.show_js_code()
    creative_edit.js_code.send_keys(JS_CODE)  # Will also contain prevoiusly inserted whitespace - that's OK.
    # Now it should not be possible to open the other textarea.
    creative_edit.show_custom_pixel(should_fail=True)
    creative_edit.hide_js_code()
    # With JS code hidden try to open custom pixel textarea again:
    creative_edit.show_custom_pixel(should_fail=True)

    # 3. Save the campaign. JS code should be stripped and saved.
    utils.save_and_return_to_step(client)
    creative_edit.refresh()
    creative_edit.assert_both_textareas_hidden()
    creative_edit.show_js_code()
    assert creative_edit.js_code.get_attribute('value') == JS_CODE.strip()

    # 4. Entering custom pixel should fail because we have JS code inserted.
    creative_edit.show_custom_pixel(should_fail=True)
    creative_edit.js_code.clear()  # Clear JS code textarea.
    assert creative_edit.js_code.get_attribute('value') == ''

    # 5. Now with JS code empty it should be possible to insert custom tracker.
    creative_edit.show_custom_pixel()
    creative_edit.custom_pixel.send_keys('My home page')  # Invalid URL.
    creative_edit.show_js_code(should_fail=True)
    creative_edit.hide_custom_pixel()

    client.click_on_class('button-save-changes')
    # Error modal should appear. Handle the error.
    client.wait_for_modal()
    assert SITE_ERROR in client.get_modal_errors()
    client.close_modal()
    assert 'input-error' in creative_edit.custom_pixel.get_attribute('class')

    creative_edit.show_custom_pixel()
    creative_edit.custom_pixel.clear()
    creative_edit.custom_pixel.send_keys(PIXEL_URL)  # Insert a valid URL.

    utils.save_and_return_to_step(client)
    creative_edit.refresh()
    creative_edit.assert_both_textareas_hidden()

    creative_edit.show_custom_pixel()
    assert creative_edit.custom_pixel.get_attribute('value') == PIXEL_URL.strip()
Пример #16
0
def test_brand_protection_widget(client, fill_db):
    '''
        Tests adding and removing brand protection widget
    '''

    strategy = fill_db.models['strategy']['Hello this is Citrus']

    utils.go_to_step(client, 'targeting', existing=True)

    # checking additional data costs counter
    costs = client.find_element_by_class_name('-t-additional-data-costs')
    assert costs.text == '-'

    # adding BRAND PROTECTION widget to INCLUDE section
    widget_type = 'ProximicBrandProtection'
    widget = display_widget(client, widget_type)

    # additional data costs shouldn't be added
    client.wait_until(lambda: costs.text == '-')

    # checking if all segments are available and not selected
    segments = SegmentProximicMaturityRating.objects.all()\
        .values_list('name', flat=True)

    for segment in segments:
        el = client.find_element_by_class_name('-t-protection-%s' % segment)
        assert el
        assert 'active' not in el.get_attribute('class').split()

    # checking segments in database
    assert strategy.segment_proximic_maturity_rating.all().count() == 0

    # selecting PG-13 segment
    client.click_on_class('protection-PG13')

    # checking additional data costs counter
    client.wait_until(lambda: costs.text == '$%s' %
                      constants.TARGETING_ADDITIONAL_DATA_COSTS['brand_protection'])

    # checking label in widget's header
    assert 'PG13' in get_tags(widget)

    # saving campaign
    utils.save_and_return_to_step(client)

    # check segment in database
    segments_in_db = strategy.segment_proximic_maturity_rating.all()
    client.wait_until(lambda: segments_in_db.count() == 1)

    # checking if PG-13 segment is already selected
    segment = client.find_element_by_class_name('-t-protection-PG13')
    assert client.has_class(segment, 'active')

    # checking label in widget's header
    widget_class = '-t-widget-include-%s' % widget_type
    widget = client.find_element_by_class_name(widget_class)
    assert 'PG13' in get_tags(widget)

    # removing widget
    client.click_on_class('widget-include-%s-remove' % widget_type)

    # checking if widget has been removed
    assert client.is_present_in_DOM(widget_class) is False

    # checking additional data costs counter
    costs = client.find_element_by_class_name('-t-additional-data-costs')
    client.wait_until(lambda: costs.text == '-')

    # saving campaign
    utils.save_and_return_to_step(client)

    # check if widget is removed after save
    assert client.is_present_in_DOM(widget_class) is False

    # checking segments in database
    client.wait_until(lambda: segments_in_db.count() == 0)
Пример #17
0
def test_tree_widget(client, fill_db, widget_name, get_category_tree, get_strategy_categories,
                     section='include'):
    '''
    Test editing content categories

    :param string widget_name: Name of widget, defined in strategy.js
    :param function get_category_tree: Function retrieving list of categories with subcategories
    :param function get_strategy_categories: A function retrieving saved
        categories from strategy
    :param string section: Name of targeting section widget will be added to.
        Can equal 'include' or 'exclude'
    '''
    def scroll_to_bottom():
        '''
        Make sure that entire category list is visible
        by scrolling to a button under the widget
        '''
        btn_class = '-t-%s-dropdown' % section
        include_btn = client.find_element_by_class_name(btn_class)
        include_btn.location_once_scrolled_into_view

    def find_by_text(elements, text):
        '''
        Find first WebElement with a matching text

        :param list elements: List of WebElements
        :param string text: Text to match
        '''
        def by_text(element):
            element.location_once_scrolled_into_view
            return element.text == text
        matches = filter(by_text, elements)
        return matches[0]

    def expand(node):
        '''
        Expand tree node, return list of child nodes

        :param WebElement node: Element containing collapse handle and node name
        :returns Element containing list of child nodes
        :rtype WebElement
        '''
        expand_btn = node.find_element_by_class_name('collapsed')
        subelements_selector = expand_btn.get_attribute('data-target')
        client.click(expand_btn)
        scroll_to_bottom()
        client.wait_until_displayed(subelements_selector, by="css_selector")
        return client.find_element_by_css_selector(subelements_selector)

    def collapse(node):
        '''
        Collapse tree node

        :param WebElement node: Element containing collapse handle and node name
        '''
        collapse_btn = node.find_element_by_class_name('collapse-handle')
        subelements_selector = collapse_btn.get_attribute('data-target')
        client.click(collapse_btn)
        client.wait_until_displayed(subelements_selector, by="css_selector", until=False)

    # Select 1 random main category, and 1 random subcategory that is
    # not included in the first category.
    category_tree = get_category_tree()
    category_tree_with_children = filter(lambda c: c.get('children'), category_tree)

    strategy = Strategy.objects.all().first()
    WIDGET_CLASS = '-t-widget-%s-%s' % (section, widget_name)
    random_main_categories = sample(category_tree_with_children, 2)
    first_category = random_main_categories[0]
    second_category = random_main_categories[1]
    SELECTED_CATEGORIES = []
    SELECTED_MAIN_CATEGORY = first_category['name']
    SELECTED_MAIN_CATEGORY_CHILDREN = [c['name'] for c in first_category['children']]
    SELECTED_SUBCATEGORY_PARENT = second_category['name']
    SELECTED_SUBCATEGORY = choice(second_category['children'])['name']

    # Store categories that should be saved to DB
    SELECTED_CATEGORIES.append(SELECTED_MAIN_CATEGORY)
    SELECTED_CATEGORIES.extend(SELECTED_MAIN_CATEGORY_CHILDREN)
    SELECTED_CATEGORIES.append(SELECTED_SUBCATEGORY)
    IS_ONLY_SUBCATEGORY = (len(second_category['children']) == 1)
    if IS_ONLY_SUBCATEGORY:
        SELECTED_CATEGORIES.append(SELECTED_SUBCATEGORY_PARENT)

    # Go to targeting, display widget and make sure it is fully visible
    utils.go_to_step(client, 'targeting', existing=True)

    widget = display_widget(client, widget_name, section=section)

    scroll_to_bottom()

    # Check if all main categories are displayed.

    main_tree_elements = [e for e in widget.find_elements_by_class_name('-t-tree-main') if e.text]

    ui_main_categories = [e.text for e in main_tree_elements if e.text]

    main_categories = [c['name'] for c in category_tree]

    assert ui_main_categories == main_categories

    # Check if all subcategories are displayed after expanding main category.
    # Check if they are hidden when category is collapsed.
    for index, category in enumerate(category_tree):
        subcategories = [c['name'] for c in category.get('children', [])]
        ui_main_category = main_tree_elements[index]
        collapse_handle = ui_main_category.find_element_by_class_name('tree-handle')

        ui_subcategories = []

        if 'collapsed' in collapse_handle.get_attribute('class'):
            ui_main_category.location_once_scrolled_into_view
            subcategory_ul = expand(ui_main_category)
            subcategory_ul.location_once_scrolled_into_view

            for e in subcategory_ul.find_elements_by_class_name('-t-checkbox'):
                if not e.is_displayed():
                    e.location_once_scrolled_into_view

                # Filter undisplayed subelements
                if e.is_displayed() and e.text:
                    ui_subcategories.append(e.text)

            collapse(ui_main_category)

        assert sorted(ui_subcategories) == sorted(subcategories)

    # Select a random main category. Check if main and subcategory
    # checkboxes state change.

    ui_main_category = find_by_text(main_tree_elements, SELECTED_MAIN_CATEGORY)
    subcategory_ul = expand(ui_main_category)
    main_checkbox = client.get_checkbox(ui_main_category)
    assert client.is_not_checked(main_checkbox)

    sub_checkboxes = subcategory_ul.find_elements_by_class_name('-t-checkbox')
    for checkbox in sub_checkboxes:
        assert client.is_not_checked(checkbox)

    main_checkbox.click()

    assert client.is_checked(main_checkbox)
    sub_checkboxes = subcategory_ul.find_elements_by_class_name('-t-checkbox')
    for checkbox in sub_checkboxes:
        assert client.is_checked(checkbox)

    collapse(ui_main_category)

    # Select a random subcategory. Check if checkbox state chenges.

    ui_subcategory_parent = find_by_text(main_tree_elements, SELECTED_SUBCATEGORY_PARENT)
    main_checkbox = client.get_checkbox(ui_subcategory_parent)
    subcategory_ul = expand(ui_subcategory_parent)
    sub_checkboxes = subcategory_ul.find_elements_by_class_name('-t-checkbox')
    sub_checkbox = find_by_text(sub_checkboxes, SELECTED_SUBCATEGORY)

    # If there is only one child category, parent should be automatically checked
    if IS_ONLY_SUBCATEGORY:
        assert client.is_not_checked(main_checkbox)

    assert client.is_not_checked(sub_checkbox)

    client.click(sub_checkbox)

    if IS_ONLY_SUBCATEGORY:
        assert client.is_checked(main_checkbox)

    assert client.is_checked(sub_checkbox)

    collapse(ui_subcategory_parent)

    # Save strategy

    assert len(get_strategy_categories(strategy)) == 0
    utils.save_and_return_to_step(client)

    # Check if all categories were saved to DB

    db_categories = [c.name for c in get_strategy_categories(strategy)]
    assert sorted(SELECTED_CATEGORIES) == sorted(db_categories)

    # 5. Check if they are displayed correctly, uncheck them and save

    widget = client.find_element_by_class_name(WIDGET_CLASS)
    scroll_to_bottom()
    main_tree_elements = widget.find_elements_by_class_name('-t-tree-main')

    ui_main_category = find_by_text(main_tree_elements, SELECTED_MAIN_CATEGORY)
    subcategory_ul = expand(ui_main_category)
    main_checkbox = client.get_checkbox(ui_main_category)
    assert client.is_checked(main_checkbox)

    sub_checkboxes = subcategory_ul.find_elements_by_class_name('-t-checkbox')
    for checkbox in sub_checkboxes:
        assert client.is_checked(checkbox)

    main_checkbox.click()

    assert client.is_not_checked(main_checkbox)
    sub_checkboxes = subcategory_ul.find_elements_by_class_name('-t-checkbox')
    for checkbox in sub_checkboxes:
        assert client.is_not_checked(checkbox)

    collapse(ui_main_category)

    # Uncheck the subcategory

    ui_subcategory_parent = find_by_text(main_tree_elements, SELECTED_SUBCATEGORY_PARENT)
    subcategory_ul = expand(ui_subcategory_parent)
    sub_checkboxes = subcategory_ul.find_elements_by_class_name('-t-checkbox')
    sub_parent_checkbox = client.get_checkbox(ui_subcategory_parent)
    sub_checkbox = find_by_text(sub_checkboxes, SELECTED_SUBCATEGORY)

    if IS_ONLY_SUBCATEGORY:
        assert client.is_checked(sub_parent_checkbox)

    assert client.is_checked(sub_checkbox)

    client.click(sub_checkbox)

    if IS_ONLY_SUBCATEGORY:
        assert client.is_not_checked(sub_parent_checkbox)

    assert client.is_not_checked(sub_checkbox)

    collapse(ui_subcategory_parent)

    utils.save_and_return_to_step(client)

    # Check if categories were removed from UI and DB

    assert len(get_strategy_categories(strategy)) == 0
    assert client.is_present_in_DOM(WIDGET_CLASS) is False
Пример #18
0
def test_targeting_widgets_behavior(client):
    '''
    Tests if all targeting widgets are selectable from include/exclude dropdown
    Checks if they are visible and if can be removed.
    '''
    utils.go_to_step(client, 'overall')
    type_selector = client.find_element_by_class_name('-t-type')
    for option in type_selector.find_elements_by_tag_name('option'):
        if option.text == 'Mobile':
            option.click()

    targeting_step_class = 'sidebar-targeting'
    client.click_on_class(targeting_step_class)

    # Set default timeout for this test.
    client.implicitly_wait(1)

    include_dropdown, exclude_dropdown = get_dropdowns(client)
    include_target_btn = client.find_element_by_class_name('-t-include-target')
    exclude_target_btn = client.find_element_by_class_name('-t-exclude-target')

    # Test both for include and exclude dropdown
    for dropdown in [include_dropdown, exclude_dropdown]:
        if dropdown is include_dropdown:
            button = include_target_btn
            section = 'include'
        else:
            button = exclude_target_btn
            section = 'exclude'

        # Display all available widgets
        for widget_name in WIDGET_NAMES:
            widget_class = '-t-widget-%s-%s' % (section, widget_name)
            widget_dropdown_class = '-t-%s-%s' % (section, widget_name)
            widget_collapse_class = '-t-widget-%s-%s-collapse' % (section, widget_name)
            widget_expand_class = '-t-widget-%s-%s-expand' % (section, widget_name)
            widget_content_id = 'targeting-%s-%s' % (section, widget_name)

            # Dropdown should be closed
            assert client.has_not_class(dropdown, 'open') is True

            # Open the dropdown
            client.click(button)
            assert client.has_class(dropdown, 'open') is True

            # Check if dropdown contains a picked widget
            assert client.is_present_in_DOM(widget_dropdown_class) is True

            # Select widget and check if it appears.
            client.click_on_class(widget_dropdown_class, bare=True)
            client.wait_until_displayed(widget_class)

            # Check if dropdown does not contain a picked widget
            assert client.is_present_in_DOM(widget_dropdown_class) is False

            # Collapse widget
            widget_content = client.find_element_by_id(widget_content_id)
            collapse_btn = client.find_element_by_class_name(widget_collapse_class)
            expand_btn = client.find_element_by_class_name(widget_expand_class)
            assert widget_content.is_displayed() is True

            client.click_on_class(widget_collapse_class, bare=True)

            client.wait_for_widget_action(widget_content, expanded=False)

            assert client.has_not_class(widget_content, 'in') is True
            assert collapse_btn.is_displayed() is False
            assert expand_btn.is_displayed() is True

            # Expand widget
            client.click_on_class(widget_expand_class, bare=True)

            client.wait_for_widget_action(widget_content, expanded=True)

            assert client.has_class(widget_content, 'in') is True
            assert collapse_btn.is_displayed() is True
            assert expand_btn.is_displayed() is False

        # Remove all displayed widgets
        for widget_name in WIDGET_NAMES:
            widget_class = '-t-widget-%s-%s' % (section, widget_name)
            widget_dropdown_class = '-t-%s-%s' % (section, widget_name)
            widget_remove_class = '-t-widget-%s-%s-remove' % (section, widget_name)

            client.click_on_class(widget_remove_class, bare=True, scroll=True)

            # Check if widget is not displayed
            assert client.is_present_in_DOM(widget_class) is False

            # Check if dropdown does contains a picked widget
            assert client.is_present_in_DOM(widget_dropdown_class) is True
Пример #19
0
def test_include_exclude_validation(client):
    """Test if the same values cannot be included and excluded at the same time"""
    utils.go_to_step(client, 'targeting', existing=True)

    targeting_page = TargetingPage(client)

    def check_errors(*args):
        targeting_page.save()
        client.wait_for_modal()

        errors = client.get_modal_errors()
        for field_name in args:
            message = '{field_name}: Cannot include and exlude the same values'.format(field_name=field_name)
            assert message in errors

        client.close_modal()

    # Checkbox widgets
    single_column_widgets = [
        ('PeerContextual', 'Peer contextual'),
        ('PeerPageQuality', 'Peer page quality'),
        ('PeerBrandProtection', 'Peer brand protection'),
        ('PeerLanguage', 'Peer page language'),
        ('LotameDemographic', 'Lotame demographic'),
        ('LotameAdvancedDemographic', 'Lotame advanced demographic'),
        ('LotameBehavioralInterest', 'Lotame behavioral interest'),
        ('LotameInfluencer', 'Lotame influencers'),
        ('LotameOffline', 'Lotame offline'),
        ('ProximicLanguage', 'Proximic language'),
        ('ProximicPageQuality', 'Proximic page quality'),
        ('ProximicPageNoticeability', 'Proximic page noticeability'),
        ('ProximicPagePlacement', 'Proximic page placement'),
        ('ProximicContextual', 'Proximic contextual')
    ]
    for widget_name, field_name in single_column_widgets:
        for section in (targeting_page.include, targeting_page.exclude):
            widget = section.add(widget_name)
            widget.checkboxes[0].click()

        check_errors(field_name)

    multiple_column_widgets = [
        ('UserProfile', ['Age group', 'Gender']),
    ]
    for widget_name, fields in multiple_column_widgets:
        for section in (targeting_page.include, targeting_page.exclude):
            widget = section.add(widget_name)
            for group in widget.checkbox_groups:
                group[0].click()

        check_errors(*fields)

    # Custom widgets
    for section in (targeting_page.include, targeting_page.exclude):
        widget = section.add('ProximicBrandProtection')
        maturity = widget.container.find_element_by_class_name('btn-radio')
        client.click(maturity)
        safety_level = widget.checkboxes[0]
        client.click(safety_level)

    check_errors('Proximic maturity rating', 'Proximic safety level')

    # Search widgets
    search_widgets = [
        ('Device', 'sony', 'Device'),
        ('Location', 'ohio', 'Location'),
        ('Os', 'android', 'Operating system'),
        ('Carrier', 'plus', 'Carrier')
    ]
    for widget_name, text_to_type, field_name in search_widgets:
        for section in (targeting_page.include, targeting_page.exclude):

            widget = section.add(widget_name)

            # Scroll down to the button to make sure suggestions are visible
            section._dropdown.location_once_scrolled_into_view

            # type in input
            widget.search_input.send_keys(text_to_type)

            # wait for dropdown appearance
            client.wait_until_displayed(widget.search_dropdown)

            # click in dropdown first suggestion
            client.click(widget.search_suggestions[0])

        check_errors(field_name)
Пример #20
0
def test_list_widget(client, fill_db, lotame_segments, widget_name, get_segment_list, get_strategy_included,
                     get_strategy_excluded):
    """Test including and excluding segments through list widget"""

    utils.go_to_step(client, 'targeting', existing=True)
    strategy_name = client.find_element_by_class_name('-t-name').text
    strategy = Strategy.objects.get(name=strategy_name)

    # No segments should be selected
    assert get_strategy_included(strategy).count() == 0
    assert get_strategy_excluded(strategy).count() == 0

    # Choose more than 1 segment
    SAMPLE_SIZE = 6
    segments = sample(get_segment_list(), SAMPLE_SIZE)
    # Include half of the sample, and exclude the other half
    included_segments = segments[:SAMPLE_SIZE/2]
    excluded_segments = segments[SAMPLE_SIZE/2:]

    targeting_page = TargetingPage(client)
    include_widget = targeting_page.include.add(widget_name)
    exclude_widget = targeting_page.exclude.add(widget_name)

    # Include and exclude some random segments
    for widget, segments in [
        (include_widget, included_segments),
        (exclude_widget, excluded_segments)
    ]:
        checkboxes = widget.checkboxes
        for segment in segments:
            checkbox = client.find_by_text(checkboxes, segment.name)
            client.click(checkbox)
            assert client.is_checked(checkbox)
        assert sorted(widget.tags) == sorted(s.name for s in segments)

    # Save strategy and check if segments were saved
    utils.save_and_return_to_step(client)

    assert include_widget.is_displayed
    assert exclude_widget.is_displayed

    for widget, segments in [
        (include_widget, included_segments),
        (exclude_widget, excluded_segments)
    ]:
        checkboxes = widget.checkboxes
        selected_names = [s.name for s in segments]
        assert sorted(widget.tags) == sorted(selected_names)
        for checkbox in checkboxes:
            checkbox.location_once_scrolled_into_view
            if checkbox.text in selected_names:
                assert client.is_checked(checkbox)
            else:
                assert client.is_not_checked(checkbox)

    # Check included and excluded segments in database
    included_segments_db = get_strategy_included(strategy).values_list('id', 'name')
    excluded_segments_db = get_strategy_excluded(strategy).values_list('id', 'name')

    def id_and_name(segment):
        return (segment.id, segment.name)

    assert sorted(map(id_and_name, included_segments)) == sorted(included_segments_db)
    assert sorted(map(id_and_name, excluded_segments)) == sorted(excluded_segments_db)