From 02304c93312aa897d4fe8865abc37f47eecb3096 Mon Sep 17 00:00:00 2001 From: "Daniel H. Alcojor" Date: Mon, 19 Aug 2024 12:46:06 +0200 Subject: [PATCH] Add coverage preprocessor, refactor style, and adjust tests Added TS files to the coverage preprocessor in karma.conf.js and updated coverage reporters. Refactored fight component to use single quotes and improved test cases for hp-event component to handle both regeneration and damage scenarios. --- karma.conf.js | 5 +- .../hp-event/hp-event.component.spec.ts | 37 +++-- src/app/fight/fight.component.spec.ts | 3 +- src/app/fight/fight.component.ts | 145 +++++++++++------- 4 files changed, 122 insertions(+), 68 deletions(-) diff --git a/karma.conf.js b/karma.conf.js index a08be8e..34d1411 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -33,10 +33,13 @@ module.exports = function (config) { lines: 80, }, }, + preprocessors: { + "src/**/*.ts": ["coverage"], + }, coverageReporter: { dir: require("path").join(__dirname, "./coverage/comic-fight"), subdir: ".", - reporters: [{ type: "html" }, { type: "text-summary" }], + reporters: [{ type: "html" }, { type: "text" }], }, reporters: ["progress", "kjhtml"], browsers: ["Chrome"], diff --git a/src/app/components/hp-event/hp-event.component.spec.ts b/src/app/components/hp-event/hp-event.component.spec.ts index fbeddec..4a6f8d7 100644 --- a/src/app/components/hp-event/hp-event.component.spec.ts +++ b/src/app/components/hp-event/hp-event.component.spec.ts @@ -3,12 +3,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing' import { HpEventComponent } from './hp-event.component' import { Component } from '@angular/core' import { appConfig } from '../../app.config' - -const event = { - hpChange: 10, - left: 10, - top: 10, -} +import { HPEvent } from '../event/event.component' describe('HpEventComponent', () => { let component: HpEventComponent @@ -27,12 +22,32 @@ describe('HpEventComponent', () => { fixture = TestBed.createComponent(TestHostComponent) testHost = fixture.componentInstance hpEventEl = fixture.nativeElement.querySelector('cf-hp-event') - fixture.detectChanges() }) - it('should create the hp event', () => { + it('should create the hp regenerate event', () => { + testHost.event = { + hpChange: 10, + left: 10, + top: 10, + } + fixture.detectChanges() + const span = hpEventEl.querySelector('span') as HTMLElement + expect(span.className).toContain('text-regenerate') expect(hpEventEl.textContent).toContain('+10') }) + + it('should create the hp damage event', () => { + testHost.event = { + hpChange: -10, + left: 10, + top: 10, + } + fixture.detectChanges() + hpEventEl = fixture.nativeElement.querySelector('cf-hp-event') + const span = hpEventEl.querySelector('span') as HTMLElement + expect(span.className).toContain('text-damage') + expect(hpEventEl.textContent).toContain('-10') + }) }) /* @@ -45,5 +60,9 @@ describe('HpEventComponent', () => { template: ` `, }) class TestHostComponent { - event = event + event: HPEvent = { + hpChange: 0, + left: 0, + top: 0, + } } diff --git a/src/app/fight/fight.component.spec.ts b/src/app/fight/fight.component.spec.ts index c93f1a2..345e153 100644 --- a/src/app/fight/fight.component.spec.ts +++ b/src/app/fight/fight.component.spec.ts @@ -2,7 +2,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing' import { FightComponent } from './fight.component' import { provideRouter } from '@angular/router' -import { AboutComponent } from '../about/about.component' import { provideHttpClient } from '@angular/common/http' import { provideHttpClientTesting } from '@angular/common/http/testing' @@ -14,7 +13,7 @@ describe('FightComponent', () => { await TestBed.configureTestingModule({ imports: [FightComponent], providers: [ - provideRouter([{ path: '**', component: AboutComponent }]), + provideRouter([{ path: '**', component: FightComponent }]), provideHttpClient(), provideHttpClientTesting(), ], diff --git a/src/app/fight/fight.component.ts b/src/app/fight/fight.component.ts index 9e13e1f..37a6543 100644 --- a/src/app/fight/fight.component.ts +++ b/src/app/fight/fight.component.ts @@ -1,30 +1,46 @@ -import { Component, ElementRef, Input, OnInit, signal, WritableSignal } from "@angular/core" -import { RouterLink } from "@angular/router" -import { Character, DEADPOOL, WOLVERINE } from "../characters/character" -import { Event, EventComponent, HPEvent, RoundEvent } from "../components/event/event.component" -import { HealthBarComponent } from "../components/health-bar/health-bar.component" -import { getRandomFromRange } from "../utils" -import { HeaderComponent } from "../header/header.component"; -import { HpEventComponent } from "../components/hp-event/hp-event.component"; +import { + Component, + ElementRef, + Input, + OnInit, + signal, + WritableSignal, +} from '@angular/core' +import { RouterLink } from '@angular/router' +import { Character, DEADPOOL, WOLVERINE } from '../characters/character' +import { + Event, + EventComponent, + HPEvent, + RoundEvent, +} from '../components/event/event.component' +import { HealthBarComponent } from '../components/health-bar/health-bar.component' +import { getRandomFromRange } from '../utils' +import { HeaderComponent } from '../header/header.component' +import { HpEventComponent } from '../components/hp-event/hp-event.component' const DELAY = 1000 @Component({ - selector: "cf-fight", + selector: 'cf-fight', standalone: true, - imports: [HealthBarComponent, EventComponent, RouterLink, HeaderComponent, HpEventComponent], - templateUrl: "./fight.component.html", - styleUrl: "./fight.component.css", + imports: [ + HealthBarComponent, + EventComponent, + RouterLink, + HeaderComponent, + HpEventComponent, + ], + templateUrl: './fight.component.html', + styleUrl: './fight.component.css', }) export class FightComponent implements OnInit { leftCharacter = DEADPOOL leftCharacterHealth = signal(this.leftCharacter.health) - leftCharacterIdleImage?: HTMLImageElement - leftLoserClass = signal("") + leftLoserClass = signal('') rightCharacter = WOLVERINE rightCharacterHealth = signal(this.rightCharacter.health) - rightCharacterIdleImage?: HTMLImageElement - rightLoserClass = signal("") + rightLoserClass = signal('') currentRound = signal(0) roundEvents = signal([]) hpEvents = signal([]) @@ -32,6 +48,8 @@ export class FightComponent implements OnInit { gameOver = signal(false) doubleKoBackgroundStyle = `linear-gradient(90deg, ${this.leftCharacter.mainColor} 0%, ${this.rightCharacter.mainColor} 100%)` + constructor(public elementRef: ElementRef) {} + /** Input parameter read from the URL path */ @Input() set leftCharacterInitialHealth(value: number) { @@ -46,8 +64,6 @@ export class FightComponent implements OnInit { this.rightCharacter.maxHealth = value } - constructor(public elementRef: ElementRef) {} - ngOnInit(): void { this.runFight() } @@ -58,8 +74,8 @@ export class FightComponent implements OnInit { this.rightCharacterHealth.set(this.rightCharacter.maxHealth) this.leftCharacter.canAttack = true this.rightCharacter.canAttack = true - this.leftLoserClass.set("") - this.rightLoserClass.set("") + this.leftLoserClass.set('') + this.rightLoserClass.set('') this.currentRound.set(0) this.roundEvents.set([]) this.winnerEvent.set(null) @@ -95,10 +111,7 @@ export class FightComponent implements OnInit { round: this.currentRound(), events: [leftEvent, rightEvent], } - this.roundEvents.set([ - roundEvent, - ...this.roundEvents(), - ]) + this.roundEvents.set([roundEvent, ...this.roundEvents()]) } /** @@ -113,12 +126,12 @@ export class FightComponent implements OnInit { defender: Character, defenderHealth: WritableSignal, ): Event { - const side = attacker === this.leftCharacter ? "left" : "right" + const side = attacker === this.leftCharacter ? 'left' : 'right' if (attacker.canAttack) { const isDodged = Math.random() < defender.dodgeRating if (isDodged) { return { - type: "dodge", + type: 'dodge', attacker: attacker.name, defender: defender.name, alignment: side, @@ -135,10 +148,13 @@ export class FightComponent implements OnInit { critical = true } - this.showDamage(attacker === this.leftCharacter ? "right" : "left", -damage) + this.showDamage( + attacker === this.leftCharacter ? 'right' : 'left', + -damage, + ) return { - type: "attack", + type: 'attack', attacker: attacker.name, defender: defender.name, damage, @@ -148,19 +164,23 @@ export class FightComponent implements OnInit { } } else { attacker.canAttack = true - let regen = 0 + let regen: number if (attacker === this.leftCharacter) { - regen = Math.floor(this.leftCharacter.maxHealth * attacker.regenerationRating) - console.log("regenerating", this.leftCharacterHealth(), regen) + regen = Math.floor( + this.leftCharacter.maxHealth * attacker.regenerationRating, + ) + console.log('regenerating', this.leftCharacterHealth(), regen) this.leftCharacterHealth.set(this.leftCharacterHealth() + regen) } else { - regen = Math.floor(this.rightCharacter.maxHealth * attacker.regenerationRating) - console.log("regenerating", this.rightCharacterHealth(), regen) + regen = Math.floor( + this.rightCharacter.maxHealth * attacker.regenerationRating, + ) + console.log('regenerating', this.rightCharacterHealth(), regen) this.rightCharacterHealth.set(this.rightCharacterHealth() + regen) } this.showDamage(side, regen) return { - type: "regenerate", + type: 'regenerate', attacker: attacker.name, defender: defender.name, regen, @@ -173,51 +193,64 @@ export class FightComponent implements OnInit { declareWinner() { if (this.leftCharacterHealth() === 0 && this.rightCharacterHealth() === 0) { const event: Event = { - type: "winner", - attacker: "", - defender: "", - alignment: "center", - color: "black", + type: 'winner', + attacker: '', + defender: '', + alignment: 'center', + color: 'black', } this.winnerEvent.set(event) return } - const winner = this.leftCharacterHealth() > 0 ? this.leftCharacter : this.rightCharacter + const winner = + this.leftCharacterHealth() > 0 ? this.leftCharacter : this.rightCharacter const event: Event = { - type: "winner", + type: 'winner', attacker: winner.name, - defender: "", - alignment: "center", + defender: '', + alignment: 'center', color: winner.mainColor, } this.winnerEvent.set(event) - const damageTexts = this.elementRef.nativeElement.querySelectorAll(".damage-text") + const damageTexts = + this.elementRef.nativeElement.querySelectorAll('.damage-text') damageTexts.forEach((damageText: HTMLElement) => { - damageText.textContent = "" + damageText.textContent = '' }) if (this.leftCharacterHealth() === 0) { - this.leftLoserClass.set("grayscale") + this.leftLoserClass.set('grayscale') } if (this.rightCharacterHealth() === 0) { - this.rightLoserClass.set("grayscale") + this.rightLoserClass.set('grayscale') } } - showDamage(character: "left" | "right", damage: number) { + showDamage(character: 'left' | 'right', damage: number) { const el = this.elementRef.nativeElement - const image = el.querySelector(`#${character}CharacterIdleImage`) as HTMLImageElement + const image = el.querySelector( + `#${character}CharacterIdleImage`, + ) as HTMLImageElement const boundingRect = image.getBoundingClientRect() const offset = 20 - const x = getRandomFromRange(boundingRect.left + offset, boundingRect.right - offset) - const y = getRandomFromRange(boundingRect.top + offset, boundingRect.bottom - offset) - this.hpEvents.set([...this.hpEvents(), { - hpChange: damage, - left: x, - top: y, - }]) + const x = getRandomFromRange( + boundingRect.left + offset, + boundingRect.right - offset, + ) + const y = getRandomFromRange( + boundingRect.top + offset, + boundingRect.bottom - offset, + ) + this.hpEvents.set([ + ...this.hpEvents(), + { + hpChange: damage, + left: x, + top: y, + }, + ]) } delay(ms: number) {