Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
started on mdn json api usage
  • Loading branch information
nathancyam committed Jul 4, 2020
commit 662d04611293d628530168cc74e16b2f36191b0f
30 changes: 29 additions & 1 deletion src/commands/mdn/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import * as errors from '../../utils/errors';
import { getSearchUrl } from '../../utils/urlTools';
import useData from '../../utils/useData';

import { queryBuilder } from '.';
import { queryBuilder, updatedQueryBuilder } from '.';
import { getChosenResult } from '../../utils/discordTools';
import { searchResponse } from './__fixtures__/responses';

jest.mock('dom-parser');
jest.mock('../../utils/urlTools');
jest.mock('../../utils/useData');

const mockGetSearchUrl: jest.MockedFunction<typeof getSearchUrl> = getSearchUrl as any;
const mockUseData: jest.MockedFunction<typeof useData> = useData as any;
const mockChoose: jest.MockedFunction<typeof getChosenResult> = getChosenResult as any;

describe('handleMDNQuery', () => {
const sendMock = jest.fn();
Expand Down Expand Up @@ -116,3 +119,28 @@ describe('handleMDNQuery', () => {
expect(sentMessage).toMatchSnapshot();
});
});

describe('updatedMDNQuery', () => {
const sendMock = jest.fn();
const replyMock = jest.fn();
const msg: any = {
channel: { send: sendMock },
reply: replyMock,
};

test('should work', async () => {
mockGetSearchUrl.mockReturnValue('http://example.com');
mockUseData.mockResolvedValueOnce({
error: false,
text: null,
json: searchResponse,
});

const handler = updatedQueryBuilder(
mockGetSearchUrl,
mockUseData,
mockChoose
);
await handler(msg, 'Search Term');
});
});
91 changes: 91 additions & 0 deletions src/commands/mdn/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,38 @@ interface ParserResult {
meta: string;
}

interface SearchResponse {
query: string;
locale: string;
page: number;
pages: number;
starts: number;
end: number;
next: string;
previous: string | null;
count: number;
filter: Array<{
name: string;
slug: string;
options: Array<{
name: string;
slug: string;
count: number;
active: boolean;
urls: {
active: string;
inactive: string;
};
}>;
}>;
documents: Array<{
title: string;
slug: string;
locale: string;
excerpt: string;
}>;
}

interface ResultMeta {
getElementsByClassName(cls: string): DOMParser.Node[];
}
Expand Down Expand Up @@ -75,6 +107,65 @@ const extractMetadataFromResult = (result: ResultMeta) => {
};
};

export const updatedQueryBuilder = (
searchUrl: typeof getSearchUrl = getSearchUrl,
fetch: typeof useData = useData,
waitForChosenResult: typeof getChosenResult = getChosenResult
) => async (msg: Message, searchTerm: string) => {
const url = searchUrl(provider, searchTerm);
const { error, json } = await fetch<SearchResponse>(url, 'json');
if (!error) {
return msg.reply(errors.invalidResponse);
}

if (json.documents.length === 0) {
const sentMsg = await msg.reply(errors.noResults(searchTerm));
return delayedMessageAutoDeletion(sentMsg);
}

let preparedDescription = json.documents.map(
({ title, excerpt, slug }, index) =>
createMarkdownListItem(
index,
createMarkdownLink(
adjustTitleLength([`**${title}**`, excerpt].join(' - ')),
buildDirectUrl(provider, slug)
)
)
);

const expectedLength = preparedDescription.reduce(
(sum, item) => sum + item.length,
0
);
if (expectedLength + BASE_DESCRIPTION.length + 10 * '\n'.length > 2048) {
preparedDescription = preparedDescription.map(string => {
// split at markdown link ending
const [title, ...rest] = string.split('...]');

// split title on title - excerpt glue
// concat with rest
// fix broken markdown link ending
return [title.split(' - ')[0], rest.join('')].join(']');
});
}

const sentMsg = await msg.channel.send(
createListEmbed({
description: createDescription(preparedDescription),
footerText: 'Powered by the search API',
provider,
searchTerm,
url,
})
);

const result = await waitForChosenResult(sentMsg, msg, json.documents);
if (!result) {
return;
}
};

/**
* Poor man's dependency injection without introducing classes, just use closures
* and higher order functions instead. Also provides a default so we don't have
Expand Down
2 changes: 1 addition & 1 deletion src/utils/urlTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const providers: ProviderMap = {
createTitle: (searchTerm: string) => `NPM results for *${searchTerm}*`,
help: '!npm react',
icon: 'https://avatars0.githubusercontent.com/u/6078720',
search: `https://www.npmjs.com/search/suggestions?q=${SEARCH_TERM}`,
search: `https://developer.mozilla.org/api/v1/search/en-US?highlight=false&q=${SEARCH_TERM}`,
},
php: {
color: 0x8892bf,
Expand Down