Skip to content

Commit

Permalink
feat: add Crutchfield site
Browse files Browse the repository at this point in the history
- add support for Crutchfield
  • Loading branch information
dylants committed Aug 13, 2023
1 parent b918363 commit 458a11f
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ The <a href="https://www.npmjs.org/package/pino">pino</a> package is used within
The current supported sites are listed below.

- Amazon
- Crutchfield (requires Node 16)
- Home Depot

Don't see your site listed? Please consider [contributing](#contributing) to the project!
Expand Down
41 changes: 41 additions & 0 deletions src/sites/Crutchfield.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Site from '../Site';
import logger from '../logger';
import * as siteUtils from '../site-utils';
import { CheerioAPI } from 'cheerio';

export default class Crutchfield implements Site {
constructor(protected uri: string) {
if (!Crutchfield.isSite(uri)) {
throw new Error(`invalid uri for Crutchfield: ${uri}`);
}
}

getURIForPageData(): string {
return this.uri;
}

findPriceOnPage($: CheerioAPI): number {
const selectors = ['.pricing-wrapper .price.js-price'];

const priceString = siteUtils.findContentOnPage($, selectors);

if (!priceString) {
logger.error('price not found on Crutchfield page, uri: %s', this.uri);
return -1;
}

const price = siteUtils.processPrice(priceString);

return price;
}

static isSite(uri: string): boolean {
if (uri.indexOf('www.crutchfield.com') > -1) {
return true;
} else {
return false;
}
}
}

module.exports = Crutchfield;
12 changes: 12 additions & 0 deletions test/e2e/Crutchfield.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { priceFinder, verifyPrice } from './testHelper';

describe('price-finder for Crutchfield URIs', () => {
// Headphones
const uri =
'https://www.crutchfield.com/p_158WF1KX5B/Sony-WF-1000XM5-Black.html?tp=60828';

it('should respond with a price', async () => {
const price = await priceFinder.findItemPrice(uri);
verifyPrice(price);
});
});
60 changes: 60 additions & 0 deletions test/unit/sites/Crutchfield.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as cheerio from 'cheerio';
import Crutchfield from '../../../src/sites/Crutchfield';

const VALID_URI = 'http://www.crutchfield.com/product';
const INVALID_URI = 'http://www.bad.com/product';

describe('The Crutchfield Site', () => {
describe('isSite() function', () => {
it('should return true for a correct site', () => {
expect(Crutchfield.isSite(VALID_URI)).toEqual(true);
});

it('should return false for a bad site', () => {
expect(Crutchfield.isSite(INVALID_URI)).toEqual(false);
});
});

it('should throw an exception trying to create a new Crutchfield with an incorrect uri', () => {
expect(() => {
new Crutchfield(INVALID_URI);
}).toThrow(/invalid uri for Crutchfield/);
});

describe('a new Crutchfield Site', () => {
let site: Crutchfield;

beforeEach(() => {
site = new Crutchfield(VALID_URI);
});

it('should return the same URI for getURIForPageData()', () => {
expect(site.getURIForPageData()).toEqual(VALID_URI);
});

describe('with a populated page', () => {
let $: cheerio.CheerioAPI;
let bad$: cheerio.CheerioAPI;
let price: number;

beforeEach(() => {
price = 499.0;

$ = cheerio.load(
`<div class="pricing-wrapper"><div class="price js-price">$${price}</div></div>`,
);
bad$ = cheerio.load('<h1>Nothin here</h1>');
});

it('should return the price when displayed on the page', () => {
const priceFound = site.findPriceOnPage($);
expect(priceFound).toEqual(price);
});

it('should return -1 when the price is not found', () => {
const priceFound = site.findPriceOnPage(bad$);
expect(priceFound).toEqual(-1);
});
});
});
});

0 comments on commit 458a11f

Please sign in to comment.