Merge lp:~michael.nelson/ubuntu-webcatalog/953306-display-app-version into lp:ubuntu-webcatalog

Proposed by Michael Nelson
Status: Merged
Approved by: Anthony Lenton
Approved revision: 82
Merged at revision: 78
Proposed branch: lp:~michael.nelson/ubuntu-webcatalog/953306-display-app-version
Merge into: lp:ubuntu-webcatalog
Diff against target: 448 lines (+237/-43)
9 files modified
src/webcatalog/forms.py (+5/-0)
src/webcatalog/management/commands/import_app_install_data.py (+3/-0)
src/webcatalog/migrations/0010_add_app_version.py (+154/-0)
src/webcatalog/models/applications.py (+1/-0)
src/webcatalog/templates/webcatalog/application_detail.html (+6/-0)
src/webcatalog/tests/factory.py (+4/-2)
src/webcatalog/tests/test_commands.py (+41/-40)
src/webcatalog/tests/test_data/sca_apps.txt (+2/-1)
src/webcatalog/tests/test_views.py (+21/-0)
To merge this branch: bzr merge lp:~michael.nelson/ubuntu-webcatalog/953306-display-app-version
Reviewer Review Type Date Requested Status
Anthony Lenton (community) Approve
Review via email: mp+97230@code.launchpad.net

Commit message

Import and display application versions.

Description of the change

Overiew
=======

Adds Application.version, ensures it's imported for both archive and purchase apps, and displays it on the details page under the license (similar to USC).

`fab test`

To post a comment you must log in.
82. By Michael Nelson

Moved inline immport.

Revision history for this message
Anthony Lenton (elachuni) wrote :

Hi Michael,

Thanks for the branch! The only thing I think would be missing would be to also import the version for for-purchase apps, within the import_for_purchase_apps command.

About rev. 77, I think it's neat if the tests can all work with the same mock_response. Why is test_app_is_not_created_if_already_in_webcatalog removed though? Was that already tested by a different test?

Cheers,

achuni.

Revision history for this message
Michael Nelson (michael.nelson) wrote :

On Wed, Mar 14, 2012 at 11:11 PM, Anthony Lenton
<email address hidden> wrote:
> Hi Michael,
>
> Thanks for the branch!  The only thing I think would be missing would be to also import the version for for-purchase apps, within the import_for_purchase_apps command.
>

Sheesh - you had me worried there for a second. It is there, you can
see it being tested line 389 of the MP diff, it's just that
import_for_purchase_apps didn't contain the change, it uses a form to
clean the data and the form was updated (first part of the diff).

> About rev. 77, I think it's neat if the tests can all work with the same mock_response.  Why is test_app_is_not_created_if_already_in_webcatalog removed though? Was that already tested by a different test?

Yeah, with test_existing_app_gets_updated_by_archive_id, it made sense
that part of this test was to ensure not only that the existing app is
updated, but that the number of apps didn't change. If you think it
should be separate, just let me know.

Thanks!

Revision history for this message
Anthony Lenton (elachuni) wrote :

Hah, yep, I missed the test completely and thought that the form update was for import_app_install_data.

Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/webcatalog/forms.py'
--- src/webcatalog/forms.py 2012-03-06 19:35:00 +0000
+++ src/webcatalog/forms.py 2012-03-13 15:19:18 +0000
@@ -22,6 +22,7 @@
22 with_statement,22 with_statement,
23 )23 )
2424
25import apt
25from ConfigParser import ConfigParser26from ConfigParser import ConfigParser
26from StringIO import StringIO27from StringIO import StringIO
2728
@@ -108,6 +109,10 @@
108109
109 return cls(data=app_data, instance=instance)110 return cls(data=app_data, instance=instance)
110111
112 def clean_version(self):
113 value = self.cleaned_data['version']
114 return apt.apt_pkg.upstream_version(value)
115
111116
112class EmailDownloadLinkForm(forms.Form):117class EmailDownloadLinkForm(forms.Form):
113 email = forms.EmailField()118 email = forms.EmailField()
114119
=== modified file 'src/webcatalog/management/commands/import_app_install_data.py'
--- src/webcatalog/management/commands/import_app_install_data.py 2012-03-05 09:23:47 +0000
+++ src/webcatalog/management/commands/import_app_install_data.py 2012-03-13 15:19:18 +0000
@@ -264,6 +264,7 @@
264 if not app_comment:264 if not app_comment:
265 app_comment = package.name265 app_comment = package.name
266266
267 version = apt.apt_pkg.upstream_version(candidate.version)
267 if package.name in prefetched_apps:268 if package.name in prefetched_apps:
268 app = prefetched_apps[package.name]269 app = prefetched_apps[package.name]
269 if (app.description == candidate.description and270 if (app.description == candidate.description and
@@ -273,6 +274,7 @@
273 continue274 continue
274 app.description = candidate.description275 app.description = candidate.description
275 app.section = candidate.section276 app.section = candidate.section
277 app.version = version
276 app.name = app_name278 app.name = app_name
277 app.comment = app_comment279 app.comment = app_comment
278 app.save()280 app.save()
@@ -284,6 +286,7 @@
284 description=candidate.description,286 description=candidate.description,
285 section=candidate.section,287 section=candidate.section,
286 name=app_name,288 name=app_name,
289 version=version,
287 comment=app_comment,290 comment=app_comment,
288 )291 )
289 if self.verbosity == 1:292 if self.verbosity == 1:
290293
=== added file 'src/webcatalog/migrations/0010_add_app_version.py'
--- src/webcatalog/migrations/0010_add_app_version.py 1970-01-01 00:00:00 +0000
+++ src/webcatalog/migrations/0010_add_app_version.py 2012-03-13 15:19:18 +0000
@@ -0,0 +1,154 @@
1# encoding: utf-8
2import datetime
3from south.db import db
4from south.v2 import SchemaMigration
5from django.db import models
6
7class Migration(SchemaMigration):
8
9 def forwards(self, orm):
10
11 # Adding field 'Application.version'
12 db.add_column('webcatalog_application', 'version', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True), keep_default=False)
13
14
15 def backwards(self, orm):
16
17 # Deleting field 'Application.version'
18 db.delete_column('webcatalog_application', 'version')
19
20
21 models = {
22 'auth.group': {
23 'Meta': {'object_name': 'Group'},
24 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
25 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
26 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
27 },
28 'auth.permission': {
29 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
30 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
31 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
32 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
33 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
34 },
35 'auth.user': {
36 'Meta': {'object_name': 'User'},
37 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
38 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
39 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
40 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
41 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
42 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
43 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
44 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
45 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
46 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
47 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
48 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
49 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
50 },
51 'contenttypes.contenttype': {
52 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
53 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
54 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
55 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
56 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
57 },
58 'webcatalog.application': {
59 'Meta': {'unique_together': "(('distroseries', 'archive_id'),)", 'object_name': 'Application'},
60 'app_type': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
61 'architectures': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
62 'archive_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'null': 'True', 'blank': 'True'}),
63 'categories': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
64 'channel': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
65 'comment': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
66 'departments': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.Department']", 'symmetrical': 'False', 'blank': 'True'}),
67 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
68 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']"}),
69 'for_purchase': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
70 'icon': ('django.db.models.fields.files.ImageField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
71 'icon_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
72 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
73 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
74 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
75 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
76 'package_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
77 'popcon': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
78 'price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2', 'blank': 'True'}),
79 'ratings_average': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '3', 'decimal_places': '2', 'blank': 'True'}),
80 'ratings_histogram': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
81 'ratings_total': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
82 'screenshot_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
83 'section': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
84 'version': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'})
85 },
86 'webcatalog.consumer': {
87 'Meta': {'object_name': 'Consumer'},
88 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
89 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
90 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
91 'secret': ('django.db.models.fields.CharField', [], {'default': "'sEjZUPZnEgnDdaBCNkLPXCrLcWBCxu'", 'max_length': '255', 'blank': 'True'}),
92 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
93 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'oauth_consumer'", 'unique': 'True', 'to': "orm['auth.User']"})
94 },
95 'webcatalog.department': {
96 'Meta': {'object_name': 'Department'},
97 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
98 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
99 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Department']", 'null': 'True', 'blank': 'True'})
100 },
101 'webcatalog.distroseries': {
102 'Meta': {'object_name': 'DistroSeries'},
103 'code_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}),
104 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
105 'version': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'})
106 },
107 'webcatalog.exhibit': {
108 'Meta': {'object_name': 'Exhibit'},
109 'banner_url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
110 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
111 'display': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
112 'distroseries': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['webcatalog.DistroSeries']", 'symmetrical': 'False'}),
113 'html': ('django.db.models.fields.TextField', [], {}),
114 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
115 'package_names': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
116 'published': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
117 'sca_id': ('django.db.models.fields.IntegerField', [], {})
118 },
119 'webcatalog.machine': {
120 'Meta': {'unique_together': "(('owner', 'uuid'),)", 'object_name': 'Machine'},
121 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
122 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
123 'logo_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56', 'blank': 'True'}),
124 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
125 'package_list': ('django.db.models.fields.TextField', [], {}),
126 'packages_checksum': ('django.db.models.fields.CharField', [], {'max_length': '56'}),
127 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'})
128 },
129 'webcatalog.nonce': {
130 'Meta': {'object_name': 'Nonce'},
131 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}),
132 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
133 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
134 'nonce': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
135 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Token']"})
136 },
137 'webcatalog.reviewstatsimport': {
138 'Meta': {'object_name': 'ReviewStatsImport'},
139 'distroseries': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.DistroSeries']", 'unique': 'True'}),
140 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
141 'last_import': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'})
142 },
143 'webcatalog.token': {
144 'Meta': {'object_name': 'Token'},
145 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['webcatalog.Consumer']"}),
146 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
147 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
148 'token': ('django.db.models.fields.CharField', [], {'default': "'NmdZZbdybysvASwPmODfOInVgdUrtwQIuGzCBQzZgoRoppjwrK'", 'max_length': '50', 'primary_key': 'True'}),
149 'token_secret': ('django.db.models.fields.CharField', [], {'default': "'zXcfbHWuHkeoltnlevFxVswIdDArEKgnTSLZzlkLSHdUCLmluo'", 'max_length': '50'}),
150 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
151 }
152 }
153
154 complete_apps = ['webcatalog']
0155
=== modified file 'src/webcatalog/models/applications.py'
--- src/webcatalog/models/applications.py 2012-03-12 15:30:15 +0000
+++ src/webcatalog/models/applications.py 2012-03-13 15:19:18 +0000
@@ -69,6 +69,7 @@
69 # The following fields are extracted from app-install-data.69 # The following fields are extracted from app-install-data.
70 package_name = models.CharField(max_length=100)70 package_name = models.CharField(max_length=100)
71 name = models.CharField(max_length=255)71 name = models.CharField(max_length=255)
72 version = models.CharField(max_length=32, blank=True)
72 comment = models.CharField(max_length=255, blank=True)73 comment = models.CharField(max_length=255, blank=True)
73 popcon = models.IntegerField(null=True, blank=True)74 popcon = models.IntegerField(null=True, blank=True)
74 channel = models.CharField(max_length=255, blank=True)75 channel = models.CharField(max_length=255, blank=True)
7576
=== modified file 'src/webcatalog/templates/webcatalog/application_detail.html'
--- src/webcatalog/templates/webcatalog/application_detail.html 2012-03-08 20:27:19 +0000
+++ src/webcatalog/templates/webcatalog/application_detail.html 2012-03-13 15:19:18 +0000
@@ -94,6 +94,12 @@
94 <th>{% trans "License:" %}</th>94 <th>{% trans "License:" %}</th>
95 <td>{{ application.license_type }}</td>95 <td>{{ application.license_type }}</td>
96 </tr>96 </tr>
97 {% if application.version %}
98 <tr>
99 <th>{% trans "Version:" %}</th>
100 <td>{{ application.version }}</td>
101 </tr>
102 {% endif %}
97 </table>103 </table>
98 </div>104 </div>
99 <div class="share">105 <div class="share">
100106
=== modified file 'src/webcatalog/tests/factory.py'
--- src/webcatalog/tests/factory.py 2012-03-09 15:46:15 +0000
+++ src/webcatalog/tests/factory.py 2012-03-13 15:19:18 +0000
@@ -93,7 +93,8 @@
93 def make_application(self, package_name=None, name=None,93 def make_application(self, package_name=None, name=None,
94 comment=None, description=None, icon_name='', icon=None,94 comment=None, description=None, icon_name='', icon=None,
95 distroseries=None, arch='i686', ratings_average=None,95 distroseries=None, arch='i686', ratings_average=None,
96 ratings_total=None, ratings_histogram='', screenshot_url=None):96 ratings_total=None, ratings_histogram='', screenshot_url=None,
97 archive_id=None, version=''):
97 if name is None:98 if name is None:
98 name = self.get_unique_string(prefix='Readable Name')99 name = self.get_unique_string(prefix='Readable Name')
99 if package_name is None:100 if package_name is None:
@@ -110,7 +111,8 @@
110 description=description, popcon=999, icon=icon,111 description=description, popcon=999, icon=icon,
111 icon_name=icon_name, distroseries=distroseries, architectures=arch,112 icon_name=icon_name, distroseries=distroseries, architectures=arch,
112 ratings_average=ratings_average, ratings_total=ratings_total,113 ratings_average=ratings_average, ratings_total=ratings_total,
113 ratings_histogram=ratings_histogram, screenshot_url=screenshot_url)114 ratings_histogram=ratings_histogram, screenshot_url=screenshot_url,
115 archive_id=archive_id, version=version)
114116
115 def make_department(self, name, parent=None, slug=None):117 def make_department(self, name, parent=None, slug=None):
116 if slug is None:118 if slug is None:
117119
=== modified file 'src/webcatalog/tests/test_commands.py'
--- src/webcatalog/tests/test_commands.py 2012-03-06 16:51:27 +0000
+++ src/webcatalog/tests/test_commands.py 2012-03-13 15:19:18 +0000
@@ -88,6 +88,7 @@
88 mock_package.name = name88 mock_package.name = name
89 mock_package.candidate.section = ''89 mock_package.candidate.section = ''
90 mock_package.candidate.summary = summary90 mock_package.candidate.summary = summary
91 mock_package.candidate.version = '1.2.3-4ubuntu1~dev'
91 return mock_package92 return mock_package
9293
93 def make_mock_apt_cache(self):94 def make_mock_apt_cache(self):
@@ -381,6 +382,7 @@
381 otherapp = Application.objects.get(package_name='otherapp')382 otherapp = Application.objects.get(package_name='otherapp')
382 self.assertEqual('Otherapp the Internet', otherapp.name)383 self.assertEqual('Otherapp the Internet', otherapp.name)
383 self.assertEqual('A tagline for Otherapp', otherapp.comment)384 self.assertEqual('A tagline for Otherapp', otherapp.comment)
385 self.assertEqual('1.2.3', otherapp.version)
384386
385 def test_lang_specific_description_added_to_app(self):387 def test_lang_specific_description_added_to_app(self):
386 # Related to bug 879268 - our app server runs on lucid where388 # Related to bug 879268 - our app server runs on lucid where
@@ -401,6 +403,7 @@
401class ImportForPurchaseAppsTestCase(TestCaseWithFactory):403class ImportForPurchaseAppsTestCase(TestCaseWithFactory):
402404
403 def setUp(self):405 def setUp(self):
406 super(ImportForPurchaseAppsTestCase, self).setUp()
404 curdir = os.path.dirname(__file__)407 curdir = os.path.dirname(__file__)
405 sca_apps_file = os.path.join(curdir, 'test_data', 'sca_apps.txt')408 sca_apps_file = os.path.join(curdir, 'test_data', 'sca_apps.txt')
406 self.distroseries = DistroSeries.objects.create(code_name='natty')409 self.distroseries = DistroSeries.objects.create(code_name='natty')
@@ -409,69 +412,67 @@
409 mock_response = Mock()412 mock_response = Mock()
410 mock_response.code = 200413 mock_response.code = 200
411 mock_response.read.return_value = self.response_content414 mock_response.read.return_value = self.response_content
412 self.mock_response = mock_response415
413416 self.patch_urlopen = patch('urllib.urlopen')
414 @patch('urllib.urlopen')417 mock_urllib = self.patch_urlopen.start()
415 def test_app_for_purchase_is_found(self, mock_urllib):418 mock_urllib.return_value = mock_response
416 mock_urllib.return_value = self.mock_response419 self.addCleanup(self.patch_urlopen.stop)
420
421 def test_app_for_purchase_is_found(self):
417 apps_for_purchase = Application.objects.filter(for_purchase=True)422 apps_for_purchase = Application.objects.filter(for_purchase=True)
418 self.assertEqual(0, len(apps_for_purchase))423 self.assertEqual(0, len(apps_for_purchase))
424
419 call_command('import_for_purchase_apps')425 call_command('import_for_purchase_apps')
426
420 app_for_purchase = Application.objects.get(name='MyApp',427 app_for_purchase = Application.objects.get(name='MyApp',
421 distroseries=self.distroseries)428 distroseries=self.distroseries)
422 self.assertEqual(True, app_for_purchase.for_purchase)429 self.assertEqual(True, app_for_purchase.for_purchase)
423 self.assertTrue(app_for_purchase.description.find('hello') > -1)430 self.assertTrue(app_for_purchase.description.find('hello') > -1)
424431
425 @patch('urllib.urlopen')432 def test_app_gets_distroseries(self):
426 def test_app_is_not_created_if_already_in_webcatalog(self, mock_urllib):433 call_command('import_for_purchase_apps')
427 mock_urllib.return_value = self.mock_response
428 apps = Application.objects.all()
429 first = len(apps)
430 call_command('import_for_purchase_apps')
431 apps = Application.objects.all()
432 second = len(apps)
433 call_command('import_for_purchase_apps')
434 apps = Application.objects.all()
435 third = len(apps)
436 self.assertTrue(second > first)
437 # number of apps should not increase
438 self.assertEqual(second, third)
439434
440 @patch('urllib.urlopen')
441 def test_app_gets_distroseries(self, mock_urllib):
442 mock_urllib.return_value = self.mock_response
443 call_command('import_for_purchase_apps')
444 app = Application.objects.get(name='MyApp',435 app = Application.objects.get(name='MyApp',
445 distroseries=self.distroseries)436 distroseries=self.distroseries)
446 self.assertEqual(2, len(app.available_distroseries()))437 self.assertEqual(2, len(app.available_distroseries()))
447438
448 @patch('urllib.urlopen')439 def test_app_gets_price(self):
449 def test_app_gets_price(self, mock_urllib):
450 mock_urllib.return_value = self.mock_response
451 call_command('import_for_purchase_apps')440 call_command('import_for_purchase_apps')
441
452 app = Application.objects.get(name='MyApp',442 app = Application.objects.get(name='MyApp',
453 distroseries=self.distroseries)443 distroseries=self.distroseries)
454 self.assertEqual(Decimal('2.50'), app.price)444 self.assertEqual(Decimal('2.50'), app.price)
455445
456 @patch('urllib.urlopen')446 def test_existing_app_gets_updated_by_archive_id(self):
457 def test_app_gets_updated(self, mock_urllib):447 self.factory.make_application(archive_id='launchpad_zematynnad2/myppa',
458 mock_urllib.return_value = self.mock_response448 package_name='somethingelse',
459 call_command('import_for_purchase_apps')449 distroseries=self.factory.make_distroseries(code_name='maverick'))
460 updated = self.response_content.replace('hello', 'bye')450 self.factory.make_application(archive_id='launchpad_zematynnad2/myppa',
461 self.mock_response.read.return_value = updated451 package_name='somethingelse',
462 call_command('import_for_purchase_apps')
463 app = Application.objects.get(name='MyApp',
464 distroseries=self.distroseries)452 distroseries=self.distroseries)
465 self.assertEqual('bye', app.package_name)453 self.assertEqual(2, Application.objects.count())
466454
467 @patch('urllib.urlopen')455 call_command('import_for_purchase_apps')
468 def test_app_gets_icon(self, mock_urllib):456
469 mock_urllib.return_value = self.mock_response457 self.assertEqual(2, Application.objects.count())
470 call_command('import_for_purchase_apps')458 for app in Application.objects.all():
459 self.assertEqual('launchpad_zematynnad2/myppa', app.archive_id)
460 self.assertEqual('hello', app.package_name)
461
462 def test_app_gets_icon(self):
463 call_command('import_for_purchase_apps')
464
471 app = Application.objects.get(name='MyApp',465 app = Application.objects.get(name='MyApp',
472 distroseries=self.distroseries)466 distroseries=self.distroseries)
473 self.assertEqual(6461, app.icon.size)467 self.assertEqual(6461, app.icon.size)
474468
469 def test_app_gets_version(self):
470 call_command('import_for_purchase_apps')
471
472 app = Application.objects.get(package_name='hello',
473 distroseries=self.distroseries)
474 self.assertEqual('1.2.3', app.version)
475
475476
476class ImportRatingsTestCase(TestCaseWithFactory):477class ImportRatingsTestCase(TestCaseWithFactory):
477478
478479
=== modified file 'src/webcatalog/tests/test_data/sca_apps.txt'
--- src/webcatalog/tests/test_data/sca_apps.txt 2011-07-02 04:53:26 +0000
+++ src/webcatalog/tests/test_data/sca_apps.txt 2012-03-13 15:19:18 +0000
@@ -4,6 +4,7 @@
4 "signing_key_id": "",4 "signing_key_id": "",
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).",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 "package_name": "hello",6 "package_name": "hello",
7 "version": "1.2.3-2ubuntu1~dev",
7 "series": {"maverick": ["i386", "amd64"], "natty": ["i386", "amd64"]},8 "series": {"maverick": ["i386", "amd64"], "natty": ["i386", "amd64"]},
8 "price": "2.50",9 "price": "2.50",
9 "archive_id": "launchpad_zematynnad2/myppa",10 "archive_id": "launchpad_zematynnad2/myppa",
@@ -15,4 +16,4 @@
15 "categories": "Audio",16 "categories": "Audio",
16 "name": "MyApp"17 "name": "MyApp"
17 }18 }
18]
19\ No newline at end of file19\ No newline at end of file
20]
2021
=== modified file 'src/webcatalog/tests/test_views.py'
--- src/webcatalog/tests/test_views.py 2012-03-12 15:43:37 +0000
+++ src/webcatalog/tests/test_views.py 2012-03-13 15:19:18 +0000
@@ -282,6 +282,27 @@
282 'has been sent.')282 'has been sent.')
283 self.assertContains(response, 'Enter a valid e-mail address.')283 self.assertContains(response, 'Enter a valid e-mail address.')
284284
285 def test_version_and_label_displayed(self):
286 app = self.factory.make_application(version='1.2.3',
287 distroseries=self.factory.make_distroseries())
288
289 url = reverse('wc-package-detail', kwargs=dict(
290 distro=app.distroseries.code_name, package_name=app.package_name))
291 response = self.client.get(url)
292
293 self.assertContains(response, '<th>Version:</th>')
294 self.assertContains(response, '<td>1.2.3</td>')
295
296 def test_version_label_not_displayed(self):
297 app = self.factory.make_application(version='',
298 distroseries=self.factory.make_distroseries())
299
300 url = reverse('wc-package-detail', kwargs=dict(
301 distro=app.distroseries.code_name, package_name=app.package_name))
302 response = self.client.get(url)
303
304 self.assertNotContains(response, '<th>Version</th>')
305
285306
286class ApplicationDetailNoSeriesTestCase(TestCaseWithFactory):307class ApplicationDetailNoSeriesTestCase(TestCaseWithFactory):
287308

Subscribers

People subscribed via source and target branches