Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto add in region to usage stats query with the specified region in the parameter #444

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ https://browsersl.ist/api/browsers?q=defaults&region=alt-ww
// https://browsersl.ist/api/browsers?q=>0.3%&region=alt-as

{
"query": ">0.3%",
"query": ">0.3% in alt-as", // Append `in region` to audience coverage queries
"region": "alt-as",
"coverage": 92.64,
"versions": {
Expand Down
14 changes: 11 additions & 3 deletions server/lib/get-browsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@ import { readFileSync } from 'node:fs'
import browserslist from 'browserslist'
import { URL } from 'node:url'

import getQueryWithRegion from './get-query-with-region.js'

let { version: bv } = importJSON('../node_modules/browserslist/package.json')
let { version: cv } = importJSON('../node_modules/caniuse-lite/package.json')

export const QUERY_DEFAULTS = 'defaults'
export const REGION_GLOBAL = 'Global'
export const REGION_GLOBAL = 'alt-ww'

export default async function getBrowsers(query, region) {
let queryWithRegion = ''
let browsersByQuery = []

try {
browsersByQuery = browserslist(query)
queryWithRegion =
region === REGION_GLOBAL ? query : getQueryWithRegion(query, region)
browsersByQuery = browserslist(queryWithRegion)
} catch (error) {
throw error.browserslist
? error
Expand Down Expand Up @@ -69,10 +74,13 @@ export default async function getBrowsers(query, region) {
})
.sort((a, b) => b.coverage - a.coverage)

// NOTE: in browserslist
// browserslist.coverage(browserslist('>5%'), 'FR') not equals
// browserslist.coverage(browserslist('>5% in FR'))
let coverage = roundNumber(browserslist.coverage(browsersByQuery, region))

return {
query,
query: queryWithRegion,
region,
coverage,
versions: {
Expand Down
34 changes: 34 additions & 0 deletions server/lib/get-query-with-region.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import browserslist from 'browserslist'

export default function getQueryWithRegion(query, region) {
let queryParsed = browserslist.parse(query)
let queryParsedModified = queryParsed.map(expression => {
if (expression.type === 'popularity') {
return {
compose: expression.compose,
place: region,
popularity: expression.popularity,
query: [expression.query, 'in', region].join(' '),
sign: expression.sign,
type: 'popularity_in_place'
}
}
return expression
})

return getQueryFromQueryParsed(queryParsedModified)
}

function getQueryFromQueryParsed(browserslistParsed) {
return browserslistParsed.reduce(
(updatedQuery, { query: currentQuery, compose }, i) => {
// The first parsed query always contains `or`
if (i === 0) {
return currentQuery
} else {
return [updatedQuery, compose, currentQuery].join(' ')
}
},
''
)
}
23 changes: 16 additions & 7 deletions server/test/browsers.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import test from 'node:test'
import { equal, notEqual, ok, match } from 'node:assert'
import { equal, deepEqual, notEqual, ok, match, notDeepEqual } from 'node:assert'

import getBrowsers from '../lib/get-browsers.js'

test('Throws error for wrong browserslist `query`', async () => {
let error
try {
await getBrowsers('wrong', 'Global')
await getBrowsers('wrong', 'alt-ww')
} catch (e) {
error = e
}
Expand All @@ -15,7 +15,7 @@ test('Throws error for wrong browserslist `query`', async () => {
})

test('Returns multiple browser names and versions by `>1%` query', async () => {
let data = await getBrowsers('>1%', 'Global')
let data = await getBrowsers('>1%', 'alt-ww')
let browsersNames = data.browsers
let browsersVersions = Object.keys(browsersNames[0])

Expand All @@ -35,17 +35,19 @@ test('Throws error for wrong Can I Use `region`', async () => {
})

test('Returns Node.js versions without coverage`', async () => {
let data = await getBrowsers('Node > 0', 'Global')
let data = await getBrowsers('Node > 0', 'alt-ww')

equal(data.browsers[0].name, 'Node')
equal(data.browsers[0].coverage, null)
})

test('Сoverage of all browsers should differ in different regions', async () => {
let continentData = await getBrowsers('>1%', 'Global')
let countryData = await getBrowsers('>1%', 'IT')
test('Should show different coverage statistics for another regions', async () => {
let query = '>0.1% and supports es6-module'
let continentData = await getBrowsers(query, 'alt-as')
let countryData = await getBrowsers(query, 'IT')

notEqual(continentData.coverage, countryData.coverage)
notDeepEqual(continentData.browsers, countryData.browsers)
})

test('Сoverage for browser should differ in different regions', async () => {
Expand All @@ -57,3 +59,10 @@ test('Сoverage for browser should differ in different regions', async () => {

notEqual(continentBrowser.coverage, countryBrowser.coverage)
})

test('Should transform query with type `popularity` to `popularity_in_place`', async () => {
deepEqual(
await getBrowsers('>0.1% and <10%, dead', 'FR'),
await getBrowsers('>0.1% in FR and <10% in FR, dead', 'FR')
)
})
4 changes: 2 additions & 2 deletions server/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ test('Integration tests', async t => {
)

await t.test(
'responses `Global` region for `/browsers` route without `region` param',
'responses `alt-ww` region for `/browsers` route without `region` param',
async () => {
let url = new URL(`api/browsers`, base)
let response = await fetch(url)
let data = await response.json()
equal(data.region, 'Global')
equal(data.region, 'alt-ww')
}
)

Expand Down