diff --git a/api/mac-checker.js b/api/mac-checker.js index 73a6e17d..057e11ca 100644 --- a/api/mac-checker.js +++ b/api/mac-checker.js @@ -7,7 +7,8 @@ import { normalizeMacQuery } from '../common/mac-input.js'; import { lookupMac } from '../common/oui-db.js'; -export default async (req, res) => { +// `lookup` is injectable so tests can run the handler over fixture registries. +export const createMacChecker = (lookup) => async (req, res) => { const { mac } = req.query; if (!mac) { return res.status(400).json({ error: 'No MAC address provided' }); @@ -18,9 +19,11 @@ export default async (req, res) => { } // Past the boot window (requireOfflineData) only a failed download leaves this empty. - const result = lookupMac(hex); + const result = lookup(hex); if (!result) { return res.status(503).json({ error: 'MAC database unavailable' }); } res.json(result); }; + +export default createMacChecker(lookupMac); diff --git a/tests/api-handlers.test.js b/tests/api-handlers.test.js index 928161e3..d5b7645d 100644 --- a/tests/api-handlers.test.js +++ b/tests/api-handlers.test.js @@ -19,12 +19,12 @@ import getUserInfoHandler from '../api/get-user-info.js'; import getWhoisHandler from '../api/get-whois.js'; import cfRadarHandler from '../api/cf-radar.js'; import invisibilityHandler from '../api/invisibility-test.js'; -import macCheckerHandler from '../api/mac-checker.js'; +import macCheckerHandler, { createMacChecker } from '../api/mac-checker.js'; import githubStarsHandler from '../api/github-stars.js'; import personaEvaluateHandler from '../api/persona.js'; import asnProfileHandler, { peeringdbReadiness, connectivityReadiness } from '../api/asn-profile.js'; import { isAsRelLoaded } from '../common/as-rel-db.js'; -import { isOuiLoaded } from '../common/oui-db.js'; +import { describeMac } from '../common/oui-db.js'; import { isCompleteProfile } from '../common/asn-profile.js'; import updateAchievementHandler from '../api/update-user-achievement.js'; import ipcheckIngHandler from '../api/ipcheck-ing.js'; @@ -595,19 +595,26 @@ describe('mac-checker handler', () => { assert.equal(res.statusCode, 400); }); - // Reads the repo's local registries: answered when they're on disk, - // 503 when this checkout never downloaded them. - it('answers a vendor prefix from the local registries, or 503 without them', async () => { + // Over fixture registries, so the answer doesn't depend on a download. + const fixtureBlocks = new Map([ + ['3C5AB4', { registry: 'MA-L', company: 'Google, Inc.', address: 'Mountain View US 94043', country: 'US' }], + ]); + + it('answers a vendor prefix in any notation from the registries', async () => { + const handler = createMacChecker((hex) => describeMac(fixtureBlocks, hex)); const res = createResponse(); - await macCheckerHandler(createRequest({ query: { mac: '3c:5a:b4' } }), res); - if (!isOuiLoaded()) { - assert.equal(res.statusCode, 503); - assert.deepEqual(res.body, { error: 'MAC database unavailable' }); - return; - } + await handler(createRequest({ query: { mac: '3c5a.b4' } }), res); assert.equal(res.statusCode, 200); - assert.equal(res.body.success, true); - assert.equal(res.body.macPrefix.slice(0, 8), '3C:5A:B4'); + assert.equal(res.body.found, true); + assert.equal(res.body.company, 'Google, Inc.'); + assert.equal(res.body.blockSize, 16777216); + }); + + it('answers 503 when no registries are loaded', async () => { + const res = createResponse(); + await createMacChecker(() => null)(createRequest({ query: { mac: '3C:5A:B4' } }), res); + assert.equal(res.statusCode, 503); + assert.deepEqual(res.body, { error: 'MAC database unavailable' }); }); });