Skip to content

Commit

Permalink
Merge pull request #564 from 18F/remove-axios
Browse files Browse the repository at this point in the history
Replace axios with native fetch
  • Loading branch information
mgwalker authored Nov 21, 2024
2 parents 1781211 + 67f1e72 commit 2704194
Show file tree
Hide file tree
Showing 19 changed files with 231 additions and 266 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"dependencies": {
"@18f/us-federal-holidays": "^4.0.0",
"@slack/bolt": "^4.1.0",
"axios": "^1.7.7",
"cfenv": "^1.2.3",
"cheerio": "^1.0.0-rc.12",
"csv-parse": "^5.0.4",
Expand Down
5 changes: 2 additions & 3 deletions src/scripts/define.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
// @bot define contracting officer

const { directMention } = require("@slack/bolt");
const axios = require("axios");
const he = require("he");
const yaml = require("js-yaml");
const {
Expand Down Expand Up @@ -114,9 +113,9 @@ module.exports = (app) => {

// Cache the glossary for 1 minute
const glossary = await cache("glossary get", 60, async () => {
const { data } = await axios.get(
const data = await fetch(
"https://raw.githubusercontent.com/18F/the-glossary/main/glossary.yml",
);
).then((r) => r.text());

return yaml.load(data, { json: true }).entries;
});
Expand Down
8 changes: 5 additions & 3 deletions src/scripts/define.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const {
axios,
getApp,
utils: { cache },
} = require("../utils/test");
Expand Down Expand Up @@ -228,8 +227,11 @@ describe("glossary", () => {

const fetcher = cache.mock.calls[0].pop();

axios.get.mockResolvedValue({
data: `
fetch.mockResolvedValue({
// The data being pulled across the network is expected to be YAML, so
// we need to be sure we format it correctly here. Hence the funky-looking
// string.
text: async () => `
entries:
term 1: ATO
term 2:
Expand Down
34 changes: 13 additions & 21 deletions src/scripts/dot-gov.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
*/

const { directMention } = require("@slack/bolt");
const axios = require("axios");
const https = require("https");

/* eslint-disable import/no-unresolved */
Expand Down Expand Up @@ -91,10 +90,10 @@ const DOMAIN_TYPES = {

/** Current list of fields available in the CSV file. */
const DATA_FIELDS = {
NAME: "Domain Name",
TYPE: "Domain Type",
NAME: "Domain name",
TYPE: "Domain type",
AGENCY: "Agency",
ORG: "Organization",
ORG: "Organization name",
CITY: "City",
STATE: "State",
};
Expand Down Expand Up @@ -186,15 +185,13 @@ const selectDomainsAtRandom = (domainsArr, numToSelect) => {
* Returns a human-readable response status.
*/
const checkDomainStatus = async (domainObj, timeout = 2000) =>
axios
.head(`https://${domainObj[DATA_FIELDS.NAME]}`, {
timeout,
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
})
fetch(`https://${domainObj[DATA_FIELDS.NAME]}`, {
method: "HEAD",
agent: new https.Agent({ rejectUnauthorized: false }),
signal: AbortSignal.timeout(timeout),
})
.then((response) => {
if (response && response.status) {
if (response?.ok && response.status) {
return response.statusText;
}
return "Unknown Status";
Expand All @@ -203,7 +200,7 @@ const checkDomainStatus = async (domainObj, timeout = 2000) =>
if (error.response) {
return error.response.statusText;
}
if (error.code === "CERT_HAS_EXPIRED") {
if (error.cause?.code === "CERT_HAS_EXPIRED") {
return "Cert Expired";
}
return "Unknown Status";
Expand Down Expand Up @@ -240,14 +237,9 @@ module.exports = (app) => {
module.exports.dotGov = async ({ entity, searchTerm, say, thread }) => {
// fetch the domain list
const domains = await cache("dotgov domains", 1440, async () =>
axios
.get(CISA_DOTGOV_DATA_URL)
.then((response) => {
if (response && response.data) {
return parse(response.data, { columns: true });
}
return [];
})
fetch(CISA_DOTGOV_DATA_URL)
.then((response) => response.text())
.then((data) => parse(data, { columns: true }))
.catch(() => []),
);

Expand Down
101 changes: 48 additions & 53 deletions src/scripts/dot-gov.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const {
axios,
getApp,
utils: { cache },
} = require("../utils/test");
Expand All @@ -12,81 +11,81 @@ describe("dot-gov domains", () => {
{
Agency: "Non-Federal Agency",
City: "Albany",
"Domain Name": "ALBANYCA.GOV",
"Domain Type": "City",
Organization: "City of Albany",
"Domain name": "ALBANYCA.GOV",
"Domain type": "City",
"Organization name": "City of Albany",
"Security Contact Email": "(blank)",
State: "CA",
},
{
Agency: "Non-Federal Agency",
City: "Belle Plaine",
"Domain Name": "BELLEPLAINEIOWA.GOV",
"Domain Type": "City",
Organization: "City of Belle Plaine",
"Domain name": "BELLEPLAINEIOWA.GOV",
"Domain type": "City",
"Organization name": "City of Belle Plaine",
"Security Contact Email": "(blank)",
State: "IA",
},
{
Agency: "U.S. Department of Agriculture",
City: "Washington",
"Domain Name": "RURAL.GOV",
"Domain Type": "Federal - Executive",
Organization: "Rural Development",
"Domain name": "RURAL.GOV",
"Domain type": "Federal - Executive",
"Organization name": "Rural Development",
"Security Contact Email": "cyber.(blank)",
State: "DC",
},
{
Agency: "The Supreme Court",
City: "Washington",
"Domain Name": "SUPREMECOURTUS.GOV",
"Domain Type": "Federal - Judicial",
Organization: "Supreme Court of the United Statest",
"Domain name": "SUPREMECOURTUS.GOV",
"Domain type": "Federal - Judicial",
"Organization name": "Supreme Court of the United Statest",
"Security Contact Email": "(blank)",
State: "DC",
},
{
Agency: "Government Publishing Office",
City: "Washington",
"Domain Name": "USCODE.GOV",
"Domain Type": "Federal - Legislative",
Organization: "United States Government Publishing Office",
"Domain name": "USCODE.GOV",
"Domain type": "Federal - Legislative",
"Organization name": "United States Government Publishing Office",
"Security Contact Email": "(blank)",
State: "DC",
},
{
Agency: "Non-Federal Agency",
City: "Arizona City",
"Domain Name": "ACSD-AZ.GOV",
"Domain Type": "Independent Intrastate",
Organization: "Arizona City Sanitary District ",
"Domain name": "ACSD-AZ.GOV",
"Domain type": "Independent Intrastate",
"Organization name": "Arizona City Sanitary District ",
"Security Contact Email": "(blank)",
State: "AZ",
},
{
Agency: "Non-Federal Agency",
City: "Mechanicsburg",
"Domain Name": "EMSCOMPACT.GOV",
"Domain Type": "Interstate",
Organization: "Interstate Commission for EMS Personnel Practice",
"Domain name": "EMSCOMPACT.GOV",
"Domain type": "Interstate",
"Organization name": "Interstate Commission for EMS Personnel Practice",
"Security Contact Email": "(blank)",
State: "PA",
},
{
Agency: "Non-Federal Agency",
City: "St Croix",
"Domain Name": "VIVOTE.GOV",
"Domain Type": "State",
Organization: "Election System of the Virgin Islands",
"Domain name": "VIVOTE.GOV",
"Domain type": "State",
"Organization name": "Election System of the Virgin Islands",
"Security Contact Email": "(blank)",
State: "VI",
},
{
Agency: "Non-Federal Agency",
City: "Ada",
"Domain Name": "CHICKASAW-NSN.GOV",
"Domain Type": "Tribal",
Organization: "the Chickasaw Nation",
"Domain name": "CHICKASAW-NSN.GOV",
"Domain type": "Tribal",
"Organization name": "the Chickasaw Nation",
"Security Contact Email": "(blank)",
State: "OK",
},
Expand All @@ -99,10 +98,16 @@ describe("dot-gov domains", () => {
username: ".Gov",
};

const fetchResponse = {
json: jest.fn(),
text: jest.fn(),
};

beforeAll(() => {});

beforeEach(() => {
jest.resetAllMocks();
fetch.mockResolvedValue(fetchResponse);
});

afterAll(() => {});
Expand Down Expand Up @@ -138,38 +143,39 @@ describe("dot-gov domains", () => {
});

describe("gets domains from github if the cache is expired or whatever", () => {
let fetch;
let fetcher;

beforeEach(async () => {
cache.mockResolvedValue([]);
await handler(message);
fetch = cache.mock.calls[0][2];
fetcher = cache.mock.calls[0][2];
});

it("if the API throws an error", async () => {
axios.get.mockRejectedValue("error");
const out = await fetch();
fetch.mockRejectedValue("error");
const out = await fetcher();

expect(out).toEqual([]);
});

it("if the API returns a malformed object", async () => {
axios.get.mockResolvedValue({ data: { data_is_missing: [] } });
const out = await fetch();
fetchResponse.json.mockResolvedValue({ data: { data_is_missing: [] } });
const out = await fetcher();

expect(out).toEqual([]);
});

it("if the API doesn't return any domains", async () => {
axios.get.mockResolvedValue({ data: { data: [] } });
const out = await fetch();
fetchResponse.json.mockResolvedValue({ data: { data: [] } });
const out = await fetcher();

expect(out).toEqual([]);
});

it("if the API does return some domains", async () => {
axios.get.mockResolvedValue({
data: [
"Domain Name,Domain Type,Agency,Organization,City,State,Security Contact Email",
fetchResponse.text.mockResolvedValue(
[
"Domain name,Domain type,Agency,Organization name,City,State,Security Contact Email",
"ALBANYCA.GOV,City,Non-Federal Agency,City of Albany,Albany,CA,(blank)",
"BELLEPLAINEIOWA.GOV,City,Non-Federal Agency,City of Belle Plaine,Belle Plaine,IA,(blank)",
"RURAL.GOV,Federal - Executive,U.S. Department of Agriculture,Rural Development,Washington,DC,cyber.(blank)",
Expand All @@ -180,18 +186,14 @@ describe("dot-gov domains", () => {
"VIVOTE.GOV,State,Non-Federal Agency,Election System of the Virgin Islands,St Croix,VI,(blank)",
"CHICKASAW-NSN.GOV,Tribal,Non-Federal Agency,the Chickasaw Nation,Ada,OK,(blank)",
].join("\n"),
});
const out = await fetch();
);
const out = await fetcher();

expect(out).toEqual(mockCache);
});
});

describe("responds with a domain", () => {
beforeEach(() => {
axios.head.mockImplementation(() => Promise.resolve("Ok"));
});

it("unless there aren't any domains", async () => {
cache.mockResolvedValue([]);
await handler(message);
Expand All @@ -216,7 +218,7 @@ describe("dot-gov domains", () => {
});

it("even if checking the status of the domain fails", async () => {
axios.head.mockImplementation(() => Promise.reject(new Error()));
fetch.mockRejectedValue(new Error());
cache.mockResolvedValue(mockCache);
await handler(message);

Expand Down Expand Up @@ -281,10 +283,6 @@ describe("dot-gov domains", () => {
const message = { message: { thread_ts: "thread id" }, say: jest.fn() };

describe("responds with results", () => {
beforeEach(() => {
axios.head.mockImplementation(() => Promise.resolve("Ok"));
});

it("if there aren't any results", async () => {
cache.mockResolvedValue(mockCache);
message.context = {
Expand Down Expand Up @@ -341,9 +339,6 @@ describe("dot-gov domains", () => {
});
});
describe("filters correctly by entity", () => {
beforeEach(() => {
axios.head.mockImplementation(() => Promise.resolve("Ok"));
});
it("if entity is executive", async () => {
cache.mockResolvedValue(mockCache);
message.context = {
Expand Down
11 changes: 6 additions & 5 deletions src/scripts/handbook.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const axios = require("axios");
const {
helpMessage,
slack: { postEphemeralResponse },
Expand Down Expand Up @@ -42,19 +41,21 @@ module.exports = (app) => {

const {
context: {
matches: [, , search],
matches: [, search],
},
event: { thread_ts: thread, ts },
say,
} = msg;

console.log(msg.context.matches);

const searchString = search
.replace(/[”“]/g, '"') // replace smart quotes
.replace(/[’‘]/g, "'"); // more smart quotes
?.replace(/[”“]/g, '"') // replace smart quotes
?.replace(/[’‘]/g, "'"); // more smart quotes
const url = `${baseUrl}${encodeURIComponent(searchString)}`;

try {
const { data } = await axios.get(url);
const data = await fetch(url).then((r) => r.json());
const results = data.results.slice(0, 3);

if (results.length === 0) {
Expand Down
Loading

0 comments on commit 2704194

Please sign in to comment.