Nuget Hosted Package

NuGet is the package manager for .NET. It enables developers to create, share, and consume useful .NET libraries. NuGet client tools provide the ability to produce and consume these libraries as “packages”.

Write Code

I used .Net Core 2.2 and build a class library, example code: https://github.com/carlpaton/Common/

Then login at https://www.nuget.org/ with your Microsoft Account.

Create package

  1. Open the .csproj file and add the following properties inside the existing PropertyGroup tag:
1
2
3
4
5
6
7
8
9
10
<PackageId>CarlPaton.Common</PackageId>
<TargetFramework>netcoreapp2.2</TargetFramework>
<Authors>Carl Paton</Authors>
<Company>carlpaton.github.io</Company>
<Description>Common services and magic.</Description>
<Version>1.0.1</Version>
<PackageTags>c#</PackageTags>
<PackageLicenseUrl>https://github.com/carlpaton/Common/blob/master/LICENSE.md</PackageLicenseUrl>
<RepositoryUrl>https://github.com/carlpaton/Common</RepositoryUrl>
<RepositoryType>Github</RepositoryType>
  1. Build a NuGet package, this is the .nupkg file. I ran this from the root of the project C:\Dev\Common>
1
dotnet pack

This generated C:\Dev\Common\Common\bin\Debug\CarlPaton.Common.1.0.0.nupkg

Publish package

  1. Acquire your API key
  2. CD to
1
C:\Dev\Common\Common\bin\Debug
  1. Publish to nuget <3
1
dotnet nuget push CarlPaton.Common.1.0.0.nupkg -k yoursweetkeyhere -s https://api.nuget.org/v3/index.json

Version Information

Add sweet nuget version to your projects README.md on GitHub - NuGet version (CarlPaton.Common)

1
[![NuGet version (CarlPaton.Common)](https://img.shields.io/nuget/v/CarlPaton.Common.svg?style=flat-square)](https://www.nuget.org/packages/CarlPaton.Common/)

References

NgRx Selectors

Selectors are pure functions used for obtaining slices of store state.

Selector by route

This will select based on route data, example: /invoice/123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--- foo.facade.ts
public getCurrentInvoice (): Observable<IStoreItem<IInvoice>> {
return this._store.select(InvoiceSelectors.byRoute).pipe(
// tap(a => console.log(a)),
filter(a => a.isLoading === false),
dispatchAndSelect(
invoice => this._store.dispatch(new GetInvoiceAction(invoice)),
this._store.select(InvoiceSelectors.currentInvoice)
)
);
}

--- foo.selectors.ts
export const byRoute = createSelector(
RouterSelectors.currentParams,
(params: Params): string => {
return params.id;
}
);

export const currentInvoice = createSelector(
selectFeature,
(state: FeatureState) => state.counter
);

IStoreItem is just a way to wrap the response and universally (thought-out your application) check if the store slice ready.

1
2
3
4
export interface IStoreItem<T> {
isLoading: boolean;
item?: T;
}

Using selectors with props

To select a piece of state based on data that isn’t available in the store you can pass props to the selector function.

1
2
3
4
5
6
7
8
9
10
11
12
--- foo.facade.ts
public getCurrentInvoice (): Observable<IStoreItem<IInvoice>> {
return this._store.pipe(select(fromRoot.getCount, { multiply: 2 }))
}

--- foo.selectors.ts
--- here `counter` is the response from `getCounterValue` and `props` came from the call to `getCount` above. NgRx is wierd :D

export const getCount = createSelector(
getCounterValue,
(counter, props) => counter * props.multiply
);

RxJS Operators

In the .pipe( you can call any of these operators

filter

1
2
3
4
5
6
7
8
// filter to check the something comes back and properties are set
filter(storeItem => storeItem && !!storeItem.item),

// filter on a bool
filter(a => a.isLoading === false),

// filter that SOMETHING came back
filter(Boolean),

tap

1
2
// quick tap to display whats coming back
tap(a => console.log(a)),

distinctUntilChanged

1
2
3
4
5
6
7
8
9
10
11
// only fire down to the `subscribe` when `item.listingId` changes
distinctUntilChanged((prev, curr) => prev.item.listingId === curr.item.listingId)

// Example
this._listingFacade.getCurrentListing().pipe(
takeUntil(this._destroyed$),
filter(storeItem => storeItem && !!storeItem.item),
distinctUntilChanged((prev, curr) => prev.item.listingId === curr.item.listingId)
).subscribe(storeItem => {
// do something, this was usewful when resetting state
});

References

Jest

Jest is a javaScript testing framework.

1
2
3
4
5
6
7
toHaveBeenCalledWith

toBeInstanceOf

toBe

toMatchSnapshot

TestBed with mockReturnValue

This can be called inside the tests body to mock out the function getFeatures

1
TestBed.get(SomeFacade).getFeatures = jest.fn().mockReturnValue(of());

Data driven

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
--- with toBeObservable
describe('[childComponentEnabled$]', () => {
[
{ abName: true, expected: true },
{ abName: false, expected: false }
].forEach(({ abName, expected }) =>
it(`should ${expected ? '' : 'not'} use 'child-component-to-maybe-show' if abName feature is ${abName}`, marbles((m) => {
// Arrange
const fixture = TestBed.createComponent(ParentComponent);
const testComponent = fixture.componentInstance;
const abFeature = <IAbFeature> {
name: 'abName',
value: abName.toString(),
winningVariantName: 'OnVariant'
};
TestBed.get(AbFrameworkFacade).getByName = () => of(abFeature);

// Act
fixture.detectChanges();

// Assert
m.expect(testComponent.childComponentEnabled$).toBeObservable('(a|)', {
a: expected
});
}))
);
});

--- passing the array elements by object `testcase`
describe(`getSomeMethod`, () => {
[
{
someObject: {},
someBool: true,
someString: 'hoe',
someEnum: SomeEnum.hoe,
expected: 'foo'
},
{
someObject: {},
someBool: true,
someString: 'bazz',
someEnum: SomeEnum.foo,
expected: 'foo bar'
}
].forEach(testcase => {
it(`does some sweet thing,
testcase ${JSON.stringify(testcase)}`, () => {
// do all the things and set `actual`
const actual = 'wat';
expect(actual).toBe(testcase.expected);
});
});
});

References