You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This adds a `Tags` field called `tags` to the `Categorization` fieldset, with a behavior adapter that stores the chosen tags in the `Subject` metadata field.
31
+
32
+
33
+
### Test setup
34
+
35
+
Before we can run these tests, we need to load the `collective.gtags` configuration.
Let's create a content object that has this behavior enabled and check that
108
112
it works.
109
113
110
-
>>> doc = Document('doc')
111
-
>>> tags_adapter = ITags(doc, None)
112
-
>>> tags_adapter is not None
113
-
True
114
+
```pycon
115
+
>>> doc = Document("doc")
116
+
>>> tags_adapter = ITags(doc, None)
117
+
>>> tags_adapter isnotNone
118
+
True
119
+
```
114
120
115
121
We'll check that the `tags` set is built from the `Subject()` field:
116
122
117
-
>>> doc.setSubject(['One', 'Two'])
118
-
>>> doc.Subject()
119
-
('One', 'Two')
123
+
```pycon
124
+
>>> doc.setSubject(["One", "Two"])
125
+
>>> doc.Subject()
126
+
("One", "Two")
120
127
121
-
>>> tags_adapter.tags == set(['One', 'Two'])
122
-
True
128
+
>>> tags_adapter.tags ==set(["One", "Two"])
129
+
True
123
130
124
-
>>> tags_adapter.tags = set(['Two', 'Three'])
125
-
>>> doc.Subject() == ('Two', 'Three')
126
-
True
131
+
>>> tags_adapter.tags =set(["Two", "Three"])
132
+
>>> doc.Subject() == ("Two", "Three")
133
+
True
127
134
```
128
135
129
136
This test tries to prove that the behavior is correctly installed and works as intended on a suitable content class.
130
137
It is not a true unit test, however.
131
-
For a true unit test, we would simply test the *Tags* adapter directly on a dummy context, but that is not terribly interesting, since all it does is convert sets to tuples.
138
+
For a true unit test, we would test the `Tags` adapter directly on a dummy context, but that is not terribly interesting, since all it does is convert sets to tuples.
132
139
133
140
First, we configure the package.
134
-
To keep the test small, we limit ourselves to the *behaviors.zcml* file, which in this case will suffice.
135
-
We still need to include a minimal set of ZCML from Five.
141
+
To keep the test small, we limit ourselves to the {file}`behaviors.zcml` file, which in this case will suffice.
142
+
We still need to include a minimal set of ZCML from `Five`.
136
143
137
-
Next, we implement an *IBehaviorAssignable\*adapter.
138
-
This is a low-level component used by \*plone.behavior* to determine if a behavior is enabled on a particular object.
139
-
Dexterity provides an implementation that checks the type’s FTI. Our test version is much simpler - it hardcodes the
140
-
supported behaviors.
144
+
Next, we implement an `IBehaviorAssignable`adapter.
145
+
This is a low-level component used by `plone.behavior` to determine if a behavior is enabled on a particular object.
146
+
Dexterity provides an implementation that checks the type's FTI.
147
+
Our test version is much simpler: it hardcodes the supported behaviors.
141
148
142
-
With this in place, we first check that the *IBehavior* utility has been correctly registered.
143
-
This is essentially a test to show that we’ve used the *\<plone:behavior />* directive as intended.
144
-
We also verify that our schema interface is an *IFormFieldsProvider*.
145
-
For a non-form behavior, we’d omit this.
149
+
With this in place, we first check that the `IBehavior` utility has been correctly registered.
150
+
This is essentially a test to show that we've used the `<plone:behavior />` directive as intended.
151
+
We also verify that our schema interface is an `IFormFieldsProvider`.
152
+
For a non-form behavior, we'd omit this.
146
153
147
154
Finally, we test the behavior.
148
-
We’ve chosen to use CMFDefault’s *Document* type for our test, as the behavior adapter requires an object providing *IDublinCore*.
149
-
Ideally, we’d write our own class and implement *IDublinCore* directly.
150
-
However, in many cases, the types from CMFDefault are going to provide convenient test fodder.
155
+
We've chosen to use CMFDefault's `Document` type for our test, as the behavior adapter requires an object providing `IDublinCore`.
156
+
Ideally, we'd write our own class and implement `IDublinCore` directly.
157
+
However, in many cases, the types from `CMFDefault` are going to provide convenient test fodder.
151
158
152
-
If our behavior was more complex we’d add more intricate tests.
159
+
If our behavior was more complex, we'd add more intricate tests.
153
160
By the last section of the doctest, we have enough context to test the adapter factory.
154
161
155
-
To run the test, we need a test suite. In *tests.py*, we have:
The methods `_enable_refresh_behavior` and `_disable_refresh_behavior` use the `IDexterityFTI` to get the Factory Type Information for the Dexterity type (`collective.cover.content` in this case).
@@ -258,7 +266,8 @@ To disable it, remove the behavior from the FTI behaviors: `behaviors.remove(IRe
258
266
Assign the resulting behaviors list to the behaviors attribute of the FTI as a tuple: `fti.behaviors = tuple(behaviors)`.
259
267
Finally, to have the changes take effect, invalidate the schema cache: `notify(SchemaInvalidatedEvent('collective.cover.content'))`.
260
268
269
+
261
270
## A note about marker interfaces
262
271
263
272
Marker interface support depends on code that is implemented in Dexterity and is non-trivial to reproduce in a test.
264
-
If you need a marker interface in a test, set it manually with *zope.interface.alsoProvides*, or write an integration test with Dexterity content.
273
+
If you need a marker interface in a test, set it manually with `zope.interface.alsoProvides`, or write an integration test with Dexterity content.
0 commit comments