Skip to content

Commit

Permalink
Merge pull request #40 from Te99y/main
Browse files Browse the repository at this point in the history
Unit tests for frontend
  • Loading branch information
gtnolan authored Dec 9, 2024
2 parents 43ad940 + 8323e2b commit 346536d
Show file tree
Hide file tree
Showing 14 changed files with 1,277 additions and 377 deletions.
Binary file added e2e/assets/test-package.zip
Binary file not shown.
69 changes: 69 additions & 0 deletions e2e/packageIO.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { test, expect } from '@playwright/test';
import * as path from 'path';

test.describe('Package Upload and Download E2E Tests', () => {
const testPackageName = 'test-package';
const testPackageVersion = '1.0.0';
const testFileName = 'test-package.zip';
const testFilePath = `e2e/assets/${testFileName}`;
const downloadDir = `e2e/downloads`;

// test('upload a package', async ({ page }) => {
// await page.goto('http://localhost:4000');

// // Login
// await page.fill('input[name="username"]', 'ece30861defaultadminuser');
// await page.fill(
// 'input[name="password"]',
// "correcthorsebatterystaple123(!__+@**(A'\"`;DROP TABLE packages;"
// );
// await page.click('button:has-text("Login")');
// await expect(page.getByText('Welcome, ece30861defaultadminuser!')).toBeVisible();

// // Navigate to the Upload Page
// await page.getByRole('link', { name: 'Upload' }).click();

// page.on('dialog', async (dialog) => {
// expect(dialog.message()).toBe('Package uploaded successfully!'); // Assert the alert message
// await dialog.accept(); // Accept the alert to close it
// });
// // Fill out the upload form
// await page.getByLabel('Package Name:').fill(testPackageName);
// await page.getByLabel('Upload ZIP File:').setInputFiles(testFilePath);
// await page.getByRole('button', { name: 'Upload Package' }).click();
// });

test('download a package', async ({ page, context }) => {
await page.goto('http://localhost:4000'); // Replace with your app URL

// Login
await page.fill('input[name="username"]', 'ece30861defaultadminuser');
await page.fill(
'input[name="password"]',
"correcthorsebatterystaple123(!__+@**(A'\"`;DROP TABLE packages;"
);
await page.click('button:has-text("Login")');
await expect(page.getByText('Welcome, ece30861defaultadminuser!')).toBeVisible();

// Navigate to the Download Page
await page.getByRole('link', { name: 'Download' }).click();
// Search for the package
await page.getByLabel('Search by Name or Regex:').fill(testPackageName);
await page.getByRole('button', { name: 'Search' }).click();
await expect(page.getByText(`${testPackageName} (v${testPackageVersion})`)).toBeVisible();

// Start downloading the package
const [download] = await Promise.all([
context.waitForEvent('download'),
page.click('button:has-text("Download")'),
]);

// Save the downloaded file
const downloadPath = path.join(downloadDir, testFileName);
await download.saveAs(downloadPath);

// Verify the file exists
const fs = require('fs');
expect(fs.existsSync(downloadPath)).toBeTruthy();
});
});
2 changes: 1 addition & 1 deletion frontend/src/pages/download.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const DownloadPage: React.FC = () => {
setSearchPerformed(true);
} else if (response.status === 404) {
setPackages([]);
alert('No packages found with the given regex.');
setError('No packages found with the given regex.');
} else {
setError('Search failed with an unknown error.');
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/pages/history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,14 @@ const HistoryPage: React.FC = () => {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache', // Prevent caching so we dont get 304 but 200
'X-Authorization': authToken,
},
});

if (response.ok) {
const data: HistoryEntry[] = await response.json();
// console.log('Fetched history:', data); // delete this
setHistory(data);
} else {
alert('Failed to fetch history. Please try again.');
Expand Down
48 changes: 40 additions & 8 deletions frontend/src/pages/manageUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,11 @@ const ManageUsers: React.FC = () => {
<div style={{ maxWidth: '700px', margin: '0 auto', padding: '20px', border: '1px solid #ddd', borderRadius: '8px', backgroundColor: '#f9f9f9' }}>
<form onSubmit={(e) => e.preventDefault()} style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<label style={{ fontWeight: 'bold', marginBottom: '5px' }}>Username:</label>
<label htmlFor="username" style={{ fontWeight: 'bold', marginBottom: '5px' }}>
Username:
</label>
<input
id="username"
type="text"
value={newUsername}
onChange={(e) => setNewUsername(e.target.value)}
Expand All @@ -256,8 +259,11 @@ const ManageUsers: React.FC = () => {
/>
</div>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<label style={{ fontWeight: 'bold', marginBottom: '5px' }}>Password:</label>
<label htmlFor="password" style={{ fontWeight: 'bold', marginBottom: '5px' }}>
Password:
</label>
<input
id="password"
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
Expand Down Expand Up @@ -336,16 +342,27 @@ const ManageUsers: React.FC = () => {
</div>
)}


{currentMode === Modes.DELETE_USER && (
<div style={{ maxWidth: '600px', margin: '0 auto', padding: '20px', border: '1px solid #ddd', borderRadius: '8px', backgroundColor: '#f9f9f9' }}>
<div
style={{
maxWidth: '600px',
margin: '0 auto',
padding: '20px',
border: '1px solid #ddd',
borderRadius: '8px',
backgroundColor: '#f9f9f9',
}}
>
<form
onSubmit={(e) => e.preventDefault()}
style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}
>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<label style={{ fontWeight: 'bold', marginBottom: '5px' }}>Username to Delete:</label>
<label htmlFor="usernameToDelete" style={{ fontWeight: 'bold', marginBottom: '5px' }}>
Username to Delete:
</label>
<input
id="usernameToDelete"
type="text"
value={usernameToDelete}
onChange={(e) => setUsernameToDelete(e.target.value)}
Expand Down Expand Up @@ -373,14 +390,26 @@ const ManageUsers: React.FC = () => {
)}

{currentMode === Modes.CREATE_USER_GROUP && (
<div style={{ maxWidth: '600px', margin: '0 auto', padding: '20px', border: '1px solid #ddd', borderRadius: '8px', backgroundColor: '#f9f9f9' }}>
<div
style={{
maxWidth: '600px',
margin: '0 auto',
padding: '20px',
border: '1px solid #ddd',
borderRadius: '8px',
backgroundColor: '#f9f9f9',
}}
>
<form
onSubmit={(e) => e.preventDefault()}
style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}
>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<label style={{ fontWeight: 'bold', marginBottom: '5px' }}>Group Name:</label>
<label htmlFor="groupName" style={{ fontWeight: 'bold', marginBottom: '5px' }}>
Group Name:
</label>
<input
id="groupName"
type="text"
value={newGroupName}
onChange={(e) => setNewGroupName(e.target.value)}
Expand All @@ -389,8 +418,11 @@ const ManageUsers: React.FC = () => {
/>
</div>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<label style={{ fontWeight: 'bold', marginBottom: '5px' }}>Description (Optional):</label>
<label htmlFor="groupDescription" style={{ fontWeight: 'bold', marginBottom: '5px' }}>
Description (Optional):
</label>
<input
id="groupDescription"
type="text"
value={newGroupDescription}
onChange={(e) => setNewGroupDescription(e.target.value)}
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/pages/rating.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const RatingPage: React.FC = () => {
setSearchPerformed(true);
} else if (response.status === 404) {
setPackages([]);
alert('No packages found with the given regex.');
setError('No packages found with the given regex.');
} else {
setError('Search failed with an unknown error.');
}
Expand All @@ -107,6 +107,8 @@ const RatingPage: React.FC = () => {
setOffset(pageOffset);
setHasNextPage(data.length > 0);
setSearchPerformed(true);
} else if (response.status === 404) {
setError('No package found.')
} else {
setError('Search failed with an unknown error.');
}
Expand Down
46 changes: 21 additions & 25 deletions frontend/src/pages/update.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import PageLayout from './pageLayout';

interface PackageMetadata {
ID: string;
ID: number; // Ensure ID is a number
Name: string;
Version: string;
}
Expand All @@ -18,20 +18,16 @@ const UpdatePage: React.FC = () => {
const [url, setUrl] = useState<string>(''); // URL for URL-based updates
const [authToken, setAuthToken] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);

// Pagination state
const [offset, setOffset] = useState<number>(0);
const [hasNextPage, setHasNextPage] = useState<boolean>(false);

const [searchPerformed, setSearchPerformed] = useState<boolean>(false);

// Retrieve auth token from localStorage on component mount
useEffect(() => {
const token = localStorage.getItem('authToken');
if (token) {
setAuthToken(token);
} else {
console.log('No token set while entering update');
console.log('No token set while entering update page.');
}
}, []);

Expand Down Expand Up @@ -65,17 +61,16 @@ const UpdatePage: React.FC = () => {
if (response.status === 200) {
const data: PackageMetadata[] = await response.json();
setPackages(data);
setHasNextPage(false); // Pagination is not applicable for regex searches
setHasNextPage(false);
setSearchPerformed(true);
} else if (response.status === 404) {
setPackages([]);
alert('No packages found with the given regex.');
} else {
setError('Search failed with an unknown error.');
}
} else {
const requestBody = [
{ Name: searchTerm, Version: versionTerm ? versionTerm : '*' },
{ Name: searchTerm, Version: versionTerm || '*' },
];
const response = await fetch(`/packages?offset=${pageOffset}`, {
method: 'POST',
Expand Down Expand Up @@ -121,7 +116,7 @@ const UpdatePage: React.FC = () => {
const isZipFile = selectedFile.type === 'application/zip' || selectedFile.name.endsWith('.zip');

if (!isZipFile) {
alert('Please select a ZIP file.');
alert('Please select a valid ZIP file.');
e.target.value = '';
setFile(null);
} else {
Expand All @@ -144,39 +139,40 @@ const UpdatePage: React.FC = () => {
return;
}

if (file && url) {
alert('Please provide only one of either a ZIP file or a URL for the update.');
return;
}

try {
console.log(`name : ${selectedPackage.Name}`);
let payload: any = {
metadata: {
Name: selectedPackage.Name,
Version: newVersion,
ID: selectedPackage.ID,
ID: Number(selectedPackage.ID),
},
data: {
Name: selectedPackage.Name,
debloat: debloat,
},
data: {},
};

if (file) {
const fileContent = await new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
if (typeof reader.result === 'string') {
resolve(reader.result.split(',')[1]);
resolve(reader.result.split(',')[1]); // Base64 encode
}
};
reader.onerror = (error) => reject(error);
reader.readAsDataURL(file);
});

payload.data = {
Content: fileContent,
Name: selectedPackage.Name,
debloat: debloat,
};
payload.data.Content = fileContent;
} else if (url) {
payload.data = {
URL: url,
Name: selectedPackage.Name,
debloat: debloat,
};
payload.data.URL = url;
}

const response = await fetch(`/package/${selectedPackage.ID}`, {
Expand All @@ -191,14 +187,14 @@ const UpdatePage: React.FC = () => {
if (response.status === 200) {
alert('Version updated successfully!');
} else {
alert(await response.text());
const errorMsg = await response.text();
alert(`Error updating package: ${errorMsg}`);
}
} catch (error) {
console.error('Error updating package:', error);
alert('An error occurred while updating the package.');
}
};

return (
<PageLayout title="Update a Package">
<form onSubmit={(e) => { e.preventDefault(); handleSearch(0); }} style={{ maxWidth: '500px', margin: '0 auto' }}>
Expand Down
Loading

0 comments on commit 346536d

Please sign in to comment.