"""Test for the manifest library.""" import json import time import flexmock import pytest from cdnmanifest import manifest @pytest.fixture def simple_get_manifest_data(): """Return simple manifest data.""" now = int(time.time()) return now, {} @pytest.fixture def get_manifest_data(): """Return manifest data.""" with open('tests/fixtures/manifest.json') as manifest: content = manifest.read() content = json.loads(content) return content.pop('timestamp'), content @pytest.mark.parametrize('environment, application_name', [ (manifest.ENVIRONMENT_PROD, 'frontend-accounting'), (manifest.ENVIRONMENT_QA, 'frontend-distribution'), ('random', 'frontend-auth')]) def test_creating_manifest(application_name, environment): """Test creating a manifest.""" data = simple_get_manifest_data() flexmock(manifest).should_receive('get_manifest').and_return(data) current_manifest = manifest.Manifest(application_name, environment) environment = manifest.validate_environment(environment) assert current_manifest.application_name == application_name assert current_manifest.environment == environment assert not current_manifest.timestamp assert not current_manifest.content current_manifest.synchronize() assert current_manifest.timestamp is data[0] assert current_manifest.content is data[1] @pytest.mark.parametrize('environment, application_name, expires_in', [ (manifest.ENVIRONMENT_PROD, 'frontend-accounting', 2000)]) def test_creating_manifest_with_expiration( application_name, environment, expires_in): """Test creating a manifest.""" data = simple_get_manifest_data() flexmock(manifest).should_receive('get_manifest').and_return(data) current_manifest = manifest.Manifest( application_name, environment, expires_in) assert current_manifest.expires_in == expires_in @pytest.mark.parametrize('filename', ['main.bundle.js', 'main.css']) def test_getting_url(get_manifest_data, filename): """Test getting a url for an asset.""" data = get_manifest_data flexmock(manifest).should_receive('get_manifest').and_return(data) current_manifest = manifest.Manifest('frontend', manifest.ENVIRONMENT_PROD) expected_url = ( 'https://cdn.theorchard.io/frontend/20161019113904/{}'.format( filename)) assert current_manifest.get_url(filename) == expected_url @pytest.mark.parametrize('filename', ['main.bundle.js', 'main.css']) def test_getting_url_requests_synchronization(get_manifest_data, filename): """Test getting a url for an asset requests a manifest synchronization.""" data = get_manifest_data flexmock(manifest).should_receive('get_manifest').and_return(data) current_manifest = manifest.Manifest('frontend', manifest.ENVIRONMENT_PROD) flexmock(current_manifest).should_call('synchronize').once() current_manifest.get_url('file') def test_getting_url_for_unknown_asset(get_manifest_data): """Test getting an unknown asset.""" data = get_manifest_data flexmock(manifest).should_receive('get_manifest').and_return(data) current_manifest = manifest.Manifest('frontend', manifest.ENVIRONMENT_PROD) expected_url = ('https://cdn.theorchard.io/frontend/20161019113904/file') assert current_manifest.get_url('file') == expected_url def test_getting_localized_url(get_manifest_data): """Test getting a localized url for an asset.""" data = get_manifest_data flexmock(manifest).should_receive('get_manifest').and_return(data) current_manifest = manifest.Manifest('frontend', manifest.ENVIRONMENT_PROD) expected_url = ( 'https://cdn.theorchard.io/frontend/20161019113904/' 'main.fr.bundle.js') assert current_manifest.get_url('main.bundle.js', 'fr') == expected_url def test_getting_localized_url_with_unknown_localization(get_manifest_data): """Test getting a localized url for an asset.""" data = get_manifest_data flexmock(manifest).should_receive('get_manifest').and_return(data) current_manifest = manifest.Manifest('frontend', manifest.ENVIRONMENT_PROD) expected_url = ( 'https://cdn.theorchard.io/frontend/20161019113904/' 'main.bundle.js') assert current_manifest.get_url('main.bundle.js', 'foo') == expected_url def test_synchronizing_manifest(get_manifest_data): """Test synchronizing manifest and sets timestamp and content.""" data = get_manifest_data (flexmock(manifest) .should_receive('get_manifest') .and_return(data) .once()) current_manifest = manifest.Manifest('frontend', manifest.ENVIRONMENT_PROD) current_manifest.synchronize() assert current_manifest.timestamp assert current_manifest.content assert current_manifest.last_sync def test_synchronizing_without_expiration(get_manifest_data): """Test synchronizing without setting an explicit expiration. It will only synchronize one time. The way to know is by spying on the get_manifest method. Flexmock will throw an exception if the get_manifest was called twice. """ data = get_manifest_data flexmock(manifest).should_receive('get_manifest').and_return(data).once() current_manifest = manifest.Manifest('frontend', manifest.ENVIRONMENT_PROD) current_manifest.synchronize() def test_synchronizing_on_nonexpired_manifest(get_manifest_data): """Test synchronizing on non expired manifest.""" data = get_manifest_data flexmock(manifest).should_receive('get_manifest').and_return(data).once() current_manifest = manifest.Manifest( 'frontend', manifest.ENVIRONMENT_PROD, expires_in=3600) current_manifest.synchronize() def test_synchronizing_on_expired_manifest(get_manifest_data): """Test synchronizing on expired manifest, should refresh.""" data = get_manifest_data expires_in = 3600 flexmock(manifest).should_receive('get_manifest').and_return(data).twice() current_manifest = manifest.Manifest( 'frontend', manifest.ENVIRONMENT_PROD, expires_in=expires_in) current_manifest.synchronize() flexmock(time).should_receive('time').and_return( current_manifest.last_sync + expires_in + 1) current_manifest.synchronize() def test_getting_manifest_file(get_manifest_data): """Test getting a manifest file.""" data = get_manifest_data[1] data.update(timestamp=get_manifest_data[0]) data = json.dumps(data).encode('utf8') Object = flexmock(get=lambda: {'Body': flexmock(read=lambda: data)}) mock = flexmock(manifest.s3).should_receive('Object') mock = mock.with_args('prod-orcd-cdn', 'app_name/manifest.json') mock = mock.and_return(Object).once() response = manifest.get_manifest('app_name', manifest.ENVIRONMENT_PROD) assert isinstance(response, tuple) timestamp, content = response assert timestamp.isdigit() assert isinstance(content, dict) assert 'timestamp' not in content def test_creating_file_url(): """Test creating file url.""" url = manifest.create_url( 'app_name', manifest.ENVIRONMENT_PROD, 'timestamp', 'path') assert url == 'https://cdn.theorchard.io/app_name/timestamp/path' def test_validate_environment(): """Test validating the environment.""" qa = manifest.ENVIRONMENT_QA prod = manifest.ENVIRONMENT_PROD assert manifest.validate_environment(qa) is qa assert manifest.validate_environment(prod) is prod def test_validate_wrong_environment_defaults_to_qa(): """Test validating an environemtn that is not valid defaults to QA.""" qa = manifest.ENVIRONMENT_QA assert manifest.validate_environment('foo') is qa