Browse Source

Implement tests

Use custom JSDOM apart from Jest's built-in JSDOM instance because
we need to test different kinds of documents.

We will need to address problems with types, e.g. for `RadioNodeList`
because the runner could not find its declaration (for both our custom
and built-in JSDOM instances).
master
TheoryOfNekomata 3 years ago
parent
commit
90d921ff68
15 changed files with 498 additions and 46 deletions
  1. +3
    -0
      jest.config.js
  2. +2
    -0
      package.json
  3. +89
    -0
      src/index.test.ts
  4. +34
    -17
      src/index.ts
  5. +0
    -0
      test/blah.test.ts
  6. +11
    -0
      test/fixtures/index.ts
  7. +10
    -0
      test/fixtures/templates/blank.html
  8. +84
    -0
      test/fixtures/templates/default.html
  9. +19
    -0
      test/fixtures/templates/single-disabled-input.html
  10. +17
    -0
      test/fixtures/templates/single-input-with-double-input-submitters.html
  11. +17
    -0
      test/fixtures/templates/single-input-with-double-submitters.html
  12. +16
    -0
      test/fixtures/templates/single-input.html
  13. +19
    -0
      test/fixtures/templates/single-readonly-input.html
  14. +1
    -16
      tsconfig.json
  15. +176
    -13
      yarn.lock

+ 3
- 0
jest.config.js View File

@@ -0,0 +1,3 @@
module.exports = {
testEnvironment: 'node',
};

+ 2
- 0
package.json View File

@@ -46,7 +46,9 @@
],
"devDependencies": {
"@size-limit/preset-small-lib": "^4.10.2",
"@types/jsdom": "^16.2.10",
"husky": "^6.0.0",
"jsdom": "^16.5.3",
"size-limit": "^4.10.2",
"tsdx": "^0.14.1",
"tslib": "^2.2.0",


+ 89
- 0
src/index.test.ts View File

@@ -0,0 +1,89 @@
import * as fixtures from '../test/fixtures'
import getFormValues from '.'

describe('blank template', () => {
let window: fixtures.Window
beforeEach(async () => {
window = await fixtures.loadTemplate('blank')
})
it('should have blank form value', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const values = getFormValues(form)
expect(values).toEqual({})
})
})

describe('single input template', () => {
let window: fixtures.Window
beforeEach(async () => {
window = await fixtures.loadTemplate('single-input')
})
it('should have a single form value', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const values = getFormValues(form)
expect(values).toEqual({ hello: 'Hi' })
})
})

describe('single disabled input template', () => {
let window: fixtures.Window
beforeEach(async () => {
window = await fixtures.loadTemplate('single-disabled-input')
})
it('should have blank form value', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const values = getFormValues(form)
expect(values).toEqual({})
})
})

describe('single readonly input template', () => {
let window: fixtures.Window
beforeEach(async () => {
window = await fixtures.loadTemplate('single-readonly-input')
})
it('should have a single form value', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const values = getFormValues(form)
expect(values).toEqual({ hello: 'Hi' })
})
})

describe('single input with double submitters template', () => {
let window: fixtures.Window
beforeEach(async () => {
window = await fixtures.loadTemplate('single-input-with-double-submitters')
})
it('should have a single form value', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const values = getFormValues(form)
expect(values).toEqual({ hello: 'Hi' })
})

it('should include the submitter\'s value when provided', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const [submitter] = Array.from(window.document.getElementsByTagName('button'))
const values = getFormValues(form, submitter)
expect(values).toEqual({ hello: 'Hi', [submitter.name]: submitter.value })
})
})

describe('single input with double input submitters template', () => {
let window: fixtures.Window
beforeEach(async () => {
window = await fixtures.loadTemplate('single-input-with-double-input-submitters')
})

it('should have a single form value', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const values = getFormValues(form)
expect(values).toEqual({ hello: 'Hi' })
})

it('should include the submitter\'s value when provided', () => {
const [form] = Array.from(window.document.getElementsByTagName('form'))
const [,submitter] = Array.from(window.document.getElementsByTagName('input')).filter(i => i.type === 'submit')
const values = getFormValues(form, submitter)
expect(values).toEqual({ hello: 'Hi', [submitter.name]: submitter.value })
})
})

+ 34
- 17
src/index.ts View File

@@ -1,3 +1,8 @@
const RadioNodeList = global.RadioNodeList || class RadioNodeList {
name: string = ''
disabled: boolean = false
}

type HTMLFieldElement
= HTMLInputElement
| HTMLButtonElement
@@ -5,7 +10,7 @@ type HTMLFieldElement
| HTMLTextAreaElement

type FieldNode
= RadioNodeList
= typeof RadioNodeList
| HTMLFieldElement

type HTMLSubmitterElement
@@ -17,19 +22,22 @@ const isFormFieldElement = (el: FieldNode) => {
return true
}
const htmlEl = el as HTMLElement
const tagName = htmlEl.tagName.toLowerCase()
if (['SELECT', 'TEXTAREA', 'BUTTON'].includes(tagName)) {
const tagName = htmlEl.tagName
if (['SELECT', 'TEXTAREA'].includes(tagName)) {
return true
}
if (tagName !== 'INPUT') {
return false
}
const inputEl = htmlEl as HTMLInputElement
const type = inputEl.type.toLowerCase()
const type = inputEl.type
const checkedValue = inputEl.getAttribute('value')
if (type === 'checkbox' && checkedValue !== null) {
return inputEl.checked
}
if (type === 'submit' || type === 'reset') {
return false
}
return Boolean(inputEl.name)
}

@@ -95,17 +103,17 @@ const getRadioNodeListResolvedValue = (radioNodeList: RadioNodeList, submitter?:
*/
const getFieldValue = (el: FieldNode, submitter?: HTMLSubmitterElement) => {
if ((el as unknown) instanceof RadioNodeList) {
return getRadioNodeListResolvedValue(el as RadioNodeList, submitter)
return getRadioNodeListResolvedValue(el as unknown as RadioNodeList, submitter)
}

const fieldEl = el as HTMLFieldElement
const tagName = fieldEl.tagName
const type = fieldEl.type.toLowerCase()
const type = fieldEl.type
if (tagName === 'SELECT' && fieldEl.value === '') {
return null
}

if (tagName === 'INPUT' && type === 'CHECKBOX') {
if (tagName === 'INPUT' && type === 'checkbox') {
const inputFieldEl = fieldEl as HTMLInputElement
const checkedValue = inputFieldEl.getAttribute('value')
if (checkedValue !== null) {
@@ -122,38 +130,47 @@ const getFieldValue = (el: FieldNode, submitter?: HTMLSubmitterElement) => {

/**
* Returns only named form field elements.
* @param key - The key from the `form.elements` object.
* @param el - The element
*/
const isValidFormField = (key: string, el: FieldNode) => {
const isValidFormField = (el: FieldNode) => {
return (
isNaN(Number(key))
'name' in el
&& typeof el['name'] === 'string'
&& el['name'].length > 0
&& !('disabled' in el && Boolean(el['disabled']))
&& isFormFieldElement(el)
)
}

// TODO handle disabled/readonly fields
/**
* Gets the values of all the fields within the form through accessing the DOM nodes.
* @param form - The form element.
* @param submitter - The element which triggered the form's submit event.
*/
const getFormValues = (form: HTMLFormElement, submitter?: HTMLSubmitterElement) => {
if (!form) {
throw new TypeError('Invalid form element.')
}
const formElements = form.elements as unknown as Record<string | number, FieldNode>
const allFormFieldElements = Object.entries<FieldNode>(formElements)
const formFieldElements = allFormFieldElements.filter(([key, el]) => isValidFormField(key, el))
return formFieldElements.reduce(
(theFormValues, [name, el]) => {
const formFieldElements = allFormFieldElements.filter(([, el]) => isValidFormField(el))
const fieldValues = formFieldElements.reduce(
(theFormValues, [,el]) => {
const fieldValue = getFieldValue(el, submitter)
if (fieldValue === null) {
return theFormValues
}
return {
[name]: fieldValue,
[el['name'] as string]: fieldValue,
}
},
{}
)
if (Boolean(submitter as unknown)) {
return {
...fieldValues,
[(submitter as HTMLSubmitterElement).name]: (submitter as HTMLSubmitterElement).value,
}
}
return fieldValues
}

export default getFormValues

+ 0
- 0
test/blah.test.ts View File


+ 11
- 0
test/fixtures/index.ts View File

@@ -0,0 +1,11 @@
import fs from 'fs'
import path from 'path'
import {DOMWindow, JSDOM} from 'jsdom'

export type Window = DOMWindow

export const loadTemplate = async (templateName: string): Promise<Window> => {
const templatePath = path.join('test', 'fixtures', 'templates', `${templateName}.html`)
const templateRaw = await fs.promises.readFile(templatePath)
return new JSDOM(templateRaw.toString('utf-8')).window
}

+ 10
- 0
test/fixtures/templates/blank.html View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en-PH">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form></form>
</body>
</html>

+ 84
- 0
test/fixtures/templates/default.html View File

@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en-PH">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<article>
<h2></h2>
<form>
<div>
<input type="text" placeholder="First Name" name="first_name" />
</div>
<div>
<input type="text" placeholder="Middle Name" name="middle_name" />
</div>
<div>
<input type="text" placeholder="Last Name" name="last_name" />
</div>
<fieldset>
<legend>Gender</legend>
<div>
<label>
<input type="radio" name="gender" value="m" />
Male
</label>
<label>
<input type="radio" name="gender" value="f" />
Female
</label>
</div>
</fieldset>
<div>
<select name="civil_status">
<option value="">Select Civil Status</option>
<option value="single">Single</option>
<option value="married">Married</option>
<option value="divorced">Divorced</option>
<option value="separated">Separated</option>
</select>
</div>
<div>
<label>
<input type="checkbox" name="new_registration" />
New Registration
</label>
</div>
<div>
<label>
<input type="checkbox" value="filipino" name="nationality" />
Filipino
</label>
</div>
<fieldset>
<legend>
Default Dependents
</legend>
<div>
<label>
<input type="radio" value="James" name="dependent" />
James
</label>
<label>
<input type="radio" value="Jun" name="dependent" />
Jun
</label>
</div>
</fieldset>
<div>
<button type="button" class="dependents">
Add Dependents
</button>
</div>
<div>
<textarea name="notes" placeholder="Notes"></textarea>
</div>
<div>
<button name="submit" value="Hello" type="submit">Hello</button>
<button name="submit" value="Hi" type="submit">Hi</button>
</div>
</form>
</article>
</body>
</html>

+ 19
- 0
test/fixtures/templates/single-disabled-input.html View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en-PH">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<label>
<span>Hello</span>
<input
type="text" name="hello" value="Hi"
disabled
/>
</label>
<button type="submit">Submit</button>
</form>
</body>
</html>

+ 17
- 0
test/fixtures/templates/single-input-with-double-input-submitters.html View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en-PH">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<label>
<span>Hello</span>
<input type="text" name="hello" value="Hi" />
</label>
<input name="action" value="Foo" type="submit" />
<input name="action" value="Bar" type="submit" />
</form>
</body>
</html>

+ 17
- 0
test/fixtures/templates/single-input-with-double-submitters.html View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en-PH">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<label>
<span>Hello</span>
<input type="text" name="hello" value="Hi" />
</label>
<button name="action" value="Foo" type="submit">Foo</button>
<button name="action" value="Bar" type="submit">Bar</button>
</form>
</body>
</html>

+ 16
- 0
test/fixtures/templates/single-input.html View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en-PH">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<label>
<span>Hello</span>
<input type="text" name="hello" value="Hi" />
</label>
<button type="submit">Submit</button>
</form>
</body>
</html>

+ 19
- 0
test/fixtures/templates/single-readonly-input.html View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en-PH">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<label>
<span>Hello</span>
<input
type="text" name="hello" value="Hi"
readonly
/>
</label>
<button type="submit">Submit</button>
</form>
</body>
</html>

+ 1
- 16
tsconfig.json View File

@@ -1,35 +1,20 @@
{
// see https://www.typescriptlang.org/tsconfig to better understand tsconfigs
"include": ["src", "types"],
"compilerOptions": {
"module": "esnext",
"lib": ["dom", "esnext"],
"importHelpers": true,
// output .d.ts declaration files for consumers
"declaration": true,
// output .js.map sourcemap files for consumers
"sourceMap": true,
// match output dir to input dir. e.g. dist/index instead of dist/src/index
"rootDir": "./src",
// stricter type-checking for stronger correctness. Recommended by TS
"strict": true,
// linter checks for common issues
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
// noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative
"noUnusedLocals": true,
"noUnusedParameters": true,
// use Node's module resolution algorithm, instead of the legacy TS one
"moduleResolution": "node",
// transpile JSX to React.createElement
"jsx": "react",
// interop between ESM and CJS modules. Recommended by TS
"esModuleInterop": true,
// significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS
"skipLibCheck": true,
// error out if import and file system have a casing mismatch. Recommended by TS
"forceConsistentCasingInFileNames": true,
// `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc`
"noEmit": true,
"noEmit": true
}
}

+ 176
- 13
yarn.lock View File

@@ -1305,6 +1305,15 @@
jest-diff "^25.2.1"
pretty-format "^25.2.1"
"@types/jsdom@^16.2.10":
version "16.2.10"
resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.10.tgz#c05ea94682d035943ae2453b79d56178496b6653"
integrity sha512-q3aIjp3ehhVSXSbvNyuireAfvU2umRiZ2aLumyeZewCnoNaokrRDdTu5IvaeE9pzNtWHXrUnM9lb22Vl3W08EA==
dependencies:
"@types/node" "*"
"@types/parse5" "*"
"@types/tough-cookie" "*"
"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.6":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
@@ -1330,6 +1339,11 @@
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
"@types/parse5@*":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.0.tgz#38590dc2c3cf5717154064e3ee9b6947ee21b299"
integrity sha512-oPwPSj4a1wu9rsXTEGIJz91ISU725t0BmSnUhb57sI+M8XEmvUop84lzuiYdq0Y5M6xLY8DBPg0C2xEQKLyvBA==
"@types/prettier@^1.19.0":
version "1.19.1"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f"
@@ -1352,6 +1366,11 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
"@types/tough-cookie@*":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d"
integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==
"@types/yargs-parser@*":
version "20.2.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9"
@@ -1562,7 +1581,7 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
abab@^2.0.0:
abab@^2.0.0, abab@^2.0.3, abab@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
@@ -1575,6 +1594,14 @@ acorn-globals@^4.3.2:
acorn "^6.0.1"
acorn-walk "^6.0.1"
acorn-globals@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==
dependencies:
acorn "^7.1.1"
acorn-walk "^7.1.1"
acorn-jsx@^5.2.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
@@ -1585,6 +1612,11 @@ acorn-walk@^6.0.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
acorn-walk@^7.1.1:
version "7.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
acorn-walk@^8.0.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.1.0.tgz#d3c6a9faf00987a5e2b9bdb506c2aa76cd707f83"
@@ -1600,7 +1632,7 @@ acorn@^7.1.0, acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.0.4:
acorn@^8.0.4, acorn@^8.1.0:
version "8.2.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.2.2.tgz#c4574e4fea298d6e6ed4b85ab844b06dd59f26d6"
integrity sha512-VrMS8kxT0e7J1EX0p6rI/E0FbfOVcvBpbIqHThFv+f8YrZIlMfVotYcXKVPmTvPW8sW5miJzfUFrrvthUZg8VQ==
@@ -2913,7 +2945,7 @@ csso@^4.0.2:
dependencies:
css-tree "^1.1.2"
cssom@^0.4.1:
cssom@^0.4.1, cssom@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
@@ -2923,7 +2955,7 @@ cssom@~0.3.6:
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
cssstyle@^2.0.0:
cssstyle@^2.0.0, cssstyle@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
@@ -2956,6 +2988,15 @@ data-urls@^1.1.0:
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
data-urls@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==
dependencies:
abab "^2.0.3"
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -2975,6 +3016,11 @@ decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
decimal.js@^10.2.1:
version "10.2.1"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3"
integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
@@ -3117,6 +3163,13 @@ domexception@^1.0.1:
dependencies:
webidl-conversions "^4.0.2"
domexception@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==
dependencies:
webidl-conversions "^5.0.0"
domutils@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
@@ -3298,6 +3351,18 @@ escodegen@^1.11.1:
optionalDependencies:
source-map "~0.6.1"
escodegen@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd"
integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==
dependencies:
esprima "^4.0.1"
estraverse "^5.2.0"
esutils "^2.0.2"
optionator "^0.8.1"
optionalDependencies:
source-map "~0.6.1"
eslint-config-prettier@^6.0.0:
version "6.15.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9"
@@ -4182,6 +4247,13 @@ html-encoding-sniffer@^1.0.2:
dependencies:
whatwg-encoding "^1.0.1"
html-encoding-sniffer@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==
dependencies:
whatwg-encoding "^1.0.5"
html-escaper@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
@@ -4576,6 +4648,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
is-potential-custom-element-name@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
is-reference@^1.1.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
@@ -5153,6 +5230,38 @@ jsdom@^15.2.1:
ws "^7.0.0"
xml-name-validator "^3.0.0"
jsdom@^16.5.3:
version "16.5.3"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.5.3.tgz#13a755b3950eb938b4482c407238ddf16f0d2136"
integrity sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==
dependencies:
abab "^2.0.5"
acorn "^8.1.0"
acorn-globals "^6.0.0"
cssom "^0.4.4"
cssstyle "^2.3.0"
data-urls "^2.0.0"
decimal.js "^10.2.1"
domexception "^2.0.1"
escodegen "^2.0.0"
html-encoding-sniffer "^2.0.1"
is-potential-custom-element-name "^1.0.0"
nwsapi "^2.2.0"
parse5 "6.0.1"
request "^2.88.2"
request-promise-native "^1.0.9"
saxes "^5.0.1"
symbol-tree "^3.2.4"
tough-cookie "^4.0.0"
w3c-hr-time "^1.0.2"
w3c-xmlserializer "^2.0.0"
webidl-conversions "^6.1.0"
whatwg-encoding "^1.0.5"
whatwg-mimetype "^2.3.0"
whatwg-url "^8.5.0"
ws "^7.4.4"
xml-name-validator "^3.0.0"
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -5394,7 +5503,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5:
lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -6158,6 +6267,11 @@ parse5@5.1.0:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==
parse5@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
pascal-case@^3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
@@ -6697,7 +6811,7 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
psl@^1.1.28:
psl@^1.1.28, psl@^1.1.33:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
@@ -6981,7 +7095,7 @@ request-promise-core@1.1.4:
dependencies:
lodash "^4.17.19"
request-promise-native@^1.0.7:
request-promise-native@^1.0.7, request-promise-native@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
@@ -6990,7 +7104,7 @@ request-promise-native@^1.0.7:
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
request@^2.88.0:
request@^2.88.0, request@^2.88.2:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
@@ -7279,6 +7393,13 @@ saxes@^3.1.9:
dependencies:
xmlchars "^2.1.1"
saxes@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
dependencies:
xmlchars "^2.2.0"
schema-utils@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
@@ -7847,7 +7968,7 @@ svgo@^1.0.0:
unquote "~1.1.1"
util.promisify "~1.0.0"
symbol-tree@^3.2.2:
symbol-tree@^3.2.2, symbol-tree@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
@@ -8027,6 +8148,15 @@ tough-cookie@^3.0.1:
psl "^1.1.28"
punycode "^2.1.1"
tough-cookie@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
dependencies:
psl "^1.1.33"
punycode "^2.1.1"
universalify "^0.1.2"
tr46@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
@@ -8034,6 +8164,13 @@ tr46@^1.0.1:
dependencies:
punycode "^2.1.0"
tr46@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479"
integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==
dependencies:
punycode "^2.1.1"
ts-jest@^25.3.1:
version "25.5.1"
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-25.5.1.tgz#2913afd08f28385d54f2f4e828be4d261f4337c7"
@@ -8282,7 +8419,7 @@ unique-slug@^2.0.0:
dependencies:
imurmurhash "^0.1.4"
universalify@^0.1.0:
universalify@^0.1.0, universalify@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
@@ -8410,7 +8547,7 @@ vm-browserify@^1.0.1:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
w3c-hr-time@^1.0.1:
w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
@@ -8426,6 +8563,13 @@ w3c-xmlserializer@^1.1.2:
webidl-conversions "^4.0.2"
xml-name-validator "^3.0.0"
w3c-xmlserializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a"
integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==
dependencies:
xml-name-validator "^3.0.0"
walker@^1.0.7, walker@~1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
@@ -8463,6 +8607,16 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
webidl-conversions@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
webidl-conversions@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-bundle-analyzer@^4.4.0:
version "4.4.1"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.1.tgz#c71fb2eaffc10a4754d7303b224adb2342069da1"
@@ -8536,6 +8690,15 @@ whatwg-url@^7.0.0:
tr46 "^1.0.1"
webidl-conversions "^4.0.2"
whatwg-url@^8.0.0, whatwg-url@^8.5.0:
version "8.5.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.5.0.tgz#7752b8464fc0903fec89aa9846fc9efe07351fd3"
integrity sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==
dependencies:
lodash "^4.7.0"
tr46 "^2.0.2"
webidl-conversions "^6.1.0"
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
@@ -8617,7 +8780,7 @@ write@1.0.3:
dependencies:
mkdirp "^0.5.1"
ws@^7.0.0, ws@^7.3.1:
ws@^7.0.0, ws@^7.3.1, ws@^7.4.4:
version "7.4.5"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1"
integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==
@@ -8627,7 +8790,7 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xmlchars@^2.1.1:
xmlchars@^2.1.1, xmlchars@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==


Loading…
Cancel
Save