-
Notifications
You must be signed in to change notification settings - Fork 384
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Edit quote details (quote draft page) (#17730)
Closes CXSPA-4230
- Loading branch information
1 parent
0e1a6b1
commit 6c8cda1
Showing
17 changed files
with
1,262 additions
and
208 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2023 SAP Spartacus team <[email protected]> | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
export * from './quote-details-edit.component'; | ||
export * from './quote-details-edit.module'; |
66 changes: 66 additions & 0 deletions
66
feature-libs/quote/components/details/edit/quote-details-edit.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<div *ngIf="content" class="cx-card"> | ||
<!-- Card Body --> | ||
<div class="card-body cx-card-body cx-card-edit"> | ||
<!-- Card title --> | ||
<span class="cx-card-title"> | ||
{{ 'quote.details.information' | cxTranslate }} | ||
</span> | ||
<!-- Card Content --> | ||
<div class="cx-card-container"> | ||
<!-- Card Label --> | ||
<div class="cx-card-label-container"> | ||
<form [formGroup]="editForm"> | ||
<div class="cx-card-paragraph"> | ||
<div class="cx-card-paragraph-title"> | ||
{{ 'quote.details.name' | cxTranslate }} | ||
</div> | ||
<div class="form-group"> | ||
<input | ||
class="form-control" | ||
[maxLength]="content.charactersLimit" | ||
type="text" | ||
name="name" | ||
formControlName="name" | ||
/> | ||
</div> | ||
</div> | ||
<div class="cx-card-paragraph"> | ||
<div class="cx-card-paragraph-title"> | ||
{{ 'quote.details.description' | cxTranslate }} | ||
</div> | ||
<div class="form-group"> | ||
<textarea | ||
class="form-control" | ||
[maxLength]="content.charactersLimit" | ||
rows="4" | ||
name="description" | ||
formControlName="description" | ||
></textarea> | ||
<p *ngIf="content.charactersLimit" class="cx-info-text"> | ||
{{ | ||
'quote.details.charactersLeft' | ||
| cxTranslate | ||
: { | ||
count: getCharactersLeft( | ||
'description', | ||
content.charactersLimit | ||
) | ||
} | ||
}} | ||
</p> | ||
</div> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
<!-- Edit Mode Actions --> | ||
<div class="cx-card-button-container"> | ||
<button class="btn btn-tertiary" (click)="cancel()"> | ||
{{ 'common.cancel' | cxTranslate }} | ||
</button> | ||
<button class="btn btn-block btn-secondary" (click)="save()"> | ||
{{ 'common.save' | cxTranslate }} | ||
</button> | ||
</div> | ||
</div> | ||
</div> |
258 changes: 258 additions & 0 deletions
258
feature-libs/quote/components/details/edit/quote-details-edit.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
import { Component, DebugElement, Input } from '@angular/core'; | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { ReactiveFormsModule } from '@angular/forms'; | ||
import { I18nTestingModule } from '@spartacus/core'; | ||
import { ICON_TYPE } from '@spartacus/storefront'; | ||
import { CommonQuoteTestUtilsService } from '../../testing/common-quote-test-utils.service'; | ||
import { | ||
EditCard, | ||
QuoteDetailsEditComponent, | ||
} from './quote-details-edit.component'; | ||
|
||
const mockCard: EditCard = { | ||
name: 'Quote name', | ||
description: 'Here you could enter a long description for the current quote', | ||
charactersLimit: 255, | ||
}; | ||
|
||
@Component({ | ||
selector: 'cx-icon', | ||
template: '', | ||
}) | ||
class MockCxIconComponent { | ||
@Input() type: ICON_TYPE; | ||
} | ||
|
||
describe('QuoteDetailsEditComponent', () => { | ||
let fixture: ComponentFixture<QuoteDetailsEditComponent>; | ||
let component: QuoteDetailsEditComponent; | ||
let htmlElem: HTMLElement; | ||
let debugElement: DebugElement; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [I18nTestingModule, ReactiveFormsModule], | ||
declarations: [QuoteDetailsEditComponent, MockCxIconComponent], | ||
}).compileComponents(); | ||
}); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(QuoteDetailsEditComponent); | ||
htmlElem = fixture.nativeElement; | ||
debugElement = fixture.debugElement; | ||
component = fixture.componentInstance; | ||
component.content = mockCard; | ||
fixture.detectChanges(); | ||
|
||
spyOn(component.saveCard, 'emit').and.callThrough(); | ||
spyOn(component.cancelCard, 'emit').and.callThrough(); | ||
}); | ||
|
||
it('should create and render component accordingly', () => { | ||
expect(component).toBeTruthy(); | ||
|
||
CommonQuoteTestUtilsService.expectElementPresent( | ||
expect, | ||
htmlElem, | ||
'.cx-card' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementPresent( | ||
expect, | ||
htmlElem, | ||
'.cx-card-edit' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementToContainText( | ||
expect, | ||
htmlElem, | ||
'.cx-card-title', | ||
'quote.details.information' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementPresent( | ||
expect, | ||
htmlElem, | ||
'.cx-card-container' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementPresent( | ||
expect, | ||
htmlElem, | ||
'.cx-card-label-container' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectNumberOfElementsPresent( | ||
expect, | ||
htmlElem, | ||
'.cx-card-paragraph', | ||
2 | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectNumberOfElementsPresent( | ||
expect, | ||
htmlElem, | ||
'.cx-card-paragraph-title', | ||
2 | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectNumberOfElementsPresent( | ||
expect, | ||
htmlElem, | ||
'.form-group', | ||
2 | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectNumberOfElementsPresent( | ||
expect, | ||
htmlElem, | ||
'input', | ||
1 | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectNumberOfElementsPresent( | ||
expect, | ||
htmlElem, | ||
'textarea', | ||
1 | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementToContainText( | ||
expect, | ||
htmlElem, | ||
'.cx-card-paragraph-title', | ||
'quote.details.description', | ||
1 | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementToContainText( | ||
expect, | ||
htmlElem, | ||
'.cx-info-text', | ||
'quote.details.charactersLeft count:194' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementPresent( | ||
expect, | ||
htmlElem, | ||
'.cx-card-button-container' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementToContainText( | ||
expect, | ||
htmlElem, | ||
'button.btn-tertiary', | ||
'common.cancel' | ||
); | ||
|
||
CommonQuoteTestUtilsService.expectElementToContainText( | ||
expect, | ||
htmlElem, | ||
'button.btn-secondary', | ||
'common.save' | ||
); | ||
}); | ||
|
||
describe('handle action events', () => { | ||
it('should emit cancel event', () => { | ||
const cancelButton = CommonQuoteTestUtilsService.getNativeElement( | ||
debugElement, | ||
'button.btn-tertiary' | ||
); | ||
cancelButton.click(); | ||
expect(component.cancelCard.emit).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should emit edit event for disabling edit mode', () => { | ||
const saveButton = CommonQuoteTestUtilsService.getNativeElement( | ||
debugElement, | ||
'button.btn-secondary' | ||
); | ||
saveButton.click(); | ||
expect(component.saveCard.emit).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should emit edit event with an edited name and disabling edit mode', () => { | ||
const newTextForTitle1: any = 'New title for name'; | ||
component.editForm.get('name')?.setValue(newTextForTitle1); | ||
component.editForm.get('name')?.markAsDirty(); | ||
fixture.detectChanges(); | ||
const saveButton = CommonQuoteTestUtilsService.getNativeElement( | ||
debugElement, | ||
'button.btn-secondary' | ||
); | ||
saveButton.click(); | ||
expect(component.saveCard.emit).toHaveBeenCalled(); | ||
let arg: any = (component.saveCard.emit as any).calls.mostRecent() | ||
.args[0]; | ||
expect(arg.name).toEqual(newTextForTitle1); | ||
}); | ||
|
||
it('should emit edit event with an edited name, description and disabling edit mode', () => { | ||
const newTextForTitle1: any = 'New title for name'; | ||
const newTextForTitle2: any = 'Here could be found a long description'; | ||
component.editForm.get('name')?.setValue(newTextForTitle1); | ||
component.editForm.get('name')?.markAsDirty(); | ||
component.editForm.get('description')?.setValue(newTextForTitle2); | ||
component.editForm.get('description')?.markAsDirty(); | ||
fixture.detectChanges(); | ||
const saveButton = CommonQuoteTestUtilsService.getNativeElement( | ||
debugElement, | ||
'button.btn-secondary' | ||
); | ||
saveButton.click(); | ||
expect(component.saveCard.emit).toHaveBeenCalled(); | ||
let arg: any = (component.saveCard.emit as any).calls.mostRecent() | ||
.args[0]; | ||
expect(arg.name).toEqual(newTextForTitle1); | ||
expect(arg.description).toEqual(newTextForTitle2); | ||
}); | ||
}); | ||
|
||
describe('getCharactersLeft', () => { | ||
function setValue(formControlName: string, value: any): void { | ||
component.editForm.get(formControlName)?.setValue(value); | ||
component.editForm.get(formControlName)?.markAsTouched(); | ||
fixture.detectChanges(); | ||
} | ||
|
||
it('should calculate left characters', () => { | ||
const formControlName = 'description'; | ||
setValue(formControlName, 'New title for name'); | ||
|
||
if (component.content.charactersLimit) { | ||
let charactersLeft = | ||
component.content.charactersLimit - | ||
component.editForm.get(formControlName)?.value?.length; | ||
expect( | ||
component['getCharactersLeft']( | ||
formControlName, | ||
component.content.charactersLimit | ||
) | ||
).toBe(charactersLeft); | ||
|
||
charactersLeft = | ||
component.content.charactersLimit - | ||
component.editForm.get(formControlName)?.value?.length; | ||
expect( | ||
component['getCharactersLeft']( | ||
formControlName, | ||
component.content.charactersLimit | ||
) | ||
).toBe(charactersLeft); | ||
|
||
setValue(formControlName, ''); | ||
|
||
charactersLeft = | ||
component.content.charactersLimit - | ||
component.editForm.get(formControlName)?.value?.length; | ||
expect( | ||
component['getCharactersLeft']( | ||
formControlName, | ||
component.content.charactersLimit | ||
) | ||
).toBe(charactersLeft); | ||
} | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.