diff --git a/package-lock.json b/package-lock.json index 872af0ea..f4db12dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10422,6 +10422,275 @@ "jest-util": "^26.0.1" } }, + "jest-extended": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-0.11.5.tgz", + "integrity": "sha512-3RsdFpLWKScpsLD6hJuyr/tV5iFOrw7v6YjA3tPdda9sJwoHwcMROws5gwiIZfcwhHlJRwFJB2OUvGmF3evV/Q==", + "dev": true, + "requires": { + "expect": "^24.1.0", + "jest-get-type": "^22.4.3", + "jest-matcher-utils": "^22.0.0" + }, + "dependencies": { + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz", + "integrity": "sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + }, + "dependencies": { + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + }, + "dependencies": { + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + } + } + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-matcher-utils": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz", + "integrity": "sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.4.3", + "pretty-format": "^22.4.3" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "pretty-format": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", + "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + } + } + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "jest-get-type": { "version": "26.0.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.0.0.tgz", diff --git a/package.json b/package.json index 7b21f2f6..64d8a257 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "eslint-plugin-react": "^7.20.0", "husky": "^4.2.5", "jest": "^26.0.1", + "jest-extended": "^0.11.5", "lint-staged": "^10.2.2", "npm-run-all": "^4.1.5", "parcel-bundler": "^1.6.1", @@ -63,7 +64,8 @@ "\\.(jpg|jpeg|png|svg)$": "/src/__mocks__/fileMock.js" }, "setupFilesAfterEnv": [ - "./tests/setupTests.js" + "./tests/setupTests.js", + "jest-extended" ] }, "keywords": [], diff --git a/src/__snapshots__/parser.test.js.snap b/src/__snapshots__/parser.test.js.snap new file mode 100644 index 00000000..ce42910e --- /dev/null +++ b/src/__snapshots__/parser.test.js.snap @@ -0,0 +1,110 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`parser should parse query successfully 1`] = ` +Object { + "code": + I'm a label + , + "expression": Object { + "args": Array [ + "I'm a label", + ], + "call": "getByText(\\"I'm a label\\")", + "expression": "screen.getByText(\\"I'm a label\\")", + "level": 0, + "method": "getByText", + "scope": "screen", + }, + "id": 1, + "roles": Object { + "button": Array [ + , + , + ], + "document": Array [ + + + +
+ + + + + + + + + + I'm a label + + + + + + +
+ , + ], + }, + "target": + I'm a label + , + "targets": Array [ + + I'm a label + , + ], + "text": " + I'm a label +", +} +`; + +exports[`parser should remove all comments from parsed expression 1`] = ` +Object { + "args": Array [ + "button", + ], + "call": "getByRole('button')", + "expression": "getByRole('button')", + "level": 0, + "method": "getByRole", + "scope": "", +} +`; + +exports[`parser should return getByPlaceholderText as expression 1`] = ` +Object { + "args": Array [ + "I'm a placeholder", + ], + "call": "getByPlaceholderText(\\"I'm a placeholder\\")", + "expression": "screen.getByPlaceholderText(\\"I'm a placeholder\\")", + "level": 0, + "method": "getByPlaceholderText", + "scope": "screen", +} +`; + +exports[`parser should return getByPlaceholderText as expression because is the last one in the sentence 1`] = ` +Object { + "args": Array [ + "I'm a placeholder", + ], + "call": "getByPlaceholderText(\\"I'm a placeholder\\")", + "expression": "screen.getByPlaceholderText(\\"I'm a placeholder\\")", + "level": 0, + "method": "getByPlaceholderText", + "scope": "screen", +} +`; diff --git a/src/components/Playground.test.js b/src/components/Playground.test.js index 433f67b6..c1e85cca 100644 --- a/src/components/Playground.test.js +++ b/src/components/Playground.test.js @@ -1,9 +1,9 @@ import React from 'react'; import Playground from './App'; -import { renderWithContext } from '../../tests/utils/render'; +import { renderIntoContext } from '../../tests/utils/react-render'; describe('App', () => { it('should not throw on render', () => { - renderWithContext(); + renderIntoContext(); }); }); diff --git a/src/lib/ensureArray.test.js b/src/lib/ensureArray.test.js new file mode 100644 index 00000000..4d892cd9 --- /dev/null +++ b/src/lib/ensureArray.test.js @@ -0,0 +1,11 @@ +import { ensureArray } from './ensureArray'; + +it('should return an array if a non-array is passed', () => { + const resultArray = ensureArray('test'); + expect(resultArray).toEqual(['test']); +}); + +it("should return an array if it's already of array type", () => { + const resultArray = ensureArray(['test']); + expect(resultArray).toEqual(['test']); +}); diff --git a/src/lib/queryAdvise.test.js b/src/lib/queryAdvise.test.js new file mode 100644 index 00000000..23d324e4 --- /dev/null +++ b/src/lib/queryAdvise.test.js @@ -0,0 +1,11 @@ +import { getData } from './queryAdvise'; +import { renderIntoDocument } from '../../tests/utils/dom-render'; + +describe('queryAdvise', () => { + describe('getData', () => { + it('should not thrown if id attribute of DOM element is invalid', () => { + const container = renderIntoDocument(' + + I'm a label + + `); +}; +describe('parser', () => { + it('should parse query successfully', () => { + const container = setup(); + const result = parser.parse({ + htmlRoot: container, + js: 'screen.getByText("I\'m a label")', + }); + expect(result).toMatchSnapshot(); + }); + + it('should give an error if the query is not valid', () => { + const container = setup(); + const result = parser.parse({ htmlRoot: container, js: 'invalidquery' }); + expect(result.error).toBeDefined(); + expect(result.errorBody).toBeDefined(); + }); + + it('should return targets as array', () => { + const container = setup(); + let result = parser.parse({ + htmlRoot: container, + js: "screen.getAllByRole('button')", + }); + expect(result.targets).toBeArray(); + expect(result.targets).toHaveLength(2); + result = parser.parse({ + htmlRoot: container, + js: 'screen.getByText("I\'m a label")', + }); + expect(result.targets).toBeArray(); + expect(result.targets).toHaveLength(1); + }); + + it('should return getByPlaceholderText as expression because is the last one in the sentence', () => { + const container = setup(); + let result = parser.parse({ + htmlRoot: container, + js: `screen.getAllByRole('button'); + screen.getByPlaceholderText("I'm a placeholder");`, + }); + expect(result.expression).toMatchSnapshot(); + }); + + it('should remove all comments from parsed expression', () => { + const container = setup(); + let result = parser.parse({ + htmlRoot: container, + js: ` + // comment1 + /* + comment2 + */ + getByRole('button');`, + }); + expect(result.expression).toMatchSnapshot(); + }); + + it('should remove all spaces outside of quotes/tick/single quote', () => { + const container = setup(); + let result = parser.parse({ + htmlRoot: container, + js: ` get ByRol e('button');`, + }); + expect(result.expression.expression).toEqual("getByRole('button')"); + + result = parser.parse({ + htmlRoot: container, + js: ` get ByRol e("button");`, + }); + expect(result.expression.expression).toEqual('getByRole("button")'); + + result = parser.parse({ + htmlRoot: container, + js: ' get ByRol e(`button`);', + }); + expect(result.expression.expression).toEqual('getByRole(`button`)'); + }); +}); diff --git a/tests/utils/dom-render.js b/tests/utils/dom-render.js new file mode 100644 index 00000000..b8cc7eba --- /dev/null +++ b/tests/utils/dom-render.js @@ -0,0 +1,16 @@ +function render(html, { container = document.createElement('div') } = {}) { + container.innerHTML = html; + return container; +} + +function renderIntoDocument(html) { + return render(html, { container: document.body }); +} + +function cleanup() { + document.body.innerHTML = ''; +} + +afterEach(cleanup); + +export { render, renderIntoDocument, cleanup }; diff --git a/tests/utils/render.js b/tests/utils/react-render.js similarity index 74% rename from tests/utils/render.js rename to tests/utils/react-render.js index c7916f83..1450f54b 100644 --- a/tests/utils/render.js +++ b/tests/utils/react-render.js @@ -2,8 +2,8 @@ import React from 'react'; import { render } from '@testing-library/react'; import { PlaygroundProvider } from '../../src/components/Context'; -function renderWithContext(component, ...args) { +function renderIntoContext(component, ...args) { return render({component}, ...args); } -export { renderWithContext }; +export { renderIntoContext };