How to use filterJSDocumentation method in Puppeteer

Best JavaScript code snippet using puppeteer

Run Puppeteer automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

index.js

Source: index.js Github

copy
1/**
2 * Copyright 2017 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17const jsBuilder = require('./JSBuilder');
18const mdBuilder = require('./MDBuilder');
19const Documentation = require('./Documentation');
20const Message = require('../Message');
21
22const EXCLUDE_CLASSES = new Set([
23  'CSSCoverage',
24  'Connection',
25  'EmulationManager',
26  'FrameManager',
27  'JSCoverage',
28  'Helper',
29  'Launcher',
30  'Multimap',
31  'NavigatorWatcher',
32  'NetworkManager',
33  'Pipe',
34  'TaskQueue',
35  'WaitTask',
36]);
37
38const EXCLUDE_METHODS = new Set([
39  'Browser.create',
40  'Headers.fromPayload',
41  'Page.create',
42  'JSHandle.toString',
43]);
44
45/**
46 * @param {!Page} page
47 * @param {!Array<!Source>} mdSources
48 * @param {!Array<!Source>} jsSources
49 * @return {!Promise<!Array<!Message>>}
50 */
51module.exports = async function lint(page, mdSources, jsSources) {
52  const mdResult = await mdBuilder(page, mdSources);
53  const jsResult = await jsBuilder(jsSources);
54  const jsDocumentation = filterJSDocumentation(jsResult.documentation);
55  const mdDocumentation = mdResult.documentation;
56
57  const jsErrors = jsResult.errors;
58  jsErrors.push(...checkDuplicates(jsDocumentation));
59
60  const mdErrors = mdResult.errors;
61  mdErrors.push(...compareDocumentations(mdDocumentation, jsDocumentation));
62  mdErrors.push(...checkDuplicates(mdDocumentation));
63  mdErrors.push(...checkSorting(mdDocumentation));
64
65  // Push all errors with proper prefixes
66  const errors = jsErrors.map(error => '[JavaScript] ' + error);
67  errors.push(...mdErrors.map(error => '[MarkDown] ' + error));
68  return errors.map(error => Message.error(error));
69};
70
71/**
72 * @param {!Documentation} doc
73 * @return {!Array<string>}
74 */
75function checkSorting(doc) {
76  const errors = [];
77  for (const cls of doc.classesArray) {
78    const members = cls.membersArray;
79
80    // Events should go first.
81    let eventIndex = 0;
82    for (; eventIndex < members.length && members[eventIndex].type === 'event'; ++eventIndex);
83    for (; eventIndex < members.length && members[eventIndex].type !== 'event'; ++eventIndex);
84    if (eventIndex < members.length)
85      errors.push(`Events should go first. Event '${members[eventIndex].name}' in class ${cls.name} breaks order`);
86
87    // Constructor should be right after events and before all other members.
88    const constructorIndex = members.findIndex(member => member.type === 'method' && member.name === 'constructor');
89    if (constructorIndex > 0 && members[constructorIndex - 1].type !== 'event')
90      errors.push(`Constructor of ${cls.name} should go before other methods`);
91
92    // Events should be sorted alphabetically.
93    for (let i = 0; i < members.length - 1; ++i) {
94      const member1 = cls.membersArray[i];
95      const member2 = cls.membersArray[i + 1];
96      if (member1.type !== 'event' || member2.type !== 'event')
97        continue;
98      if (member1.name > member2.name)
99        errors.push(`Event '${member1.name}' in class ${cls.name} breaks alphabetic ordering of events`);
100    }
101
102    // All other members should be sorted alphabetically.
103    for (let i = 0; i < members.length - 1; ++i) {
104      const member1 = cls.membersArray[i];
105      const member2 = cls.membersArray[i + 1];
106      if (member1.type === 'event' || member2.type === 'event')
107        continue;
108      if (member1.type === 'method' && member1.name === 'constructor')
109        continue;
110      if (member1.name > member2.name) {
111        let memberName1 = `${cls.name}.${member1.name}`;
112        if (member1.type === 'method')
113          memberName1 += '()';
114        let memberName2 = `${cls.name}.${member2.name}`;
115        if (member2.type === 'method')
116          memberName2 += '()';
117        errors.push(`Bad alphabetic ordering of ${cls.name} members: ${memberName1} should go after ${memberName2}`);
118      }
119    }
120  }
121  return errors;
122}
123
124/**
125 * @param {!Documentation} jsDocumentation
126 * @return {!Documentation}
127 */
128function filterJSDocumentation(jsDocumentation) {
129  // Filter classes and methods.
130  const classes = [];
131  for (const cls of jsDocumentation.classesArray) {
132    if (EXCLUDE_CLASSES.has(cls.name))
133      continue;
134    const members = cls.membersArray.filter(member => {
135      if (member.name.startsWith('_'))
136        return false;
137      // Exclude all constructors by default.
138      if (member.name === 'constructor' && member.type === 'method')
139        return false;
140      return !EXCLUDE_METHODS.has(`${cls.name}.${member.name}`);
141    });
142    classes.push(new Documentation.Class(cls.name, members));
143  }
144  return new Documentation(classes);
145}
146
147/**
148 * @param {!Documentation} doc
149 * @return {!Array<string>}
150 */
151function checkDuplicates(doc) {
152  const errors = [];
153  const classes = new Set();
154  // Report duplicates.
155  for (const cls of doc.classesArray) {
156    if (classes.has(cls.name))
157      errors.push(`Duplicate declaration of class ${cls.name}`);
158    classes.add(cls.name);
159    const members = new Set();
160    for (const member of cls.membersArray) {
161      if (members.has(member.type + ' ' + member.name))
162        errors.push(`Duplicate declaration of ${member.type} ${cls.name}.${member.name}()`);
163      members.add(member.type + ' ' + member.name);
164      const args = new Set();
165      for (const arg of member.argsArray) {
166        if (args.has(arg.name))
167          errors.push(`Duplicate declaration of argument ${cls.name}.${member.name} "${arg.name}"`);
168        args.add(arg.name);
169      }
170    }
171  }
172  return errors;
173}
174
175/**
176 * @param {!Documentation} actual
177 * @param {!Documentation} expected
178 * @return {!Array<string>}
179 */
180function compareDocumentations(actual, expected) {
181  const errors = [];
182
183  const actualClasses = Array.from(actual.classes.keys()).sort();
184  const expectedClasses = Array.from(expected.classes.keys()).sort();
185  const classesDiff = diff(actualClasses, expectedClasses);
186  for (const className of classesDiff.extra)
187    errors.push(`Non-existing class found: ${className}`);
188  for (const className of classesDiff.missing)
189    errors.push(`Class not found: ${className}`);
190
191  for (const className of classesDiff.equal) {
192    const actualClass = actual.classes.get(className);
193    const expectedClass = expected.classes.get(className);
194    const actualMethods = Array.from(actualClass.methods.keys()).sort();
195    const expectedMethods = Array.from(expectedClass.methods.keys()).sort();
196    const methodDiff = diff(actualMethods, expectedMethods);
197    for (const methodName of methodDiff.extra)
198      errors.push(`Non-existing method found: ${className}.${methodName}()`);
199    for (const methodName of methodDiff.missing)
200      errors.push(`Method not found: ${className}.${methodName}()`);
201
202    for (const methodName of methodDiff.equal) {
203      const actualMethod = actualClass.methods.get(methodName);
204      const expectedMethod = expectedClass.methods.get(methodName);
205      if (actualMethod.hasReturn !== expectedMethod.hasReturn) {
206        if (actualMethod.hasReturn)
207          errors.push(`Method ${className}.${methodName} has unneeded description of return type`);
208        else if (!expectedMethod.async)
209          errors.push(`Method ${className}.${methodName} is missing return type description`);
210        else
211          errors.push(`Async method ${className}.${methodName} should describe return type Promise`);
212      }
213      const actualArgs = Array.from(actualMethod.args.keys());
214      const expectedArgs = Array.from(expectedMethod.args.keys());
215      const argDiff = diff(actualArgs, expectedArgs);
216      if (argDiff.extra.length || argDiff.missing.length) {
217        const text = [`Method ${className}.${methodName}() fails to describe its parameters:`];
218        for (const arg of argDiff.missing)
219          text.push(`- Argument not found: ${arg}`);
220        for (const arg of argDiff.extra)
221          text.push(`- Non-existing argument found: ${arg}`);
222        errors.push(text.join('\n'));
223      }
224    }
225    const actualProperties = Array.from(actualClass.properties.keys()).sort();
226    const expectedProperties = Array.from(expectedClass.properties.keys()).sort();
227    const propertyDiff = diff(actualProperties, expectedProperties);
228    for (const propertyName of propertyDiff.extra)
229      errors.push(`Non-existing property found: ${className}.${propertyName}`);
230    for (const propertyName of propertyDiff.missing)
231      errors.push(`Property not found: ${className}.${propertyName}`);
232
233    const actualEvents = Array.from(actualClass.events.keys()).sort();
234    const expectedEvents = Array.from(expectedClass.events.keys()).sort();
235    const eventsDiff = diff(actualEvents, expectedEvents);
236    for (const eventName of eventsDiff.extra)
237      errors.push(`Non-existing event found in class ${className}: '${eventName}'`);
238    for (const eventName of eventsDiff.missing)
239      errors.push(`Event not found in class ${className}: '${eventName}'`);
240  }
241  return errors;
242}
243
244/**
245 * @param {!Array<string>} actual
246 * @param {!Array<string>} expected
247 * @return {{extra: !Array<string>, missing: !Array<string>, equal: !Array<string>}}
248 */
249function diff(actual, expected) {
250  const N = actual.length;
251  const M = expected.length;
252  if (N === 0 && M === 0)
253    return { extra: [], missing: [], equal: []};
254  if (N === 0)
255    return {extra: [], missing: expected.slice(), equal: []};
256  if (M === 0)
257    return {extra: actual.slice(), missing: [], equal: []};
258  const d = new Array(N);
259  const bt = new Array(N);
260  for (let i = 0; i < N; ++i) {
261    d[i] = new Array(M);
262    bt[i] = new Array(M);
263    for (let j = 0; j < M; ++j) {
264      const top = val(i - 1, j);
265      const left = val(i, j - 1);
266      if (top > left) {
267        d[i][j] = top;
268        bt[i][j] = 'extra';
269      } else {
270        d[i][j] = left;
271        bt[i][j] = 'missing';
272      }
273      const diag = val(i - 1, j - 1);
274      if (actual[i] === expected[j] && d[i][j] < diag + 1) {
275        d[i][j] = diag + 1;
276        bt[i][j] = 'eq';
277      }
278    }
279  }
280  // Backtrack results.
281  let i = N - 1;
282  let j = M - 1;
283  const missing = [];
284  const extra = [];
285  const equal = [];
286  while (i >= 0 && j >= 0) {
287    switch (bt[i][j]) {
288      case 'extra':
289        extra.push(actual[i]);
290        i -= 1;
291        break;
292      case 'missing':
293        missing.push(expected[j]);
294        j -= 1;
295        break;
296      case 'eq':
297        equal.push(actual[i]);
298        i -= 1;
299        j -= 1;
300        break;
301    }
302  }
303  while (i >= 0)
304    extra.push(actual[i--]);
305  while (j >= 0)
306    missing.push(expected[j--]);
307  extra.reverse();
308  missing.reverse();
309  equal.reverse();
310  return {extra, missing, equal};
311
312  function val(i, j) {
313    return i < 0 || j < 0 ? 0 : d[i][j];
314  }
315}
316
317
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Puppeteer on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)