Skip to content

Commit

Permalink
Merge pull request #2 from elliotBraem/feat/edge-cases
Browse files Browse the repository at this point in the history
handles edge cases and better styles
  • Loading branch information
elliotBraem authored Dec 20, 2024
2 parents 00c72de + 6d99479 commit dec4299
Show file tree
Hide file tree
Showing 21 changed files with 10,137 additions and 201 deletions.
45 changes: 0 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
- [Submission Process](#submission-process)
- [Moderation System](#moderation-system)
- [Rate Limiting](#rate-limiting)
- [Customization](#customization)
- [Frontend Customization](#frontend-customization)
- [Backend Customization](#backend-customization)
- [Contributing](#contributing)

</details>
Expand Down Expand Up @@ -226,48 +223,6 @@ To maintain quality:
- Rate limits reset daily
- Exceeding the limit results in a notification tweet

## Customization

### Frontend Customization

The frontend can be customized in several ways:

1. **Styling**
- Modify `frontend/tailwind.config.js` for theme customization
- Update global styles in `frontend/src/index.css`
- Component-specific styles in respective component files

2. **Components**
- Add new components in `frontend/src/components/`
- Modify existing components for different layouts or functionality

3. **Configuration**
- Update API endpoints in environment variables
- Modify build settings in `vite.config.ts`

See the [Frontend README](./frontend/README.md) for detailed customization options.

### Backend Customization

The backend service can be extended and customized:

1. **Services**
- Add new services in `backend/src/services/`
- Modify existing services for different functionality
- Extend API endpoints as needed

2. **Configuration**
- Update environment variables for different integrations
- Modify admin settings in `src/config/`
- Adjust rate limits and other constraints

3. **Integration**
- Add new blockchain integrations
- Extend social media support
- Implement additional APIs

See the [Backend README](./backend/README.md) for detailed customization options.

## Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
Expand Down
18 changes: 18 additions & 0 deletions backend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/** @type {import('jest').Config} */
export default {
preset: "ts-jest",
testEnvironment: "node",
extensionsToTreatAsEsm: [".ts"],
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
transform: {
"^.+\\.tsx?$": [
"ts-jest",
{
useESM: true,
},
],
},
setupFiles: ["<rootDir>/src/__tests__/setup.ts"],
};
7 changes: 5 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"scripts": {
"build": "bun build ./src/index.ts --target=bun --outdir=dist --format=esm",
"start": "bun run dist/index.js",
"dev": "bun run --watch src/index.ts"
"dev": "bun run --watch src/index.ts",
"test": "jest",
"test:watch": "jest --watch"
},
"browserslist": {
"production": [
Expand All @@ -27,13 +29,14 @@
"@types/ora": "^3.2.0",
"bun-types": "^1.1.40",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.1",
"typescript": "^5.3.3"
},
"dependencies": {
"@types/cors": "^2.8.17",
"agent-twitter-client": "^0.0.16",
"cors": "^2.8.5",
"@types/cors": "^2.8.17",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"ora": "^8.1.1",
Expand Down
90 changes: 90 additions & 0 deletions backend/src/__tests__/mocks/twitter-client.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Tweet } from "agent-twitter-client";

export class MockScraper {
private mockTweets: Tweet[] = [];
private _isLoggedIn = false;
private cookies: string[] = [];

// Method to add mock tweets for testing
public addMockTweet(tweet: Tweet) {
this.mockTweets.push(tweet);
}

// Method to clear mock tweets
public clearMockTweets() {
this.mockTweets = [];
}

async login(
username: string,
password: string,
email: string,
): Promise<void> {
this._isLoggedIn = true;
}

async logout(): Promise<void> {
this._isLoggedIn = false;
}

async isLoggedIn(): Promise<boolean> {
return this._isLoggedIn;
}

async setCookies(cookies: string[]): Promise<void> {
this.cookies = cookies;
}

async getCookies(): Promise<string[]> {
return this.cookies;
}

async getUserIdByScreenName(screenName: string): Promise<string> {
return `mock-user-id-${screenName}`;
}

async fetchSearchTweets(
query: string,
count: number,
mode: any,
cursor?: string,
): Promise<{ tweets: Tweet[] }> {
// If cursor is provided, simulate pagination by returning tweets after that ID
if (cursor) {
const cursorIndex = this.mockTweets.findIndex((t) => t.id === cursor);
if (cursorIndex !== -1) {
return {
tweets: this.mockTweets.slice(
cursorIndex + 1,
cursorIndex + 1 + count,
),
};
}
}

return {
tweets: this.mockTweets.slice(0, count),
};
}

async getTweet(tweetId: string): Promise<Tweet | null> {
return this.mockTweets.find((t) => t.id === tweetId) || null;
}

async sendTweet(message: string, replyToId?: string): Promise<Response> {
const mockResponse = {
json: async () => ({
data: {
create_tweet: {
tweet_results: {
result: {
rest_id: `mock-reply-${Date.now()}`,
},
},
},
},
}),
};
return mockResponse as Response;
}
}
83 changes: 83 additions & 0 deletions backend/src/__tests__/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { beforeAll, mock } from "bun:test";

// Mock environment variables
process.env.PORT = "3000";
process.env.NODE_ENV = "test";

// Mock Bun server
const mockServer = {
upgrade: mock(() => true),
fetch: mock(() => new Response()),
publish: mock(() => {}),
unsubscribe: mock(() => {}),
reload: mock(() => {}),
pendingWebSockets: new Set(),
stop: mock(() => {}),
};

const mockFile = {
exists: mock(() => Promise.resolve(true)),
text: mock(() => Promise.resolve("")),
stream: mock(() => new ReadableStream()),
size: 0,
type: "text/plain",
};

// Create a proxy to handle server initialization
const serverProxy = new Proxy(mockServer, {
get: (target, prop) => {
if (prop === "upgrade") {
return (req: Request) => true;
}
return target[prop as keyof typeof target];
},
});

globalThis.Bun = {
serve: mock(() => serverProxy),
file: mock((path: string) => mockFile),
} as any;

// Mock logger
const mockLogger = {
info: mock(() => {}),
error: mock(() => {}),
debug: mock(() => {}),
};

const mockSpinner = {
startSpinner: mock(() => {}),
succeedSpinner: mock(() => {}),
failSpinner: mock(() => {}),
cleanup: mock(() => {}),
};

// Mock modules
import { logger } from "../utils/logger";
Object.assign(logger, mockLogger);
Object.assign(logger, mockSpinner);

// Mock config
import config from "../config/config";
Object.assign(config, {
twitter: {
username: "test_user",
password: "test_pass",
email: "[email protected]",
},
});

// Mock ADMIN_ACCOUNTS
import { ADMIN_ACCOUNTS } from "../config/admins";
(ADMIN_ACCOUNTS as any) = ["admin"];

// Mock server functions
import { main, broadcastUpdate } from "../index";
Object.assign(
main,
mock(() => Promise.resolve()),
);
Object.assign(
broadcastUpdate,
mock(() => {}),
);
Loading

0 comments on commit dec4299

Please sign in to comment.