Merge lp:~michael.nelson/ubuntu-webcatalog/993813-cannot-import-for-purchase-with-archive-id-none into lp:ubuntu-webcatalog
- 993813-cannot-import-for-purchase-with-archive-id-none
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Łukasz Czyżykowski | ||||
Approved revision: | 120 | ||||
Merged at revision: | 116 | ||||
Proposed branch: | lp:~michael.nelson/ubuntu-webcatalog/993813-cannot-import-for-purchase-with-archive-id-none | ||||
Merge into: | lp:ubuntu-webcatalog | ||||
Diff against target: |
583 lines (+390/-61) 7 files modified
src/webcatalog/forms.py (+14/-3) src/webcatalog/migrations/0021_add_archive_id.py (+166/-0) src/webcatalog/models/applications.py (+1/-0) src/webcatalog/tests/factory.py (+3/-2) src/webcatalog/tests/test_commands.py (+99/-55) src/webcatalog/tests/test_data/sca_apps.txt (+43/-1) src/webcatalog/tests/test_forms.py (+64/-0) |
||||
To merge this branch: | bzr merge lp:~michael.nelson/ubuntu-webcatalog/993813-cannot-import-for-purchase-with-archive-id-none | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Łukasz Czyżykowski (community) | Approve | ||
Review via email: mp+104546@code.launchpad.net |
Commit message
Add Application.
Description of the change
Overview
========
Updates the ForPurchaseAppl
I've also moved a bunch of tests for extras that were in the ImportForPurcha
Initially, I thought arb apps should be saved with archive_id=None, but as Application.
`fab test`
- 120. By Michael Nelson
-
Merged trunk and resolved conflicts.
Preview Diff
1 | === modified file 'src/webcatalog/forms.py' |
2 | --- src/webcatalog/forms.py 2012-05-03 12:39:31 +0000 |
3 | +++ src/webcatalog/forms.py 2012-05-03 13:10:29 +0000 |
4 | @@ -144,10 +144,21 @@ |
5 | if 'debtags' in app_data and app_data['debtags']: |
6 | app_data['debtags'] = json.dumps([get_hw_short_description(x) |
7 | for x in app_data['debtags']]) |
8 | + app_data['application_id'] = app_data.get('id') |
9 | + |
10 | try: |
11 | - instance = Application.objects.get( |
12 | - archive_id=app_data.get('archive_id'), |
13 | - distroseries=distroseries) |
14 | + # XXX 2012-05-03 michaeln bug=993813 We can update to use |
15 | + # application_id only below once an import runs on production |
16 | + # setting the application_ids. |
17 | + archive_id = app_data.get('archive_id') |
18 | + if archive_id: |
19 | + instance = Application.objects.get( |
20 | + archive_id=archive_id, |
21 | + distroseries=distroseries) |
22 | + else: |
23 | + instance = Application.objects.get( |
24 | + application_id=app_data['application_id'], |
25 | + distroseries=distroseries) |
26 | except Application.DoesNotExist: |
27 | instance = None |
28 | |
29 | |
30 | === added file 'src/webcatalog/migrations/0021_add_archive_id.py' |
31 | --- src/webcatalog/migrations/0021_add_archive_id.py 1970-01-01 00:00:00 +0000 |
32 | +++ src/webcatalog/migrations/0021_add_archive_id.py 2012-05-03 13:10:29 +0000 |
33 | @@ -0,0 +1,166 @@ |
34 | +# encoding: utf-8 |
35 | +import datetime |
36 | +from south.db import db |
37 | +from south.v2 import SchemaMigration |
38 | +from django.db import models |
39 | + |
40 | +class Migration(SchemaMigration): |
41 | + |
42 | + def forwards(self, orm): |
43 | + |
44 | + # Adding field 'Application.application_id' |
45 | + db.add_column('webcatalog_application', 'application_id', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False) |
46 | + |
47 | + |
48 | + def backwards(self, orm): |
49 | + |
50 | + # Deleting field 'Application.application_id' |
51 | + db.delete_column('webcatalog_application', 'application_id') |
52 | + |
53 | + |
54 | + models = { |
55 | + 'auth.group': { |
56 | + 'Meta': {'object_name': 'Group'}, |
57 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
58 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
59 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
60 | + }, |
61 | + 'auth.permission': { |
62 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, |
63 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
64 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), |
65 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
66 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
67 | + }, |
68 | + 'auth.user': { |
69 | + 'Meta': {'object_name': 'User'}, |
70 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
71 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), |
72 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
73 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), |
74 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
75 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
76 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
77 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
78 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
79 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
80 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
81 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), |
82 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
83 | + }, |
84 | + 'contenttypes.contenttype': { |
85 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
86 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
87 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
88 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
89 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
90 | + }, |
91 | + 'webcatalog.application': { |
92 | + 'Meta': {'unique_together': "(('distroseries', 'archive_id'),)", 'object_name': 'Application'}, |
93 | + 'app_type': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), |
94 | + 'application_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
95 | + 'architectures': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
96 | + 'archive_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'null': 'True', 'blank': 'True'}), |
97 | + 'categories': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
98 | + 'channel': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
99 | + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
100 | + 'debtags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
101 | + 'departments': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.Department']", 'symmetrical': 'False', 'blank': 'True'}), |
102 | + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
103 | + 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']"}), |
104 | + 'for_purchase': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
105 | + 'icon': ('django.db.models.fields.files.ImageField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), |
106 | + 'icon_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
107 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
108 | + 'is_latest': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
109 | + 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
110 | + 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), |
111 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
112 | + 'package_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
113 | + 'popcon': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
114 | + 'price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2', 'blank': 'True'}), |
115 | + 'ratings_average': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '3', 'decimal_places': '2', 'blank': 'True'}), |
116 | + 'ratings_histogram': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), |
117 | + 'ratings_total': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
118 | + 'section': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), |
119 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), |
120 | + 'wilson_score': ('django.db.models.fields.FloatField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}) |
121 | + }, |
122 | + 'webcatalog.applicationmedia': { |
123 | + 'Meta': {'unique_together': "(('application', 'url'),)", 'object_name': 'ApplicationMedia'}, |
124 | + 'application': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Application']"}), |
125 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
126 | + 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), |
127 | + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) |
128 | + }, |
129 | + 'webcatalog.consumer': { |
130 | + 'Meta': {'object_name': 'Consumer'}, |
131 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
132 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
133 | + 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), |
134 | + 'secret': ('django.db.models.fields.CharField', [], {'default': "'MbyfjpwvpAZhZPLmGbEXCNhSGMCWCv'", 'max_length': '255', 'blank': 'True'}), |
135 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), |
136 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'oauth_consumer'", 'unique': 'True', 'to': "orm['auth.User']"}) |
137 | + }, |
138 | + 'webcatalog.department': { |
139 | + 'Meta': {'object_name': 'Department'}, |
140 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
141 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}), |
142 | + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Department']", 'null': 'True', 'blank': 'True'}), |
143 | + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) |
144 | + }, |
145 | + 'webcatalog.distroseries': { |
146 | + 'Meta': {'object_name': 'DistroSeries'}, |
147 | + 'code_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}), |
148 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
149 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}) |
150 | + }, |
151 | + 'webcatalog.exhibit': { |
152 | + 'Meta': {'object_name': 'Exhibit'}, |
153 | + 'banner_url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), |
154 | + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
155 | + 'display': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), |
156 | + 'distroseries': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.DistroSeries']", 'symmetrical': 'False'}), |
157 | + 'html': ('django.db.models.fields.TextField', [], {}), |
158 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
159 | + 'package_names': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), |
160 | + 'published': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
161 | + 'sca_id': ('django.db.models.fields.IntegerField', [], {}), |
162 | + 'weight': ('django.db.models.fields.IntegerField', [], {'default': '0'}) |
163 | + }, |
164 | + 'webcatalog.machine': { |
165 | + 'Meta': {'unique_together': "(('owner', 'uuid'),)", 'object_name': 'Machine'}, |
166 | + 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '64'}), |
167 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
168 | + 'logo_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56', 'blank': 'True'}), |
169 | + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), |
170 | + 'package_list': ('django.db.models.fields.TextField', [], {}), |
171 | + 'packages_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56'}), |
172 | + 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}) |
173 | + }, |
174 | + 'webcatalog.nonce': { |
175 | + 'Meta': {'object_name': 'Nonce'}, |
176 | + 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), |
177 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
178 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
179 | + 'nonce': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), |
180 | + 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Token']"}) |
181 | + }, |
182 | + 'webcatalog.reviewstatsimport': { |
183 | + 'Meta': {'object_name': 'ReviewStatsImport'}, |
184 | + 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']", 'unique': 'True'}), |
185 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
186 | + 'last_import': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}) |
187 | + }, |
188 | + 'webcatalog.token': { |
189 | + 'Meta': {'object_name': 'Token'}, |
190 | + 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), |
191 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
192 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
193 | + 'token': ('django.db.models.fields.CharField', [], {'default': "'afduSDFNmldZMjYZFoBLOhXEULKLrbmDGPKtuoHEUVLCyheFhY'", 'max_length': '50', 'primary_key': 'True'}), |
194 | + 'token_secret': ('django.db.models.fields.CharField', [], {'default': "'obbeyYIEgkoxRBtOlkaXbtfgOGnkWUVIppSANzntzFEMuOytlC'", 'max_length': '50'}), |
195 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) |
196 | + } |
197 | + } |
198 | + |
199 | + complete_apps = ['webcatalog'] |
200 | |
201 | === modified file 'src/webcatalog/models/applications.py' |
202 | --- src/webcatalog/models/applications.py 2012-04-13 20:45:03 +0000 |
203 | +++ src/webcatalog/models/applications.py 2012-05-03 13:10:29 +0000 |
204 | @@ -89,6 +89,7 @@ |
205 | db_index=True, blank=True) |
206 | price = models.DecimalField(max_digits=7, decimal_places=2, null=True, |
207 | blank=True, help_text="For-purchase applications (in US Dollars).") |
208 | + application_id = models.IntegerField(null=True, blank=True) |
209 | |
210 | ratings_total = models.IntegerField(null=True, blank=True) |
211 | ratings_average = models.DecimalField(max_digits=3, decimal_places=2, |
212 | |
213 | === modified file 'src/webcatalog/tests/factory.py' |
214 | --- src/webcatalog/tests/factory.py 2012-04-17 17:09:03 +0000 |
215 | +++ src/webcatalog/tests/factory.py 2012-05-03 13:10:29 +0000 |
216 | @@ -101,7 +101,7 @@ |
217 | distroseries=None, arch='i686', ratings_average=None, |
218 | ratings_total=None, ratings_histogram='', screenshot_url='', |
219 | archive_id=None, version='', is_latest=False, wilson_score=0.0, |
220 | - debtags=[]): |
221 | + debtags=[], application_id=None): |
222 | if name is None: |
223 | name = self.get_unique_string(prefix='Readable Name') |
224 | if package_name is None: |
225 | @@ -120,7 +120,8 @@ |
226 | ratings_average=ratings_average, ratings_total=ratings_total, |
227 | ratings_histogram=ratings_histogram, |
228 | archive_id=archive_id, version=version, is_latest=is_latest, |
229 | - wilson_score=wilson_score, debtags=debtags) |
230 | + wilson_score=wilson_score, debtags=debtags, |
231 | + application_id=application_id) |
232 | |
233 | if screenshot_url: |
234 | ApplicationMedia.objects.create( |
235 | |
236 | === modified file 'src/webcatalog/tests/test_commands.py' |
237 | --- src/webcatalog/tests/test_commands.py 2012-04-20 16:57:50 +0000 |
238 | +++ src/webcatalog/tests/test_commands.py 2012-05-03 13:10:29 +0000 |
239 | @@ -433,26 +433,86 @@ |
240 | command.process_desktop_file(desktop_file, '', distroseries) |
241 | # no breakage! |
242 | |
243 | + @patch('urllib.urlopen') |
244 | + def test_fetch_icon_from_extras(self, mock_urlopen): |
245 | + mock_urlopen.return_value.getcode.return_value = 200 |
246 | + mock_urlopen.return_value.read.return_value = "I'm a png!" |
247 | + app = self.factory.make_application() |
248 | + candidate = Mock() |
249 | + candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' |
250 | + candidate.record = {'Icon': 'foo.png'} |
251 | + command = import_app_install_data.Command() |
252 | + |
253 | + command.fetch_icon_from_extras(app, candidate) |
254 | + |
255 | + self.assertEqual("I'm a png!", app.icon.read()) |
256 | + self.assertEqual(1, mock_urlopen.call_count) |
257 | + mock_urlopen.assert_called_with( |
258 | + 'http://extras.ubuntu.com/meta/foo.png') |
259 | + |
260 | + @patch('urllib.urlopen') |
261 | + def test_fetches_nothing_if_no_icon(self, mock_urlopen): |
262 | + app = self.factory.make_application() |
263 | + candidate = Mock() |
264 | + candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' |
265 | + candidate.record = {} |
266 | + command = import_app_install_data.Command() |
267 | + |
268 | + command.fetch_icon_from_extras(app, candidate) |
269 | + |
270 | + self.assertEqual(0, mock_urlopen.call_count) |
271 | + self.assertFalse(app.icon) |
272 | + |
273 | + @patch('urllib.urlopen') |
274 | + def test_fetches_nothing_if_not_in_extras(self, mock_urlopen): |
275 | + app = self.factory.make_application() |
276 | + candidate = Mock() |
277 | + candidate.uri = 'http://archive.ubuntu.com/pool/f/foobar.deb' |
278 | + candidate.record = {'Icon': 'foobar.png'} |
279 | + command = import_app_install_data.Command() |
280 | + |
281 | + command.fetch_icon_from_extras(app, candidate) |
282 | + |
283 | + self.assertEqual(0, mock_urlopen.call_count) |
284 | + self.assertFalse(app.icon) |
285 | + |
286 | |
287 | class ImportForPurchaseAppsTestCase(TestCaseWithFactory): |
288 | |
289 | def setUp(self): |
290 | super(ImportForPurchaseAppsTestCase, self).setUp() |
291 | - curdir = os.path.dirname(__file__) |
292 | - sca_apps_file = os.path.join(curdir, 'test_data', 'sca_apps.txt') |
293 | self.natty = self.factory.make_distroseries( |
294 | code_name='natty', version='11.04') |
295 | self.maverick = self.factory.make_distroseries( |
296 | code_name='maverick', version='10.10') |
297 | - with open(sca_apps_file) as content: |
298 | - self.response_content = content.read() |
299 | - mock_response = Mock() |
300 | - mock_response.code = 200 |
301 | - mock_response.read.return_value = self.response_content |
302 | |
303 | self.patch_urlopen = patch('urllib.urlopen') |
304 | - mock_urllib = self.patch_urlopen.start() |
305 | - mock_urllib.return_value = mock_response |
306 | + self.mock_urlopen = self.patch_urlopen.start() |
307 | + |
308 | + def mock_urlopen_fn(url): |
309 | + """Return predetermined test_data content for given urls.""" |
310 | + available_apps_url = '%sapplications/any/ubuntu/any/any/' % ( |
311 | + settings.SCA_API_URL) |
312 | + icon_arb_url = ('http://sc.staging.ubuntu.com/' |
313 | + 'site_media/appmedia/2012/04/ktip.png') |
314 | + icon_hello_url = ('http://localhost:8000/' |
315 | + 'site_media/icons/2011/06/eg_64x64.png') |
316 | + filenames = { |
317 | + available_apps_url: 'sca_apps.txt', |
318 | + icon_arb_url: 'ubuntu-cof.png', |
319 | + icon_hello_url: 'ubuntu-cof.png', |
320 | + } |
321 | + curdir = os.path.dirname(__file__) |
322 | + sca_apps_file = os.path.join(curdir, 'test_data', |
323 | + filenames[url]) |
324 | + with open(sca_apps_file) as content: |
325 | + self.response_content = content.read() |
326 | + mock_response = Mock() |
327 | + mock_response.code = 200 |
328 | + mock_response.read.return_value = self.response_content |
329 | + return mock_response |
330 | + |
331 | + self.mock_urlopen.side_effect = mock_urlopen_fn |
332 | self.addCleanup(self.patch_urlopen.stop) |
333 | |
334 | def test_app_for_purchase_is_found(self): |
335 | @@ -486,21 +546,30 @@ |
336 | self.factory.make_application(archive_id='launchpad_zematynnad2/myppa', |
337 | package_name='somethingelse', |
338 | distroseries=self.natty) |
339 | - self.assertEqual(2, Application.objects.count()) |
340 | + self.assertEqual(2, |
341 | + Application.objects.filter( |
342 | + distroseries__in=(self.natty, self.maverick)).count()) |
343 | |
344 | call_command('import_for_purchase_apps') |
345 | |
346 | - self.assertEqual(2, Application.objects.count()) |
347 | - for app in Application.objects.all(): |
348 | + actual_apps = Application.objects.filter( |
349 | + distroseries__in=(self.natty, self.maverick)) |
350 | + self.assertEqual(2, actual_apps.count()) |
351 | + for app in actual_apps: |
352 | self.assertEqual('launchpad_zematynnad2/myppa', app.archive_id) |
353 | self.assertEqual('hello', app.package_name) |
354 | |
355 | def test_app_gets_icon(self): |
356 | call_command('import_for_purchase_apps') |
357 | |
358 | + self.mock_urlopen.assert_called_with( |
359 | + 'http://sc.staging.ubuntu.com/' |
360 | + 'site_media/appmedia/2012/04/ktip.png') |
361 | app = Application.objects.get(name='MyApp', |
362 | distroseries=self.natty) |
363 | - self.assertEqual(6461, app.icon.size) |
364 | + # The urlopen double returns the test_data/ubuntu-cof.png which has |
365 | + # a size of 2438. |
366 | + self.assertEqual(2438, app.icon.size) |
367 | |
368 | def test_app_gets_version(self): |
369 | call_command('import_for_purchase_apps') |
370 | @@ -524,48 +593,23 @@ |
371 | qs = app.applicationmedia_set.filter(media_type='screenshot') |
372 | self.assertEqual(2, qs.count()) |
373 | |
374 | - @patch('urllib.urlopen') |
375 | - def test_fetch_icon_from_extras(self, mock_urlopen): |
376 | - mock_urlopen.return_value.getcode.return_value = 200 |
377 | - mock_urlopen.return_value.read.return_value = "I'm a png!" |
378 | - app = self.factory.make_application() |
379 | - candidate = Mock() |
380 | - candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' |
381 | - candidate.record = {'Icon': 'foo.png'} |
382 | - command = import_app_install_data.Command() |
383 | - |
384 | - command.fetch_icon_from_extras(app, candidate) |
385 | - |
386 | - self.assertEqual("I'm a png!", app.icon.read()) |
387 | - self.assertEqual(1, mock_urlopen.call_count) |
388 | - mock_urlopen.assert_called_with( |
389 | - 'http://extras.ubuntu.com/meta/foo.png') |
390 | - |
391 | - @patch('urllib.urlopen') |
392 | - def test_fetches_nothing_if_no_icon(self, mock_urlopen): |
393 | - app = self.factory.make_application() |
394 | - candidate = Mock() |
395 | - candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' |
396 | - candidate.record = {} |
397 | - command = import_app_install_data.Command() |
398 | - |
399 | - command.fetch_icon_from_extras(app, candidate) |
400 | - |
401 | - self.assertEqual(0, mock_urlopen.call_count) |
402 | - self.assertFalse(app.icon) |
403 | - |
404 | - @patch('urllib.urlopen') |
405 | - def test_fetches_nothing_if_not_in_extras(self, mock_urlopen): |
406 | - app = self.factory.make_application() |
407 | - candidate = Mock() |
408 | - candidate.uri = 'http://archive.ubuntu.com/pool/f/foobar.deb' |
409 | - candidate.record = {'Icon': 'foobar.png'} |
410 | - command = import_app_install_data.Command() |
411 | - |
412 | - command.fetch_icon_from_extras(app, candidate) |
413 | - |
414 | - self.assertEqual(0, mock_urlopen.call_count) |
415 | - self.assertFalse(app.icon) |
416 | + def test_import_arb_app(self): |
417 | + call_command('import_for_purchase_apps') |
418 | + |
419 | + arb_apps = Application.objects.filter(package_name='eg_arb_app') |
420 | + self.assertEqual(2, arb_apps.count()) |
421 | + self.assertEqual('', arb_apps[0].archive_id) |
422 | + self.assertEqual('', arb_apps[1].archive_id) |
423 | + |
424 | + def test_import_arb_app_handle_existing_none_archive_id(self): |
425 | + precise = self.factory.make_distroseries(code_name='precise') |
426 | + self.factory.make_application(archive_id=None, distroseries=precise) |
427 | + self.factory.make_application(archive_id=None, distroseries=precise) |
428 | + |
429 | + call_command('import_for_purchase_apps') |
430 | + |
431 | + arb_apps = Application.objects.filter(package_name='eg_arb_app') |
432 | + self.assertEqual(2, arb_apps.count()) |
433 | |
434 | |
435 | class ImportRatingsTestCase(TestCaseWithFactory): |
436 | |
437 | === modified file 'src/webcatalog/tests/test_data/sca_apps.txt' |
438 | --- src/webcatalog/tests/test_data/sca_apps.txt 2012-03-19 13:39:16 +0000 |
439 | +++ src/webcatalog/tests/test_data/sca_apps.txt 2012-05-03 13:10:29 +0000 |
440 | @@ -1,5 +1,6 @@ |
441 | [ |
442 | { |
443 | + "id": 18, |
444 | "status": "Published", |
445 | "signing_key_id": "", |
446 | "description": "MyAppTagline\nThe classic greeting, and a good example\r\n The GNU hello program produces a familiar, friendly greeting. It\r\n allows non-programmers to use a classic computer science tool which\r\n would otherwise be unavailable to them.\r\n .\r\n Seriously, though: this is an example of how to do a Debian package.\r\n It is the Debian version of the GNU Project's `hello world' program\r\n (which is itself an example for the GNU Project).", |
447 | @@ -8,7 +9,6 @@ |
448 | "series": {"maverick": ["i386", "amd64"], "natty": ["i386", "amd64"]}, |
449 | "price": "2.50", |
450 | "archive_id": "launchpad_zematynnad2/myppa", |
451 | - "icon_data": "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", |
452 | "screenshot_url": "", |
453 | "screenshot_urls": [ |
454 | "http://localhost:8000/screenshot_1.png", |
455 | @@ -19,5 +19,47 @@ |
456 | "icon_url": "http://localhost:8000/site_media/icons/2011/06/eg_64x64.png", |
457 | "categories": "Audio", |
458 | "name": "MyApp" |
459 | + }, |
460 | + { |
461 | + "package_name": "eg_arb_app", |
462 | + "video_embedded_html_urls": [], |
463 | + "series": { |
464 | + "precise": [ |
465 | + "amd64", |
466 | + "i386" |
467 | + ], |
468 | + "oneiric": [ |
469 | + "i386", |
470 | + "amd64" |
471 | + ] |
472 | + }, |
473 | + "video_urls": [], |
474 | + "screenshot_url": "http://sc.staging.ubuntu.com/site_media/appmedia/2012/04/IMG_20120401_144332.jpg", |
475 | + "id": 595, |
476 | + "archive_id": null, |
477 | + "support_url": "http://example.com/foo", |
478 | + "icon_url": "http://sc.staging.ubuntu.com/site_media/appmedia/2012/04/ktip.png", |
479 | + "version": "1.2", |
480 | + "demo": null, |
481 | + "department": [ |
482 | + "Accessories" |
483 | + ], |
484 | + "tos_url": "", |
485 | + "channel": "Independent", |
486 | + "status": "Published", |
487 | + "signing_key_id": "", |
488 | + "description": "This is a test about ARB apps\nThis is a description. My test application will provide magic and wonder to kids of all ages.", |
489 | + "price": "0.00", |
490 | + "debtags": [ |
491 | + "hardware::input:mouse" |
492 | + ], |
493 | + "date_published": "2012-04-30 19:34:08.011454", |
494 | + "categories": "Utility", |
495 | + "name": "ARB test", |
496 | + "license": "GNU GPL v3", |
497 | + "screenshot_urls": [ |
498 | + "http://sc.staging.ubuntu.com/site_media/appmedia/2012/04/IMG_20120401_144332.jpg" |
499 | + ], |
500 | + "archive_root": "http://extras.ubuntu.com/" |
501 | } |
502 | ] |
503 | |
504 | === modified file 'src/webcatalog/tests/test_forms.py' |
505 | --- src/webcatalog/tests/test_forms.py 2012-05-02 15:18:48 +0000 |
506 | +++ src/webcatalog/tests/test_forms.py 2012-05-03 13:10:29 +0000 |
507 | @@ -203,6 +203,7 @@ |
508 | app.distroseries) |
509 | self.assertTrue(form.is_valid()) |
510 | form.save_media_urls() |
511 | + |
512 | self.assertEqual(3, app.applicationmedia_set.count()) |
513 | actual_urls = [media.url for media in app.applicationmedia_set.all()] |
514 | self.assertEqual([ |
515 | @@ -211,6 +212,69 @@ |
516 | 'http://example.com/video1.mp4', |
517 | ], actual_urls) |
518 | |
519 | + def make_valid_data(self, **kwargs): |
520 | + data = { |
521 | + u'status': u'Published', |
522 | + u'signing_key_id': u'', |
523 | + u'description': u'This is a description.', |
524 | + u'package_name': self.factory.get_unique_string(prefix='pkg'), |
525 | + u'video_embedded_html_urls': [], |
526 | + u'series': { |
527 | + u'precise': [u'amd64', u'i386'], |
528 | + u'oneiric': [u'i386', u'amd64'] |
529 | + }, |
530 | + u'price': u'0.00', |
531 | + u'debtags': '["mouse"]', |
532 | + u'date_published': u'2012-04-30 19:34:08.011454', |
533 | + u'video_urls': [], |
534 | + u'screenshot_url': u'http://sc.staging.ubuntu.com/' |
535 | + 'site_media/appmedia/2012/04/' |
536 | + 'IMG_20120401_144332.jpg', |
537 | + u'id': 595, |
538 | + u'categories': u'Utility', |
539 | + u'archive_id': self.factory.get_unique_string(prefix='archid/'), |
540 | + u'name': u'Test App', |
541 | + u'license': u'GNU GPL v3', |
542 | + u'support_url': u'http://example.com/foo', |
543 | + u'icon_url': u'http://sc.staging.ubuntu.com/' |
544 | + 'site_media/appmedia/2012/04/ktip.png', |
545 | + u'comment': u'This is a test app', |
546 | + u'version': u'1.2', |
547 | + u'screenshot_urls': [ |
548 | + u'http://sc.staging.ubuntu.com/' |
549 | + 'site_media/appmedia/2012/04/IMG_20120401_144332.jpg', |
550 | + ], |
551 | + u'demo': None, |
552 | + u'department': [u'Accessories'], |
553 | + u'archive_root': u'http://extras.ubuntu.com/', |
554 | + u'tos_url': u'', |
555 | + u'channel': u'Independent', |
556 | + } |
557 | + data.update(**kwargs) |
558 | + return data |
559 | + |
560 | + def test_archive_id_none_uses_application_id(self): |
561 | + precise = self.factory.make_distroseries(code_name='precise') |
562 | + existing_app = self.factory.make_application( |
563 | + archive_id=None, application_id=21, distroseries=precise) |
564 | + |
565 | + data = self.make_valid_data(archive_id=None, id=21) |
566 | + form = ForPurchaseApplicationForm.from_api_data(data, precise) |
567 | + |
568 | + self.assertEqual(existing_app, form.instance) |
569 | + |
570 | + def test_updates_application_id(self): |
571 | + precise = self.factory.make_distroseries(code_name='precise') |
572 | + existing_app = self.factory.make_application( |
573 | + archive_id='foo/bar', application_id=None, distroseries=precise) |
574 | + |
575 | + data = self.make_valid_data(archive_id='foo/bar', id=21) |
576 | + form = ForPurchaseApplicationForm.from_api_data(data, precise) |
577 | + form.save() |
578 | + |
579 | + app_reloaded = Application.objects.get(id=existing_app.id) |
580 | + self.assertEqual(21, app_reloaded.application_id) |
581 | + |
582 | |
583 | class MultiURLFieldTestCase(TestCase): |
584 |
LGTM