Skip to content

Commit

Permalink
Fixed non-string labels (fixes #816).
Browse files Browse the repository at this point in the history
  • Loading branch information
radekmie committed Oct 24, 2020
1 parent ab34011 commit 75aef5c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 19 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Next

- **Fixed:** Regression of accepting non-string labels in `useField` and `connectField`. [\#816](https://github.com/vazco/uniforms/issues/816)

## [v3.0.0-rc.5](https://github.com/vazco/uniforms/tree/v3.0.0-rc.5) (2020-09-30)

- **Added:** New `disableItem` prop in `SelectField`. [\#736](https://github.com/vazco/uniforms/issues/736)
Expand Down
59 changes: 58 additions & 1 deletion packages/uniforms/__tests__/connectField.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { ReactNode } from 'react';
import { SimpleSchema } from 'simpl-schema';
import { Context, connectField, randomIds } from 'uniforms';
import { SimpleSchemaBridge } from 'uniforms-bridge-simple-schema';
Expand Down Expand Up @@ -125,4 +125,61 @@ describe('connectField', () => {
expect(onChange).toBeCalledWith('field', 'initialValueExample');
});
});

// TODO: Write tests for `placeholder`.
describe('when rendered with label', () => {
const labelA = <span style={{ color: 'red' }}>Error</span>;
const labelB = <span style={{ color: 'green' }}>OK</span>;

it.each([
['Props', '', false, 'Props'],
['Props', '', true, 'Props'],
['Props', 'Schema', false, 'Props'],
['Props', 'Schema', true, 'Props'],
['Props', labelB, false, 'Props'],
['Props', labelB, true, 'Props'],
[false, '', false, ''],
[false, '', true, ''],
[false, 'Schema', false, ''],
[false, 'Schema', true, ''],
[false, labelB, false, ''],
[false, labelB, true, ''],
[labelA, '', false, labelA],
[labelA, '', true, labelA],
[labelA, 'Schema', false, labelA],
[labelA, 'Schema', true, labelA],
[labelA, labelB, false, labelA],
[labelA, labelB, true, labelA],
[true, '', false, ''],
[true, '', true, ''],
[true, 'Schema', false, 'Schema'],
[true, 'Schema', true, 'Schema'],
[true, labelB, false, labelB],
[true, labelB, true, labelB],
[undefined, '', false, ''],
[undefined, '', true, ''],
[undefined, 'Schema', false, ''],
[undefined, 'Schema', true, 'Schema'],
[undefined, labelB, false, ''],
[undefined, labelB, true, labelB],
] as [ReactNode, ReactNode, boolean, ReactNode][])(
'resolves it correctly (%#)',
(prop, schema, state, result) => {
const context: typeof reactContext = {
context: {
...reactContext.context,
state: { ...reactContext.context.state, label: state },
},
};

jest
.spyOn(context.context.schema, 'getProps')
.mockReturnValueOnce({ label: schema });

const Field = connectField(Test);
const wrapper = mount(<Field name="field" label={prop} />, context);
expect(wrapper.find(Test).prop('label')).toBe(result);
},
);
});
});
38 changes: 20 additions & 18 deletions packages/uniforms/src/useField.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
import get from 'lodash/get';
import mapValues from 'lodash/mapValues';
import { useCallback, useEffect, useMemo } from 'react';
import { ReactNode, useCallback, useEffect, useMemo } from 'react';

import { joinName } from './joinName';
import { GuaranteedProps } from './types';
import { useForm } from './useForm';

function propagate(
prop: unknown,
schema: unknown,
prop: ReactNode,
schema: ReactNode,
state: boolean,
fallback: string,
): [string, string] {
const schemaDisabled = schema === false || schema === '';
const schemaValue =
typeof schema === 'string' ? schema : schemaDisabled ? '' : fallback;
const resultValue =
typeof prop === 'string'
? prop
: prop === null ||
prop === false ||
(prop === undefined && !state) ||
schemaDisabled
fallback: ReactNode,
): [ReactNode, ReactNode] {
const forcedFallbackInProp = prop === true || prop === undefined;
const forcedFallbackInSchema = schema === true || schema === undefined;

const schemaValue = forcedFallbackInSchema ? fallback : schema;
const value =
prop === '' ||
prop === false ||
(forcedFallbackInProp && (forcedFallbackInSchema || !state))
? ''
: schemaValue;
return [resultValue, schemaValue];
: forcedFallbackInProp
? schemaValue
: prop;

return [value, schemaValue];
}

export function useField<
Expand Down Expand Up @@ -112,7 +113,8 @@ export function useField<
...props,
label,
name,
placeholder,
// TODO: Should we assert `typeof placeholder === 'string'`?
placeholder: placeholder as string,
};

return [fieldProps, context] as [typeof fieldProps, typeof context];
Expand Down

0 comments on commit 75aef5c

Please sign in to comment.