cypress 8.7.0 → 9.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/lib/cli.js CHANGED
@@ -3,8 +3,6 @@
3
3
  // @ts-check
4
4
  const _ = require('lodash');
5
5
 
6
- const R = require('ramda');
7
-
8
6
  const commander = require('commander');
9
7
 
10
8
  const {
@@ -238,11 +236,18 @@ const castCypressRunOptions = opts => {
238
236
  // only properties that have type "string | false" in our TS definition
239
237
  // require special handling, because CLI parsing takes care of purely
240
238
  // boolean arguments
241
- const result = R.evolve({
242
- port: coerceAnyStringToInt,
243
- configFile: coerceFalseOrString
244
- })(opts);
245
- return result;
239
+ const castOpts = { ...opts
240
+ };
241
+
242
+ if (_.has(opts, 'port')) {
243
+ castOpts.port = coerceAnyStringToInt(opts.port);
244
+ }
245
+
246
+ if (_.has(opts, 'configFile')) {
247
+ castOpts.configFile = coerceFalseOrString(opts.configFile);
248
+ }
249
+
250
+ return castOpts;
246
251
  };
247
252
 
248
253
  module.exports = {
package/lib/errors.js CHANGED
@@ -7,10 +7,6 @@ const {
7
7
  stripIndents
8
8
  } = require('common-tags');
9
9
 
10
- const {
11
- merge
12
- } = require('ramda');
13
-
14
10
  const la = require('lazy-ass');
15
11
 
16
12
  const is = require('check-more-types');
@@ -45,6 +41,12 @@ const invalidRunProjectPath = {
45
41
  ${chalk.blue(runDocumentationUrl)}
46
42
  `
47
43
  };
44
+ const invalidOS = {
45
+ description: 'The Cypress App could not be installed. Your machine does not meet the operating system requirements.',
46
+ solution: stripIndent`
47
+
48
+ ${chalk.blue('https://on.cypress.io/guides/getting-started/installing-cypress#system-requirements')}`
49
+ };
48
50
  const failedDownload = {
49
51
  description: 'The Cypress App could not be downloaded.',
50
52
  solution: stripIndent`
@@ -233,9 +235,9 @@ const CYPRESS_RUN_BINARY = {
233
235
 
234
236
  function addPlatformInformation(info) {
235
237
  return util.getPlatformInfo().then(platform => {
236
- return merge(info, {
238
+ return { ...info,
237
239
  platform
238
- });
240
+ };
239
241
  });
240
242
  }
241
243
  /**
@@ -374,6 +376,7 @@ module.exports = {
374
376
  missingApp,
375
377
  notInstalledCI,
376
378
  missingDependency,
379
+ invalidOS,
377
380
  invalidSmokeTestDisplayError,
378
381
  versionMismatch,
379
382
  binaryNotExecutable,
package/lib/exec/info.js CHANGED
@@ -13,9 +13,7 @@ const chalk = require('chalk');
13
13
 
14
14
  const prettyBytes = require('pretty-bytes');
15
15
 
16
- const _ = require('lodash');
17
-
18
- const R = require('ramda'); // color for numbers and show values
16
+ const _ = require('lodash'); // color for numbers and show values
19
17
 
20
18
 
21
19
  const g = chalk.green; // color for paths
@@ -30,14 +28,21 @@ methods.findProxyEnvironmentVariables = () => {
30
28
  return _.pick(process.env, ['HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY']);
31
29
  };
32
30
 
33
- const maskSensitiveVariables = R.evolve({
34
- CYPRESS_RECORD_KEY: R.always('<redacted>')
35
- });
31
+ const maskSensitiveVariables = obj => {
32
+ const masked = { ...obj
33
+ };
34
+
35
+ if (masked.CYPRESS_RECORD_KEY) {
36
+ masked.CYPRESS_RECORD_KEY = '<redacted>';
37
+ }
38
+
39
+ return masked;
40
+ };
36
41
 
37
42
  methods.findCypressEnvironmentVariables = () => {
38
43
  const isCyVariable = (val, key) => key.startsWith('CYPRESS_');
39
44
 
40
- return R.pickBy(isCyVariable)(process.env);
45
+ return _.pickBy(process.env, isCyVariable);
41
46
  };
42
47
 
43
48
  const formatCypressVariables = () => {
package/lib/exec/spawn.js CHANGED
@@ -86,7 +86,7 @@ module.exports = {
86
86
  args = [args];
87
87
  }
88
88
 
89
- args = [...args, '--cwd', process.cwd()];
89
+ args = [...args, '--cwd', process.cwd(), '--userNodePath', process.execPath, '--userNodeVersion', process.versions.node];
90
90
 
91
91
  _.defaults(options, {
92
92
  dev: false,
package/lib/logger.js CHANGED
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
2
 
3
- const R = require('ramda');
4
-
5
3
  const chalk = require('chalk');
6
4
 
7
5
  let logs = [];
@@ -36,7 +34,10 @@ const always = (...messages) => {
36
34
 
37
35
  const logLines = text => {
38
36
  const lines = text.split('\n');
39
- R.forEach(log, lines);
37
+
38
+ for (const line of lines) {
39
+ log(line);
40
+ }
40
41
  };
41
42
 
42
43
  const print = () => {
@@ -41,19 +41,6 @@ const getProxyForUrlWithNpmConfig = url => {
41
41
  return getProxyForUrl(url) || process.env.npm_config_https_proxy || process.env.npm_config_proxy || null;
42
42
  };
43
43
 
44
- const getRealOsArch = () => {
45
- // os.arch() returns the arch for which this node was compiled
46
- // we want the operating system's arch instead: x64 or x86
47
- const osArch = arch();
48
-
49
- if (osArch === 'x86') {
50
- // match process.platform output
51
- return 'ia32';
52
- }
53
-
54
- return osArch;
55
- };
56
-
57
44
  const getBaseUrl = () => {
58
45
  if (util.getEnv('CYPRESS_DOWNLOAD_MIRROR')) {
59
46
  let baseUrl = util.getEnv('CYPRESS_DOWNLOAD_MIRROR');
@@ -91,8 +78,7 @@ const getCA = () => {
91
78
  const prepend = urlPath => {
92
79
  const endpoint = url.resolve(getBaseUrl(), urlPath);
93
80
  const platform = os.platform();
94
- const arch = getRealOsArch();
95
- return `${endpoint}?platform=${platform}&arch=${arch}`;
81
+ return `${endpoint}?platform=${platform}&arch=${arch()}`;
96
82
  };
97
83
 
98
84
  const getUrl = version => {
@@ -64,6 +64,10 @@ const getNpmArgv = () => {
64
64
  const getVersionSpecifier = (startDir = path.resolve(__dirname, '../..')) => {
65
65
  const argv = getNpmArgv();
66
66
 
67
+ if ((process.env.npm_package_resolved || '').endsWith('cypress.tgz')) {
68
+ return process.env.npm_package_resolved;
69
+ }
70
+
67
71
  if (argv) {
68
72
  const tgz = _.find(argv, t => t.endsWith('cypress.tgz'));
69
73
 
@@ -104,7 +108,7 @@ const getVersionSpecifier = (startDir = path.resolve(__dirname, '../..')) => {
104
108
  });
105
109
  };
106
110
 
107
- const betaNpmUrlRe = /^\/beta\/npm\/(?<version>[0-9.]+)\/(?<artifactSlug>[^/]+)\/cypress\.tgz$/; // convert a prerelease NPM package .tgz URL to the corresponding binary .zip URL
111
+ const betaNpmUrlRe = /^\/beta\/npm\/(?<version>[0-9.]+)\/(?<artifactSlug>.+?)\/cypress\.tgz$/; // convert a prerelease NPM package .tgz URL to the corresponding binary .zip URL
108
112
 
109
113
  const getBinaryUrlFromPrereleaseNpmUrl = npmUrl => {
110
114
  let parsed;
@@ -226,6 +230,12 @@ const downloadAndUnzip = ({
226
230
  return Promise.resolve(tasks.run());
227
231
  };
228
232
 
233
+ const validateOS = () => {
234
+ return util.getPlatformInfo().then(platformInfo => {
235
+ return platformInfo.match(/(darwin|linux|win32)-x64/);
236
+ });
237
+ };
238
+
229
239
  const start = (options = {}) => {
230
240
  debug('installing with options %j', options);
231
241
 
@@ -269,7 +279,13 @@ const start = (options = {}) => {
269
279
  const installDir = state.getVersionDir(pkgVersion);
270
280
  const cacheDir = state.getCacheDir();
271
281
  const binaryDir = state.getBinaryDir(pkgVersion);
272
- return fs.ensureDirAsync(cacheDir).catch({
282
+ return validateOS().then(isValid => {
283
+ if (!isValid) {
284
+ return throwFormErrorText(errors.invalidOS)();
285
+ }
286
+ }).then(() => {
287
+ return fs.ensureDirAsync(cacheDir);
288
+ }).catch({
273
289
  code: 'EACCES'
274
290
  }, err => {
275
291
  return throwFormErrorText(errors.invalidCacheDirectory)(stripIndent`
@@ -8,8 +8,6 @@ const path = require('path');
8
8
 
9
9
  const untildify = require('untildify');
10
10
 
11
- const R = require('ramda');
12
-
13
11
  const debug = require('debug')('cypress:cli');
14
12
 
15
13
  const fs = require('../fs');
@@ -203,9 +201,12 @@ const getBinaryPkgAsync = binaryDir => {
203
201
  });
204
202
  };
205
203
 
206
- const getBinaryPkgVersion = R.propOr(null, 'version');
207
- const getBinaryElectronVersion = R.propOr(null, 'electronVersion');
208
- const getBinaryElectronNodeVersion = R.propOr(null, 'electronNodeVersion');
204
+ const getBinaryPkgVersion = o => _.get(o, 'version', null);
205
+
206
+ const getBinaryElectronVersion = o => _.get(o, 'electronVersion', null);
207
+
208
+ const getBinaryElectronNodeVersion = o => _.get(o, 'electronNodeVersion', null);
209
+
209
210
  module.exports = {
210
211
  getPathToExecutable,
211
212
  getPlatformExecutable,
@@ -37,7 +37,7 @@ const xvfb = require('../exec/xvfb');
37
37
 
38
38
  const state = require('./state');
39
39
 
40
- const VERIFY_TEST_RUNNER_TIMEOUT_MS = 30000;
40
+ const VERIFY_TEST_RUNNER_TIMEOUT_MS = process.env.CYPRESS_VERIFY_TIMEOUT || 30000;
41
41
 
42
42
  const checkExecutable = binaryDir => {
43
43
  const executable = state.getPathToExecutable(binaryDir);
package/lib/util.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const _ = require('lodash');
4
4
 
5
- const R = require('ramda');
5
+ const arch = require('arch');
6
6
 
7
7
  const os = require('os');
8
8
 
@@ -133,9 +133,8 @@ const logBrokenGtkDisplayWarning = () => {
133
133
  };
134
134
 
135
135
  function stdoutLineMatches(expectedLine, stdout) {
136
- const lines = stdout.split('\n').map(R.trim);
137
- const lineMatches = R.equals(expectedLine);
138
- return lines.some(lineMatches);
136
+ const lines = stdout.split('\n').map(val => val.trim());
137
+ return lines.some(line => line === expectedLine);
139
138
  }
140
139
  /**
141
140
  * Confirms if given value is a valid CYPRESS_INTERNAL_ENV value. Undefined values
@@ -220,11 +219,16 @@ const parseOpts = opts => {
220
219
  // remove double quotes from certain options
221
220
 
222
221
 
223
- const removeQuotes = {
224
- group: dequote,
225
- ciBuildId: dequote
222
+ const cleanOpts = { ...opts
226
223
  };
227
- const cleanOpts = R.evolve(removeQuotes, opts);
224
+ const toDequote = ['group', 'ciBuildId'];
225
+
226
+ for (const prop of toDequote) {
227
+ if (_.has(opts, prop)) {
228
+ cleanOpts[prop] = dequote(opts[prop]);
229
+ }
230
+ }
231
+
228
232
  debug('parsed cli options %o', cleanOpts);
229
233
  return cleanOpts;
230
234
  };
@@ -404,8 +408,14 @@ const util = {
404
408
 
405
409
  getPlatformInfo() {
406
410
  return util.getOsVersionAsync().then(version => {
411
+ let osArch = arch();
412
+
413
+ if (osArch === 'x86') {
414
+ osArch = 'ia32';
415
+ }
416
+
407
417
  return stripIndent`
408
- Platform: ${os.platform()} (${version})
418
+ Platform: ${os.platform()}-${osArch} (${version})
409
419
  Cypress Version: ${util.pkgVersion()}
410
420
  `;
411
421
  });
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "cypress",
3
- "version": "8.7.0",
3
+ "version": "9.2.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "postinstall": "node index.js --exec install",
7
7
  "size": "t=\"$(npm pack .)\"; wc -c \"${t}\"; tar tvf \"${t}\"; rm \"${t}\";"
8
8
  },
9
9
  "dependencies": {
10
- "@cypress/request": "^2.88.6",
10
+ "@cypress/request": "^2.88.10",
11
11
  "@cypress/xvfb": "^1.2.4",
12
12
  "@types/node": "^14.14.31",
13
13
  "@types/sinonjs__fake-timers": "^6.0.2",
14
14
  "@types/sizzle": "^2.3.2",
15
15
  "arch": "^2.2.0",
16
16
  "blob-util": "^2.0.2",
17
- "bluebird": "^3.7.2",
17
+ "bluebird": "3.7.2",
18
18
  "cachedir": "^2.3.0",
19
19
  "chalk": "^4.1.0",
20
20
  "check-more-types": "^2.24.0",
@@ -42,7 +42,6 @@
42
42
  "ospath": "^1.2.2",
43
43
  "pretty-bytes": "^5.6.0",
44
44
  "proxy-from-env": "1.0.0",
45
- "ramda": "~0.27.1",
46
45
  "request-progress": "^3.0.0",
47
46
  "supports-color": "^8.1.1",
48
47
  "tmp": "~0.2.1",
@@ -7,13 +7,38 @@ declare namespace Cypress {
7
7
  type HttpMethod = string
8
8
  type RequestBody = string | object
9
9
  type ViewportOrientation = 'portrait' | 'landscape'
10
- type PrevSubject = 'optional' | 'element' | 'document' | 'window'
10
+ type PrevSubject = keyof PrevSubjectMap
11
11
  type TestingType = 'e2e' | 'component'
12
12
  type PluginConfig = (on: PluginEvents, config: PluginConfigOptions) => void | ConfigOptions | Promise<ConfigOptions>
13
13
 
14
+ interface PrevSubjectMap<O = unknown> {
15
+ optional: O
16
+ element: JQuery
17
+ document: Document
18
+ window: Window
19
+ }
20
+
14
21
  interface CommandOptions {
15
22
  prevSubject: boolean | PrevSubject | PrevSubject[]
16
23
  }
24
+ interface CommandFn<T extends keyof ChainableMethods> {
25
+ (this: Mocha.Context, ...args: Parameters<ChainableMethods[T]>): ReturnType<ChainableMethods[T]> | void
26
+ }
27
+ interface CommandFnWithSubject<T extends keyof ChainableMethods, S> {
28
+ (this: Mocha.Context, prevSubject: S, ...args: Parameters<ChainableMethods[T]>): ReturnType<ChainableMethods[T]> | void
29
+ }
30
+ interface CommandOriginalFn<T extends keyof ChainableMethods> extends CallableFunction {
31
+ (...args: Parameters<ChainableMethods[T]>): ReturnType<ChainableMethods[T]>
32
+ }
33
+ interface CommandOriginalFnWithSubject<T extends keyof ChainableMethods, S> extends CallableFunction {
34
+ (prevSubject: S, ...args: Parameters<ChainableMethods[T]>): ReturnType<ChainableMethods[T]>
35
+ }
36
+ interface CommandFnWithOriginalFn<T extends keyof Chainable> {
37
+ (this: Mocha.Context, originalFn: CommandOriginalFn<T>, ...args: Parameters<ChainableMethods[T]>): ReturnType<ChainableMethods[T]> | void
38
+ }
39
+ interface CommandFnWithOriginalFnAndSubject<T extends keyof Chainable, S> {
40
+ (this: Mocha.Context, originalFn: CommandOriginalFnWithSubject<T, S>, prevSubject: S, ...args: Parameters<ChainableMethods[T]>): ReturnType<ChainableMethods[T]> | void
41
+ }
17
42
  interface ObjectLike {
18
43
  [key: string]: any
19
44
  }
@@ -280,7 +305,7 @@ declare namespace Cypress {
280
305
  * Currently executing test runnable instance.
281
306
  */
282
307
  currentTest: {
283
- title: string,
308
+ title: string
284
309
  titlePath: string[]
285
310
  }
286
311
 
@@ -294,6 +319,11 @@ declare namespace Cypress {
294
319
  */
295
320
  LocalStorage: LocalStorage
296
321
 
322
+ /**
323
+ * Internal class for session management.
324
+ */
325
+ session: Session
326
+
297
327
  /**
298
328
  * Current testing type, determined by the Test Runner chosen to run.
299
329
  */
@@ -328,7 +358,7 @@ declare namespace Cypress {
328
358
  // 60000
329
359
  ```
330
360
  */
331
- config<K extends keyof ConfigOptions>(key: K): ResolvedConfigOptions[K]
361
+ config<K extends keyof Config>(key: K): Config[K]
332
362
  /**
333
363
  * Sets one configuration value.
334
364
  * @see https://on.cypress.io/config
@@ -337,7 +367,7 @@ declare namespace Cypress {
337
367
  Cypress.config('viewportWidth', 800)
338
368
  ```
339
369
  */
340
- config<K extends keyof ConfigOptions>(key: K, value: ResolvedConfigOptions[K]): void
370
+ config<K extends keyof TestConfigOverrides>(key: K, value: TestConfigOverrides[K]): void
341
371
  /**
342
372
  * Sets multiple configuration values at once.
343
373
  * @see https://on.cypress.io/config
@@ -420,9 +450,16 @@ declare namespace Cypress {
420
450
  * @see https://on.cypress.io/api/commands
421
451
  */
422
452
  Commands: {
423
- add(name: string, fn: (...args: any[]) => CanReturnChainable): void
424
- add(name: string, options: CommandOptions, fn: (...args: any[]) => CanReturnChainable): void
425
- overwrite(name: string, fn: (...args: any[]) => CanReturnChainable): void
453
+ add<T extends keyof Chainable>(name: T, fn: CommandFn<T>): void
454
+ add<T extends keyof Chainable>(name: T, options: CommandOptions & {prevSubject: false}, fn: CommandFn<T>): void
455
+ add<T extends keyof Chainable, S extends PrevSubject>(
456
+ name: T, options: CommandOptions & { prevSubject: true | S | ['optional'] }, fn: CommandFnWithSubject<T, PrevSubjectMap[S]>,
457
+ ): void
458
+ add<T extends keyof Chainable, S extends PrevSubject>(
459
+ name: T, options: CommandOptions & { prevSubject: S[] }, fn: CommandFnWithSubject<T, PrevSubjectMap<void>[S]>,
460
+ ): void
461
+ overwrite<T extends keyof Chainable>(name: T, fn: CommandFnWithOriginalFn<T>): void
462
+ overwrite<T extends keyof Chainable, S extends PrevSubject>(name: T, fn: CommandFnWithOriginalFnAndSubject<T, PrevSubjectMap[S]>): void
426
463
  }
427
464
 
428
465
  /**
@@ -2209,12 +2246,9 @@ declare namespace Cypress {
2209
2246
  * @see https://on.cypress.io/writefile
2210
2247
  ```
2211
2248
  cy.writeFile('path/to/message.txt', 'Hello World')
2212
- .then((text) => {
2213
- expect(text).to.equal('Hello World') // true
2214
- })
2215
2249
  ```
2216
2250
  */
2217
- writeFile<C extends FileContents>(filePath: string, contents: C, encoding: Encodings): Chainable<C>
2251
+ writeFile(filePath: string, contents: FileContents, encoding: Encodings): Chainable<null>
2218
2252
  /**
2219
2253
  * Write to a file with the specified encoding and contents.
2220
2254
  *
@@ -2223,12 +2257,10 @@ declare namespace Cypress {
2223
2257
  cy.writeFile('path/to/ascii.txt', 'Hello World', {
2224
2258
  flag: 'a+',
2225
2259
  encoding: 'ascii'
2226
- }).then((text) => {
2227
- expect(text).to.equal('Hello World') // true
2228
2260
  })
2229
2261
  ```
2230
2262
  */
2231
- writeFile<C extends FileContents>(filePath: string, contents: C, options?: Partial<WriteFileOptions>): Chainable<C>
2263
+ writeFile(filePath: string, contents: FileContents, options?: Partial<WriteFileOptions & Timeoutable>): Chainable<null>
2232
2264
  /**
2233
2265
  * Write to a file with the specified encoding and contents.
2234
2266
  *
@@ -2238,12 +2270,10 @@ declare namespace Cypress {
2238
2270
  ```
2239
2271
  cy.writeFile('path/to/ascii.txt', 'Hello World', 'utf8', {
2240
2272
  flag: 'a+',
2241
- }).then((text) => {
2242
- expect(text).to.equal('Hello World') // true
2243
2273
  })
2244
2274
  ```
2245
2275
  */
2246
- writeFile<C extends FileContents>(filePath: string, contents: C, encoding: Encodings, options?: Partial<WriteFileOptions>): Chainable<C>
2276
+ writeFile(filePath: string, contents: FileContents, encoding: Encodings, options?: Partial<WriteFileOptions & Timeoutable>): Chainable<null>
2247
2277
 
2248
2278
  /**
2249
2279
  * jQuery library bound to the AUT
@@ -2255,6 +2285,12 @@ declare namespace Cypress {
2255
2285
  $$<TElement extends Element = HTMLElement>(selector: JQuery.Selector, context?: Element | Document | JQuery): JQuery<TElement>
2256
2286
  }
2257
2287
 
2288
+ type ChainableMethods<Subject = any> = {
2289
+ [P in keyof Chainable<Subject>]: Chainable<Subject>[P] extends ((...args: any[]) => any)
2290
+ ? Chainable<Subject>[P]
2291
+ : never
2292
+ }
2293
+
2258
2294
  interface SinonSpyAgent<A extends sinon.SinonSpy> {
2259
2295
  log(shouldOutput?: boolean): Omit<A, 'withArgs'> & Agent<A>
2260
2296
 
@@ -2886,7 +2922,7 @@ declare namespace Cypress {
2886
2922
  xhrUrl: string
2887
2923
  }
2888
2924
 
2889
- interface TestConfigOverrides extends Partial<Pick<ConfigOptions, 'animationDistanceThreshold' | 'baseUrl' | 'defaultCommandTimeout' | 'env' | 'execTimeout' | 'includeShadowDom' | 'requestTimeout' | 'responseTimeout' | 'retries' | 'scrollBehavior' | 'taskTimeout' | 'viewportHeight' | 'viewportWidth' | 'waitForAnimations'>> {
2925
+ interface TestConfigOverrides extends Partial<Pick<ConfigOptions, 'animationDistanceThreshold' | 'baseUrl' | 'blockHosts' | 'defaultCommandTimeout' | 'env' | 'execTimeout' | 'includeShadowDom' | 'numTestsKeptInMemory' | 'pageLoadTimeout' | 'redirectionLimit' | 'requestTimeout' | 'responseTimeout' | 'retries' | 'screenshotOnRunFailure' | 'slowTestThreshold' | 'scrollBehavior' | 'taskTimeout' | 'viewportHeight' | 'viewportWidth' | 'waitForAnimations'>> {
2890
2926
  browser?: IsBrowserMatcher | IsBrowserMatcher[]
2891
2927
  keystrokeDelay?: number
2892
2928
  }
@@ -3086,6 +3122,11 @@ declare namespace Cypress {
3086
3122
  onAnyAbort(route: RouteOptions, proxy: any): void
3087
3123
  }
3088
3124
 
3125
+ interface Session {
3126
+ // Clear all saved sessions and re-run the current spec file.
3127
+ clearAllSavedSessions: () => Promise<void>
3128
+ }
3129
+
3089
3130
  type SameSiteStatus = 'no_restriction' | 'strict' | 'lax'
3090
3131
 
3091
3132
  interface SetCookieOptions extends Loggable, Timeoutable {
@@ -5677,7 +5718,7 @@ declare namespace Cypress {
5677
5718
  xhr: XMLHttpRequest
5678
5719
  }
5679
5720
 
5680
- type Encodings = 'ascii' | 'base64' | 'binary' | 'hex' | 'latin1' | 'utf8' | 'utf-8' | 'ucs2' | 'ucs-2' | 'utf16le' | 'utf-16le'
5721
+ type Encodings = 'ascii' | 'base64' | 'binary' | 'hex' | 'latin1' | 'utf8' | 'utf-8' | 'ucs2' | 'ucs-2' | 'utf16le' | 'utf-16le' | null
5681
5722
  type PositionType = 'topLeft' | 'top' | 'topRight' | 'left' | 'center' | 'right' | 'bottomLeft' | 'bottom' | 'bottomRight'
5682
5723
  type ViewportPreset = 'macbook-16' | 'macbook-15' | 'macbook-13' | 'macbook-11' | 'ipad-2' | 'ipad-mini' | 'iphone-xr' | 'iphone-x' | 'iphone-6+' | 'iphone-se2' | 'iphone-8' | 'iphone-7' | 'iphone-6' | 'iphone-5' | 'iphone-4' | 'iphone-3' | 'samsung-s10' | 'samsung-note9'
5683
5724
  interface Offset {