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 | 144 | if 'debtags' in app_data and app_data['debtags']: | 144 | if 'debtags' in app_data and app_data['debtags']: |
6 | 145 | app_data['debtags'] = json.dumps([get_hw_short_description(x) | 145 | app_data['debtags'] = json.dumps([get_hw_short_description(x) |
7 | 146 | for x in app_data['debtags']]) | 146 | for x in app_data['debtags']]) |
8 | 147 | app_data['application_id'] = app_data.get('id') | ||
9 | 148 | |||
10 | 147 | try: | 149 | try: |
14 | 148 | instance = Application.objects.get( | 150 | # XXX 2012-05-03 michaeln bug=993813 We can update to use |
15 | 149 | archive_id=app_data.get('archive_id'), | 151 | # application_id only below once an import runs on production |
16 | 150 | distroseries=distroseries) | 152 | # setting the application_ids. |
17 | 153 | archive_id = app_data.get('archive_id') | ||
18 | 154 | if archive_id: | ||
19 | 155 | instance = Application.objects.get( | ||
20 | 156 | archive_id=archive_id, | ||
21 | 157 | distroseries=distroseries) | ||
22 | 158 | else: | ||
23 | 159 | instance = Application.objects.get( | ||
24 | 160 | application_id=app_data['application_id'], | ||
25 | 161 | distroseries=distroseries) | ||
26 | 151 | except Application.DoesNotExist: | 162 | except Application.DoesNotExist: |
27 | 152 | instance = None | 163 | instance = None |
28 | 153 | 164 | ||
29 | 154 | 165 | ||
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 | 1 | # encoding: utf-8 | ||
35 | 2 | import datetime | ||
36 | 3 | from south.db import db | ||
37 | 4 | from south.v2 import SchemaMigration | ||
38 | 5 | from django.db import models | ||
39 | 6 | |||
40 | 7 | class Migration(SchemaMigration): | ||
41 | 8 | |||
42 | 9 | def forwards(self, orm): | ||
43 | 10 | |||
44 | 11 | # Adding field 'Application.application_id' | ||
45 | 12 | db.add_column('webcatalog_application', 'application_id', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False) | ||
46 | 13 | |||
47 | 14 | |||
48 | 15 | def backwards(self, orm): | ||
49 | 16 | |||
50 | 17 | # Deleting field 'Application.application_id' | ||
51 | 18 | db.delete_column('webcatalog_application', 'application_id') | ||
52 | 19 | |||
53 | 20 | |||
54 | 21 | models = { | ||
55 | 22 | 'auth.group': { | ||
56 | 23 | 'Meta': {'object_name': 'Group'}, | ||
57 | 24 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
58 | 25 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
59 | 26 | 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
60 | 27 | }, | ||
61 | 28 | 'auth.permission': { | ||
62 | 29 | 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
63 | 30 | 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
64 | 31 | 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
65 | 32 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
66 | 33 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
67 | 34 | }, | ||
68 | 35 | 'auth.user': { | ||
69 | 36 | 'Meta': {'object_name': 'User'}, | ||
70 | 37 | 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
71 | 38 | 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
72 | 39 | 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
73 | 40 | 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
74 | 41 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
75 | 42 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
76 | 43 | 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
77 | 44 | 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
78 | 45 | 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
79 | 46 | 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
80 | 47 | 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
81 | 48 | 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
82 | 49 | 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
83 | 50 | }, | ||
84 | 51 | 'contenttypes.contenttype': { | ||
85 | 52 | 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
86 | 53 | 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
87 | 54 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
88 | 55 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
89 | 56 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
90 | 57 | }, | ||
91 | 58 | 'webcatalog.application': { | ||
92 | 59 | 'Meta': {'unique_together': "(('distroseries', 'archive_id'),)", 'object_name': 'Application'}, | ||
93 | 60 | 'app_type': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), | ||
94 | 61 | 'application_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
95 | 62 | 'architectures': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
96 | 63 | 'archive_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'null': 'True', 'blank': 'True'}), | ||
97 | 64 | 'categories': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
98 | 65 | 'channel': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
99 | 66 | 'comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
100 | 67 | 'debtags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
101 | 68 | 'departments': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.Department']", 'symmetrical': 'False', 'blank': 'True'}), | ||
102 | 69 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
103 | 70 | 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']"}), | ||
104 | 71 | 'for_purchase': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
105 | 72 | 'icon': ('django.db.models.fields.files.ImageField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), | ||
106 | 73 | 'icon_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
107 | 74 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
108 | 75 | 'is_latest': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
109 | 76 | 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
110 | 77 | 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), | ||
111 | 78 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
112 | 79 | 'package_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
113 | 80 | 'popcon': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
114 | 81 | 'price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2', 'blank': 'True'}), | ||
115 | 82 | 'ratings_average': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '3', 'decimal_places': '2', 'blank': 'True'}), | ||
116 | 83 | 'ratings_histogram': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), | ||
117 | 84 | 'ratings_total': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
118 | 85 | 'section': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), | ||
119 | 86 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
120 | 87 | 'wilson_score': ('django.db.models.fields.FloatField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}) | ||
121 | 88 | }, | ||
122 | 89 | 'webcatalog.applicationmedia': { | ||
123 | 90 | 'Meta': {'unique_together': "(('application', 'url'),)", 'object_name': 'ApplicationMedia'}, | ||
124 | 91 | 'application': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Application']"}), | ||
125 | 92 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
126 | 93 | 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), | ||
127 | 94 | 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) | ||
128 | 95 | }, | ||
129 | 96 | 'webcatalog.consumer': { | ||
130 | 97 | 'Meta': {'object_name': 'Consumer'}, | ||
131 | 98 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
132 | 99 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
133 | 100 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
134 | 101 | 'secret': ('django.db.models.fields.CharField', [], {'default': "'MbyfjpwvpAZhZPLmGbEXCNhSGMCWCv'", 'max_length': '255', 'blank': 'True'}), | ||
135 | 102 | 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), | ||
136 | 103 | 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'oauth_consumer'", 'unique': 'True', 'to': "orm['auth.User']"}) | ||
137 | 104 | }, | ||
138 | 105 | 'webcatalog.department': { | ||
139 | 106 | 'Meta': {'object_name': 'Department'}, | ||
140 | 107 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
141 | 108 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
142 | 109 | 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Department']", 'null': 'True', 'blank': 'True'}), | ||
143 | 110 | 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) | ||
144 | 111 | }, | ||
145 | 112 | 'webcatalog.distroseries': { | ||
146 | 113 | 'Meta': {'object_name': 'DistroSeries'}, | ||
147 | 114 | 'code_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}), | ||
148 | 115 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
149 | 116 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}) | ||
150 | 117 | }, | ||
151 | 118 | 'webcatalog.exhibit': { | ||
152 | 119 | 'Meta': {'object_name': 'Exhibit'}, | ||
153 | 120 | 'banner_url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), | ||
154 | 121 | 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
155 | 122 | 'display': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), | ||
156 | 123 | 'distroseries': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.DistroSeries']", 'symmetrical': 'False'}), | ||
157 | 124 | 'html': ('django.db.models.fields.TextField', [], {}), | ||
158 | 125 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
159 | 126 | 'package_names': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), | ||
160 | 127 | 'published': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
161 | 128 | 'sca_id': ('django.db.models.fields.IntegerField', [], {}), | ||
162 | 129 | 'weight': ('django.db.models.fields.IntegerField', [], {'default': '0'}) | ||
163 | 130 | }, | ||
164 | 131 | 'webcatalog.machine': { | ||
165 | 132 | 'Meta': {'unique_together': "(('owner', 'uuid'),)", 'object_name': 'Machine'}, | ||
166 | 133 | 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
167 | 134 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
168 | 135 | 'logo_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56', 'blank': 'True'}), | ||
169 | 136 | 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), | ||
170 | 137 | 'package_list': ('django.db.models.fields.TextField', [], {}), | ||
171 | 138 | 'packages_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56'}), | ||
172 | 139 | 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}) | ||
173 | 140 | }, | ||
174 | 141 | 'webcatalog.nonce': { | ||
175 | 142 | 'Meta': {'object_name': 'Nonce'}, | ||
176 | 143 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), | ||
177 | 144 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
178 | 145 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
179 | 146 | 'nonce': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), | ||
180 | 147 | 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Token']"}) | ||
181 | 148 | }, | ||
182 | 149 | 'webcatalog.reviewstatsimport': { | ||
183 | 150 | 'Meta': {'object_name': 'ReviewStatsImport'}, | ||
184 | 151 | 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']", 'unique': 'True'}), | ||
185 | 152 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
186 | 153 | 'last_import': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}) | ||
187 | 154 | }, | ||
188 | 155 | 'webcatalog.token': { | ||
189 | 156 | 'Meta': {'object_name': 'Token'}, | ||
190 | 157 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}), | ||
191 | 158 | 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
192 | 159 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
193 | 160 | 'token': ('django.db.models.fields.CharField', [], {'default': "'afduSDFNmldZMjYZFoBLOhXEULKLrbmDGPKtuoHEUVLCyheFhY'", 'max_length': '50', 'primary_key': 'True'}), | ||
194 | 161 | 'token_secret': ('django.db.models.fields.CharField', [], {'default': "'obbeyYIEgkoxRBtOlkaXbtfgOGnkWUVIppSANzntzFEMuOytlC'", 'max_length': '50'}), | ||
195 | 162 | 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) | ||
196 | 163 | } | ||
197 | 164 | } | ||
198 | 165 | |||
199 | 166 | complete_apps = ['webcatalog'] | ||
200 | 0 | 167 | ||
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 | 89 | db_index=True, blank=True) | 89 | db_index=True, blank=True) |
206 | 90 | price = models.DecimalField(max_digits=7, decimal_places=2, null=True, | 90 | price = models.DecimalField(max_digits=7, decimal_places=2, null=True, |
207 | 91 | blank=True, help_text="For-purchase applications (in US Dollars).") | 91 | blank=True, help_text="For-purchase applications (in US Dollars).") |
208 | 92 | application_id = models.IntegerField(null=True, blank=True) | ||
209 | 92 | 93 | ||
210 | 93 | ratings_total = models.IntegerField(null=True, blank=True) | 94 | ratings_total = models.IntegerField(null=True, blank=True) |
211 | 94 | ratings_average = models.DecimalField(max_digits=3, decimal_places=2, | 95 | ratings_average = models.DecimalField(max_digits=3, decimal_places=2, |
212 | 95 | 96 | ||
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 | 101 | distroseries=None, arch='i686', ratings_average=None, | 101 | distroseries=None, arch='i686', ratings_average=None, |
218 | 102 | ratings_total=None, ratings_histogram='', screenshot_url='', | 102 | ratings_total=None, ratings_histogram='', screenshot_url='', |
219 | 103 | archive_id=None, version='', is_latest=False, wilson_score=0.0, | 103 | archive_id=None, version='', is_latest=False, wilson_score=0.0, |
221 | 104 | debtags=[]): | 104 | debtags=[], application_id=None): |
222 | 105 | if name is None: | 105 | if name is None: |
223 | 106 | name = self.get_unique_string(prefix='Readable Name') | 106 | name = self.get_unique_string(prefix='Readable Name') |
224 | 107 | if package_name is None: | 107 | if package_name is None: |
225 | @@ -120,7 +120,8 @@ | |||
226 | 120 | ratings_average=ratings_average, ratings_total=ratings_total, | 120 | ratings_average=ratings_average, ratings_total=ratings_total, |
227 | 121 | ratings_histogram=ratings_histogram, | 121 | ratings_histogram=ratings_histogram, |
228 | 122 | archive_id=archive_id, version=version, is_latest=is_latest, | 122 | archive_id=archive_id, version=version, is_latest=is_latest, |
230 | 123 | wilson_score=wilson_score, debtags=debtags) | 123 | wilson_score=wilson_score, debtags=debtags, |
231 | 124 | application_id=application_id) | ||
232 | 124 | 125 | ||
233 | 125 | if screenshot_url: | 126 | if screenshot_url: |
234 | 126 | ApplicationMedia.objects.create( | 127 | ApplicationMedia.objects.create( |
235 | 127 | 128 | ||
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 | 433 | command.process_desktop_file(desktop_file, '', distroseries) | 433 | command.process_desktop_file(desktop_file, '', distroseries) |
241 | 434 | # no breakage! | 434 | # no breakage! |
242 | 435 | 435 | ||
243 | 436 | @patch('urllib.urlopen') | ||
244 | 437 | def test_fetch_icon_from_extras(self, mock_urlopen): | ||
245 | 438 | mock_urlopen.return_value.getcode.return_value = 200 | ||
246 | 439 | mock_urlopen.return_value.read.return_value = "I'm a png!" | ||
247 | 440 | app = self.factory.make_application() | ||
248 | 441 | candidate = Mock() | ||
249 | 442 | candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' | ||
250 | 443 | candidate.record = {'Icon': 'foo.png'} | ||
251 | 444 | command = import_app_install_data.Command() | ||
252 | 445 | |||
253 | 446 | command.fetch_icon_from_extras(app, candidate) | ||
254 | 447 | |||
255 | 448 | self.assertEqual("I'm a png!", app.icon.read()) | ||
256 | 449 | self.assertEqual(1, mock_urlopen.call_count) | ||
257 | 450 | mock_urlopen.assert_called_with( | ||
258 | 451 | 'http://extras.ubuntu.com/meta/foo.png') | ||
259 | 452 | |||
260 | 453 | @patch('urllib.urlopen') | ||
261 | 454 | def test_fetches_nothing_if_no_icon(self, mock_urlopen): | ||
262 | 455 | app = self.factory.make_application() | ||
263 | 456 | candidate = Mock() | ||
264 | 457 | candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' | ||
265 | 458 | candidate.record = {} | ||
266 | 459 | command = import_app_install_data.Command() | ||
267 | 460 | |||
268 | 461 | command.fetch_icon_from_extras(app, candidate) | ||
269 | 462 | |||
270 | 463 | self.assertEqual(0, mock_urlopen.call_count) | ||
271 | 464 | self.assertFalse(app.icon) | ||
272 | 465 | |||
273 | 466 | @patch('urllib.urlopen') | ||
274 | 467 | def test_fetches_nothing_if_not_in_extras(self, mock_urlopen): | ||
275 | 468 | app = self.factory.make_application() | ||
276 | 469 | candidate = Mock() | ||
277 | 470 | candidate.uri = 'http://archive.ubuntu.com/pool/f/foobar.deb' | ||
278 | 471 | candidate.record = {'Icon': 'foobar.png'} | ||
279 | 472 | command = import_app_install_data.Command() | ||
280 | 473 | |||
281 | 474 | command.fetch_icon_from_extras(app, candidate) | ||
282 | 475 | |||
283 | 476 | self.assertEqual(0, mock_urlopen.call_count) | ||
284 | 477 | self.assertFalse(app.icon) | ||
285 | 478 | |||
286 | 436 | 479 | ||
287 | 437 | class ImportForPurchaseAppsTestCase(TestCaseWithFactory): | 480 | class ImportForPurchaseAppsTestCase(TestCaseWithFactory): |
288 | 438 | 481 | ||
289 | 439 | def setUp(self): | 482 | def setUp(self): |
290 | 440 | super(ImportForPurchaseAppsTestCase, self).setUp() | 483 | super(ImportForPurchaseAppsTestCase, self).setUp() |
291 | 441 | curdir = os.path.dirname(__file__) | ||
292 | 442 | sca_apps_file = os.path.join(curdir, 'test_data', 'sca_apps.txt') | ||
293 | 443 | self.natty = self.factory.make_distroseries( | 484 | self.natty = self.factory.make_distroseries( |
294 | 444 | code_name='natty', version='11.04') | 485 | code_name='natty', version='11.04') |
295 | 445 | self.maverick = self.factory.make_distroseries( | 486 | self.maverick = self.factory.make_distroseries( |
296 | 446 | code_name='maverick', version='10.10') | 487 | code_name='maverick', version='10.10') |
297 | 447 | with open(sca_apps_file) as content: | ||
298 | 448 | self.response_content = content.read() | ||
299 | 449 | mock_response = Mock() | ||
300 | 450 | mock_response.code = 200 | ||
301 | 451 | mock_response.read.return_value = self.response_content | ||
302 | 452 | 488 | ||
303 | 453 | self.patch_urlopen = patch('urllib.urlopen') | 489 | self.patch_urlopen = patch('urllib.urlopen') |
306 | 454 | mock_urllib = self.patch_urlopen.start() | 490 | self.mock_urlopen = self.patch_urlopen.start() |
307 | 455 | mock_urllib.return_value = mock_response | 491 | |
308 | 492 | def mock_urlopen_fn(url): | ||
309 | 493 | """Return predetermined test_data content for given urls.""" | ||
310 | 494 | available_apps_url = '%sapplications/any/ubuntu/any/any/' % ( | ||
311 | 495 | settings.SCA_API_URL) | ||
312 | 496 | icon_arb_url = ('http://sc.staging.ubuntu.com/' | ||
313 | 497 | 'site_media/appmedia/2012/04/ktip.png') | ||
314 | 498 | icon_hello_url = ('http://localhost:8000/' | ||
315 | 499 | 'site_media/icons/2011/06/eg_64x64.png') | ||
316 | 500 | filenames = { | ||
317 | 501 | available_apps_url: 'sca_apps.txt', | ||
318 | 502 | icon_arb_url: 'ubuntu-cof.png', | ||
319 | 503 | icon_hello_url: 'ubuntu-cof.png', | ||
320 | 504 | } | ||
321 | 505 | curdir = os.path.dirname(__file__) | ||
322 | 506 | sca_apps_file = os.path.join(curdir, 'test_data', | ||
323 | 507 | filenames[url]) | ||
324 | 508 | with open(sca_apps_file) as content: | ||
325 | 509 | self.response_content = content.read() | ||
326 | 510 | mock_response = Mock() | ||
327 | 511 | mock_response.code = 200 | ||
328 | 512 | mock_response.read.return_value = self.response_content | ||
329 | 513 | return mock_response | ||
330 | 514 | |||
331 | 515 | self.mock_urlopen.side_effect = mock_urlopen_fn | ||
332 | 456 | self.addCleanup(self.patch_urlopen.stop) | 516 | self.addCleanup(self.patch_urlopen.stop) |
333 | 457 | 517 | ||
334 | 458 | def test_app_for_purchase_is_found(self): | 518 | def test_app_for_purchase_is_found(self): |
335 | @@ -486,21 +546,30 @@ | |||
336 | 486 | self.factory.make_application(archive_id='launchpad_zematynnad2/myppa', | 546 | self.factory.make_application(archive_id='launchpad_zematynnad2/myppa', |
337 | 487 | package_name='somethingelse', | 547 | package_name='somethingelse', |
338 | 488 | distroseries=self.natty) | 548 | distroseries=self.natty) |
340 | 489 | self.assertEqual(2, Application.objects.count()) | 549 | self.assertEqual(2, |
341 | 550 | Application.objects.filter( | ||
342 | 551 | distroseries__in=(self.natty, self.maverick)).count()) | ||
343 | 490 | 552 | ||
344 | 491 | call_command('import_for_purchase_apps') | 553 | call_command('import_for_purchase_apps') |
345 | 492 | 554 | ||
348 | 493 | self.assertEqual(2, Application.objects.count()) | 555 | actual_apps = Application.objects.filter( |
349 | 494 | for app in Application.objects.all(): | 556 | distroseries__in=(self.natty, self.maverick)) |
350 | 557 | self.assertEqual(2, actual_apps.count()) | ||
351 | 558 | for app in actual_apps: | ||
352 | 495 | self.assertEqual('launchpad_zematynnad2/myppa', app.archive_id) | 559 | self.assertEqual('launchpad_zematynnad2/myppa', app.archive_id) |
353 | 496 | self.assertEqual('hello', app.package_name) | 560 | self.assertEqual('hello', app.package_name) |
354 | 497 | 561 | ||
355 | 498 | def test_app_gets_icon(self): | 562 | def test_app_gets_icon(self): |
356 | 499 | call_command('import_for_purchase_apps') | 563 | call_command('import_for_purchase_apps') |
357 | 500 | 564 | ||
358 | 565 | self.mock_urlopen.assert_called_with( | ||
359 | 566 | 'http://sc.staging.ubuntu.com/' | ||
360 | 567 | 'site_media/appmedia/2012/04/ktip.png') | ||
361 | 501 | app = Application.objects.get(name='MyApp', | 568 | app = Application.objects.get(name='MyApp', |
362 | 502 | distroseries=self.natty) | 569 | distroseries=self.natty) |
364 | 503 | self.assertEqual(6461, app.icon.size) | 570 | # The urlopen double returns the test_data/ubuntu-cof.png which has |
365 | 571 | # a size of 2438. | ||
366 | 572 | self.assertEqual(2438, app.icon.size) | ||
367 | 504 | 573 | ||
368 | 505 | def test_app_gets_version(self): | 574 | def test_app_gets_version(self): |
369 | 506 | call_command('import_for_purchase_apps') | 575 | call_command('import_for_purchase_apps') |
370 | @@ -524,48 +593,23 @@ | |||
371 | 524 | qs = app.applicationmedia_set.filter(media_type='screenshot') | 593 | qs = app.applicationmedia_set.filter(media_type='screenshot') |
372 | 525 | self.assertEqual(2, qs.count()) | 594 | self.assertEqual(2, qs.count()) |
373 | 526 | 595 | ||
416 | 527 | @patch('urllib.urlopen') | 596 | def test_import_arb_app(self): |
417 | 528 | def test_fetch_icon_from_extras(self, mock_urlopen): | 597 | call_command('import_for_purchase_apps') |
418 | 529 | mock_urlopen.return_value.getcode.return_value = 200 | 598 | |
419 | 530 | mock_urlopen.return_value.read.return_value = "I'm a png!" | 599 | arb_apps = Application.objects.filter(package_name='eg_arb_app') |
420 | 531 | app = self.factory.make_application() | 600 | self.assertEqual(2, arb_apps.count()) |
421 | 532 | candidate = Mock() | 601 | self.assertEqual('', arb_apps[0].archive_id) |
422 | 533 | candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' | 602 | self.assertEqual('', arb_apps[1].archive_id) |
423 | 534 | candidate.record = {'Icon': 'foo.png'} | 603 | |
424 | 535 | command = import_app_install_data.Command() | 604 | def test_import_arb_app_handle_existing_none_archive_id(self): |
425 | 536 | 605 | precise = self.factory.make_distroseries(code_name='precise') | |
426 | 537 | command.fetch_icon_from_extras(app, candidate) | 606 | self.factory.make_application(archive_id=None, distroseries=precise) |
427 | 538 | 607 | self.factory.make_application(archive_id=None, distroseries=precise) | |
428 | 539 | self.assertEqual("I'm a png!", app.icon.read()) | 608 | |
429 | 540 | self.assertEqual(1, mock_urlopen.call_count) | 609 | call_command('import_for_purchase_apps') |
430 | 541 | mock_urlopen.assert_called_with( | 610 | |
431 | 542 | 'http://extras.ubuntu.com/meta/foo.png') | 611 | arb_apps = Application.objects.filter(package_name='eg_arb_app') |
432 | 543 | 612 | self.assertEqual(2, arb_apps.count()) | |
391 | 544 | @patch('urllib.urlopen') | ||
392 | 545 | def test_fetches_nothing_if_no_icon(self, mock_urlopen): | ||
393 | 546 | app = self.factory.make_application() | ||
394 | 547 | candidate = Mock() | ||
395 | 548 | candidate.uri = 'http://extras.ubuntu.com/pool/f/foobar.deb' | ||
396 | 549 | candidate.record = {} | ||
397 | 550 | command = import_app_install_data.Command() | ||
398 | 551 | |||
399 | 552 | command.fetch_icon_from_extras(app, candidate) | ||
400 | 553 | |||
401 | 554 | self.assertEqual(0, mock_urlopen.call_count) | ||
402 | 555 | self.assertFalse(app.icon) | ||
403 | 556 | |||
404 | 557 | @patch('urllib.urlopen') | ||
405 | 558 | def test_fetches_nothing_if_not_in_extras(self, mock_urlopen): | ||
406 | 559 | app = self.factory.make_application() | ||
407 | 560 | candidate = Mock() | ||
408 | 561 | candidate.uri = 'http://archive.ubuntu.com/pool/f/foobar.deb' | ||
409 | 562 | candidate.record = {'Icon': 'foobar.png'} | ||
410 | 563 | command = import_app_install_data.Command() | ||
411 | 564 | |||
412 | 565 | command.fetch_icon_from_extras(app, candidate) | ||
413 | 566 | |||
414 | 567 | self.assertEqual(0, mock_urlopen.call_count) | ||
415 | 568 | self.assertFalse(app.icon) | ||
433 | 569 | 613 | ||
434 | 570 | 614 | ||
435 | 571 | class ImportRatingsTestCase(TestCaseWithFactory): | 615 | class ImportRatingsTestCase(TestCaseWithFactory): |
436 | 572 | 616 | ||
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 | 1 | [ | 1 | [ |
442 | 2 | { | 2 | { |
443 | 3 | "id": 18, | ||
444 | 3 | "status": "Published", | 4 | "status": "Published", |
445 | 4 | "signing_key_id": "", | 5 | "signing_key_id": "", |
446 | 5 | "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).", | 6 | "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 | 8 | "series": {"maverick": ["i386", "amd64"], "natty": ["i386", "amd64"]}, | 9 | "series": {"maverick": ["i386", "amd64"], "natty": ["i386", "amd64"]}, |
449 | 9 | "price": "2.50", | 10 | "price": "2.50", |
450 | 10 | "archive_id": "launchpad_zematynnad2/myppa", | 11 | "archive_id": "launchpad_zematynnad2/myppa", |
451 | 11 | "icon_data": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAACXBIWXMAAAsSAAALEgHS3X78AAAFMnpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarVRLciU5DtvnKeoI4J88DvVhRN9gjj+LZ7vssrsjZqKlRaYgCaQISM/9z1/z/Pr16xdZyqMW6eUOAHr0ANx4tQQQIAwAfsNU01QFABE+4et5fZ1B1ADsbYLe8Aui9R0PB3ECkHf8+WBlks8T75syvADoH0T3NVJ+Zch4VN1CvIL9PSoAza8bv4w7k+NrUNcHAOotzDuLQFhYUK/Fb3Wgt6xm1yvDL/gDIhSBPhOBwBCgvwcggaBfmX0pwwMA/WL/ow6Kfi3+Cbc/8QfE7wCE32K2QEJaIMYQEpEWFpcWCP+87vlp4dv56bN/jKUkP+a+Hff5rRQchD8t4K+/HzxGhc8eez5N5J8m++0x0LdaUQP8u7a/iTQLX9rfe2nm5MwFQNBW11J/EdFXN8+cBagASDgcAYchEQgECoVEY5PiYGNhYT9UxCQYUjrUNHTpUNOmzWDly8Fg5s1CmzanBBdvgZCoqCgNh5ScR1JYNl8RUeGPXAiFQmFjYVPi4FAKM9FmEv7en5/A/6d/EM3s1yOTLxkUEBAzACYCQYhAM1sBmreaGui9P++afGqvm6YwOAKJQmO9KJbRux0EAoZCYDDo8+YOivN+VaFEMGImISU4iZETgjmIVDipqAnJorxoE5nxoWfAKuIcnIxCk1NQUlGz8QsublExcQlJKWkVVTV1DU0tbRPTx8zcwtLK2sXVzd3D08s7JDQsPCIyKjolNS09IzMru7iktKy84qmsqm5uaW1r7+js6l68ZOmy5StWrlq9ecvWbdt37Ny1+/CRo8eOn3hOnjp96fKVq9eu37h56/bQ8Mjo2PjE5NT0h2qvh42+qkZ/KPfPqtGbagyFQqCI36oROOKdgggKYxKCEysZIZyCSJiFk5CkykVNizahWESMnwGZc/AhNDmr6CW2oQ/tfiv3j7o9pv+Tbvx3yj3lFf+Gcs/xE2/KfdftB9VOA9iQ1/tJrzsImQe4wcdEYs/ciz57hVHugWK0dy/Wfe6KWckr7nE6a5dUHyvWRdtzpz53I+huqY5WIsGuvAKRDQb1QtFQ7iDj3lor/FIgaqOLSuluZ6ndD4fM3ei2ECe/hLnX4jYvu0bXkgEOOXBvlEH6IlsRcsRr+d5rbq+nxl2szHvlCqe5p/rW9dyghGTf8HNiDuUMsK53M7unJc+0S8xqXk9zUiRZSkfOaPsMEGo+WzV32GyuvYKabwNwHcjxtuG9uBc2sax5+gjLVN7NwM57g6qPH77b7lyLFbmB3W1JLpu2ae7t5YLbuCJnm6k/55zwpHuqD60yRkGkaDvMKHbeFtLEnpU0XH2DQblsJon6ll9pmn4sZFFu67jstSNI+Hjlpb615hyyw8pNiwoyRLbdcySmXUJOWnj4jSdJz73IQ6lxw5zYqrkkVK8JI3nLcu+1NUhHwy1kVbrQxh1NZ9urnqCSLUQnpo+HdobstWh299UbQZSS3Tn7MDhtY7PEQt84MVeODImdB3aCSGZW+6rRGSBHbbrmhhmdrXv3Ybdtd8WBRZgXu1HcsuvToXc9dM7y65Ck42vtI34dkUoijBkgybCJ1qE1pJe1CvS6EGX73BWXfT1xcIiqOWpLhDpZL7cutSgn2E4m6KIM9FZXV4/q0iMn26vPXiazn91KwSJno5PywkWq80YdXGSZxmx0JUdGR3Ui1jpCZHdoTRDTDPC4zgDcm3LV4pxb1hNH1Ma9wnen3i1JK6PNRTnEjWLWMiO2mjn1/BfOqvbjWmnkpgAAAAl2cEFnAAAAQAAAAEAA6vP4YAAAEvFJREFUaN6FWsty5FaOxeuSTEoqleRy+dURdkRvOjpifmEW/Q2zmk+Yb+39REXHLLrttqvHUpVemXzcC2AWIG9SKdnDhSKrkknicQAcABf/4z//iwie7h+G8alr2q+/eU8ERMTMiNi2rZm1iYmIEQHAEQEAwInIXUsp7khEZqaqzGxmqllE1HIpxZHdHRTMzB3MzNXcvZSMiMWymSm4mbmjqqKBqiKiqqoWdzdzVS1mwzBcX79/9+6d2vK0nLMAAD6/iJCIQgcAaNtWCEQEHRCBU0JEIkpJUkrurqoAME2Tqp6fn8NyGQCwYDEopYBCKYVZSimulvNsZqWUuUwAkE2nacpZzcyyxldmBgDu7u6IyMwAZGZmBkDxDkQURKw60HJx/EUkdzczB3Z3YSEid2IhAFA1RI0XENHFxRt3n6YpJUFEd08pTdPkjmUqAJBzFhIwB3Az6/teEjlAKaU4uPs0zsMwEEDTNKtLyzzPT4ehlHJz84loNHcHQEQANHAD2HqAtn4opaSUmAkAiAiciMSsEDMCIyKghbqhgBuWom5o5qXklORwGEXIHcKTACAiAUBiALRpysTMzGY+z7OZdV2nOYtIzllV3U1E+r4novv7x0B1iBoeRkRhQAZEAAJkRIbjy5qmAUQiUkBJgkSEiTkxh6pCyG5eipqV3e4MwA6H8fLy4uL8LJep6zozc/emadDR3RHBjN09NYyIpcxz1sPhYEjCyaAMh4ERpGkMgFMyV1V191LKFiPuISMhwisxAAiImFISEXMXkZKzSDNPIyISyePjvpS567qLi4uUkqoOw3Bz86lt2+vr6wges6Sqi72J0BEAVAsAABoC5jyZWdM0IjLOmnMmoqurq2k4MHPOGSAiNbJFRHkIfgyAZzGwBgABASLmYrmMu90OkbuOETFndfeU2qZpzs/7lJKZTdMkIpeXl1dXX4SLSymqamYRKmCGgIhoZkQUGQYAun43z7MblFIQqWmaw+Hh4e7+6uoS0B2MJZkTAACH95CIcMmBgIjgAPAbHiAiQNrv9ymlYRi+uH4bACWicRxVs/tORMLYRJRzPhwOqioi5+d9zlktPz4NV1dXxFxFZyZVjc+qZmZMiZlNwd3bdte2LYDVxFAlil8hIiLD5nL3JWOEZouiTO6eWPpuFwiOkBinw/n5OTOmdMHMgEaESD7nMZKgiCA6MzMzoCDizc2vF2cX8T8hgbuLpMi8KaU8KzOre16uCcCIMZBZFaipIgBp5kSk6kQiVZvqnSWNm+12O2lSJAQA6LqubVMpiOSAVu9vmqZpGvDFv8QAAKVo3++6rkXHjx8/vnnzpm3bMMf93cOubwEIyYl8KRcFLy8vAC7mPFSD5pzdPYrBc6TAGgz+DEJLFQAExP3wJFl87wDQXr5tWJx0mqYkggCERIThRQSoxSMKLRExEgEyS87lm2++eXx8rOF+/e7d/f0dEdS0yOp5mlIydxck8+IRvm4ATky0Qj0e6wiIyIAWEKrhG44OsJ2fn+92u3hHIi5ljsSqZSbiuCdQF+5StbZtw8VEJMIBcxEGwL7vw6Jd103TdHHxZppGAFtRgbtdFzTEXVV5m3bMgAgBDBGJA0Lhf1uKVw0XIkL0qpKq5jwhekosIoRomkPJKjozi0gENACk1MbPa/0n4bnMnOTj//5r158X9ZLt5uZmnvM0ZTdzMy3zrmsInQkiYPA5XNydABiO/7N+MNrGdP2aiJqmadu267qoo0hOdMy223QWn4P2EZE7iojZguNI9gDw7t27aZrGcby9vSUUZmaWJnUisoamBbOK4rUNzhXiXv8e68BJDCxqEZAbmjIJmDsWJEEAJFg1ZEQECBcv9YVoESVoiLupKiCIyDTNIU3X9USS89Q0Tc7ZzIoWMytlTkyOAOZ4rFzhSXhudUAHinKISACAyPjiEpEwQ40ND8zR4rTqCmZumma/3wcHdve7u7vqSSKapqnWuMfHexF58+ZNxQZT6rounhxcdVN04QRL1fO+pkwBIHc3d0dwRAXvRADNQVmYCUJgd2cOEC7uLsVSapgXint+3oeeZnYYh0tTACBmUGukMTN02PUtoGnJcz6ICDMDgqqCAZG4O3Nyd1B1d3MjXJOou7r7Gl1ACAqIaAi09Q4iIvrL2ry9wrm8sEhzdxGpFprnGQC+++67nHOImFIKxYLhDMOgllNKUdcjUyEiUwp/bmMsMsFJ4NZ/Gr5GJX5f+mNOII7Xh2SqWkpZKhqAmd7f30d20nwkkk3TXF5ehubzPFegupqqOliwkgqV9e+pJutXHoz0WQQH2XgJu/rLQHM8cYEBACI+PDxEDxWs6euvvw4cB9+sdSY0PBwOu90uQB/NV+Ak+tJ4zjNjm52ERM1RC5WIfiACFBFx7QoQOWj3+vOFjcT7mDmkbNv26uoqHp1SOhwOZ2dn8zw/PDxcXb6NICEiWwGz2+3u7u5KKWYa9dXdHbQSnpcXAfAJkXBwB3kVXlt2FM56jh8CQF+vMG3XdSIyTVNYvZTStm3f93maRaTauD4zeFFKEt12KcW8IOI8z3Fn5ZuvoXqjWETt0cKVxAJXfhZ+WO8hAKzUMoj+fr+fpjyOc43vIJuqut/va3tOgI2kyFQXFxdt26KD5lKbhFJKhejW/L8p/iqWPSsTvxvKFWbxppDm4eHhcDgsZEl1S8KPYBVZQta9aZpQNfq+QHkE1dbq25J/os8zBapMLyHIImoWDzOIWgGOANEkEqobklx/8eWby8thHIEQmYQYHRpJYB5NZmCjKrCk9rWvqTJtYbYF0sreoNKwY3fxasTUu3POcd80Tbu+jVrb9/00TRGvAKDFf/7557OzMyLa9W3f95pLZNVIl3UqUUqJh4dAS04AiCjfomZLdV9iKRLoOhdywNdwts24qjpNU5jqzeW5mQk3bp5nNbOU0h//+MdgyymlnPOu7dq2HceRiNq23e/3kUl/+umnr7766vC0DxS5ubrV+Ia1hr7IP0HB8FU4SZXyRNsoT2FFADg7OwvIzvOIiEnaMGSEbLT2EQ/xP7vdLmATHhuGAQC++uqrGD0cDoeYCaguEwBbKeGJDjUHvhR9yYHbWxmRvOpzxGJkcQBQ1a7tD/sxcvzj42Ow6MPhUEq5vb2N+x8fH9+/f991XTyqFl0RCdwPw/D58+eHh4dhGAJXJyz9VVS/6gTZKPqMslbzVw5DRMMwvH37NlARaX6e567rdrtd/Pb29tbM/vDtd09PT3/5y79/+PA/Hz58iHxa6cYvv/zS933TNNHvVlua28uKW8NgM6R4li3pZaDUH0THG2Q7pbTb7S4uLkRkt9v1fR+WizHg2dlZCHd5efnu3TsA+Pbbb93h+++/X+fMGpU75/z+/fu+79u2TSltk94yTjZHh99JLScAO8lCBmAAC70ppbTtrpL+qDIiElZ394eHB0mUpH16eoqnjsP89uoNkQzDQATDMKSUAu41Zmy9TmxnCub6avJZUU8A4IbuDk5BsWX7A0MwBAZwULOlLQYA5vT0tMytuq4H0JJzEmrSLiVhlpInoeTu/W7nCuM8//Ofv1xdv/v73//x9u21qk9TdvdgijEhXwkVRF1XVTMHoFyyiIBqzDvM1BFsjeM6GipeENldj5XlpHYE+0Vc5moBnvADERAjkURzw7RUQFVN0hLS0+FhGvPf/va3T58+jcPw5ZdfjuMY8+coLCmlWIJEcYjwiJTlblubHiMh8s3qhLUKk2yFPkYP8OpiD/hGEVVV1RwTVSKq3WoUgYB4KWW323369On+8e729var9+9vbm66rpvnmYhEJCX+8ccfa4KKsW7TNCmltm2naazT3C2DfDUMEHHhiWYGYODkfvwubB92isEfMzeNbMcq9Wrbdpqm1HQ559vb26Zpmi5FrJdSanOMiI+Pj8zc931U6EBp7QRiuBRWq6Tod9hxJOYYFfmxKK6lwF15Wcx42Gmbrbc6RFIqOjvom8tzd+92OyKaxrGWgspN3r17F+JuV0kAHtPfbYj/FqVbNzVIVehtMIRAdepWB1iLAdBOSmaoV1eD4zje3NxEhSaiz58/55yDjEQARNtQqVvFzDZBbYWuMm4DNT5I/Q3iM03qvPHYgoCaGzsgIFIwKoQoRYhZS8jR933XdV988UXOU9tIznp2dpYSI7pZaRoZxzFauUBB0DhEoE353/Y9sdt8tQ4AAFVOW1EYf7dW2a4Kj1uE2toRMUt4qe5U6uoyxtpRVYjo7u4u2Ee1/W/VqS2Yn1ff+LyOQyO3lFJilh3RExF8ZBZosPHPiR+DhlW/1QcG/wMwdw3oj+N4cXGxalhUC7gz0UJjXpC52qgcezqiysYXLlRKYUHVHNvPkxq5pXTPDfNsylKlD38SUQB9O/mJe4ZhCG+IsLvD88B72Uy6O6y/DVKznakAAJmXegV+KmCOAWEITvD/XR8/fhwO02E//vrrr1vLVYoWWUi1xGgQn3vyZWZ7nU88r1oRxCVCwEG3oH/RBy32OHFOfWiQ0wCPu+/3h4iZ7VuZWYSJSEv5HflOXLFtNdcavBolpK+hXD+4YyxfquOeN6wAgO7gvuxoELhr+8+fPz89PfV9H+cmItsEkJasV3Px5oGrZFYt9rK3rG48gXflQqaWtxXx9115UiYjKkopP/zwAyKal5wzEUT9quZcpxh6AptNS2iIFHTo5F0x232l4TwpH2bFf/uCF6itqVZEIoqCdLRtW6eCla0wE4ATIp1SGt+Y/5WO/gTSzwZZgf71Nbr1wFbEI+UGNzjRQd19moeu66Ypl2L3d/tPt3fbyddKb6CUonbiui1X45eeWeknOTIi1Qpw9EB9SpjQ0BR01llB1xbn+CwDcERHcHewBRsGCuRzySk1WuD67bs8hRXCOlrHOMwyjvPj0z4XRWKMPStQbf22WjmCusV4IduyNi4r+UN0d5UtDGoQl1JS8pVi4Do69udTHXJQcHJ0N2cWImia5ud/fgTD/qIdhklk4TmRpqODzaW4e85D13VE6O64Wifq90v0H+GwEI5NU/8S6JtEdPoEd0czpGBC5kTgBstBDk3M0zReX10iCZIjFSCPAh+7TDOYpmm/H8bxcHV9iUw1DW9SzWndPCGnJ8EgJ4TnWLuWs1FwwlPRAcyd4KQIMNI4jmB4e3vbtLu3b9/uD2NKTAillHGcVJU5icj19TXAWwAQYY/R4vMkcVITTmjyyT1RyNB++6prJSR0NUdAIkc0c0cjpCDXxJiYml2n+kZSy4k4JyJiMkRgFncHZAByKPVER5B23NQE3274HNCXfd5yw3PWtHhgC7htJGzdspbh1QDujkCOZkZwPNdANN/e/ipNe3V9zSwiyW2sOcMcowgQsXtZBoqIhFjWwry+biPV8zR6UoLk5LsXDoCIM3d3I0NEdARAR3c0AyHwZThlDcucp2++/ZpYhmFqu26aBuFFADNTW/RERCIgXjPbmsu288UKk1eLQNXh2BP/PoriMjNERkB3QANEMI+wcEJUVRZW1dhDmhWipVd8ufrNeU6QVqoX8HiFigZVWQjlazFAJ02tqkabWmn9NpgQUcENl/0kqK25D0spTugGSZqobgjmVmJfX5v62LoGp9jv9/WQQQzw4qRC8CZEVHcDZ+bYO8UQoNp+2YmUUpgpTtUFW6yMaNuyhJdmLYyNqRK6zlMS0VKEWFUZ2cww9KFYu88ArmoppVL0cDiY86+//np5eXl7e8uMzFwS1+1BTGWQYgNd6rTCrcQC/CWZcHepRyfdPchwfFH547ohF0SPtT0LUiktE5RMgODoABmLF+/7c3AHcyuqJafEQDSOIxGHk+PQWt/3Z2c7M1PLxRQBiViEASBrDCFhPTRiJW+sCeBAABpzRI+xSmwIo6uM8VPYu5SiorV5JQJgAiQhaJImyKAwF0Du3QEbBgQ1czMwR3RmLKUgyToVFCK9urra7/fh8FJKifM7gGZW7Li6XTPsEjmzVop5yvMk9uBxGiDGPrF/bttdREKs7kQEwJCZpfH8ZOXhl5//oZP/9NOn5vzroYC19Od/+/MykUdyB2IpNoEqEWVVcyeiDx8+xA58HEdVTU1aTp/EqcAk81zcEIkAMbb2lJbBVC0Iy9y01oHaUtbxRFDiekpypWJAwUVQIe+H+3/968ebv/71v+/z+c1+PvvizR9++P7sbGeaiZucM6hFslZVcBKh/X7405/+tN/vz87ODoen41kWpNghuDsCqxWgZf1sCgo4z7O9SEHHJV/dHYTcsSwKBWIgFSERq0pRZZt0+NRS5vJ03nKhxuR8RmSWeR5tnkGCNppBwAnjEGPf97e3t7Eo2e2WleF2WlNKAUrIFG0JApvlrPZyPHqEUEz9I97v7+/HcRSRruvadtd13VPbxbGNiq4ktKOh99t5emDUkqcy5zFD6vq7u7uShd01f0JkR1M3jFkLxB6tiflKzvnTJ0VEtRwL8DopmfNysD/gkHOWtgssnYzr4vo/GUpMfYuAF0sAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTAtMTAtMjBUMTM6MDM6NDYrMDA6MDDnSvk1AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDEwLTEwLTIwVDEzOjAzOjQ2KzAwOjAwlhdBiQAAABF0RVh0anBlZzpjb2xvcnNwYWNlADIsdVWfAAAAIHRFWHRqcGVnOnNhbXBsaW5nLWZhY3RvcgAyeDIsMXgxLDF4MUn6prQAAAAASUVORK5CYII=", | ||
452 | 12 | "screenshot_url": "", | 12 | "screenshot_url": "", |
453 | 13 | "screenshot_urls": [ | 13 | "screenshot_urls": [ |
454 | 14 | "http://localhost:8000/screenshot_1.png", | 14 | "http://localhost:8000/screenshot_1.png", |
455 | @@ -19,5 +19,47 @@ | |||
456 | 19 | "icon_url": "http://localhost:8000/site_media/icons/2011/06/eg_64x64.png", | 19 | "icon_url": "http://localhost:8000/site_media/icons/2011/06/eg_64x64.png", |
457 | 20 | "categories": "Audio", | 20 | "categories": "Audio", |
458 | 21 | "name": "MyApp" | 21 | "name": "MyApp" |
459 | 22 | }, | ||
460 | 23 | { | ||
461 | 24 | "package_name": "eg_arb_app", | ||
462 | 25 | "video_embedded_html_urls": [], | ||
463 | 26 | "series": { | ||
464 | 27 | "precise": [ | ||
465 | 28 | "amd64", | ||
466 | 29 | "i386" | ||
467 | 30 | ], | ||
468 | 31 | "oneiric": [ | ||
469 | 32 | "i386", | ||
470 | 33 | "amd64" | ||
471 | 34 | ] | ||
472 | 35 | }, | ||
473 | 36 | "video_urls": [], | ||
474 | 37 | "screenshot_url": "http://sc.staging.ubuntu.com/site_media/appmedia/2012/04/IMG_20120401_144332.jpg", | ||
475 | 38 | "id": 595, | ||
476 | 39 | "archive_id": null, | ||
477 | 40 | "support_url": "http://example.com/foo", | ||
478 | 41 | "icon_url": "http://sc.staging.ubuntu.com/site_media/appmedia/2012/04/ktip.png", | ||
479 | 42 | "version": "1.2", | ||
480 | 43 | "demo": null, | ||
481 | 44 | "department": [ | ||
482 | 45 | "Accessories" | ||
483 | 46 | ], | ||
484 | 47 | "tos_url": "", | ||
485 | 48 | "channel": "Independent", | ||
486 | 49 | "status": "Published", | ||
487 | 50 | "signing_key_id": "", | ||
488 | 51 | "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 | 52 | "price": "0.00", | ||
490 | 53 | "debtags": [ | ||
491 | 54 | "hardware::input:mouse" | ||
492 | 55 | ], | ||
493 | 56 | "date_published": "2012-04-30 19:34:08.011454", | ||
494 | 57 | "categories": "Utility", | ||
495 | 58 | "name": "ARB test", | ||
496 | 59 | "license": "GNU GPL v3", | ||
497 | 60 | "screenshot_urls": [ | ||
498 | 61 | "http://sc.staging.ubuntu.com/site_media/appmedia/2012/04/IMG_20120401_144332.jpg" | ||
499 | 62 | ], | ||
500 | 63 | "archive_root": "http://extras.ubuntu.com/" | ||
501 | 22 | } | 64 | } |
502 | 23 | ] | 65 | ] |
503 | 24 | 66 | ||
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 | 203 | app.distroseries) | 203 | app.distroseries) |
509 | 204 | self.assertTrue(form.is_valid()) | 204 | self.assertTrue(form.is_valid()) |
510 | 205 | form.save_media_urls() | 205 | form.save_media_urls() |
511 | 206 | |||
512 | 206 | self.assertEqual(3, app.applicationmedia_set.count()) | 207 | self.assertEqual(3, app.applicationmedia_set.count()) |
513 | 207 | actual_urls = [media.url for media in app.applicationmedia_set.all()] | 208 | actual_urls = [media.url for media in app.applicationmedia_set.all()] |
514 | 208 | self.assertEqual([ | 209 | self.assertEqual([ |
515 | @@ -211,6 +212,69 @@ | |||
516 | 211 | 'http://example.com/video1.mp4', | 212 | 'http://example.com/video1.mp4', |
517 | 212 | ], actual_urls) | 213 | ], actual_urls) |
518 | 213 | 214 | ||
519 | 215 | def make_valid_data(self, **kwargs): | ||
520 | 216 | data = { | ||
521 | 217 | u'status': u'Published', | ||
522 | 218 | u'signing_key_id': u'', | ||
523 | 219 | u'description': u'This is a description.', | ||
524 | 220 | u'package_name': self.factory.get_unique_string(prefix='pkg'), | ||
525 | 221 | u'video_embedded_html_urls': [], | ||
526 | 222 | u'series': { | ||
527 | 223 | u'precise': [u'amd64', u'i386'], | ||
528 | 224 | u'oneiric': [u'i386', u'amd64'] | ||
529 | 225 | }, | ||
530 | 226 | u'price': u'0.00', | ||
531 | 227 | u'debtags': '["mouse"]', | ||
532 | 228 | u'date_published': u'2012-04-30 19:34:08.011454', | ||
533 | 229 | u'video_urls': [], | ||
534 | 230 | u'screenshot_url': u'http://sc.staging.ubuntu.com/' | ||
535 | 231 | 'site_media/appmedia/2012/04/' | ||
536 | 232 | 'IMG_20120401_144332.jpg', | ||
537 | 233 | u'id': 595, | ||
538 | 234 | u'categories': u'Utility', | ||
539 | 235 | u'archive_id': self.factory.get_unique_string(prefix='archid/'), | ||
540 | 236 | u'name': u'Test App', | ||
541 | 237 | u'license': u'GNU GPL v3', | ||
542 | 238 | u'support_url': u'http://example.com/foo', | ||
543 | 239 | u'icon_url': u'http://sc.staging.ubuntu.com/' | ||
544 | 240 | 'site_media/appmedia/2012/04/ktip.png', | ||
545 | 241 | u'comment': u'This is a test app', | ||
546 | 242 | u'version': u'1.2', | ||
547 | 243 | u'screenshot_urls': [ | ||
548 | 244 | u'http://sc.staging.ubuntu.com/' | ||
549 | 245 | 'site_media/appmedia/2012/04/IMG_20120401_144332.jpg', | ||
550 | 246 | ], | ||
551 | 247 | u'demo': None, | ||
552 | 248 | u'department': [u'Accessories'], | ||
553 | 249 | u'archive_root': u'http://extras.ubuntu.com/', | ||
554 | 250 | u'tos_url': u'', | ||
555 | 251 | u'channel': u'Independent', | ||
556 | 252 | } | ||
557 | 253 | data.update(**kwargs) | ||
558 | 254 | return data | ||
559 | 255 | |||
560 | 256 | def test_archive_id_none_uses_application_id(self): | ||
561 | 257 | precise = self.factory.make_distroseries(code_name='precise') | ||
562 | 258 | existing_app = self.factory.make_application( | ||
563 | 259 | archive_id=None, application_id=21, distroseries=precise) | ||
564 | 260 | |||
565 | 261 | data = self.make_valid_data(archive_id=None, id=21) | ||
566 | 262 | form = ForPurchaseApplicationForm.from_api_data(data, precise) | ||
567 | 263 | |||
568 | 264 | self.assertEqual(existing_app, form.instance) | ||
569 | 265 | |||
570 | 266 | def test_updates_application_id(self): | ||
571 | 267 | precise = self.factory.make_distroseries(code_name='precise') | ||
572 | 268 | existing_app = self.factory.make_application( | ||
573 | 269 | archive_id='foo/bar', application_id=None, distroseries=precise) | ||
574 | 270 | |||
575 | 271 | data = self.make_valid_data(archive_id='foo/bar', id=21) | ||
576 | 272 | form = ForPurchaseApplicationForm.from_api_data(data, precise) | ||
577 | 273 | form.save() | ||
578 | 274 | |||
579 | 275 | app_reloaded = Application.objects.get(id=existing_app.id) | ||
580 | 276 | self.assertEqual(21, app_reloaded.application_id) | ||
581 | 277 | |||
582 | 214 | 278 | ||
583 | 215 | class MultiURLFieldTestCase(TestCase): | 279 | class MultiURLFieldTestCase(TestCase): |
584 | 216 | 280 |
LGTM