1#!/usr/bin/env python 2 3""" 4test installing and managing webapps in a profile 5""" 6 7import os 8import shutil 9import unittest 10from tempfile import mkdtemp 11 12from mozprofile.webapps import WebappCollection, Webapp, WebappFormatException 13 14here = os.path.dirname(os.path.abspath(__file__)) 15 16 17class WebappTest(unittest.TestCase): 18 """Tests reading, installing and cleaning webapps 19 from a profile. 20 """ 21 manifest_path_1 = os.path.join(here, 'files', 'webapps1.json') 22 manifest_path_2 = os.path.join(here, 'files', 'webapps2.json') 23 24 def setUp(self): 25 self.profile = mkdtemp(prefix='test_webapp') 26 self.webapps_dir = os.path.join(self.profile, 'webapps') 27 self.webapps_json_path = os.path.join(self.webapps_dir, 'webapps.json') 28 29 def tearDown(self): 30 shutil.rmtree(self.profile) 31 32 def test_read_json_manifest(self): 33 """Tests WebappCollection.read_json""" 34 # Parse a list of webapp objects and verify it worked 35 manifest_json_1 = WebappCollection.read_json(self.manifest_path_1) 36 self.assertEqual(len(manifest_json_1), 7) 37 for app in manifest_json_1: 38 self.assertIsInstance(app, Webapp) 39 for key in Webapp.required_keys: 40 self.assertIn(key, app) 41 42 # Parse a dictionary of webapp objects and verify it worked 43 manifest_json_2 = WebappCollection.read_json(self.manifest_path_2) 44 self.assertEqual(len(manifest_json_2), 5) 45 for app in manifest_json_2: 46 self.assertIsInstance(app, Webapp) 47 for key in Webapp.required_keys: 48 self.assertIn(key, app) 49 50 def test_invalid_webapp(self): 51 """Tests a webapp with a missing required key""" 52 webapps = WebappCollection(self.profile) 53 # Missing the required key "description", exception should be raised 54 self.assertRaises(WebappFormatException, webapps.append, {'name': 'foo'}) 55 56 def test_webapp_collection(self): 57 """Tests the methods of the WebappCollection object""" 58 webapp_1 = {'name': 'test_app_1', 59 'description': 'a description', 60 'manifestURL': 'http://example.com/1/manifest.webapp', 61 'appStatus': 1} 62 63 webapp_2 = {'name': 'test_app_2', 64 'description': 'another description', 65 'manifestURL': 'http://example.com/2/manifest.webapp', 66 'appStatus': 2} 67 68 webapp_3 = {'name': 'test_app_2', 69 'description': 'a third description', 70 'manifestURL': 'http://example.com/3/manifest.webapp', 71 'appStatus': 3} 72 73 webapps = WebappCollection(self.profile) 74 self.assertEqual(len(webapps), 0) 75 76 # WebappCollection should behave like a list 77 def invalid_index(): 78 webapps[0] 79 self.assertRaises(IndexError, invalid_index) 80 81 # Append a webapp object 82 webapps.append(webapp_1) 83 self.assertTrue(len(webapps), 1) 84 self.assertIsInstance(webapps[0], Webapp) 85 self.assertEqual(len(webapps[0]), len(webapp_1)) 86 self.assertEqual(len(set(webapps[0].items()) & set(webapp_1.items())), len(webapp_1)) 87 88 # Remove a webapp object 89 webapps.remove(webapp_1) 90 self.assertEqual(len(webapps), 0) 91 92 # Extend a list of webapp objects 93 webapps.extend([webapp_1, webapp_2]) 94 self.assertEqual(len(webapps), 2) 95 self.assertTrue(webapp_1 in webapps) 96 self.assertTrue(webapp_2 in webapps) 97 self.assertNotEquals(webapps[0], webapps[1]) 98 99 # Insert a webapp object 100 webapps.insert(1, webapp_3) 101 self.assertEqual(len(webapps), 3) 102 self.assertEqual(webapps[1], webapps[2]) 103 for app in webapps: 104 self.assertIsInstance(app, Webapp) 105 106 # Assigning an invalid type (must be accepted by the dict() constructor) should throw 107 def invalid_type(): 108 webapps[2] = 1 109 self.assertRaises(WebappFormatException, invalid_type) 110 111 def test_install_webapps(self): 112 """Test installing webapps into a profile that has no prior webapps""" 113 webapps = WebappCollection(self.profile, apps=self.manifest_path_1) 114 self.assertFalse(os.path.exists(self.webapps_dir)) 115 116 # update the webapp manifests for the first time 117 webapps.update_manifests() 118 self.assertFalse(os.path.isdir(os.path.join(self.profile, webapps.backup_dir))) 119 self.assertTrue(os.path.isfile(self.webapps_json_path)) 120 121 webapps_json = webapps.read_json(self.webapps_json_path, description="fake description") 122 self.assertEqual(len(webapps_json), 7) 123 for app in webapps_json: 124 self.assertIsInstance(app, Webapp) 125 126 manifest_json_1 = webapps.read_json(self.manifest_path_1) 127 manifest_json_2 = webapps.read_json(self.manifest_path_2) 128 self.assertEqual(len(webapps_json), len(manifest_json_1)) 129 for app in webapps_json: 130 self.assertTrue(app in manifest_json_1) 131 132 # Remove one of the webapps from WebappCollection after it got installed 133 removed_app = manifest_json_1[2] 134 webapps.remove(removed_app) 135 # Add new webapps to the collection 136 webapps.extend(manifest_json_2) 137 138 # update the webapp manifests a second time 139 webapps.update_manifests() 140 self.assertFalse(os.path.isdir(os.path.join(self.profile, webapps.backup_dir))) 141 self.assertTrue(os.path.isfile(self.webapps_json_path)) 142 143 webapps_json = webapps.read_json(self.webapps_json_path, description="a description") 144 self.assertEqual(len(webapps_json), 11) 145 146 # The new apps should be added 147 for app in webapps_json: 148 self.assertIsInstance(app, Webapp) 149 self.assertTrue(os.path.isfile(os.path.join(self.webapps_dir, app['name'], 150 'manifest.webapp'))) 151 # The removed app should not exist in the manifest 152 self.assertNotIn(removed_app, webapps_json) 153 self.assertFalse(os.path.exists(os.path.join(self.webapps_dir, removed_app['name']))) 154 155 # Cleaning should delete the webapps directory entirely 156 # since there was nothing there before 157 webapps.clean() 158 self.assertFalse(os.path.isdir(self.webapps_dir)) 159 160 def test_install_webapps_preexisting(self): 161 """Tests installing webapps when the webapps directory already exists""" 162 manifest_json_2 = WebappCollection.read_json(self.manifest_path_2) 163 164 # Synthesize a pre-existing webapps directory 165 os.mkdir(self.webapps_dir) 166 shutil.copyfile(self.manifest_path_2, self.webapps_json_path) 167 for app in manifest_json_2: 168 app_path = os.path.join(self.webapps_dir, app['name']) 169 os.mkdir(app_path) 170 f = open(os.path.join(app_path, 'manifest.webapp'), 'w') 171 f.close() 172 173 webapps = WebappCollection(self.profile, apps=self.manifest_path_1) 174 self.assertTrue(os.path.exists(self.webapps_dir)) 175 176 # update webapp manifests for the first time 177 webapps.update_manifests() 178 # A backup should be created 179 self.assertTrue(os.path.isdir(os.path.join(self.profile, webapps.backup_dir))) 180 181 # Both manifests should remain installed 182 webapps_json = webapps.read_json(self.webapps_json_path, description='a fake description') 183 self.assertEqual(len(webapps_json), 12) 184 for app in webapps_json: 185 self.assertIsInstance(app, Webapp) 186 self.assertTrue(os.path.isfile(os.path.join(self.webapps_dir, app['name'], 187 'manifest.webapp'))) 188 189 # Upon cleaning the backup should be restored 190 webapps.clean() 191 self.assertFalse(os.path.isdir(os.path.join(self.profile, webapps.backup_dir))) 192 193 # The original webapps should still be installed 194 webapps_json = webapps.read_json(self.webapps_json_path) 195 for app in webapps_json: 196 self.assertIsInstance(app, Webapp) 197 self.assertTrue(os.path.isfile(os.path.join(self.webapps_dir, app['name'], 198 'manifest.webapp'))) 199 self.assertEqual(webapps_json, manifest_json_2) 200 201if __name__ == '__main__': 202 unittest.main() 203