import unittest
from robot.libraries.BuiltIn import RobotNotRunningError
from cumulusci.robotframework.Salesforce import Salesforce
from unittest import mock


# FIXME: we shouldn't have to tweak these tests for every
# version. The tests should be smarter.
class TestLocators(unittest.TestCase):
    @mock.patch("cumulusci.robotframework.Salesforce.Salesforce.get_latest_api_version")
    def test_locators_in_robot_context(self, get_latest_api_version):
        """Verify we can get locators for the current org api version"""
        get_latest_api_version.return_value = 50.0

        # This instantiates the robot library, mimicking a robot library import.
        # We've mocked out the code that would otherwise throw an error since
        # we're not running in the context of a robot test. The library should
        # return the latest version of the locators.
        sf = Salesforce()

        expected = "cumulusci.robotframework.locators_50"
        actual = sf.locators_module.__name__
        message = "expected to load '{}', actually loaded '{}'".format(expected, actual)
        self.assertEqual(expected, actual, message)

        pass

    @mock.patch(
        "robot.libraries.BuiltIn.BuiltIn.get_library_instance",
        side_effect=RobotNotRunningError(),
    )
    def test_locators_outside_robot_context(self, builtin_mock):
        """Verify that we get the latest locators if not running in the context of a robot test"""

        # This instantiates the robot library, mimicing a robot library import
        # however, because we've mocked get_library_instance to throw an error,
        # we expect the library to still be instantiated, but with the latest
        # version of the locators.
        sf = Salesforce()
        expected = "cumulusci.robotframework.locators_50"
        actual = sf.locators_module.__name__
        message = "expected to load '{}', actually loaded '{}'".format(expected, actual)
        self.assertEqual(expected, actual, message)

    def test_locators_50(self):
        """Verify that locators_50 is a superset of the locators_49

        This test is far from perfect, but it should at least flag a
        catastrophic error in how locators for a version that augments
        the locators from previous versions.

        Note: this test assumes that locators_49 doesn't delete any of the
        keys from 49.

        """
        import cumulusci.robotframework.locators_49 as locators_49
        import cumulusci.robotframework.locators_50 as locators_50

        keys_49 = set(locators_49.lex_locators)
        keys_50 = set(locators_50.lex_locators)

        self.assertNotEqual(
            id(locators_49.lex_locators),
            id(locators_50.lex_locators),
            "locators_49.lex_locators and locators_50.lex_locators are the same object",
        )
        self.assertTrue(len(keys_49) > 0)
        self.assertTrue(keys_49.issubset(keys_50))

@@ -151,16 +151,41 @@
 rt mock%0A
+from pathlib import Path%0A
 %0A%0A# FIXM
@@ -1736,32 +1736,33 @@
 f the locators.%0A
+%0A
         sf = Sal
@@ -1770,16 +1770,157 @@
 sforce()
+%0A%0A        locator_folder = Path(%22./cumulusci/robotframework%22)%0A        locator_modules = sorted(locator_folder.glob(%22locators_%5B0-9%5D%5B0-9%5D.py%22))
 %0A       
@@ -1923,32 +1923,33 @@
      expected = 
+f
 %22cumulusci.robot
@@ -1954,36 +1954,52 @@
 otframework.
+%7B
 locator
-s_50%22
+_modules%5B-1%5D.stem%7D%22%0A
 %0A        act
@@ -2197,17 +2197,17 @@
 cators_5
-0
+1
 (self):%0A
@@ -2239,17 +2239,17 @@
 cators_5
-0
+1
  is a su
@@ -2271,18 +2271,18 @@
 ocators_
-49
+50
 %0A%0A      
@@ -2507,18 +2507,18 @@
 ocators_
-49
+51
  doesn't
@@ -2554,18 +2554,18 @@
 ys from 
-49
+50
 .%0A%0A     
@@ -2620,18 +2620,18 @@
 ocators_
-49
+50
  as loca
@@ -2635,18 +2635,18 @@
 ocators_
-49
+50
 %0A       
@@ -2680,33 +2680,33 @@
 ework.locators_5
-0
+1
  as locators_50%0A
@@ -2695,33 +2695,33 @@
 51 as locators_5
-0
+1
 %0A%0A        keys_4
@@ -2719,18 +2719,18 @@
    keys_
-49
+50
  = set(l
@@ -2729,34 +2729,34 @@
  = set(locators_
-49
+50
 .lex_locators)%0A 
@@ -2760,33 +2760,33 @@
 )%0A        keys_5
-0
+1
  = set(locators_
@@ -2778,33 +2778,33 @@
 = set(locators_5
-0
+1
 .lex_locators)%0A%0A
@@ -2848,34 +2848,34 @@
     id(locators_
-49
+50
 .lex_locators),%0A
@@ -2891,33 +2891,33 @@
    id(locators_5
-0
+1
 .lex_locators),%0A
@@ -2938,18 +2938,18 @@
 ocators_
-49
+50
 .lex_loc
@@ -2960,33 +2960,33 @@
 s and locators_5
-0
+1
 .lex_locators ar
@@ -3048,18 +3048,18 @@
 en(keys_
-49
+50
 ) %3E 0)%0A 
@@ -3090,10 +3090,10 @@
 eys_
-49
+50
 .iss
@@ -3104,12 +3104,12 @@
 t(keys_5
-0
+1
 ))%0A

Fix a unit test so that we don't have to update it for every API revision. I partly fixed the FIXME, but the last test still could be written in a way that doesn't require hand-editing for each API version.