Skip to content

Commit

Permalink
✨ [Socialite] New methods and one renamed method (#33)
Browse files Browse the repository at this point in the history
* ✨ [Socialite] New method and one renamed method

* 🔥 [Utilities] Remove getUrlWithSubstitutions from global exports

* ⏪ [Utilities] Revert last commit

* 📝 [Changeset] Create report
  • Loading branch information
beefchimi authored Jan 19, 2022
1 parent de51f10 commit ffdd379
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 54 deletions.
5 changes: 5 additions & 0 deletions .changeset/fast-carpets-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'socialitejs': patch
---

Added `getNetwork()` and `getPreferredUrl()` methods. Also renamed `getNetworks()` to `getAllNetworks()`.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import type {SocialiteId} from 'socialitejs';
const allNetworksInstance = new Socialite(Object.values(socialiteNetworks));

// Logs to the console all social networks included in the code base.
console.log(allNetworksInstance.getNetworks());
console.log(allNetworksInstance.getAllNetworks());

// Initializing `Socialite` without any networks (pass empty `array`):
const selectiveNetworksInstance = new Socialite([]);
Expand All @@ -81,7 +81,7 @@ Object.keys(socialiteNetworks).forEach((network) => {
});

// Logs to the console all social networks not found in `excludedNetworks`.
console.log(selectiveNetworksInstance.getNetworks());
console.log(selectiveNetworksInstance.getAllNetworks());
```

## Features
Expand Down
28 changes: 23 additions & 5 deletions src/socialite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import {defaultUserMatcher, schemeRegExp} from './capture';
import {MatchUserSource} from './types';
import type {
BasicUrl,
ParsedUrlGroups,
NetworkId,
SocialiteNetwork,
NetworkMap,
SocialiteNetworkProperties,
ParsedUrlGroups,
SocialiteProfile,
SocialiteNetwork,
SocialiteNetworkProperties,
UrlMinCriteria,
UserName,
} from './types';
import {
filterNetworkProperties,
Expand Down Expand Up @@ -52,12 +53,29 @@ export class Socialite {
this._networks.clear();
}

getNetworks(subset?: SocialiteNetworkProperties) {
getNetwork(id: NetworkId) {
return this._networks.get(id);
}

getAllNetworks(subset?: SocialiteNetworkProperties) {
return [...this._networks.values()].map((network) =>
subset ? filterNetworkProperties(network, subset) : network,
);
}

getPreferredUrl(id: NetworkId, user?: UserName) {
if (!this.hasNetwork(id)) {
return false;
}

// BUG: TypeScript doesn't understand that we have
// returned early if the `id` does not exist.
// https://github.com/beefchimi/socialite/issues/4
const {preferredUrl, prefix} = this.getNetwork(id) as SocialiteNetwork;

return getUrlWithSubstitutions(preferredUrl, user, prefix);
}

parseUrl(url: BasicUrl) {
const groups = getUrlGroups(url);
// TODO: https://github.com/beefchimi/socialite/issues/5
Expand All @@ -78,7 +96,7 @@ export class Socialite {
// https://github.com/beefchimi/socialite/issues/4
const targetNetwork =
id && this.hasNetwork(id)
? this._networks.get(id)
? this.getNetwork(id)
: this.getNetworkFromDomain(groups.domain);

if (!targetNetwork) {
Expand Down
141 changes: 97 additions & 44 deletions src/tests/socialite-network-methods.test.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,22 @@
import {defaultSocialiteNetworks} from '../data';
import {
facebook as networkFacebook,
twitter as networkTwitter,
} from '../networks';
import {Socialite} from '../socialite';
import type {
SocialiteNetwork,
NetworkMap,
NetworkSubset,
SocialiteNetworkProperties,
} from '../types';
import {mockCustomNetworks} from './fixtures';
import {mockCustomNetworks, mockGenericUser} from './fixtures';

describe('Socialite network methods', () => {
describe('getNetworks() > subset', () => {
it('returns only the properties requested', () => {
const mockSubset: SocialiteNetworkProperties = [
'preferredUrl',
'matcher',
];
const mockSocialite = new Socialite();

const networks = mockSocialite.getNetworks(mockSubset);

const defaultFirstNetwork = defaultSocialiteNetworks[0];
const defaultLastNetwork =
defaultSocialiteNetworks[defaultSocialiteNetworks.length - 1];

const firstNetworkSubset = networks[0];
const defaultFirstNetworkSubset = {
preferredUrl: defaultFirstNetwork.preferredUrl,
matcher: defaultFirstNetwork.matcher,
};

const lastNetworkSubset = networks[networks.length - 1];
const defaultLastNetworkSubset = {
preferredUrl: defaultLastNetwork.preferredUrl,
matcher: defaultLastNetwork.matcher,
};

expect(firstNetworkSubset).toStrictEqual(defaultFirstNetworkSubset);
expect(lastNetworkSubset).toStrictEqual(defaultLastNetworkSubset);
});
});

describe('hasNetwork()', () => {
it('returns `true` when requesting a default network', () => {
const mockSocialite = new Socialite();
expect(mockSocialite.hasNetwork('facebook')).toBe(true);
expect(mockSocialite.hasNetwork(networkFacebook.id)).toBe(true);
});

it('returns `true` when requesting a non-default network that has been added', () => {
Expand Down Expand Up @@ -71,7 +44,7 @@ describe('Socialite network methods', () => {

const networkKeysFromMap = [...(addedNetwork as NetworkMap).keys()];
const networkKeysFromObjects = filterNetworkIds(
mockSocialite.getNetworks(),
mockSocialite.getAllNetworks(),
);

expect(networkKeysFromMap).toStrictEqual(networkKeysFromObjects);
Expand All @@ -87,14 +60,14 @@ describe('Socialite network methods', () => {
};

const mockSocialite = new Socialite();
const initialNetworks = mockSocialite.getNetworks();
const initialNetworks = mockSocialite.getAllNetworks();

expect(initialNetworks[0]).toBe(defaultSocialiteNetworks[0]);

const addedNetwork = mockSocialite.addNetwork(mockNetwork);
expect(addedNetwork).toBe(false);

const updatedNetworks = mockSocialite.getNetworks();
const updatedNetworks = mockSocialite.getAllNetworks();

expect(updatedNetworks[0]).toBe(defaultSocialiteNetworks[0]);
expect(updatedNetworks[0]).not.toBe(mockNetwork);
Expand All @@ -107,12 +80,12 @@ describe('Socialite network methods', () => {
};

const mockSocialite = new Socialite();
const initialNetworks = mockSocialite.getNetworks();
const initialNetworks = mockSocialite.getAllNetworks();

expect(initialNetworks[0]).toBe(defaultSocialiteNetworks[0]);

const addedNetwork = mockSocialite.addNetwork(mockNetwork, true);
const updatedNetworks = mockSocialite.getNetworks();
const updatedNetworks = mockSocialite.getAllNetworks();

expect(updatedNetworks[0]).not.toBe(defaultSocialiteNetworks[0]);
expect(updatedNetworks[0]).toBe(mockNetwork);
Expand All @@ -127,15 +100,15 @@ describe('Socialite network methods', () => {
const mockRemovedId = defaultSocialiteNetworks[0].id;
const mockSocialite = new Socialite();

expect(mockSocialite.hasNetwork('facebook')).toBe(true);
expect(mockSocialite.hasNetwork(networkFacebook.id)).toBe(true);

const removedNetwork = mockSocialite.removeNetwork(mockRemovedId);

expect(removedNetwork).toBe(true);
expect(mockSocialite.hasNetwork('facebook')).toBe(false);
expect(mockSocialite.hasNetwork(networkFacebook.id)).toBe(false);

const networkKeysFromObjects = filterNetworkIds(
mockSocialite.getNetworks(),
mockSocialite.getAllNetworks(),
);

expect(networkKeysFromObjects).toHaveLength(
Expand All @@ -155,7 +128,7 @@ describe('Socialite network methods', () => {
expect(mockSocialite.hasNetwork(mockRemovedId)).toBe(false);

const networkKeysFromObjects = filterNetworkIds(
mockSocialite.getNetworks(),
mockSocialite.getAllNetworks(),
);

expect(networkKeysFromObjects).toHaveLength(
Expand All @@ -168,15 +141,95 @@ describe('Socialite network methods', () => {
it('completely empties the network Map', () => {
const mockSocialite = new Socialite();

const initialNetworks = mockSocialite.getNetworks();
const initialNetworks = mockSocialite.getAllNetworks();
expect(initialNetworks).toHaveLength(defaultSocialiteNetworks.length);

mockSocialite.emptyNetworks();

const updatedNetworks = mockSocialite.getNetworks();
const updatedNetworks = mockSocialite.getAllNetworks();
expect(updatedNetworks).toHaveLength(0);
});
});

describe('getNetwork()', () => {
it('returns the requested network', () => {
const mockSocialite = new Socialite();

const network = mockSocialite.getNetwork(networkFacebook.id);
expect(network).toStrictEqual(networkFacebook);
});

it('returns `undefined` if the network does not exist', () => {
const mockSocialite = new Socialite();

const network = mockSocialite.getNetwork('foo');
expect(network).toBeUndefined();
});
});

describe('getAllNetworks()', () => {
it('returns everything by default', () => {
const mockSocialite = new Socialite();
const networks = mockSocialite.getAllNetworks();

// TODO: There are likely better patterns for looping
// over assertings in Jest / Vitest.
networks.forEach((network, index) => {
expect(network).toStrictEqual(defaultSocialiteNetworks[index]);
});
});

it('returns only the properties requested', () => {
const mockSubset: SocialiteNetworkProperties = [
'preferredUrl',
'matcher',
];
const mockSocialite = new Socialite();

const networks = mockSocialite.getAllNetworks(mockSubset);

const defaultNetworkSubsets: NetworkSubset[] =
defaultSocialiteNetworks.map(({preferredUrl, matcher}) => ({
preferredUrl,
matcher,
}));

// TODO: There are likely better patterns for looping
// over assertings in Jest / Vitest.
networks.forEach((network, index) => {
expect(network).toStrictEqual(defaultNetworkSubsets[index]);
});
});
});

describe('getPreferredUrl()', () => {
it('returns the `preferredUrl` with only `user` replaced', () => {
const mockSocialite = new Socialite();

const preferredUrl = mockSocialite.getPreferredUrl(
networkFacebook.id,
mockGenericUser,
);
expect(preferredUrl).toBe(`https://facebook.com/${mockGenericUser}`);
});

it('returns the `preferredUrl` with both `user` and `prefix` replaced', () => {
const mockSocialite = new Socialite();

const preferredUrl = mockSocialite.getPreferredUrl(
networkTwitter.id,
mockGenericUser,
);
expect(preferredUrl).toBe(`https://twitter.com/@${mockGenericUser}`);
});

it('returns `false` if the network does not exist', () => {
const mockSocialite = new Socialite();

const network = mockSocialite.getPreferredUrl('foo');
expect(network).toBe(false);
});
});
});

function filterNetworkIds(networks: NetworkSubset[]) {
Expand Down
10 changes: 7 additions & 3 deletions src/tests/socialite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@ describe('Socialite class instance', () => {

it('contains the default networks', () => {
const mockSocialite = new Socialite();
expect(mockSocialite.getNetworks()).toStrictEqual(defaultSocialiteNetworks);
expect(mockSocialite.getAllNetworks()).toStrictEqual(
defaultSocialiteNetworks,
);
});

it('constructor argument overwrites the default networks', () => {
const mockSocialite = new Socialite(mockCustomNetworks);
expect(mockSocialite.getNetworks()).toStrictEqual(mockCustomNetworks);
expect(mockSocialite.getAllNetworks()).toStrictEqual(mockCustomNetworks);
});

it('constructor argument ignores an empty array', () => {
const mockNetworks: SocialiteNetwork[] = [];
const mockSocialite = new Socialite(mockNetworks);

expect(mockSocialite.getNetworks()).toStrictEqual(defaultSocialiteNetworks);
expect(mockSocialite.getAllNetworks()).toStrictEqual(
defaultSocialiteNetworks,
);
});

describe('fixUrlScheme()', () => {
Expand Down

0 comments on commit ffdd379

Please sign in to comment.