diff --git a/src/experiments.ts b/src/experiments.ts index c93d5b7..d6aea2c 100644 --- a/src/experiments.ts +++ b/src/experiments.ts @@ -19,7 +19,7 @@ const Experiments: { [key in Experiment]: ExperimentConfig } = { export const experimentCheck = (experiment: Experiment, condition = true) => { console.log(`Checking experiment ${experiment}`); const experimentEnabled = - (Experiments[experiment].percentage > Math.random()) && condition; + Experiments[experiment].percentage > Math.random() && condition; console.log(`Experiment ${experiment} enabled: ${experimentEnabled}`); return experimentEnabled; }; diff --git a/src/helpers/card.ts b/src/helpers/card.ts index 0a4dc69..1ae000a 100644 --- a/src/helpers/card.ts +++ b/src/helpers/card.ts @@ -4,78 +4,66 @@ import { calculateTimeLeftString } from './pollTime'; export const renderCard = ( card: GraphQLTweet['card'] ): { poll?: APIPoll; external_media?: APIExternalMedia } => { - // We convert the binding_values array into an object with the legacy format - // TODO Clean this up + if (!Array.isArray(card.legacy.binding_values)) { + return {}; + } + const binding_values: Record< string, { string_value?: string; boolean_value?: boolean } > = {}; - if (Array.isArray(card.legacy.binding_values)) { - card.legacy.binding_values.forEach(value => { - if (value.key && value.value) { - binding_values[value.key] = value.value; - } - }); - } + + card.legacy.binding_values.forEach(value => { + if (value.key && value.value) { + binding_values[value.key] = value.value; + } + }); console.log('rendering card'); - if (typeof binding_values !== 'undefined') { - if (typeof binding_values.choice1_count !== 'undefined') { - const poll = {} as APIPoll; - - poll.ends_at = binding_values.end_datetime_utc?.string_value || ''; - poll.time_left_en = calculateTimeLeftString( - new Date(binding_values.end_datetime_utc?.string_value || '') + if (binding_values.choice1_count?.string_value) { + const choices: { [label: string]: number } = {}; + for (let i = 1; i <= 4; i++) { + choices[binding_values[`choice${i}_label`]?.string_value || ''] = parseInt( + binding_values[`choice${i}_count`]?.string_value || '0' ); + } - const choices: { [label: string]: number } = { - [binding_values.choice1_label?.string_value || '']: parseInt( - binding_values.choice1_count?.string_value || '0' - ), - [binding_values.choice2_label?.string_value || '']: parseInt( - binding_values.choice2_count?.string_value || '0' - ), - [binding_values.choice3_label?.string_value || '']: parseInt( - binding_values.choice3_count?.string_value || '0' - ), - [binding_values.choice4_label?.string_value || '']: parseInt( - binding_values.choice4_count?.string_value || '0' - ) - }; + const total_votes = Object.values(choices).reduce((a, b) => a + b, 0); - poll.total_votes = Object.values(choices).reduce((a, b) => a + b, 0); - - poll.choices = Object.keys(choices) - .filter(label => label !== '') - .map(label => { - return { + return { + poll: { + ends_at: binding_values.end_datetime_utc?.string_value || '', + time_left_en: calculateTimeLeftString( + new Date(binding_values.end_datetime_utc?.string_value || '') + ), + total_votes, + choices: Object.keys(choices) + .filter(label => label !== '') + .map(label => ({ label: label, count: choices[label], - percentage: - (Math.round((choices[label] / poll.total_votes) * 1000) || 0) / 10 || 0 - }; - }); - - return { poll: poll }; - } else if ( - typeof binding_values.player_url !== 'undefined' && - binding_values.player_url.string_value - ) { - /* Oh good, a non-Twitter video URL! This enables YouTube embeds and stuff to just work */ - return { - external_media: { - type: 'video', - url: binding_values.player_url.string_value, - width: parseInt( - (binding_values.player_width?.string_value || '1280').replace('px', '') - ), // TODO: Replacing px might not be necessary, it's just there as a precaution - height: parseInt( - (binding_values.player_height?.string_value || '720').replace('px', '') - ) - } - }; - } + percentage: (Math.round((choices[label] / total_votes) * 1000) || 0) / 10 + })) + } + }; } + + if (binding_values.player_url?.string_value) { + /* Oh good, a non-Twitter video URL! This enables YouTube embeds and stuff to just work */ + return { + external_media: { + type: 'video', + url: binding_values.player_url.string_value, + width: parseInt( + (binding_values.player_width?.string_value || '1280').replace('px', '') + ), // TODO: Replacing px might not be necessary, it's just there as a precaution + height: parseInt( + (binding_values.player_height?.string_value || '720').replace('px', '') + ) + } + }; + } + return {}; }; diff --git a/test/index.test.ts b/test/index.test.ts index 257b1c1..fdeff92 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -8,6 +8,22 @@ const humanHeaders = { const githubUrl = 'https://github.com/FixTweet/FixTweet'; const twitterBaseUrl = 'https://twitter.com'; +// @ts-expect-error - Performance not included in jest environment +if (!globalThis.performance) { + // @ts-expect-error - Performance not included in jest environment + globalThis.performance = {}; +} + +// @ts-expect-error - Performance not included in jest environment +if (!globalThis.performance.now) { + var start = Date.now(); + + // @ts-expect-error - Performance not included in jest environment + globalThis.performance.now = function () { + return Date.now() - start; + }; +} + test('Home page redirect', async () => { const result = await cacheWrapper( new Request('https://fxtwitter.com', { @@ -87,7 +103,6 @@ test('API fetch basic Tweet', async () => { expect(tweet.author.name).toBeTruthy(); expect(tweet.author.avatar_url).toBeTruthy(); expect(tweet.author.banner_url).toBeTruthy(); - expect(tweet.author.avatar_color).toBeTruthy(); expect(tweet.replies).toBeGreaterThan(0); expect(tweet.retweets).toBeGreaterThan(0); expect(tweet.likes).toBeGreaterThan(0); @@ -123,7 +138,6 @@ test('API fetch video Tweet', async () => { expect(tweet.author.name).toBeTruthy(); expect(tweet.author.avatar_url).toBeTruthy(); expect(tweet.author.banner_url).toBeTruthy(); - expect(tweet.author.avatar_color).toBeTruthy(); expect(tweet.replies).toBeGreaterThan(0); expect(tweet.retweets).toBeGreaterThan(0); expect(tweet.likes).toBeGreaterThan(0); @@ -167,7 +181,6 @@ test('API fetch multi-photo Tweet', async () => { expect(tweet.author.name).toBeTruthy(); expect(tweet.author.avatar_url).toBeTruthy(); expect(tweet.author.banner_url).toBeTruthy(); - expect(tweet.author.avatar_color).toBeTruthy(); expect(tweet.twitter_card).toEqual('summary_large_image'); expect(tweet.created_at).toEqual('Mon Oct 04 18:30:53 +0000 2021'); expect(tweet.created_timestamp).toEqual(1633372253); @@ -215,7 +228,6 @@ test('API fetch poll Tweet', async () => { expect(tweet.author.name).toBeTruthy(); expect(tweet.author.avatar_url).toBeTruthy(); expect(tweet.author.banner_url).toBeTruthy(); - expect(tweet.author.avatar_color).toBeTruthy(); expect(tweet.twitter_card).toEqual('tweet'); expect(tweet.created_at).toEqual('Thu Oct 25 15:07:31 +0000 2018'); expect(tweet.created_timestamp).toEqual(1540480051);