chore(coverage): fix coverage for events (#4787)

We used to track API Coverage for public events, but this was regressed in the refactoring that
introduced `//lib/Events.js`.

This patch:
- Brings back API Coverage for events
- Combines all coverage-generated tests into a single one. This way
we can generate less data for flakiness dashboard.
This commit is contained in:
Andrey Lushnikov 2019-08-01 16:09:50 -07:00 committed by GitHub
parent 7ee9af49db
commit 5c7c45f0aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 14 deletions

View File

@ -96,7 +96,7 @@ if (process.env.BROWSER === 'firefox') {
testRunner, testRunner,
}); });
if (process.env.COVERAGE) if (process.env.COVERAGE)
utils.recordAPICoverage(testRunner, require('../lib/api'), CHROMIUM_NO_COVERAGE); utils.recordAPICoverage(testRunner, require('../lib/api'), require('../lib/Events').Events, CHROMIUM_NO_COVERAGE);
}); });
} }

View File

@ -21,10 +21,11 @@ const PROJECT_ROOT = fs.existsSync(path.join(__dirname, '..', 'package.json')) ?
/** /**
* @param {Map<string, boolean>} apiCoverage * @param {Map<string, boolean>} apiCoverage
* @param {Object} events
* @param {string} className * @param {string} className
* @param {!Object} classType * @param {!Object} classType
*/ */
function traceAPICoverage(apiCoverage, className, classType) { function traceAPICoverage(apiCoverage, events, className, classType) {
className = className.substring(0, 1).toLowerCase() + className.substring(1); className = className.substring(0, 1).toLowerCase() + className.substring(1);
for (const methodName of Reflect.ownKeys(classType.prototype)) { for (const methodName of Reflect.ownKeys(classType.prototype)) {
const method = Reflect.get(classType.prototype, methodName); const method = Reflect.get(classType.prototype, methodName);
@ -37,12 +38,14 @@ function traceAPICoverage(apiCoverage, className, classType) {
}); });
} }
if (classType.Events) { if (events[classType.name]) {
for (const event of Object.values(classType.Events)) for (const event of Object.values(events[classType.name])) {
if (typeof event !== 'symbol')
apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, false); apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, false);
}
const method = Reflect.get(classType.prototype, 'emit'); const method = Reflect.get(classType.prototype, 'emit');
Reflect.set(classType.prototype, 'emit', function(event, ...args) { Reflect.set(classType.prototype, 'emit', function(event, ...args) {
if (this.listenerCount(event)) if (typeof event !== 'symbol' && this.listenerCount(event))
apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, true); apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, true);
return method.call(this, event, ...args); return method.call(this, event, ...args);
}); });
@ -50,17 +53,20 @@ function traceAPICoverage(apiCoverage, className, classType) {
} }
const utils = module.exports = { const utils = module.exports = {
recordAPICoverage: function(testRunner, api, disabled) { recordAPICoverage: function(testRunner, api, events, disabled) {
const coverage = new Map(); const coverage = new Map();
for (const [className, classType] of Object.entries(api)) for (const [className, classType] of Object.entries(api))
traceAPICoverage(coverage, className, classType); traceAPICoverage(coverage, events, className, classType);
testRunner.describe('COVERAGE', () => { testRunner.describe('COVERAGE', () => {
testRunner.it('should call all API methods', () => {
const missingMethods = [];
for (const method of coverage.keys()) { for (const method of coverage.keys()) {
(disabled.has(method) ? testRunner.xit : testRunner.it)(`public api '${method}' should be called`, async({page, server}) => { if (!coverage.get(method) && !disabled.has(method))
if (!coverage.get(method)) missingMethods.push(method);
throw new Error('NOT CALLED!');
});
} }
if (missingMethods.length)
throw new Error('Certain API Methods are not called: ' + missingMethods.join(', '));
});
}); });
}, },