@sitecore-feaas/clientside 0.4.0-alpha.9 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/build/components/FEAASComponent.js +22 -10
- package/build/components/FEAASComponent.js.map +1 -1
- package/build/components/FEAASElement.js +3 -3
- package/build/components/FEAASElement.js.map +1 -1
- package/build/dom/html.js +3 -2
- package/build/dom/html.js.map +1 -1
- package/build/ui/react.js +24 -9
- package/build/ui/react.js.map +1 -1
- package/build/utils/settings.js +6 -0
- package/build/utils/settings.js.map +1 -1
- package/dist/browser/headless.cjs +6 -6
- package/dist/browser/headless.cjs.map +3 -3
- package/dist/browser/headless.esm.js +6 -6
- package/dist/browser/headless.esm.js.map +1 -1
- package/dist/browser/index.cjs +5 -5
- package/dist/browser/index.cjs.map +3 -3
- package/dist/browser/index.esm.js +5 -5
- package/dist/browser/index.esm.js.map +1 -1
- package/dist/browser/react.cjs +7 -7
- package/dist/browser/react.cjs.map +4 -4
- package/dist/browser/react.esm.js +7 -7
- package/dist/browser/react.esm.js.map +1 -1
- package/dist/node/headless.cjs +4 -4
- package/dist/node/headless.cjs.map +3 -3
- package/dist/node/headless.esm.js +4 -4
- package/dist/node/headless.esm.js.map +3 -3
- package/dist/node/index.cjs +4 -4
- package/dist/node/index.cjs.map +3 -3
- package/dist/node/index.esm.js +4 -4
- package/dist/node/index.esm.js.map +3 -3
- package/dist/node/react.cjs +4 -4
- package/dist/node/react.cjs.map +4 -4
- package/dist/node/react.esm.js +4 -4
- package/dist/node/react.esm.js.map +4 -4
- package/headless.cjs +4 -4
- package/headless.cjs.map +3 -3
- package/headless.js +4 -4
- package/headless.js.map +3 -3
- package/package.json +3 -3
- package/react.cjs +7 -7
- package/react.cjs.map +4 -4
- package/react.js +7 -7
- package/react.js.map +4 -4
- package/scripts/build.js +10 -1
- package/scripts/test-setup.ts +0 -1
- package/src/components/FEAASComponent.tsx +29 -12
- package/src/components/FEAASElement.tsx +1 -1
- package/src/dom/html.ts +2 -2
- package/src/ui/react.tsx +33 -12
- package/src/utils/settings.ts +6 -0
- package/test/FEAASComponent.react.test.tsx +11 -11
- package/test/FEAASComponent.test.tsx +165 -13
- package/test/FEAASContext.test.tsx +1 -1
- package/test/ServerComponent.test.tsx +99 -15
- package/types/components/FEAASComponent.d.ts +5 -5
- package/types/components/FEAASComponent.d.ts.map +1 -1
- package/types/components/FEAASElement.d.ts.map +1 -1
- package/types/ui/react.d.ts +9 -4
- package/types/ui/react.d.ts.map +1 -1
- package/types/utils/settings.d.ts +7 -5
- package/types/utils/settings.d.ts.map +1 -1
package/scripts/build.js
CHANGED
|
@@ -17,7 +17,16 @@ function compile({ input, output, ...step }) {
|
|
|
17
17
|
outfile: path.resolve(__dirname, '../' + output),
|
|
18
18
|
bundle: true,
|
|
19
19
|
write: false,
|
|
20
|
-
external: [
|
|
20
|
+
external: [
|
|
21
|
+
'node:crypto',
|
|
22
|
+
'node-fetch',
|
|
23
|
+
'_MAGIC_IMPORT_COMMENTS_ESBUILD_WORKAROUND__',
|
|
24
|
+
'react',
|
|
25
|
+
'react-dom',
|
|
26
|
+
'vm',
|
|
27
|
+
'@sitecore/byoc',
|
|
28
|
+
'@sitecore/byoc/react'
|
|
29
|
+
],
|
|
21
30
|
...step,
|
|
22
31
|
|
|
23
32
|
minify: true,
|
package/scripts/test-setup.ts
CHANGED
|
@@ -24,6 +24,7 @@ export function FEAASComponentsProps(element: FEAASElement) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
const fetch = element.getAttribute('fetch')
|
|
27
28
|
return {
|
|
28
29
|
data: (data || {}) as DataOptions,
|
|
29
30
|
cdn: element.getContextAttribute('cdn') ?? cdn ?? DEFAULT_CDN_URL,
|
|
@@ -37,7 +38,12 @@ export function FEAASComponentsProps(element: FEAASElement) {
|
|
|
37
38
|
editable: element.getAttribute('editable') != null,
|
|
38
39
|
suspended: element.getAttribute('suspended') != null,
|
|
39
40
|
lastModified: element.getAttribute('last-modified'),
|
|
40
|
-
|
|
41
|
+
fetch:
|
|
42
|
+
fetch == 'false'
|
|
43
|
+
? []
|
|
44
|
+
: fetch == null || fetch == 'true'
|
|
45
|
+
? ['data', 'template', 'stylesheet']
|
|
46
|
+
: fetch.split(/(\s+|\-)+/g).filter(Boolean)
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
|
|
@@ -92,7 +98,6 @@ export class FEAASComponent extends FEAASElement<FEAASComponentsProps, string> {
|
|
|
92
98
|
cdn: DEFAULT_CDN_URL,
|
|
93
99
|
revision: 'published',
|
|
94
100
|
version: 'responsive',
|
|
95
|
-
withStylesheet: true,
|
|
96
101
|
editable: false,
|
|
97
102
|
suspended: false,
|
|
98
103
|
data: {}
|
|
@@ -124,7 +129,7 @@ export class FEAASComponent extends FEAASElement<FEAASComponentsProps, string> {
|
|
|
124
129
|
|
|
125
130
|
super.attributeChangedCallback(name, oldValue, newValue)
|
|
126
131
|
|
|
127
|
-
if (name === 'data') {
|
|
132
|
+
if (name === 'data' && this.props.fetch.includes('data')) {
|
|
128
133
|
this.fetchData()
|
|
129
134
|
}
|
|
130
135
|
}
|
|
@@ -202,7 +207,7 @@ export class FEAASComponent extends FEAASElement<FEAASComponentsProps, string> {
|
|
|
202
207
|
|
|
203
208
|
const advanceIfEverythingIsReady = () => {
|
|
204
209
|
// html is not loaded
|
|
205
|
-
if (
|
|
210
|
+
if (this.payload == null) return
|
|
206
211
|
|
|
207
212
|
// shared stylesheet is still being loaded
|
|
208
213
|
if (stylesheetPromise) return
|
|
@@ -213,20 +218,26 @@ export class FEAASComponent extends FEAASElement<FEAASComponentsProps, string> {
|
|
|
213
218
|
this.onLoad(this.payload)
|
|
214
219
|
}
|
|
215
220
|
|
|
216
|
-
if (this.props.
|
|
221
|
+
if (this.props.fetch.includes('stylesheet')) {
|
|
217
222
|
var stylesheetPromise = loadStylesheetAllowStale({ ...this.props }).then(() => {
|
|
218
223
|
stylesheetPromise = null
|
|
219
224
|
advanceIfEverythingIsReady()
|
|
220
225
|
})
|
|
221
226
|
}
|
|
222
227
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
this.whenDataReady.then(() => advanceIfEverythingIsReady()),
|
|
226
|
-
fetchAndRevalidateComponent(this.props, (html) => {
|
|
228
|
+
if (this.props.fetch.includes('template')) {
|
|
229
|
+
var templatePromise = fetchAndRevalidateComponent(this.props, (html) => {
|
|
227
230
|
this.payload = html
|
|
228
231
|
advanceIfEverythingIsReady()
|
|
229
232
|
})
|
|
233
|
+
} else {
|
|
234
|
+
this.payload = this.props.template ?? this.innerHTML
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return Promise.all([
|
|
238
|
+
stylesheetPromise,
|
|
239
|
+
this.whenDataReady.then(() => advanceIfEverythingIsReady()),
|
|
240
|
+
templatePromise
|
|
230
241
|
]).then(() => this.payload)
|
|
231
242
|
}
|
|
232
243
|
|
|
@@ -240,7 +251,8 @@ export class FEAASComponent extends FEAASElement<FEAASComponentsProps, string> {
|
|
|
240
251
|
|
|
241
252
|
update() {
|
|
242
253
|
this.alreadyRendered = true
|
|
243
|
-
if
|
|
254
|
+
// avoid unnecessary rendering if hydration was disabled
|
|
255
|
+
if (!this.props.fetch.includes('data') && !this.props.fetch.includes('template') && this.firstElementChild) return
|
|
244
256
|
if (Array.from(this.children).filter((c) => c.tagName != 'BR').length > 0 && !this.needsRefresh) {
|
|
245
257
|
renderDOMElement(this, this.readyData)
|
|
246
258
|
} else {
|
|
@@ -254,6 +266,8 @@ export class FEAASComponent extends FEAASElement<FEAASComponentsProps, string> {
|
|
|
254
266
|
}
|
|
255
267
|
}
|
|
256
268
|
|
|
269
|
+
type FetchKeyword = 'data' | 'template' | 'stylesheet'
|
|
270
|
+
|
|
257
271
|
declare global {
|
|
258
272
|
namespace JSX {
|
|
259
273
|
interface IntrinsicElements {
|
|
@@ -267,8 +281,11 @@ declare global {
|
|
|
267
281
|
children?: any
|
|
268
282
|
dangerouslySetInnerHTML?: { __html: string }
|
|
269
283
|
'last-modified'?: string
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
fetch?:
|
|
285
|
+
| `${FetchKeyword} ${FetchKeyword} ${FetchKeyword}`
|
|
286
|
+
| `${FetchKeyword} ${FetchKeyword}`
|
|
287
|
+
| `${FetchKeyword}`
|
|
288
|
+
| ''
|
|
272
289
|
} & (
|
|
273
290
|
| {
|
|
274
291
|
/**
|
|
@@ -142,7 +142,6 @@ export class FEAASElement<Props = any, Payload = any> extends WebComponent {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
log(...args: any) {
|
|
145
|
-
if (typeof process != 'undefined' && process.env.TESTING) return
|
|
146
145
|
const format = args[0]
|
|
147
146
|
|
|
148
147
|
if (
|
|
@@ -412,6 +411,7 @@ export class FEAASElement<Props = any, Payload = any> extends WebComponent {
|
|
|
412
411
|
const ErrorBoundary = this.getReactErrorBoundary()
|
|
413
412
|
const Wrapper = this.getReactWrapper(target)
|
|
414
413
|
return (
|
|
414
|
+
// @ts-ignore TS5 react types throws here
|
|
415
415
|
<ErrorBoundary key={target.tagName + '-' + target.getUID()} slot={target.getAttribute('slot')}>
|
|
416
416
|
<Wrapper />
|
|
417
417
|
</ErrorBoundary>
|
package/src/dom/html.ts
CHANGED
|
@@ -243,7 +243,7 @@ export function parseHTML(html: string): HTMLNode[] {
|
|
|
243
243
|
const closingTagMatch = html.match(/^<\/([\w-]+)>/)
|
|
244
244
|
|
|
245
245
|
if (openTagMatch) {
|
|
246
|
-
const nodeName = openTagMatch[1]
|
|
246
|
+
const nodeName = openTagMatch[1].toLowerCase()
|
|
247
247
|
const attrsStr = openTagMatch[2] || ''
|
|
248
248
|
const attrs =
|
|
249
249
|
attrsStr.match(/([\w-]+)(="([^"]*)")?/g)?.map((attr) => {
|
|
@@ -260,7 +260,7 @@ export function parseHTML(html: string): HTMLNode[] {
|
|
|
260
260
|
} else {
|
|
261
261
|
nodes.push(node)
|
|
262
262
|
}
|
|
263
|
-
stack.push(node)
|
|
263
|
+
if (!['img', 'input', 'br'].includes(nodeName)) stack.push(node)
|
|
264
264
|
html = html.slice(openTagMatch[0].length)
|
|
265
265
|
} else if (closingTagMatch) {
|
|
266
266
|
stack.pop()
|
package/src/ui/react.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import * as BYOC from '@sitecore/byoc/react'
|
|
2
3
|
import { HTMLNode, parseHTMLContent, renderHTMLContent } from '../dom/html.js'
|
|
3
4
|
import { DataSettings } from '../utils/settings.js'
|
|
4
5
|
import {
|
|
@@ -12,13 +13,21 @@ import {
|
|
|
12
13
|
parseComponentSource,
|
|
13
14
|
parseStylesheetSource
|
|
14
15
|
} from './index.js'
|
|
15
|
-
import * as BYOC from '@sitecore/byoc/react'
|
|
16
16
|
export * from '../headless.js'
|
|
17
17
|
export { External, FEAASExternalPropsObject, getComponent, linkComponents, registerComponent } from './FEAASExternal.js'
|
|
18
18
|
export * from './index.js'
|
|
19
19
|
export { renderHTMLContent }
|
|
20
20
|
|
|
21
|
+
type FEEASReactComponentFetch = string[] | string | null | undefined | boolean
|
|
22
|
+
export function normalizeFetchAttribute(fetch: FEEASReactComponentFetch) {
|
|
23
|
+
if (fetch == null || fetch === true) {
|
|
24
|
+
return ['template', 'stylesheet', 'data']
|
|
25
|
+
}
|
|
26
|
+
return [].concat(fetch || [])
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
export type FEAASReactComponentProps = FEAASComponentProps & {
|
|
30
|
+
fetch?: FEEASReactComponentFetch
|
|
22
31
|
preload?: boolean
|
|
23
32
|
lastModified?: Date | string
|
|
24
33
|
}
|
|
@@ -44,8 +53,9 @@ export const FEAASReactStylesheet = (props: FEAASCDNStylesheetParams | FEAASCDNS
|
|
|
44
53
|
* @param {FEAASReactComponentProps} props - The properties for the component.
|
|
45
54
|
* @returns {Promise<JSX.Element>} The JSX element representing the component.
|
|
46
55
|
*/
|
|
47
|
-
export const FEAASReactServerComponent = async ({ ...props }: FEAASReactComponentProps) => {
|
|
48
|
-
const fetchedData = await DataSettings.fetch(
|
|
56
|
+
export const FEAASReactServerComponent = async ({ data, fetch, ...props }: FEAASReactComponentProps) => {
|
|
57
|
+
const fetchedData = await DataSettings.fetch(data || {})
|
|
58
|
+
fetch = normalizeFetchAttribute(fetch ?? ['stylesheet'])
|
|
49
59
|
|
|
50
60
|
const p: FEAASReactComponentProps = { ...props }
|
|
51
61
|
|
|
@@ -54,13 +64,17 @@ export const FEAASReactServerComponent = async ({ ...props }: FEAASReactComponen
|
|
|
54
64
|
|
|
55
65
|
p.template = response.template
|
|
56
66
|
p.lastModified = response.lastModified
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
} else if (props?.template == null && !fetch.includes('template')) {
|
|
68
|
+
fetch.push('template')
|
|
59
69
|
}
|
|
60
70
|
|
|
61
|
-
return FEAASReactComponent({
|
|
71
|
+
return FEAASReactComponent({
|
|
72
|
+
...p,
|
|
73
|
+
data,
|
|
74
|
+
fetch,
|
|
75
|
+
fetchedData
|
|
76
|
+
})
|
|
62
77
|
}
|
|
63
|
-
|
|
64
78
|
/**
|
|
65
79
|
* A wrapper over FEAAS.Component for use in React. It converts a passed template HTML into React,
|
|
66
80
|
* allowing external components in the render tree. Data can be provided in JSON format.
|
|
@@ -68,12 +82,17 @@ export const FEAASReactServerComponent = async ({ ...props }: FEAASReactComponen
|
|
|
68
82
|
* @param {FEAASReactComponentProps} props - The properties for the component.
|
|
69
83
|
* @returns {JSX.Element} The JSX element representing the component.
|
|
70
84
|
*/
|
|
71
|
-
export function FEAASReactComponent({
|
|
85
|
+
export function FEAASReactComponent({
|
|
86
|
+
data,
|
|
87
|
+
lastModified,
|
|
88
|
+
fetchedData,
|
|
89
|
+
...props
|
|
90
|
+
}: FEAASReactComponentProps & { fetchedData?: any }) {
|
|
72
91
|
let preload = null
|
|
73
92
|
let children: null | React.ReactNode
|
|
74
93
|
|
|
75
94
|
if ('template' in props && props.template) {
|
|
76
|
-
children = parseHTMLContent(props.template, data || {}).map((node, index) =>
|
|
95
|
+
children = parseHTMLContent(props.template, fetchedData || data || {}).map((node, index) =>
|
|
77
96
|
HTMLNodeToReact(
|
|
78
97
|
node,
|
|
79
98
|
(node, attributes) => {
|
|
@@ -94,7 +113,8 @@ export function FEAASReactComponent({ data, ...props }: FEAASReactComponentProps
|
|
|
94
113
|
if ('src' in props) {
|
|
95
114
|
props = { ...parseComponentSource(props.src), ...props }
|
|
96
115
|
}
|
|
97
|
-
|
|
116
|
+
const fetch = normalizeFetchAttribute(props.fetch)
|
|
117
|
+
const embeddedData = fetch.includes('data') ? data : fetch.includes('template') ? fetchedData : null
|
|
98
118
|
return (
|
|
99
119
|
<>
|
|
100
120
|
{'preload' in props && preload === true && 'src' in props && (
|
|
@@ -106,10 +126,11 @@ export function FEAASReactComponent({ data, ...props }: FEAASReactComponentProps
|
|
|
106
126
|
<feaas-component
|
|
107
127
|
class='-feaas'
|
|
108
128
|
{...props}
|
|
129
|
+
last-modified={lastModified ? String(lastModified) : null}
|
|
130
|
+
fetch={props.fetch == null ? props.fetch : ([].concat(props.fetch).join(' ') as any)}
|
|
109
131
|
suppressHydrationWarning
|
|
110
132
|
template={null}
|
|
111
|
-
data={typeof
|
|
112
|
-
hydrate={'false'}
|
|
133
|
+
data={typeof embeddedData == 'string' ? embeddedData : embeddedData ? JSON.stringify(embeddedData) : null}
|
|
113
134
|
>
|
|
114
135
|
{children}
|
|
115
136
|
</feaas-component>
|
package/src/utils/settings.ts
CHANGED
|
@@ -192,9 +192,15 @@ export async function fetchData(data: DataOptions): Promise<DataScopes> {
|
|
|
192
192
|
)
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
export async function hasDataSettings(data: DataOptions) {
|
|
196
|
+
if (!data) return false
|
|
197
|
+
return isDataSettings(data) || Object.values(data).some(isDataSettings)
|
|
198
|
+
}
|
|
199
|
+
|
|
195
200
|
DataSettings.clean = clean
|
|
196
201
|
DataSettings.toFetchArguments = toFetchArguments
|
|
197
202
|
DataSettings.fetchOne = fetchDataSettings
|
|
198
203
|
DataSettings.fetch = fetchData
|
|
199
204
|
DataSettings.isDataSettings = isDataSettings
|
|
205
|
+
DataSettings.hasDataSettings = hasDataSettings
|
|
200
206
|
DataSettings.fetchImplementation = (...args: Parameters<typeof fetch>) => fetch(...args)
|
|
@@ -53,7 +53,7 @@ describe('React', () => {
|
|
|
53
53
|
<section>
|
|
54
54
|
<Component src='library/test'></Component>
|
|
55
55
|
</section>,
|
|
56
|
-
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test"
|
|
56
|
+
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test"></feaas-component></section>'
|
|
57
57
|
)
|
|
58
58
|
})
|
|
59
59
|
it('render react with empty template', async () => {
|
|
@@ -61,7 +61,7 @@ describe('React', () => {
|
|
|
61
61
|
<section>
|
|
62
62
|
<Component src='library/test' template=''></Component>
|
|
63
63
|
</section>,
|
|
64
|
-
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test"
|
|
64
|
+
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test"></feaas-component></section>'
|
|
65
65
|
)
|
|
66
66
|
})
|
|
67
67
|
it('render react component with src and overrides', async () => {
|
|
@@ -69,7 +69,7 @@ describe('React', () => {
|
|
|
69
69
|
<section>
|
|
70
70
|
<Component src='library/test' component='test2'></Component>
|
|
71
71
|
</section>,
|
|
72
|
-
'<section><feaas-component class="-feaas" library="library" component="test2" src="library/test"
|
|
72
|
+
'<section><feaas-component class="-feaas" library="library" component="test2" src="library/test"></feaas-component></section>'
|
|
73
73
|
)
|
|
74
74
|
})
|
|
75
75
|
it('render react component with extras', async () => {
|
|
@@ -77,7 +77,7 @@ describe('React', () => {
|
|
|
77
77
|
<section>
|
|
78
78
|
<Component src='library/test' version='v1'></Component>
|
|
79
79
|
</section>,
|
|
80
|
-
'<section><feaas-component class="-feaas" library="library" component="test" version="v1" src="library/test"
|
|
80
|
+
'<section><feaas-component class="-feaas" library="library" component="test" version="v1" src="library/test"></feaas-component></section>'
|
|
81
81
|
)
|
|
82
82
|
})
|
|
83
83
|
it('render react template', async () => {
|
|
@@ -85,7 +85,7 @@ describe('React', () => {
|
|
|
85
85
|
<section>
|
|
86
86
|
<Component src='library/test' template={'<div data-path-src="abc">'}></Component>
|
|
87
87
|
</section>,
|
|
88
|
-
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test"
|
|
88
|
+
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test"><div data-path-src="abc"></div></feaas-component></section>'
|
|
89
89
|
)
|
|
90
90
|
})
|
|
91
91
|
it('render template with data and src', async () => {
|
|
@@ -93,7 +93,7 @@ describe('React', () => {
|
|
|
93
93
|
<section>
|
|
94
94
|
<Component src='library/test' template={'<div data-path-src="abc">'} data={{ abc: 321 }}></Component>
|
|
95
95
|
</section>,
|
|
96
|
-
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test" data="{"abc":321}"
|
|
96
|
+
'<section><feaas-component class="-feaas" library="library" component="test" src="library/test" data="{"abc":321}"><div data-path-src="abc"></div></feaas-component></section>'
|
|
97
97
|
)
|
|
98
98
|
})
|
|
99
99
|
it('render template with data but without src', async () => {
|
|
@@ -106,7 +106,7 @@ describe('React', () => {
|
|
|
106
106
|
data={{ abc: 321 }}
|
|
107
107
|
></Component>
|
|
108
108
|
</section>,
|
|
109
|
-
'<section><feaas-component class="-feaas" library="library" component="test" data="{"abc":321}"
|
|
109
|
+
'<section><feaas-component class="-feaas" library="library" component="test" data="{"abc":321}"><div data-path-src="abc"></div></feaas-component></section>'
|
|
110
110
|
)
|
|
111
111
|
})
|
|
112
112
|
it('render template with style attribute', async () => {
|
|
@@ -114,7 +114,7 @@ describe('React', () => {
|
|
|
114
114
|
<section>
|
|
115
115
|
<Component template={'<div data-path-src="abc">'} data={{ abc: 321 }}></Component>
|
|
116
116
|
</section>,
|
|
117
|
-
'<section><feaas-component class="-feaas" data="{"abc":321}"
|
|
117
|
+
'<section><feaas-component class="-feaas" data="{"abc":321}"><div data-path-src="abc"></div></feaas-component></section>'
|
|
118
118
|
)
|
|
119
119
|
})
|
|
120
120
|
it('render unwrapped external component with stringified values', async () => {
|
|
@@ -137,7 +137,7 @@ describe('React', () => {
|
|
|
137
137
|
data={{ abc: 321 }}
|
|
138
138
|
></Component>
|
|
139
139
|
</section>,
|
|
140
|
-
'<section><feaas-component class="-feaas" data="{"abc":321}"
|
|
140
|
+
'<section><feaas-component class="-feaas" data="{"abc":321}"><feaas-external telephone="12345" first-name="Yarik" data-external-id="MyTestComponent" hydrate="false"><div>Hello my name is Yarik (string) and my tel is 12345 (number). And context value is DEFAULT</div></feaas-external></feaas-component></section>'
|
|
141
141
|
)
|
|
142
142
|
})
|
|
143
143
|
it('render wrapped external component with context provider', async () => {
|
|
@@ -153,7 +153,7 @@ describe('React', () => {
|
|
|
153
153
|
></Component>
|
|
154
154
|
</section>
|
|
155
155
|
</DataContext.Provider>,
|
|
156
|
-
'<section><feaas-component class="-feaas" data="{"abc":321}"
|
|
156
|
+
'<section><feaas-component class="-feaas" data="{"abc":321}"><feaas-external telephone="12345" first-name="Yarik" data-external-id="MyTestComponent" hydrate="false"><div>Hello my name is Yarik (string) and my tel is 12345 (number). And context value is INHERITED</div></feaas-external></feaas-component></section>'
|
|
157
157
|
)
|
|
158
158
|
})
|
|
159
159
|
it('render wrapped external component with context provider and data mapping', async () => {
|
|
@@ -169,7 +169,7 @@ describe('React', () => {
|
|
|
169
169
|
></Component>
|
|
170
170
|
</section>
|
|
171
171
|
</DataContext.Provider>,
|
|
172
|
-
'<section><feaas-component class="-feaas" data="{"telephone":321}"
|
|
172
|
+
'<section><feaas-component class="-feaas" data="{"telephone":321}"><feaas-external data-path-attributes="$" first-name="Yarik" telephone="321" data-attributes-keys="telephone" data-external-id="MyTestComponent" hydrate="false"><div>Hello my name is Yarik (string) and my tel is 321 (number). And context value is INHERITED</div></feaas-external></feaas-component></section>'
|
|
173
173
|
)
|
|
174
174
|
})
|
|
175
175
|
})
|
|
@@ -36,7 +36,7 @@ describe('Components', () => {
|
|
|
36
36
|
|
|
37
37
|
// Fixme юhange to production component
|
|
38
38
|
document.body.innerHTML =
|
|
39
|
-
'<feaas-component
|
|
39
|
+
'<feaas-component fetch="template data" library="L" cdn="CDN" component="C" version="V" revision="R"></feaas-component>'
|
|
40
40
|
|
|
41
41
|
const component = document.body.firstElementChild as FEAASComponent
|
|
42
42
|
|
|
@@ -46,6 +46,164 @@ describe('Components', () => {
|
|
|
46
46
|
expect(component.innerHTML).toContain('TODAY')
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
+
describe('fetch control', () => {
|
|
50
|
+
it('should not make requests when hydration is turned off', async () => {
|
|
51
|
+
const spy = vi.spyOn(global, 'fetch')
|
|
52
|
+
|
|
53
|
+
// Fixme юhange to production component
|
|
54
|
+
document.body.innerHTML =
|
|
55
|
+
'<feaas-component fetch="" library="L" cdn="CDN" component="C" version="V" revision="R"></feaas-component>'
|
|
56
|
+
|
|
57
|
+
const component = document.body.firstElementChild as FEAASComponent
|
|
58
|
+
|
|
59
|
+
await expect(component.whenRendered).resolves.toEqual(component)
|
|
60
|
+
expect(spy).toHaveBeenCalledTimes(0)
|
|
61
|
+
|
|
62
|
+
expect(component.innerHTML).toBe('')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('should not make requests when hydration is turned off, but should render template', async () => {
|
|
66
|
+
const spy = vi.spyOn(global, 'fetch')
|
|
67
|
+
|
|
68
|
+
// Fixme юhange to production component
|
|
69
|
+
document.body.innerHTML =
|
|
70
|
+
'<feaas-component fetch="" library="L" cdn="CDN" component="C" version="V" revision="R" template="abc"></feaas-component>'
|
|
71
|
+
|
|
72
|
+
const component = document.body.firstElementChild as FEAASComponent
|
|
73
|
+
|
|
74
|
+
await expect(component.whenRendered).resolves.toEqual(component)
|
|
75
|
+
expect(spy).toHaveBeenCalledTimes(0)
|
|
76
|
+
|
|
77
|
+
expect(component.innerHTML).toBe('abc')
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('should only make css request with fetch="stylesheet"', async () => {
|
|
81
|
+
const spy = vi.spyOn(global, 'fetch')
|
|
82
|
+
spy.mockImplementation(async (url: string, options: Parameters<typeof fetch>[1] = {}) => {
|
|
83
|
+
if (url.match('.css')) {
|
|
84
|
+
return new Response('{}', {
|
|
85
|
+
headers: {
|
|
86
|
+
date: now.toUTCString(),
|
|
87
|
+
'last-modified': earlier.toUTCString()
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
// Fixme юhange to production component
|
|
93
|
+
document.body.innerHTML =
|
|
94
|
+
'<feaas-component fetch="stylesheet" library="L" cdn="CDN" component="C" version="V" revision="R">abc</feaas-component>'
|
|
95
|
+
|
|
96
|
+
const component = document.body.firstElementChild as FEAASComponent
|
|
97
|
+
|
|
98
|
+
await expect(component.whenRendered).resolves.toEqual(component)
|
|
99
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
100
|
+
expect(component.innerHTML).toBe('abc')
|
|
101
|
+
expect(document.head.querySelectorAll('style').length).toEqual(1)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('should make html/css requests when fetch="stylesheet template"', async () => {
|
|
105
|
+
const spy = vi.spyOn(global, 'fetch')
|
|
106
|
+
spy.mockImplementation(async (url: string, options: Parameters<typeof fetch>[1] = {}) => {
|
|
107
|
+
if (url.match('CDN/components/L/C/V/R')) {
|
|
108
|
+
return new Response('TODAY', {
|
|
109
|
+
headers: {
|
|
110
|
+
date: now.toUTCString(),
|
|
111
|
+
'last-modified': earlier.toUTCString()
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
if (url.match('.css')) {
|
|
116
|
+
return new Response('{}', {
|
|
117
|
+
headers: {
|
|
118
|
+
date: now.toUTCString(),
|
|
119
|
+
'last-modified': earlier.toUTCString()
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
document.body.innerHTML =
|
|
125
|
+
'<feaas-component fetch="stylesheet template" library="L" cdn="CDN" component="C" version="V" revision="R"></feaas-component>'
|
|
126
|
+
|
|
127
|
+
const component = document.body.firstElementChild as FEAASComponent
|
|
128
|
+
|
|
129
|
+
await expect(component.whenRendered).resolves.toEqual(component)
|
|
130
|
+
expect(spy).toHaveBeenCalledTimes(2)
|
|
131
|
+
expect(component.innerHTML).toBe('TODAY')
|
|
132
|
+
expect(document.head.querySelectorAll('style').length).toEqual(1)
|
|
133
|
+
})
|
|
134
|
+
it('should make data/css requests when fetch="stylesheet data"', async () => {
|
|
135
|
+
const spy = vi.spyOn(global, 'fetch')
|
|
136
|
+
spy.mockImplementation(async (url: string, options: Parameters<typeof fetch>[1] = {}) => {
|
|
137
|
+
if (url.match('my.json')) {
|
|
138
|
+
return new Response('{"path": "value"}', {
|
|
139
|
+
headers: {
|
|
140
|
+
date: now.toUTCString(),
|
|
141
|
+
'last-modified': earlier.toUTCString()
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
if (url.match('.css')) {
|
|
146
|
+
return new Response('{}', {
|
|
147
|
+
headers: {
|
|
148
|
+
date: now.toUTCString(),
|
|
149
|
+
'last-modified': earlier.toUTCString()
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
document.body.innerHTML =
|
|
156
|
+
'<feaas-component fetch="stylesheet data" data=\'{"source": {"url": "my.json"}}\' library="L" cdn="CDN" component="C" version="V" revision="R"><var data-path="source.path"></var></feaas-component>'
|
|
157
|
+
|
|
158
|
+
const component = document.body.firstElementChild as FEAASComponent
|
|
159
|
+
|
|
160
|
+
await expect(component.whenRendered).resolves.toEqual(component)
|
|
161
|
+
expect(spy).toHaveBeenCalledTimes(2)
|
|
162
|
+
expect(component.innerHTML).toBe('<var data-path="source.path">value</var>')
|
|
163
|
+
expect(document.head.querySelectorAll('style').length).toEqual(1)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('should make data/css/html requests when fetch="template stylesheet data"', async () => {
|
|
167
|
+
const spy = vi.spyOn(global, 'fetch')
|
|
168
|
+
spy.mockImplementation(async (url: string, options: Parameters<typeof fetch>[1] = {}) => {
|
|
169
|
+
if (url.match('.html')) {
|
|
170
|
+
return new Response('<var data-path="source.path"></var>', {
|
|
171
|
+
headers: {
|
|
172
|
+
date: now.toUTCString(),
|
|
173
|
+
'last-modified': earlier.toUTCString()
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
}
|
|
177
|
+
if (url.match('my.json')) {
|
|
178
|
+
return new Response('{"path": "value"}', {
|
|
179
|
+
headers: {
|
|
180
|
+
date: now.toUTCString(),
|
|
181
|
+
'last-modified': earlier.toUTCString()
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
if (url.match('.css')) {
|
|
186
|
+
return new Response('{}', {
|
|
187
|
+
headers: {
|
|
188
|
+
date: now.toUTCString(),
|
|
189
|
+
'last-modified': earlier.toUTCString()
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
document.body.innerHTML =
|
|
196
|
+
'<feaas-component fetch="template stylesheet data" data=\'{"source": {"url": "my.json"}}\' library="L" cdn="CDN" component="C" version="V" revision="R"></feaas-component>'
|
|
197
|
+
|
|
198
|
+
const component = document.body.firstElementChild as FEAASComponent
|
|
199
|
+
|
|
200
|
+
await expect(component.whenRendered).resolves.toEqual(component)
|
|
201
|
+
expect(spy).toHaveBeenCalledTimes(3)
|
|
202
|
+
expect(component.innerHTML).toBe('<var data-path="source.path">value</var>')
|
|
203
|
+
expect(document.head.querySelectorAll('style').length).toEqual(1)
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
49
207
|
it('should load component using src attribute shorthand', async () => {
|
|
50
208
|
const spy = vi.spyOn(global, 'fetch')
|
|
51
209
|
spy.mockImplementation(async (url: string, options: Parameters<typeof fetch>[1] = {}) => {
|
|
@@ -59,9 +217,8 @@ describe('Components', () => {
|
|
|
59
217
|
}
|
|
60
218
|
})
|
|
61
219
|
|
|
62
|
-
// Fixme change to production component
|
|
63
220
|
document.body.innerHTML =
|
|
64
|
-
'<feaas-component
|
|
221
|
+
'<feaas-component fetch="template data" src="http://a/components/b/c/d/1.html"></feaas-component>'
|
|
65
222
|
|
|
66
223
|
const component = document.body.firstElementChild as FEAASComponent
|
|
67
224
|
|
|
@@ -69,7 +226,7 @@ describe('Components', () => {
|
|
|
69
226
|
expect(spy).toHaveBeenCalledTimes(1)
|
|
70
227
|
|
|
71
228
|
expect(component.outerHTML).toBe(
|
|
72
|
-
`<feaas-component
|
|
229
|
+
`<feaas-component fetch="template data" src="http://a/components/b/c/d/1.html" cdn="http://a" library="b" component="c" version="d" revision="1" class="-feaas">TODAY</feaas-component>`
|
|
73
230
|
)
|
|
74
231
|
})
|
|
75
232
|
|
|
@@ -94,7 +251,6 @@ describe('Components', () => {
|
|
|
94
251
|
}
|
|
95
252
|
})
|
|
96
253
|
|
|
97
|
-
// Fixme change to production component
|
|
98
254
|
document.body.innerHTML =
|
|
99
255
|
'<feaas-component src="http://a/components/b/c/d/1.html"></feaas-component><feaas-component src="http://a/components/b/c/d/staged.html"></feaas-component>'
|
|
100
256
|
|
|
@@ -117,7 +273,6 @@ describe('Components', () => {
|
|
|
117
273
|
}
|
|
118
274
|
})
|
|
119
275
|
|
|
120
|
-
// Fixme change to production component
|
|
121
276
|
document.body.innerHTML =
|
|
122
277
|
'<feaas-component src="http://a/components/b/c/d/1.html"></feaas-component><link rel="stylesheet" href="http://a/styles/b/published.css" />'
|
|
123
278
|
|
|
@@ -148,9 +303,8 @@ describe('Components', () => {
|
|
|
148
303
|
}
|
|
149
304
|
})
|
|
150
305
|
|
|
151
|
-
// Fixme change to production component
|
|
152
306
|
document.body.innerHTML =
|
|
153
|
-
'<feaas-component
|
|
307
|
+
'<feaas-component fetch="template data" library="L" cdn="CDN" component="C" version="V" revision="R"></feaas-component>'
|
|
154
308
|
|
|
155
309
|
const component = document.body.firstElementChild as FEAASComponent
|
|
156
310
|
|
|
@@ -190,9 +344,8 @@ describe('Components', () => {
|
|
|
190
344
|
}
|
|
191
345
|
})
|
|
192
346
|
|
|
193
|
-
// Fixme change to production component
|
|
194
347
|
document.body.innerHTML =
|
|
195
|
-
'<feaas-component
|
|
348
|
+
'<feaas-component fetch="template data" library="L" cdn="CDN" component="C" version="V" revision="R"></feaas-component>'
|
|
196
349
|
|
|
197
350
|
const component = document.body.firstElementChild as FEAASComponent
|
|
198
351
|
// Renders cached version initially
|
|
@@ -226,9 +379,8 @@ describe('Components', () => {
|
|
|
226
379
|
}
|
|
227
380
|
})
|
|
228
381
|
|
|
229
|
-
// Fixme change to production component
|
|
230
382
|
document.body.innerHTML =
|
|
231
|
-
'<feaas-component
|
|
383
|
+
'<feaas-component fetch="template data" library="L" cdn="CDN" component="C1" version="V" revision="R"></feaas-component>'
|
|
232
384
|
|
|
233
385
|
const component = document.body.firstElementChild as FEAASComponent
|
|
234
386
|
await expect(component.whenRendered).resolves.toEqual(component)
|
|
@@ -302,7 +454,7 @@ describe('Components', () => {
|
|
|
302
454
|
}
|
|
303
455
|
}
|
|
304
456
|
})
|
|
305
|
-
|
|
457
|
+
|
|
306
458
|
document.body.innerHTML = '<feaas-component src="L/C"></feaas-component>'
|
|
307
459
|
const component = document.body.firstElementChild as FEAASComponent
|
|
308
460
|
expect(document.head.querySelector('style')).toBeNull()
|
|
@@ -154,7 +154,7 @@ describe('React', function () {
|
|
|
154
154
|
it('should nest components into context', async () => {
|
|
155
155
|
const renders = [] as FEAASElement[]
|
|
156
156
|
class FEAASElementTestRenderOrder extends FEAASElement {
|
|
157
|
-
render(props: any, payload: any): ReactNode
|
|
157
|
+
render(props: any, payload: any): ReactNode {
|
|
158
158
|
return null
|
|
159
159
|
}
|
|
160
160
|
load() {
|