feat(validation): relax Instagram URL validation to support all content types
- Create validateInstagramUrl utility using URL constructor - Replace regex-based validation with hostname and protocol checks - Support posts, reels, IGTV, and URLs with query parameters - Add comprehensive unit tests (22 tests, all passing) - Add integration tests for new URL formats - Update API documentation with supported URL formats Closes: #RelaxInstagramUrlValidation
This commit is contained in:
@@ -71,10 +71,72 @@ describe('Queue API Endpoints', () => {
|
||||
expect(item?.url).toBe('https://www.instagram.com/p/XYZ789');
|
||||
});
|
||||
|
||||
it('should accept Instagram reel URLs', async () => {
|
||||
const request = new Request('http://localhost/api/queue', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
url: 'https://instagram.com/reel/ABC123'
|
||||
})
|
||||
});
|
||||
|
||||
const response = await queuePOST({ request } as any);
|
||||
expect(response.status).toBe(200);
|
||||
const data = await response.json();
|
||||
expect(data.url).toBe('https://instagram.com/reel/ABC123');
|
||||
});
|
||||
|
||||
it('should accept Instagram URLs with query parameters', async () => {
|
||||
const request = new Request('http://localhost/api/queue', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
url: 'https://www.instagram.com/reel/DSevV5CDcNm/?utm_source=ig_web_copy_link'
|
||||
})
|
||||
});
|
||||
|
||||
const response = await queuePOST({ request } as any);
|
||||
expect(response.status).toBe(200);
|
||||
const data = await response.json();
|
||||
expect(data.url).toBe('https://www.instagram.com/reel/DSevV5CDcNm/?utm_source=ig_web_copy_link');
|
||||
});
|
||||
|
||||
it('should accept Instagram IGTV URLs', async () => {
|
||||
const request = new Request('http://localhost/api/queue', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
url: 'https://instagram.com/tv/XYZ789'
|
||||
})
|
||||
});
|
||||
|
||||
const response = await queuePOST({ request } as any);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('should reject HTTP (non-HTTPS) URLs', async () => {
|
||||
const request = new Request('http://localhost/api/queue', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
url: 'http://instagram.com/p/ABC123'
|
||||
})
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await queuePOST({ request } as any);
|
||||
expect(response.status).toBe(400);
|
||||
const data = await response.json();
|
||||
expect(data.message).toContain('HTTPS');
|
||||
} catch (err: any) {
|
||||
expect(err.status).toBe(400);
|
||||
expect(err.body.message).toContain('HTTPS');
|
||||
}
|
||||
});
|
||||
|
||||
it('should reject invalid Instagram URL formats', async () => {
|
||||
const invalidUrls = [
|
||||
'https://facebook.com/post/123',
|
||||
'https://instagram.com/user/profile',
|
||||
'not-a-url',
|
||||
'https://other-site.com'
|
||||
];
|
||||
@@ -93,11 +155,12 @@ describe('Queue API Endpoints', () => {
|
||||
// If we get here, check the response status
|
||||
expect(response.status).toBe(400);
|
||||
const data = await response.json();
|
||||
expect(data.message).toBe('Invalid Instagram URL format. Expected: https://instagram.com/p/{post-id}');
|
||||
// Updated to check for new error messages
|
||||
expect(data.message).toBeTruthy();
|
||||
} catch (err: any) {
|
||||
// SvelteKit's error() throws - check the error
|
||||
expect(err.status).toBe(400);
|
||||
expect(err.body.message).toBe('Invalid Instagram URL format. Expected: https://instagram.com/p/{post-id}');
|
||||
expect(err.body.message).toBeTruthy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +168,33 @@ describe('Queue API Endpoints', () => {
|
||||
expect(queueManager.getAll()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should reject non-Instagram domains', async () => {
|
||||
const invalidUrls = [
|
||||
'https://facebook.com/post/123',
|
||||
'https://twitter.com/status/456',
|
||||
'https://example.com',
|
||||
'https://instagram.com.evil.com/p/123'
|
||||
];
|
||||
|
||||
for (const url of invalidUrls) {
|
||||
const request = new Request('http://localhost/api/queue', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ url })
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await queuePOST({ request } as any);
|
||||
expect(response.status).toBe(400);
|
||||
const data = await response.json();
|
||||
expect(data.message).toContain('instagram.com');
|
||||
} catch (err: any) {
|
||||
expect(err.status).toBe(400);
|
||||
expect(err.body.message).toContain('instagram.com');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should reject missing URL', async () => {
|
||||
const request = new Request('http://localhost/api/queue', {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user