Improve tests (#854)

Recover commented out tests, 
Improve usage of helper in driver, 
Added data-wd-key for test to use instead of classes
Moved all non tsx file to a single folder (lib) instead of lib and utils

---------

Co-authored-by: Yuri Astrakhan <yuriastrakhan@gmail.com>
This commit is contained in:
Harel M
2023-12-27 10:19:59 +02:00
committed by GitHub
parent 09a1f3f87b
commit b784bf2b84
31 changed files with 62 additions and 405 deletions

View File

@@ -71,7 +71,7 @@ export default class MaputnikDriver {
if (styleProperties) { if (styleProperties) {
cy.on("window:confirm", () => true); cy.on("window:confirm", () => true);
} }
cy.get(".maputnik-toolbar-link").should("be.visible"); this.helper.get.element("toolbar:link").should("be.visible");
}, },
fillLayersModal: (opts: {type: string, layer?: string, id?: string}) => { fillLayersModal: (opts: {type: string, layer?: string, id?: string}) => {
var type = opts.type; var type = opts.type;
@@ -83,22 +83,24 @@ export default class MaputnikDriver {
id = `${type}:${uuid()}`; id = `${type}:${uuid()}`;
} }
cy.get( this.helper.get.element("add-layer.layer-type.select").select(type);
this.get.dataAttribute("add-layer.layer-type", "select") this.helper.get.element("add-layer.layer-id.input").type(id);
).select(type);
cy.get(this.get.dataAttribute("add-layer.layer-id", "input")).type(id);
if (layer) { if (layer) {
cy.get( this.when.within("add-layer.layer-source-block", () => {
this.get.dataAttribute("add-layer.layer-source-block", "input") cy.get("input").type(layer!);
).type(layer); })
} }
this.when.click("add-layer"); this.when.click("add-layer");
return id; return id;
}, },
typeKeys: (keys: string) => { typeKeys: (keys: string, selector?: string) => {
cy.get("body").type(keys); if (selector) {
this.helper.get.element(selector).type(keys);
} else {
cy.get("body").type(keys);
}
}, },
click: (selector: string) => { click: (selector: string) => {
@@ -124,7 +126,7 @@ export default class MaputnikDriver {
}, },
setValue: (selector: string, text: string) => { setValue: (selector: string, text: string) => {
cy.get(selector).clear().type(text, { parseSpecialCharSequences: false }); this.helper.get.element(selector).clear().type(text, { parseSpecialCharSequences: false });
}, },
closeModal: (key: string) => { closeModal: (key: string) => {
@@ -135,8 +137,8 @@ export default class MaputnikDriver {
openLayersModal: () => { openLayersModal: () => {
this.helper.when.click("layer-list:add-layer"); this.helper.when.click("layer-list:add-layer");
cy.get(this.get.dataAttribute("modal:add-layer")).should("exist"); this.helper.get.element("modal:add-layer").should("exist");
cy.get(this.get.dataAttribute("modal:add-layer")).should("be.visible"); this.helper.get.element("modal:add-layer").should("be.visible");
}, },
}; };
@@ -153,9 +155,6 @@ export default class MaputnikDriver {
exampleFileUrl: () => { exampleFileUrl: () => {
return "http://localhost:8888/example-style.json"; return "http://localhost:8888/example-style.json";
}, },
dataAttribute: (key: string, selector?: string): string => {
return `*[data-wd-key='${key}'] ${selector || ""}`;
},
}; };
public should = { public should = {

View File

@@ -134,10 +134,7 @@ describe("layers", () => {
var id = uuid(); var id = uuid();
when.selectWithin("add-layer.layer-type", "background"); when.selectWithin("add-layer.layer-type", "background");
when.setValue( when.setValue("add-layer.layer-id.input", "background:" + id);
get.dataAttribute("add-layer.layer-id", "input"),
"background:" + id
);
when.click("add-layer"); when.click("add-layer");
@@ -162,10 +159,7 @@ describe("layers", () => {
when.click("layer-list-item:background:" + bgId); when.click("layer-list-item:background:" + bgId);
var id = uuid(); var id = uuid();
when.setValue( when.setValue("layer-editor.layer-id.input", "foobar:" + id);
get.dataAttribute("layer-editor.layer-id", "input"),
"foobar:" + id
);
when.click("min-zoom"); when.click("min-zoom");
should.equalStyleStore( should.equalStyleStore(
@@ -183,10 +177,7 @@ describe("layers", () => {
var bgId = createBackground(); var bgId = createBackground();
when.click("layer-list-item:background:" + bgId); when.click("layer-list-item:background:" + bgId);
when.setValue( when.setValue("min-zoom.input-text", "1");
get.dataAttribute("min-zoom", 'input[type="text"]'),
"1"
);
when.click("layer-editor.layer-id"); when.click("layer-editor.layer-id");
@@ -202,25 +193,20 @@ describe("layers", () => {
); );
// AND RESET! // AND RESET!
// driver.setValue(driver.get.dataAttribute("min-zoom", "input"), "") when.typeKeys("{backspace}", "min-zoom.input-text");
// driver.click(driver.get.dataAttribute("max-zoom", "input")); when.click("max-zoom.input-text");
// driver.isStyleStoreEqual((a: any) => a.layers, [ should.equalStyleStore((a: any) => a.layers, [{
// { "id": 'background:'+bgId,
// "id": 'background:'+bgId, "type": 'background'
// "type": 'background' }]);
// }
// ]);
}); });
it("max-zoom", () => { it("max-zoom", () => {
var bgId = createBackground(); var bgId = createBackground();
when.click("layer-list-item:background:" + bgId); when.click("layer-list-item:background:" + bgId);
when.setValue( when.setValue("max-zoom.input-text", "1");
get.dataAttribute("max-zoom", 'input[type="text"]'),
"1"
);
when.click("layer-editor.layer-id"); when.click("layer-editor.layer-id");
@@ -238,10 +224,10 @@ describe("layers", () => {
it("comments", () => { it("comments", () => {
var bgId = createBackground(); var bgId = createBackground();
var id = uuid(); var comment = "42";
when.click("layer-list-item:background:" + bgId); when.click("layer-list-item:background:" + bgId);
when.setValue(get.dataAttribute("layer-comment", "textarea"), id); when.setValue("layer-comment.input", comment);
when.click("layer-editor.layer-id"); when.click("layer-editor.layer-id");
@@ -252,23 +238,20 @@ describe("layers", () => {
id: "background:" + bgId, id: "background:" + bgId,
type: "background", type: "background",
metadata: { metadata: {
"maputnik:comment": id, "maputnik:comment": comment,
}, },
}, },
] ]
); );
// Unset it again. // Unset it again.
// TODO: This fails when.typeKeys("{backspace}{backspace}", "layer-comment.input");
// driver.setValue(driver.getDataAttribute("layer-comment", "textarea"), ""); when.click("min-zoom.input-text");
// driver.click(driver.getDataAttribute("min-zoom", "input"));
// driver.isStyleStoreEqual((a: any) => a.layers, [ should.equalStyleStore((a: any) => a.layers, [{
// { "id": 'background:' + bgId,
// "id": 'background:'+bgId, "type": 'background'
// "type": 'background' }]);
// }
// ]);
}); });
it("color", () => { it("color", () => {

View File

@@ -26,7 +26,7 @@ describe("modals", () => {
it("load from url", () => { it("load from url", () => {
var styleFileUrl = get.exampleFileUrl(); var styleFileUrl = get.exampleFileUrl();
when.setValue(get.dataAttribute("modal:open.url.input"), styleFileUrl); when.setValue("modal:open.url.input", styleFileUrl);
when.click("modal:open.url.button"); when.click("modal:open.url.button");
when.waitForExampleFileRequset(); when.waitForExampleFileRequset();
@@ -83,30 +83,27 @@ describe("modals", () => {
}); });
it("show name specifications", () => { it("show name specifications", () => {
when.setValue(get.dataAttribute("modal:settings.name"), "foobar"); when.setValue("modal:settings.name", "foobar");
when.click("modal:settings.owner"); when.click("modal:settings.owner");
should.equalStyleStore((obj) => obj.name, "foobar"); should.equalStyleStore((obj) => obj.name, "foobar");
}); });
it("owner", () => { it("owner", () => {
when.setValue(get.dataAttribute("modal:settings.owner"), "foobar"); when.setValue("modal:settings.owner", "foobar");
when.click("modal:settings.name"); when.click("modal:settings.name");
should.equalStyleStore((obj) => obj.owner, "foobar"); should.equalStyleStore((obj) => obj.owner, "foobar");
}); });
it("sprite url", () => { it("sprite url", () => {
when.setValue( when.setValue("modal:settings.sprite", "http://example.com");
get.dataAttribute("modal:settings.sprite"),
"http://example.com"
);
when.click("modal:settings.name"); when.click("modal:settings.name");
should.equalStyleStore((obj) => obj.sprite, "http://example.com"); should.equalStyleStore((obj) => obj.sprite, "http://example.com");
}); });
it("glyphs url", () => { it("glyphs url", () => {
var glyphsUrl = "http://example.com/{fontstack}/{range}.pbf"; var glyphsUrl = "http://example.com/{fontstack}/{range}.pbf";
when.setValue(get.dataAttribute("modal:settings.glyphs"), glyphsUrl); when.setValue("modal:settings.glyphs", glyphsUrl);
when.click("modal:settings.name"); when.click("modal:settings.name");
should.equalStyleStore((obj) => obj.glyphs, glyphsUrl); should.equalStyleStore((obj) => obj.glyphs, glyphsUrl);
@@ -115,9 +112,7 @@ describe("modals", () => {
it("maptiler access token", () => { it("maptiler access token", () => {
var apiKey = "testing123"; var apiKey = "testing123";
when.setValue( when.setValue(
get.dataAttribute( "modal:settings.maputnik:openmaptiles_access_token",
"modal:settings.maputnik:openmaptiles_access_token"
),
apiKey apiKey
); );
when.click("modal:settings.name"); when.click("modal:settings.name");
@@ -130,12 +125,7 @@ describe("modals", () => {
it("thunderforest access token", () => { it("thunderforest access token", () => {
var apiKey = "testing123"; var apiKey = "testing123";
when.setValue( when.setValue("modal:settings.maputnik:thunderforest_access_token", apiKey);
get.dataAttribute(
"modal:settings.maputnik:thunderforest_access_token"
),
apiKey
);
when.click("modal:settings.name"); when.click("modal:settings.name");
should.equalStyleStore( should.equalStyleStore(

View File

@@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import {formatLayerId} from '../util/format'; import {formatLayerId} from '../libs/format';
import {LayerSpecification, StyleSpecification} from 'maplibre-gl'; import {LayerSpecification, StyleSpecification} from 'maplibre-gl';
type AppMessagePanelProps = { type AppMessagePanelProps = {

View File

@@ -36,6 +36,7 @@ class ToolbarLink extends React.Component<ToolbarLinkProps> {
href={this.props.href} href={this.props.href}
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
data-wd-key="toolbar:link"
> >
{this.props.children} {this.props.children}
</a> </a>
@@ -56,6 +57,7 @@ class ToolbarLinkHighlighted extends React.Component<ToolbarLinkHighlightedProps
href={this.props.href} href={this.props.href}
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
data-wd-key="toolbar:link-highlighted"
> >
<span className="maputnik-toolbar-link-wrapper"> <span className="maputnik-toolbar-link-wrapper">
{this.props.children} {this.props.children}

View File

@@ -26,6 +26,7 @@ export default class FieldComment extends React.Component<FieldCommentProps> {
value={this.props.value} value={this.props.value}
onChange={this.props.onChange} onChange={this.props.onChange}
default="Comment..." default="Comment..."
data-wd-key="layer-comment.input"
/> />
</Block> </Block>
} }

View File

@@ -5,7 +5,7 @@ import DataProperty, { Stop } from './_DataProperty'
import ZoomProperty from './_ZoomProperty' import ZoomProperty from './_ZoomProperty'
import ExpressionProperty from './_ExpressionProperty' import ExpressionProperty from './_ExpressionProperty'
import {function as styleFunction} from '@maplibre/maplibre-gl-style-spec'; import {function as styleFunction} from '@maplibre/maplibre-gl-style-spec';
import {findDefaultFromSpec} from '../util/spec-helper'; import {findDefaultFromSpec} from '../libs/spec-helper';
function isLiteralExpression(value: any) { function isLiteralExpression(value: any) {

View File

@@ -20,6 +20,7 @@ export default class FieldId extends React.Component<FieldIdProps> {
<InputString <InputString
value={this.props.value} value={this.props.value}
onInput={this.props.onChange} onInput={this.props.onChange}
data-wd-key={this.props.wdKey + ".input"}
/> />
</Block> </Block>
} }

View File

@@ -23,6 +23,7 @@ export default class FieldMaxZoom extends React.Component<FieldMaxZoomProps> {
min={latest.layer.maxzoom.minimum} min={latest.layer.maxzoom.minimum}
max={latest.layer.maxzoom.maximum} max={latest.layer.maxzoom.maximum}
default={latest.layer.maxzoom.maximum} default={latest.layer.maxzoom.maximum}
data-wd-key="max-zoom.input"
/> />
</Block> </Block>
} }

View File

@@ -23,6 +23,7 @@ export default class FieldMinZoom extends React.Component<FieldMinZoomProps> {
min={latest.layer.minzoom.minimum} min={latest.layer.minzoom.minimum}
max={latest.layer.minzoom.maximum} max={latest.layer.minzoom.maximum}
default={latest.layer.minzoom.minimum} default={latest.layer.minzoom.minimum}
data-wd-key='min-zoom.input'
/> />
</Block> </Block>
} }

View File

@@ -44,6 +44,7 @@ export default class FieldType extends React.Component<FieldTypeProps> {
]} ]}
onChange={this.props.onChange} onChange={this.props.onChange}
value={this.props.value} value={this.props.value}
data-wd-key={this.props.wdKey + ".select"}
/> />
} }
</Block> </Block>

View File

@@ -8,7 +8,7 @@ import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/lib/codemirror.css' import 'codemirror/lib/codemirror.css'
import 'codemirror/addon/lint/lint.css' import 'codemirror/addon/lint/lint.css'
import stringifyPretty from 'json-stringify-pretty-compact' import stringifyPretty from 'json-stringify-pretty-compact'
import '../util/codemirror-mgl'; import '../libs/codemirror-mgl';
export type InputJsonProps = { export type InputJsonProps = {

View File

@@ -9,7 +9,7 @@ export type InputNumberProps = {
onChange?(value: number | undefined): unknown onChange?(value: number | undefined): unknown
allowRange?: boolean allowRange?: boolean
rangeStep?: number rangeStep?: number
wdKey?: string "data-wd-key"?: string
required?: boolean required?: boolean
"aria-label"?: string "aria-label"?: string
}; };
@@ -197,6 +197,7 @@ export default class InputNumber extends React.Component<InputNumberProps, Input
dirtyValue: this.state.value, dirtyValue: this.state.value,
}); });
}} }}
data-wd-key={this.props["data-wd-key"] + "-range"}
/> />
<input <input
key="text" key="text"
@@ -215,6 +216,8 @@ export default class InputNumber extends React.Component<InputNumberProps, Input
this.setState({editing: false}); this.setState({editing: false});
this.resetValue() this.resetValue()
}} }}
data-wd-key={this.props["data-wd-key"] + "-text"}
/> />
</div> </div>
} }
@@ -233,6 +236,7 @@ export default class InputNumber extends React.Component<InputNumberProps, Input
}} }}
onBlur={this.resetValue} onBlur={this.resetValue}
required={this.props.required} required={this.props.required}
data-wd-key={this.props["data-wd-key"]}
/> />
} }
} }

View File

@@ -18,7 +18,7 @@ import FieldSource from './FieldSource'
import FieldSourceLayer from './FieldSourceLayer' import FieldSourceLayer from './FieldSourceLayer'
import { changeType, changeProperty } from '../libs/layer' import { changeType, changeProperty } from '../libs/layer'
import layout from '../config/layout.json' import layout from '../config/layout.json'
import {formatLayerId} from '../util/format'; import {formatLayerId} from '../libs/format';
function getLayoutForType(type: LayerSpecification["type"]) { function getLayoutForType(type: LayerSpecification["type"]) {

View File

@@ -10,9 +10,9 @@ import InputSelect from './InputSelect'
import Block from './Block' import Block from './Block'
import docUid from '../libs/document-uid' import docUid from '../libs/document-uid'
import sortNumerically from '../libs/sort-numerically' import sortNumerically from '../libs/sort-numerically'
import {findDefaultFromSpec} from '../util/spec-helper'; import {findDefaultFromSpec} from '../libs/spec-helper';
import labelFromFieldName from './_labelFromFieldName' import labelFromFieldName from '../libs/label-from-field-name'
import DeleteStopButton from './_DeleteStopButton' import DeleteStopButton from './_DeleteStopButton'

View File

@@ -4,7 +4,7 @@ import stringifyPretty from 'json-stringify-pretty-compact'
import Block from './Block' import Block from './Block'
import InputButton from './InputButton' import InputButton from './InputButton'
import labelFromFieldName from './_labelFromFieldName' import labelFromFieldName from '../libs/label-from-field-name'
import FieldJson from './FieldJson' import FieldJson from './FieldJson'

View File

@@ -1,31 +0,0 @@
import React from 'react'
import Block from './Block'
import FieldString from './FieldString'
type BlockCommentProps = {
value?: string
onChange(...args: unknown[]): unknown
};
export default class BlockComment extends React.Component<BlockCommentProps> {
render() {
const fieldSpec = {
doc: "Comments for the current layer. This is non-standard and not in the spec."
};
return <Block
label={"Comments"}
fieldSpec={fieldSpec}
data-wd-key="layer-comment"
>
<FieldString
multi={true}
value={this.props.value}
onChange={this.props.onChange}
default="Comment..."
/>
</Block>
}
}

View File

@@ -1,61 +0,0 @@
import React from 'react'
import Block from './Block'
import FieldAutocomplete from './FieldAutocomplete'
type FieldFontProps = {
value?: string[]
default?: string[]
fonts?: unknown[]
style?: object
onChange(...args: unknown[]): unknown
label?: string
};
export default class FieldFont extends React.Component<FieldFontProps> {
static defaultProps = {
fonts: []
}
get values() {
const out = this.props.value || this.props.default || [];
// Always put a "" in the last field to you can keep adding entries
if (out[out.length-1] !== ""){
return out.concat("");
}
else {
return out;
}
}
changeFont(idx: number, newValue: string) {
const changedValues = this.values.slice(0)
changedValues[idx] = newValue
const filteredValues = changedValues
.filter(v => v !== undefined)
.filter(v => v !== "")
this.props.onChange(filteredValues);
}
render() {
const inputs = this.values.map((value, i) => {
return <li
key={i}
>
<FieldAutocomplete
value={value}
options={this.props.fonts!.map(f => [f, f])}
onChange={this.changeFont.bind(this, i)}
/>
</li>
})
return <Block label={this.props.label}>
<ul className="maputnik-font">
{inputs}
</ul>
</Block>
}
}

View File

@@ -1,27 +0,0 @@
import React from 'react'
import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block'
import FieldString from './FieldString'
type BlockIdProps = {
value: string
wdKey: string
onChange(...args: unknown[]): unknown
error?: {message: string}
};
export default class BlockId extends React.Component<BlockIdProps> {
render() {
return <Block label={"ID"} fieldSpec={latest.layer.id}
data-wd-key={this.props.wdKey}
error={this.props.error}
>
<FieldString
value={this.props.value}
onChange={this.props.onChange}
/>
</Block>
}
}

View File

@@ -1,30 +0,0 @@
import React from 'react'
import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block'
import FieldNumber from './FieldNumber'
type BlockMaxZoomProps = {
value?: number
onChange(...args: unknown[]): unknown
error?: {message: string}
};
export default class BlockMaxZoom extends React.Component<BlockMaxZoomProps> {
render() {
return <Block label={"Max Zoom"} fieldSpec={latest.layer.maxzoom}
error={this.props.error}
data-wd-key="max-zoom"
>
<FieldNumber
allowRange={true}
value={this.props.value}
onChange={this.props.onChange}
min={latest.layer.maxzoom.minimum}
max={latest.layer.maxzoom.maximum}
default={latest.layer.maxzoom.maximum}
/>
</Block>
}
}

View File

@@ -1,30 +0,0 @@
import React from 'react'
import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block'
import FieldNumber from './FieldNumber'
type BlockMinZoomProps = {
value?: number
onChange(...args: unknown[]): unknown
error?: {message: string}
};
export default class BlockMinZoom extends React.Component<BlockMinZoomProps> {
render() {
return <Block label={"Min Zoom"} fieldSpec={latest.layer.minzoom}
error={this.props.error}
data-wd-key="min-zoom"
>
<FieldNumber
allowRange={true}
value={this.props.value}
onChange={this.props.onChange}
min={latest.layer.minzoom.minimum}
max={latest.layer.minzoom.maximum}
default={latest.layer.minzoom.minimum}
/>
</Block>
}
}

View File

@@ -1,36 +0,0 @@
import React from 'react'
import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block'
import FieldAutocomplete from './FieldAutocomplete'
type BlockSourceProps = {
value?: string
wdKey?: string
onChange?(...args: unknown[]): unknown
sourceIds?: unknown[]
error?: {message: string}
};
export default class BlockSource extends React.Component<BlockSourceProps> {
static defaultProps = {
onChange: () => {},
sourceIds: [],
}
render() {
return <Block
label={"Source"}
fieldSpec={latest.layer.source}
error={this.props.error}
data-wd-key={this.props.wdKey}
>
<FieldAutocomplete
value={this.props.value}
onChange={this.props.onChange!}
options={this.props.sourceIds!.map(src => [src, src])}
/>
</Block>
}
}

View File

@@ -1,34 +0,0 @@
import React from 'react'
import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block'
import FieldAutocomplete from './FieldAutocomplete'
type BlockSourceLayerProps = {
value?: string
onChange?(...args: unknown[]): unknown
sourceLayerIds?: unknown[]
isFixed?: boolean
};
export default class BlockSourceLayer extends React.Component<BlockSourceLayerProps> {
static defaultProps = {
onChange: () => {},
sourceLayerIds: [],
isFixed: false
}
render() {
return <Block label={"Source Layer"} fieldSpec={latest.layer['source-layer']}
data-wd-key="layer-source-layer"
>
<FieldAutocomplete
keepMenuWithinWindowBounds={!!this.props.isFixed}
value={this.props.value}
onChange={this.props.onChange!}
options={this.props.sourceLayerIds!.map(l => [l, l])}
/>
</Block>
}
}

View File

@@ -1,25 +0,0 @@
import React from 'react'
import FieldAutocomplete from './FieldAutocomplete'
type FieldSymbolProps = {
value?: string
icons?: unknown[]
onChange(...args: unknown[]): unknown
};
export default class FieldSymbol extends React.Component<FieldSymbolProps> {
static defaultProps = {
icons: []
}
render() {
return <FieldAutocomplete
value={this.props.value}
options={this.props.icons!.map(f => [f, f])}
onChange={this.props.onChange}
/>
}
}

View File

@@ -1,52 +0,0 @@
import React from 'react'
import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block'
import FieldSelect from './FieldSelect'
import FieldString from './FieldString'
type BlockTypeProps = {
value: string
wdKey?: string
onChange(...args: unknown[]): unknown
error?: {message: string}
disabled?: boolean
};
export default class BlockType extends React.Component<BlockTypeProps> {
static defaultProps = {
disabled: false,
}
render() {
return <Block label={"Type"} fieldSpec={latest.layer.type}
data-wd-key={this.props.wdKey}
error={this.props.error}
>
{this.props.disabled &&
<FieldString
value={this.props.value}
disabled={true}
/>
}
{!this.props.disabled &&
<FieldSelect
options={[
['background', 'Background'],
['fill', 'Fill'],
['line', 'Line'],
['symbol', 'Symbol'],
['raster', 'Raster'],
['circle', 'Circle'],
['fill-extrusion', 'Fill Extrusion'],
['hillshade', 'Hillshade'],
['heatmap', 'Heatmap'],
]}
onChange={this.props.onChange}
value={this.props.value}
/>
}
</Block>
}
}

View File

@@ -3,7 +3,7 @@ import React from 'react'
import SpecField, {SpecFieldProps} from './SpecField' import SpecField, {SpecFieldProps} from './SpecField'
import FunctionButtons from './_FunctionButtons' import FunctionButtons from './_FunctionButtons'
import labelFromFieldName from './_labelFromFieldName' import labelFromFieldName from '../libs/label-from-field-name'
type SpecPropertyProps = SpecFieldProps & { type SpecPropertyProps = SpecFieldProps & {

View File

@@ -9,7 +9,7 @@ import InputSelect from './InputSelect'
import Block from './Block' import Block from './Block'
import DeleteStopButton from './_DeleteStopButton' import DeleteStopButton from './_DeleteStopButton'
import labelFromFieldName from './_labelFromFieldName' import labelFromFieldName from '../libs/label-from-field-name'
import docUid from '../libs/document-uid' import docUid from '../libs/document-uid'
import sortNumerically from '../libs/sort-numerically' import sortNumerically from '../libs/sort-numerically'