Skip to content

Commit

Permalink
Merge pull request #112 from vish-mv/main
Browse files Browse the repository at this point in the history
Add Test Cases for Twitter Connector APIs and Update Mock Server
  • Loading branch information
NipunaRanasinghe committed Jul 2, 2024
2 parents 85bae8d + 8fe084c commit bbe31a2
Show file tree
Hide file tree
Showing 10 changed files with 504 additions and 224 deletions.
36 changes: 36 additions & 0 deletions ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,15 @@ dependencies = [
{org = "ballerina", name = "jballerina.java"}
]

[[package]]
org = "ballerina"
name = "lang.error"
version = "0.0.0"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
]

[[package]]
org = "ballerina"
name = "lang.int"
Expand Down Expand Up @@ -205,6 +214,9 @@ dependencies = [
{org = "ballerina", name = "lang.value"},
{org = "ballerina", name = "observe"}
]
modules = [
{org = "ballerina", packageName = "log", moduleName = "log"}
]

[[package]]
org = "ballerina"
Expand Down Expand Up @@ -245,6 +257,9 @@ dependencies = [
{org = "ballerina", name = "io"},
{org = "ballerina", name = "jballerina.java"}
]
modules = [
{org = "ballerina", packageName = "os", moduleName = "os"}
]

[[package]]
org = "ballerina"
Expand All @@ -255,13 +270,30 @@ dependencies = [
{org = "ballerina", name = "time"}
]

[[package]]
org = "ballerina"
name = "test"
version = "0.0.0"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "lang.array"},
{org = "ballerina", name = "lang.error"}
]
modules = [
{org = "ballerina", packageName = "test", moduleName = "test"}
]

[[package]]
org = "ballerina"
name = "time"
version = "2.4.0"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
]
modules = [
{org = "ballerina", packageName = "time", moduleName = "time"}
]

[[package]]
org = "ballerina"
Expand Down Expand Up @@ -293,6 +325,10 @@ version = "4.0.0"
dependencies = [
{org = "ballerina", name = "constraint"},
{org = "ballerina", name = "http"},
{org = "ballerina", name = "log"},
{org = "ballerina", name = "os"},
{org = "ballerina", name = "test"},
{org = "ballerina", name = "time"},
{org = "ballerina", name = "url"},
{org = "ballerinai", name = "observe"}
]
Expand Down
85 changes: 85 additions & 0 deletions ballerina/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Running Tests

## Prerequisites
You need a bearer token and a Access token from twittter(X) developer account.

To do this, refer to [Ballerina Twitter Connector](https://github.com/ballerina-platform/module-ballerinax-twitter/blob/main/ballerina/Module.md).

And You need Find Your User ID For run some of the tests.
Via This Website you can find it [Twitter ID Finder](https://twiteridfinder.com/).

# Running Tests

There are two test environments for running the Twitter(X) connector tests. The default test environment is the mock server for Twitter API. The other test environment is the actual Twitter (X) API.

You can run the tests in either of these environments and each has its own compatible set of tests.

Test Groups | Environment
-------------|---------------------------------------------------
mock_tests | Mock server for Twitter(X) API (Defualt Environment)
live_tests | Twitter(X) API

## Running Tests in the Mock Server

To execute the tests on the mock server, ensure that the `IS_LIVE_SERVER` environment variable is either set to `false` or unset before initiating the tests.

This environment variable can be configured within the `Config.toml` file located in the tests directory or specified as an environmental variable.

#### Using a Config.toml File

Create a `Config.toml` file in the tests directory and the following content:

```toml
isLiveServer = false
```

#### Using Environment Variables

Alternatively, you can set your authentication credentials as environment variables:
If you are using linux or mac, you can use following method:
```bash
export IS_LIVE_SERVER=false
```
If you are using Windows you can use following method:
```bash
set IS_LIVE_SERVER=false
```
Then, run the following command to run the tests:

```bash
./gradlew clean test
```

## Running Tests Against Twitter(X) Live API

#### Using a Config.toml File

Create a `Config.toml` file in the tests directory and add your authentication credentials a

```toml
isLiveServer = true
token = "<your-twitter-access-token>"
userId = "<your-twitter-user-id>"
```

#### Using Environment Variables

Alternatively, you can set your authentication credentials as environment variables:
If you are using linux or mac, you can use following method:
```bash
export IS_LIVE_SERVER=true
export TWITTER_TOKEN ="<your-twitter-access-token>"
export TWITTER_USER_ID ="<your-twitter-user-id>"
```

If you are using Windows you can use following method:
```bash
setx IS_LIVE_SERVER true
setx TWITTER_TOKEN <your-twitter-access-token>
setx TWITTER_USER_ID <your-twitter-user-id>
```
Then, run the following command to run the tests:

```bash
./gradlew clean test
```
208 changes: 208 additions & 0 deletions ballerina/tests/mock_service.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/http;
import ballerina/log;

listener http:Listener httpListener = new (9090);

http:Service mockService = service object {

# Remove a bookmarked Post
#
# + id - The ID of the authenticated source User whose bookmark is to be removed.
# + tweet_id - The ID of the Post that the source User is removing from bookmarks.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function delete users/[UserIdMatchesAuthenticatedUser id]/bookmarks/[TweetId tweet_id]() returns BookmarkMutationResponse|http:Response {
return {
"data":{"bookmarked":false}
};
}

# Causes the User (in the path) to unlike the specified Post
#
# + id - The ID of the authenticated source User that is requesting to unlike the Post.
# + tweet_id - The ID of the Post that the User is requesting to unlike.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function delete users/[UserIdMatchesAuthenticatedUser id]/likes/[TweetId tweet_id]() returns UsersLikesDeleteResponse|http:Response {
return {
"data":{"liked":false}
};
}

# Causes the User (in the path) to unretweet the specified Post
#
# + id - The ID of the authenticated source User that is requesting to repost the Post.
# + source_tweet_id - The ID of the Post that the User is requesting to unretweet.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function delete users/[UserIdMatchesAuthenticatedUser id]/retweets/[TweetId source_tweet_id]() returns UsersRetweetsDeleteResponse|http:Response {
return {
"data":{"retweeted":false}
};
}

# Unfollow User
#
# + source_user_id - The ID of the authenticated source User that is requesting to unfollow the target User.
# + target_user_id - The ID of the User that the source User is requesting to unfollow.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function delete users/[UserIdMatchesAuthenticatedUser source_user_id]/following/[UserId target_user_id]() returns UsersFollowingDeleteResponse|http:Response {
return {
"data":{"following":false}
};
}

# Unmute User by User ID
#
# + source_user_id - The ID of the authenticated source User that is requesting to unmute the target User.
# + target_user_id - The ID of the User that the source User is requesting to unmute.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function delete users/[UserIdMatchesAuthenticatedUser source_user_id]/muting/[UserId target_user_id]() returns MuteUserMutationResponse|http:Response {
return {
"data":{"muting":false}
};
}

# Post lookup by Post ID
#
# + id - A single Post ID.
# + tweet\.fields - A comma separated list of Tweet fields to display.
# + expansions - A comma separated list of fields to expand.
# + media\.fields - A comma separated list of Media fields to display.
# + poll\.fields - A comma separated list of Poll fields to display.
# + user\.fields - A comma separated list of User fields to display.
# + place\.fields - A comma separated list of Place fields to display.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function get tweets/[TweetId id](("attachments"|"author_id"|"card_uri"|"context_annotations"|"conversation_id"|"created_at"|"edit_controls"|"edit_history_tweet_ids"|"entities"|"geo"|"id"|"in_reply_to_user_id"|"lang"|"non_public_metrics"|"note_tweet"|"organic_metrics"|"possibly_sensitive"|"promoted_metrics"|"public_metrics"|"referenced_tweets"|"reply_settings"|"scopes"|"source"|"text"|"username"|"withheld")[]? tweet\.fields, ("attachments.media_keys"|"attachments.media_source_tweet"|"attachments.poll_ids"|"author_id"|"edit_history_tweet_ids"|"entities.mentions.username"|"geo.place_id"|"in_reply_to_user_id"|"entities.note.mentions.username"|"referenced_tweets.id"|"referenced_tweets.id.author_id"|"author_screen_name")[]? expansions, ("alt_text"|"duration_ms"|"height"|"media_key"|"non_public_metrics"|"organic_metrics"|"preview_image_url"|"promoted_metrics"|"public_metrics"|"type"|"url"|"variants"|"width")[]? media\.fields, ("duration_minutes"|"end_datetime"|"id"|"options"|"voting_status")[]? poll\.fields, ("connection_status"|"created_at"|"description"|"entities"|"id"|"location"|"most_recent_tweet_id"|"name"|"pinned_tweet_id"|"profile_image_url"|"protected"|"public_metrics"|"receives_your_dm"|"subscription_type"|"url"|"username"|"verified"|"verified_type"|"withheld")[]? user\.fields, ("contained_within"|"country"|"country_code"|"full_name"|"geo"|"id"|"name"|"place_type")[]? place\.fields) returns Get2TweetsIdResponse|http:Response {
return {
"data":{"edit_history_tweet_ids":["1806286701704462623"],"id":"1806286701704462623","text":"aasbcascbasjbc"}
};
}

resource function get users/'by/username/[string username](("connection_status"|"created_at"|"description"|"entities"|"id"|"location"|"most_recent_tweet_id"|"name"|"pinned_tweet_id"|"profile_image_url"|"protected"|"public_metrics"|"receives_your_dm"|"subscription_type"|"url"|"username"|"verified"|"verified_type"|"withheld")[]? user\.fields, ("most_recent_tweet_id"|"pinned_tweet_id")[]? expansions, ("attachments"|"author_id"|"card_uri"|"context_annotations"|"conversation_id"|"created_at"|"edit_controls"|"edit_history_tweet_ids"|"entities"|"geo"|"id"|"in_reply_to_user_id"|"lang"|"non_public_metrics"|"note_tweet"|"organic_metrics"|"possibly_sensitive"|"promoted_metrics"|"public_metrics"|"referenced_tweets"|"reply_settings"|"scopes"|"source"|"text"|"username"|"withheld")[]? tweet\.fields) returns Get2UsersByUsernameUsernameResponse|http:Response {
return {
"data":{"id":"350224247","name":"Kumar Sangakkara","username":"KumarSanga2"}
};
}

# Creation of a Post
#
# + return - returns can be any of following types
# http:Created (The request has succeeded.)
# http:Response (The request has failed.)
resource function post tweets(@http:Payload TweetCreateRequest payload) returns TweetCreateResponse|http:Response {
return {
"data":{"id":"1807808193139204482","text":"Twitter Test at[1719850035,0.227505100]","edit_history_tweet_ids":["1807808193139204482"]}
};
}

# Add Post to Bookmarks
#
# + id - The ID of the authenticated source User for whom to add bookmarks.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function post users/[UserIdMatchesAuthenticatedUser id]/bookmarks(@http:Payload BookmarkAddRequest payload) returns BookmarkMutationResponse|http:Response {
return {
"data":{"bookmarked":true}
};
}

# Follow User
#
# + id - The ID of the authenticated source User that is requesting to follow the target User.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function post users/[UserIdMatchesAuthenticatedUser id]/following(@http:Payload UsersFollowingCreateRequest payload) returns UsersFollowingCreateResponse|http:Response {
return {
"data":{"following":true,"pending_follow":false}
};
}

# Causes the User (in the path) to like the specified Post
#
# + id - The ID of the authenticated source User that is requesting to like the Post.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function post users/[UserIdMatchesAuthenticatedUser id]/likes(@http:Payload UsersLikesCreateRequest payload) returns UsersLikesCreateResponse|http:Response {
return {
"data":{"liked":true}
};
}

# Mute User by User ID.
#
# + id - The ID of the authenticated source User that is requesting to mute the target User.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function post users/[UserIdMatchesAuthenticatedUser id]/muting(@http:Payload MuteUserRequest payload) returns MuteUserMutationResponse|http:Response {
return {
"data":{"muting":true}
};
}

# Causes the User (in the path) to repost the specified Post.
#
# + id - The ID of the authenticated source User that is requesting to repost the Post.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function post users/[UserIdMatchesAuthenticatedUser id]/retweets(@http:Payload UsersRetweetsCreateRequest payload) returns UsersRetweetsCreateResponse|http:Response {
return {
"data":{"retweeted":true,"rest_id":"1807808194787590411"}
};
}

# User lookup by IDs
#
# + ids - A list of User IDs, comma-separated. You can specify up to 100 IDs.
# + user\.fields - A comma separated list of User fields to display.
# + expansions - A comma separated list of fields to expand.
# + tweet\.fields - A comma separated list of Tweet fields to display.
# + return - returns can be any of following types
# http:Ok (The request has succeeded.)
# http:Response (The request has failed.)
resource function get users(UserId[] ids, ("connection_status"|"created_at"|"description"|"entities"|"id"|"location"|"most_recent_tweet_id"|"name"|"pinned_tweet_id"|"profile_image_url"|"protected"|"public_metrics"|"receives_your_dm"|"subscription_type"|"url"|"username"|"verified"|"verified_type"|"withheld")[]? user\.fields, ("most_recent_tweet_id"|"pinned_tweet_id")[]? expansions, ("attachments"|"author_id"|"card_uri"|"context_annotations"|"conversation_id"|"created_at"|"edit_controls"|"edit_history_tweet_ids"|"entities"|"geo"|"id"|"in_reply_to_user_id"|"lang"|"non_public_metrics"|"note_tweet"|"organic_metrics"|"possibly_sensitive"|"promoted_metrics"|"public_metrics"|"referenced_tweets"|"reply_settings"|"scopes"|"source"|"text"|"username"|"withheld")[]? tweet\.fields) returns Get2UsersResponse|http:Response {
return {
"data":[{"id":"350224247","name":"Kumar Sangakkara","username":"KumarSanga2"}]
};
}
};

function init() returns error? {
if isLiveServer {
log:printInfo("Skiping mock server initialization as the tests are running on live server");
return;
}
log:printInfo("Initiating mock server");
check httpListener.attach(mockService, "/");
check httpListener.'start();
}
Loading

0 comments on commit bbe31a2

Please sign in to comment.