From cf820d7b889c82c6d9dd2d38f7038ba88bb0a5e8 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 5 Sep 2022 13:33:59 -0400 Subject: [PATCH 1/6] Add intended test and reorganize Prior to this commit, the expected error in a test for the `inferSupportStatements` function was satisfied by a similar error from the `getSupportMatrix` function. Modify the test to demonstrate the intended error. Add a second test to preserve coverage for `getSupportMatrix`. In both cases, define the expected error more precisely in order to reduce risk for similar false positives in the future. --- unittest/unit/update-bcd.ts | 48 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/unittest/unit/update-bcd.ts b/unittest/unit/update-bcd.ts index 7c987fa1c..06ed01c8f 100644 --- a/unittest/unit/update-bcd.ts +++ b/unittest/unit/update-bcd.ts @@ -629,6 +629,27 @@ describe('BCD updater', () => { ); }); + it('Invalid results', () => { + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: 87 as any + } + ] + }, + userAgent: + 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36' + }; + + assert.throws(() => { + getSupportMatrix([report], bcd.browsers, overrides); + }, 'result not true/false/null; got 87'); + }); + afterEach(() => { logger.warn.restore(); }); @@ -677,27 +698,14 @@ describe('BCD updater', () => { } it('Invalid results', () => { - assert.throws(() => { - const report: Report = { - __version: '0.3.1', - results: { - 'https://mdn-bcd-collector.appspot.com/tests/': [ - { - name: 'api.AbortController', - exposure: 'Window', - result: 87 as any - } - ] - }, - userAgent: - 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36' - }; - const versionMap = getSupportMatrix([report], bcd.browsers, overrides) - .entries() - .next() - .value[1].entries() - .next().value[1]; + const versionMap = new Map([ + ['82', null], + ['83', 87 as any], + ['84', true], + ['85', true] + ]); + assert.throws(() => { inferSupportStatements(versionMap); }, 'result not true/false/null; got 87'); }); From 380316172f2fa2a940736a7b1d7a26cf84c2a70e Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Tue, 6 Sep 2022 16:38:24 -0400 Subject: [PATCH 2/6] Complete test coverage: `inferSupportStatements` --- unittest/unit/update-bcd.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/unittest/unit/update-bcd.ts b/unittest/unit/update-bcd.ts index 06ed01c8f..804401e72 100644 --- a/unittest/unit/update-bcd.ts +++ b/unittest/unit/update-bcd.ts @@ -709,6 +709,35 @@ describe('BCD updater', () => { inferSupportStatements(versionMap); }, 'result not true/false/null; got 87'); }); + + it('non-contiguous data, support added', () => { + const versionMap = new Map([ + ['82', false], + ['83', null], + ['84', true] + ]); + + assert.deepEqual(inferSupportStatements(versionMap), [ + { + version_added: '82> ≤84' + } + ]); + }); + + it('non-contiguous data, support removed', () => { + const versionMap = new Map([ + ['82', true], + ['83', null], + ['84', false] + ]); + + assert.deepEqual(inferSupportStatements(versionMap), [ + { + version_added: '82', + version_removed: '82> ≤84' + } + ]); + }); }); describe('update', () => { From 034012f8cfb886b1dfa2c494b4fcf3156b32a113 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 5 Sep 2022 14:25:39 -0400 Subject: [PATCH 3/6] Complete test coverage: `update` --- unittest/unit/update-bcd.ts | 267 ++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) diff --git a/unittest/unit/update-bcd.ts b/unittest/unit/update-bcd.ts index 804401e72..990ab2ee7 100644 --- a/unittest/unit/update-bcd.ts +++ b/unittest/unit/update-bcd.ts @@ -11,6 +11,8 @@ import {Report} from '../../types/types.js'; import {assert} from 'chai'; import sinon from 'sinon'; import fs from 'fs-extra'; +import minimatch from 'minimatch'; +import {Browsers} from '@mdn/browser-compat-data/types'; import logger from '../../logger.js'; import { @@ -26,6 +28,12 @@ const overrides = await fs.readJson( new URL('./overrides.test.json', import.meta.url) ); +const clone = (value) => JSON.parse(JSON.stringify(value)); +const chromeAndroid86UaString = + 'Mozilla/5.0 (Linux; Android 10; SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.5112.97 Mobile Safari/537.36'; +const firefox92UaString = + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:92.0) Gecko/20100101 Firefox/92.0'; + const reports: Report[] = [ { __version: '0.3.1', @@ -898,5 +906,264 @@ describe('BCD updater', () => { version_added: null }); }); + + it('skips negative results for unsupported features', () => { + const initialBcd = { + api: { + AbortController: { + __compat: { + support: { + firefox: {version_added: '91', flags: [{}]} + } + } + } + }, + browsers: { + firefox: {name: 'Firefox', releases: {91: {}, 92: {}, 93: {}}} + } as unknown as Browsers + }; + const finalBcd = clone(initialBcd); + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: false + } + ] + }, + userAgent: firefox92UaString + }; + + const sm = getSupportMatrix([report], initialBcd.browsers, []); + update(finalBcd, sm, {}); + assert.deepEqual(finalBcd, initialBcd); + }); + + it('skips complex support scenarios', () => { + const initialBcd: any = { + api: { + AbortController: { + __compat: { + support: { + firefox: [{version_added: '91'}, {version_removed: '92'}] + } + } + } + }, + browsers: { + firefox: {name: 'Firefox', releases: {91: {}, 92: {}, 93: {}}} + } + }; + const finalBcd = clone(initialBcd); + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: false + } + ] + }, + userAgent: firefox92UaString + }; + + const sm = getSupportMatrix([report], initialBcd.browsers, []); + update(finalBcd, sm, {}); + assert.deepEqual(finalBcd, initialBcd); + }); + + it('skips removed features', () => { + const initialBcd: any = { + api: { + AbortController: { + __compat: { + support: { + firefox: {version_removed: '91'} + } + } + } + }, + browsers: { + firefox: {name: 'Firefox', releases: {91: {}, 92: {}, 93: {}}} + } + }; + const finalBcd = clone(initialBcd); + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: true + } + ] + }, + userAgent: firefox92UaString + }; + + const sm = getSupportMatrix([report], initialBcd.browsers, []); + update(finalBcd, sm, {}); + assert.deepEqual(finalBcd, initialBcd); + }); + + it('persists non-default statements', () => { + const initialBcd: any = { + api: { + AbortController: { + __compat: { + support: { + firefox: {version_added: '91', flags: [{}]} + } + } + } + }, + browsers: { + firefox: {name: 'Firefox', releases: {91: {}, 92: {}, 93: {}}} + } + }; + const finalBcd = clone(initialBcd); + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: true + } + ] + }, + userAgent: firefox92UaString + }; + const expectedBcd = clone(initialBcd); + expectedBcd.api.AbortController.__compat.support.firefox = [ + { + version_added: '≤92' + }, + { + flags: [{}], + version_added: '91' + } + ]; + + const sm = getSupportMatrix([report], initialBcd.browsers, []); + update(finalBcd, sm, {}); + assert.deepEqual(finalBcd, expectedBcd); + }); + + it('overrides existing support information in response to negative test results', () => { + const initialBcd: any = { + api: { + AbortController: { + __compat: { + support: { + firefox: {version_added: '91'} + } + } + } + }, + browsers: { + firefox: {name: 'Firefox', releases: {91: {}, 92: {}, 93: {}}} + } + }; + const finalBcd = clone(initialBcd); + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: false + } + ] + }, + userAgent: firefox92UaString + }; + const expectedBcd = clone(initialBcd); + expectedBcd.api.AbortController.__compat.support.firefox.version_added = + false; + + const sm = getSupportMatrix([report], initialBcd.browsers, []); + update(finalBcd, sm, {}); + assert.deepEqual(finalBcd, expectedBcd); + }); + + describe('filtering', () => { + let expectedBcd; + beforeEach(() => { + expectedBcd = clone(bcd); + }); + + it('path', () => { + const filter = { + path: new minimatch.Minimatch('css.properties.*') + }; + expectedBcd.css.properties[ + 'font-family' + ].__compat.support.chrome.version_added = '84'; + expectedBcd.css.properties[ + 'font-style' + ].__compat.support.chrome.version_added = '85'; + update(bcdCopy, supportMatrix, filter); + assert.deepEqual(bcdCopy, expectedBcd); + }); + + it('release', () => { + const filter = {release: '84'}; + expectedBcd.css.properties[ + 'font-family' + ].__compat.support.chrome.version_added = '84'; + update(bcdCopy, supportMatrix, filter); + assert.deepEqual(bcdCopy, expectedBcd); + }); + }); + + it('persists "mirror" when test results align with support data', () => { + const initialBcd = { + api: { + AbortController: { + __compat: { + support: { + chrome: {version_added: '85'}, + chrome_android: 'mirror' + } + } + } + }, + browsers: { + chrome: {name: 'Chrome', releases: {85: {}, 86: {}}}, + chrome_android: { + name: 'Chrome Android', + upstream: 'chrome', + releases: {86: {}} + } + } as unknown as Browsers + }; + const finalBcd = clone(initialBcd); + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: true + } + ] + }, + userAgent: chromeAndroid86UaString + }; + + const sm = getSupportMatrix([report], initialBcd.browsers, []); + update(finalBcd, sm, {}); + assert.deepEqual(finalBcd, initialBcd); + }); }); }); From cb2d7516ccdbd9b6cdf3083a500327fd589db092 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Wed, 7 Sep 2022 18:49:13 -0400 Subject: [PATCH 4/6] fixup! Complete test coverage: `update` --- unittest/unit/update-bcd.ts | 40 +++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/unittest/unit/update-bcd.ts b/unittest/unit/update-bcd.ts index 990ab2ee7..15c264ce8 100644 --- a/unittest/unit/update-bcd.ts +++ b/unittest/unit/update-bcd.ts @@ -938,7 +938,10 @@ describe('BCD updater', () => { }; const sm = getSupportMatrix([report], initialBcd.browsers, []); - update(finalBcd, sm, {}); + + const modified = update(finalBcd, sm, {}); + + assert.equal(modified, false, 'modified'); assert.deepEqual(finalBcd, initialBcd); }); @@ -973,7 +976,10 @@ describe('BCD updater', () => { }; const sm = getSupportMatrix([report], initialBcd.browsers, []); - update(finalBcd, sm, {}); + + const modified = update(finalBcd, sm, {}); + + assert.equal(modified, false, 'modified'); assert.deepEqual(finalBcd, initialBcd); }); @@ -1008,7 +1014,10 @@ describe('BCD updater', () => { }; const sm = getSupportMatrix([report], initialBcd.browsers, []); - update(finalBcd, sm, {}); + + const modified = update(finalBcd, sm, {}); + + assert.equal(modified, false, 'modified'); assert.deepEqual(finalBcd, initialBcd); }); @@ -1053,7 +1062,10 @@ describe('BCD updater', () => { ]; const sm = getSupportMatrix([report], initialBcd.browsers, []); - update(finalBcd, sm, {}); + + const modified = update(finalBcd, sm, {}); + + assert(modified, 'modified'); assert.deepEqual(finalBcd, expectedBcd); }); @@ -1091,7 +1103,10 @@ describe('BCD updater', () => { false; const sm = getSupportMatrix([report], initialBcd.browsers, []); - update(finalBcd, sm, {}); + + const modified = update(finalBcd, sm, {}); + + assert(modified, 'modified'); assert.deepEqual(finalBcd, expectedBcd); }); @@ -1111,7 +1126,10 @@ describe('BCD updater', () => { expectedBcd.css.properties[ 'font-style' ].__compat.support.chrome.version_added = '85'; - update(bcdCopy, supportMatrix, filter); + + const modified = update(bcdCopy, supportMatrix, filter); + + assert(modified, 'modified'); assert.deepEqual(bcdCopy, expectedBcd); }); @@ -1120,7 +1138,10 @@ describe('BCD updater', () => { expectedBcd.css.properties[ 'font-family' ].__compat.support.chrome.version_added = '84'; - update(bcdCopy, supportMatrix, filter); + + const modified = update(bcdCopy, supportMatrix, filter); + + assert(modified, 'modified'); assert.deepEqual(bcdCopy, expectedBcd); }); }); @@ -1162,7 +1183,10 @@ describe('BCD updater', () => { }; const sm = getSupportMatrix([report], initialBcd.browsers, []); - update(finalBcd, sm, {}); + + const modified = update(finalBcd, sm, {}); + + assert(modified, 'modified'); assert.deepEqual(finalBcd, initialBcd); }); }); From 71873a83223a7605917af7d566f553d661dd21b5 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Thu, 8 Sep 2022 23:03:16 -0400 Subject: [PATCH 5/6] fixup! Complete test coverage: `update` --- unittest/unit/update-bcd.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittest/unit/update-bcd.ts b/unittest/unit/update-bcd.ts index 15c264ce8..6caab3aed 100644 --- a/unittest/unit/update-bcd.ts +++ b/unittest/unit/update-bcd.ts @@ -1152,7 +1152,7 @@ describe('BCD updater', () => { AbortController: { __compat: { support: { - chrome: {version_added: '85'}, + chrome: {version_added: '86'}, chrome_android: 'mirror' } } @@ -1186,7 +1186,7 @@ describe('BCD updater', () => { const modified = update(finalBcd, sm, {}); - assert(modified, 'modified'); + assert.equal(modified, false, 'modified'); assert.deepEqual(finalBcd, initialBcd); }); }); From c6d5e7225f9f5752831418ee12bfd246ebc62ee3 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Mon, 19 Sep 2022 14:22:34 -0400 Subject: [PATCH 6/6] Incorporate review feedback --- unittest/unit/update-bcd.ts | 54 +++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/unittest/unit/update-bcd.ts b/unittest/unit/update-bcd.ts index 37839c8cc..c6c12a769 100644 --- a/unittest/unit/update-bcd.ts +++ b/unittest/unit/update-bcd.ts @@ -1036,7 +1036,7 @@ describe('BCD updater', () => { assert.deepEqual(finalBcd, initialBcd); }); - it('skips negative results for unsupported features', () => { + it('retains flag data for unsupported features', () => { const initialBcd = { api: { AbortController: { @@ -1074,13 +1074,16 @@ describe('BCD updater', () => { assert.deepEqual(finalBcd, initialBcd); }); - it('skips complex support scenarios', () => { + it('no update given partial confirmation of complex support scenario', () => { const initialBcd: any = { api: { AbortController: { __compat: { support: { - firefox: [{version_added: '91'}, {version_removed: '92'}] + firefox: [ + {version_added: '92'}, + {version_added: '91', partial_implementation: true, notes: ''} + ] } } } @@ -1112,19 +1115,60 @@ describe('BCD updater', () => { assert.deepEqual(finalBcd, initialBcd); }); + it('skips complex support scenarios', () => { + const initialBcd: any = { + api: { + AbortController: { + __compat: { + support: { + firefox: [ + {version_added: '94'}, + {version_added: '93', partial_implementation: true, notes: ''} + ] + } + } + } + }, + browsers: { + firefox: {name: 'Firefox', releases: {91: {}, 92: {}, 93: {}, 94: {}}} + } + }; + const finalBcd = clone(initialBcd); + const report: Report = { + __version: '0.3.1', + results: { + 'https://mdn-bcd-collector.appspot.com/tests/': [ + { + name: 'api.AbortController', + exposure: 'Window', + result: false + } + ] + }, + userAgent: firefox92UaString + }; + + const sm = getSupportMatrix([report], initialBcd.browsers, []); + + const modified = update(finalBcd, sm, {}); + + assert.equal(modified, false, 'modified'); + assert.deepEqual(finalBcd, initialBcd); + }); + it('skips removed features', () => { const initialBcd: any = { api: { AbortController: { __compat: { support: { - firefox: {version_removed: '91'} + firefox: {version_added: '90', version_removed: '91'} } } } }, browsers: { - firefox: {name: 'Firefox', releases: {91: {}, 92: {}, 93: {}}} + firefox: {name: 'Firefox', releases: {90: {}, 91: {}, 92: {}}} } }; const finalBcd = clone(initialBcd);