Unit-Testing NSPasteboard
How Pasteboards Work
NSPasteboard is Mac OS X’s mechanism for handling copy and paste, drag and drop, and the choosing of fonts and colors.
When an app needs to take advantage of one of those features, they just call up the appropriate pasteboard. Along with the data to be read or written, the pasteboard stores the type of the data. On a given pasteboard, Mac applications can read and write data in multiple formats. Usually it’s in a number of standardized and well-understood formats.
Putting Up With Word
It’s a nice system, and most of the time it works in a pretty straightforward way. But there are a few problems that come up in writing an app like ShoveBox that deals extensively with the pasteboard.
When you drag a paragraph out of Microsoft Word, it’s published reasonably enough as rich and plain text, but also as a picture of the text. I’m not sure how that would ever be useful, but ShoveBox needs to know to prioritize the rich text.
When you drag a URL out of Safari’s address bar, it publishes it as a URL, as plain text, and as a couple of Safari-native formats for bookmarks. Not bad at all! But Firefox publishes URLs dragged from the address bar as plain text and, oddly, rich text. ShoveBox prefers rich text over plain text, but because of Firefox, it now parses both for URLs.
The sum of these sort of idiosyncrasies makes it difficult to handle input optimally in every scenario. After all, what if a concession made for one application’s data screws up the handling of another’s? The busy college student I am, I don’t have time to test it with every app after every minor change to this logic.
Enter PastePacker and OCUnit
To run OCUnit tests of every kind of drag-and-drop that ShoveBox should reasonably be expected to handle, we need some way of freezing the pasteboard and reconstituting it for the test.
Unfortunately, NSPasteboard does not support NSCoding, but it’s quite easy to just look at the list of types and grab the NSData for each type. Then, to make the pasteboard again, we just make a new one and pump the data back in.
PastePacker is a little app that look me all of an hour to write. It lets you copy and paste or drag-and-drop data into it, then it lets you save it to a plist-based format I call .pboard.
Download App: PastePacker.zip (109KB)
Horrible Source: http://svn.wonderwarp.com/pastepacker/
The interface is pretty bad, and it offers only a useless view of the pasteboard data as hex. But when I get time to work on it, I’ll be turning it into a more useful tool for any kind of pasteboard debugging.
So in my growing collection of unit tests, I just have a function to load in the appropriate .pboard file from a folder of them inside my unit test bundle. I simply check to make sure it’s got the right type and includes the correct data.
The next few releases will incorporate the results of this unit-testing.

