Angular sürümünde uygulamanın bu bileşeninin, bir label ve input içeren bir div olacağını görebiliriz. Bu klasik bir form alanıdır.
feat/inputDetail adında bir dal oluşturun. src/components/ klasörü altında InputDetail.cy.tsx ve InputDetail.tsx adında 2 dosya oluşturun. Her zamanki gibi, bir bileşen render ile minimal başlayın; aşağıdakileri dosyalara kopyalayın ve yarn cy:open-ct ile koşucuyu açtıktan sonra testi çalıştırın.
İlk başarısız testimize geçelim. Bir input etiketinin placeholder niteliği olması gerekiyor. Hem bunu hem de Testing Library'nin findByPlaceholderText'ini kullanarak kontrol edebiliriz (Kırmızı 1).
Hemen bu değerin bir özellik olması gerektiğini söyleyebiliriz, çünkü sert kodlanmış değer nedeniyle. Testi ve bileşeni bir prop kabul etmek üzere geliştiriyoruz (Düzenleme 1).
İhtiyacımız olan bir sonraki etiket label'dır. Bu, formlarda yaygın bir düzendir; css ve niteliklerle bir div etiketi içinde label ve input etiketlerini içeren bir yapıdır. Başarısız bir test yazalım (Kırmızı 2).
Form alanlarının da bir value özelliği bulunmaktadır. Bu özellik, ağdan gelen readonly değerleri veya yazılabilir form alanları için kullanılabilir. Şimdilik, bir formun defaultValue değerini kontrol eden başarısız bir test yazalım ve aynı zamanda stilleri ekleyelim (Kırmızı 3).
Form alanı için 2 çeşit önerdik; salt okunur ve yazılabilir alan. İki durum yaratalım. Bir alanın değiştirilebilir olduğunu kontrol eden ilk test geçmelidir. İkinci test, girişin salt okunur olduğunu kontrol eder ve şimdilik başarısız olmalıdır. Ayrıca, mevcut olmayan bir readOnly özelliği geçmeye çalışırken derleyici göstergesi alırız (Kırmızı 4).
// src/components/InputDetail.cy.tsximport InputDetail from"./InputDetail";import"../styles.scss";describe("InputDetail", () => {it("should allow the input field to be modified", () => {constplaceholder="Aslaug";constname="name";constvalue="some value";constnewValue="42";cy.mount( <InputDetailname={name} value={value} placeholder={placeholder} /> );cy.contains(name);cy.findByPlaceholderText(placeholder).clear().type(newValue);cy.get("input").should("have.value", newValue); });it("should not allow the input field to be modified when readonly", () => {constplaceholder="Aslaug";constname="name";constvalue="some value";cy.mount( <InputDetailname={name}value={value}placeholder={placeholder}readOnly={true} /> );cy.contains(name);cy.findByPlaceholderText(placeholder).should("have.attr","readOnly"); });});
readOnly özelliğini tiplere, argümanlara ve bileşenin salt okunur özelliğine ekleyerek geçen bir test alabiliriz (Yeşil 4). Bu noktada, name ve value zorunlu alanlar olduğunu ve geri kalanların isteğe bağlı olduğunu belirtmek önemlidir.
Bir form alanı için ihtiyaç duyduğumuz son özellik, yazılabilir bir alan olduğunda onChange'dir. Form alanı değiştiğinde onChange olayının çağrıldığını kontrol etmek için testi geliştirelim (Kırmızı 5). onChange değeri basitçe cy.stub().as('onChange')'dir.
// src/components/InputDetail.cy.tsximport InputDetail from"./InputDetail";import"../styles.scss";describe("InputDetail", () => {it("should allow the input field to be modified", () => {constplaceholder="Aslaug";constname="name";constvalue="some value";constnewValue="42";cy.mount( <InputDetailname={name}value={value}placeholder={placeholder}onChange={cy.stub().as("onChange")} /> );cy.contains(name);cy.findByPlaceholderText(placeholder).clear().type(newValue);cy.get("input").should("have.value", newValue);cy.get("@onChange").should("have.been.called"); });it("should not allow the input field to be modified when readonly", () => {constplaceholder="Aslaug";constname="name";constvalue="some value";cy.mount( <InputDetailname={name}value={value}placeholder={placeholder}readOnly={true} /> );cy.contains(name);cy.findByPlaceholderText(placeholder).should("have.attr","readOnly");cy.get("input").should("have.value", value); });});
Testi geçmek için, yeni onChange özelliği için tipi eklemeliyiz, bileşenin argümanını ve giriş etiketinin özelliğini eklemeliyiz (Yeşil 5).
onChange kontrolü ile testi daha spesifik hale getirebiliriz. 42 yazarken 2 kez çağrılmalıdır (Düzenleme 5).
// src/components/InputDetail.cy.tsximport InputDetail from"./InputDetail";import"../styles.scss";describe("InputDetail", () => {constplaceholder="Aslaug";constname="name";constvalue="some value";constnewValue="42";it("should allow the input field to be modified", () => {cy.mount( <InputDetailname={name}value={value}placeholder={placeholder}onChange={cy.stub().as("onChange")} /> );cy.contains("label", name);cy.findByPlaceholderText(placeholder).clear().type(newValue);cy.findByDisplayValue(newValue);cy.get("@onChange").its("callCount").should("eq",newValue.length+1); });it("should not allow the input field to be modified", () => {cy.mount( <InputDetailname={name}value={value}placeholder={placeholder}readOnly={true} /> );cy.contains("label", name);cy.findByPlaceholderText(placeholder).should("have.value", value).and("have.attr","readOnly"); });});
Son dokunuş olarak, bileşeni bir alt öğe olarak kullanıldığında başvurmayı kolaylaştırmak için bir data-cy seçici ekleriz.
// src/components/InputDetail.test.tsximport InputDetail from"./InputDetail";import { render, screen } from"@testing-library/react";import userEvent from"@testing-library/user-event";describe("InputDetail", () => {constplaceholder="Aslaug";constname="name";constvalue="some value";constnewValue="42";it("should allow the input field to be modified",async () => {constonChange=jest.fn();render( <InputDetailname={name}value={value}placeholder={placeholder}onChange={onChange} /> );awaitscreen.findByText(name);constinputField=awaitscreen.findByPlaceholderText(placeholder);awaituserEvent.clear(inputField);awaituserEvent.type(inputField, newValue);expect(inputField).toHaveDisplayValue(newValue);expect(onChange).toHaveBeenCalledTimes(newValue.length); });it("should not allow the input field to be modified",async () => {render( <InputDetailname={name}value={value}placeholder={placeholder}readOnly={true} /> );awaitscreen.findByText(name);constinputField=awaitscreen.findByPlaceholderText(placeholder);expect(inputField).toHaveDisplayValue(value);expect(inputField).toHaveAttribute("readOnly"); });});
Özet
findByPlaceholderText komutunu kullanarak input placeholder metin kontrolü ile başladık (Kırmızı 1).
Testin geçmesi için placeholder özelliğine sabit bir değer atadık (Yeşil 1).
Sabit değeri bir prop ile değiştirdik. Prop'u tiplere, bileşenin argümanlarına ekledik ve placeholder özelliğinin değeri için bu argümanı kullandık (Düzenleme 1).
Formlarda sıkça rastlanan bir model belirledik; bir div'ın, css ve özniteliklerle birlikte bir label ve input'u sarmalıyor. Etiket etiketi altındaki alan adını kontrol eden başarısız bir test yazdık (Kırmızı 2).
Yeni prop'u tiplere, bileşenin argümanlarına ve label etiketine ekledik (Yeşil 2).
Formlar üzerinde önemli bir bilgi belirledik: input type="text" bir input'u metin girişi yapar, label htmlFor={someValue}label ve input etiketlerini bağlar. Bileşeni bu bilgi ile geliştirdik (Düzenleme 2).
Yeni bir prop için value / defaultValue testi ekledik (Kırmızı 3).
Önceki döngülerde olduğu gibi, defaultValue'yi tip, bileşenin argümanları ve input özniteliğine ekleyerek testi yeşile çevirdik (Yeşil 3).
Bileşenin iki çeşidini desteklemeye karar verdik; yazılabilir alanlar için biri ve salt okunur alanlar için diğeri. Salt okunur alanın değiştirilmemesi gerektiğini doğrulayan yeni bir test ekledik (Kırmızı 4).
Önceki döngülerde olduğu gibi, readOnly tipini, bileşene argümanı ve eşleşen bir prop ile özniteliği ekledik (Yeşil 4).
Sonunda, alanda onChange prop'u istedik. Alanı değiştirirken onChange olayının çağrıldığını kontrol eden bir test ekledik (Kırmızı 5).
Yeni prop için tip ekledik, bileşene argümanı ve eşleşen bir prop ile özniteliği ekledik (Yeşil 5).
Testi, belirli sayıda onChange çağrısını kontrol etmek için geliştirdik (Düzenleme 5).
Alınacak Dersler
Bileşen testine bir prop eklerken:
Prop'u bileşen tiplerine ekleyin.
Bileşene veya argümanlara ekleyin.
Bileşende prop'u kullanın.
Takeaways
When adding a prop to the component test:
Add the prop to the component types.
Add it to the arguments or the component.
Use the prop in the component.
Bir div'ın label ve input'u sarmalaması, form alanları oluşturmak için yaygın bir modeldir. input type="text" bir input'u metin girişi yapar, label htmlFor={someValue}label ve input etiketlerini bağlar.