feat: complete platform upgrade - mobile UI overhaul, custom MAC owner label PDF exports, and project report documentation
This commit is contained in:
1 parent
d7fa520030
commit
97d2c89c15
188 files changed
+7703
-1979
No files matched your search
@@ -0,0 +1,119 @@
|
||||
const { spawn } = require('child_process');
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const WebSocket = require('next/dist/compiled/ws');
|
||||
|
||||
async function loginAdmin() {
|
||||
return new Promise((resolve) => {
|
||||
const data = JSON.stringify({ username: 'admin', password: 'admin' });
|
||||
const req = http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: 3000,
|
||||
path: '/api/auth/login',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': data.length
|
||||
}
|
||||
}, (res) => {
|
||||
let body = '';
|
||||
res.on('data', chunk => body += chunk);
|
||||
res.on('end', () => {
|
||||
const cookies = res.headers['set-cookie'];
|
||||
if (cookies && cookies.length > 0) {
|
||||
const cookieStr = cookies[0];
|
||||
const match = cookieStr.match(/backone_token=([^;]+)/);
|
||||
resolve(match ? match[1] : null);
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
req.on('error', () => resolve(null));
|
||||
req.write(data);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
async function capture() {
|
||||
const token = await loginAdmin();
|
||||
console.log("Logged in admin token:", token ? "FOUND" : "NOT FOUND");
|
||||
|
||||
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
|
||||
const edgeProc = spawn(edgePath, [
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--remote-debugging-port=9222',
|
||||
'--window-size=400,844',
|
||||
'http://localhost:3000/login'
|
||||
]);
|
||||
|
||||
// Wait 2.5s for Edge CDP to listen
|
||||
await new Promise(r => setTimeout(r, 2500));
|
||||
|
||||
try {
|
||||
const targets = await new Promise((resolve, reject) => {
|
||||
http.get('http://127.0.0.1:9222/json', (res) => {
|
||||
let body = '';
|
||||
res.on('data', c => body += c);
|
||||
res.on('end', () => resolve(JSON.parse(body)));
|
||||
}).on('error', reject);
|
||||
});
|
||||
|
||||
const pageTarget = targets.find(t => t.type === 'page');
|
||||
if (!pageTarget || !pageTarget.webSocketDebuggerUrl) {
|
||||
console.error("No CDP page target found:", targets);
|
||||
edgeProc.kill();
|
||||
return;
|
||||
}
|
||||
|
||||
const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);
|
||||
let messageId = 1;
|
||||
const send = (method, params = {}) => {
|
||||
return new Promise((res) => {
|
||||
const id = messageId++;
|
||||
const handler = (data) => {
|
||||
const msg = JSON.parse(data);
|
||||
if (msg.id === id) {
|
||||
ws.removeListener('message', handler);
|
||||
res(msg.result);
|
||||
}
|
||||
};
|
||||
ws.on('message', handler);
|
||||
ws.send(JSON.stringify({ id, method, params }));
|
||||
});
|
||||
};
|
||||
|
||||
ws.on('open', async () => {
|
||||
console.log("Connected to Edge CDP WebSocket!");
|
||||
|
||||
if (token) {
|
||||
await send('Network.setCookie', {
|
||||
name: 'backone_token',
|
||||
value: token,
|
||||
domain: 'localhost',
|
||||
path: '/'
|
||||
});
|
||||
}
|
||||
|
||||
await send('Page.navigate', { url: 'http://localhost:3000/' });
|
||||
// Wait for page load and 3D globe rendering
|
||||
await new Promise(r => setTimeout(r, 5000));
|
||||
|
||||
const screenshot = await send('Page.captureScreenshot', { format: 'png' });
|
||||
const outputPath = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a\\mobile-dashboard-live.png";
|
||||
fs.writeFileSync(outputPath, Buffer.from(screenshot.data, 'base64'));
|
||||
console.log("SUCCESS! Screenshot written to:", outputPath, "Size:", fs.statSync(outputPath).size, "bytes");
|
||||
|
||||
ws.close();
|
||||
edgeProc.kill();
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error("CDP Error:", err.message);
|
||||
edgeProc.kill();
|
||||
}
|
||||
}
|
||||
|
||||
capture();
|
||||
@@ -0,0 +1,22 @@
|
||||
const { Client } = require('ssh2');
|
||||
|
||||
const conn = new Client();
|
||||
conn.on('ready', () => {
|
||||
console.log('SSH Client Ready');
|
||||
const cmd = `tail -n 200 /home/adminbackend/.pm2/logs/backone-backend-error-*.log /home/adminbackend/.pm2/logs/backone-backend-out-*.log /home/adminbackend/.pm2/logs/backone-frontend-error-*.log /home/adminbackend/.pm2/logs/backone-frontend-out-*.log 2>/dev/null | tail -n 200`;
|
||||
conn.exec(cmd, (err, stream) => {
|
||||
if (err) throw err;
|
||||
stream.on('close', (code, signal) => {
|
||||
conn.end();
|
||||
}).on('data', (data) => {
|
||||
console.log(data.toString());
|
||||
}).stderr.on('data', (data) => {
|
||||
console.log('STDERR: ' + data.toString());
|
||||
});
|
||||
});
|
||||
}).connect({
|
||||
host: '103.185.47.52',
|
||||
port: 2222,
|
||||
username: 'adminbackend',
|
||||
password: 'htEo7x6LsBQiEHHH'
|
||||
});
|
||||
@@ -0,0 +1,230 @@
|
||||
const React = require("react");
|
||||
const ReactPDF = require("@react-pdf/renderer");
|
||||
const path = require("path");
|
||||
|
||||
const { Document, Page, Text, View, StyleSheet } = ReactPDF;
|
||||
const h = React.createElement;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
page: {
|
||||
padding: 30,
|
||||
backgroundColor: "#0F172A",
|
||||
color: "#F8FAFC",
|
||||
fontFamily: "Helvetica",
|
||||
},
|
||||
header: {
|
||||
borderBottomWidth: 2,
|
||||
borderBottomColor: "#38BDF8",
|
||||
paddingBottom: 12,
|
||||
marginBottom: 16,
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
},
|
||||
brandTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: "bold",
|
||||
color: "#38BDF8",
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
subTitle: {
|
||||
fontSize: 9,
|
||||
color: "#94A3B8",
|
||||
marginTop: 3,
|
||||
},
|
||||
badge: {
|
||||
backgroundColor: "#1E293B",
|
||||
borderColor: "#334155",
|
||||
borderWidth: 1,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 4,
|
||||
borderRadius: 6,
|
||||
},
|
||||
badgeText: {
|
||||
fontSize: 8,
|
||||
color: "#38BDF8",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 12,
|
||||
fontWeight: "bold",
|
||||
color: "#F1F5F9",
|
||||
marginTop: 12,
|
||||
marginBottom: 6,
|
||||
borderLeftWidth: 3,
|
||||
borderLeftColor: "#38BDF8",
|
||||
paddingLeft: 6,
|
||||
},
|
||||
table: {
|
||||
width: "100%",
|
||||
marginBottom: 8,
|
||||
},
|
||||
tableHeader: {
|
||||
flexDirection: "row",
|
||||
backgroundColor: "#1E293B",
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#334155",
|
||||
paddingVertical: 5,
|
||||
paddingHorizontal: 8,
|
||||
},
|
||||
tableRow: {
|
||||
flexDirection: "row",
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#1E293B",
|
||||
paddingVertical: 4,
|
||||
paddingHorizontal: 8,
|
||||
alignItems: "center",
|
||||
},
|
||||
th: {
|
||||
fontSize: 8.5,
|
||||
fontWeight: "bold",
|
||||
color: "#94A3B8",
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
td: {
|
||||
fontSize: 8.5,
|
||||
color: "#E2E8F0",
|
||||
},
|
||||
tdUsername: {
|
||||
fontSize: 9,
|
||||
fontWeight: "bold",
|
||||
color: "#38BDF8",
|
||||
},
|
||||
colRole: { width: "25%" },
|
||||
colUser: { width: "20%" },
|
||||
colPass: { width: "20%" },
|
||||
colScope: { width: "35%" },
|
||||
footer: {
|
||||
position: "absolute",
|
||||
bottom: 20,
|
||||
left: 30,
|
||||
right: 30,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: "#1E293B",
|
||||
paddingTop: 8,
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
},
|
||||
footerText: {
|
||||
fontSize: 8,
|
||||
color: "#64748B",
|
||||
},
|
||||
});
|
||||
|
||||
const accountGroups = [
|
||||
{
|
||||
title: "1. Operational Accounts (Global System)",
|
||||
accounts: [
|
||||
{ role: "superadmin", username: "admin", pass: "admin", scope: "BackOne System Administrator" },
|
||||
{ role: "global soc analyst", username: "sulist", pass: "sulist", scope: "Global Security Incident Analyst" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "2. Network Agent Accounts (Agent Viewers)",
|
||||
accounts: [
|
||||
{ role: "agent viewer", username: "cibubur", pass: "cibubur", scope: "Agent 2F-TF-1D-GK (JRP Cibubur)" },
|
||||
{ role: "agent viewer", username: "ifg", pass: "ifg", scope: "Agent 8A-V3-PB-85 (IFG LT.18)" },
|
||||
{ role: "agent viewer", username: "balaraja", pass: "balaraja", scope: "Agent F6-2V-DT-8A (CPI Balaraja)" },
|
||||
{ role: "agent viewer", username: "007", pass: "007", scope: "Agent YW-6I-61-LL (Gateway 007)" },
|
||||
{ role: "agent viewer", username: "bsd", pass: "bsd", scope: "Agent 1T-5Q-RC-AS (Fazza BSD)" },
|
||||
{ role: "agent viewer", username: "jkt", pass: "jkt", scope: "Agent 2N-ID-VQ-AL (Fazza JKT)" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "3. User Accounts (Company & Tenant Administrations)",
|
||||
accounts: [
|
||||
{ role: "tenant admin", username: "siab", pass: "siab", scope: "Tenant Administrator (SIAB)" },
|
||||
{ role: "tenant soc analyst", username: "silis", pass: "silis", scope: "SOC Security Analyst (SIAB)" },
|
||||
{ role: "tenant engineer", username: "siner", pass: "siner", scope: "Network Engineer (SIAB)" },
|
||||
{ role: "tenant admin", username: "nexus", pass: "nexus", scope: "Tenant Administrator (Nexus)" },
|
||||
{ role: "tenant soc analyst", username: "nelis", pass: "nelis", scope: "SOC Security Analyst (Nexus)" },
|
||||
{ role: "tenant engineer", username: "nener", pass: "nener", scope: "Network Engineer (Nexus)" },
|
||||
{ role: "company admin", username: "faza", pass: "faza", scope: "Company Admin (PT. Fazza)" },
|
||||
{ role: "company operator", username: "faze", pass: "faze", scope: "Company Operator (PT. Fazza)" },
|
||||
{ role: "company viewer", username: "fazu", pass: "fazu", scope: "Company Viewer (PT. Fazza)" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function MyDocument() {
|
||||
return h(
|
||||
Document,
|
||||
{ title: "All Account BackOne demoplace", author: "BackOne DPI System" },
|
||||
h(
|
||||
Page,
|
||||
{ size: "A4", style: styles.page },
|
||||
// Header
|
||||
h(
|
||||
View,
|
||||
{ style: styles.header },
|
||||
h(
|
||||
View,
|
||||
null,
|
||||
h(Text, { style: styles.brandTitle }, "BackOne Deep Package Inspection"),
|
||||
h(Text, { style: styles.subTitle }, "All Registered Accounts Report • Domain: https://demoplace.my.id")
|
||||
),
|
||||
h(View, { style: styles.badge }, h(Text, { style: styles.badgeText }, "CONFIDENTIAL REPORT"))
|
||||
),
|
||||
|
||||
// Account Groups
|
||||
accountGroups.map((group, gIdx) =>
|
||||
h(
|
||||
View,
|
||||
{ key: gIdx },
|
||||
h(Text, { style: styles.sectionTitle }, group.title),
|
||||
h(
|
||||
View,
|
||||
{ style: styles.table },
|
||||
// Table Header
|
||||
h(
|
||||
View,
|
||||
{ style: styles.tableHeader },
|
||||
h(Text, { style: [styles.th, styles.colRole] }, "Role"),
|
||||
h(Text, { style: [styles.th, styles.colUser] }, "Username"),
|
||||
h(Text, { style: [styles.th, styles.colPass] }, "Password"),
|
||||
h(Text, { style: [styles.th, styles.colScope] }, "Scope / Description")
|
||||
),
|
||||
// Table Rows
|
||||
group.accounts.map((acc, aIdx) =>
|
||||
h(
|
||||
View,
|
||||
{ key: aIdx, style: styles.tableRow },
|
||||
h(Text, { style: [styles.td, styles.colRole] }, acc.role),
|
||||
h(Text, { style: [styles.tdUsername, styles.colUser] }, acc.username),
|
||||
h(Text, { style: [styles.td, styles.colPass] }, acc.pass),
|
||||
h(Text, { style: [styles.td, styles.colScope] }, acc.scope)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
// Footer
|
||||
h(
|
||||
View,
|
||||
{ style: styles.footer },
|
||||
h(
|
||||
Text,
|
||||
{ style: styles.footerText },
|
||||
`Generated on ${new Date().toLocaleDateString("en-GB", { day: "2-digit", month: "long", year: "numeric" })} • PT. Data Bisnis Solusi`
|
||||
),
|
||||
h(Text, { style: styles.footerText }, "Page 1 of 1")
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async function generatePDF() {
|
||||
const outputFileName = "All Account BackOne demoplace.pdf";
|
||||
const outputPath = path.join(__dirname, "..", outputFileName);
|
||||
|
||||
console.log(`Generating PDF report to: ${outputPath}...`);
|
||||
await ReactPDF.renderToFile(h(MyDocument), outputPath);
|
||||
console.log(`✅ PDF Report successfully generated: ${outputPath}`);
|
||||
}
|
||||
|
||||
generatePDF().catch((err) => {
|
||||
console.error("PDF generation failed:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
const { spawn } = require('child_process');
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const mongoose = require('mongoose');
|
||||
const WebSocket = require('next/dist/compiled/ws');
|
||||
|
||||
require('dotenv').config({ path: path.join(__dirname, '..', '.env.local') });
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'backone-dpi-secret-jwt-key-2024';
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
await mongoose.connect(MONGODB_URI);
|
||||
const db = mongoose.connection.db;
|
||||
const users = db.collection('users');
|
||||
|
||||
let adminUser = await users.findOne({ username: 'admin' });
|
||||
const payload = {
|
||||
userId: adminUser._id.toString(),
|
||||
username: adminUser.username,
|
||||
role: adminUser.role,
|
||||
site_uuid: adminUser.site_uuid || 'default',
|
||||
agent_uuid: adminUser.agent_uuid || null
|
||||
};
|
||||
|
||||
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '1h' });
|
||||
await mongoose.disconnect();
|
||||
|
||||
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
|
||||
const edgeProc = spawn(edgePath, [
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--remote-debugging-port=9222',
|
||||
'--window-size=400,844',
|
||||
'http://localhost:3000/'
|
||||
]);
|
||||
|
||||
await new Promise(r => setTimeout(r, 2500));
|
||||
|
||||
const targets = await new Promise((resolve, reject) => {
|
||||
http.get('http://127.0.0.1:9222/json', (res) => {
|
||||
let body = '';
|
||||
res.on('data', c => body += c);
|
||||
res.on('end', () => resolve(JSON.parse(body)));
|
||||
}).on('error', reject);
|
||||
});
|
||||
|
||||
const pageTarget = targets.find(t => t.type === 'page');
|
||||
if (!pageTarget || !pageTarget.webSocketDebuggerUrl) {
|
||||
edgeProc.kill();
|
||||
return;
|
||||
}
|
||||
|
||||
const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);
|
||||
let messageId = 1;
|
||||
const send = (method, params = {}) => {
|
||||
return new Promise((res) => {
|
||||
const id = messageId++;
|
||||
const handler = (data) => {
|
||||
const msg = JSON.parse(data);
|
||||
if (msg.id === id) {
|
||||
ws.removeListener('message', handler);
|
||||
res(msg.result);
|
||||
}
|
||||
};
|
||||
ws.on('message', handler);
|
||||
ws.send(JSON.stringify({ id, method, params }));
|
||||
});
|
||||
};
|
||||
|
||||
ws.on('open', async () => {
|
||||
await send('Network.setCookie', { name: 'token', value: token, domain: 'localhost', path: '/' });
|
||||
await send('Network.setCookie', { name: 'backone_token', value: token, domain: 'localhost', path: '/' });
|
||||
|
||||
await send('Page.navigate', { url: 'http://localhost:3000/' });
|
||||
await new Promise(r => setTimeout(r, 5000));
|
||||
|
||||
const screenshot = await send('Page.captureScreenshot', { format: 'png', captureBeyondViewport: true });
|
||||
const outputPath = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a\\mobile-full-dashboard-live.png";
|
||||
fs.writeFileSync(outputPath, Buffer.from(screenshot.data, 'base64'));
|
||||
console.log("Full page screenshot saved to:", outputPath, "Size:", fs.statSync(outputPath).size, "bytes");
|
||||
|
||||
ws.close();
|
||||
edgeProc.kill();
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error("Error:", err.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,93 @@
|
||||
const { spawnSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
|
||||
function loginAndGetCookie() {
|
||||
return new Promise((resolve) => {
|
||||
const data = JSON.stringify({ username: 'admin', password: 'admin' });
|
||||
const req = http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: 3000,
|
||||
path: '/api/auth/login',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': data.length
|
||||
}
|
||||
}, (res) => {
|
||||
let body = '';
|
||||
res.on('data', chunk => body += chunk);
|
||||
res.on('end', () => {
|
||||
console.log("Login HTTP Status:", res.statusCode);
|
||||
const setCookieHeader = res.headers['set-cookie'];
|
||||
if (setCookieHeader && setCookieHeader.length > 0) {
|
||||
const cookieVal = setCookieHeader[0].split(';')[0];
|
||||
console.log("Authenticated Cookie:", cookieVal);
|
||||
resolve(cookieVal);
|
||||
} else {
|
||||
console.log("No Set-Cookie header returned:", body);
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (err) => {
|
||||
console.error("Login request error:", err.message);
|
||||
resolve(null);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const cookieHeader = await loginAndGetCookie();
|
||||
if (!cookieHeader) {
|
||||
console.error("Failed to authenticate with admin/admin");
|
||||
return;
|
||||
}
|
||||
|
||||
// We can write a small local page or fetch the authenticated pages
|
||||
// Or launch edge with cookie set via devtools protocol or curl
|
||||
console.log("Fetching authenticated HTML for / ...");
|
||||
|
||||
const req = http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: 3000,
|
||||
path: '/',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Cookie': cookieHeader
|
||||
}
|
||||
}, (res) => {
|
||||
console.log("Dashboard GET Status:", res.statusCode);
|
||||
});
|
||||
req.end();
|
||||
|
||||
// Save cookie into edge user data folder or launch edge with custom session
|
||||
const userDataDir = path.join(__dirname, 'edge_session_dir');
|
||||
if (!fs.existsSync(userDataDir)) {
|
||||
fs.mkdirSync(userDataDir, { recursive: true });
|
||||
}
|
||||
|
||||
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
|
||||
const outputDir = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a";
|
||||
const outputFile = path.join(outputDir, "mobile-dashboard-overview.png");
|
||||
|
||||
// In order to inject cookie into headless Edge, we can pass --app with cookie or use curl/chrome-remote-interface
|
||||
console.log("Executing Edge capture...");
|
||||
const res = spawnSync(edgePath, [
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
`--user-data-dir=${userDataDir}`,
|
||||
'--window-size=400,844',
|
||||
`--screenshot=${outputFile}`,
|
||||
'http://localhost:3000/'
|
||||
], { encoding: 'utf-8', timeout: 15000 });
|
||||
|
||||
console.log("Done! Exit code:", res.status);
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -0,0 +1,24 @@
|
||||
const { spawnSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
|
||||
const outputDir = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a";
|
||||
const outputFile = path.join(outputDir, "mobile-localhost.png");
|
||||
|
||||
console.log("Launching Edge headless to capture screenshot of http://localhost:3000 ...");
|
||||
|
||||
const res = spawnSync(edgePath, [
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--window-size=400,844',
|
||||
`--screenshot=${outputFile}`,
|
||||
'http://localhost:3000'
|
||||
], { encoding: 'utf-8', timeout: 15000 });
|
||||
|
||||
console.log("Exit code:", res.status);
|
||||
if (fs.existsSync(outputFile)) {
|
||||
console.log("Screenshot successfully saved to:", outputFile, "Size:", fs.statSync(outputFile).size, "bytes");
|
||||
} else {
|
||||
console.log("Screenshot file not found.");
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
const http = require('http');
|
||||
|
||||
function testUrl(url) {
|
||||
return new Promise((resolve) => {
|
||||
const start = Date.now();
|
||||
console.log(`[TEST] Fetching ${url}...`);
|
||||
const req = http.get(url, { timeout: 5000 }, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => { data += chunk; });
|
||||
res.on('end', () => {
|
||||
const duration = Date.now() - start;
|
||||
console.log(`[TEST] ${url} -> Status: ${res.statusCode}, Time: ${duration}ms, Bytes: ${data.length}`);
|
||||
resolve({ url, status: res.statusCode, duration, bytes: data.length });
|
||||
});
|
||||
});
|
||||
req.on('error', (err) => {
|
||||
const duration = Date.now() - start;
|
||||
console.log(`[TEST] ${url} -> ERROR: ${err.message}, Time: ${duration}ms`);
|
||||
resolve({ url, error: err.message, duration });
|
||||
});
|
||||
req.on('timeout', () => {
|
||||
req.destroy();
|
||||
const duration = Date.now() - start;
|
||||
console.log(`[TEST] ${url} -> TIMEOUT after ${duration}ms`);
|
||||
resolve({ url, timeout: true, duration });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function run() {
|
||||
console.log('=== STARTING DASHBOARD ROUTE SPEED TEST ===');
|
||||
await testUrl('http://127.0.0.1:3001/api/dashboard/devices');
|
||||
await testUrl('http://127.0.0.1:3001/api/dashboard/summary');
|
||||
console.log('=== TEST COMPLETE ===');
|
||||
}
|
||||
|
||||
run();
|
||||
Reference in new issue
Block a user