Skip to content

Commit

Permalink
feat(search): support for other than de countries
Browse files Browse the repository at this point in the history
  • Loading branch information
Ephigenia committed Jan 3, 2018
1 parent ee3f267 commit bb3e59e
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 43 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
"postversion": "git push && git push --tags",
"preversion": "npm test",
"start": "node $npm_package_main",
"tdd": "mocha --watch \"$npm_package_config_paths_source/**/*.test.js\"",
"test:ci": "mocha --reporter=dot \"$npm_package_config_paths_source/**/*.test.js\"",
"test:watch": "mocha --watch \"$npm_package_10onfig_paths_source/**/*.test.js\"",
"test": "mocha \"$npm_package_config_paths_source/**/*.test.js\"",
"version": "npm run changelog && git add CHANGELOG.md",
"version:recommend": "conventional-recommended-bump --preset angular"
Expand Down
45 changes: 26 additions & 19 deletions source/cli-search.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const request = require('request');
const Fuse = require('fuse.js');
const Table = require('cli-table');

const stores = require('./lib/stores');
const debug = require('debug')('ikea');

program
Expand All @@ -22,32 +23,31 @@ program
)
.option(
'-c, --country [countryCodes]',
'optional single country id or multiple country ids separated by comma, ' +
'default value is "de" which would list the availability for all stores ' +
'in germany',
'optional single 2-letter country code or multiple country code ' +
'separated by comma, default value is "de" which would list the ' +
'availability for all stores in germany',
'de'
)
.action(function(query) {
// @TODO validate query string, min length = 1

const countryCode = program.country;
// @TODO determine language code from counrtycode using the list from
// cli-stores
const languageCode = countryCode;
const languageCode = stores.getLanguageCode(countryCode);

// the url contains a integer value which is the first letter of the search
// query 0 = A, Z = 25
const firstLetter = query.substr(0, 1).toLowerCase();
const letterCode = firstLetter.charCodeAt(0) - 97;

// @TODO error when letterCodee is not betewen 0 and 25
// @TODO error when letterCode is not betewen 0 and 25

const url = 'http://www.ikea.com/' +
countryCode + '/' + languageCode +
'/catalog/productsaz/' + letterCode
'/';
debug('GET', url);
request.get(url, function(err, response) {
request.get(url, (err, response) => {
// @TODO throw err
debug('RECEIVED', 'statusCode:', response.statusCode, 'bytes:', response.body.length);
const $ = cheerio.load(response.body);
Expand All @@ -66,27 +66,34 @@ program
keys: ['name'],
shouldSort: true,
includeScore: true,
threshold: 0.3,
}
const fuse = new Fuse(productCollections, options);
const matches = fuse.search(query);

debug('found ' + matches.length + ' matches');
if (matches.lenth === 0) {
console.error('No matches found! to saad!');
if (matches.length === 0) {
console.error(
'The given query "' + query +'" with the country code ' +
'"' + countryCode + '" did not lead to any product groups or ' +
'collections matching the query. The query always matches with the ' +
'first letter so be sure that the first letter of the query is ' +
'correct.'
);
process.exit();
}

// when there was something found, scrape the collection page and list
// all products on that page in a table
const url2 = matches[0].item.url;
debug('GET', url2);
request.get(url2, function(err, response) {
request.get(url2, (err, response) => {
// @TODO throw err
debug('RECEIVED', 'statusCode:', response.statusCode, 'bytes:', response.body.length);

// parsing the products out of the html body
const $2 = cheerio.load(response.body);
const productList = $2('.product').toArray()
.map(function(elm) {
.map(elm => {
const imageUri = $2(elm).find('.image img').attr('src');
const uri = $2(elm).find('.productLink').attr('href');
const price = $2(elm).find('.price').text().trim().split(/\r\n/)[0];
Expand All @@ -97,6 +104,7 @@ program
return { name, price, id, uri, imageUri };
});

// generate report
const table = new Table({
head: [
'name',
Expand All @@ -105,15 +113,14 @@ program
'uri',
'imageUri',
],
colAligns: ['left', 'left', 'right']
colAligns: ['left', 'right', 'right']
});
productList
.map(function(product) {
return [product.name, product.price, product.id, product.uri, product.imageUri];
})
.map(function(item) {
table.push(item);
});
.map(product => [
product.name, product.price, product.id, product.uri, product.imageUri
])
.map(item => table.push(item));

console.log(table.toString());
}); // request url2
}); // request
Expand Down
29 changes: 6 additions & 23 deletions source/cli-stores.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,7 @@ const pkg = require('./../package.json');
const request = require('request');

const debug = require('debug')('ikea');

const unsupportedCountryCodes = [
'bg',
'cy',
'do',
'eg',
'es_islas',
'gb',
'gr',
'id',
'ie',
'in',
'is',
'lio',
'ma',
'rs',
'tr',
];
const stores = require('./lib/stores');

program
.version(pkg.version)
Expand Down Expand Up @@ -56,7 +39,7 @@ program
// some of the ikea country pages are not supported by the cli script
// check for such codes and exit before scraping anything
let foundUnsupportedCountryCodes = countryCodes.reduce(function(list, val) {
if (unsupportedCountryCodes.indexOf(val) === -1) return list;
if (stores.isSupportedCountryCode(val)) return list;
list.push(val);
return list;
}, []);
Expand All @@ -78,7 +61,7 @@ program
// trying to use a fixed productId of a product which must be popular in
// all countries
let productId = '30275861';
let languageCode = countryCode;
let languageCode = stores.getLanguageCode(countryCode);

switch(countryCode) {
case 'cz':
Expand Down Expand Up @@ -140,7 +123,7 @@ program
debug('RECEIVED', response.statusCode, response.body.length);
let $ = cheerio.load(response.body);
let storeDropdownElm = $('#ikeaStoreNumber1')[0];
let stores = $(storeDropdownElm).find('option')
let foundStores = $(storeDropdownElm).find('option')
.map(function(index, elm) {
return {
buCode: $(elm).attr('value'),
Expand All @@ -149,13 +132,13 @@ program
};
})
.toArray()
// filter stores where buCode is 3-letter digit and store name is
// filter foundStores where buCode is 3-letter digit and store name is
// not empty
.filter(function(store) {
return store.buCode && store.buCode.match(/^\d+$/) && store.name;
});

console.log(reporter.show(stores));
console.log(reporter.show(foundStores));
}); // forEach
}); // action
})
Expand Down
71 changes: 71 additions & 0 deletions source/lib/stores.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,75 @@ module.exports = {
}
return null;
},

getLanguageCode: function(countryCode) {
let languageCode = countryCode;
switch(countryCode) {
case 'cz':
languageCode = 'cs';
break;
case 'dk':
languageCode = 'da';
break;
case 'lio':
languageCode = 'en';
break;
case 'jp':
languageCode = 'ja';
break;
case 'kr':
languageCode = 'en';
break;
case 'se':
languageCode = 'sv';
break;
case 'aa':
case 'au':
case 'hk':
case 'my':
case 'sg':
case 'th':
languageCode = 'en';
break;
case 'cn':
case 'tw':
languageCode = 'zh';
break;
case 'ae':
case 'ca':
case 'jo':
case 'kw':
case 'qa':
case 'sa':
case 'us':
languageCode = 'en';
break;
case 'at':
case 'ch':
languageCode = 'de';
break;
}
return languageCode;
},

isSupportedCountryCode: function(code) {
const unsupportedCountryCodes = [
'bg',
'cy',
'do',
'eg',
'es_islas',
'gb',
'gr',
'id',
'ie',
'in',
'is',
'lio',
'ma',
'rs',
'tr',
];
return unsupportedCountryCodes.indexOf(code) === -1;
}
};
15 changes: 15 additions & 0 deletions source/lib/stores.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,19 @@ describe('stores', function() {
expect(stores.findNameByBuCode(387)).to.equal('Graz');
});
});

describe('getLanguageCode', function() {
it('returns the countryCode when it’s not in the mapping', () => {
expect(stores.getLanguageCode('de')).to.equal('de');
});
it('returns "de" for "at"', () => {
expect(stores.getLanguageCode('at')).to.equal('de');
});
it('returns "en" for "lio"', () => {
expect(stores.getLanguageCode('lio')).to.equal('en');
});
it('returns "en" for "kr"', () => {
expect(stores.getLanguageCode('kr')).to.equal('en');
});
});
});

0 comments on commit bb3e59e

Please sign in to comment.