Compare commits

..

11 commits
minify ... main

Author SHA1 Message Date
3cc7a378c0 Merge pull request 'index: increase font of critter name' (#9) from font-size into main
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 32s
Reviewed-on: #9
2023-09-28 18:23:43 +00:00
e32d3c9233
app: logging & in-memory sqlite while in non-prod
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 30s
The tests are currently working on my laptop, but failing on the CI
actions. 🤔
There have always been errors on it inserting animals to the database,
and now seem like it fails to get routes before the async promise is
fufilled? I'm not sure.

Switch everything to the bole logger, and not the `console.`
stuff.

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-28 14:13:59 -04:00
6c0c6b071c
index: increase font of critter name
Some checks failed
Basic Checking / Explore-Gitea-Actions (push) Failing after 29s
Fixes #3

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-28 13:46:18 -04:00
d6b3c31348
package.json: run test with local installed jest
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 31s
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-28 13:31:55 -04:00
b9d9ecaec2 Merge pull request '*: restructuring to make testing flow nicer' (#8) from restructure into main
Some checks failed
Basic Checking / Explore-Gitea-Actions (push) Failing after 30s
Reviewed-on: #8
2023-09-26 19:09:36 +00:00
ef4e816dac
*: restructuring to make testing flow nicer
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 50s
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-26 15:07:54 -04:00
281945a672 Merge pull request '*: beginning unittest setup' (#7) from unittest into main
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 7s
Reviewed-on: #7
2023-09-26 19:06:41 +00:00
94eac4f89b
*: beginning unittest setup
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 7s
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-26 12:38:11 -05:00
0997f578c5
animals.json: adding moar animals
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 7s
Fixes #4

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-22 10:23:42 -04:00
6215557a7f
gitea actions!
All checks were successful
Basic Checking / Explore-Gitea-Actions (push) Successful in 47s
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-15 21:34:45 -04:00
6114ef68b0
express: always use params in SQL
this way it handles the sanitizing and avoids injection

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2023-09-15 20:31:47 -04:00
15 changed files with 5544 additions and 2280 deletions

View file

@ -0,0 +1,23 @@
name: Basic Checking
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on: [push]
jobs:
Explore-Gitea-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18.x
- name: Install packages
run: npm install
- name: Run tests
run: npm test
- run: echo "🍏 This job's status is ${{ job.status }}."

65
animals.json Normal file
View file

@ -0,0 +1,65 @@
{
"animals": [
"Squirrel",
"Armadillo",
"Beaver",
"Cricket",
"Eagle",
"Ferret",
"Fox",
"Frog",
"Guinea Pig",
"Hamster",
"Hummingbird",
"Iguana",
"Mouse",
"Muskrat",
"Newt",
"Otter",
"Parakeet",
"Penguin",
"Pigeon",
"Possum",
"Rabbit",
"Raccoon",
"Rat",
"Snake",
"Spider",
"Turtle",
"Wolf pup",
"Squirrel",
"Possum",
"Frog",
"Rat",
"Otter",
"Raccoon",
"Snake",
"Ferret",
"Mouse",
"Armadillo",
"Hamster",
"Fox",
"Iguana",
"Spider",
"Turtle",
"Beaver",
"Rabbit",
"Eagle",
"Pigeon",
"Parakeet",
"Hummingbird",
"Penguin",
"Cricket",
"Newt",
"Muskrat",
"Guinea Pig",
"Quokka",
"Fennec Fox",
"Flying Squirrel",
"Hedgehog",
"Badger",
"Koala Bear",
"Porcupine",
"Skunk"
]
}

View file

@ -4,15 +4,18 @@ const path = require("path");
const morgan = require("morgan"); const morgan = require("morgan");
const bodyParser = require("body-parser"); const bodyParser = require("body-parser");
const sqlite3 = require("sqlite3").verbose(); const sqlite3 = require("sqlite3").verbose();
const bole = require('bole');
const log = bole('app');
const config = require('./config');
const app = express(); const app = express();
const port = 3000;
// Create an SQLite database and initialize tables // Create an SQLite database and initialize tables
const db = new sqlite3.Database("db/results.db", (err) => { const db = new sqlite3.Database(config.db_path, (err) => {
if (err) { if (err) {
console.error("Error opening SQLite database:", err.message); log.error("Error opening SQLite database:", err.message);
} else { } else {
console.log("Connected to SQLite database"); log.info("Connected to SQLite database", config.db_path);
db.run(` db.run(`
CREATE TABLE IF NOT EXISTS button_clicks ( CREATE TABLE IF NOT EXISTS button_clicks (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -51,24 +54,24 @@ try {
var jsondata = JSON.parse(data); var jsondata = JSON.parse(data);
animals = jsondata.animals; animals = jsondata.animals;
for (const animal of animals) { for (const animal of animals) {
db.run( db.run(`
` INSERT INTO animals(name)
INSERT INTO animals(name) SELECT ?
SELECT '${animal}' WHERE NOT EXISTS(SELECT 1 FROM animals WHERE name = ?);
WHERE NOT EXISTS(SELECT 1 FROM animals WHERE name = '${animal}');
`, `,
[animal, animal],
(err) => { (err) => {
if (err) { if (err) {
console.error(`Error inserting animal ${animal}: `, err.message); log.error(`Error inserting animal ${animal}: `, err.message);
} else { } else {
console.log(`Success inserting animal ${animal}`); log.info(`Success inserting animal ${animal}`);
} }
}, },
); );
} }
}); });
} catch (error) { } catch (error) {
console.error("Error loading animals:", error); log.error("Error loading animals:", error);
animals = ["Dog", "Cat", "Elephant", "Lion", "Giraffe"]; animals = ["Dog", "Cat", "Elephant", "Lion", "Giraffe"];
} }
@ -88,7 +91,7 @@ app.get("/getNextAnimal", async (req, res) => {
const randomAnimal = animals[randomIndex]; const randomAnimal = animals[randomIndex];
res.json({ animalName: randomAnimal }); res.json({ animalName: randomAnimal });
} catch (error) { } catch (error) {
console.error("Error fetching random animal:", error); log.error("Error fetching random animal:", error);
res.status(500).json({ error: "Internal server error" }); res.status(500).json({ error: "Internal server error" });
} }
}); });
@ -98,7 +101,7 @@ app.post("/recordButtonClick", (req, res) => {
try { try {
//const { buttonName, sessionId } = req.body; //const { buttonName, sessionId } = req.body;
const result = req.body; const result = req.body;
console.error(result); log.error(result);
db.run( db.run(
"INSERT INTO button_clicks (session_id, animal_name, button_name, timestamp, time_difference) VALUES (?, ?, ?, ?, ?)", "INSERT INTO button_clicks (session_id, animal_name, button_name, timestamp, time_difference) VALUES (?, ?, ?, ?, ?)",
@ -111,7 +114,7 @@ app.post("/recordButtonClick", (req, res) => {
], ],
(err) => { (err) => {
if (err) { if (err) {
console.error("Error recording button click:", err.message); log.error("Error recording button click:", err.message);
res.status(500).json({ error: "Internal server error" }); res.status(500).json({ error: "Internal server error" });
} else { } else {
res.sendStatus(200); res.sendStatus(200);
@ -119,7 +122,7 @@ app.post("/recordButtonClick", (req, res) => {
}, },
); );
} catch (error) { } catch (error) {
console.error("Error recording button click:", error); log.error("Error recording button click:", error);
res.status(500).json({ error: "Internal server error" }); res.status(500).json({ error: "Internal server error" });
} }
}); });
@ -200,11 +203,11 @@ app.get("/results", async (req, res) => {
await Promise.all([getCount, getTotalAvgTime, getAvgTime]); await Promise.all([getCount, getTotalAvgTime, getAvgTime]);
res.json(results); res.json(results);
} catch (error) { } catch (error) {
console.error("Error fetching results:", error); log.error("Error fetching results:", error);
res.status(500).json({ error: "Internal server error" }); res.status(500).json({ error: "Internal server error" });
} }
}); });
app.listen(port, () => { module.exports = app;
console.log(`Server is running on port ${port}`);
}); // vim:set sts=2 sw=2 et:

29
app.test.js Normal file
View file

@ -0,0 +1,29 @@
// app.test.js
const request = require('supertest');
const app = require('./app');
describe('GET /', () => {
it('should respond with 200 status', async () => {
const response = await request(app).get('/');
expect(response.statusCode).toBe(200);
//expect(response.body.message).toBe('Hello, World!');
});
});
describe('GET /asset/frontend.js', () => {
it('should respond with 200 status', async () => {
const response = await request(app).get('/asset/frontend.js');
expect(response.statusCode).toBe(200);
//expect(response.body.message).toBe('Hello, World!');
});
});
describe('GET /getNextAnimal', () => {
it('should respond with 200 status', async () => {
const response = await request(app).get('/getNextAnimal');
expect(response.statusCode).toBe(200);
//expect(response.body.message).toBe('Hello, World!');
});
});
// vim:set sts=2 sw=2 et:

17
config.js Normal file
View file

@ -0,0 +1,17 @@
var config = module.exports;
var PRODUCTION = process.env.NODE_ENV === 'production';
const bole = require('bole');
config.express = {
port: process.env.EXPRESS_PORT || 3000,
ip: '127.0.0.1',
};
if (PRODUCTION) {
config.express.ip = '0.0.0.0';
config.db_path = "db/results.db";
bole.output({ level: 'info', stream: process.stdout })
} else {
config.db_path = ":memory:";
bole.output({ level: 'debug', stream: process.stdout })
}

View file

@ -1,31 +0,0 @@
{
"animals": [
"Squirrel",
"Armadillo",
"Beaver",
"Cricket",
"Eagle",
"Ferret",
"Fox",
"Frog",
"Guinea Pig",
"Hamster",
"Hummingbird",
"Iguana",
"Mouse",
"Muskrat",
"Newt",
"Otter",
"Parakeet",
"Penguin",
"Pigeon",
"Possum",
"Rabbit",
"Raccoon",
"Rat",
"Snake",
"Spider",
"Turtle",
"Wolf pup"
]
}

View file

@ -1 +0,0 @@
let a;let b;function c(){return (Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15))}async function d(){try {var A=await fetch('/getNextAnimal');var _=await A.json();document.getElementById('animal-name').textContent=_.animalName} catch (B) {console.error('Error fetching data:',B)}}function e(){var A=document.cookie.replace(/(?:(?:^|.*;\s*)sessionId\s*=\s*([^;]*).*$)|^.*$/,'$1');if(!A){var _=c();document.cookie=`sessionId=${_}`;return _}return A}function f(){var A=c();document.cookie=`sessionId=${A}`;g();e()}function g(){a=new Date()}function h(){if(a&&b){var A=b-a;console.log(`Time since session start: ${A} milliseconds`)}}document.getElementById('isCritterButton').addEventListener('click',()=>i('is critter',e()));document.getElementById('isNotCritterButton').addEventListener('click',()=>i('is not critter',e()));document.getElementById('startOverButton').addEventListener('click',()=>{f();d()});async function i(A,_){try {var B=new Date();if(b){var C=B-b,_b=document.getElementById('animal-name').textContent,_c=JSON.stringify({animal:_b,button:A,session:_,difference:C,time:a});await fetch('/recordButtonClick',{method:'POST',headers:{'Content-Type':'application/json'},body:_c})}b=B;h();d()} catch (_a) {console.error('Error recording button click:',_a)}}d();g();

2222
express/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@
</head> </head>
<body> <body>
<div id="isCritter"> <div id="isCritter">
<h1>Is this a Critter?</h1> <h3>Is this a Critter?</h3>
<p id="animal-name">what about?:</p> <p id="animal-name">what about?:</p>
<button id="isCritterButton">Is Critter</button> <button id="isCritterButton">Is Critter</button>
<button id="isNotCritterButton">Is <b>not</b> Critter</button> <button id="isNotCritterButton">Is <b>not</b> Critter</button>
@ -21,8 +21,11 @@
<div id="footer"> <div id="footer">
© 2023. All rights reserved. <a href="mailto:isacritter@hashbangbash.com">isacritter</a>; <a href="https://paypal.me/vbatts/1" target="_blank">keep isacritter alive</a> © 2023. All rights reserved. <a href="mailto:isacritter@hashbangbash.com">isacritter</a>; <a href="https://paypal.me/vbatts/1" target="_blank">keep isacritter alive</a>
</div> </div>
<script src="/asset/frontend.min.js"></script> <script src="/asset/frontend.js"></script>
<style type="text/css"> <style type="text/css">
#animal-name {
font-size: 25px;
}
#isCritter { #isCritter {
text-align: center; text-align: center;
} }

5359
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -4,9 +4,9 @@
"description": "", "description": "",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "./node_modules/.bin/jest",
"minify": "cat ./asset/frontend.js | ./node_modules/.bin/minify --js > asset/frontend.min.js", "start": "node server.js",
"start": "node server.js" "act": "act -W ./.gitea/workflows/"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -16,9 +16,13 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"bole": "^5.0.7",
"express": "^4.18.2", "express": "^4.18.2",
"minify": "^10.5.2",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"sqlite3": "^5.1.6" "sqlite3": "^5.1.6"
},
"devDependencies": {
"jest": "^29.7.0",
"supertest": "^6.3.3"
} }
} }

15
server.js Normal file
View file

@ -0,0 +1,15 @@
const config = require('./config');
const app = require('./app');
const bole = require('bole');
const log = bole('server');
app.listen(config.express.port, config.express.ip, function(error) {
if (error) {
log.error('Unable to listen for connections', error);
process.exit(10);
}
log.info('express is listening on http://' +
config.express.ip + ':' + config.express.port)
});
// vim:set sts=2 sw=2 et: