Skip to content

Commit 928a406

Browse files
committed
Add file upload capability to browser tool
1 parent 55bbe88 commit 928a406

File tree

14 files changed

+1525
-8
lines changed

14 files changed

+1525
-8
lines changed

e2e/fixtures/file-upload-test.html

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>File Upload Test</title>
7+
<style>
8+
body {
9+
font-family: Arial, sans-serif;
10+
max-width: 800px;
11+
margin: 0 auto;
12+
padding: 20px;
13+
}
14+
.upload-container {
15+
border: 2px dashed #ccc;
16+
padding: 20px;
17+
text-align: center;
18+
margin: 20px 0;
19+
}
20+
.file-input {
21+
margin-bottom: 10px;
22+
}
23+
.hidden-file-input {
24+
display: none;
25+
}
26+
.custom-file-button {
27+
background-color: #4CAF50;
28+
color: white;
29+
padding: 10px 15px;
30+
border: none;
31+
border-radius: 4px;
32+
cursor: pointer;
33+
}
34+
.file-list {
35+
margin-top: 20px;
36+
border: 1px solid #eee;
37+
padding: 10px;
38+
}
39+
.file-item {
40+
padding: 5px;
41+
margin: 5px 0;
42+
background-color: #f9f9f9;
43+
}
44+
.success {
45+
color: green;
46+
font-weight: bold;
47+
display: none;
48+
}
49+
</style>
50+
</head>
51+
<body>
52+
<h1>File Upload Test Page</h1>
53+
<p>This page is used to test the file upload functionality in the browser tool.</p>
54+
55+
<div class="upload-container">
56+
<h2>Standard File Input</h2>
57+
<input type="file" id="fileInput" class="file-input">
58+
<div id="standardSuccess" class="success">File uploaded successfully!</div>
59+
<div id="standardFileList" class="file-list"></div>
60+
</div>
61+
62+
<div class="upload-container">
63+
<h2>Hidden File Input with Custom Button</h2>
64+
<input type="file" id="hiddenFileInput" class="hidden-file-input">
65+
<button id="customButton" class="custom-file-button">Choose File</button>
66+
<div id="hiddenSuccess" class="success">File uploaded successfully!</div>
67+
<div id="hiddenFileList" class="file-list"></div>
68+
</div>
69+
70+
<script>
71+
// Standard file input
72+
document.getElementById('fileInput').addEventListener('change', function(e) {
73+
const fileList = document.getElementById('standardFileList');
74+
fileList.innerHTML = '';
75+
76+
for (const file of this.files) {
77+
const fileItem = document.createElement('div');
78+
fileItem.className = 'file-item';
79+
fileItem.textContent = `File: ${file.name}, Size: ${file.size} bytes, Type: ${file.type}`;
80+
fileList.appendChild(fileItem);
81+
}
82+
83+
document.getElementById('standardSuccess').style.display = 'block';
84+
});
85+
86+
// Custom button for hidden file input
87+
document.getElementById('customButton').addEventListener('click', function() {
88+
document.getElementById('hiddenFileInput').click();
89+
});
90+
91+
// Hidden file input
92+
document.getElementById('hiddenFileInput').addEventListener('change', function(e) {
93+
const fileList = document.getElementById('hiddenFileList');
94+
fileList.innerHTML = '';
95+
96+
for (const file of this.files) {
97+
const fileItem = document.createElement('div');
98+
fileItem.className = 'file-item';
99+
fileItem.textContent = `File: ${file.name}, Size: ${file.size} bytes, Type: ${file.type}`;
100+
fileList.appendChild(fileItem);
101+
}
102+
103+
document.getElementById('hiddenSuccess').style.display = 'block';
104+
});
105+
</script>
106+
</body>
107+
</html>

e2e/fixtures/test-upload-file.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
This is a test file for upload functionality.
2+
It contains multiple lines of text to verify that
3+
file uploads work correctly in the browser tool.
4+
5+
The file upload feature should be able to:
6+
1. Upload files to standard file inputs
7+
2. Upload files to hidden file inputs
8+
3. Handle different file types
9+
4. Provide appropriate feedback
10+
11+
This test file is used in the e2e tests to verify
12+
that the file upload functionality works as expected.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const vscode = require('vscode');
2+
const path = require('path');
3+
const fs = require('fs');
4+
5+
describe('Browser Action Upload Mock Tests', () => {
6+
const testFilePath = path.join(__dirname, '../../fixtures/test-upload-file.txt');
7+
const testHtmlPath = path.join(__dirname, '../../fixtures/file-upload-test.html');
8+
9+
beforeAll(() => {
10+
// Ensure test files exist
11+
expect(fs.existsSync(testFilePath)).toBe(true);
12+
expect(fs.existsSync(testHtmlPath)).toBe(true);
13+
});
14+
15+
test('Browser upload action parameters are correctly parsed', async () => {
16+
// This is a mock test that verifies the upload action parameters are correctly parsed
17+
// The actual upload functionality is tested in the integration tests
18+
19+
const mockBrowserSession = {
20+
upload: jest.fn().mockResolvedValue({
21+
screenshot: 'data:image/png;base64,mockScreenshot',
22+
logs: 'File uploaded successfully',
23+
}),
24+
};
25+
26+
// Simulate the upload action
27+
const result = await mockBrowserSession.upload('#fileInput', testFilePath);
28+
29+
// Verify the mock was called with the correct parameters
30+
expect(mockBrowserSession.upload).toHaveBeenCalledWith('#fileInput', testFilePath);
31+
32+
// Verify the result structure
33+
expect(result).toHaveProperty('screenshot');
34+
expect(result).toHaveProperty('logs');
35+
});
36+
37+
test('Upload action handles errors correctly', async () => {
38+
// Mock browser session with error
39+
const mockBrowserSession = {
40+
upload: jest.fn().mockRejectedValue(new Error('File not found')),
41+
};
42+
43+
// Attempt to upload with invalid file path
44+
try {
45+
await mockBrowserSession.upload('#fileInput', 'non-existent-file.txt');
46+
fail('Should have thrown an error');
47+
} catch (error) {
48+
expect(error.message).toBe('File not found');
49+
}
50+
});
51+
});
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const vscode = require('vscode');
2+
const path = require('path');
3+
const fs = require('fs');
4+
5+
describe('Browser Upload Verification Tests', () => {
6+
const testFilePath = path.join(__dirname, '../../fixtures/test-upload-file.txt');
7+
const testHtmlPath = path.join(__dirname, '../../fixtures/file-upload-test.html');
8+
9+
beforeAll(() => {
10+
// Ensure test files exist
11+
expect(fs.existsSync(testFilePath)).toBe(true);
12+
expect(fs.existsSync(testHtmlPath)).toBe(true);
13+
});
14+
15+
test('File upload parameters are correctly validated', () => {
16+
// Test validation of selector parameter
17+
const validateSelector = (selector) => {
18+
if (!selector) {
19+
return { valid: false, error: 'Missing selector parameter' };
20+
}
21+
return { valid: true };
22+
};
23+
24+
// Test validation of filepath parameter
25+
const validateFilepath = (filepath) => {
26+
if (!filepath) {
27+
return { valid: false, error: 'Missing filepath parameter' };
28+
}
29+
if (!fs.existsSync(filepath)) {
30+
return { valid: false, error: `File not found: ${filepath}` };
31+
}
32+
return { valid: true };
33+
};
34+
35+
// Test cases for selector validation
36+
expect(validateSelector('')).toEqual({ valid: false, error: 'Missing selector parameter' });
37+
expect(validateSelector(null)).toEqual({ valid: false, error: 'Missing selector parameter' });
38+
expect(validateSelector(undefined)).toEqual({ valid: false, error: 'Missing selector parameter' });
39+
expect(validateSelector('#fileInput')).toEqual({ valid: true });
40+
41+
// Test cases for filepath validation
42+
expect(validateFilepath('')).toEqual({ valid: false, error: 'Missing filepath parameter' });
43+
expect(validateFilepath(null)).toEqual({ valid: false, error: 'Missing filepath parameter' });
44+
expect(validateFilepath(undefined)).toEqual({ valid: false, error: 'Missing filepath parameter' });
45+
expect(validateFilepath('non-existent-file.txt')).toEqual({
46+
valid: false,
47+
error: 'File not found: non-existent-file.txt'
48+
});
49+
expect(validateFilepath(testFilePath)).toEqual({ valid: true });
50+
});
51+
52+
test('Upload action correctly processes file paths', () => {
53+
// Test path normalization
54+
const normalizePath = (filepath) => {
55+
if (!filepath) return '';
56+
return path.normalize(filepath);
57+
};
58+
59+
// Test cases for path normalization
60+
expect(normalizePath('/path/to/file.txt')).toBe('/path/to/file.txt');
61+
expect(normalizePath('/path/../to/file.txt')).toBe('/to/file.txt');
62+
expect(normalizePath('./file.txt')).toBe('file.txt');
63+
64+
// Test absolute path resolution
65+
const resolveAbsolutePath = (filepath, cwd) => {
66+
if (!filepath) return '';
67+
if (path.isAbsolute(filepath)) return filepath;
68+
return path.resolve(cwd, filepath);
69+
};
70+
71+
// Test cases for absolute path resolution
72+
const cwd = '/test/cwd';
73+
expect(resolveAbsolutePath('/absolute/path/file.txt', cwd)).toBe('/absolute/path/file.txt');
74+
expect(resolveAbsolutePath('relative/path/file.txt', cwd)).toBe('/test/cwd/relative/path/file.txt');
75+
});
76+
});
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
const vscode = require('vscode');
2+
const path = require('path');
3+
const fs = require('fs');
4+
5+
describe('Run Upload Test', () => {
6+
const testFilePath = path.join(__dirname, '../../fixtures/test-upload-file.txt');
7+
const testHtmlPath = path.join(__dirname, '../../fixtures/file-upload-test.html');
8+
9+
beforeAll(() => {
10+
// Ensure test files exist
11+
expect(fs.existsSync(testFilePath)).toBe(true);
12+
expect(fs.existsSync(testHtmlPath)).toBe(true);
13+
});
14+
15+
test('Test file upload integration with browser action', async () => {
16+
// This test is a placeholder for the actual integration test
17+
// The real test would be run in the e2e/src/suite/browser-action-upload.test.ts file
18+
19+
// Mock the browser session
20+
const mockBrowserSession = {
21+
launchBrowser: jest.fn().mockResolvedValue(undefined),
22+
navigateToUrl: jest.fn().mockResolvedValue({
23+
screenshot: 'data:image/png;base64,mockScreenshot',
24+
logs: 'Page loaded',
25+
}),
26+
upload: jest.fn().mockResolvedValue({
27+
screenshot: 'data:image/png;base64,mockScreenshot',
28+
logs: 'File uploaded successfully',
29+
}),
30+
closeBrowser: jest.fn().mockResolvedValue({}),
31+
};
32+
33+
// Simulate the test flow
34+
await mockBrowserSession.launchBrowser();
35+
36+
// Navigate to the test HTML file using file:// protocol
37+
const fileUrl = `file://${testHtmlPath}`;
38+
await mockBrowserSession.navigateToUrl(fileUrl);
39+
40+
// Upload the test file to the standard file input
41+
await mockBrowserSession.upload('#fileInput', testFilePath);
42+
43+
// Upload the test file to the hidden file input
44+
await mockBrowserSession.upload('#hiddenFileInput', testFilePath);
45+
46+
// Close the browser
47+
await mockBrowserSession.closeBrowser();
48+
49+
// Verify all methods were called with the correct parameters
50+
expect(mockBrowserSession.launchBrowser).toHaveBeenCalled();
51+
expect(mockBrowserSession.navigateToUrl).toHaveBeenCalledWith(fileUrl);
52+
expect(mockBrowserSession.upload).toHaveBeenCalledWith('#fileInput', testFilePath);
53+
expect(mockBrowserSession.upload).toHaveBeenCalledWith('#hiddenFileInput', testFilePath);
54+
expect(mockBrowserSession.closeBrowser).toHaveBeenCalled();
55+
});
56+
57+
test('Test file upload with error handling', async () => {
58+
// Mock the browser session with an error for the upload method
59+
const mockBrowserSession = {
60+
launchBrowser: jest.fn().mockResolvedValue(undefined),
61+
navigateToUrl: jest.fn().mockResolvedValue({
62+
screenshot: 'data:image/png;base64,mockScreenshot',
63+
logs: 'Page loaded',
64+
}),
65+
upload: jest.fn().mockRejectedValue(new Error('File input not found')),
66+
closeBrowser: jest.fn().mockResolvedValue({}),
67+
};
68+
69+
// Simulate the test flow
70+
await mockBrowserSession.launchBrowser();
71+
72+
// Navigate to the test HTML file
73+
const fileUrl = `file://${testHtmlPath}`;
74+
await mockBrowserSession.navigateToUrl(fileUrl);
75+
76+
// Attempt to upload to a non-existent file input
77+
try {
78+
await mockBrowserSession.upload('#nonExistentInput', testFilePath);
79+
fail('Should have thrown an error');
80+
} catch (error) {
81+
expect(error.message).toBe('File input not found');
82+
}
83+
84+
// Close the browser
85+
await mockBrowserSession.closeBrowser();
86+
87+
// Verify methods were called with the correct parameters
88+
expect(mockBrowserSession.launchBrowser).toHaveBeenCalled();
89+
expect(mockBrowserSession.navigateToUrl).toHaveBeenCalledWith(fileUrl);
90+
expect(mockBrowserSession.upload).toHaveBeenCalledWith('#nonExistentInput', testFilePath);
91+
expect(mockBrowserSession.closeBrowser).toHaveBeenCalled();
92+
});
93+
});

0 commit comments

Comments
 (0)