1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5import os
6
7from marionette_driver.by import By
8from marionette_driver.errors import JavascriptException
9
10from marionette_harness import (
11    MarionetteTestCase,
12    skip_if_chrome,
13    skip_if_mobile,
14    WindowManagerMixin,
15)
16
17
18class TestImportScriptContent(WindowManagerMixin, MarionetteTestCase):
19    contexts = set(["chrome", "content"])
20
21    script_file = os.path.abspath(
22        os.path.join(__file__, os.path.pardir, "importscript.js"))
23    another_script_file = os.path.abspath(
24        os.path.join(__file__, os.path.pardir, "importanotherscript.js"))
25
26    def setUp(self):
27        super(TestImportScriptContent, self).setUp()
28
29        for context in self.contexts:
30            with self.marionette.using_context(context):
31                self.marionette.clear_imported_scripts()
32        self.reset_context()
33
34    def tearDown(self):
35        self.close_all_windows()
36
37        super(TestImportScriptContent, self).tearDown()
38
39    def reset_context(self):
40        self.marionette.set_context("content")
41
42    @property
43    def current_context(self):
44        return self.marionette._send_message("getContext", key="value")
45
46    @property
47    def other_context(self):
48        return self.contexts.copy().difference([self.current_context]).pop()
49
50    def is_defined(self, symbol):
51        return self.marionette.execute_script(
52            "return typeof {} != 'undefined'".format(symbol))
53
54    def assert_defined(self, symbol, msg=None):
55        if msg is None:
56            msg = "Expected symbol {} to be defined".format(symbol)
57        self.assertTrue(self.is_defined(symbol), msg)
58
59    def assert_undefined(self, symbol, msg=None):
60        if msg is None:
61            msg = "Expected symbol {} to be undefined".format(symbol)
62        self.assertFalse(self.is_defined(symbol), msg)
63
64    def assert_scripts_cleared(self):
65        self.marionette.import_script(self.script_file)
66        self.assert_defined("testFunc")
67        self.marionette.clear_imported_scripts()
68        self.assert_undefined("testFunc")
69
70    def test_import_script(self):
71        self.marionette.import_script(self.script_file)
72        self.assertEqual(
73            "i'm a test function!", self.marionette.execute_script("return testFunc();"))
74        self.assertEqual("i'm a test function!", self.marionette.execute_async_script(
75            "marionetteScriptFinished(testFunc());"))
76
77    def test_import_script_twice(self):
78        self.marionette.import_script(self.script_file)
79        self.assert_defined("testFunc")
80
81        # TODO(ato): Note that the WebDriver command primitives
82        # does not allow us to check what scripts have been imported.
83        # I suspect we must to do this through an xpcshell test.
84
85        self.marionette.import_script(self.script_file)
86        self.assert_defined("testFunc")
87
88    def test_import_script_and_clear(self):
89        self.marionette.import_script(self.script_file)
90        self.assert_defined("testFunc")
91        self.marionette.clear_imported_scripts()
92        self.assert_scripts_cleared()
93        self.assert_undefined("testFunc")
94        with self.assertRaises(JavascriptException):
95            self.marionette.execute_script("return testFunc()")
96        with self.assertRaises(JavascriptException):
97            self.marionette.execute_async_script(
98                "marionetteScriptFinished(testFunc())")
99
100    def test_clear_scripts_in_other_context(self):
101        self.marionette.import_script(self.script_file)
102        self.assert_defined("testFunc")
103
104        # clearing other context's script file should not affect ours
105        with self.marionette.using_context(self.other_context):
106            self.marionette.clear_imported_scripts()
107            self.assert_undefined("testFunc")
108
109        self.assert_defined("testFunc")
110
111    def test_multiple_imports(self):
112        self.marionette.import_script(self.script_file)
113        self.marionette.import_script(self.another_script_file)
114        self.assert_defined("testFunc")
115        self.assert_defined("testAnotherFunc")
116
117    @skip_if_chrome("Needs content scope")
118    @skip_if_mobile("New windows not supported in Fennec")
119    def test_imports_apply_globally(self):
120        self.marionette.navigate(
121            self.marionette.absolute_url("test_windows.html"))
122
123        def open_window_with_link():
124            self.marionette.find_element(By.LINK_TEXT, "Open new window").click()
125
126        new_window = self.open_window(trigger=open_window_with_link)
127        self.marionette.switch_to_window(new_window)
128
129        self.marionette.import_script(self.script_file)
130        self.marionette.close_chrome_window()
131
132        self.marionette.switch_to_window(self.start_window)
133        self.assert_defined("testFunc")
134
135
136class TestImportScriptChrome(TestImportScriptContent):
137    def reset_context(self):
138        self.marionette.set_context("chrome")
139