Skip to content

Commit f627ade

Browse files
balavishnuvjBalavishnu V Jkentcdodds
authored
feat: add logPlaygroundUrl in screen (#781)
Co-authored-by: Balavishnu V J <[email protected]> Co-authored-by: Kent C. Dodds <[email protected]>
1 parent 8eebd9e commit f627ade

File tree

4 files changed

+107
-30
lines changed

4 files changed

+107
-30
lines changed

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@
4242
"@babel/runtime": "^7.10.3",
4343
"@types/aria-query": "^4.2.0",
4444
"aria-query": "^4.2.2",
45+
"chalk": "^4.1.0",
4546
"dom-accessibility-api": "^0.5.1",
46-
"pretty-format": "^26.4.2",
47-
"chalk": "^4.1.0"
47+
"lz-string": "^1.4.4",
48+
"pretty-format": "^26.4.2"
4849
},
4950
"devDependencies": {
5051
"@testing-library/jest-dom": "^5.10.1",
@@ -78,4 +79,4 @@
7879
"url": "https://github.com/testing-library/dom-testing-library/issues"
7980
},
8081
"homepage": "https://github.com/testing-library/dom-testing-library#readme"
81-
}
82+
}

src/__tests__/screen.js

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {screen} from '..'
2-
import {renderIntoDocument} from './helpers/test-utils'
2+
import {render, renderIntoDocument} from './helpers/test-utils'
33

44
// Since screen.debug internally calls getUserCodeFrame, we mock it so it doesn't affect these tests
55
jest.mock('../get-user-code-frame', () => ({
@@ -21,6 +21,49 @@ test('exposes queries that are attached to document.body', async () => {
2121
expect(screen.queryByText(/hello world/i)).not.toBeNull()
2222
})
2323

24+
test('logs Playground URL that are attached to document.body', () => {
25+
renderIntoDocument(`<div>hello world</div>`)
26+
screen.logTestingPlaygroundURL()
27+
expect(console.log).toHaveBeenCalledTimes(1)
28+
expect(console.log.mock.calls[0][0]).toMatchInlineSnapshot(`
29+
"Open this URL in your browser
30+
31+
https://testing-playground.com/#markup=DwEwlgbgfAFgpgGwQewAQHdkCcEmAenGiA"
32+
`)
33+
})
34+
35+
test('logs messsage when element is empty', () => {
36+
screen.logTestingPlaygroundURL(document.createElement('div'))
37+
expect(console.log).toHaveBeenCalledTimes(1)
38+
expect(console.log.mock.calls[0][0]).toMatchInlineSnapshot(
39+
`"The provided element doesn't have any children."`,
40+
)
41+
})
42+
43+
test('logs messsage when element is not a valid HTML', () => {
44+
screen.logTestingPlaygroundURL(null)
45+
expect(console.log).toHaveBeenCalledTimes(1)
46+
expect(console.log.mock.calls[0][0]).toMatchInlineSnapshot(
47+
`"The element you're providing isn't a valid DOM element."`,
48+
)
49+
console.log.mockClear()
50+
screen.logTestingPlaygroundURL({})
51+
expect(console.log).toHaveBeenCalledTimes(1)
52+
expect(console.log.mock.calls[0][0]).toMatchInlineSnapshot(
53+
`"The element you're providing isn't a valid DOM element."`,
54+
)
55+
})
56+
57+
test('logs Playground URL that are passed as element', () => {
58+
screen.logTestingPlaygroundURL(render(`<h1>Sign <em>up</em></h1>`).container)
59+
expect(console.log).toHaveBeenCalledTimes(1)
60+
expect(console.log.mock.calls[0][0]).toMatchInlineSnapshot(`
61+
"Open this URL in your browser
62+
63+
https://testing-playground.com/#markup=DwCwjAfAyglg5gOwATAKYFsIFcAOwD0GEB4EQA"
64+
`)
65+
})
66+
2467
test('exposes debug method', () => {
2568
renderIntoDocument(
2669
`<button>test</button><span>multi-test</span><div>multi-test</div>`,

src/screen.js

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,51 @@
1+
import {compressToEncodedURIComponent} from 'lz-string'
12
import * as queries from './queries'
23
import {getQueriesForElement} from './get-queries-for-element'
34
import {logDOM} from './pretty-dom'
5+
import {getDocument} from './helpers'
6+
7+
function unindent(string) {
8+
// remove white spaces first, to save a few bytes.
9+
// testing-playground will reformat on load any ways.
10+
return string.replace(/[ \t]*[\n][ \t]*/g, '\n')
11+
}
12+
13+
function encode(value) {
14+
return compressToEncodedURIComponent(unindent(value))
15+
}
16+
17+
function getPlaygroundUrl(markup) {
18+
return `https://testing-playground.com/#markup=${encode(markup)}`
19+
}
420

521
const debug = (element, maxLength, options) =>
622
Array.isArray(element)
723
? element.forEach(el => logDOM(el, maxLength, options))
824
: logDOM(element, maxLength, options)
925

26+
const logTestingPlaygroundURL = (element = getDocument().body) => {
27+
if (!element || !('innerHTML' in element)) {
28+
console.log(`The element you're providing isn't a valid DOM element.`)
29+
return
30+
}
31+
if (!element.innerHTML) {
32+
console.log(`The provided element doesn't have any children.`)
33+
return
34+
}
35+
console.log(
36+
`Open this URL in your browser\n\n${getPlaygroundUrl(element.innerHTML)}`,
37+
)
38+
}
39+
40+
const initialValue = {debug, logTestingPlaygroundURL}
1041
export const screen =
1142
typeof document !== 'undefined' && document.body
12-
? getQueriesForElement(document.body, queries, {debug})
13-
: Object.keys(queries).reduce(
14-
(helpers, key) => {
15-
helpers[key] = () => {
16-
throw new TypeError(
17-
'For queries bound to document.body a global document has to be available... Learn more: https://testing-library.com/s/screen-global-error',
18-
)
19-
}
20-
return helpers
21-
},
22-
{debug},
23-
)
43+
? getQueriesForElement(document.body, queries, initialValue)
44+
: Object.keys(queries).reduce((helpers, key) => {
45+
helpers[key] = () => {
46+
throw new TypeError(
47+
'For queries bound to document.body a global document has to be available... Learn more: https://testing-library.com/s/screen-global-error',
48+
)
49+
}
50+
return helpers
51+
}, initialValue)

types/screen.d.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
import { BoundFunctions, Queries } from './get-queries-for-element';
2-
import * as queries from './queries';
3-
import { OptionsReceived } from 'pretty-format';
1+
import {BoundFunctions, Queries} from './get-queries-for-element'
2+
import * as queries from './queries'
3+
import {OptionsReceived} from 'pretty-format'
44

55
export type Screen<Q extends Queries = typeof queries> = BoundFunctions<Q> & {
6-
/**
7-
* Convenience function for `pretty-dom` which also allows an array
8-
* of elements
9-
*/
10-
debug: (
11-
element?: Element | HTMLDocument | Array<Element | HTMLDocument>,
12-
maxLength?: number,
13-
options?: OptionsReceived,
14-
) => void;
15-
};
6+
/**
7+
* Convenience function for `pretty-dom` which also allows an array
8+
* of elements
9+
*/
10+
debug: (
11+
element?: Element | HTMLDocument | Array<Element | HTMLDocument>,
12+
maxLength?: number,
13+
options?: OptionsReceived,
14+
) => void
15+
/**
16+
* Convenience function for `Testing Playground` which logs URL that
17+
* can be opened in a browser
18+
*/
19+
logTestingPlaygroundURL: (element?: Element | HTMLDocument) => void
20+
}
1621

17-
export const screen: Screen;
22+
export const screen: Screen

0 commit comments

Comments
 (0)