PageRenderTime 63ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/externals/GData/Source/Tests/GDataFeedTest.m

http://google-email-uploader-mac.googlecode.com/
Objective C | 2212 lines | 1440 code | 472 blank | 300 comment | 25 complexity | d08856f41ab760b3b32aadb99534327a MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright (c) 2007 Google Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. //
  16. // GDataFeedTest.m
  17. //
  18. #import "GData.h"
  19. #import "GDataFeedTest.h"
  20. #import "GDataElementsTest.h"
  21. #import "GDataEntryCalendarEvent.h"
  22. #import "GDataEntryYouTubeVideo.h"
  23. #import "GDataMapConstants.h"
  24. @implementation GDataFeedTest
  25. - (void)runTests:(TestKeyPathValues *)tests {
  26. // step through each feed test
  27. for (int testIndex = 0;
  28. tests[testIndex].str1 != nil;
  29. testIndex++) {
  30. // get the class of this feed and the path to the test file of xml data
  31. //
  32. // The class name may specify a service version, like GDataFeedCalendar/2.0,
  33. // and may have a "-ignoreUnknown" suffix indicating unknown elements should be
  34. // ignored, like GDataFeedCalendar-ignore/2.0
  35. NSString *className = tests[testIndex].str1;
  36. NSString *serviceVersion = nil;
  37. BOOL shouldIgnoreUnknowns = NO;
  38. NSArray *components = [className componentsSeparatedByString:@"/"];
  39. if ([components count] == 2) {
  40. className = [components objectAtIndex:0];
  41. serviceVersion = [components objectAtIndex:1];
  42. }
  43. if ([className hasSuffix:@"-ignoreUnknown"]) {
  44. shouldIgnoreUnknowns = YES;
  45. NSUInteger nameLen = [className length] - [@"-ignoreUnknown" length];
  46. className = [className substringToIndex:nameLen];
  47. }
  48. #ifdef GDATA_TARGET_NAMESPACE
  49. className = [NSString stringWithFormat:@"%s_%@",
  50. GDATA_TARGET_NAMESPACE_STRING, className];
  51. #endif
  52. Class gdataClass = NSClassFromString(className);
  53. STAssertNotNil(gdataClass, @"Cannot make class for class name: %@", className);
  54. NSString *feedPath = tests[testIndex].str2;
  55. NSData *data = [NSData dataWithContentsOfFile:feedPath];
  56. STAssertNotNil(data, @"Cannot read feed from %@", feedPath);
  57. // create the feed object
  58. GDataFeedBase *feed1 = nil;
  59. if ([gdataClass instancesRespondToSelector:@selector(initWithData:serviceVersion:)]) {
  60. feed1 = [[[gdataClass alloc] initWithData:data
  61. serviceVersion:serviceVersion
  62. shouldIgnoreUnknowns:shouldIgnoreUnknowns] autorelease];
  63. } else {
  64. // this "feed" isn't a proper feed, and might be an entry
  65. NSError *error = nil;
  66. NSXMLDocument *doc = [[[NSXMLDocument alloc] initWithData:data
  67. options:0
  68. error:&error] autorelease];
  69. STAssertNotNil(doc, @"Cannot allocate XML document for %@, error %@",
  70. feedPath, error);
  71. NSXMLElement* root = [doc rootElement];
  72. feed1 = [[[gdataClass alloc] initWithXMLElement:root
  73. parent:nil
  74. serviceVersion:serviceVersion
  75. surrogates:nil
  76. shouldIgnoreUnknowns:shouldIgnoreUnknowns] autorelease];
  77. }
  78. // copy the feed object
  79. GDataObject *feed1copy = [[feed1 copy] autorelease];
  80. STAssertTrue([feed1 isEqual:feed1copy], @"Failed copy feed (%@) from %@ to %@",
  81. feedPath, feed1, feed1copy);
  82. // make a new feed object we'll test against from XML generated by the copy
  83. NSXMLElement *outputXML = [feed1copy XMLElement];
  84. GDataFeedBase *feed2 = [[[gdataClass alloc] initWithXMLElement:outputXML
  85. parent:nil
  86. serviceVersion:serviceVersion
  87. surrogates:nil
  88. shouldIgnoreUnknowns:shouldIgnoreUnknowns] autorelease];
  89. STAssertTrue([feed2 isEqual:feed1copy], @"Failed for %@ using XML \n %@\n\nto convert\n %@ \nto\n %@",
  90. feedPath, outputXML, feed1copy, feed2);
  91. // generate a description; this can fire an exception for an invalid keyPath
  92. // in the description record list
  93. STAssertNotNil([feed2 description], @"Could not generate description for %@",
  94. feedPath);
  95. // step through all the key-value path tests
  96. while (1) {
  97. ++testIndex;
  98. NSString *keyPath = tests[testIndex].str1;
  99. NSString *expectedValue = tests[testIndex].str2;
  100. if (keyPath == nil || [keyPath length] == 0) break;
  101. #if GDATA_USES_LIBXML
  102. // skip the XMLStrings until we can normalize whitespace and closing
  103. // brackets and other minor differences
  104. if ([keyPath hasSuffix:@".XMLString"]) continue;
  105. #endif
  106. NSString *result = [GDataElementsTest valueInObject:feed2
  107. forKeyPathIncludingArrays:keyPath];
  108. // if the result wasn't a string but responds to stringValue, then
  109. // invoke that to get a string
  110. if ([expectedValue isKindOfClass:[NSString class]]
  111. && ![result isKindOfClass:[NSString class]]
  112. && [result respondsToSelector:@selector(stringValue)]) {
  113. result = [(id)result stringValue];
  114. }
  115. // we'll test for equality unless the expected result begins "hasPrefix:"
  116. // or "contains:"
  117. if ([expectedValue hasPrefix:@"hasPrefix:"]) {
  118. NSString *prefix = [expectedValue substringFromIndex:[@"hasPrefix:" length]];
  119. STAssertTrue([result hasPrefix:prefix], @"failed object %@ \n testing key path '%@' for prefix:\n %@ \n!= prefix:\n %@",
  120. feed2, keyPath, result, prefix);
  121. } else if ([expectedValue hasPrefix:@"contains:"]) {
  122. NSString *substring = [expectedValue substringFromIndex:[@"contains:" length]];
  123. NSRange range = [result rangeOfString:substring];
  124. STAssertTrue(result != nil && range.location != NSNotFound,
  125. @"failed object %@ \n testing key path '%@' for substring:\n %@ \n!= contains:\n %@",
  126. feed2, keyPath, result, substring);
  127. } else {
  128. #ifdef GDATA_TARGET_NAMESPACE
  129. // tests for class name need the prefix added
  130. if ([keyPath hasSuffix:@"className"]
  131. && [expectedValue hasPrefix:@"GData"]) {
  132. expectedValue = [NSString stringWithFormat:@"%s_%@",
  133. GDATA_TARGET_NAMESPACE_STRING, expectedValue];
  134. }
  135. #endif
  136. STAssertTrue(AreEqualOrBothNil(result, expectedValue), @"failed object %@ \n testing key path '%@'\n %@ \n!= \n %@",
  137. feed2, keyPath, result, expectedValue);
  138. }
  139. }
  140. }
  141. }
  142. - (void)testBooksFeed {
  143. //
  144. // Volumes Feed
  145. //
  146. TestKeyPathValues tests[] =
  147. {
  148. { @"GDataFeedVolume", @"Tests/FeedBooksVolumesTest1.xml" },
  149. // GDataFeedVolume paths
  150. { @"identifier", @"http://www.google.com/books/feeds/users/1728172424007912469/volumes" },
  151. { @"authors.0.name", @"1728172424007912469" },
  152. // GDataEntryVolume paths
  153. { @"entries.0.creators.0", @"Jim Davis" },
  154. { @"entries.0.dates.0", @"2006-01-31" },
  155. { @"entries.0.volumeDescriptions.0", @"contains:Pig Out" },
  156. { @"entries.0.embeddability", kGDataBooksNotEmbeddable },
  157. { @"entries.0.openAccess", kGDataBooksEnabled },
  158. { @"entries.0.formats.0", @"93 pages" },
  159. { @"entries.0.volumeIdentifiers.0", @"_PRJAAAACAAJ" },
  160. { @"entries.0.volumeIdentifiers.1", @"ISBN:0345464664" },
  161. { @"entries.0.publishers.0", @"Ballantine Books" },
  162. { @"entries.0.subjects.0", @"Humor" },
  163. { @"entries.0.volumeTitles.0", @"Garfield Pigs Out" },
  164. { @"entries.0.viewability", kGDataBooksViewNoPages },
  165. { @"entries.0.thumbnailLink.href", @"hasPrefix:http://bks2.books.google.com/books?id=_PRJAAAACAAJ" },
  166. { @"entries.0.previewLink.href", @"contains:id=_PRJAAAACAAJ&ie=ISO-8859-1" },
  167. { @"entries.0.infoLink.href", @"contains:id=_PRJAAAACAAJ&ie=ISO-8859-1" },
  168. { @"entries.0.rating.value", @"3" },
  169. { @"entries.0.rating.average", @"2" },
  170. { @"entries.0.review", @"Ageless? No way." },
  171. { @"entries.0.contentVersion", @"1.2beta5" },
  172. { @"", @"" },
  173. { nil, nil }
  174. };
  175. [self runTests:tests];
  176. }
  177. - (void)testCalendarFeed {
  178. TestKeyPathValues tests[] =
  179. {
  180. //
  181. // Calendar Feed
  182. //
  183. { @"GDataFeedCalendar/2.0", @"Tests/FeedCalendarTest1.xml" },
  184. // GDataFeedCalendar paths
  185. { @"title", @"Fred Flintstone's Calendar List" },
  186. { @"links.1.rel", kGDataLinkRelPost },
  187. { @"links.2.rel", @"self" },
  188. { @"authors.0.name", @"Fred Flintstone" },
  189. { @"authors.0.email", @"fred@gmail.com" },
  190. { @"generator.URI", @"http://www.google.com/calendar" },
  191. { @"generator.name", @"Google Calendar" },
  192. { @"generator.version", @"1.0" },
  193. { @"startIndex", @"1" },
  194. { @"itemsPerPage", @"3" },
  195. { @"ETag", @"Nofzeigeritznum" },
  196. { @"fieldSelection", @"@gd:*,link" },
  197. { @"unknownAttributes.@count", @"0" },
  198. { @"unknownChildren.@count", @"0" },
  199. // GDataEntryCalendar paths
  200. { @"entries.0.identifier", @"http://www.google.com/calendar/feeds/test%40domain.net/test%40domain.net" },
  201. { @"entries.0.publishedDate.RFC3339String", @"2006-11-14T00:03:38Z" },
  202. { @"entries.0.updatedDate.RFC3339String", @"2006-11-09T00:16:10Z" },
  203. { @"entries.0.editedDate.RFC3339String", @"2006-11-09T00:16:15Z" },
  204. { @"entries.0.title", @"Fred Flintstone" },
  205. { @"entries.0.links.0.rel", @"alternate" },
  206. { @"entries.0.links.1.href", @"http://www.google.com/calendar/feeds/test%40domain.net/test%40domain.net" },
  207. { @"entries.0.authors.0.name", @"Fred Flintstone" },
  208. { @"entries.0.authors.0.email", @"fred@gmail.com" },
  209. { @"entries.0.isHidden", @"0" },
  210. { @"entries.0.timeZoneName", @"America/Los_Angeles" },
  211. { @"entries.0.timesCleaned", @"31" },
  212. { @"entries.0.color", @"#B1365F" },
  213. { @"entries.0.accessLevel", kGDataCalendarAccessOwner},
  214. { @"entries.0.overrideName", @"over-ride-name" },
  215. { @"entries.0.ETag", @"W/C04EQXc6fCp7ImA9WxZbGUU." },
  216. { @"entries.0.fieldSelection", @"@gd:*,title,gd:when" },
  217. { @"entries.1.locations.0", @"Joes Pub" },
  218. { @"entries.1.fieldSelection", nil },
  219. { @"entries.2.isSelected", @"0" },
  220. { @"entries.2.isHidden", @"1" },
  221. { @"entries.0.unknownAttributes.@count", @"0" },
  222. { @"entries.0.unknownChildren.@count", @"0" },
  223. { @"", @"" }, // end of feed
  224. //
  225. // CalendarEvent Feed
  226. //
  227. { @"GDataFeedCalendarEvent", @"Tests/FeedCalendarEventTest1.xml" },
  228. // GDataFeedCalendarEvent paths
  229. { @"title", @"Fred Flintstone" },
  230. { @"subtitle", @"Fred Flintstone" },
  231. { @"links.0.rel", kGDataLinkRelFeed },
  232. { @"links.2.rel", @"self" },
  233. { @"authors.0.name", @"Fred Flintstone" },
  234. { @"authors.0.email", @"fred@gmail.com" },
  235. { @"identifier", @"http://www.google.com/calendar/feeds/test%40gmail.com/private/full" },
  236. { @"namespaces.gCal", kGDataNamespaceGCal },
  237. { @"generator.URI", @"http://www.google.com/calendar" },
  238. { @"generator.name", @"Google Calendar" },
  239. { @"generator.version", @"1.0" },
  240. { @"startIndex", @"1" },
  241. { @"itemsPerPage", @"100000" },
  242. { @"timeZoneName", @"America/Los_Angeles" },
  243. { @"timesCleaned", @"7" },
  244. { @"unknownAttributes.@count", @"0" },
  245. { @"unknownChildren.@count", @"0" },
  246. // GDataEntryCalendarEvent paths
  247. { @"entries.0.identifier", @"contains:i12d4avieju0vogcga72aj3908" },
  248. { @"entries.0.publishedDate.RFC3339String", @"2006-10-27T22:48:14Z" },
  249. { @"entries.0.updatedDate.RFC3339String", @"2006-11-03T21:17:40Z" },
  250. { @"entries.0.title", @"3 days" },
  251. { @"entries.0.content", @"The description field" },
  252. { @"entries.0.links.0.title", @"alternate" },
  253. { @"entries.0.links.1.rel", @"self" },
  254. { @"entries.0.authors.0.name", @"Fred Flintstone" },
  255. { @"entries.0.authors.0.email", @"fred@gmail.com" },
  256. { @"entries.0.visibility", kGDataEventVisibilityDefault },
  257. { @"entries.0.comment.feedLink.href", @"contains:i12d4avieju0vogcga72aj3908/comments" },
  258. { @"entries.0.shouldSendEventNotifications", @"0" },
  259. { @"entries.0.isQuickAdd", @"0" },
  260. { @"entries.0.transparency", kGDataEventTransparencyOpaque },
  261. { @"entries.0.eventStatus", kGDataEventStatusConfirmed },
  262. { @"entries.0.participants.0.email", @"FredFlintstone@gmail.com" },
  263. { @"entries.0.participants.0.rel", kGDataWhoEventAttendee },
  264. { @"entries.0.participants.0.attendeeStatus", kGDataWhoAttendeeStatusDeclined },
  265. { @"entries.0.participants.1.numberOfAdditionalGuests", @"5" },
  266. { @"entries.0.participants.1.email", @"FredFlintstone@google.com" },
  267. { @"entries.0.participants.2.email", @"freg@gmail.com" },
  268. { @"entries.0.times.0.endTime.RFC3339String", @"2006-11-16" },
  269. { @"entries.0.times.0.reminders.0.minutes", @"10" },
  270. { @"entries.0.locations.0", @"The-where-field" },
  271. { @"entries.0.locations.0.rel", nil },
  272. { @"entries.0.sequenceNumber", @"2" },
  273. { @"entries.0.iCalUID", @"4A24A0FF-EA3A-4839-AA09-F4283CB6D345" },
  274. { @"entries.0.canGuestsModify", @"0" },
  275. { @"entries.0.canGuestsInviteOthers", @"0" },
  276. { @"entries.0.canGuestsSeeGuests", @"0" },
  277. { @"entries.0.canAnyoneAddSelf", @"0" },
  278. { @"entries.1.recurrence", @"hasPrefix:DTSTART;VALUE=DATE:20061120" },
  279. { @"entries.1.reminders.0.minutes", @"10" },
  280. { @"entries.1.isDeleted", @"0" },
  281. { @"entries.3.locations.0", @"Seattle" },
  282. { @"entries.3.isDeleted", @"1" },
  283. { @"entries.3.canGuestsModify", @"1" },
  284. { @"entries.3.canGuestsInviteOthers", @"1" },
  285. { @"entries.3.canGuestsSeeGuests", @"1" },
  286. { @"entries.3.canAnyoneAddSelf", @"1" },
  287. { @"entries.0.unknownAttributes.@count", @"0" },
  288. { @"entries.0.unknownChildren.@count", @"0" },
  289. { @"", @"" }, // end of feed
  290. //
  291. // CalendarEvent Feed with no entries
  292. //
  293. { @"GDataFeedCalendarEvent", @"Tests/FeedCalendarEventTest0.xml" },
  294. // GDataFeedCalendarEvent paths
  295. { @"title", @"Fred Flintstone" },
  296. { @"subtitle", @"Fred Flintstone" },
  297. { @"links.0.rel", kGDataLinkRelFeed },
  298. { @"links.2.rel", @"self" },
  299. { @"authors.0.name", @"Fred Flintstone" },
  300. { @"authors.0.email", @"fred@gmail.com" },
  301. { @"identifier", @"http://www.google.com/calendar/feeds/test%40gmail.com/private/full" },
  302. { @"namespaces.gCal", kGDataNamespaceGCal },
  303. { @"generator.URI", @"http://www.google.com/calendar" },
  304. { @"generator.name", @"Google Calendar" },
  305. { @"generator.version", @"1.0" },
  306. { @"startIndex", @"1" },
  307. { @"itemsPerPage", @"100000" },
  308. { @"timeZoneName", @"America/Los_Angeles" },
  309. { @"timesCleaned", @"7" },
  310. { @"unknownAttributes.@count", @"0" },
  311. { @"unknownChildren.@count", @"0" },
  312. // GDataEntryCalendarEvent paths
  313. { @"entries.@count", @"0" },
  314. { @"", @"" }, // end of feed
  315. { nil, nil } // end of test array
  316. };
  317. [self runTests:tests];
  318. }
  319. - (void)testContactsFeed {
  320. TestKeyPathValues tests[] =
  321. {
  322. //
  323. // Contact Feed
  324. //
  325. { @"GDataFeedContact/2.0", @"Tests/FeedContactTest1.xml" },
  326. // GDataFeedContact paths
  327. { @"title", @"Contacts" },
  328. { @"categories.0.term", kGDataCategoryContact },
  329. { @"links.1.rel", kGDataLinkRelPost },
  330. { @"unknownAttributes.@count.stringValue", @"0" },
  331. { @"unknownChildren.@count.stringValue", @"0" },
  332. // GDataEntryContact paths
  333. // First entry is real; second entry is deleted
  334. { @"entries.0.identifier", @"contains:9cfaae9" },
  335. { @"entries.0.categories.0.term", kGDataCategoryContact },
  336. { @"entries.0.isDeleted", @"0" },
  337. { @"entries.0.primaryOrganization.orgName", @"Le Company" },
  338. { @"entries.0.organizations.0.orgName", @"Le Company" },
  339. { @"entries.0.organizations.0.orgTitle", @"Titularstuff" },
  340. { @"entries.0.organizations.0.label", nil },
  341. { @"entries.0.organizations.0.rel", kGDataContactOther },
  342. { @"entries.0.organizations.0.isPrimary", @"1" },
  343. { @"entries.0.organizations.1.orgName", @"Deadhead Associates" },
  344. { @"entries.0.organizations.1.orgTitle", @"Groupie" },
  345. { @"entries.0.organizations.1.label", @"DAz" },
  346. { @"entries.0.organizations.1.rel", nil },
  347. { @"entries.0.organizations.1.isPrimary", @"0" },
  348. { @"entries.0.primaryIMAddress.address", @"fooaimz" },
  349. { @"entries.0.IMAddresses.0.protocol", kGDataIMProtocolAIM },
  350. { @"entries.0.IMAddresses.0.address", @"fooaimz" },
  351. { @"entries.0.IMAddresses.0.label", @"werkz" },
  352. { @"entries.0.IMAddresses.0.isPrimary", @"1" },
  353. { @"entries.0.IMAddresses.1.protocol", kGDataIMProtocolMSN },
  354. { @"entries.0.IMAddresses.1.address", @"foomsn" },
  355. { @"entries.0.IMAddresses.1.label", nil },
  356. { @"entries.0.IMAddresses.1.rel", kGDataContactHome },
  357. { @"entries.0.IMAddresses.1.isPrimary", @"0" },
  358. { @"entries.0.IMAddresses.2.protocol", kGDataIMProtocolGoogleTalk },
  359. { @"entries.0.IMAddresses.2.address", @"foo@gmail.com" },
  360. { @"entries.0.IMAddresses.2.label", nil },
  361. { @"entries.0.IMAddresses.2.rel", kGDataContactOther },
  362. { @"entries.0.IMAddresses.2.isPrimary", @"0" },
  363. { @"entries.0.IMAddresses.3.protocol", kGDataIMProtocolJabber },
  364. { @"entries.0.IMAddresses.3.address", @"foo@jabber.org" },
  365. { @"entries.0.IMAddresses.3.label", @"jabz" },
  366. { @"entries.0.IMAddresses.3.rel", nil },
  367. { @"entries.0.IMAddresses.3.isPrimary", @"0" },
  368. { @"entries.0.primaryPhoneNumber.stringValue", @"123-4567" },
  369. { @"entries.0.phoneNumbers.0.stringValue", @"123-4567" },
  370. { @"entries.0.phoneNumbers.0.label", nil },
  371. { @"entries.0.phoneNumbers.0.rel", kGDataPhoneNumberMobile },
  372. { @"entries.0.phoneNumbers.0.isPrimary", @"1" },
  373. { @"entries.0.phoneNumbers.1.stringValue", @"333-1414" },
  374. { @"entries.0.phoneNumbers.1.label", @"shoefone" },
  375. { @"entries.0.phoneNumbers.1.rel", nil },
  376. { @"entries.0.phoneNumbers.1.isPrimary", @"0" },
  377. { @"entries.0.primaryPostalAddress.stringValue", @"123 Lane St" },
  378. { @"entries.0.postalAddresses.0.stringValue", @"123 Lane St" },
  379. { @"entries.0.postalAddresses.0.label", nil },
  380. { @"entries.0.postalAddresses.0.rel", kGDataContactHome },
  381. { @"entries.0.postalAddresses.0.isPrimary", @"1" },
  382. { @"entries.0.primaryEmailAddress.address", @"foo@bar.com" },
  383. { @"entries.0.emailAddresses.0.address", @"foo@bar.com" },
  384. { @"entries.0.emailAddresses.0.label", nil },
  385. { @"entries.0.emailAddresses.0.rel", kGDataContactHome },
  386. { @"entries.0.emailAddresses.0.isPrimary", @"1" },
  387. { @"entries.0.emailAddresses.1.address", @"2@bar.com" },
  388. { @"entries.0.emailAddresses.1.label", @"norzglie" },
  389. { @"entries.0.emailAddresses.1.rel", nil },
  390. { @"entries.0.emailAddresses.1.isPrimary", @"0" },
  391. { @"entries.0.groupMembershipInfos.0.href", @"http://www.google.com/m8/feeds/contactGroups/user@gmail.com/full/2" },
  392. { @"entries.0.groupMembershipInfos.0.isDeleted", @"1" },
  393. { @"entries.0.extendedProperties.0.name", @"com.mycompany.myprop" },
  394. { @"entries.0.extendedProperties.0.value", @"zoop" },
  395. { @"entries.0.extendedProperties.0.XMLValues", nil },
  396. { @"entries.0.extendedProperties.1.name", @"com.mycompany.myprop2" },
  397. { @"entries.0.extendedProperties.1.value", nil },
  398. { @"entries.0.extendedProperties.1.XMLValues.0.XMLString", @"<myXML><myChild attr=\"nerf\"></myChild></myXML>" },
  399. { @"entries.0.extendedProperties.1.unknownChildren.@count.stringValue", @"0" },
  400. { @"entries.1.identifier", @"contains:b001135" },
  401. { @"entries.1.categories.0.term", kGDataCategoryContact },
  402. { @"entries.1.isDeleted", @"1" },
  403. { @"entries.0.unknownAttributes.@count.stringValue", @"0" },
  404. { @"entries.0.unknownChildren.@count.stringValue", @"0" },
  405. { @"", @"" }, // end of feed
  406. //
  407. // Contact Feed with V3 elements
  408. //
  409. { @"GDataFeedContact/3.0", @"Tests/FeedContactTest2.xml" },
  410. // GDataFeedContact paths
  411. { @"title", @"Fred Flintstone's Contacts" },
  412. { @"categories.0.term", kGDataCategoryContact },
  413. { @"ETag", @"W/\"DkYHQHgzfCt7ImA9WxJREEU.\"" },
  414. { @"unknownAttributes.@count.stringValue", @"0" },
  415. { @"unknownChildren.@count.stringValue", @"0" },
  416. // GDataEntryContact paths
  417. { @"entries.0.identifier", @"contains:754fdf0c0db53ab3" },
  418. { @"entries.0.categories.0.term", kGDataCategoryContact },
  419. { @"entries.0.isDeleted", @"0" },
  420. { @"entries.0.ETag", @"\"Rno_eTVSLyt7ImA9WxJREEUORwc.\"" },
  421. { @"entries.0.editedDate.RFC3339String", @"2009-05-11T23:20:37Z" },
  422. { @"entries.0.primaryOrganization.orgName", @"Acme Corp." },
  423. { @"entries.0.organizations.0.orgName", @"Acme Corp." },
  424. { @"entries.0.organizations.0.orgTitle", nil },
  425. { @"entries.0.organizations.0.label", nil },
  426. { @"entries.0.organizations.0.rel", kGDataContactWork },
  427. { @"entries.0.organizations.0.isPrimary", @"1" },
  428. { @"entries.0.primaryIMAddress.address", nil },
  429. { @"entries.0.IMAddresses.0.protocol", kGDataIMProtocolGoogleTalk },
  430. { @"entries.0.IMAddresses.0.address", @"fredsim@example.com" },
  431. { @"entries.0.IMAddresses.0.label", @"main messaging addr" },
  432. { @"entries.0.IMAddresses.0.rel", nil },
  433. { @"entries.0.IMAddresses.0.isPrimary", @"0" },
  434. { @"entries.0.primaryPhoneNumber.stringValue", @"425-555-1234" },
  435. { @"entries.0.phoneNumbers.0.stringValue", @"425-555-1234" },
  436. { @"entries.0.phoneNumbers.0.label", @"Grand Central" },
  437. { @"entries.0.phoneNumbers.0.rel", nil },
  438. { @"entries.0.phoneNumbers.0.isPrimary", @"1" },
  439. { @"entries.0.phoneNumbers.1.stringValue", @"425-555-0000" },
  440. { @"entries.0.phoneNumbers.1.label", nil },
  441. { @"entries.0.phoneNumbers.1.rel", kGDataPhoneNumberCar },
  442. { @"entries.0.phoneNumbers.1.isPrimary", @"0" },
  443. { @"entries.0.primaryStructuredPostalAddress.street", @"301 Cobblestone Way" },
  444. { @"entries.0.structuredPostalAddresses.0.street", @"301 Cobblestone Way" },
  445. { @"entries.0.structuredPostalAddresses.0.postCode", @"12345" },
  446. { @"entries.0.structuredPostalAddresses.0.formattedAddress", @"301 Cobblestone Way\nBedrock, CA 12345\nUnited States" },
  447. { @"entries.0.structuredPostalAddresses.0.region", @"CA" },
  448. { @"entries.0.structuredPostalAddresses.0.countryName", @"United States" },
  449. { @"entries.0.structuredPostalAddresses.0.label", nil },
  450. { @"entries.0.structuredPostalAddresses.0.rel", kGDataContactHome },
  451. { @"entries.0.structuredPostalAddresses.0.isPrimary", @"1" },
  452. { @"entries.0.primaryEmailAddress.address", @"fred@example.com" },
  453. { @"entries.0.emailAddresses.0.address", @"fred@example.com" },
  454. { @"entries.0.emailAddresses.0.label", nil },
  455. { @"entries.0.emailAddresses.0.rel", kGDataContactHome },
  456. { @"entries.0.emailAddresses.0.isPrimary", @"1" },
  457. { @"entries.0.groupMembershipInfos.0.href", @"http://www.google.com/m8/feeds/groups/fredflintstone%40example.com/base/6" },
  458. { @"entries.0.groupMembershipInfos.0.isDeleted", @"0" },
  459. { @"entries.0.extendedProperties.0.name", @"fredprop" },
  460. { @"entries.0.extendedProperties.0.value", @"12345" },
  461. { @"entries.0.extendedProperties.0.XMLValues", nil },
  462. { @"entries.0.billingInformation", @"account overdue" },
  463. { @"entries.0.birthday", @"1990-12-01" },
  464. { @"entries.0.birthdayDate.timeIntervalSince1970", @"660052800" },
  465. { @"entries.0.calendarLinks.0.rel", nil },
  466. { @"entries.0.calendarLinks.0.label", @"full calendar" },
  467. { @"entries.0.calendarLinks.0.href", @"http://www.google.com/calendar/render" },
  468. { @"entries.0.primaryCalendarLink.label", @"full calendar" },
  469. { @"entries.0.directoryServer", @"dir server" },
  470. // { @"entries.0.events.0", @"" },
  471. { @"entries.0.externalIDs.0.label", @"ext id" },
  472. { @"entries.0.externalIDs.0.rel", nil },
  473. { @"entries.0.externalIDs.0.stringValue", @"54321" },
  474. { @"entries.0.gender", @"male" },
  475. { @"entries.0.hobbies.0.stringValue", @"gurgling" },
  476. { @"entries.0.initials", @"F.F." },
  477. { @"entries.0.jots.0.rel", kGDataContactJotHome },
  478. { @"entries.0.jots.0.stringValue", @"1248" },
  479. // { @"entries.0.languages.0", @"" },
  480. { @"entries.0.maidenName", @"Marshovitzky" },
  481. { @"entries.0.mileage", @"42 miles" },
  482. { @"entries.0.name.fullName", @"Fred Flintstone" },
  483. { @"entries.0.name.givenName", @"Fred" },
  484. { @"entries.0.name.familyName", @"Flintstone" },
  485. { @"entries.0.nickname", @"Rocks" },
  486. { @"entries.0.occupation", @"TV Personality" },
  487. { @"entries.0.priority", kGDataContactPriorityLow },
  488. { @"entries.0.relations.0.rel", kGDataContactRelationPartner },
  489. { @"entries.0.relations.0.label", nil },
  490. { @"entries.0.relations.0.stringValue", @"Wilma" },
  491. { @"entries.0.sensitivity", kGDataContactSensitivityNormal },
  492. { @"entries.0.shortName", @"Freddy" },
  493. { @"entries.0.subject", @"subject val" },
  494. { @"entries.0.userDefinedFields.0.key", @"Cat" },
  495. { @"entries.0.userDefinedFields.0.stringValue", @"Cheezeburger" },
  496. { @"entries.0.websiteLinks.0.href", @"http://example.com/site.html" },
  497. { @"entries.0.websiteLinks.0.rel", kGDataContactWebsiteLinkHomePage },
  498. { @"entries.0.websiteLinks.0.label", nil },
  499. { @"entries.0.websiteLinks.0.isPrimary", @"0" },
  500. { @"entries.0.where", @"The Quarry" },
  501. { @"entries.0.unknownAttributes.@count.stringValue", @"0" },
  502. { @"entries.0.unknownChildren.@count.stringValue", @"0" },
  503. { @"", @"" }, // end of feed
  504. { nil, nil } // end of test array
  505. };
  506. [self runTests:tests];
  507. }
  508. - (void)testSpreadsheetFeeds {
  509. TestKeyPathValues tests[] =
  510. {
  511. //
  512. // Spreadsheet feed (list of user's spreadsheets)
  513. //
  514. { @"GDataFeedSpreadsheet", @"Tests/FeedSpreadsheetTest1.xml" },
  515. // feed paths
  516. { @"identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full" },
  517. { @"links.2.href", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full?tfe=" },
  518. { @"title", @"Available Spreadsheets - test@foo.net" },
  519. { @"unknownAttributes.@count", @"0" },
  520. { @"unknownChildren.@count", @"0" },
  521. // entry paths
  522. // There is one entry
  523. { @"entries.0.identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full/o04181601172097104111.497668944883620000" },
  524. { @"entries.0.updatedDate.RFC3339String", @"2007-03-22T23:25:53Z" },
  525. { @"entries.0.categories.2.scheme", kGDataCategorySchemeSpreadsheet },
  526. { @"entries.0.categories.2.term", kGDataCategorySpreadsheet },
  527. { @"entries.0.title", @"My Test Spreadsheet" },
  528. { @"entries.0.unknownAttributes.@count", @"0" },
  529. { @"entries.0.unknownChildren.@count", @"1" },
  530. { @"", @"" }, // end of feed
  531. // repeat the test, with unknown children turned off
  532. { @"GDataFeedSpreadsheet-ignoreUnknown", @"Tests/FeedSpreadsheetTest1.xml" },
  533. // feed paths
  534. { @"identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full" },
  535. { @"unknownAttributes.@count", @"0" },
  536. { @"unknownChildren.@count", @"0" },
  537. // entry paths
  538. // There is one entry
  539. { @"entries.0.identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full/o04181601172097104111.497668944883620000" },
  540. { @"entries.0.updatedDate.RFC3339String", @"2007-03-22T23:25:53Z" },
  541. { @"entries.0.unknownAttributes.@count", @"0" },
  542. { @"entries.0.unknownChildren.@count", @"0" },
  543. { @"", @"" }, // end of feed
  544. //
  545. // Worksheet feed (list of a spreadsheet's worksheets)
  546. //
  547. { @"GDataFeedWorksheet", @"Tests/FeedSpreadsheetWorksheetTest1.xml" },
  548. // feed paths
  549. { @"identifier", @"http://spreadsheets.google.com/feeds/worksheets/o04181601172097104111.497668944883620000/private/full" },
  550. { @"links.2.href", @"http://spreadsheets.google.com/feeds/worksheets/o04181601172097104111.497668944883620000/private/full?tfe=" },
  551. { @"title", @"My Test Spreadsheet" },
  552. { @"authors.0.email", @"test@foo.net" },
  553. { @"unknownAttributes.@count", @"0" },
  554. { @"unknownChildren.@count", @"0" },
  555. // entry paths
  556. // There is one entry
  557. { @"entries.0.identifier", @"http://spreadsheets.google.com/feeds/worksheets/o04181601172097104111.497668944883620000/private/full/od6" },
  558. { @"entries.0.updatedDate.RFC3339String", @"2007-03-22T23:28:50Z" },
  559. { @"entries.0.categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  560. { @"entries.0.categories.0.term", kGDataCategoryWorksheet },
  561. { @"entries.0.title", @"Sheet1" },
  562. { @"entries.0.rowCount", @"100" },
  563. { @"entries.0.columnCount", @"20" },
  564. { @"entries.0.unknownAttributes.@count", @"0" },
  565. { @"entries.0.unknownChildren.@count", @"0" },
  566. { @"", @"" }, // end of feed
  567. //
  568. // Cells feed (all of a worksheet's cells)
  569. //
  570. { @"GDataFeedSpreadsheetCell", @"Tests/FeedSpreadsheetCellsTest1.xml" },
  571. // feed paths
  572. { @"identifier", @"http://spreadsheets.google.com/feeds/cells/o04181601172097104111.497668944883620000/od6/private/full" },
  573. { @"links.0.href", @"http://spreadsheets.google.com/ccc?key=o04181601172097104111.497668944883620000" },
  574. { @"categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  575. { @"categories.0.term", kGDataCategorySpreadsheetCell },
  576. { @"title", @"Sheet1" },
  577. { @"authors.0.email", @"test@foo.net" },
  578. { @"rowCount", @"100" },
  579. { @"columnCount", @"20" },
  580. { @"unknownAttributes.@count", @"0" },
  581. { @"unknownChildren.@count", @"0" },
  582. // entry paths
  583. // The sheet looks like this (2 cols x 4 rows)
  584. // Fred Martha
  585. // =pi() =sin(A2)
  586. // =1.5*pi() =sin(A3)
  587. // =2.0*pi() =sin(A4)
  588. { @"entries.1.identifier", @"http://spreadsheets.google.com/feeds/cells/o04181601172097104111.497668944883620000/od6/private/full/R1C2" },
  589. { @"entries.1.updatedDate.RFC3339String", @"2007-03-22T23:28:50Z" },
  590. { @"entries.1.categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  591. { @"entries.1.categories.0.term", kGDataCategorySpreadsheetCell },
  592. { @"entries.1.title", @"B1" },
  593. { @"entries.1.cell.column", @"2" },
  594. { @"entries.1.cell.row", @"1" },
  595. { @"entries.1.cell.inputString", @"Martha" },
  596. { @"entries.1.cell.numericValue", nil },
  597. { @"entries.1.cell.resultString", @"Martha" },
  598. { @"entries.0.unknownAttributes.@count", @"0" },
  599. { @"entries.0.unknownChildren.@count", @"0" },
  600. { @"", @"" }, // end of feed
  601. //
  602. // List feed (all of a worksheet as a list) which contains customElements
  603. //
  604. // feed paths
  605. { @"GDataFeedSpreadsheetList", @"Tests/FeedSpreadsheetListTest1.xml" },
  606. { @"identifier", @"http://spreadsheets.google.com/feeds/list/o04181601172097104111.497668944883620000/od6/private/full" },
  607. { @"links.0.href", @"http://spreadsheets.google.com/ccc?key=o04181601172097104111.497668944883620000" },
  608. { @"categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  609. { @"categories.0.term", kGDataCategorySpreadsheetList },
  610. { @"title", @"Sheet1" },
  611. { @"authors.0.email", @"test@foo.net" },
  612. { @"unknownAttributes.@count", @"0" },
  613. { @"unknownChildren.@count", @"0" },
  614. // entry paths
  615. { @"entries.1.customElementDictionary.fred", @"4.71238898038469" },
  616. { @"entries.1.customElementDictionary.martha", @"-1" },
  617. { @"entries.0.unknownAttributes.@count", @"0" },
  618. { @"entries.0.unknownChildren.@count", @"0" },
  619. { @"", @"" }, // end of feed
  620. //
  621. // Table feed
  622. //
  623. // feed paths
  624. { @"GDataFeedSpreadsheetTable", @"Tests/FeedSpreadsheetTableTest1.xml" },
  625. { @"identifier", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/tables" },
  626. { @"categories.0.scheme", kGDataCategoryScheme },
  627. { @"categories.0.term", kGDataCategorySpreadsheetTable },
  628. { @"title", @"Table of Doom" },
  629. { @"authors.0.email", @"fredflintstone@example.com" },
  630. { @"unknownAttributes.@count", @"0" },
  631. { @"unknownChildren.@count", @"0" },
  632. // entry paths
  633. { @"entries.0.content.sourceURI", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/records/1" },
  634. { @"entries.0.spreadsheetData.startIndex", @"4" },
  635. { @"entries.0.spreadsheetData.numberOfRows", @"3" },
  636. { @"entries.0.spreadsheetData.insertionMode", kGDataSpreadsheetModeInsert },
  637. { @"entries.0.spreadsheetData.columns.0.name", @"Column Beta" },
  638. { @"entries.0.spreadsheetData.columns.0.indexString", @"B" },
  639. { @"entries.0.spreadsheetHeader.row", @"3" },
  640. { @"entries.0.worksheetName", @"Sheet 1" },
  641. { @"entries.0.unknownAttributes.@count", @"0" },
  642. { @"entries.0.unknownChildren.@count", @"0" },
  643. { @"", @"" }, // end of feed
  644. //
  645. // Record feed
  646. //
  647. // feed paths
  648. { @"GDataFeedSpreadsheetRecord", @"Tests/FeedSpreadsheetRecordTest1.xml" },
  649. { @"identifier", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/records/1" },
  650. { @"categories.0.scheme", kGDataCategoryScheme },
  651. { @"categories.0.term", kGDataCategorySpreadsheetRecord },
  652. { @"title", @"Records of Doom" },
  653. { @"authors.0.email", @"fredflintstone@example.com" },
  654. { @"unknownAttributes.@count", @"0" },
  655. { @"unknownChildren.@count", @"0" },
  656. // entry paths
  657. { @"entries.0.content", @"Column Beta: clouds, Column Alpha: mars" },
  658. { @"entries.0.editLink.href", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/records/1/cn6ca" },
  659. { @"entries.0.fields.0.name", @"Column Beta" },
  660. { @"entries.0.fields.0.indexString", @"B" },
  661. { @"entries.0.fields.0.value", @"clouds" },
  662. { @"entries.0.fields.0.formula", @"3+something" },
  663. { @"entries.0.unknownAttributes.@count", @"0" },
  664. { @"entries.0.unknownChildren.@count", @"0" },
  665. { @"", @"" }, // end of feed
  666. { nil, nil } // end of test array
  667. };
  668. [self runTests:tests];
  669. }
  670. - (void)testAnalyticsFeeds {
  671. TestKeyPathValues tests[] =
  672. {
  673. //
  674. // Account feed
  675. //
  676. { @"GDataFeedAnalyticsAccount/2.0", @"Tests/FeedAnalyticsAccountTest1.xml" },
  677. // GDataFeedAnalyticsAccount paths
  678. { @"authors.0.name", @"Google Analytics" },
  679. { @"title", @"Profile list for fredflintstone@example.com" },
  680. { @"segments.0.name", @"All Visits" },
  681. { @"segments.0.analyticsID", @"gaid::-1" },
  682. { @"segments.0.definition", @"" },
  683. { @"segments.1.definition", @"ga:visitorType==New Visitor" },
  684. // GDataEntryAnalyticsAccount paths
  685. { @"entries.0.tableID", @"ga:7966084" },
  686. { @"entries.0.analyticsProperties.0.name", @"ga:accountId" },
  687. { @"entries.0.analyticsProperties.0.stringValue", @"8925159" },
  688. { @"entries.0.analyticsProperties.1.name", @"ga:accountName" },
  689. { @"entries.0.analyticsProperties.1.stringValue", @"example" },
  690. { @"entries.0.customVariables.0.index", @"3" },
  691. { @"entries.0.customVariables.0.name", @"User" },
  692. { @"entries.0.customVariables.0.scope", @"visitor" },
  693. { @"entries.0.goals.0.isActive", @"1" },
  694. { @"entries.0.goals.0.name", @"My Main Goal" },
  695. { @"entries.0.goals.0.number", @"1" },
  696. { @"entries.0.goals.0.value", @"1.100000023841858" },
  697. { @"entries.0.goals.0.destination.isCaseSensitive", @"0" },
  698. { @"entries.0.goals.0.destination.expression", @"/wiki/DocPage" },
  699. { @"entries.0.goals.0.destination.matchType", @"head" },
  700. { @"entries.0.goals.0.destination.isStep1Required", @"0" },
  701. { @"entries.0.goals.0.destination.steps.0.name", @"Wiki step" },
  702. { @"entries.0.goals.0.destination.steps.0.number", @"1" },
  703. { @"entries.0.goals.0.destination.steps.0.path", @"/wiki" },
  704. { @"entries.0.goals.0.engagement", nil },
  705. { @"", @"" }, // end of feed
  706. //
  707. // Data feed
  708. //
  709. { @"GDataFeedAnalyticsData/2.0", @"Tests/FeedAnalyticsDataTest1.xml" },
  710. // GDataFeedAnalyticsData paths
  711. { @"authors.0.name", @"Google Analytics" },
  712. { @"title", @"Google Analytics Data for Profile 7966084" },
  713. { @"startDateString", @"2009-05-18" },
  714. { @"endDateString", @"2009-05-20" },
  715. { @"aggregateGroup.metrics.0.confidenceInterval", @"0" },
  716. { @"aggregateGroup.metrics.0.name", @"ga:pageviews" },
  717. { @"aggregateGroup.metrics.0.type", kGDataMetricTypeInteger },
  718. { @"aggregateGroup.metrics.0.stringValue", @"12" },
  719. { @"aggregateGroup.metrics.0.doubleValue", @"12" },
  720. { @"dataSources.0.tableID", @"ga:7966084" },
  721. { @"dataSources.0.tableName", @"www.example.net" },
  722. { @"dataSources.0.analyticsProperties.0.name", @"ga:profileId" },
  723. { @"dataSources.0.analyticsProperties.0.stringValue", @"7966084" },
  724. { @"dataSources.0.analyticsPropertyWithNameAccountName.stringValue", @"example" },
  725. { @"segments.0.name", @"New Visitors" },
  726. { @"segments.0.analyticsID", @"gaid::-2" },
  727. { @"segments.0.definition", @"ga:visitorType==New Visitor" },
  728. // GDataEntryAnalyticsData paths
  729. { @"entries.0.title", @"ga:country=United States" },
  730. { @"entries.0.dimensions.0.name", @"ga:country" },
  731. { @"entries.0.dimensions.0.stringValue", @"United States" },
  732. { @"entries.0.dimensionWithNameCountry.stringValue", @"United States" },
  733. { @"entries.0.metrics.0.confidenceInterval", @"5.1" },
  734. { @"entries.0.metrics.0.name", @"ga:pageviews" },
  735. { @"entries.0.metrics.0.type", kGDataMetricTypeInteger },
  736. { @"entries.0.metrics.0.stringValue", @"37" },
  737. { @"entries.0.metrics.0.doubleValue", @"37" },
  738. { @"entries.0.metricWithNamePageviews.stringValue", @"37" },
  739. { @"", @"" }, // end of feed
  740. { nil, nil } // end of test array
  741. };
  742. [self runTests:tests];
  743. }
  744. - (void)testCodeSearchFeed {
  745. TestKeyPathValues tests[] =
  746. {
  747. //
  748. // Feed of a user's albums
  749. //
  750. { @"GDataFeedCodeSearch", @"Tests/FeedCodeSearchTest1.xml" },
  751. // GDataFeedCodeSearch paths
  752. { @"authors.0.name", @"Google Code Search" },
  753. { @"authors.0.URI", @"http://www.google.com/codesearch" },
  754. // GDataEntryCodeSearch paths
  755. { @"entries.0.package.name", @"http://ftp.funet.fi/pub/CPAN/src/perl-5.9.1.tar.gz" },
  756. { @"entries.0.package.URI", @"http://ftp.funet.fi/pub/CPAN/src/perl-5.9.1.tar.gz" },
  757. { @"entries.1.package.name", @"http://gentoo.osuosl.org/distfiles/Perl6-Pugs-6.2.12.tar.gz" },
  758. { @"entries.1.package.URI", @"http://gentoo.osuosl.org/distfiles/Perl6-Pugs-6.2.12.tar.gz" },
  759. { @"entries.1.file.name", @"Perl6-Pugs-6.2.12/t/subroutines/sub_named_params.t" },
  760. { @"entries.1.matches.0.lineNumberString", @"131" },
  761. { @"entries.1.matches.0.type", @"text/html" },
  762. { @"entries.1.matches.0", @"hasPrefix:<pre>my %fellowship" },
  763. { @"entries.1.matches.1.lineNumberString", @"132" },
  764. { @"entries.1.matches.1.type", @"text/html" },
  765. { @"entries.1.matches.1", @"hasPrefix:<pre>is(%fellowship&lt;hobbit&gt;" },
  766. { @"", @"" }, // end of feed
  767. { nil, nil } // end of test array
  768. };
  769. [self runTests:tests];
  770. }
  771. - (void)testPhotosFeeds {
  772. // TODO: test geoLocation once we have a good sample of it
  773. // Test a non-ASCII character and some html characters in a TextConstruct.
  774. // We'll allocate it dynamically since source code cannot contain non-ASCII.
  775. NSString *templateStr = @"Test %C Alb%Cm";
  776. NSString *photoAlbumName = [NSString stringWithFormat:templateStr,
  777. 0x262F, 0x00FC]; // yin yang, u with umlaut
  778. // Non-ascii photo description, includes the Wheel of Dharma
  779. NSString *photoDescriptionText = [NSString stringWithFormat:
  780. @"Caption for the car %C photo", 0x2638];
  781. TestKeyPathValues tests[] =
  782. {
  783. //
  784. // Feed of a user's albums
  785. //
  786. { @"GDataFeedPhotoUser", @"Tests/FeedPhotosUserAlbum1.xml" },
  787. // GDataFeedPhotosAlbum paths
  788. { @"username", @"TestdomainTestAccount" },
  789. { @"nickname", @"Greg" },
  790. { @"thumbnail", @"hasPrefix:http://lh3.google.com/image/TestdomainTestAccount" },
  791. { @"quotaLimit", @"1073741824" },
  792. { @"quotaUsed", @"108303" },
  793. { @"maxPhotosPerAlbum", @"500" },
  794. { @"categories.0.term", kGDataCategoryPhotosUser },
  795. { @"unknownAttributes.@count", @"0" },
  796. { @"unknownChildren.@count", @"0" },
  797. // GDataEntryPhotoAlbum paths
  798. { @"entries.0.categories.0.term", kGDataCategoryPhotosAlbum },
  799. { @"entries.0.mediaGroup.mediaTitle", photoAlbumName },
  800. { @"entries.0.mediaGroup.mediaDescription", @"Album description" },
  801. { @"entries.0.mediaGroup.mediaCredits.0", @"Greg" },
  802. { @"entries.0.mediaGroup.mediaContents.0.medium", @"image" },
  803. { @"entries.0.mediaGroup.mediaContents.0.type", @"image/jpeg" },
  804. { @"entries.0.mediaGroup.mediaContents.0.URLString", @"hasPrefix:http://lh5.google.com/image/TestdomainTestAccount" },
  805. { @"entries.0.mediaGroup.mediaThumbnails.0.height", @"160" },
  806. { @"entries.0.mediaGroup.mediaThumbnails.0.URLString", @"hasPrefix:http://lh5.google.com/image/TestdomainTestAccount" },
  807. { @"entries.0.GPhotoID", @"5067143575034336993" },
  808. { @"entries.0.access", @"public" },
  809. { @"entries.0.photosUsed", @"2" },
  810. { @"entries.0.commentCount", @"0" },
  811. { @"entries.0.bytesUsed", @"108303" },
  812. { @"entries.0.nickname", @"Greg" },
  813. { @"entries.0.photosLeft", @"498" },
  814. { @"entries.0.commentsEnabled", @"1" },
  815. { @"entries.0.location", @"Album Site" },
  816. { @"entries.0.timestamp.dateValue.timeIntervalSince1970", @"1179730800" },
  817. { @"entries.0.username", @"TestdomainTestAccount" },
  818. { @"entries.0.identifier", @"http://photos.googleapis.com/data/entry/api/user/TestdomainTestAccount/albumid/5067143575034336993" },
  819. { @"entries.0.title.type", @"text" },
  820. { @"entries.0.title", photoAlbumName },
  821. { @"entries.0.photoDescription", @"Album description" },
  822. { @"entries.0.rightsString", @"public" },
  823. { @"entries.0.unknownAttributes.@count", @"0" },
  824. { @"entries.0.unknownChildren.@count", @"0" },
  825. { @"", @"" }, // end of feed
  826. //
  827. // Feed of an album's photos
  828. //
  829. { @"GDataFeedPhotoAlbum/2.0", @"Tests/FeedPhotosAlbumPhoto1.xml" },
  830. // GDataFeedPhotoAlbum - feed paths
  831. { @"GPhotoID", @"5067143575034336993" },
  832. { @"access", @"public" },
  833. { @"photosUsed", @"2" },
  834. { @"commentCount", @"0" },
  835. { @"bytesUsed", @"108303" },
  836. { @"nickname", @"Greg" },
  837. { @"photosLeft", @"498" },
  838. { @"commentsEnabled", @"1" },
  839. { @"location", @"Album Site" },
  840. { @"timestamp.dateValue.timeIntervalSince1970", @"1179730800" },
  841. { @"username", @"TestdomainTestAccount" },
  842. { @"identifier", @"http://photos.googleapis.com/data/feed/api/user/test%40testdomain.net/albumid/5067143575034336993" },
  843. { @"title.type", @"text" },
  844. { @"title", photoAlbumName },
  845. { @"photoDescription", @"Album description" },
  846. { @"rights", @"public" },
  847. { @"categories.0.term", kGDataCategoryPhotosAlbum },
  848. { @"feedLink.href", @"contains:albumid/5067143575034336993" },
  849. { @"feedLink.rel", kGDataLinkRelFeed },
  850. { @"postLink.href", @"contains:albumid/5067143575034336993" },
  851. { @"postLink.rel", kGDataLinkRelPost },
  852. { @"alternateLink.href", @"contains:/TestAlbM" },
  853. { @"alternateLink.rel", @"alternate" },
  854. { @"selfLink.href", @"contains:test%40testdomain.net/albumid/5067143575034336993?start-index=1" },
  855. { @"selfLink.rel", @"self" },
  856. { @"firstEntry.GPhotoID", @"5067143579329304306" },
  857. { @"unknownAttributes.@count", @"0" },
  858. { @"unknownChildren.@count", @"0" },
  859. // GDataEntryPhoto - entry paths
  860. { @"entries.0.categories.0.term", kGDataCategoryPhotosPhoto },
  861. { @"entries.0.checksum", @"23512309abbs298" },
  862. { @"entries.0.GPhotoID", @"5067143579329304306" },
  863. { @"entries.0.albumID", @"5067143575034336993" },
  864. { @"entries.0.width", @"660" },
  865. { @"entries.0.height", @"433" },
  866. { @"entries.0.videoStatus", kGDataPhotoStatusReady },
  867. { @"entries.0.commentsEnabled", @"1" },
  868. { @"entries.0.size", @"87225" },
  869. { @"entries.0.commentCount", @"1" },
  870. { @"entries.0.timestamp.dateValue.timeIntervalSince1970", @"1179786301" },
  871. { @"entries.0.title", @"Car.jpg" },
  872. { @"entries.0.photoDescription", photoDescriptionText },
  873. { @"entries.0.content.sourceURI", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg" },
  874. { @"entries.0.content.type", @"image/jpeg" },
  875. { @"entries.0.mediaGroup.mediaTitle", @"Car.jpg" },
  876. { @"entries.0.mediaGroup.mediaDescription", photoDescriptionText },
  877. { @"entries.0.mediaGroup.mediaCredits.0", @"Greg" },
  878. { @"entries.0.mediaGroup.mediaContents.0.medium", @"image" },
  879. { @"entries.0.mediaGroup.mediaContents.0.type", @"image/jpeg" },
  880. { @"entries.0.mediaGroup.mediaContents.0.URLString", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg" },
  881. { @"entries.0.mediaGroup.mediaThumbnails.0.height", @"47" },
  882. { @"entries.0.mediaGroup.mediaThumbnails.0.width", @"72" },
  883. { @"entries.0.mediaGroup.mediaThumbnails.0.URLString", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg?imgmax=72" },
  884. { @"entries.0.mediaGroup.mediaKeywords", @"headlight, red car" },
  885. { @"entries.0.EXIFTags.tagDictionary.exposure", @"0.0080" },
  886. { @"entries.0.EXIFTags.tagDictionary.imageUniqueID", @"d8a9e8fd57a384d216f4b2a853d654fc" },
  887. { @"entries.0.editMediaLink.href", @"contains:5067143579329304306" },
  888. { @"entries.0.editMediaLink.type", @"image/jpeg" },
  889. { @"entries.0.alternateLink.href", @"contains:photo#5067143579329304306" },
  890. { @"entries.0.alternateLink.type", kGDataLinkTypeHTML },
  891. { @"entries.0.HTMLLink.href", @"contains:photo#5067143579329304306" },
  892. { @"entries.0.selfLink.href", @"contains:photoid/5067143579329304306" },
  893. { @"entries.0.selfLink.type", kGDataLinkTypeAtom },
  894. { @"entries.0.feedLink.href", @"contains:photoid/5067143579329304306" },
  895. { @"entries.0.feedLink.type", kGDataLinkTypeAtom },
  896. { @"entries.0.unknownAttributes.@count", @"0" },
  897. { @"entries.0.unknownChildren.@count", @"0" },
  898. { @"", @"" }, // end of feed
  899. //
  900. // Feed of a photo's comments
  901. //
  902. { @"GDataFeedPhoto/2.0", @"Tests/FeedPhotosPhotoComment1.xml" },
  903. // GDataFeedPhoto - feed paths
  904. { @"generator.URI", @"http://photos.google.com/" },
  905. { @"generator.name", @"Google Photos" },
  906. { @"generator.version", @"1.00" },
  907. { @"EXIFTags.tagDictionary.exposure", @"0.0080" },
  908. { @"categories.0.term", kGDataCategoryPhotosPhoto },
  909. { @"EXIFTags.tagDictionary.imageUniqueID", @"d8a9e8fd57a384d216f4b2a853d654fc" },
  910. { @"checksum", @"23512309abbs298" },
  911. { @"GPhotoID", @"5067143579329304306" },
  912. { @"albumID", @"5067143575034336993" },
  913. { @"width", @"660" },
  914. { @"height", @"433" },
  915. { @"commentsEnabled", @"1" },
  916. { @"size", @"87225" },
  917. { @"commentCount", @"1" },
  918. { @"timestamp.dateValue.timeIntervalSince1970", @"1179786301" },
  919. { @"title", @"Car.jpg" },
  920. { @"photoDescription", photoDescriptionText },
  921. { @"icon", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg?imgmax=288" },
  922. { @"unknownAttributes.@count", @"0" },
  923. { @"unknownChildren.@count", @"0" },
  924. // GDataEntryPhotoComment - entry paths
  925. { @"entries.0.photoID", @"5067143579329304306" },
  926. { @"entries.0.GPhotoID", @"5067146044640532244" },
  927. { @"entries.0.categories.0.term", kGDataCategoryPhotosComment },
  928. { @"entries.0.unknownAttributes.@count", @"0" },
  929. { @"entries.0.unknownChildren.@count", @"0" },
  930. { @"", @"" }, // end of feed
  931. //
  932. // Feed of a user's tags
  933. //
  934. // GDataFeedPhotoUser - feed paths
  935. { @"GDataFeedPhotoUser", @"Tests/FeedPhotosUserTag1.xml" },
  936. { @"username", @"TestdomainTestAccount" },
  937. { @"nickname", @"Greg" },
  938. { @"thumbnail", @"hasPrefix:http://lh3.google.com/image/TestdomainTestAccount" },
  939. { @"quotaLimit", @"1073741824" },
  940. { @"quotaUsed", @"108303" },
  941. { @"maxPhotosPerAlbum", @"500" },
  942. { @"categories.0.term", kGDataCategoryPhotosUser },
  943. { @"unknownAttributes.@count", @"0" },
  944. { @"unknownChildren.@count", @"0" },
  945. // GDataEntryPhotoTag - entry paths
  946. { @"entries.0.title", @"headlight" },
  947. { @"entries.0.photoDescription", @"headlight" },
  948. { @"entries.0.categories.0.term", kGDataCategoryPhotosTag },
  949. { @"entries.0.unknownAttributes.@count", @"0" },
  950. { @"entries.0.unknownChildren.@count", @"0" },
  951. { @"entries.1.title", @"red car" },
  952. { @"entries.1.photoDescription", @"red car" },
  953. { @"entries.1.categories.0.term", kGDataCategoryPhotosTag },
  954. { @"entries.1.unknownAttributes.@count", @"0" },
  955. { @"entries.1.unknownChildren.@count", @"0" },
  956. { @"", @"" }, // end of feed
  957. //
  958. // Feed of a user entry
  959. //
  960. // This is really a fake feed created by requesting just a single
  961. // user entry from the picasa server, using
  962. // GET http://photos.googleapis.com/data/entry/api/user/<username>
  963. //
  964. // GDataFeedPhotoUser - feed paths (none)
  965. // GDataEntryPhotoUser - entry paths
  966. { @"GDataFeedPhotoUser", @"Tests/FeedPhotosUserEntry1.xml" },
  967. { @"entries.0.nickname", @"Greg" },
  968. { @"entries.0.username", @"TestdomainTestAccount" },
  969. { @"entries.0.thumbnail", @"hasPrefix:http://lh3.google.com/image/TestdomainTestAccount/AAAAUbcFQeo" },
  970. { @"entries.0.identifier", @"http://photos.googleapis.com/data/entry/api/user/TestdomainTestAccount" },
  971. { @"entries.0.categories.0.term", kGDataCategoryPhotosUser },
  972. { @"entries.0.unknownAttributes.@count", @"0" },
  973. { @"entries.0.unknownChildren.@count", @"0" },
  974. { @"", @"" }, // end of feed
  975. //
  976. // Feed of search results
  977. //
  978. // feed paths
  979. { @"GDataFeedPhoto/2.0", @"Tests/FeedPhotosSearch1.xml" },
  980. { @"title", @"Search Results" },
  981. // entry paths
  982. { @"entries.0.title", @"Leangi_Pima_Shetland_Sheepdog_puppies_f2_3d_4.jpg" },
  983. { @"entries.0.GPhotoID", @"5310251879415742162" },
  984. { @"entries.0.albumID", @"5310242183362606433" },
  985. { @"entries.0.albumTitle", @"Shetland Sheepdog - B-litter - Belinda Mali Zmaj & Marvithall Sherwood" },
  986. { @"entries.0.albumDescription", @"Leangi Pima Shetland Sheepdog puppies" },
  987. { @"entries.0.location", @"Belgrade, Serbia, Leangi Pima kennel" },
  988. { @"entries.0.snippet", @"... <b>puppies</b> ..." },
  989. { @"entries.0.snippetType", kGDataPhotoSnippetTypePhotoTags },
  990. { @"entries.0.truncated", @"0" },
  991. { @"", @"" }, // end of feed
  992. { nil, nil } // end of test array
  993. };
  994. [self runTests:tests];
  995. }
  996. - (void)testWebmasterToolsFeeds {
  997. TestKeyPathValues tests[] =
  998. {
  999. //
  1000. // Feed of a user's sites
  1001. //
  1002. { @"GDataFeedSite", @"Tests/FeedWebmasterToolsSite1.xml" },
  1003. { @"identifier", @"http://www.google.com/webmasters/tools/feeds/sites" },
  1004. // GDataEntrySite methods
  1005. { @"entries.0.categories.0.term", kGDataCategorySiteInfo },
  1006. { @"entries.0.isIndexed", @"1" },
  1007. { @"entries.0.crawledDate.date.timeIntervalSince1970", @"1206358560" },
  1008. { @"entries.0.isVerified", @"1" },
  1009. { @"entries.0.verificationMethods.@count", @"2" },
  1010. { @"entries.0.verificationMethods.0.type", kGDataSiteVerificationMethodMetatag },
  1011. { @"entries.0.verificationMethods.0.isInUse", @"0" },
  1012. { @"entries.0.verificationMethods.1.type", kGDataSiteVerificationMethodHTMLPage },
  1013. { @"entries.0.verificationMethods.1.isInUse", @"1" },
  1014. { @"entries.0.verificationMethods.1.value", @"google28a5eb30440fabf0.html" },
  1015. { @"entries.0.verificationMethodInUse.value", @"google28a5eb30440fabf0.html" },
  1016. { @"entries.0.verificationEntryLink.href", @"contains:/http%3A%2F%2Fwww.domain.com%2F/verification" },
  1017. { @"entries.0.sitemapsEntryLink.href", @"contains:/http%3A%2F%2Fwww.domain.com%2F/sitemaps" },
  1018. { @"entries.0.geoLocation", @"US" },
  1019. { @"entries.0.preferredDomain", kGDataSiteCrawlPreferredDomainNone },
  1020. { @"entries.0.crawlRate", kGDataSiteCrawlRateNormal },
  1021. { @"entries.0.hasEnhancedImageSearch", @"1" },
  1022. { @"entries.0.entryLinks.@count", @"2" },
  1023. { @"", @"" }, // end of feed
  1024. //
  1025. // Feed of a site's sitemaps
  1026. //
  1027. { @"GDataFeedSitemap", @"Tests/FeedWebmasterToolsSitemap1.xml" },
  1028. { @"identifier", @"contains:http%3A%2F%2Fwww.domain.com%2F/sitemaps" },
  1029. { @"sitemapNews.publicationLabels.@count", @"3" },
  1030. { @"sitemapNews.publicationLabels.2.stringValue", @"a third publabel" },
  1031. { @"sitemapMobile.markupLanguages.@count", @"3" },
  1032. { @"sitemapMobile.markupLanguages.2.stringValue", @"cHTML" },
  1033. // GDataEntrySitemap methods
  1034. { @"entries.0.categories.0.term", kGDataCategorySitemapRegular },
  1035. { @"entries.0.sitemapType", @"WEB" },
  1036. { @"entries.0.sitemapStatus", @"Pending" },
  1037. { @"entries.0.lastDownloadDate", nil },
  1038. { @"entries.0.sitemapURLCount", @"99" },
  1039. { @"entries.1.categories.0.term", kGDataCategorySitemapMobile },
  1040. { @"entries.1.markupLanguage", @"HTML" },
  1041. { @"entries.1.sitemapStatus", @"StatusValue" },
  1042. { @"entries.1.lastDownloadDate.date.timeIntervalSince1970", @"1163878052" },
  1043. { @"entries.1.sitemapURLCount", @"102" },
  1044. { @"entries.2.categories.0.term", kGDataCategorySitemapNews },
  1045. { @"entries.2.publicationLabel", @"pubLabelValue" },
  1046. { @"entries.2.sitemapStatus", @"AnotherStatusValue" },
  1047. { @"entries.2.lastDownloadDate.date.timeIntervalSince1970", @"1163878052" },
  1048. { @"entries.2.sitemapURLCount", @"102" },
  1049. { @"", @"" }, // end of feed
  1050. //
  1051. // Feed of a site's crawl issues
  1052. //
  1053. { @"GDataFeedSiteCrawlIssue", @"Tests/FeedWebmasterToolsCrawlIssues1.xml" },
  1054. { @"identifier", @"contains:http%3A%2F%2Fwww.example.net%2F/crawlissues" },
  1055. { @"title", @"Crawl Issues" },
  1056. // GDataEntrySiteCrawlIssue methods
  1057. { @"entries.0.crawlType", kGDataSiteCrawlTypeWeb },
  1058. { @"entries.0.detectedDate.RFC3339String", @"2008-11-17T01:06:10Z" },
  1059. { @"entries.0.detail", @"4xx Error" },
  1060. { @"entries.0.issueType", @"http-error" },
  1061. { @"entries.0.issueURLString", @"http://example.com/dir/" },
  1062. { @"entries.0.issueLinkedFromURLStrings.0", @"http://example.com" },
  1063. { @"entries.0.issueLinkedFromURLStrings.0.className", @"NSCFString" },
  1064. { @"", @"" }, // end of feed
  1065. //
  1066. // Feed of a site's messages
  1067. //
  1068. { @"GDataFeedSiteMessage", @"Tests/FeedWebmasterToolsMessages1.xml" },
  1069. { @"title", @"Messages" },
  1070. // GDataEntrySiteNessage methods
  1071. { @"entries.0.body", @"Crawl rate change has been requested." },
  1072. { @"entries.0.messageDate.RFC3339String", @"2008-09-18T20:49:57Z" },
  1073. { @"entries.0.language", @"en" },
  1074. { @"entries.0.read", @"1" },
  1075. { @"entries.0.subject", @"hasPrefix:Crawl rate change request" },
  1076. { @"", @"" }, // end of feed
  1077. //
  1078. // Feed of a site's keywords
  1079. //
  1080. { @"GDataFeedSiteKeyword", @"Tests/FeedWebmasterToolsKeywords1.xml" },
  1081. { @"identifier", @"contains:http%3A%2F%2Fwww.example.net%2F/keywords" },
  1082. { @"keywords.@count", @"4" },
  1083. { @"keywordsWithInternalSource.@count", @"1" },
  1084. { @"keywords.0.stringValue", @"example net" },
  1085. { @"keywords.0.source", kGDataSiteKeywordExternal },
  1086. { @"keywordsWithInternalSource.0.stringValue", @"example" },
  1087. { @"keywordsWithInternalSource.0.source", kGDataSiteKeywordInternal },
  1088. // the keywords feed has no entries
  1089. { @"entries", nil },
  1090. { @"", @"" }, // end of feed
  1091. { nil, nil } // end of test array
  1092. };
  1093. [self runTests:tests];
  1094. }
  1095. - (void)testMessageFeed {
  1096. TestKeyPathValues tests[] =
  1097. {
  1098. //
  1099. // Message Feed
  1100. //
  1101. { @"GDataFeedMessage", @"Tests/FeedMessageTest1.xml" },
  1102. // GDataFeedMessage paths
  1103. { @"links.0.href", @"hasPrefix:http://www.google.com/calendar/feeds/default" },
  1104. { @"categories.0.term", kGDataMessage },
  1105. { @"unknownAttributes.@count", @"0" },
  1106. { @"unknownChildren.@count", @"0" },
  1107. // GDataEntryMessage paths
  1108. { @"entries.0.categories.0.term", kGDataMessage },
  1109. { @"entries.0.categories.1.term", kGDataMessageSent },
  1110. { @"entries.0.identifier", @"http://mymail.example.com/feeds/jo/home/full/e1a2af06df8a563edf9d32ec9fd61e03f7f3b67b" },
  1111. { @"entries.0.content", @"Hi, Fritz -- The information you're looking for is on p. 47." },
  1112. { @"entries.0.title", @"Re: Info?" },
  1113. { @"entries.0.participants.0.rel", kGDataWhoMessageFrom },
  1114. { @"entries.0.participants.1.rel", kGDataWhoMessageTo },
  1115. { @"entries.0.unknownAttributes.@count", @"0" },
  1116. { @"entries.0.unknownChildren.@count", @"0" },
  1117. { @"", @"" }, // end of feed
  1118. { nil, nil } // end of test array
  1119. };
  1120. [self runTests:tests];
  1121. }
  1122. - (void)testDocListFeed {
  1123. TestKeyPathValues tests[] =
  1124. {
  1125. //
  1126. // Docs Feed
  1127. //
  1128. { @"GDataFeedDocList", @"Tests/FeedDocListTest1.xml" },
  1129. { @"identifier", @"http://docs.google.com/feeds/documents/private/full" },
  1130. // Docs Entries. The elements are all standard atom protocol elements,
  1131. // so we are just interested that the proper entry class has been
  1132. // instantiated
  1133. { @"entries.0.className", @"GDataEntryStandardDoc" },
  1134. { @"entries.0.categories.0.term", @"http://schemas.google.com/docs/2007#document"},
  1135. { @"entries.0.categories.0.label", @"document"},
  1136. { @"entries.0.lastViewed.date.timeIntervalSince1970", @"1222905296"},
  1137. { @"entries.0.writersCanInvite", @"1"},
  1138. { @"entries.0.lastModifiedBy.name", @"Fred Flintstone"},
  1139. { @"entries.0.quotaBytesUsed", @"12345"},
  1140. { @"entries.0.documentDescription", @"cherry soda"},
  1141. { @"entries.0.MD5Checksum", @"2b01142f7481c7b056c4b410d28f33cf"},
  1142. { @"entries.0.filename", @"hi mom.txt"},
  1143. { @"entries.0.suggestedFilename", @"Hi Mom.txt"},
  1144. { @"entries.0.lastCommented", @"2007-08-02T20:09:40Z"},
  1145. { @"entries.0.isRemoved", @"1"},
  1146. { @"entries.0.changestamp", @"1234"},
  1147. { @"entries.0.isHidden", @"1"},
  1148. { @"entries.1.className", @"GDataEntrySpreadsheetDoc" },
  1149. { @"entries.1.categories.0.term", @"http://schemas.google.com/docs/2007#spreadsheet"},
  1150. { @"entries.1.categories.0.label", @"spreadsheet"},
  1151. { @"entries.2.className", @"GDataEntryPresentationDoc" },
  1152. { @"entries.2.categories.0.term", @"http://schemas.google.com/docs/2007#presentation"},
  1153. { @"entries.2.categories.0.label", @"presentation"},
  1154. { @"entries.2.isStarred", @"0"},
  1155. { @"entries.3.className", @"GDataEntryPDFDoc" },
  1156. { @"entries.3.categories.0.term", @"http://schemas.google.com/docs/2007#pdf"},
  1157. { @"entries.3.categories.0.label", @"pdf"},
  1158. { @"entries.3.isStarred", @"1"},
  1159. { @"entries.3.isHidden", @"0"},
  1160. { @"entries.3.ACLFeedLink.href", @"contains:pdf54595c7b"},
  1161. { @"entries.3.parentLinks.0.href", @"contains:cc5275b740e3" },
  1162. { @"entries.4.className", @"GDataEntryFolderDoc" },
  1163. { @"entries.4.categories.0.term", @"http://schemas.google.com/docs/2007#folder"},
  1164. { @"entries.4.categories.0.label", @"folder"},
  1165. { @"entries.0.unknownAttributes.@count", @"0" },
  1166. { @"entries.0.unknownChildren.@count", @"0" },
  1167. { @"", @"" }, // end of feed
  1168. //
  1169. // DocList User Metadata Entry
  1170. //
  1171. { @"GDataEntryDocListMetadata", @"Tests/EntryDocListMetadataTest1.xml" },
  1172. { @"identifier", @"http://docs.google.com/feeds/metadata/fredflintstone%40example.net" },
  1173. { @"quotaBytesTotal", @"1073741824" },
  1174. { @"quotaBytesUsed", @"124432802" },
  1175. { @"quotaBytesUsedInTrash", @"89564924" },
  1176. { @"exportFormats.0.source", @"presentation" },
  1177. { @"exportFormats.0.target", @"text/plain" },
  1178. { @"importFormats.1.source", @"application/vnd.sun.xml.writer" },
  1179. { @"importFormats.1.target", @"document" },
  1180. { @"features.0.featureName", @"ocr" },
  1181. { @"features.0.featureRate", nil },
  1182. { @"features.1.featureName", @"translation" },
  1183. { @"features.1.featureRate", @"2.0" },
  1184. { @"maxUploadSizes.0.longLongNumberValue", @"512000" },
  1185. { @"maxUploadSizes.0.uploadKind", @"document" },
  1186. { @"maxUploadSizeForKindPDF.longLongNumberValue", @"1048571000" },
  1187. { @"featureForNameUploadAny.featureName", @"upload_any" },
  1188. { @"featureForNameUploadNone", nil },
  1189. { @"", @"" }, // end of feed
  1190. { nil, nil } // end of test array
  1191. };
  1192. [self runTests:tests];
  1193. };
  1194. - (void)testFinanceFeed {
  1195. TestKeyPathValues tests[] =
  1196. {
  1197. //
  1198. // Portfolio feed
  1199. //
  1200. { @"GDataFeedFinancePortfolio", @"Tests/FeedFinancePortfolioTest1.xml" },
  1201. { @"identifier", @"http://finance.google.com/finance/feeds/default/portfolios" },
  1202. // Portfolio entry
  1203. { @"entries.0.className", @"GDataEntryFinancePortfolio" },
  1204. { @"entries.0.positionURL.absoluteString", @"http://finance.google.com/finance/feeds/default/portfolios/1/positions" },
  1205. { @"entries.0.portfolioData.currencyCode", @"USD" },
  1206. { @"entries.0.portfolioData.gainPercentage", @"10.3" },
  1207. { @"entries.0.portfolioData.return1w", @"12" },
  1208. { @"entries.0.portfolioData.return1y", @"17" },
  1209. { @"entries.0.portfolioData.return3m", @"0" },
  1210. { @"entries.0.portfolioData.return3y", @"23" },
  1211. { @"entries.0.portfolioData.return4w", @"-41" },
  1212. { @"entries.0.portfolioData.return5y", @"10" },
  1213. { @"entries.0.portfolioData.returnOverall", @"12" },
  1214. { @"entries.0.portfolioData.returnYTD", @"6.7" },
  1215. { @"", @"" }, // end of feed
  1216. //
  1217. // Position feed
  1218. //
  1219. { @"GDataFeedFinancePosition", @"Tests/FeedFinancePositionTest1.xml" },
  1220. { @"identifier", @"http://finance.google.com/finance/feeds/default/portfolios/1/positions" },
  1221. // Position entry
  1222. { @"entries.0.className", @"GDataEntryFinancePosition" },
  1223. { @"entries.0.transactionURL.absoluteString", @"http://finance.google.com/finance/feeds/default/portfolios/1/positions/NASDAQ:GOOG/transactions" },
  1224. { @"entries.0.symbol.exchange", @"NASDAQ" },
  1225. { @"entries.0.symbol.fullName", @"Google Inc." },
  1226. { @"entries.0.symbol.symbol", @"GOOG" },
  1227. { @"entries.0.positionData.shares", @"2" },
  1228. { @"entries.0.positionData.gainPercentage", @"1.3" },
  1229. { @"entries.0.positionData.return1w", @"0.07" },
  1230. { @"entries.0.positionData.return1y", @"-10" },
  1231. { @"entries.0.positionData.return3m", @"172.1" },
  1232. { @"entries.0.positionData.return3y", @"5.4" },
  1233. { @"entries.0.positionData.return4w", @"-4" },
  1234. { @"entries.0.positionData.return5y", @"11" },
  1235. { @"entries.0.positionData.returnOverall", @"12" },
  1236. { @"entries.0.positionData.returnYTD", @"13" },
  1237. { @"", @"" }, // end of feed
  1238. //
  1239. // Transaction feed
  1240. //
  1241. { @"GDataFeedFinanceTransaction", @"Tests/FeedFinanceTransactionTest1.xml" },
  1242. { @"identifier", @"http://finance.google.com/finance/feeds/default/portfolios/1/positions/NASDAQ%3AAAPL/transactions" },
  1243. // Transaction entry
  1244. { @"entries.0.className", @"GDataEntryFinanceTransaction" },
  1245. { @"entries.0.transactionData.date.date.timeIntervalSince1970", @"1212364800" },
  1246. { @"entries.0.transactionData.shares", @"100" },
  1247. { @"entries.0.transactionData.type", @"Buy" },
  1248. { @"entries.0.transactionData.notes", @"Astrologer&#39;s advice" },
  1249. { @"entries.0.transactionData.commission.moneyWithPrimaryCurrency.amount", @"13.12" },
  1250. { @"entries.0.transactionData.commission.moneyWithPrimaryCurrency.currencyCode", @"USD" },
  1251. { @"entries.0.transactionData.price.moneyWithPrimaryCurrency.amount", @"120" },
  1252. { @"entries.0.transactionData.price.moneyWithPrimaryCurrency.currencyCode", @"USD" },
  1253. { @"entries.0.transactionData.price.moneyWithSecondaryCurrency.amount", @"110" },
  1254. { @"entries.0.transactionData.price.moneyWithSecondaryCurrency.currencyCode", @"CAD" },
  1255. { @"", @"" }, // end of feed
  1256. { nil, nil } // end of test array
  1257. };
  1258. [self runTests:tests];
  1259. };
  1260. - (void)testYouTubeFeeds {
  1261. TestKeyPathValues tests[] =
  1262. {
  1263. //
  1264. // user profile
  1265. //
  1266. // note that the user profile "feed" is really an entry returned by the
  1267. // YouTube server
  1268. { @"GDataEntryYouTubeUserProfile/2.0", @"Tests/FeedYouTubeUserProfile1.xml" },
  1269. // entry elements
  1270. { @"identifier", @"http://gdata.youtube.com/feeds/api/users/TestAccount" },
  1271. // user profile entry elements
  1272. { @"className", @"GDataEntryYouTubeUserProfile" },
  1273. { @"channelType", @"Standard" },
  1274. { @"statistics.lastWebAccess.RFC3339String", @"2008-01-30T11:38:20-08:00" },
  1275. { @"statistics.videoWatchCount", @"1" },
  1276. { @"statistics.viewCount", @"2" },
  1277. { @"statistics.favoriteCount", @"7" },
  1278. { @"statistics.totalUploadViews", @"37" },
  1279. { @"books", @"Booksz" },
  1280. { @"aboutMe", @"Narf narf" },
  1281. { @"age", @"49" },
  1282. { @"thumbnail.URLString", @"http://i.ytimg.com/vi/Bkhnvn1PIHs/default.jpg" },
  1283. { @"company", @"Apple, Google" },
  1284. { @"gender", @"m" },
  1285. { @"hobbies", @"Hobbiez, and more hobbiez" },
  1286. { @"hometown", @"Oakland, CA" },
  1287. { @"location", @"Seattle, WA, US" },
  1288. { @"movies", @"Moviez" },
  1289. { @"music", @"Musicz" },
  1290. { @"occupation", @"worker, player" },
  1291. { @"relationship", @"open" },
  1292. { @"school", @"Wildwood Elementary" },
  1293. { @"username", @"TestAccount" },
  1294. { @"firstName", @"Test" },
  1295. { @"lastName", @"Account" },
  1296. { @"feedLinks.@count", @"6" },
  1297. { @"unknownAttributes.@count", @"0" },
  1298. { @"unknownChildren.@count", @"0" },
  1299. { @"", @"" }, // end of feed
  1300. //
  1301. // video feed
  1302. //
  1303. { @"GDataFeedYouTubeVideo/2.0", @"Tests/FeedYouTubeVideo1.xml" },
  1304. // video entry elements
  1305. { @"entries.0.statistics.viewCount", @"177" },
  1306. { @"entries.0.comment.feedLink.href", @"http://gdata.youtube.com/feeds/api/videos/Dl643JFJWig/comments" },
  1307. { @"entries.0.links.0.youTubeToken.stringValue", @"ZeeToken" },
  1308. { @"entries.0.isEmbeddable", @"0" },
  1309. { @"entries.0.rating.numberOfLikes", @"100" },
  1310. { @"entries.0.rating.numberOfDislikes", @"25" },
  1311. { @"entries.0.mediaGroup.duration", @"3266" },
  1312. { @"entries.0.mediaGroup.isPrivate", @"1" },
  1313. { @"entries.0.mediaGroup.mediaPlayers.0.URLString", @"http://www.youtube.com/watch?v=Dl643JFJWig" },
  1314. { @"entries.0.mediaGroup.mediaRatings.0.stringValue", @"1" },
  1315. { @"entries.0.mediaGroup.mediaRatings.0.youTubeCountry", @"KR" },
  1316. { @"entries.0.mediaGroup.mediaThumbnails.0.height", @"97" },
  1317. { @"entries.0.mediaGroup.mediaThumbnails.0.youTubeName", @"abc987" },
  1318. { @"entries.0.publicationState.name", @"rejected" },
  1319. { @"entries.0.publicationState.reasonCode", @"32" },
  1320. { @"entries.0.publicationState.helpURLString", @"http://www.youtube.com/" },
  1321. { @"entries.0.publicationState.errorDescription", @"incorrect format" },
  1322. { @"entries.0.isIncomplete", @"1" },
  1323. { @"entries.0.captionTracksLink.href", @"contains:GppRTi2JGQ8/captions" },
  1324. { @"entries.0.videoResponsesLink.href", @"contains:Dl643JFJWig/responses" },
  1325. { @"entries.0.accessControls.0.action", kGDataYouTubeAccessControlVideoRespond },
  1326. { @"entries.0.accessControls.0.permission", kGDataYouTubeAccessControlPermissionDenied },
  1327. { @"entries.0.accessControls.1.action", kGDataYouTubeAccessControlComment },
  1328. { @"entries.0.accessControls.1.permission", kGDataYouTubeAccessControlPermissionAllowed },
  1329. { @"entries.0.accessControls.1.type", @"group" },
  1330. { @"entries.0.accessControls.1.value", @"friends" },
  1331. { @"unknownAttributes.@count", @"0" },
  1332. { @"unknownChildren.@count", @"0" },
  1333. { @"", @"" }, // end of feed
  1334. //
  1335. // playlist link feed, v2
  1336. //
  1337. { @"GDataFeedYouTubePlaylistLink/2.0", @"Tests/FeedYouTubePlaylistLink1.xml" },
  1338. { @"categories.0.term", kGDataCategoryYouTubePlaylistLink },
  1339. { @"totalResults", @"2" },
  1340. { @"startIndex", @"1" },
  1341. { @"itemsPerPage", @"22" },
  1342. { @"entries.0.className", @"GDataEntryYouTubePlaylistLink" },
  1343. { @"entries.0.isPrivate", @"1" },
  1344. { @"entries.0.categories.0.term", kGDataCategoryYouTubePlaylistLink },
  1345. { @"entries.0.categories.1.scheme", kGDataSchemeYouTubeTag },
  1346. { @"entries.0.categories.1.term", @"moreplaylisttags" },
  1347. { @"entries.0.countHint", @"10" },
  1348. { @"entries.1.categories.0.scheme", kGDataSchemeYouTubeTag },
  1349. { @"entries.1.categories.0.term", @"PlaylistTags" },
  1350. { @"entries.1.categories.1.term", kGDataCategoryYouTubePlaylistLink },
  1351. { @"entries.1.isPrivate", @"0" },
  1352. { @"entries.1.mediaGroup.mediaThumbnails.0.URLString", @"http://i.ytimg.com/vi/L-PzCdlQ5aY/default.jpg" },
  1353. { @"unknownAttributes.@count", @"0" },
  1354. { @"unknownChildren.@count", @"0" },
  1355. { @"", @"" }, // end of feed
  1356. //
  1357. // playlist feed
  1358. //
  1359. { @"GDataFeedYouTubePlaylist", @"Tests/FeedYouTubePlaylist1.xml" },
  1360. { @"categories.0.term", kGDataCategoryYouTubePlaylist },
  1361. { @"categories.1.scheme", kGDataSchemeYouTubeTag },
  1362. { @"categories.1.term", @"PlaylistTags" },
  1363. { @"totalResults", @"2" },
  1364. { @"startIndex", @"1" },
  1365. { @"itemsPerPage", @"25" },
  1366. { @"mediaGroup.mediaContents.0.URLString", @"http://www.youtube.com/ep.swf?id=BBA2B78EF2F08B10" },
  1367. { @"mediaGroup.mediaContents.0.youTubeFormatNumber", @"5" },
  1368. { @"entries.0.className", @"GDataEntryYouTubePlaylist" },
  1369. { @"entries.0.categories.0.term", kGDataCategoryYouTubePlaylist },
  1370. { @"entries.0.mediaGroup.mediaTitle", @"The Graphing Calculator Story" },
  1371. { @"entries.0.mediaGroup.mediaDescription", @"Google TechTalks" },
  1372. { @"entries.0.mediaGroup.mediaKeywords.keywords.1", @"avitzur" },
  1373. { @"entries.0.mediaGroup.duration", @"3266" },
  1374. { @"entries.0.statistics.viewCount", @"185" },
  1375. { @"entries.0.position", @"1" },
  1376. { @"unknownAttributes.@count", @"0" },
  1377. { @"unknownChildren.@count", @"0" },
  1378. { @"", @"" }, // end of feed
  1379. //
  1380. // contacts feed
  1381. //
  1382. { @"GDataFeedYouTubeFriend", @"Tests/FeedYouTubeContacts1.xml" },
  1383. { @"categories.0.term", kGDataCategoryYouTubeFriend },
  1384. { @"entries.0.className", @"GDataEntryYouTubeFriend" },
  1385. { @"entries.0.username", @"fredflintstone" },
  1386. { @"entries.0.status", @"accepted" },
  1387. { @"entries.0.unknownAttributes.@count", @"0" },
  1388. { @"entries.0.unknownChildren.@count", @"0" },
  1389. { @"", @"" }, // end of feed
  1390. //
  1391. // caption track feed
  1392. //
  1393. { @"GDataFeedYouTubeCaptionTrack", @"Tests/FeedYouTubeCaptionTracks1.xml" },
  1394. { @"categories.0.term", kGDataCategoryYouTubeCaptionTrack },
  1395. { @"entries.0.className", @"GDataEntryYouTubeCaptionTrack" },
  1396. { @"entries.0.title", @"captrack name" },
  1397. { @"entries.0.categories.0.term", kGDataCategoryYouTubeCaptionTrack },
  1398. { @"entries.0.publicationState.name", @"failed" },
  1399. { @"entries.0.publicationState.reasonCode", @"invalidFormat" },
  1400. { @"entries.0.derived", kGDataYouTubeDerivedSpeechRecogniion },
  1401. { @"entries.0.unknownAttributes.@count", @"0" },
  1402. { @"entries.0.unknownChildren.@count", @"0" },
  1403. { @"entries.0.unknownChildren", nil },
  1404. { @"", @"" }, // end of feed
  1405. //
  1406. // subscription feed
  1407. //
  1408. { @"GDataFeedYouTubeSubscription/2.0", @"Tests/FeedYouTubeSubscriptions1.xml" },
  1409. // feed elements
  1410. { @"identifier", @"http://gdata.youtube.com/feeds/api/users/testaccount/subscriptions?start-index=1&max-results=25" },
  1411. { @"logo", @"http://www.youtube.com/img/pic_youtubelogo_123x63.gif" },
  1412. // subscription entry elements
  1413. { @"entries.0.className", @"GDataEntryYouTubeSubscription" },
  1414. { @"entries.0.subscriptionType", @"channel" },
  1415. { @"entries.0.username", @"googletechtalks" },
  1416. { @"entries.0.content.sourceURI", @"http://gdata.youtube.com/feeds/api/users/googletechtalks/uploads" },
  1417. { @"entries.0.countHint", @"2" },
  1418. { @"entries.0.relatedLink.href", @"http://gdata.youtube.com/feeds/api/users/TestAccount" },
  1419. { @"entries.1.youTubeQueryString", @"cute dogs" },
  1420. { @"entries.1.playlistID", @"1sbd45" },
  1421. { @"entries.1.playlistTitle", @"Dog Playlist" },
  1422. { @"entries.0.unknownAttributes.@count", @"0" },
  1423. { @"entries.0.unknownChildren.@count", @"0" },
  1424. { @"", @"" }, // end of feed
  1425. //
  1426. // favorites feed
  1427. //
  1428. { @"GDataFeedYouTubeFavorite/2.0", @"Tests/FeedYouTubeFavorites1.xml" },
  1429. // feed elements
  1430. { @"ETag", @"W/\"CUACQX47eCp7ImA9WxdSEkg.\"" },
  1431. { @"identifier", @"tag:youtube,2008:user:fredflintstone:favorites" },
  1432. { @"logo", @"http://www.youtube.com/img/pic_youtubelogo_123x63.gif" },
  1433. // favorites entry elements
  1434. { @"entries.0.className", @"GDataEntryYouTubeFavorite" },
  1435. { @"entries.0.ETag", @"W/\"CUACQX47eCp7ImA9WxdSEkg.\"" },
  1436. { @"entries.0.identifier", @"tag:youtube,2008:favorite:vjVQa1PpcFP8fBdcAc_YTSRHgC1CE_ageg03_RO2EVk" },
  1437. { @"entries.0.content.sourceURI", @"http://www.youtube.com/v/I-t-7lTw6mA&f=gdata_user_favorites" },
  1438. { @"entries.0.location", @"mountain view, ca" },
  1439. { @"entries.0.recordedDate", @"2008-03-04" },
  1440. { @"entries.0.mediaGroup.mediaTitle", @"Authors@Google: Michael Pollan" },
  1441. { @"entries.0.mediaGroup.mediaDescription", @"Michael Pollan visits Google" },
  1442. { @"entries.0.mediaGroup.videoID", @"I-t-7lTw6mA" },
  1443. { @"entries.0.mediaGroup.aspectRatio", @"widescreen" },
  1444. { @"entries.0.mediaGroup.uploadedDate.date.timeIntervalSince1970", @"1204847352" },
  1445. { @"entries.0.mediaGroup.mediaCredits.0.role", @"uploader" },
  1446. { @"entries.0.mediaGroup.mediaCredits.0.scheme", @"urn:youtube" },
  1447. { @"entries.0.mediaGroup.mediaCredits.0.youTubeCreditType", @"partner" },
  1448. { @"entries.0.mediaGroup.mediaContents.0.duration", @"3554" },
  1449. { @"entries.0.mediaGroup.mediaContents.0.expression", @"full" },
  1450. { @"entries.0.mediaGroup.mediaContents.0.medium", @"video" },
  1451. { @"entries.0.mediaGroup.mediaContents.0.type", @"application/x-shockwave-flash" },
  1452. { @"entries.0.mediaGroup.mediaContents.0.URLString", @"http://www.youtube.com/v/I-t-7lTw6mA&f=gdata_user_favorites" },
  1453. { @"entries.0.mediaGroup.mediaContents.0.youTubeFormatNumber", @"5" },
  1454. { @"entries.0.mediaGroup.highQualityThumbnail.URLString", @"http://i.ytimg.com/vi/I-t-7lTw6mA/0.jpg" },
  1455. { @"entries.0.mediaGroup.mediaContentWithFormatNumber1.type", @"video/3gpp" },
  1456. { @"entries.0.unknownAttributes.@count", @"0" },
  1457. { @"entries.0.unknownChildren.@count", @"0" },
  1458. { @"", @"" }, // end of feed
  1459. //
  1460. // user events feed
  1461. //
  1462. { @"GDataFeedYouTubeUserEvent/2.0", @"Tests/FeedYouTubeUserEventTest1.xml" },
  1463. // feed elements
  1464. { @"ETag", @"W/\"AkUBRH47eCp7ImA9WxVWFkU.\"" },
  1465. { @"identifier", @"tag:youtube.com,2008:events" },
  1466. // entry elements
  1467. { @"entries.0.className", @"GDataEntryYouTubeUserEvent" },
  1468. { @"entries.0.kindCategory.term", kGDataCategoryYouTubeUserEvent },
  1469. { @"entries.0.ETag", @"W/\"AkUBRH47eCp7ImA9WxVWFkU.\"" },
  1470. { @"entries.0.identifier", @"tag:youtube.com,2008:event:Z3JlZ3JvYmJpbnM3MTIzNTY4ODI1NUJlbGFuYXI%3D" },
  1471. { @"entries.0.username", @"wilmaflintstone" },
  1472. { @"entries.0.userEventType", kGDataYouTubeUserEventFriendAdded },
  1473. { @"entries.0.unknownAttributes.@count", @"0" },
  1474. { @"entries.0.unknownChildren.@count", @"0" },
  1475. { @"entries.1.userEventType", kGDataYouTubeUserEventVideoFavorited },
  1476. { @"entries.1.videoLink.href", @"http://gdata.youtube.com/feeds/api/videos/cxFfUsDgnaU" },
  1477. { @"entries.1.videoID", @"cxFfUsDgnaU" },
  1478. { @"entries.1.unknownAttributes.@count", @"0" },
  1479. { @"entries.1.unknownChildren.@count", @"0" },
  1480. { @"", @"" }, // end of feed
  1481. { nil, nil } // end of test array
  1482. };
  1483. [self runTests:tests];
  1484. };
  1485. - (void)testMapsFeed {
  1486. TestKeyPathValues tests[] =
  1487. {
  1488. //
  1489. // Map Feature Feed
  1490. //
  1491. { @"GDataFeedMapFeature/2.0", @"Tests/FeedMapFeaturesTest1.xml" },
  1492. // feature feed elements
  1493. { @"title", @"Kirkland Office" },
  1494. { @"identifier", @"http://maps.google.com/maps/feeds/features/2063624404192119555/0046a899354a8585d4d" },
  1495. { @"unknownAttributes.@count", @"0" },
  1496. { @"unknownChildren.@count", @"0" },
  1497. // feature entry elements
  1498. { @"entries.0.editedDate.RFC3339String", @"2009-05-23T02:10:51Z" },
  1499. { @"entries.0.categories.0.term", kGDataCategoryMapFeature },
  1500. { @"entries.0.KMLValues.@count", @"1" },
  1501. { @"entries.0.KMLValues.0.name", @"Placemark" },
  1502. { @"entries.0.viewLink.href", @"contains:view/00047730f33bb0097204c" },
  1503. { @"entries.0.postalAddress.city", @"Anytown" },
  1504. { @"entries.0.customProperties.@count", @"2" },
  1505. { @"entries.0.customProperties.0.name", @"distance" },
  1506. { @"entries.0.customProperties.0.unit", @"meters" },
  1507. { @"entries.0.customProperties.0.value", @"36" },
  1508. { @"entries.0.customPropertyWithHeightName.value", @"10.2" },
  1509. { @"entries.0.unknownAttributes.@count", @"0" },
  1510. { @"entries.0.unknownChildren.@count", @"0" },
  1511. { @"", @"" }, // end of feed
  1512. { nil, nil } // end of test array
  1513. };
  1514. [self runTests:tests];
  1515. }
  1516. - (void)testBlogFeeds {
  1517. TestKeyPathValues tests[] =
  1518. {
  1519. //
  1520. // Blog feed
  1521. //
  1522. { @"GDataFeedBlog/2.0", @"Tests/FeedBlogTest1.xml" },
  1523. // feed elements
  1524. { @"title", @"TestAccount's Blogs" },
  1525. { @"unknownAttributes.@count", @"0" },
  1526. { @"unknownChildren.@count", @"0" },
  1527. // entry elements - no extensions, so just test convenience accessors
  1528. { @"entries.0.templateLink.href", @"http://www.blogger.com/feeds/145278007186576769/template" },
  1529. { @"entries.0.settingsLink.href", @"http://www.blogger.com/feeds/145278007186576769/settings" },
  1530. { @"entries.0.unknownAttributes.@count", @"0" },
  1531. { @"entries.0.unknownChildren.@count", @"0" },
  1532. { @"", @"" }, // end of feed
  1533. //
  1534. // Blog post feed
  1535. //
  1536. { @"GDataFeedBlogPost/2.0", @"Tests/FeedBlogPostTest1.xml" },
  1537. // feed elements
  1538. { @"title", @"Test Posts" },
  1539. { @"unknownAttributes.@count", @"0" },
  1540. { @"unknownChildren.@count", @"0" },
  1541. // entry elements
  1542. { @"entries.0.atomPubControl.isDraft", @"1" },
  1543. { @"entries.0.identifier", @"tag:blogger.com,1999:blog-1452780071865767697.post-6317479243618470383" },
  1544. { @"entries.0.total", @"3" },
  1545. { @"entries.0.thumbnail.URLString", @"contains:Hippo.jpg" },
  1546. { @"entries.0.repliesHTMLLink.href", @"https://www.blogger.com/comment.g?blogID=1452780071865767697&postID=6317479243618470383" },
  1547. { @"entries.0.repliesAtomLink.href", @"http://testaccount.blogspot.com/feeds/6317479243618470383/comments/default" },
  1548. { @"entries.0.enclosureLink.href", @"http://example.net/file.txt" },
  1549. { @"entries.0.unknownAttributes.@count", @"0" },
  1550. { @"entries.0.unknownChildren.@count", @"0" },
  1551. { @"", @"" }, // end of feed
  1552. //
  1553. // Blog comments feed
  1554. //
  1555. { @"GDataFeedBlogComment/2.0", @"Tests/FeedBlogCommentsTest1.xml" },
  1556. // feed elements
  1557. { @"title", @"Comments on Post" },
  1558. { @"unknownAttributes.@count", @"0" },
  1559. { @"unknownChildren.@count", @"0" },
  1560. // entry elements
  1561. { @"entries.0.inReplyTo.href", @"http://testaccount.blogspot.com/2009/06/post-created-2009-06-02-161600-0700.html" },
  1562. { @"entries.0.inReplyTo.ref", @"tag:blogger.com,1999:blog-1452780071865767697.post-1015986829942539734" },
  1563. { @"entries.0.inReplyTo.source", @"http://testaccount.blogspot.com/feeds/posts/default/1015986829942539734" },
  1564. { @"entries.0.inReplyTo.type", kGDataLinkTypeHTML },
  1565. { @"entries.0.unknownAttributes.@count", @"0" },
  1566. { @"entries.0.unknownChildren.@count", @"0" },
  1567. { @"", @"" }, // end of feed
  1568. { nil, nil } // end of test array
  1569. };
  1570. [self runTests:tests];
  1571. }
  1572. - (void)testACLFeed {
  1573. TestKeyPathValues tests[] =
  1574. {
  1575. //
  1576. // ACL Feed
  1577. //
  1578. { @"GDataFeedACL", @"Tests/FeedACLTest1.xml" },
  1579. // GDataFeedACL paths
  1580. { @"links.0.href", @"http://www.google.com/calendar/feeds/test%40gmail.com/private/full" },
  1581. { @"links.0.rel", kGDataLinkRelControlledObject },
  1582. { @"categories.0.term", kGDataCategoryACL },
  1583. { @"categories.0.scheme", kGDataCategoryScheme },
  1584. { @"unknownAttributes.@count", @"0" },
  1585. { @"unknownChildren.@count", @"0" },
  1586. // GDataEntryACL paths (scope and role are the main elements)
  1587. { @"entries.0.categories.0.term", kGDataCategoryACL },
  1588. { @"entries.0.identifier", @"http://www.google.com/calendar/feeds/test%40gmail.com/acl/full/user%3Atest%40gmail.com" },
  1589. { @"entries.0.content", @"" },
  1590. { @"entries.0.links.1.rel", @"edit" },
  1591. { @"entries.0.scope.type", @"user" },
  1592. { @"entries.0.scope.value", @"test@example.com" },
  1593. { @"entries.0.role.value", @"http://schemas.google.com/gCal/2005#owner" },
  1594. { @"entries.0.unknownAttributes.@count", @"0" },
  1595. { @"entries.0.unknownChildren.@count", @"0" },
  1596. { @"entries.1.scope.type", @"user" },
  1597. { @"entries.1.scope.name", @"wilma" },
  1598. { @"entries.1.keyedRole.key", @"A123B" },
  1599. { @"entries.1.keyedRole.role.value", @"reader" },
  1600. { @"entries.1.keyedRole.additionalRoles.1.value", @"pigeon" },
  1601. { @"entries.1.unknownAttributes.@count", @"0" },
  1602. { @"entries.1.unknownChildren.@count", @"0" },
  1603. { @"", @"" }, // end of feed
  1604. { nil, nil } // end of test array
  1605. };
  1606. [self runTests:tests];
  1607. }
  1608. - (void)testServiceDocuments {
  1609. TestKeyPathValues tests[] =
  1610. {
  1611. //
  1612. // service document
  1613. //
  1614. { @"GDataAtomServiceDocument", @"Tests/FeedServiceDocTest2.xml" },
  1615. // GDataAtomServiceDocument paths
  1616. { @"namespaces.app", kGDataNamespaceAtomPub },
  1617. { @"workspaces.@count", @"2" },
  1618. // workspace paths
  1619. { @"workspaces.0.title", @"fredflintstone workspace" },
  1620. { @"workspaces.0.collections.@count", @"1" },
  1621. { @"workspaces.0.collections.0.title", @"filetypes" },
  1622. { @"workspaces.0.collections.0.serviceAcceptStrings.@count", @"5" },
  1623. { @"workspaces.0.collections.0.serviceAcceptStrings.0", @"image/png" },
  1624. { @"workspaces.0.collections.0.serviceAcceptStrings.1", @"image/jpeg" },
  1625. { @"workspaces.1.title", @"Second Workspace" },
  1626. { @"workspaces.1.collections.@count", @"1" },
  1627. { @"workspaces.1.collections.0.href", @"http://example.org/hrefcollection" },
  1628. { @"workspaces.1.collections.0.title", @"Remaindered Links" },
  1629. { @"workspaces.1.collections.0.serviceAcceptStrings.@count", @"1" },
  1630. { @"workspaces.1.collections.0.serviceAcceptStrings.0", @"entry" },
  1631. { @"workspaces.1.collections.0.categoryGroup.isFixed", @"1" },
  1632. { @"workspaces.1.collections.0.categoryGroup.scheme", @"bogusscheme" },
  1633. { @"workspaces.1.collections.0.categoryGroup.href", @"bogushref" },
  1634. { @"workspaces.1.collections.0.categoryGroup.categories.@count", @"2" },
  1635. { @"workspaces.1.collections.0.categoryGroup.categories.1.term", @"serious" },
  1636. { @"unknownAttributes.@count", @"0" },
  1637. { @"unknownChildren.@count", @"0" },
  1638. { @"", @"" }, // end of feed
  1639. { nil, nil } // end of test array
  1640. };
  1641. [self runTests:tests];
  1642. }
  1643. - (void)testDetachedEntries {
  1644. // get a feed, retain the entries, release the feed, then verify that the
  1645. // entries are usable with the feed itself gone
  1646. NSData *data = [NSData dataWithContentsOfFile:@"Tests/FeedCalendarEventTest1.xml"];
  1647. STAssertNotNil(data, @"Cannot read feed for detach test");
  1648. // create the feed object
  1649. GDataFeedBase *feed = [[GDataFeedCalendarEvent alloc] initWithData:data
  1650. serviceVersion:@"2.1"
  1651. shouldIgnoreUnknowns:NO];
  1652. STAssertNotNil(feed, @"Cannot make detaching feed");
  1653. NSArray *entries = [[[feed entries] retain] autorelease];
  1654. STAssertTrue([entries count] > 0, @"Feed lacks entries to detach");
  1655. [feed release];
  1656. GDataEntryBase *firstEntry = [entries objectAtIndex:0];
  1657. NSString *title = [[firstEntry title] stringValue];
  1658. STAssertEqualObjects(title, @"3 days", @"testing an element in a detached entry");
  1659. NSString *titleType = [[firstEntry title] type];
  1660. STAssertEqualObjects(titleType, @"text", @"testing an attribute in a detached entry");
  1661. }
  1662. @end
  1663. ///////////////////////////////////////////////////////////////////////////
  1664. //
  1665. // categories to test helper methods that require arguments
  1666. //
  1667. //
  1668. // YouTube
  1669. //
  1670. @interface GDataYouTubeMediaGroup (TestHelperMethods)
  1671. @end
  1672. @implementation GDataYouTubeMediaGroup (TestHelperMethods)
  1673. - (GDataMediaContent *)mediaContentWithFormatNumber1 {
  1674. return [self mediaContentWithFormatNumber:kGDataYouTubeMediaContentFormatRTSPStream];
  1675. }
  1676. @end
  1677. //
  1678. // analytics
  1679. //
  1680. @interface GDataAnalyticsDataSource (TestHelperMethods)
  1681. - (GDataAnalyticsProperty *)analyticsPropertyWithNameAccountName;
  1682. @end
  1683. @implementation GDataAnalyticsDataSource (TestHelperMethods)
  1684. - (GDataAnalyticsProperty *)analyticsPropertyWithNameAccountName {
  1685. return [self analyticsPropertyWithName:@"ga:accountName"];
  1686. }
  1687. @end
  1688. @interface GDataEntryAnalyticsData (TestHelperMethods)
  1689. - (GDataAnalyticsDimension *)dimensionWithNameCountry;
  1690. - (GDataAnalyticsMetric *)metricWithNamePageviews;
  1691. @end
  1692. @implementation GDataEntryAnalyticsData (TestHelperMethods)
  1693. - (GDataAnalyticsDimension *)dimensionWithNameCountry {
  1694. return [self dimensionWithName:@"ga:country"];
  1695. }
  1696. - (GDataAnalyticsMetric *)metricWithNamePageviews {
  1697. return [self metricWithName:@"ga:pageviews"];
  1698. }
  1699. @end
  1700. //
  1701. // maps
  1702. //
  1703. @interface GDataEntryMapFeature (TestHelperMethods)
  1704. - (GDataCustomProperty *)customPropertyWithHeightName;
  1705. @end
  1706. @implementation GDataEntryMapFeature (TestHelperMethods)
  1707. - (GDataCustomProperty *)customPropertyWithHeightName {
  1708. return [self customPropertyWithName:@"height"];
  1709. }
  1710. @end
  1711. //
  1712. // DocList User Metadata
  1713. //
  1714. @interface GDataEntryDocListMetadata (TestHelperMethods)
  1715. - (GDataDocMaxUploadSize *)maxUploadSizeForKindPDF;
  1716. - (GDataDocFeature *)featureForNameUploadAny;
  1717. - (GDataDocFeature *)featureForNameUploadNone;
  1718. @end
  1719. @implementation GDataEntryDocListMetadata (TestHelperMethods)
  1720. - (GDataDocMaxUploadSize *)maxUploadSizeForKindPDF {
  1721. return [self maxUploadSizeForKind:@"pdf"];
  1722. }
  1723. - (GDataDocFeature *)featureForNameUploadAny {
  1724. return [self featureForName:@"upload_any"];
  1725. }
  1726. - (GDataDocFeature *)featureForNameUploadNone {
  1727. return [self featureForName:@"upload_none"];
  1728. }
  1729. @end
  1730. //
  1731. // webmaster tools
  1732. //
  1733. @interface GDataFeedSiteKeyword (TestHelperMethods)
  1734. - (NSArray *)keywordsWithInternalSource;
  1735. @end
  1736. @implementation GDataFeedSiteKeyword (TestHelperMethods)
  1737. - (NSArray *)keywordsWithInternalSource {
  1738. return [self keywordsWithSource:kGDataSiteKeywordInternal];
  1739. }
  1740. @end