Skip to content

Commit

Permalink
fix enumerableobject (#13)
Browse files Browse the repository at this point in the history
* fixed autoformat code style

* updated packages; replaced c8 with v8

* removed indent eslint rule (doesn't work as intended)

* fixed value detection on enum object

* test coverage+; optimized detaching events
  • Loading branch information
maddin1502 authored Jun 23, 2023
1 parent e651552 commit c619e81
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 50 deletions.
1 change: 0 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-var-requires": "warn",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/indent": ["warn", 2],
"@typescript-eslint/comma-dangle": "warn",
"@typescript-eslint/no-shadow": "warn",
"@typescript-eslint/semi": "warn",
Expand Down
4 changes: 4 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "none"
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"/README.md": true,
"/tests/reports": true
},
"editor.renderFinalNewline": false,
"editor.renderFinalNewline": "off",
"files.insertFinalNewline": true,
"editor.insertSpaces": true,
"files.eol": "\n",
Expand Down
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-lib-extended",
"version": "2.0.3",
"version": "2.0.4",
"description": "Additional types and tools for typescript",
"files": [
"dist"
Expand All @@ -16,8 +16,8 @@
"test": "vitest run --coverage",
"test-ui": "vitest --ui",
"test-watch": "vitest watch",
"reset-modules": "npx --quiet rimraf node_modules/ package-lock.json",
"reset-creation": "npx --quiet rimraf dist/ tests/reports/",
"reset-modules": "npx --quiet -y rimraf node_modules/ package-lock.json",
"reset-creation": "npx --quiet -y rimraf dist/ tests/reports/",
"reset": "npm run reset-creation && npm run reset-modules",
"validate": "npm run reset && npm i && npm run build && npm test",
"create": "npm run reset-creation && npm run build && npm test",
Expand Down Expand Up @@ -47,12 +47,12 @@
"access": "public"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.32.0",
"@typescript-eslint/parser": "^5.32.0",
"@vitest/ui": "^0.21.0",
"c8": "^7.12.0",
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/parser": "^5.60.0",
"@vitest/coverage-v8": "^0.32.2",
"@vitest/ui": "^0.32.2",
"eslint": "^8.21.0",
"typescript": "^4.7.4",
"vitest": "^0.21.0"
"typescript": "^5.1.3",
"vitest": "^0.32.0"
}
}
2 changes: 1 addition & 1 deletion src/enumerable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class EnumerableObject {
for (let i = 0; i < keys.length; i++) {
const key = keys[i];

if (/^[0-9]$/.exec(key)) {
if (/^[0-9]+$/.exec(key)) {
continue;
}

Expand Down
28 changes: 15 additions & 13 deletions src/event/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ import type { EventSubscription, EventUnsubscription } from './types';
* @template TArgs
*/
export class Event<TSender, TArgs extends EventArgs | void = void> {
private _detached: boolean;
private _subscribe: EventSubscription<TSender, TArgs> | undefined;
private _unsubscribe: EventUnsubscription | undefined;
private _subscription:
| undefined
| {
subscribe: EventSubscription<TSender, TArgs>;
unsubscribe: EventUnsubscription;
};

constructor(
subscribe_: EventSubscription<TSender, TArgs>,
unsubscrbe_: EventUnsubscription,
unsubscribe_: EventUnsubscription,
detachEventProxy_: (detachEvent_: () => void) => void
) {
this._detached = false;
this._subscribe = subscribe_;
this._unsubscribe = unsubscrbe_;
this._subscription = {
subscribe: subscribe_,
unsubscribe: unsubscribe_
};
detachEventProxy_(() => this.detach());
}

Expand All @@ -33,7 +37,7 @@ export class Event<TSender, TArgs extends EventArgs | void = void> {
* @memberof Event
*/
public get subscribe(): EventSubscription<TSender, TArgs> {
return this.validateDetached(this._subscribe);
return this.validateDetached(this._subscription?.subscribe);
}

/**
Expand All @@ -44,20 +48,18 @@ export class Event<TSender, TArgs extends EventArgs | void = void> {
* @memberof Event
*/
public get unsubscribe(): EventUnsubscription {
return this.validateDetached(this._unsubscribe);
return this.validateDetached(this._subscription?.unsubscribe);
}

private validateDetached<T>(value_: T | undefined): T | never {
if (this._detached || value_ === undefined) {
if (value_ === undefined) {
throw new Error('Event is detached!');
}

return value_;
}

private detach(): void {
this._detached = true;
this._subscribe = undefined;
this._unsubscribe = undefined;
this._subscription = undefined;
}
}
67 changes: 61 additions & 6 deletions tests/code/enumerable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,86 @@ enum StringEnum {
b = 'bar'
}

enum MoreThan10Items {
a,
b,
c,
d,
e,
f,
g,
h,
i,
j,
k,
l
}

describe(EnumerableObject.name, () => {
test('entries', () => {
expect.assertions(3);
expect.assertions(4);
const enumObj = new EnumerableObject();

expect(enumObj.entries(MixedEnum)).toEqual([['a', 'foo'], ['b', 1]]);
expect(enumObj.entries(NumberEnum)).toEqual([['a', 0], ['b', 1]]);
expect(enumObj.entries(StringEnum)).toEqual([['a', 'foo'], ['b', 'bar']]);
expect(enumObj.entries(MixedEnum)).toEqual([
['a', 'foo'],
['b', 1]
]);
expect(enumObj.entries(NumberEnum)).toEqual([
['a', 0],
['b', 1]
]);
expect(enumObj.entries(StringEnum)).toEqual([
['a', 'foo'],
['b', 'bar']
]);
expect(enumObj.entries(MoreThan10Items)).toEqual([
['a', 0],
['b', 1],
['c', 2],
['d', 3],
['e', 4],
['f', 5],
['g', 6],
['h', 7],
['i', 8],
['j', 9],
['k', 10],
['l', 11]
]);
});

test('values', () => {
expect.assertions(3);
expect.assertions(4);
const enumObj = new EnumerableObject();

expect(enumObj.values(MixedEnum)).toEqual(['foo', 1]);
expect(enumObj.values(NumberEnum)).toEqual([0, 1]);
expect(enumObj.values(StringEnum)).toEqual(['foo', 'bar']);
expect(enumObj.values(MoreThan10Items)).toEqual([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
]);
});

test('keys', () => {
expect.assertions(3);
expect.assertions(4);
const enumObj = new EnumerableObject();

expect(enumObj.keys(MixedEnum)).toEqual(['a', 'b']);
expect(enumObj.keys(NumberEnum)).toEqual(['a', 'b']);
expect(enumObj.keys(StringEnum)).toEqual(['a', 'b']);
expect(enumObj.keys(MoreThan10Items)).toEqual([
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l'
]);
});
});
85 changes: 66 additions & 19 deletions tests/code/event.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { CancelEventArgs } from '../../src/event/args/cancel';
import { EventHandler } from '../../src/event/handler';

class TestSubject extends Disposable {
private _valueChangingHandler: EventHandler<this, CancelEventArgs<{ old: number, new: number }>>;
private _valueChangingHandler: EventHandler<
this,
CancelEventArgs<{ old: number; new: number }>
>;
private _valueChangedHandler: EventHandler<this, EventArgs<number>>;
private _value: number;

Expand All @@ -21,13 +24,25 @@ class TestSubject extends Disposable {
});
}

public get changing(): Event<this, CancelEventArgs<{ old: number, new: number }>> { return this._valueChangingHandler.event; }
public get changing(): Event<
this,
CancelEventArgs<{ old: number; new: number }>
> {
return this._valueChangingHandler.event;
}

public get changed(): Event<this, EventArgs<number>> { return this._valueChangedHandler.event; }
public get changed(): Event<this, EventArgs<number>> {
return this._valueChangedHandler.event;
}

public get value(): number { return this._value; }
public get value(): number {
return this._value;
}
public set value(new_: number) {
const cancelArgs = new CancelEventArgs<{ old: number, new: number }>({ old: this._value, new: new_ });
const cancelArgs = new CancelEventArgs<{ old: number; new: number }>({
old: this._value,
new: new_
});
this._valueChangingHandler.invoke(this, cancelArgs);

if (cancelArgs.cancel) {
Expand All @@ -45,22 +60,30 @@ function createTestSubject(value_: number): TestSubject {

describe(TestSubject.name, () => {
test('value', () => {
expect.assertions(25);
expect.assertions(27);
const subject = createTestSubject(42);
let changingCount = 0;
let changedCount = 0;
expect(subject.changing.subscribe('changing', (sender_, args_) => {
expect(subject === sender_).toBe(true);
changingCount++;
args_.cancel = args_.value.new === 21;
})).toBe(true);
expect(subject.changed.subscribe('changed', (sender_, args_) => {
expect(subject === sender_).toBe(true);
changedCount++;
expect(args_.value).toBe(123456789);
})).toBe(true);
expect(
subject.changing.subscribe('changing', (sender_, args_) => {
expect(subject === sender_).toBe(true);
changingCount++;
args_.cancel = args_.value.new === 21;
})
).toBe(true);
expect(
subject.changed.subscribe('changed', (sender_, args_) => {
expect(subject === sender_).toBe(true);
changedCount++;
expect(args_.value).toBe(123456789);
})
).toBe(true);

expect(subject.changing.subscribe('changing', () => { /** */ })).toBe(false);
expect(
subject.changing.subscribe('changing', () => {
/** */
})
).toBe(false);

expect(changingCount).toBe(0);
expect(changedCount).toBe(0);
Expand All @@ -82,10 +105,34 @@ describe(TestSubject.name, () => {
expect(changedCount).toBe(1);
expect(subject.value).toBe(21);

const changingEventBeforeDispose = subject.changing;
const changedEventBeforeDispose = subject.changed;
subject.dispose();

expect(() => subject.changing.subscribe('x', () => { /** */ })).toThrow();
expect(() => subject.changed.subscribe('y', () => { /** */ })).toThrow();
expect(() => {
// will throw on getting "changing" event
subject.changing.subscribe('x', () => {
/** */
});
}).toThrow();
expect(() => {
// will throw on subscribing detached event
changingEventBeforeDispose.subscribe('x', () => {
/** */
});
}).toThrow();
expect(() =>
// will throw on getting "changed" event
subject.changed.subscribe('y', () => {
/** */
})
).toThrow();
expect(() => {
// will throw on subscribing detached event
changedEventBeforeDispose.subscribe('x', () => {
/** */
});
}).toThrow();
expect(() => subject.changing.unsubscribe('x')).toThrow();
expect(() => subject.changed.unsubscribe('y')).toThrow();
});
Expand Down

0 comments on commit c619e81

Please sign in to comment.