def test_url_updated_when_putting_same_key_different_url(): """ updating a short url works """ repository = InMemoryURLRepository() short_url = "short" original_url1 = OriginalUrl("www.first.com") original_url2 = OriginalUrl("www.second.com", datetime.now()) repository.put(short_url, original_url1) repository.put(short_url, original_url2) assert len(repository.url_map) == 1 assert repository.get(short_url) is original_url2
def test_shorten_url_timouts_after_some_time_if_generated_urls_exist(mock_repo, mock_generate): """ a UrlGenerationTimeoutException is generated if all the generated short urls exist """ url = "www.ibm.com" shortened_url1 = "sdede" shortened_url2 = "xaaa3" shortened_url3 = "cdece" mock_generate.side_effect = [shortened_url1, shortened_url2, shortened_url3] mock_repo.get = MagicMock(side_effect=[OriginalUrl("existing"), OriginalUrl("existing"), OriginalUrl("existing")]) controller = ShortUrlController(mock_repo, mock_generate) with pytest.raises(UrlGenerationTimeoutException): controller.shorten_url(url)
def test_put_and_get_shorturl(): """ putting and getting a short url works """ repository = InMemoryURLRepository() short_url = "short" original_url = OriginalUrl("www.url.com/rr") repository.put(short_url, original_url) assert repository.get(short_url) is original_url
def test_get_original_url_for_existing_short_url(mock_repo): """ get_original_url for an existing short url works """ original_url = OriginalUrl("www.ibm.com") mock_repo.get = MagicMock(return_value=original_url) mock_generate = MagicMock controller = ShortUrlController(mock_repo, mock_generate) assert controller.get_original_url("shorturl") is original_url
def test_delete_existing_shorturl(): """ short urls can be deleted """ repository = InMemoryURLRepository() short_url = "short" original_url = OriginalUrl("www.url.com/rr") repository.put(short_url, original_url) repository.delete(short_url) assert len(repository.url_map) == 0
def test_delete_older_than(): """ original urls with timestamp older than given are deleted """ repository = InMemoryURLRepository() now = datetime.now() a_day = timedelta(days=1) a_year = timedelta(days=365) short_url, short_url1, short_url2 = "short", "short1", "short2" original_url = OriginalUrl("www.url.com") original_url_recent = OriginalUrl("www.url.com", now) original_url_old = OriginalUrl("www.old.com", now - a_year) repository.put(short_url, original_url) repository.put(short_url1, original_url_recent) repository.put(short_url2, original_url_old) a_day_ago = now - a_day repository.delete_older_than(a_day_ago) assert len(repository.url_map) == 2 for _, original_url in repository.url_map.items(): assert original_url.timestamp is None or original_url.timestamp > a_day_ago
def test_shorten_url_generates_again_when_existing(mock_repo, mock_generate): """ a new short url is generated if the current is already mapped """ url = "www.ibm.com" shortened_url1 = "sdede" shortened_url2 = "dvdfs" mock_generate.side_effect = [shortened_url1, shortened_url2] mock_repo.get = MagicMock(side_effect=[OriginalUrl("existing"), None]) controller = ShortUrlController(mock_repo, mock_generate) shortened_url = controller.shorten_url(url) _assert_put_call_args(mock_repo, shortened_url2, url) assert shortened_url.short_url == "http://www.your_service.com/{}".format(shortened_url2)
def shorten_url(self, url): """ Attempts to shorten a given url (timeouts if not possible), storing it along the original url and timestamp :param url: a valid url string :return: ShortUrlDTO with the shortened url\ :raise: UrlGenerationTimeoutException if couldn't generate a new short url in time """ for _ in range(self.URL_GENERATION_TIMEOUT): short_url = self.generate_short_url_fn(url) if not self.url_repository.get(short_url): original_url = OriginalUrl(url=url, timestamp=datetime.now()) self.url_repository.put(short_url, original_url) return ShortUrlDTO(short_url) raise UrlGenerationTimeoutException( "Took too long to generate a non existing short url")