Skip to content

Commit

Permalink
Merge pull request #50 from TRIPTYK/tk-139
Browse files Browse the repository at this point in the history
Tk 139
  • Loading branch information
Brenion authored Aug 28, 2024
2 parents 80f1f37 + 6164d17 commit 6c7af43
Show file tree
Hide file tree
Showing 112 changed files with 14,262 additions and 10,619 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
.tpk-input[data-has-error="true"] > input {
@apply border-red-300 text-red-900 placeholder-red-300 focus:ring-red-500 focus:border-red-500;
}

.tpk-input-validation-toggle-button {
@apply absolute top-11 right-4 w-12 flex justify-center;
}
3 changes: 3 additions & 0 deletions doc-app/tests/dummy/public/assets/icons/eye-shut.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions doc-app/tests/dummy/public/assets/icons/eye.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { hbs } from 'ember-cli-htmlbars';
import {
type TestContext,
fillIn,
click,
findAll,
render,
settled,
Expand All @@ -16,39 +17,48 @@ module('Integration | Component | tpk-validation-input', function (hooks) {

async function renderComponent() {
await render(
hbs`<TpkValidationInput data-test-validation-input @classless={{this.classless}} @label="label" @onChange={{this.onChange}} @changeset={{this.changeset}} @validationField="name" as |I|>
<I.Label>
label
</I.Label>
<I.Input/>
</TpkValidationInput>`,
hbs`<TpkValidationInput @showTogglePasswordButton={{this.showTogglePasswordButton}} @type={{this.type}} data-test-validation-input @classless={{this.classless}} @label="label" @onChange={{this.onChange}} @changeset={{this.changeset}} @validationField="name" />`,
);
}

async function renderYieldedComponent() {
await render(
hbs`<TpkValidationInput @showTogglePasswordButton={{this.showTogglePasswordButton}} @type={{this.type}} data-test-validation-input @classless={{this.classless}} @label="yieldedLabel" @onChange={{this.onChange}} @changeset={{this.changeset}} @validationField="name" as |I| >
<I.Label/>
<I.Input/>
</TpkValidationInput>
`,
);
}

function setupChangeset(this: TestContext) {
const changeset = new ImmerChangeset({
name: 'a',
name: 'value',
});

this.set('changeset', changeset);
return changeset;
}

function setType(this: TestContext, type: string) {
this.set('type', type);
}

test('It changes data-has-error attribue on error', async function (assert) {
const changeset = setupChangeset.call(this);

await renderComponent();
assert.dom('[data-test-tpk-input]').exists();
assert.dom('[data-test-tpk-input-label]').containsText('label');
assert.dom('[data-test-tpk-input-input]').hasValue('a');
assert.dom('[data-test-tpk-input-input]').hasValue('value');

await fillIn('[data-test-tpk-input-input]', '');
assert.strictEqual(changeset.get('name'), '');

changeset.addError({
message: 'required',
value: '',
originalValue: 'a',
originalValue: 'value',
key: 'name',
});

Expand All @@ -65,21 +75,70 @@ module('Integration | Component | tpk-validation-input', function (hooks) {
assert.strictEqual(value, 'blah');
assert.strictEqual(
changeset.get('name'),
'a',
'value',
'Value not changed in the changeset',
);
});

await renderComponent();

await fillIn('[data-test-validation-input] input', 'blah');
assert.verifySteps(['change']);
});

test('Classless removes all the classes', async function (assert) {
test('renders generic input validation', async function (assert) {
const changeset = setupChangeset.call(this);

await renderComponent();
assert.dom('[data-test-input-not-yielded]').exists();
assert.dom('[data-test-label-not-yielded]').exists();
assert.dom('[data-test-label-not-yielded]').containsText('label');
assert.dom('[data-test-input-not-yielded]').hasValue('value');

assert.strictEqual(changeset.get('name'), 'value');
});

test('it overrides generic input by yielded one', async function (assert) {
const changeset = setupChangeset.call(this);

await renderYieldedComponent();
assert.dom('[data-test-input-not-yielded]').doesNotExist();
assert.dom('[data-test-label-not-yielded]').doesNotExist();
assert.dom('[data-test-tpk-input]').exists();
assert.dom('[data-test-tpk-input-label]').containsText('yieldedLabel');
await fillIn('[data-test-tpk-input-input]', 'yieldedValue');
assert.dom('[data-test-tpk-input-input]').hasValue('yieldedValue');
});

test('it passes showTogglePasswordButton to show or hide Toggle button', async function (assert) {
setType.call(this, 'password');
setupChangeset.call(this);
this.set('classless', false);
await renderComponent();
assert.dom('[data-test-toggle-button]').doesNotExist();
this.set('showTogglePasswordButton', true);
assert.dom('[data-test-toggle-button]').exists();
assert
.dom('[data-test-validation-input] input')
.hasAttribute('type', 'password');
});

test('it changes type when click on toggleButton ', async function (assert) {
setType.call(this, 'password');
setupChangeset.call(this);
this.set('classless', false);
this.set('showTogglePasswordButton', true);
await renderComponent();
assert
.dom('[data-test-validation-input] input')
.hasAttribute('type', 'password');
await click('[data-test-toggle-button]');
assert.dom('[data-test-validation-input] input').hasAttribute('type', '');
});

test('Classless removes all the classes', async function (assert) {
this.set('classless', false);
this.set('showTogglePasswordButton', true);
setupChangeset.call(this);
await renderComponent();

findAll('*')
Expand All @@ -89,7 +148,6 @@ module('Integration | Component | tpk-validation-input', function (hooks) {
});

this.set('classless', true);

findAll('*').forEach((e) => {
assert.dom(e).hasNoClass(/tpk-.*/);
});
Expand All @@ -100,10 +158,10 @@ module('Integration | Component | tpk-validation-input', function (hooks) {

this.set('onChange', (value: string) => {
assert.step('change');
assert.strictEqual(value, 'blah');
assert.strictEqual(value, 'valueChanged');
assert.strictEqual(
changeset.get('name'),
'a',
'value',
'Value not changed in the changeset',
);
});
Expand All @@ -115,16 +173,11 @@ module('Integration | Component | tpk-validation-input', function (hooks) {
@onChange={{this.onChange}}
@changeset={{this.changeset}}
@validationField="name"
data-test-input="name" as |TI|
>
<TI.Label>
Mot de passe
</TI.Label>
<TI.Input/>
</TpkValidationInput>`,
data-test-input="name"
/>`,
);

await fillIn('[data-test-input="name"] input', 'blah');
await fillIn('[data-test-input="name"] input', 'valueChanged');
assert.verifySteps(['change']);
});

Expand All @@ -146,7 +199,7 @@ module('Integration | Component | tpk-validation-input', function (hooks) {
</TpkValidationInput>`,
);

await fillIn('[data-test-input="name"] input', 'blah');
assert.strictEqual(changeset.get('name'), 'blah');
await fillIn('[data-test-input="name"] input', 'valueChanged');
assert.strictEqual(changeset.get('name'), 'valueChanged');
});
});
25 changes: 21 additions & 4 deletions doc-app/tests/integration/components/ember-input/tpk-input-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ module('Integration | Component | tpk-input', function (hooks) {
test('class/less by default', async function (assert) {
this.set('classless', false);
await render(
hbs`<TpkInput @classless={{this.classless}} @label="label" @value="value" as |I|>
<I.Input />
<I.Label />
</TpkInput>`,
hbs`<TpkInput @classless={{this.classless}} @label="label" @value="value" />`,
);

assert.dom('.tpk-input-label').exists().containsText('label');
Expand All @@ -33,6 +30,26 @@ module('Integration | Component | tpk-input', function (hooks) {
});
});

test('class/has block element yield', async function (assert) {
await render(
hbs`<TpkInput @classless={{this.classless}} @label="label" @value="value" as |I|>
<I.Input />
<I.Label />
</TpkInput>`,
);
assert.dom('.tpk-input-label').exists().containsText('label');
assert.dom('.tpk-input-input').exists().hasValue('value');
assert.dom('.tpk-input').exists();

this.set('classless', true);

findAll('*')
.filter((e) => e.id !== 'modal-overlays')
.forEach((e) => {
assert.dom(e).hasNoClass(/tpk-.*/);
});
});

test('input yield only', async function (assert) {
await render(
hbs`<TpkInput @type="password" @onChange={{this.change}} @label="label" @value="value" as |O|>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { action } from '@ember/object';
import { type BaseValidationSignature, BaseValidationComponent } from './base.ts';
import type {TpkInputSignature} from '@triptyk/ember-input/components/tpk-input';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
import {
type BaseValidationSignature,
BaseValidationComponent,
} from './base.ts';
import type { TpkInputSignature } from '@triptyk/ember-input/components/tpk-input';
import TpkInput from '@triptyk/ember-input/components/tpk-input';
import { hash } from '@ember/helper';

Expand All @@ -15,12 +20,18 @@ export interface TpkValidationInputComponentSignature
unmaskValue?: boolean;
disabled?: boolean;
changeEvent?: 'input' | 'change';
showTogglePasswordButton?: boolean;
step?: number;
min?: number;
maxlength?: number;
mandatory?: boolean;
placeholder?: string;
};
Blocks: {
default: [
{
Input: TpkInputSignature['Blocks']['default'][0]['Input'];
Label: TpkInputSignature['Blocks']['default'][0]['Label'];
Input?: TpkInputSignature['Blocks']['default'][0]['Input'];
Label?: TpkInputSignature['Blocks']['default'][0]['Label'];
errors: TpkValidationInputComponent['errors'];
hasError: TpkValidationInputComponent['hasError'];
firstError: TpkValidationInputComponent['firstError'];
Expand All @@ -31,13 +42,26 @@ export interface TpkValidationInputComponentSignature
}

export default class TpkValidationInputComponent extends BaseValidationComponent<TpkValidationInputComponentSignature> {
@tracked showPassword = false;
@action onChange(value: string | number | Date | null) {
if (this.args.onChange) {
return this.args.onChange(value);
}
return this.args.changeset.set(this.args.validationField, value);
}

get type() {
if (this.showPassword) {
return '';
}
return this.args.type;
}

@action
togglePassword() {
this.showPassword = !this.showPassword;
}

get value() {
return super.value as string;
}
Expand All @@ -46,7 +70,7 @@ export default class TpkValidationInputComponent extends BaseValidationComponent
<TpkInput
@value={{this.value}}
@label={{@label}}
@type={{@type}}
@type={{this.type}}
@onChange={{this.onChange}}
@classless={{@classless}}
@changeEvent={{@changeEvent}}
Expand All @@ -57,15 +81,68 @@ export default class TpkValidationInputComponent extends BaseValidationComponent
data-has-error='{{this.hasError}}'
as |I|
>
{{yield
(hash
Input=I.Input
Label=I.Label
errors=this.errors
hasError=this.hasError
firstError=this.firstError
)
}}
{{#if (has-block)}}
{{yield
(hash
Input=I.Input
Label=I.Label
errors=this.errors
hasError=this.hasError
firstError=this.firstError
)
}}
{{else}}
<I.Label
class={{unless @classless 'tpk-input-validation-label'}}
data-test-label-not-yielded
>
{{@label}}
{{#if @mandatory}}
<span>
*
</span>
{{/if}}
</I.Label>
<I.Input
step={{@step}}
min={{@min}}
disabled={{@disabled}}
placeholder={{@placeholder}}
class={{unless @classless 'tpk-input-validation-input'}}
aria-autocomplete='none'
autocomplete='off'
autofill='off'
maxlength={{@maxlength}}
data-test-input-not-yielded
/>
{{yield
(hash
errors=this.errors hasError=this.hasError firstError=this.firstError
)
}}
{{/if}}
{{#if @showTogglePasswordButton}}
<button
type='button'
class={{unless @classless 'tpk-input-validation-toggle-button'}}
title={{if this.showPassword 'show' 'hide'}}
{{on 'click' this.togglePassword}}
data-test-toggle-button
>
<img
src={{if
this.showPassword
'/assets/icons/eye-shut.svg'
'/assets/icons/eye.svg'
}}
alt='eye'
class={{unless
@classless
'tpk-input-validation-toggle-button-image'
}}
/>
</button>
{{/if}}
</TpkInput>
</template>
}
Loading

0 comments on commit 6c7af43

Please sign in to comment.