Skip to content

Commit

Permalink
feat: finally working
Browse files Browse the repository at this point in the history
  • Loading branch information
crnsh committed Mar 7, 2024
1 parent cc3444c commit 53dfe41
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 32 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
dist
dist
tests
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<img src="https://img.shields.io/npm/v/million-lint-check">
<img src="https://img.shields.io/npm/l/million-lint-check">
<img src="https://img.shields.io/npm/dt/million-lint-check">
<p/>
</p>
<hr/>

## What?
Expand All @@ -19,4 +19,4 @@ It works by doing the following things -
4. Randomly interacts (fuzzes) with the client and detects Million Lint suggestions using [puppeteer](https://www.npmjs.com/package/puppeteer)

## Installation
- Run `npx million-lint-check@latest --port $PORT`, where `$PORT` is the port your frontend will run on in development.
- Run `npx million-lint-check@latest setup $PORT`, where `$PORT` is the port your frontend will run on in development.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "million-lint-check",
"version": "1.0.8",
"version": "1.0.9",
"description": "A command-line tool to verify if Million Lint is active in a project.",
"main": "index.js",
"files": [
Expand Down
21 changes: 4 additions & 17 deletions src/fuzzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,12 @@ import { Page } from 'puppeteer';
export const fuzzPage = async (page: Page) => {
// Get all interactive elements
const buttons = await page.$$('button');
const links = await page.$$('a');
const inputs = await page.$$('[type="text"], [type="email"], [type="password"]');

// Combine them into one array
const interactiveElements = [...buttons, ...links, ...inputs];

// Randomly interact with elements
for (let i = 0; i < 100; i++) { // Example: perform 5 random interactions
const elementIndex = Math.floor(Math.random() * interactiveElements.length);
const element = interactiveElements[elementIndex];
for (let i = 0; i < 100; i++) {
const elementIndex = Math.floor(Math.random() * buttons.length);
const element = buttons[elementIndex];

if (await element.isIntersectingViewport()) {
if (inputs.includes(element)) {
// For inputs, type a random string
await element.type('Random String');
} else {
// For buttons and links, click on them
await element.click();
}
}
await element.click();
}
};
24 changes: 22 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ program.command('setup')
.argument('<port>', 'Frontend port', myParseInt)
.description('Sets up the Million Lint in the project')
.action(async (port: number, options) => {
// Function to kill the development server
function killDevServer() {
console.log('\nShutting down development server...');
process.kill(-devServer!.pid!); // Kill the process group
}

// Listen for termination signals
process.on('SIGINT', killDevServer);
process.on('SIGTERM', killDevServer);
process.on('SIGUSR1', killDevServer);
process.on('SIGUSR2', killDevServer);

if (!(Number.isInteger(port) && 0 <= port && port <= 65535)) {
console.log('Invalid port!')
exit(1)
Expand All @@ -41,10 +53,18 @@ program.command('setup')
detached: true,
});
console.log('Development server started in the background.');
devServer.unref();

console.log('Opening browser and interacting with components...');
await checkWhetherMillionWorks(port)
try {
await checkWhetherMillionWorks(port, devServer)
} catch(error : any) {
console.log(error.message)
killDevServer()
exit(1)
} finally {
killDevServer()
exit(0)
}
});

program.parse(process.argv);
23 changes: 15 additions & 8 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { InvalidArgumentError } from "commander";
import { fuzzPage } from "./fuzzer";
import puppeteer, { Browser } from "puppeteer";
import { exit } from "process";
import { ChildProcess } from "child_process";

export async function tryConnect(url: string, browser: Browser, maxAttempts = 10) {
let attempts = 0;
Expand All @@ -19,7 +20,7 @@ export async function tryConnect(url: string, browser: Browser, maxAttempts = 10
console.log(`Attempt ${attempts} failed. Error: ${error.message}`);
if (attempts >= maxAttempts) {
console.log('Max attempts reached. Giving up.');
exit(1)
return false
} else {
console.log(`Retrying in 5 seconds...`);
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait for 5 seconds
Expand All @@ -31,20 +32,26 @@ export async function tryConnect(url: string, browser: Browser, maxAttempts = 10
return attemptConnection(); // Start the first attempt
}


export async function checkWhetherMillionWorks( port: number ) {
const browser = await puppeteer.launch();
export async function checkWhetherMillionWorks( port: number, devServer: ChildProcess ) {
const browser = await puppeteer.launch({ headless: false });
const url = `http://localhost:${port}`
const page = await tryConnect(url, browser, 100)
const response = await page.goto(url); // Your app's URL here
console.log(response?.json())
if (!page) {
exit()
}
await page.goto(url, { waitUntil: ['networkidle0', 'load'] });

// interact with the website - press buttons, type random strings in boxes, click random things, etc.
console.log(`Randomly interacting with page...`);
await fuzzPage(page);

// check whether the element that has class name 'million-embed' also has class name 'active'
const element = await page.$('.million-embed');
const isActive = await page.evaluate((el) => el!.classList.contains('active'), element);
console.log(`Finding element...`);
const isActive = await page.evaluateHandle(() => {
const element = document!.querySelector("body > div:nth-child(4)")!.shadowRoot!.querySelector("div > div")
return element?.classList.contains('active')
});
console.log(isActive)
if (isActive) {
console.log('Million Lint is working as expected!');
}
Expand Down
5 changes: 4 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@
"sourceMap": true,
"esModuleInterop": true,
"moduleResolution": "node"
}
},
"exclude": [
"tests/**/*",
]
}

0 comments on commit 53dfe41

Please sign in to comment.