Skip to content

Commit

Permalink
Added join implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei15193 committed May 1, 2024
1 parent f103ed9 commit 30e3c76
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 6 deletions.
12 changes: 12 additions & 0 deletions src/collections/IReadOnlyObservableCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ export interface IReadOnlyObservableCollection<TItem> extends Iterable<TItem>, I
findLast<TResult extends TItem>(callback: (item: TItem, index: number, colleciton: this) => item is TResult): TResult | undefined;
findLast<TResult extends TItem, TContext>(callback: (this: TContext, item: TItem, index: number, colleciton: this) => item is TResult, thisArg: TContext): TResult | undefined;

/**
* Merges the current collection with the given [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) and returns a new JavaScript [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array).
* @param items The items to concatenate.
* @returns Returns a new [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) containing the items of this collection followed by the items in the provided [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array).
* @see [Array.concat](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/concat)
*/
concat(...items: readonly (TItem | readonly TItem[])[]): TItem[];

map<TResult>(callback: (item: TItem, index: number, colleciton: this) => TResult): TResult[];
Expand All @@ -105,6 +111,12 @@ export interface IReadOnlyObservableCollection<TItem> extends Iterable<TItem>, I

slice(start?: number, end?: number): TItem[];

/**
* Aggregates the contained items into a {@link String} placing the provided `separator` between them.
* @param separator The separator used to insert between items when aggregating them into a {@link String}.
* @returns The aggregated items as a {@link String}.
* @see [Array.join](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/join)
*/
join(separator?: string): string;

some(callback: (item: TItem, index: number, collection: this) => boolean): boolean;
Expand Down
15 changes: 10 additions & 5 deletions src/collections/ObservableCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { ReadOnlyObservableCollection } from './ReadOnlyObservableCollection';
* @see [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
*/
export class ObservableCollection<TItem> extends ReadOnlyObservableCollection<TItem> implements IObservableCollection<TItem> {
/** Initializes a new instance of the {@link ObservableCollection} class.
/**
* Initializes a new instance of the {@link ObservableCollection} class.
* @param items The items to initialize the collection with.
*/
public constructor(...items: readonly TItem[]) {
Expand Down Expand Up @@ -40,15 +41,17 @@ export class ObservableCollection<TItem> extends ReadOnlyObservableCollection<TI
return super.push(...items);
}

/** Removes the last element from the collection and returns it. If the collection is empty, `undefined` is returned.
/**
* Removes the last element from the collection and returns it. If the collection is empty, `undefined` is returned.
* @returns The last element in the collection that was removed.
* @see [Array.pop](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/pop)
*/
public pop(): TItem | undefined {
return super.pop();
}

/** Inserts new elements at the start of the collection, and returns the new length of the collection.
/**
* Inserts new elements at the start of the collection, and returns the new length of the collection.
* @param items Elements to insert at the start of the collection.
* @returns The new length of the collection.
* @see [Array.unshift](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)
Expand Down Expand Up @@ -76,7 +79,8 @@ export class ObservableCollection<TItem> extends ReadOnlyObservableCollection<TI
return super.get(index);
}

/** Sets the provided item at the provided index.
/**
* Sets the provided item at the provided index.
* @param index The index to which to set the item.
* @param item The item to set.
* @throws {@link RangeError} when the index is outside the bounds of the collection.
Expand All @@ -85,7 +89,8 @@ export class ObservableCollection<TItem> extends ReadOnlyObservableCollection<TI
super.set(index, item);
}

/** Removes and/or adds elements to the collection and returns the deleted elements.
/**
* Removes and/or adds elements to the collection and returns the deleted elements.
* @param start The zero-based location in the collection from which to start removing elements.
* @param deleteCount The number of elements to remove.
* @param items The items to insert at the given start location.
Expand Down
2 changes: 1 addition & 1 deletion src/collections/ReadOnlyObservableCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export class ReadOnlyObservableCollection<TItem> extends ViewModel implements IR
* @see [Array.join](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/join)
*/
public join(separator?: string): string {
throw new Error('Method not implemented.');
return Array.from(this).join(separator);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ObservableCollection } from '../../ObservableCollection';
import { testBlankMutatingOperation } from './common';

describe('ObserableCollection.join', (): void => {
it('joining an empty collection returns an empty string', (): void => {
testBlankMutatingOperation<number>({
initialState: [],

applyOperation: collection => collection.join()
});
});

it('joining an empty collection with separator returns an empty string', (): void => {
testBlankMutatingOperation<number>({
initialState: [],

applyOperation: collection => collection.join('-')
});
});

it('joining a collection returns a string containing the string representations of each element in one string separated by comma', (): void => {
testBlankMutatingOperation<unknown>({
initialState: [null, undefined, 1, 'A', { prop: 'value' }, new Date(), ObservableCollection],

applyOperation: collection => collection.join()
});
});

it('joining a collection with separator returns a string containing the string representations of each element in one string separated by the separator', (): void => {
testBlankMutatingOperation<unknown>({
initialState: [null, undefined, 1, 'A', { prop: 'value' }, new Date(), ObservableCollection],

applyOperation: collection => collection.join('-')
});
});

it('joining a collection with undefined separator returns a string containing the string representations of each element in one string separated by comma', (): void => {
testBlankMutatingOperation<unknown>({
initialState: [null, undefined, 1, 'A', { prop: 'value' }, new Date(), ObservableCollection],

applyOperation: collection => collection.join(undefined)
});
});

it('joining a collection with null separator returns a string containing the string representations of each element in one string', (): void => {
testBlankMutatingOperation<unknown>({
initialState: [null, undefined, 1, 'A', { prop: 'value' }, new Date(), ObservableCollection],

applyOperation: collection => collection.join(null)
});
});

it('calling join while iterating will not break iterators', (): void => {
expect(
() => {
const observableCollection = new ObservableCollection<number>(1, 2, 3);

for (const _ of observableCollection)
observableCollection.join();
})
.not
.toThrow();
});
});

0 comments on commit 30e3c76

Please sign in to comment.