-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathAgate-View.js
More file actions
169 lines (133 loc) · 5.05 KB
/
Copy pathAgate-View.js
File metadata and controls
169 lines (133 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import classnames from 'classnames/bind';
import spotlight from '@enact/spotlight';
import {urlParamsToObject} from '@enact/ui-test-utils/utils';
import {cloneElement, Component as ReactComponent, useEffect} from 'react';
import ThemeDecorator from '../../../ThemeDecorator';
import {agateComponents, agateTestMetadata} from './AgateComponents';
import AgateImports from './importer';
import css from './Agate-View.less';
const url = new URL(window.location.href);
// Bind our classnames against css modules
const cx = classnames.bind(css);
const LoremString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac tellus in velit ornare commodo. Nam dignissim fringilla nulla, sit amet hendrerit sapien laoreet quis. Praesent quis tellus non diam viverra feugiat.';
spotlight.setPointerMode(true);
const parsed = urlParamsToObject();
function getWrapperClasses ({wrapper}) {
return cx('wrapper', wrapper, parsed.skin);
}
function getWrapperStyle ({wrapper = {}}) {
const {padded} = wrapper;
if (padded && padded !== true) {
return {'--wrapper-padding': padded};
}
}
function prepareTest (componentName, testId) {
const ElementProps = {
'data-ui-test-id': 'test',
style: {outlineColor: 'lime'},
className: css.outline
};
if (!agateComponents[componentName] || !agateComponents[componentName][testId]) {
return {
testElement: <div>INVALID COMPONENT OR TEST ID</div>,
wrapperClasses: css.error
};
}
let component = agateComponents[componentName][testId];
// If test wants focus, set mode to 5-way so autofocus works
if (component.focus) {
spotlight.setPointerMode(false);
}
// If this is a complex test (not a bare component), extract component for cloning
if (component.component) {
component = component.component;
}
let children = component.props.children;
if (children === '-Lorem') {
children = LoremString;
}
// TODO: extract back to test and in metadata converter unpack date?
if (component.props.defaultValue && /\d{4}-\d{2}-\d{2}/.test(component.props.defaultValue)) {
ElementProps.defaultValue = new Date(component.props.defaultValue);
}
return {
testElement: cloneElement(component, ElementProps, children),
wrapperClasses: getWrapperClasses(agateComponents[componentName][testId]),
wrapperStyle: getWrapperStyle(agateComponents[componentName][testId])
};
}
function prepareFromUrl () {
// Naively, assuming parsed in the form of: {component: 'ComponentName', props: {}}
const Component = AgateImports[parsed.component];
const componentProps = parsed.props || {};
const wrapperProps = parsed.wrapper || {};
if (componentProps.children === '-Lorem') {
componentProps.children = LoremString;
}
if (componentProps.defaultValue && /\d{4}-\d{2}-\d{2}/.test(componentProps.defaultValue)) {
componentProps.defaultValue = new Date(componentProps.defaultValue);
}
return {
testElement: <Component {...componentProps} />,
wrapperClasses: getWrapperClasses({skin: parsed.skin, wrapper: wrapperProps}),
wrapperStyle: getWrapperStyle({skin: parsed.skin, wrapper: wrapperProps})
};
}
class App extends ReactComponent {
static getDerivedStateFromError () {
// Update state so the next render will show the fallback UI.
return {hasError: true};
}
constructor (props) {
super(props);
this.state = {hasError: false};
}
render () {
const {component, testId, locale, ...props} = this.props;
let testElement;
let wrapperClasses, wrapperStyle;
if (this.state.hasError) {
return (
<div {...props}>
<div className={css.error}>
ERROR IN {component} test {testId}
</div>
</div>
);
}
if (testId >= 0) {
({testElement, wrapperClasses, wrapperStyle} = prepareTest(component, testId, locale));
} else {
({testElement, wrapperClasses, wrapperStyle} = prepareFromUrl());
}
return (
<div {...props}>
<div className={wrapperClasses} style={wrapperStyle}>{testElement}</div>
</div>
);
}
}
// Declared at module scope, so the components are not created during render (react-hooks/static-components).
const WrappedAgateAppAutoFocus = ThemeDecorator({noAutoFocus: false}, App);
const WrappedAgateAppNoAutoFocus = ThemeDecorator({noAutoFocus: true}, App);
const ExportedAgateApp = (props) => {
// Common test parameters
const skin = url.searchParams.get('skin');
const skinVariants = JSON.parse(url.searchParams.get('skinVariants'));
// Legacy test parameters
let locale = url.searchParams.get('locale');
let noAutoFocus = true;
if (props.testId >= 0 && agateComponents[props.component] && agateComponents[props.component][props.testId]) {
locale = agateComponents[props.component][props.testId].locale;
noAutoFocus = !agateComponents[props.component][props.testId].focus;
}
const WrappedAgateApp = noAutoFocus ? WrappedAgateAppNoAutoFocus : WrappedAgateAppAutoFocus;
useEffect(() => {
document.querySelector('#root > div').classList.add('spotlight-input-key');
}, []);
return (
<WrappedAgateApp {...props} skin={skin} skinVariants={skinVariants} locale={locale} />
);
};
export default ExportedAgateApp;
export {agateComponents as components, agateTestMetadata as testMetadata};