forked from adamlaska/browser-compat-data
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest-versions.js
More file actions
180 lines (163 loc) · 6.1 KB
/
test-versions.js
File metadata and controls
180 lines (163 loc) · 6.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
'use strict';
const compareVersions = require('compare-versions');
const chalk = require('chalk');
const { Logger } = require('./utils.js');
/**
* @typedef {import('../../types').Identifier} Identifier
* @typedef {import('../../types').SimpleSupportStatement} SimpleSupportStatement
* @typedef {import('../../types').SupportBlock} SupportBlock
* @typedef {import('../../types').VersionValue} VersionValue
*/
const browsers = require('../..').browsers;
/** @type {Object<string, string[]>} */
const validBrowserVersions = {};
/** @type {Object<string, string[]>} */
const VERSION_RANGE_BROWSERS = {
edge: ['≤18', '≤79'],
ie: ['≤6', '≤11'],
opera: ['≤12.1', '≤15'],
opera_android: ['≤12.1', '≤14'],
safari: ['≤4'],
safari_ios: ['≤3'],
webview_android: ['≤37'],
};
for (const browser of Object.keys(browsers)) {
validBrowserVersions[browser] = Object.keys(browsers[browser].releases);
if (VERSION_RANGE_BROWSERS[browser]) {
validBrowserVersions[browser].push(...VERSION_RANGE_BROWSERS[browser]);
}
if (browsers[browser].preview_name) {
validBrowserVersions[browser].push('preview');
}
}
/**
* @param {string} browserIdentifier
* @param {VersionValue} version
*/
function isValidVersion(browserIdentifier, version) {
if (typeof version === 'string') {
return validBrowserVersions[browserIdentifier].includes(version);
} else {
return true;
}
}
/**
* @param {SimpleSupportStatement} statement
* @returns {boolean|null}
*/
function addedBeforeRemoved(statement) {
// In order to ensure that the versions could be displayed without the "≤"
// markers and still make sense, compare the versions without them. This
// means that combinations like version_added: "≤37" + version_removed: "37"
// are not allowed, even though this can be technically correct.
const added = statement.version_added.replace('≤', '');
const removed = statement.version_removed.replace('≤', '');
if (!compareVersions.validate(added) || !compareVersions.validate(removed)) {
return null;
}
if (added === 'preview' && removed === 'preview') {
return false;
}
if (added === 'preview' && removed !== 'preview') {
return false;
}
if (added !== 'preview' && removed === 'preview') {
return true;
}
return compareVersions.compare(added, removed, '<');
}
/**
* @param {SupportBlock} supportData
* @param {string} relPath
* @param {Logger} logger
*/
function checkVersions(supportData, relPath, logger) {
const browsersToCheck = Object.keys(supportData);
for (const browser of browsersToCheck) {
if (validBrowserVersions[browser]) {
/** @type {SimpleSupportStatement[]} */
const supportStatements = [];
if (Array.isArray(supportData[browser])) {
Array.prototype.push.apply(supportStatements, supportData[browser]);
} else {
supportStatements.push(supportData[browser]);
}
const validBrowserVersionsString = `true, false, null, ${validBrowserVersions[
browser
].join(', ')}`;
const validBrowserVersionsTruthy = `true, ${validBrowserVersions[
browser
].join(', ')}`;
for (const statement of supportStatements) {
if (!isValidVersion(browser, statement.version_added)) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_added: "${statement.version_added}"} is {bold NOT} a valid version number for {bold ${browser}}\n Valid {bold ${browser}} versions are: ${validBrowserVersionsString}}`,
);
}
if (!isValidVersion(browser, statement.version_removed)) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_removed: "${statement.version_removed}"} is {bold NOT} a valid version number for {bold ${browser}}\n Valid {bold ${browser}} versions are: ${validBrowserVersionsString}}`,
);
}
if ('version_added' in statement && 'version_removed' in statement) {
if (statement.version_added === statement.version_removed) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_added: "${statement.version_added}"} must not be the same as {bold version_removed} for {bold ${browser}}}`,
);
}
if (
typeof statement.version_added !== 'string' &&
statement.version_added !== true
) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_added: "${statement.version_added}"} is {bold NOT} a valid version number for {bold ${browser}} when {bold version_removed} is present\n Valid {bold ${browser}} versions are: ${validBrowserVersionsTruthy}}`,
);
} else if (
typeof statement.version_added === 'string' &&
typeof statement.version_removed === 'string'
) {
if (addedBeforeRemoved(statement) === false) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_removed: "${statement.version_removed}"} must be greater than {bold version_added: "${statement.version_added}"}}`,
);
}
}
}
if ('flags' in statement) {
if (browsers[browser].accepts_flags === false) {
logger.error(
chalk`{red → {bold ${relPath}} - This browser ({bold ${browser}}) does not support flags, so support cannot be behind a flag for this feature.}`,
);
}
}
}
}
}
}
/**
* @param {string} filename
*/
function testVersions(filename) {
/** @type {Identifier} */
const data = require(filename);
const logger = new Logger('Versions');
/**
* @param {Identifier} data
* @param {string} [relPath]
*/
function findSupport(data, relPath) {
for (const prop in data) {
if (prop === '__compat' && data[prop].support) {
checkVersions(data[prop].support, relPath, logger);
}
const sub = data[prop];
if (typeof sub === 'object') {
findSupport(sub, relPath ? `${relPath}.${prop}` : `${prop}`);
}
}
}
findSupport(data);
logger.emit();
return logger.hasErrors();
}
module.exports = testVersions;