Fixed path event, renamed testCondition to logicTest & fixed some tests
Some checks failed
Build / Build NPM Project (push) Failing after 44s
Build / Publish Documentation (push) Has been skipped
Build / Tag Version (push) Has been skipped

This commit is contained in:
Zakary Timson 2025-05-11 11:46:03 -04:00
parent 3fd5c5ed57
commit 26cc18ffb3
8 changed files with 76 additions and 146 deletions

View File

@ -1,104 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>About Us | OurTrainingRoom</title>
<style>
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #fdfdfd;
color: #333;
line-height: 1.6;
}
header {
background: #004080;
color: #fff;
padding: 2rem 1rem;
text-align: center;
}
header h1 {
margin: 0;
font-size: 2.5rem;
}
main {
max-width: 800px;
margin: 2rem auto;
padding: 0 1rem;
}
section {
margin-bottom: 2rem;
}
h2 {
color: #004080;
margin-bottom: 0.5rem;
}
ul {
padding-left: 1.25rem;
}
footer {
text-align: center;
font-size: 0.9rem;
color: #777;
padding: 2rem 1rem;
background: #f1f1f1;
margin-top: 4rem;
}
</style>
</head>
<body>
<header>
<h1>About Us</h1>
<p>Empowering Learning Through Innovation</p>
</header>
<main>
<section>
<p>
E-learning has evolved significantly since its inception. Today, there's a shift towards
blended learning services, integrating online activities with practical, real-world applications.
</p>
</section>
<section>
<h2>What We Do</h2>
<p>At <strong>OurTrainingRoom.com</strong>, we specialize in content management and professional development training tailored for:</p>
<ul>
<li>School Boards</li>
<li>Municipalities</li>
<li>Hospitals</li>
<li>Large Corporations</li>
</ul>
</section>
<section>
<h2>Our Roots</h2>
<p>
Our parent company, <strong>The Auxilium Group</strong>, is a leader in online data management.
The formation of OurTrainingRoom.com was a natural progression to deliver state-of-the-art front-end e-learning programs.
</p>
</section>
<section>
<h2>Our Approach</h2>
<p>
Built on principles of quality and continuous improvement, our diverse delivery range continues to grow.
We set new trends by enhancing our existing products and attentively listening to our clients and their employees.
This unique approach has solidified our position in the industry, making a substantial impact for our clients.
</p>
</section>
<section>
<h2>Have a Question?</h2>
<p>
We value your inquiries and are here to assist you. Please reach out with any questions or feedback.
</p>
</section>
</main>
<footer>
&copy; 2025 OurTrainingRoom.com. All rights reserved.
</footer>
</body>
</html>

View File

@ -1,6 +1,6 @@
{ {
"name": "@ztimson/utils", "name": "@ztimson/utils",
"version": "0.24.2", "version": "0.24.3",
"description": "Utility library", "description": "Utility library",
"author": "Zak Timson", "author": "Zak Timson",
"license": "MIT", "license": "MIT",

View File

@ -31,7 +31,7 @@ export function PE(str: TemplateStringsArray, ...args: any[]) {
if(str[i]) combined.push(str[i]); if(str[i]) combined.push(str[i]);
if(args[i]) combined.push(args[i]); if(args[i]) combined.push(args[i]);
} }
return new PathEvent(combined.join('')); return new PathEvent(combined.join('/'));
} }
/** /**
@ -79,16 +79,16 @@ export class PathEvent {
set none(v: boolean) { v ? this.methods = new ASet<Method>(['n']) : this.methods.delete('n'); } set none(v: boolean) { v ? this.methods = new ASet<Method>(['n']) : this.methods.delete('n'); }
/** Create method specified */ /** Create method specified */
get create(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('c')) } get create(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('c')) }
set create(v: boolean) { v ? this.methods.delete('n').add('c') : this.methods.delete('c'); } set create(v: boolean) { v ? this.methods.delete('n').delete('*').add('c') : this.methods.delete('c'); }
/** Read method specified */ /** Read method specified */
get read(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('r')) } get read(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('r')) }
set read(v: boolean) { v ? this.methods.delete('n').add('r') : this.methods.delete('r'); } set read(v: boolean) { v ? this.methods.delete('n').delete('*').add('r') : this.methods.delete('r'); }
/** Update method specified */ /** Update method specified */
get update(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('u')) } get update(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('u')) }
set update(v: boolean) { v ? this.methods.delete('n').add('u') : this.methods.delete('u'); } set update(v: boolean) { v ? this.methods.delete('n').delete('*').add('u') : this.methods.delete('u'); }
/** Delete method specified */ /** Delete method specified */
get delete(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('d')) } get delete(): boolean { return !this.methods.has('n') && (this.methods.has('*') || this.methods.has('d')) }
set delete(v: boolean) { v ? this.methods.delete('n').add('d') : this.methods.delete('d'); } set delete(v: boolean) { v ? this.methods.delete('n').delete('*').add('d') : this.methods.delete('d'); }
constructor(Event: string | PathEvent) { constructor(Event: string | PathEvent) {
if(typeof Event == 'object') return Object.assign(this, Event); if(typeof Event == 'object') return Object.assign(this, Event);

View File

@ -1,4 +1,4 @@
import {dotNotation, JSONAttemptParse} from './objects.ts'; import {dotNotation, JSONAttemptParse, JSONSerialize} from './objects.ts';
export function search(rows: any[], search: string, regex?: boolean, transform: Function = (r: any) => r) { export function search(rows: any[], search: string, regex?: boolean, transform: Function = (r: any) => r) {
if(!rows) return []; if(!rows) return [];
@ -13,12 +13,18 @@ export function search(rows: any[], search: string, regex?: boolean, transform:
catch { return false; } catch { return false; }
}).length }).length
} else { } else {
return testCondition(search, r); return logicTest(r, search);
} }
}); });
} }
export function testCondition(condition: string, row: any) { /**
* Test an object against a logic condition. By default values are checked
* @param {string} condition
* @param {object} target
* @return {boolean}
*/
export function logicTest(target: object, condition: string): boolean {
const evalBoolean = (a: any, op: string, b: any): boolean => { const evalBoolean = (a: any, op: string, b: any): boolean => {
switch(op) { switch(op) {
case '=': case '=':
@ -40,11 +46,11 @@ export function testCondition(condition: string, row: any) {
// Boolean operator // Boolean operator
const prop = /(\S+)\s*(==?|!=|>=|>|<=|<)\s*(\S+)/g.exec(p); const prop = /(\S+)\s*(==?|!=|>=|>|<=|<)\s*(\S+)/g.exec(p);
if(prop) { if(prop) {
const key = Object.keys(row).find(k => k.toLowerCase() == prop[1].toLowerCase()); const key = Object.keys(target).find(k => k.toLowerCase() == prop[1].toLowerCase());
return evalBoolean(dotNotation<any>(row, key || prop[1]), prop[2], JSONAttemptParse(prop[3])); return evalBoolean(dotNotation<any>(target, key || prop[1]), prop[2], JSONAttemptParse(prop[3]));
} }
// Case-sensitive // Case-sensitive
const v = Object.values(row).map(v => typeof v == 'object' && v != null ? JSON.stringify(v) : v).join(''); const v = Object.values(target).map(JSONSerialize).join('');
if(/[A-Z]/g.test(condition)) return v.includes(p); if(/[A-Z]/g.test(condition)) return v.includes(p);
// Case-insensitive // Case-insensitive
return v.toLowerCase().includes(p); return v.toLowerCase().includes(p);

View File

@ -1,36 +1,18 @@
import {sleep, parseUrl} from '../src'; import {fn} from '../src';
describe('Miscellanies Utilities', () => { describe('Miscellanies Utilities', () => {
describe('sleep', () => { describe('fn', () => {
test('wait until', async () => { test('async', async () => {
const wait = ~~(Math.random() * 500); const test = {a: Math.random()};
const time = new Date().getTime(); const resp = fn(test, 'return a;', true);
await sleep(wait); expect(resp instanceof Promise).toBeTruthy();
expect(new Date().getTime()).toBeGreaterThanOrEqual(time + wait); expect(await resp).toEqual(test['a']);
});
});
describe('urlParser', () => {
test('localhost w/ port', () => {
const parsed = parseUrl('http://localhost:4200/some/path?q1=test1&q2=test2#frag');
expect(parsed.protocol).toStrictEqual('http');
expect(parsed.host).toStrictEqual('localhost:4200');
expect(parsed.domain).toStrictEqual('localhost');
expect(parsed.port).toStrictEqual(4200);
expect(parsed.path).toStrictEqual('/some/path');
expect(parsed.query).toStrictEqual({q1: 'test1', q2: 'test2'});
expect(parsed.fragment).toStrictEqual('frag');
}); });
test('advanced URL', () => { test('sync', async () => {
const parsed = parseUrl('https://sub.domain.example.com/some/path?q1=test1&q2=test2#frag'); const test = {a: Math.random()};
expect(parsed.protocol).toStrictEqual('https'); const resp = fn(test, 'return a;3');
expect(parsed.host).toStrictEqual('sub.domain.example.com'); expect(resp).toEqual(test['a']);
expect(parsed.domain).toStrictEqual('example.com');
expect(parsed.subdomain).toStrictEqual('sub.domain');
expect(parsed.path).toStrictEqual('/some/path');
expect(parsed.query).toStrictEqual({q1: 'test1', q2: 'test2'});
expect(parsed.fragment).toStrictEqual('frag');
}); });
}); });
}); });

9
tests/search.spec.ts Normal file
View File

@ -0,0 +1,9 @@
import {logicTest} from '../src';
describe('Search Utilities', () => {
describe('testCondition', () => {
test('=', () => {
expect(logicTest(''))
});
});
});

View File

@ -1,4 +1,5 @@
import {matchAll, randomString, randomStringBuilder} from "../src"; import {matchAll, parseUrl, randomString, randomStringBuilder} from "../src";
describe('String Utilities', () => { describe('String Utilities', () => {
describe('randomString', () => { describe('randomString', () => {
@ -47,4 +48,28 @@ describe('String Utilities', () => {
test('using regex', () => expect(matchAll('fooBar fooBar FooBar', /fooBar/g).length).toBe(2)); test('using regex', () => expect(matchAll('fooBar fooBar FooBar', /fooBar/g).length).toBe(2));
test('using malformed regex', () => expect(() => matchAll('fooBar fooBar FooBar', /fooBar/)).toThrow()); test('using malformed regex', () => expect(() => matchAll('fooBar fooBar FooBar', /fooBar/)).toThrow());
}); });
describe('urlParser', () => {
test('localhost', () => {
const parsed = parseUrl('http://localhost:4200/some/path?q1=test1&q2=test2#frag');
expect(parsed.protocol).toStrictEqual('http');
expect(parsed.host).toStrictEqual('localhost:4200');
expect(parsed.domain).toStrictEqual('localhost');
expect(parsed.port).toStrictEqual(4200);
expect(parsed.path).toStrictEqual('/some/path');
expect(parsed.query).toStrictEqual({q1: 'test1', q2: 'test2'});
expect(parsed.fragment).toStrictEqual('frag');
});
test('subdomains', () => {
const parsed = parseUrl('https://sub.domain.example.com/some/path?q1=test1&q2=test2#frag');
expect(parsed.protocol).toStrictEqual('https');
expect(parsed.host).toStrictEqual('sub.domain.example.com');
expect(parsed.domain).toStrictEqual('example.com');
expect(parsed.subdomain).toStrictEqual('sub.domain');
expect(parsed.path).toStrictEqual('/some/path');
expect(parsed.query).toStrictEqual({q1: 'test1', q2: 'test2'});
expect(parsed.fragment).toStrictEqual('frag');
});
});
}); });

12
tests/time.spec.ts Normal file
View File

@ -0,0 +1,12 @@
import {sleep} from '../src';
describe('Time Utilities', () => {
describe('sleep', () => {
test('wait until', async () => {
const wait = ~~(Math.random() * 500);
const time = new Date().getTime();
await sleep(wait);
expect(new Date().getTime()).toBeGreaterThanOrEqual(time + wait);
});
});
});