mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 12:53:03 -05:00
feat(challenge24): create challenge 24
This commit is contained in:
55
apps/create-harness/README.md
Normal file
55
apps/create-harness/README.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<h1>Create a component harness</h1>
|
||||||
|
|
||||||
|
> Author: Thomas Laforge
|
||||||
|
|
||||||
|
### Information
|
||||||
|
|
||||||
|
The goal of this challenge is to create a test harness for `slider.component.ts`. The harness file, `slider.harness.ts`, has already been created.
|
||||||
|
|
||||||
|
The following API needs to be implemented:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
async clickPlus(): Promise<void> ;
|
||||||
|
|
||||||
|
async clickMinus(): Promise<void>;
|
||||||
|
|
||||||
|
async getValue(): Promise<number> ;
|
||||||
|
|
||||||
|
async getMinValue(): Promise<number>;
|
||||||
|
|
||||||
|
async disabled(): Promise<boolean>;
|
||||||
|
|
||||||
|
async setValue(value: number): Promise<void>;
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, you should create a `HarnessPredicate` with the default predicate and the `minValue` property.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
static with<T extends MySliderHarness>(
|
||||||
|
this: ComponentHarnessConstructor<T>,
|
||||||
|
options: SliderHarnessFilters = {}
|
||||||
|
): HarnessPredicate<T>;
|
||||||
|
```
|
||||||
|
|
||||||
|
Lastly, you will need to create the test suite for `app.component`. Some default tests have already been written, but feel free to add as many tests as you want and create as many harness methods as you need.
|
||||||
|
|
||||||
|
> Angular Material documentation can be found [here](https://material.angular.io/cdk/test-harnesses/overview)
|
||||||
|
|
||||||
|
Good luck !!! 💪
|
||||||
|
|
||||||
|
### Submitting your work
|
||||||
|
|
||||||
|
1. Fork the project
|
||||||
|
2. clone it
|
||||||
|
3. npm install
|
||||||
|
4. `npx nx serve create-harness`
|
||||||
|
5. _...work on it_
|
||||||
|
6. Commit your work
|
||||||
|
7. Submit a PR with a title beginning with **Answer:24** that I will review and other dev can review.
|
||||||
|
|
||||||
|
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="create-harness"/></a>
|
||||||
|
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="create-harness solution author"/></a>
|
||||||
|
|
||||||
|
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="create-harness blog article"/></a> -->
|
||||||
|
|
||||||
|
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>
|
||||||
15
apps/create-harness/src/app/app.component.spec.ts
Normal file
15
apps/create-harness/src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { render } from '@testing-library/angular';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
test('select first slider and value must be 16 after clicking twice on plus button', async () => {
|
||||||
|
await render(AppComponent);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('select first slider and click 1 time on plus button and twice on minus button, slider must be 10 again', async () => {
|
||||||
|
await render(AppComponent);
|
||||||
|
});
|
||||||
|
test('second slider is disabled, click 4 times on first slider and slider 2 must be enabled', async () => {
|
||||||
|
await render(AppComponent);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -13,14 +13,16 @@ import { SliderComponent } from './slider.component';
|
|||||||
[maxValue]="30"
|
[maxValue]="30"
|
||||||
(valueChange)="slider1Value.set($event)" />
|
(valueChange)="slider1Value.set($event)" />
|
||||||
<h2>Slider 2: {{ slider2Value() }}</h2>
|
<h2>Slider 2: {{ slider2Value() }}</h2>
|
||||||
|
<p>Enabled only if Slider 1 > 20</p>
|
||||||
<app-slider
|
<app-slider
|
||||||
[step]="10"
|
[step]="10"
|
||||||
[maxValue]="1000"
|
[maxValue]="1000"
|
||||||
|
[disabled]="slider1Value() < 20"
|
||||||
(valueChange)="slider2Value.set($event)" />
|
(valueChange)="slider2Value.set($event)" />
|
||||||
`,
|
`,
|
||||||
styles: [''],
|
styles: [''],
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
slider1Value = signal(0);
|
slider1Value = signal(10);
|
||||||
slider2Value = signal(0);
|
slider2Value = signal(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ApplicationConfig } from '@angular/core';
|
import { ApplicationConfig } from '@angular/core';
|
||||||
|
import { provideAnimations } from '@angular/platform-browser/animations';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [],
|
providers: [provideAnimations()],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { render } from '@testing-library/angular';
|
|
||||||
import { SliderComponent } from './slider.component';
|
|
||||||
|
|
||||||
describe('SliderComponent', () => {
|
|
||||||
test('should have 1 slider, 3 checkboxes, 4 inputs, 2 buttons', async () => {
|
|
||||||
await render(SliderComponent);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -4,14 +4,15 @@ import { FormsModule } from '@angular/forms';
|
|||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatSliderModule } from '@angular/material/slider';
|
import { MatSliderModule } from '@angular/material/slider';
|
||||||
|
import { skip } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-slider',
|
selector: 'app-slider',
|
||||||
template: `
|
template: `
|
||||||
<mat-card class="flex">
|
<mat-card class="items-center">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<div class="flex gap-10 items-center">
|
<div class="flex gap-10 items-center">
|
||||||
<button mat-mini-fab (click)="back()">
|
<button id="minusButton" mat-mini-fab (click)="back()">
|
||||||
<mat-icon>arrow_back_ios</mat-icon>
|
<mat-icon>arrow_back_ios</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
{{ minValue }}
|
{{ minValue }}
|
||||||
@@ -19,11 +20,15 @@ import { MatSliderModule } from '@angular/material/slider';
|
|||||||
class="m-4"
|
class="m-4"
|
||||||
[max]="maxValue"
|
[max]="maxValue"
|
||||||
[min]="minValue"
|
[min]="minValue"
|
||||||
|
[disabled]="disabled"
|
||||||
[step]="step">
|
[step]="step">
|
||||||
<input matSliderThumb [value]="value()" />
|
<input
|
||||||
|
matSliderThumb
|
||||||
|
[value]="value()"
|
||||||
|
(valueChange)="value.set($event)" />
|
||||||
</mat-slider>
|
</mat-slider>
|
||||||
{{ maxValue }}
|
{{ maxValue }}
|
||||||
<button mat-mini-fab (click)="forward()">
|
<button id="plusButton" mat-mini-fab (click)="forward()">
|
||||||
<mat-icon>arrow_forward_ios</mat-icon>
|
<mat-icon>arrow_forward_ios</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,21 +42,23 @@ import { MatSliderModule } from '@angular/material/slider';
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-mdc-card + .mat-mdc-card {
|
.mat-mdc-card {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
],
|
],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [MatCardModule, FormsModule, MatSliderModule, MatIconModule],
|
imports: [MatCardModule, MatSliderModule, MatIconModule, FormsModule],
|
||||||
})
|
})
|
||||||
export class SliderComponent implements OnInit {
|
export class SliderComponent implements OnInit {
|
||||||
@Input() step = 1;
|
@Input() step = 1;
|
||||||
@Input() minValue = 0;
|
@Input() minValue = 0;
|
||||||
@Input() maxValue = 100;
|
@Input() maxValue = 100;
|
||||||
|
@Input() disabled = false;
|
||||||
|
|
||||||
value = signal(0);
|
value = signal(0);
|
||||||
@Output() valueChange = toObservable(this.value);
|
@Output() valueChange = toObservable(this.value).pipe(skip(1));
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.value.set(this.minValue);
|
this.value.set(this.minValue);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ComponentHarness } from '@angular/cdk/testing';
|
import { ComponentHarness } from '@angular/cdk/testing';
|
||||||
|
|
||||||
class MySliderHarness extends ComponentHarness {
|
export class MySliderHarness extends ComponentHarness {
|
||||||
static hostSelector = 'app-slider';
|
static hostSelector = 'app-slider';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user