-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enabled ci-cd and enhanced the counter logic
- Loading branch information
1 parent
470f3a3
commit 8553012
Showing
8 changed files
with
6,110 additions
and
593 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name: Node.js CI | ||
|
||
on: | ||
push: | ||
branches: [master] | ||
pull_request: | ||
branches: [master] | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
|
||
services: | ||
mongo: | ||
image: mongo | ||
ports: | ||
- 27017:27017 | ||
|
||
strategy: | ||
matrix: | ||
node-version: [14.x, 16.x] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v2 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
cache: 'npm' | ||
|
||
- name: Install dependencies | ||
run: npm ci | ||
|
||
- name: Run tests | ||
run: npm test | ||
env: | ||
MONGODB_URI: ${{ secrets.MONGODB_URI }} | ||
PORT: ${{ secrets.PORT }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
const request = require('supertest'); | ||
const { MongoClient } = require('mongodb'); | ||
const { MongoMemoryServer } = require('mongodb-memory-server'); | ||
const makeApp = require('../../api/view-counter'); | ||
|
||
// This suite tests the API endpoints of the view-counter application | ||
describe('API /view-counter Tests', () => { | ||
let mongoServer; | ||
let client; | ||
let app; | ||
|
||
// Set up an in-memory MongoDB instance before running tests | ||
beforeAll(async () => { | ||
mongoServer = await MongoMemoryServer.create(); | ||
const uri = mongoServer.getUri(); | ||
console.log('Test MongoDB URI:', uri); | ||
client = new MongoClient(uri); | ||
await client.connect(); | ||
|
||
// Initialize the app with a test database client | ||
app = makeApp(client); | ||
}); | ||
|
||
// Clean up and close MongoDB connection after tests are complete | ||
afterAll(async () => { | ||
await client.close(); | ||
await mongoServer.stop(); | ||
}); | ||
|
||
// Test for successful view count increment and badge URL generation | ||
test('increments view count and returns badge URL for valid username', async () => { | ||
const username = 'testuser'; | ||
const response = await request(app).get('/api/view-counter').query({ username }); | ||
expect(response.status).toBe(302); | ||
|
||
// Check if the response redirects to the correct badge URL | ||
const badgeUrlRegex = /^https:\/\/custom-icon-badges\.demolab\.com\/static\/v1\?.*/; | ||
expect(response.headers.location).toMatch(badgeUrlRegex); | ||
|
||
// Verify the view count in the database | ||
const db = client.db('githubViews'); | ||
const result = await db.collection('viewCounts').findOne({ username }); | ||
expect(result).not.toBeNull(); | ||
expect(result.views).toBe(1); | ||
|
||
// Additional logging for debugging purposes | ||
const allDocuments = await db.collection('viewCounts').find({}).toArray(); | ||
console.log('All documents in viewCounts collection:', allDocuments); | ||
}); | ||
|
||
// Test for handling missing username parameter | ||
test('returns 400 Bad Request for missing username', async () => { | ||
const response = await request(app).get('/api/view-counter'); | ||
expect(response.status).toBe(400); | ||
}); | ||
|
||
// Test for handling concurrent requests correctly | ||
test('handles concurrent requests correctly', async () => { | ||
const username = 'concurrentUser'; | ||
const requestCount = 5; | ||
|
||
// Send multiple concurrent requests | ||
const promises = Array.from({ length: requestCount }, () => | ||
request(app).get('/api/view-counter').query({ username }), | ||
); | ||
|
||
const responses = await Promise.all(promises); | ||
responses.forEach((response) => { | ||
expect(response.status).toBe(302); | ||
expect(response.headers.location).toMatch( | ||
/^https:\/\/custom-icon-badges\.demolab\.com\/static\/v1\?.*/, | ||
); | ||
}); | ||
|
||
// Verify that the view count matches the number of requests sent | ||
const db = client.db('githubViews'); | ||
const result = await db.collection('viewCounts').findOne({ username }); | ||
expect(result.views).toBe(requestCount); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
const { formatNumberWithCommas, formatLargeNumber, generateBadge } = require('../badgeGenerator'); | ||
|
||
describe('Badge Generator Tests', () => { | ||
// Tests for formatNumberWithCommas | ||
describe('formatNumberWithCommas function', () => { | ||
// Standard formatting tests | ||
test('formats numbers with commas', () => { | ||
expect(formatNumberWithCommas(1000)).toBe('1,000'); | ||
expect(formatNumberWithCommas(1234567)).toBe('1,234,567'); | ||
}); | ||
|
||
// Handling small numbers | ||
test('handles small numbers without commas', () => { | ||
expect(formatNumberWithCommas(999)).toBe('999'); | ||
}); | ||
|
||
// Zero handling | ||
test('handles zero correctly', () => { | ||
expect(formatNumberWithCommas(0)).toBe('0'); | ||
}); | ||
|
||
// Edge case tests for negative numbers and non-numeric values | ||
test('handles negative numbers', () => { | ||
expect(formatNumberWithCommas(-1000)).toBe('-1,000'); | ||
}); | ||
|
||
test('handles non-numeric values', () => { | ||
expect(formatLargeNumber('abcd')).toBe('NaN'); | ||
}); | ||
}); | ||
|
||
// Tests for formatLargeNumber | ||
describe('formatLargeNumber function', () => { | ||
// Standard abbreviation tests | ||
test('formats large numbers with abbreviations', () => { | ||
expect(formatLargeNumber(150000)).toBe('150k'); | ||
expect(formatLargeNumber(2000000)).toBe('2M'); | ||
}); | ||
|
||
// Handling smaller numbers | ||
test('handles numbers less than 1000 without abbreviation', () => { | ||
expect(formatLargeNumber(999)).toBe('999'); | ||
}); | ||
|
||
// Handling millions and billions | ||
test('handles millions and billions correctly', () => { | ||
expect(formatLargeNumber(1000000)).toBe('1M'); | ||
expect(formatLargeNumber(1000000000)).toBe('1B'); | ||
}); | ||
|
||
// Edge case tests for negative numbers, non-numeric values, and floating-point numbers | ||
test('handles negative numbers', () => { | ||
expect(formatLargeNumber(-100000)).toBe('-100,000'); | ||
}); | ||
|
||
test('handles non-numeric values', () => { | ||
expect(formatLargeNumber('abcd')).toBe('NaN'); | ||
}); | ||
|
||
test('handles floating-point numbers', () => { | ||
expect(formatLargeNumber(999.99)).toBe('999.99'); | ||
}); | ||
}); | ||
|
||
// Tests for generateBadge | ||
describe('generateBadge function', () => { | ||
// Test for correct badge URL generation for small numbers | ||
test('generates correct badge URL for small numbers', () => { | ||
const count = 150; | ||
const expectedUrl = | ||
'https://custom-icon-badges.demolab.com/static/v1?label=Profile+Visitors&message=150&color=007ec6&style=for-the-badge&logo=github&logoColor=white&logoSource=feather'; | ||
expect(generateBadge(count)).toBe(expectedUrl); | ||
}); | ||
|
||
test('generates correct badge URL for large numbers', () => { | ||
const count = 150000; | ||
const expectedUrl = | ||
'https://custom-icon-badges.demolab.com/static/v1?label=Profile+Visitors&message=150k&color=007ec6&style=for-the-badge&logo=github&logoColor=white&logoSource=feather'; | ||
expect(generateBadge(count)).toBe(expectedUrl); | ||
}); | ||
|
||
// Handling zero views | ||
test('handles zero views correctly', () => { | ||
const count = 0; | ||
const expectedUrl = | ||
'https://custom-icon-badges.demolab.com/static/v1?label=Profile+Visitors&message=0&color=007ec6&style=for-the-badge&logo=github&logoColor=white&logoSource=feather'; | ||
expect(generateBadge(count)).toBe(expectedUrl); | ||
}); | ||
|
||
// Handling very large numbers | ||
test('handles very large numbers correctly', () => { | ||
const count = 1000000000; // 1 billion | ||
const expectedUrl = | ||
'https://custom-icon-badges.demolab.com/static/v1?label=Profile+Visitors&message=1B&color=007ec6&style=for-the-badge&logo=github&logoColor=white&logoSource=feather'; | ||
expect(generateBadge(count)).toBe(expectedUrl); | ||
}); | ||
|
||
// Additional scenario tests for different styles, colors | ||
test('generates badge with custom style and color', () => { | ||
const count = 500; | ||
const style = 'for-the-badge'; | ||
const color = '007ec6'; | ||
const expectedUrl = | ||
'https://custom-icon-badges.demolab.com/static/v1?label=Profile+Visitors&message=500&color=007ec6&style=for-the-badge&logo=github&logoColor=white&logoSource=feather'; | ||
expect(generateBadge(count, style, color)).toBe(expectedUrl); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
jest.mock('dotenv', () => ({ | ||
config: jest.fn().mockImplementation(() => { | ||
process.env.MONGODB_URI = 'mockMongoUri'; | ||
process.env.PORT = '3001'; | ||
}), | ||
})); | ||
|
||
const configModule = require('../config'); | ||
|
||
describe('Configuration Tests', () => { | ||
const originalEnv = process.env; | ||
|
||
beforeEach(() => { | ||
jest.resetModules(); // Reset modules to clear any cached data | ||
process.env = { ...originalEnv }; // Reset environment variables to their original state | ||
}); | ||
|
||
afterAll(() => { | ||
process.env = originalEnv; // Restore original environment variables after tests | ||
}); | ||
|
||
// Test loading of MongoDB URI | ||
test('loads correct MongoDB URI', () => { | ||
process.env.MONGODB_URI = 'mockMongoUri'; | ||
jest.resetModules(); // Reset modules after changing the environment variable | ||
const config = require('../config'); // Reload the module to reflect the new environment variable | ||
expect(config.mongodb.uri).toBe('mockMongoUri'); | ||
}); | ||
|
||
// Test error for missing MongoDB URI | ||
test('throws error if MONGODB_URI is missing', () => { | ||
delete process.env.MONGODB_URI; | ||
expect(() => configModule.__get__('config')).toThrow(); | ||
}); | ||
|
||
// Test loading of server port | ||
test('loads correct server port', () => { | ||
process.env.PORT = '3001'; | ||
jest.resetModules(); // Reset modules after changing the environment variable | ||
const config = require('../config'); // Reload the module to reflect the new environment variable | ||
expect(config.server.port).toBe(3001); | ||
}); | ||
|
||
// Test defaults to port 3001 if PORT not set | ||
test('defaults to port 3001 if PORT not set', () => { | ||
delete process.env.PORT; | ||
jest.resetModules(); // Reset modules after changing the environment variable | ||
const config = require('../config'); // Reload the module to reflect the new environment variable | ||
expect(config.server.port).toBe(3001); | ||
}); | ||
|
||
// Test sets rate limiting configuration | ||
test('sets rate limiting configuration', () => { | ||
const config = require('../config'); // Directly require the module | ||
expect(config.rateLimit.windowMs).toBe(60 * 1000); | ||
expect(config.rateLimit.max).toBe(100); | ||
}); | ||
}); |
Oops, something went wrong.