Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 115 additions & 14 deletions packages/main/cypress/specs/MultiComboBox.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1495,18 +1495,18 @@ describe("Validation & Value State", () => {
cy.realType("4");

cy.get("@input")
.should("have.value", "1");
.should("have.value", "14");

cy.get("@mcb")
.should("have.attr", "value-state", "Negative");
});

it("Reset value state validation after 2500ms", () => {
it("Invalid input persists - no automatic clearing", () => {
cy.mount(
<MultiComboBox>
<MultiComboBoxItem text="112"></MultiComboBoxItem>
<MultiComboBoxItem text="12"></MultiComboBoxItem>
<MultiComboBoxItem text="3"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 1"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 2"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 3"></MultiComboBoxItem>
</MultiComboBox>
);

Expand All @@ -1517,21 +1517,73 @@ describe("Validation & Value State", () => {
cy.get("@mcb")
.should("be.focused");

cy.realType("4");
cy.realType("InvalidText");

cy.get("@mcb")
.should("have.attr", "value-state", "Negative");

cy.wait(2500);
cy.get("@mcb")
.shadow()
.find("input")
.as("input")
.should("have.value", "InvalidText");

// Wait to test that the value state persists after some time
cy.wait(2500)

cy.get("@input")
.should("have.value", "InvalidText");

cy.get("@mcb")
.should("have.attr", "value-state", "Negative");
});

it("Value state resets when valid entry is entered after invalid input", () => {
cy.mount(
<MultiComboBox>
<MultiComboBoxItem text="Item 1"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 2"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 3"></MultiComboBoxItem>
</MultiComboBox>
);

cy.get("[ui5-multi-combobox]")
.as("mcb")
.realClick();

cy.get("@mcb")
.should("be.focused");

// Type invalid text
cy.realType("xyz");

cy.get("@mcb")
.should("have.attr", "value-state", "Negative");

cy.get("@mcb")
.shadow()
.find("input")
.as("input")
.should("have.value", "xyz");

// Clear and type valid text
cy.get("@input")
.clear();

cy.realType("Item");

cy.get("@mcb")
.should("have.attr", "value-state", "None");

cy.get("@input")
.should("have.value", "Item 1");
});

it("Built in validation by typing a non existing option", () => {
it("Value state resets when input is cleared after invalid entry", () => {
cy.mount(
<MultiComboBox>
<MultiComboBoxItem text="Cosy"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 1"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 2"></MultiComboBoxItem>
</MultiComboBox>
);

Expand All @@ -1542,12 +1594,64 @@ describe("Validation & Value State", () => {
cy.get("@mcb")
.should("be.focused");

cy.realType("CCo");
// Type invalid text
cy.realType("InvalidValue");

cy.get("@mcb")
.should("have.attr", "value-state", "Negative");

cy.get("@mcb")
.shadow()
.find("input")
.should("have.value", "Cosy");
.as("input")
.should("have.value", "InvalidValue");

// Clear the input
cy.get("@input")
.clear();

cy.get("@mcb")
.should("have.attr", "value-state", "None");

cy.get("@input")
.should("have.value", "");
});

it("Value state preserved when switching between valid and invalid", () => {
cy.mount(
<MultiComboBox valueState="Critical">
<MultiComboBoxItem text="Item 1"></MultiComboBoxItem>
<MultiComboBoxItem text="Item 2"></MultiComboBoxItem>
</MultiComboBox>
);

cy.get("[ui5-multi-combobox]")
.as("mcb")
.realClick();

cy.get("@mcb")
.should("be.focused");

cy.get("@mcb")
.should("have.attr", "value-state", "Critical");

// Type invalid text
cy.realType("xyz");

cy.get("@mcb")
.should("have.attr", "value-state", "Negative");

cy.get("@mcb")
.shadow()
.find("input")
.as("input");

// Clear and verify original state is restored
cy.get("@input")
.clear();

cy.get("@mcb")
.should("have.attr", "value-state", "Critical");
});

it("Tests if item is created when enter is pressed while validation is ongoing", () => {
Expand Down Expand Up @@ -4214,7 +4318,6 @@ describe("MultiComboBox Composition", () => {
simulateCompositionStages(["ㄲ", "ㄲㅏ"], "까");

cy.get("@mcb").should("have.attr", "value-state", "Negative");
cy.get("@input").should("have.value", "");
cy.get("@mcb")
.shadow()
.find("[ui5-tokenizer] [ui5-token]")
Expand Down Expand Up @@ -4248,7 +4351,6 @@ describe("MultiComboBox Composition", () => {

simulateCompositionStages(["ず", "ずx"], "ずx");
cy.get("@mcb").should("have.attr", "value-state", "Negative");
cy.get("@input").should("have.value", "");
cy.get("@mcb")
.shadow()
.find("[ui5-tokenizer] [ui5-token]")
Expand Down Expand Up @@ -4284,7 +4386,6 @@ describe("MultiComboBox Composition", () => {

simulateCompositionStages(["p", "pi", "pin"], "品味");
cy.get("@mcb").should("have.attr", "value-state", "Negative");
cy.get("@input").should("have.value", "");
cy.get("@mcb")
.shadow()
.find("[ui5-tokenizer] [ui5-token]")
Expand Down
21 changes: 6 additions & 15 deletions packages/main/src/MultiComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,6 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
const input = e.target as HTMLInputElement;
const value: string = input.value;
const filteredItems: Array<IMultiComboBoxItem> = this._filterItems(value);
const oldValueState: `${ValueState}` = this.valueState;

this._shouldFilterItems = true;

Expand All @@ -721,24 +720,20 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
this.valueState = this._effectiveValueState;
this._validationTimeout = null;
} else {
input.value = this._inputLastValue;
return;
}
}

this._effectiveValueState = this.valueState;
// Save the original value state before setting validation error
if (this.valueState !== ValueState.Negative) {
this._effectiveValueState = this.valueState;
}

if (!this._isComposing && !filteredItems.length && value && !this.noValidation) {
const newValue = this.valueBeforeAutoComplete || this._inputLastValue;

input.value = newValue;
this.value = newValue;
this.valueState = ValueState.Negative;

this._shouldAutocomplete = false;
this._resetValueState(oldValueState);

return;
} else if ((filteredItems.length || !value) && this.valueState === ValueState.Negative) {
this.valueState = this._effectiveValueState;
}

if (!this._isComposing) {
Expand Down Expand Up @@ -1938,10 +1933,6 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
}

this._tokenizer.expanded = this.open;
// remove the value if user focus out the input and focus is not going in the popover
if (!isPhone() && !this.noValidation && !focusIsGoingInPopover) {
this.value = "";
}
}
}
/**
Expand Down
Loading