def post(self, *args, **kwargs):
        super(AjaxTags, self).post()

        new_tag_name = self.request.POST.get('name')
        new_tag = None

        if Tag.get_by_key(new_tag_name) is None:
            new_tag = Tag(name=new_tag_name).put()

        response = json.dumps(
            None if new_tag is None
            else {'key': new_tag.urlsafe(), 'name': new_tag_name})

        self.response.out.write(response)
class EditPostTests(BaseTest):
    def setUp(self):
        super(EditPostTests, self).setUp()

        self.test_tag_1 = Tag(name="test tag 1").put()
        self.test_tag_2 = Tag(name="test tag 2").put()
        self.test_tag_3 = Tag(name="test tag 3").put()

        self.test_author = Author(nickname="test", email="*****@*****.**").put()

        self.test_post = (
            Post(
                subject="test post",
                mark_down="test mark down",
                html="test html",
                is_published=True,
                author=self.test_author,
                tags=[self.test_tag_1],
            )
            .put()
            .get()
        )

    def test_must_be_admin_to_view_page(self):
        self.app.get(get_route("edit_post", key=self.test_post.key.urlsafe()), status=403)

    def test_existing_tags_available_on_page_load(self):
        self.login("*****@*****.**", admin=True)

        response = self.app.get(get_route("edit_post", key=self.test_post.key.urlsafe()))
        soup = BeautifulSoup(response.body)

        multiselect_box = soup.find("select", {"name": "tags"})
        options = multiselect_box.findAll("option")

        self.assertEqual(len(options), 3)

    def test_existing_post_content_loads_on_edit(self):
        self.login("*****@*****.**", admin=True)

        response = self.app.get(get_route("edit_post", key=self.test_post.key.urlsafe()), status=200)

        edit_form = response.form

        self.assertEqual(edit_form["subject"].value, "test post")
        self.assertEqual(edit_form["mark_down"].value, "test mark down")
        self.assertEqual(edit_form["is_published"].value, "on")
        self.assertEqual(edit_form["tags"].value, [self.test_tag_1.urlsafe()])
        self.assertEqual(edit_form["key"].value, self.test_post.key.urlsafe())
class ModelDeserializationTests(BaseTest):
    def setUp(self):
        super(ModelDeserializationTests, self).setUp()
        self.login("*****@*****.**")

        self.test_key = Tag(name="Test Tag for Key").put()

        self.testing_model = (
            TestModel(
                bool_prop=True,
                string_prop="unmodified",
                text_prop="unmodified",
                datetime_prop=datetime(1982, 5, 21, 16, 0, 0, 0),
            )
            .put()
            .get()
        )

    def test_can_deserialize_a_dict_to_model(self):
        test_dict = {
            "bool_prop": True,
            "string_prop": "string value",
            "text_prop": "text value",
            "datetime_prop": "1982-05-21 16:00",
            "key_prop": self.test_key.urlsafe(),
        }

        deser_model = TestModel.deserialize(test_dict)

        self.assertTrue(deser_model.bool_prop)
        self.assertEqual(deser_model.string_prop, test_dict["string_prop"])
        self.assertEqual(deser_model.text_prop, test_dict["text_prop"])
        self.assertEqual(deser_model.datetime_prop, datetime(1982, 5, 21, 16, 0, 0, 0))
        self.assertEqual(deser_model.key_prop, self.test_key)

    def test_can_deserialize_a_serialized_array_with_repeated_keys(self):
        post_serialized_array = [
            {"name": "repeated_key_prop", "value": self.test_key.urlsafe()},
            {"name": "repeated_key_prop", "value": self.test_key.urlsafe()},
        ]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.repeated_key_prop)
        self.assertEqual(len(deser_model.repeated_key_prop), 2)

    def test_can_deserialize_a_serialized_array_with_regular_key_prop(self):
        post_serialized_array = [{"name": "regular_key_prop", "value": self.test_key.urlsafe()}]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.regular_key_prop)
        self.assertEqual(deser_model.regular_key_prop, self.test_key)

    def test_can_deserialize_serialized_array_with_datetime_props(self):
        post_serialized_array = [
            {"name": "repeated_datetime_prop", "value": "1982-05-21 16:00"},
            {"name": "repeated_datetime_prop", "value": "1982-05-21 17:00"},
        ]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.repeated_datetime_prop)
        self.assertEqual(len(deser_model.repeated_datetime_prop), 2)
        self.assertIn(datetime(1982, 5, 21, 16, 0, 0, 0), deser_model.repeated_datetime_prop)
        self.assertIn(datetime(1982, 5, 21, 17, 0, 0, 0), deser_model.repeated_datetime_prop)

    def test_can_deserialize_serialized_array_with_regular_datetime_prop(self):
        post_serialized_array = [{"name": "regular_datetime_prop", "value": "1982-05-21 16:00"}]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.regular_datetime_prop)
        self.assertEqual(deser_model.regular_datetime_prop, datetime(1982, 5, 21, 16, 0, 0, 0))

    def test_can_deserialize_serialized_array_with_date_props(self):
        post_serialized_array = [
            {"name": "repeated_date_prop", "value": "1982-05-21"},
            {"name": "repeated_date_prop", "value": "1982-05-21"},
        ]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.repeated_date_prop)
        self.assertEqual(len(deser_model.repeated_date_prop), 2)
        self.assertIn(datetime(1982, 5, 21), deser_model.repeated_date_prop)
        self.assertIn(datetime(1982, 5, 21), deser_model.repeated_date_prop)

    def test_can_deserialize_serialized_array_with_regular_date_prop(self):
        post_serialized_array = [{"name": "regular_date_prop", "value": "1982-05-21"}]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.regular_date_prop)
        self.assertEqual(deser_model.regular_date_prop, datetime(1982, 5, 21))

    def test_can_deserialize_a_serialized_array_with_repeated_bool_props(self):
        post_serialized_array = [
            {"name": "repeated_bool_prop", "value": "on"},
            {"name": "repeated_bool_prop", "value": ""},
        ]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.repeated_bool_prop)
        self.assertEqual(len(deser_model.repeated_bool_prop), 2)
        self.assertIn(True, deser_model.repeated_bool_prop)
        self.assertIn(False, deser_model.repeated_bool_prop)

    def test_can_deserialize_a_serialized_array_with_regular_bool_prop(self):
        post_serialized_array = [{"name": "regular_bool_prop", "value": "on"}]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertTrue(deser_model.regular_bool_prop)

    def test_can_deserialize_serialized_array_with_repeated_string_prop(self):
        post_serialized_array = [
            {"name": "repeated_string_prop", "value": "first string"},
            {"name": "repeated_string_prop", "value": "second string"},
        ]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.repeated_string_prop)
        self.assertEqual(len(deser_model.repeated_string_prop), 2)
        self.assertIn("first string", deser_model.repeated_string_prop)
        self.assertIn("second string", deser_model.repeated_string_prop)

    def test_can_deserialize_a_serialized_array_with_regular_string_prop(self):
        post_serialized_array = [{"name": "regular_string_prop", "value": "just a test string"}]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertEqual(deser_model.regular_string_prop, "just a test string")

    def test_can_deserialize_a_serialized_array_with_repeated_text_prop(self):
        post_serialized_array = [
            {"name": "repeated_text_prop", "value": "this is some sample text."},
            {"name": "repeated_text_prop", "value": "this is some more sample text."},
        ]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertIsNotNone(deser_model.repeated_text_prop)
        self.assertEqual(len(deser_model.repeated_text_prop), 2)
        self.assertIn("this is some sample text.", deser_model.repeated_text_prop)
        self.assertIn("this is some more sample text.", deser_model.repeated_text_prop)

    def test_can_deserialize_a_serialized_array_with_regular_text_prop(self):
        post_serialized_array = [{"name": "regular_text_prop", "value": "just a regular text prop"}]

        deser_model = TestModel2.deserialize(post_serialized_array)

        self.assertIsNotNone(deser_model)
        self.assertEqual(deser_model.regular_text_prop, "just a regular text prop")

    def test_can_update_existing_model_using_a_dict(self):
        update_dict = {
            "key": self.testing_model.key.urlsafe(),
            "bool_prop": True,
            "string_prop": "modified",
            "text_prop": "modified",
            "datetime_prop": "2012-07-04 12:00",
            "key_prop": self.test_key.urlsafe(),
        }

        updated_model = TestModel.deserialize(update_dict)

        self.assertEqual(updated_model.key, self.testing_model.key)
        self.assertTrue(updated_model.bool_prop)
        self.assertEqual(updated_model.string_prop, "modified")
        self.assertEqual(updated_model.text_prop, "modified")
        self.assertEqual(updated_model.datetime_prop, datetime(2012, 7, 4, 12))

    def test_can_update_existing_model_using_a_serialized_array(self):
        update_serialize_array = [
            {"name": "key", "value": self.testing_model.key.urlsafe()},
            {"name": "bool_prop", "value": ""},
            {"name": "string_prop", "value": "modified"},
            {"name": "text_prop", "value": "modified"},
            {"name": "datetime_prop", "value": "2012-07-04 12:00"},
        ]

        updated_model = TestModel.deserialize(update_serialize_array)

        self.assertEqual(updated_model.key, self.testing_model.key)
        self.assertFalse(updated_model.bool_prop)
        self.assertEqual(updated_model.string_prop, "modified")
        self.assertEqual(updated_model.text_prop, "modified")
        self.assertEqual(updated_model.datetime_prop, datetime(2012, 7, 4, 12))

    def test_missing_bool_prop_assumed_to_be_false(self):
        test_dict = {
            "key": self.testing_model.key.urlsafe(),
            "string_prop": "string value",
            "text_prop": "text value",
            "datetime_prop": "1982-05-21 16:00",
            "key_prop": self.test_key.urlsafe(),
        }

        updated_model = TestModel.deserialize(test_dict)

        self.assertFalse(updated_model.bool_prop)