Skip to content
This repository was archived by the owner on Mar 5, 2022. It is now read-only.

Commit 5525a05

Browse files
Add radioactive state example (#409)
Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>
1 parent f9c1710 commit 5525a05

File tree

17 files changed

+456
-0
lines changed

17 files changed

+456
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ Spec | Description
179179
[tutorial](cypress/component/advanced/tutorial) | A few tests adopted from [ReactJS Tutorial](https://reactjs.org/tutorial/tutorial.html), including Tic-Tac-Toe game
180180
[use-local-storage](cypress/component/advanced/use-local-storage) | Use hooks to load and save items into `localStorage`
181181
[portal](cypress/component/advanced/portal) | Component test for `ReactDOM.createPortal` feature
182+
[radioactive-state](cypress/component/advanced/radioactive-state) | Testing components that use [radioactive-state](https://github.com/MananTank/radioactive-state) library
182183
[react-bootstrap](cypress/component/advanced/react-bootstrap) | Confirms [react-bootstrap](https://react-bootstrap.github.io/) components are working
183184
[select React component](cypress/component/advanced/react-book-example/src/components/ProductsList.spec.js) | Uses [cypress-react-selector](https://github.com/abhinaba-ghosh/cypress-react-selector) to find DOM elements using React component name and state values
184185
<!-- prettier-ignore-end -->
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# radioactive-state example
2+
3+
Testing components that use [radioactive-state](https://github.com/MananTank/radioactive-state) library.
4+
5+
![Counters test](images/counters.gif)
6+
7+
![Todos test](images/todos.gif)
8+
9+
Tests [counter](./counter), [counters](./counters), [todos](./todos)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react'
2+
import useRS from 'radioactive-state'
3+
4+
// click on the counter to increment
5+
6+
export const Counter = () => {
7+
// create a radioactive state
8+
const state = useRS({
9+
count: 0,
10+
})
11+
12+
// mutating the state triggers a re-render
13+
const increment = () => state.count++
14+
15+
return (
16+
<div className="count" onClick={increment}>
17+
{state.count}
18+
</div>
19+
)
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import './counter.css'
2+
import React from 'react'
3+
import { mount } from 'cypress-react-unit-test'
4+
import { Counter } from './Counter.jsx'
5+
6+
describe('reactive-state Counter', () => {
7+
it('increments count on click', () => {
8+
mount(
9+
<div className="App">
10+
<Counter />
11+
</div>,
12+
)
13+
cy.contains('.count', '0')
14+
.click()
15+
.click()
16+
.click()
17+
cy.contains('.count', '3')
18+
})
19+
})
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
.App {
2+
font-family: sans-serif;
3+
text-align: center;
4+
display: grid;
5+
place-items: center;
6+
min-height: 100vh;
7+
}
8+
9+
.count {
10+
font-size: 5rem;
11+
color: white;
12+
width: 150px;
13+
height: 150px;
14+
border-radius: 50%;
15+
display: grid;
16+
place-items: center;
17+
cursor: pointer;
18+
user-select: none;
19+
transition: all 100ms ease;
20+
background: #3069f9;
21+
border: 10px solid rgb(198, 214, 253);
22+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
23+
}
24+
25+
.count:active {
26+
transform: scale(0.95);
27+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
28+
}
29+
30+
* {
31+
margin: 0;
32+
padding: 0;
33+
box-sizing: border-box;
34+
}
35+
36+
body {
37+
margin: 0;
38+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
39+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
40+
sans-serif;
41+
-webkit-font-smoothing: antialiased;
42+
-moz-osx-font-smoothing: grayscale;
43+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react'
2+
import useRS from 'radioactive-state'
3+
4+
// deep mutation also triggers re-render !
5+
const Counters = () => {
6+
const state = useRS({
7+
counts: [0],
8+
sum: 0,
9+
})
10+
11+
const increment = i => {
12+
state.counts[i]++
13+
state.sum++
14+
}
15+
16+
const addCounter = () => state.counts.push(0)
17+
18+
return (
19+
<>
20+
<button onClick={addCounter}> Add Counter </button>
21+
<div className="counts">
22+
{state.counts.map((count, i) => (
23+
<div className="count" onClick={() => increment(i)} key={i}>
24+
{count}
25+
</div>
26+
))}
27+
</div>
28+
<div className="count sum">{state.sum}</div>
29+
</>
30+
)
31+
}
32+
33+
export default Counters
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import './counters.css'
2+
import React from 'react'
3+
import { mount } from 'cypress-react-unit-test'
4+
import Counters from './Counters.jsx'
5+
6+
describe('reactive-state Counters', () => {
7+
it('increments single count on click', () => {
8+
mount(
9+
<div className="App">
10+
<Counters />
11+
</div>,
12+
)
13+
cy.contains('.count', '0')
14+
.click()
15+
.click()
16+
.click()
17+
// increments the counter itself
18+
cy.contains('.count', '3')
19+
// increments the sum
20+
cy.contains('.sum', '3')
21+
22+
// add two more counters
23+
cy.contains('Add Counter')
24+
.click()
25+
.click()
26+
cy.get('.counts .count').should('have.length', 3)
27+
// clicking the new counters increments the sum
28+
cy.get('.count')
29+
.eq(1)
30+
.click()
31+
cy.contains('.sum', '4')
32+
cy.get('.count')
33+
.eq(2)
34+
.click()
35+
cy.contains('.sum', '5')
36+
})
37+
})
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
.App {
2+
font-family: sans-serif;
3+
text-align: center;
4+
padding: 20px;
5+
display: flex;
6+
flex-direction: column;
7+
align-items: center;
8+
min-height: 100vh;
9+
}
10+
11+
.count {
12+
background: #3069f9;
13+
border: 6px solid rgb(198, 214, 253);
14+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
15+
margin: 10px;
16+
font-size: 2rem;
17+
color: white;
18+
width: 80px;
19+
height: 80px;
20+
border-radius: 50%;
21+
display: grid;
22+
place-items: center;
23+
cursor: pointer;
24+
user-select: none;
25+
transition: all 100ms ease;
26+
}
27+
28+
.count.sum {
29+
background: #ff3944;
30+
border-color: #ffb0b5;
31+
width: 100px;
32+
height: 100px;
33+
font-size: 3rem;
34+
}
35+
36+
.counts {
37+
display: flex;
38+
flex-wrap: wrap;
39+
justify-content: center;
40+
}
41+
42+
.count:not(.sum):active {
43+
transform: scale(0.95);
44+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
45+
}
46+
47+
* {
48+
margin: 0;
49+
padding: 0;
50+
box-sizing: border-box;
51+
}
52+
53+
body {
54+
margin: 0;
55+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
56+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
57+
sans-serif;
58+
-webkit-font-smoothing: antialiased;
59+
-moz-osx-font-smoothing: grayscale;
60+
}
61+
62+
button {
63+
background: #ffd400;
64+
border: 5px solid #fdee81;
65+
outline: none;
66+
font-size: 1.5rem;
67+
padding: 15px;
68+
border-radius: 10px;
69+
margin: 20px;
70+
transition: all 150ms ease;
71+
cursor: pointer;
72+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
73+
}
74+
75+
button:active {
76+
transform: scale(0.9);
77+
}
369 KB
Loading
457 KB
Loading

0 commit comments

Comments
 (0)