/ clis / twitter / timeline.test.js
timeline.test.js
  1  import { describe, expect, it } from 'vitest';
  2  import { __test__ } from './timeline.js';
  3  describe('twitter timeline helpers', () => {
  4      it('builds for-you variables with withCommunity', () => {
  5          expect(__test__.buildTimelineVariables('for-you', 20)).toEqual({
  6              count: 20,
  7              includePromotedContent: false,
  8              latestControlAvailable: true,
  9              requestContext: 'launch',
 10              withCommunity: true,
 11          });
 12      });
 13      it('builds following variables with seenTweetIds instead of withCommunity', () => {
 14          expect(__test__.buildTimelineVariables('following', 20, 'cursor-1')).toEqual({
 15              count: 20,
 16              includePromotedContent: false,
 17              latestControlAvailable: true,
 18              requestContext: 'launch',
 19              seenTweetIds: [],
 20              cursor: 'cursor-1',
 21          });
 22      });
 23      it('encodes variables into timeline url', () => {
 24          const url = __test__.buildHomeTimelineUrl('query123', 'HomeLatestTimeline', {
 25              count: 20,
 26              seenTweetIds: [],
 27          });
 28          expect(url).toContain('/i/api/graphql/query123/HomeLatestTimeline');
 29          expect(url).toContain('variables=');
 30          expect(url).toContain('features=');
 31          expect(decodeURIComponent(url)).toContain('"seenTweetIds":[]');
 32      });
 33      it('parses tweets and bottom cursor from home timeline payload', () => {
 34          const payload = {
 35              data: {
 36                  home: {
 37                      home_timeline_urt: {
 38                          instructions: [
 39                              {
 40                                  entries: [
 41                                      {
 42                                          entryId: 'tweet-1',
 43                                          content: {
 44                                              itemContent: {
 45                                                  tweet_results: {
 46                                                      result: {
 47                                                          rest_id: '1',
 48                                                          legacy: {
 49                                                              full_text: 'hello',
 50                                                              favorite_count: 3,
 51                                                              retweet_count: 2,
 52                                                              reply_count: 1,
 53                                                              created_at: 'now',
 54                                                          },
 55                                                          core: {
 56                                                              user_results: {
 57                                                                  result: {
 58                                                                      legacy: {
 59                                                                          screen_name: 'alice',
 60                                                                      },
 61                                                                  },
 62                                                              },
 63                                                          },
 64                                                          views: {
 65                                                              count: '9',
 66                                                          },
 67                                                      },
 68                                                  },
 69                                              },
 70                                          },
 71                                      },
 72                                      {
 73                                          entryId: 'cursor-bottom-1',
 74                                          content: {
 75                                              entryType: 'TimelineTimelineCursor',
 76                                              cursorType: 'Bottom',
 77                                              value: 'cursor-next',
 78                                          },
 79                                      },
 80                                  ],
 81                              },
 82                          ],
 83                      },
 84                  },
 85              },
 86          };
 87          const result = __test__.parseHomeTimeline(payload, new Set());
 88          expect(result.nextCursor).toBe('cursor-next');
 89          expect(result.tweets).toHaveLength(1);
 90          expect(result.tweets[0]).toMatchObject({
 91              id: '1',
 92              author: 'alice',
 93              text: 'hello',
 94              likes: 3,
 95              retweets: 2,
 96              replies: 1,
 97              views: 9,
 98              created_at: 'now',
 99              url: 'https://x.com/alice/status/1',
100          });
101      });
102  });