Merge lp:~sinzui/charmworld/sane-categories into lp:~juju-jitsu/charmworld/trunk

Proposed by Curtis Hovey
Status: Merged
Approved by: Curtis Hovey
Approved revision: 301
Merged at revision: 300
Proposed branch: lp:~sinzui/charmworld/sane-categories
Merge into: lp:~juju-jitsu/charmworld/trunk
Diff against target: 105 lines (+41/-2)
5 files modified
charmworld/models.py (+13/-1)
charmworld/static/css/theme.less (+4/-0)
charmworld/templates/charm.pt (+7/-0)
charmworld/tests/test_models.py (+12/-1)
charmworld/views/tests/test_api.py (+5/-0)
To merge this branch: bzr merge lp:~sinzui/charmworld/sane-categories
Reviewer Review Type Date Requested Status
Aaron Bentley (community) Approve
Review via email: mp+173570@code.launchpad.net

Commit message

Do not include bogus categories in charm data.

Description of the change

The GUI is mis-rendering the icons for charms with invalid categories

RULES

    Pre-implementation: rick
    * Proof does not enforce the 6 valid categories because it wants to
      maintain backward compatibility. The API though, does need to enforce
      the categories to discourage mistakes and community fragmentation.
    * The Charm model object is passing the categories to the API and pages.
      It ensures categories is a list.
      * It must also ensure the categories are one or more of the official
        categories.

    Extra credit
    * Update the charm page to list the categories after the summary.

QA

    * Visit http://staging.jujucharms.com/~nextrevision/precise/openvpn/json
    * Verify the categories property does not contain "application".
    * Visit http://staging.jujucharms.com/~nextrevision/precise/openvpn
    * Verify the categories property shown, but there are no categories.

To post a comment you must log in.
Revision history for this message
Aaron Bentley (abentley) :
review: Approve
301. By Curtis Hovey

Added test to confirm that the API does not include invalid categories.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charmworld/models.py'
2--- charmworld/models.py 2013-07-04 16:30:39 +0000
3+++ charmworld/models.py 2013-07-08 20:05:31 +0000
4@@ -252,6 +252,15 @@
5 'is_featured': False,
6 }
7
8+ OFFICIAL_CATEGORIES = [
9+ 'applications',
10+ 'app-servers',
11+ 'cache-proxy',
12+ 'databases',
13+ 'file-servers',
14+ 'misc',
15+ ]
16+
17 def __init__(self, charm_data):
18 """Init the charm from a charm representation.
19
20@@ -491,7 +500,10 @@
21
22 The categories come from the charm's metadata.
23 """
24- return self._representation['categories']
25+ return [
26+ category for category in self._representation['categories']
27+ if category in self.OFFICIAL_CATEGORIES
28+ ]
29
30 @property
31 def maintainer(self):
32
33=== modified file 'charmworld/static/css/theme.less'
34--- charmworld/static/css/theme.less 2013-01-21 14:14:49 +0000
35+++ charmworld/static/css/theme.less 2013-07-08 20:05:31 +0000
36@@ -70,3 +70,7 @@
37 .left-align {
38 text-align: left
39 }
40+
41+.field .subordinate {
42+ margin-bottom: 0;
43+}
44
45=== modified file 'charmworld/templates/charm.pt'
46--- charmworld/templates/charm.pt 2013-06-25 08:32:00 +0000
47+++ charmworld/templates/charm.pt 2013-07-08 20:05:31 +0000
48@@ -39,6 +39,13 @@
49 ${charm.summary}
50 </div>
51
52+ <div class="field">
53+ <b>categories</b><br/>
54+ <ul class="subordinate">
55+ <li tal:repeat="category charm.categories">${category}</li>
56+ </ul>
57+ </div>
58+
59 <div class="field" tal:condition="charm.store_data.get('errors', False)">
60 <b>Charm Store</b><br/>
61 <em>juju deploy ${charm.store_data['address']}</em>
62
63=== modified file 'charmworld/tests/test_models.py'
64--- charmworld/tests/test_models.py 2013-07-01 14:45:02 +0000
65+++ charmworld/tests/test_models.py 2013-07-08 20:05:31 +0000
66@@ -355,11 +355,22 @@
67 categories = ['cache-proxy', 'app-servers']
68 charm_data = factory.get_charm_json(categories=categories)
69 charm = Charm(charm_data)
70- self.assertIs(categories, charm.categories)
71+ self.assertEqual(categories, charm.categories)
72 # The default is an empty list.
73 charm = Charm({})
74 self.assertEqual([], charm.categories)
75
76+ def test_categories_are_official(self):
77+ # Unofficial categories are filtered out of the list.
78+ categories = ['application']
79+ charm_data = factory.get_charm_json(categories=categories)
80+ charm = Charm(charm_data)
81+ self.assertEqual(
82+ ['applications', 'app-servers', 'cache-proxy', 'databases',
83+ 'file-servers', 'misc'],
84+ charm.OFFICIAL_CATEGORIES)
85+ self.assertEqual([], charm.categories)
86+
87 def test_maintainer(self):
88 # The maintainer property is a list of category names.
89 maintainer = ['Jane <jane@example.com>', 'Ian <ian@example.com>']
90
91=== modified file 'charmworld/views/tests/test_api.py'
92--- charmworld/views/tests/test_api.py 2013-07-02 12:28:28 +0000
93+++ charmworld/views/tests/test_api.py 2013-07-08 20:05:31 +0000
94@@ -702,6 +702,11 @@
95 formatted = self.api_class._format_charm(Charm(charm))
96 self.assertFalse(formatted['is_approved'])
97
98+ def test_format_invalid_category(self):
99+ charm = factory.get_charm_json(categories=['applications', 'bong'])
100+ formatted = self.api_class._format_charm(Charm(charm))
101+ self.assertEqual(['applications'], formatted['categories'])
102+
103 def test_charm(self):
104 """Retrieving a charm works."""
105 self.use_index_client()

Subscribers

People subscribed via source and target branches