Testowanie klawiatury
Do symulacji obsługi klawiatury posłuży nam niezawodna biblioteka user-event .
Załóżmy, że mam zwykłe pole tekstowe. Po wpisaniu danych i wciśnięciu przycisku Enter wartość powinna zostać dodana do listy.
Przykład:
import { useState } from "react" ;
export function MyComponent ( ) {
const [tasks, setTasks] = useState([]);
const [task, setTask] = useState('' );
const onChangeTask = (e ) => {
setTask(e.target.value)
};
const onAddTask = (e ) => {
if (e.code == 'Enter' && task) {
setTasks([task, ...tasks]);
setTask('' );
}
}
return (
<>
<div >
<label htmlFor ="newTask" > Task title:</label >
<input
type ="text"
id ="newTask"
value ={task}
onChange ={onChangeTask}
onKeyDown ={onAddTask}
/>
</div >
<ul >
{
tasks.map((task, index) => (
<li key ={index} >
{task}
</li >
))
}
</ul >
</>
)
}
Test:
import {render, screen, within} from '@testing-library/react' ;
const { getByLabelText, getByTestId } = screen;
const renderComponent = () => {
render(<MyComponent /> );
const addTaskField = getByLabelText('Task title:' );
const taskList = within(getByTestId('task-list' ));
const addTask = async (newTask) => {
await userEvent.clear(addTaskField)
await userEvent.type(addTaskField, newTask);
await userEvent.keyboard('[Enter]' );
}
return {
addTaskField,
taskList,
addTask
}
}
test('should add new task to the list' , async () => {
const { taskList, addTask } = renderComponent();
await addTask('My task' );
expect(taskList.getByText('My task' ));
});
Za dodanie zadania do listy odpowiedzialna jest w tym teście funkcja addTask . Wywołana jest tam funkcja keyboard z biblioteki user event , która w tym przypadku symuluje wciśnięcie przycisku Enter na klawiaturze.
We listopadzie opublikowałem 6 wpisów :
Swfit
Klasy
Protokoły
Kontrola dostępu
Extension
Narysowałem dwa komiksy :
Coding rules
Face the problem
Przeczytałem dwie książki:
Outpost 2 — Dmitry Glukhovsky
Dawno temu w Warszawie — Jakub Żulczyk
Przesłuchałem pięć audiobooki:
Rozjemca — Brandon Sanderson
Powróceni — Abdulrazak Gurnah
Zło ze wschodu — Andrzej Pilipiuk
Legion — Elżbieta Cherezińska
Ziemiomorze. Czarnoksiężnik z Archipelagu — Ursula K. Le Guin
Rozszerzenia
Rozszerzenia w Swift służą do dodania funkcjonalności do już istniejącego typu. Może to być typ zarówno wbudowany w język, jak i stworzony przez programistę.
Rozszerzenie można dodać do klasy , struktury , protokołu , enumeracji i innych typów w Swift .
Żeby dodać nowe rozszerzenie, należy użyć słowa kluczowego extension .
Za pomocą rozszerzenie możesz dodać nową funkcjonalność, ale nie możesz nadpisać już istniejącej.
Przykłady
Typ własny
class Calculator {
func add (a: Int, b: Int) -> Int {
return a + b
}
}
extension Calculator {
func subtract (a: Int, b: Int) -> Int {
return a - b
}
}
var calculator = Calculator ()
print (calculator.add(a: 7 , b: 3 ))
print (calculator.subtract(a: 7 , b: 3 ))
Typ wbudowany
Możesz też dodać rozszerzenie do typu wbudowanego:
extension Int {
func square () -> Int {
return self * self
}
}
var a: Int = 7
print ("a * a = \(a.square())" )
print ("a = \(a)" )
Jeśli chcesz zmienić stan użyj słowa kluczowego mutating i nową wartość przypisz do self :
extension Int {
mutating func square () {
self = self * self
}
}
var a: Int = 7
a.square()
print ("a = \(a)" )
a.square()
print ("a = \(a)" )
Computed property
Za pomocą rozszerzenia nie możesz dodać stored property :
extension SomeType {
var property1: Int
}
ale możesz dodać computed property :
struct User {
var firstName: String = ""
var lastName: String = ""
}
extension User {
var fullName: String {
return firstName + " " + lastName
}
}
var user = User (firstName: "James" , lastName: "Bond" );
print (user.fullName)
Kontrola dostępu w Swift
Dzięki kontroli dostępu możesz określić dostępność klas, struktur, enumeracji, protokołach, właściwości, metod itp.
Swift udostępnia kilka poziomów dostępu.
Są to:
open
public
private
fileprivate
internal
Dostęp: open
Poziom dostępu open pozwala na to, że każdy ma do tego dostęp: zarówno z poziomu modułu jak i z zewnątrz.
Dzięki temu możesz pozwolić sobie także na nadpisywanie.
Jest to najmniej restrykcyjnym poziomem dostępu w Swift .
Dostęp: public
Jeśli określisz coś jako public to znaczy, że informujesz, że każdy może mieć do tego dostęp.
Podobne do open , ale różnica między nimi jest taka, że masz do tego dostęp wszędzie, ale nie możesz sobie pozwolić na nadpisanie z poziomu innego modułu.
Na przykład:
class MyClass {
public name: String = ""
}
var obj = MyClass ()
obj.name = "Public"
print (obj.name)
Dostęp: private
private sprawia, że dostęp jest ograniczony do danego zakresu.
class User {
private firstName: String = ""
private lastName: String = ""
init (firstName: String , lastName: String ) {
self .firstName = firstName
self .lastName = lastName
}
func getFullName () -> String {
return "\(firstName) \(lastName)"
}
}
var user = User (firstName: "Jan" , lastName: "Kowalski" )
print (user.getFullName())
user.firstName = "Adam"
Dostęp: fileprivate
Ten poziom dostępu podobny jest do private . Różnica jest taka, że dostęp jest ograniczony w obrębie pliku.
class User {
fileprivate firstName: String = ""
fileprivate lastName: String = ""
init (firstName: String , lastName: String ) {
self .firstName = firstName
self .lastName = lastName
}
func getFullName () -> String {
return "\(firstName) \(lastName)"
}
}
var user = User (firstName: "Jan" , lastName: "Kowalski" )
print (user.getFullName())
user.firstName = "Adam"
print (user.getFullName())
Jeśli spróbujesz się dostać do firstName lub lastName w innym pliku , zostanie zgłoszony błąd.
Inny przykład:
fileprivate class MyClass {
name: String = ""
}
Tak oznaczoną klasę: MyClass możesz używać tylko w pliku, w którym jest stworzona.
Dostęp: internal
internal to domyślny poziom dostępu w Swift .
Czyli zapis:
class MyClass {
...
}
jest równoznaczny z:
internal class MyClass {
...
}
A co to robi? W taki sposób informujemy, że kod jest dostępny w obrębie modułu , ale na zewnątrz już nie.
Nowsze wpisy
Poprzednie wpisy