diff --git a/common/test/acceptance/pages/studio/html_component_editor.py b/common/test/acceptance/pages/studio/html_component_editor.py index e705d4d9ad..50f2a83035 100644 --- a/common/test/acceptance/pages/studio/html_component_editor.py +++ b/common/test/acceptance/pages/studio/html_component_editor.py @@ -1,5 +1,6 @@ from common.test.acceptance.pages.studio.utils import type_in_codemirror from xblock_editor import XBlockEditorView +from common.test.acceptance.pages.common.utils import click_css class HtmlXBlockEditorView(XBlockEditorView): @@ -8,6 +9,8 @@ class HtmlXBlockEditorView(XBlockEditorView): """ editor_mode_css = '.edit-xblock-modal .editor-modes .editor-button' + settings_tab = '.editor-modes .settings-button' + save_settings_button = '.action-save' def set_content_and_save(self, content, raw=False): """Types content into the html component and presses Save. @@ -58,3 +61,108 @@ class HtmlXBlockEditorView(XBlockEditorView): type_in_codemirror(self, 0, content) self.q(css='.mce-foot .mce-primary').click() + + def open_settings_tab(self): + """ + Clicks settings button on the modal + """ + click_css(self, self.settings_tab) + + def save_settings(self): + """ + Click save button on the modal + """ + click_css(self, self.save_settings_button) + + def open_link_plugin(self): + """ + Opens up the link plugin on editor + """ + self.q(css='[aria-label="Insert/edit link"]').click() + self.wait_for_element_visibility('.mce-window-head', 'Window header present') + + def save_static_link(self, static_link): + """ + Adds static link inside the link plugin + """ + self.q(css='.mce-combobox .mce-textbox').fill(static_link) + self.q(css='.mce-btn.mce-primary').click() + + @property + def href(self): + """ + Gets the href from the editor + """ + return self.q(css="#tinymce>p>a").attrs('href')[0] + + def switch_to_iframe(self): + """ + Switches to the editor iframe + """ + self.browser.switch_to_frame(self.browser.find_element_by_tag_name('iframe')) + + @property + def url_from_the_link_plugin(self): + """ + Clicks the already set link from the editor and then returns the URL from the link plugin + """ + self.open_link_plugin() + return self.browser.execute_script('return $(".mce-textbox").val();') + + def get_default_settings(self): + """ + Returns default display name and editor + """ + display_name_setting = self.q(css='.wrapper-comp-setting input[type="text"]:nth-child(2)').attrs('value')[0] + editor_setting = self.q(css='.wrapper-comp-setting .input.setting-input :nth-child(1)').text[0] + return [display_name_setting, editor_setting] + + @property + def keys(self): + """ + Gets setting keys + """ + return self.q(css='.label.setting-label[for]').text + + def set_field_val(self, field_display_name, field_value): + """ + If editing, set the value of a field. + """ + selector = '.xblock-studio_view li.field label:contains("{}") + input'.format(field_display_name) + script = "$(arguments[0]).val(arguments[1]).change();" + self.browser.execute_script(script, selector, field_value) + + def save(self): + """ + Clicks save button. + """ + click_css(self, '.save-button') + + +class HTMLEditorIframe(XBlockEditorView): + """ + Represent the iframe on HTMl editor view + """ + + def is_browser_on_page(self): + return self.q(css='#tinymce').present + + @property + def href(self): + """ + Gets the href from the editor + """ + return self.q(css="#tinymce>p>a").attrs('href')[0] + + def select_link(self): + """ + Clicks the already set link from the editor and then returns the URL from the link plugin + """ + self.q(css='#tinymce>p>a').first.click() + + def switch_to_default(self): + """ + Switches to default page + + """ + self.browser.switch_to_default_content() diff --git a/common/test/acceptance/tests/studio/test_studio_html_editor.py b/common/test/acceptance/tests/studio/test_studio_html_editor.py new file mode 100644 index 0000000000..7cf2058454 --- /dev/null +++ b/common/test/acceptance/tests/studio/test_studio_html_editor.py @@ -0,0 +1,102 @@ +""" +Acceptance tests for HTML component in studio +""" +from common.test.acceptance.tests.studio.base_studio_test import ContainerBase +from common.test.acceptance.fixtures.course import XBlockFixtureDesc +from common.test.acceptance.pages.studio.container import ContainerPage, XBlockWrapper +from common.test.acceptance.pages.studio.utils import add_component +from common.test.acceptance.pages.studio.html_component_editor import HtmlXBlockEditorView, HTMLEditorIframe + + +class HTMLComponentEditor(ContainerBase): + """ + Feature: CMS.Component Adding + As a course author, I want to be able to add and edit HTML component + """ + def setUp(self, is_staff=True): + """ + Create a course with a section, subsection, and unit to which to add the component. + """ + super(HTMLComponentEditor, self).setUp(is_staff=is_staff) + self.component = 'Text' + self.unit = self.go_to_unit_page() + self.container_page = ContainerPage(self.browser, None) + self.xblock_wrapper = XBlockWrapper(self.browser, None) + # Add HTML component + add_component(self.container_page, 'html', self.component) + self.component = self.unit.xblocks[1] + self.container_page.edit() + self.html_editor = HtmlXBlockEditorView(self.browser, self.component.locator) + self.iframe = HTMLEditorIframe(self.browser, self.component.locator) + + def populate_course_fixture(self, course_fixture): + """ + Adds a course fixture + """ + course_fixture.add_children( + XBlockFixtureDesc('chapter', 'Test Section').add_children( + XBlockFixtureDesc('sequential', 'Test Subsection').add_children( + XBlockFixtureDesc('vertical', 'Test Unit') + ) + ) + ) + + def test_user_can_view_metadata(self): + """ + Scenario: User can view metadata + Given I have created a Blank HTML Page + And I edit and select Settings + Then I see the HTML component settings + """ + self.html_editor.open_settings_tab() + display_name_value = self.html_editor.get_default_settings()[0] + display_name_key = self.html_editor.keys[0] + self.assertEqual( + ['Display Name', 'Text'], + [display_name_key, display_name_value], + "Settings not found" + ) + editor_value = self.html_editor.get_default_settings()[1] + editor_key = self.html_editor.keys[1] + self.assertEqual( + ['Editor', 'Visual'], + [editor_key, editor_value], + "Settings not found" + ) + + def test_user_can_modify_display_name(self): + """ + Scenario: User can modify display name + Given I have created a Blank HTML Page + And I edit and select Settings + Then I can modify the display name + And my display name change is persisted on save + """ + self.html_editor.open_settings_tab() + self.html_editor.set_field_val('Display Name', 'New Name') + self.html_editor.save_settings() + component_name = self.unit.xblock_titles[0] + self.assertEqual(component_name, 'New Name', "Component name is not as edited") + + def test_link_plugin_sets_url_correctly(self): + """ + Scenario: TinyMCE link plugin sets urls correctly + Given I have created a Blank HTML Page + When I edit the page + And I add a link with static link "/static/image.jpg" via the Link Plugin Icon + Then the href link is rewritten to the asset link "image.jpg" + And the link is shown as "/static/image.jpg" in the Link Plugin + """ + static_link = '/static/image.jpg' + self.html_editor.open_link_plugin() + self.html_editor.save_static_link(static_link) + self.html_editor.switch_to_iframe() + href = self.iframe.href + self.assertIn('image.jpg', href) + self.iframe.select_link() + self.iframe.switch_to_default() + self.assertEqual( + self.html_editor.url_from_the_link_plugin, + static_link, + "URL in the link plugin is different" + )