# frozen_string_literal: true

# Copyright (C) 2011 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

require_relative "../common"

describe "jquery ui" do
  include_context "in-process server selenium tests"

  def active
    driver.switch_to.active_element
  end

  def shift_tab
    driver.action.key_down(:shift)
          .send_keys(:tab)
          .key_up(:shift)
          .perform
  end

  def create_simple_modal
    driver.execute_script(<<~JS)
      $('<div><select /><input /></div>')
        .dialog({
          modal: true,
          zIndex: 1000
        })
        .find('select')
        .focus()
    JS
  end

  before do
    course_with_teacher_logged_in
    get "/"
  end

  it "makes dialogs modal when passed modal=true option" do
    expect(driver.execute_script(<<~JS)).to be true
      return $('<div />').dialog({
        modal: true,
        zIndex: 1000
      }).dialog('option', 'modal');
    JS
    expect(f(".ui-widget-overlay")).to be_displayed

    # make sure that hiding then showing the same dialog again, it still looks modal
    expect(driver.execute_script(<<~JS)).to be true
      return $('<div />')
        .dialog({
          modal: true,
          zIndex: 1000
        })
        .dialog('close')
        .dialog('open')
        .dialog('option', 'modal');
    JS
    expect(f(".ui-widget-overlay")).to be_displayed
  end

  it "captures tabbing" do
    create_simple_modal
    expect(active.tag_name).to eq "select"
    active.send_keys(:tab)
    expect(active.tag_name).to eq "input"
    active.send_keys(:tab)
    expect(active.tag_name).to eq "button"
    active.send_keys(:tab)
    expect(active.tag_name).to eq "select"
  end

  # We need to find alternate test case for calendar since the
  # calender widget has been replaced with InstUI in the assignments modal

  # context "calendar widget" do
  #   it "lets you replace content by selecting and typing instead of appending" do
  #     get "/courses/#{@course.id}/assignments"

  #     f(".add_assignment").click
  #     wait_for_ajaximations
  #     f(".ui-datepicker-trigger").click
  #     wait_for_ajaximations
  #     f(".ui-datepicker-time-hour").send_keys("12")
  #     f(".ui-datepicker-time-minute").send_keys("00")
  #     f(".ui-datepicker-ok").click
  #     wait_for_ajaximations

  #     f(".ui-datepicker-trigger").click
  #     wait_for_ajaximations

  #     driver.execute_script("$('#ui-datepicker-time-hour').select();")
  #     f("#ui-datepicker-time-hour").send_keys("5")
  #     expect(f("#ui-datepicker-time-hour")).to have_attribute("value", "5")
  #   end
  # end

  context "dialog titles" do
    # jquery ui doesn't escape dialog titles by default (even when inferred from
    # title attributes!). our modified ui.dialog does (and hopefully jquery.ui
    # will too in 1.9). to pass in an html title that you don't want escaped,
    # wrap it in a jquery object.
    #
    # see http://bugs.jqueryui.com/ticket/6016
    it "html-escapes inferred dialog titles" do
      title = "<b>this</b> is the title"
      expect(driver.execute_script(<<~JS)).to eq title
        return $('<div id="jqueryui_test" title="#{title}">hello</div>')
          .dialog({
            modal: true,
            zIndex: 1000
          })
          .parent('.ui-dialog')
          .find('.ui-dialog-title')
          .text();
      JS
    end

    it "uses a non-breaking space for empty titles" do
      expect(driver.execute_script(<<~JS)).to eq "\302\240"
        return $('<div id="jqueryui_test">hello</div>')
          .dialog({
            modal: true,
            zIndex: 1000
          })
          .parent('.ui-dialog')
          .find('.ui-dialog-title')
          .text();
      JS

      expect(driver.execute_script(<<~JS)).to eq "\302\240"
        return $('#jqueryui_test')
          .dialog({
            modal: true,
            zIndex: 1000
          })
          .dialog('option', 'title', 'foo')
          .dialog('option', 'title', '')
          .parent('.ui-dialog')
          .find('.ui-dialog-title')
          .text();
      JS
    end

    it "html-escapes explicit string dialog titles" do
      title = "<b>this</b> is the title"
      expect(driver.execute_script(<<~JS)).to eq title
        return $('<div id="jqueryui_test">hello again</div>')
          .dialog({
            title: #{title.inspect},
            modal: true,
            zIndex: 1000
          })
          .parent('.ui-dialog')
          .find('.ui-dialog-title')
          .text();
      JS

      new_title = "and now <i>this</i> is the title"
      expect(driver.execute_script(<<~JS)).to eq new_title
        return $('#jqueryui_test')
          .dialog()
          .dialog('option', 'title', #{new_title.inspect})
          .parent('.ui-dialog')
          .find('.ui-dialog-title')
          .text();
      JS
    end
  end

  context "admin-links" do
    before do
      driver.execute_script(<<~JS)
        $('<div class="al-selenium">\
            <a class="al-trigger btn" role="button" aria-haspopup="true" aria-owns="toolbar-1" href="#">\
              <i class="icon-settings"></i>\
              <i class="icon-mini-arrow-down"></i>\
              <span class="screenreader-only">Settings</span>\
            </a>\
            <ul id="toolbar-1" class="al-options" role="menu">\
              <li role="presentation">\
                <a href="#" class="icon-edit">Edit</a>\
              </li>\
            </ul>\
          </div>').appendTo($('#content')).find('.al-trigger').focus();
      JS
    end

    it "opens every time when pressing return" do
      container = f(".al-selenium")
      options = ".al-options:visible"
      scroll_to(f(".footer-logo"))
      expect(container).not_to contain_jqcss(options)
      active.send_keys(:return)
      expect(container).to contain_jqcss(options)
      f(".icon-edit").click
      expect(container).not_to contain_jqcss(options)
      f(".al-selenium .al-trigger").send_keys(:return)
      expect(container).to contain_jqcss(options)
    end
  end
end
