Skip to content

Commit 4ef19fc

Browse files
committed
test: add more fixtures
1 parent fffc6bd commit 4ef19fc

14 files changed

+353
-2
lines changed

benchmark/js-benchmark.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ await Promise.all(
1818
)
1919

2020
const t2 = performance.now()
21-
console.log(((t2 - t1)/1000).toFixed(3), "seconds")
21+
console.log(((t2 - t1) / 1000).toFixed(3), "seconds")

benchmark/native-benchmark.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ const t1 = performance.now()
88
await minifyFiles(jsonFiles)
99

1010
const t2 = performance.now()
11-
console.log(((t2 - t1)/1000).toFixed(3), "seconds")
11+
console.log(((t2 - t1) / 1000).toFixed(3), "seconds")

test/fixtures/asyncresource.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"files": [
3+
{
4+
"name": "main",
5+
"content": "import { createSignal, createResource } from \"solid-js\";\nimport { render } from \"solid-js/web\";\n\nconst fetchUser = async (id) =>\n (await fetch(`https://swapi.dev/api/people/${id}/`)).json();\n\nconst App = () => {\n const [userId, setUserId] = createSignal();\n const [user] = createResource(userId, fetchUser);\n\n return (\n <>\n <input\n type=\"number\"\n min=\"1\"\n placeholder=\"Enter Numeric Id\"\n onInput={(e) => setUserId(e.currentTarget.value)}\n />\n <span>{user.loading && \"Loading...\"}</span>\n <div>\n <pre>{JSON.stringify(user(), null, 2)}</pre>\n </div>\n </>\n );\n};\n\nrender(App, document.getElementById(\"app\"));"
6+
}
7+
]
8+
}

test/fixtures/counter.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "Counter",
3+
"description": "A simple standard counter example",
4+
"files": [
5+
{
6+
"name": "main",
7+
"content": [
8+
"import { createSignal, onCleanup } from \"solid-js\";",
9+
"import { render } from \"solid-js/web\";",
10+
"",
11+
"const CountingComponent = () => {",
12+
"\tconst [count, setCount] = createSignal(0);",
13+
"\tconst interval = setInterval(",
14+
"\t\t() => setCount(c => c + 1),",
15+
"\t\t1000",
16+
"\t);",
17+
"\tonCleanup(() => clearInterval(interval));",
18+
"\treturn <div>Count value is {count()}</div>;",
19+
"};",
20+
"",
21+
"render(() => <CountingComponent />, document.getElementById(\"app\"));"
22+
]
23+
}
24+
]
25+
}

test/fixtures/counterstore.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"files": [
3+
{
4+
"name": "main",
5+
"content": "import { render } from \"solid-js/web\";\nimport { CounterProvider, useCounter } from \"CounterStore.tsx\";\n\nconst MiddleComponent = () => <NestedComponent />;\n\nconst NestedComponent = () => {\n const [count, { increment, decrement }] = useCounter();\n return (\n <>\n <p>{count()}</p>\n <button onClick={increment}>+</button>\n <button onClick={decrement}>-</button>\n </>\n );\n};\n\nconst App = () => (\n <CounterProvider count={7}>\n <MiddleComponent />\n </CounterProvider>\n);\n\nrender(App, document.getElementById(\"app\"));"
6+
},
7+
{
8+
"name": "CounterStore",
9+
"content": "import { createSignal, createContext, useContext, Component } from \"solid-js\";\n\ntype CounterStore = [\n () => number,\n { increment?: () => void; decrement?: () => void }\n];\n\nconst CounterContext = createContext<CounterStore>([() => 0, {}]);\n\nexport const CounterProvider: Component<{ count: number }> = props => {\n const [count, setCount] = createSignal(props.count || 0),\n store: CounterStore = [\n count,\n {\n increment() {\n setCount(c => c + 1);\n },\n decrement() {\n setCount(c => c - 1);\n }\n }\n ];\n\n return (\n <CounterContext.Provider value={store}>\n {props.children}\n </CounterContext.Provider>\n );\n};\n\nexport function useCounter() {\n return useContext(CounterContext);\n}"
10+
}
11+
]
12+
}

test/fixtures/cssanimations.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"files": [
3+
{
4+
"name": "main",
5+
"content": "import { createSignal, For, Match, Switch } from \"solid-js\";\nimport { render } from \"solid-js/web\";\nimport { Transition, TransitionGroup } from \"solid-transition-group\";\nimport \"./styles.css\"\n\nfunction shuffle(array) {\n return array.sort(() => Math.random() - 0.5);\n}\nlet nextId = 10;\n\nconst App = () => {\n const [show, toggleShow] = createSignal(true),\n [select, setSelect] = createSignal(0),\n [numList, setNumList] = createSignal([1, 2, 3, 4, 5, 6, 7, 8, 9]),\n randomIndex = () => Math.floor(Math.random() * numList().length);\n\n return (\n <>\n <button onClick={() => toggleShow(!show())}>\n {show() ? \"Hide\" : \"Show\"}\n </button>\n <br />\n <b>Transition:</b>\n <Transition name=\"slide-fade\">\n {show() && (\n <div>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris\n facilisis enim libero, at lacinia diam fermentum id. Pellentesque\n habitant morbi tristique senectus et netus.\n </div>\n )}\n </Transition>\n <br />\n <b>Animation:</b>\n <Transition name=\"bounce\">\n {show() && (\n <div>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris\n facilisis enim libero, at lacinia diam fermentum id. Pellentesque\n habitant morbi tristique senectus et netus.\n </div>\n )}\n </Transition>\n <br />\n <b>Custom JS:</b>\n <Transition\n onEnter={(el, done) => {\n const a = el.animate([{ opacity: 0 }, { opacity: 1 }], {\n duration: 600\n });\n a.finished.then(done);\n }}\n onExit={(el, done) => {\n const a = el.animate([{ opacity: 1 }, { opacity: 0 }], {\n duration: 600\n });\n a.finished.then(done);\n }}\n >\n {show() && (\n <div>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris\n facilisis enim libero, at lacinia diam fermentum id. Pellentesque\n habitant morbi tristique senectus et netus.\n </div>\n )}\n </Transition>\n <br />\n <b>Switch OutIn</b>\n <br />\n <button onClick={() => setSelect((select() + 1) % 3)}>Next</button>\n <Transition name=\"fade\" mode=\"outin\">\n <Switch>\n <Match when={select() === 0}>\n <p class=\"container\">The First</p>\n </Match>\n <Match when={select() === 1}>\n <p class=\"container\">The Second</p>\n </Match>\n <Match when={select() === 2}>\n <p class=\"container\">The Third</p>\n </Match>\n </Switch>\n </Transition>\n <b>Group</b>\n <br />\n <button\n onClick={() => {\n const list = numList(),\n idx = randomIndex();\n setNumList([...list.slice(0, idx), nextId++, ...list.slice(idx)]);\n }}\n >\n Add\n </button>\n <button\n onClick={() => {\n const list = numList(),\n idx = randomIndex();\n setNumList([...list.slice(0, idx), ...list.slice(idx + 1)]);\n }}\n >\n Remove\n </button>\n <button\n onClick={() => {\n const randomList = shuffle(numList().slice());\n setNumList(randomList);\n }}\n >\n Shuffle\n </button>\n <br />\n <TransitionGroup name=\"list-item\">\n <For each={numList()}>{(r) => <span class=\"list-item\">{r}</span>}</For>\n </TransitionGroup>\n </>\n );\n};\n\nrender(App, document.getElementById(\"app\"));"
6+
},
7+
{
8+
"name": "styles",
9+
"type": "css",
10+
"content": ".container {\n position: relative;\n}\n\n.fade-enter-active,\n.fade-exit-active {\n transition: opacity 0.5s;\n}\n.fade-enter,\n.fade-exit-to {\n opacity: 0;\n}\n\n.slide-fade-enter-active {\n transition: all 0.3s ease;\n}\n.slide-fade-exit-active {\n transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);\n}\n.slide-fade-enter,\n.slide-fade-exit-to {\n transform: translateX(10px);\n opacity: 0;\n}\n\n.bounce-enter-active {\n animation: bounce-in 0.5s;\n}\n.bounce-exit-active {\n animation: bounce-in 0.5s reverse;\n}\n@keyframes bounce-in {\n 0% {\n transform: scale(0);\n }\n 50% {\n transform: scale(1.5);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n.list-item {\n transition: all 0.5s;\n display: inline-block;\n margin-right: 10px;\n}\n\n.list-item-enter,\n.list-item-exit-to {\n opacity: 0;\n transform: translateY(30px);\n}\n.list-item-exit-active {\n position: absolute;\n}\n"
11+
}
12+
]
13+
}

test/fixtures/forms.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"files": [
3+
{
4+
"name": "main",
5+
"content": "// @ts-nocheck\nimport { render } from \"solid-js/web\";\nimport { createStore } from \"solid-js/store\";\nimport { useForm } from \"./validation\";\nimport \"./styles.css\";\n\nconst EMAILS = [\"[email protected]\", \"[email protected]\", \"[email protected]\"];\n\nfunction fetchUserName(name) {\n return new Promise((resolve) => {\n setTimeout(() => resolve(EMAILS.indexOf(name) > -1), 200);\n });\n}\n\nconst ErrorMessage = ({ error }) => <span class=\"error-message\">{error}</span>;\n\nconst App = () => {\n const { validate, formSubmit, errors } = useForm({\n errorClass: \"error-input\"\n });\n const [fields, setFields] = createStore();\n const fn = (form) => {\n // form.submit()\n console.log(\"Done\");\n };\n const userNameExists = async ({ value }) => {\n const exists = await fetchUserName(value);\n return exists && `${value} is already being used`;\n };\n const matchesPassword = ({ value }) =>\n value === fields.password ? false : \"Passwords must Match\";\n\n return (\n <form use:formSubmit={fn}>\n <h1>Sign Up</h1>\n <div class=\"field-block\">\n <input\n name=\"email\"\n type=\"email\"\n placeholder=\"Email\"\n required\n use:validate={[userNameExists]}\n />\n {errors.email && <ErrorMessage error={errors.email} />}\n </div>\n <div class=\"field-block\">\n <input\n type=\"password\"\n name=\"password\"\n placeholder=\"Password\"\n required=\"\"\n minlength=\"8\"\n onInput={(e) => setFields(\"password\", e.target.value)}\n use:validate\n />\n {errors.password && <ErrorMessage error={errors.password} />}\n </div>\n <div class=\"field-block\">\n <input\n type=\"password\"\n name=\"confirmpassword\"\n placeholder=\"Confirm Password\"\n required=\"\"\n use:validate={[matchesPassword]}\n />\n {errors.confirmpassword && (\n <ErrorMessage error={errors.confirmpassword} />\n )}\n </div>\n\n <button type=\"submit\">Submit</button>\n </form>\n );\n};\n\nrender(App, document.getElementById(\"app\"));\n"
6+
},
7+
{
8+
"name": "validation",
9+
"content": "import { createStore } from \"solid-js/store\";\n\nfunction checkValid({ element, validators = [] }, setErrors, errorClass) {\n return async () => {\n element.setCustomValidity(\"\");\n element.checkValidity();\n let message = element.validationMessage;\n if (!message) {\n for (const validator of validators) {\n const text = await validator(element);\n if (text) {\n element.setCustomValidity(text);\n break;\n }\n }\n message = element.validationMessage;\n }\n if (message) {\n errorClass && element.classList.toggle(errorClass, true);\n setErrors({ [element.name]: message });\n }\n };\n}\n\nexport function useForm({ errorClass }) {\n const [errors, setErrors] = createStore({}),\n fields = {};\n\n const validate = (ref, accessor) => {\n const validators = accessor() || [];\n let config;\n fields[ref.name] = config = { element: ref, validators };\n ref.onblur = checkValid(config, setErrors, errorClass);\n ref.oninput = () => {\n if (!errors[ref.name]) return;\n setErrors({ [ref.name]: undefined });\n errorClass && ref.classList.toggle(errorClass, false);\n };\n };\n\n const formSubmit = (ref, accessor) => {\n const callback = accessor() || (() => {});\n ref.setAttribute(\"novalidate\", \"\");\n ref.onsubmit = async (e) => {\n e.preventDefault();\n let errored = false;\n\n for (const k in fields) {\n const field = fields[k];\n await checkValid(field, setErrors, errorClass)();\n if (!errored && field.element.validationMessage) {\n field.element.focus();\n errored = true;\n }\n }\n !errored && callback(ref);\n };\n };\n\n return { validate, formSubmit, errors };\n}\n"
10+
},
11+
{
12+
"name": "styles",
13+
"type": "css",
14+
"content": "input {\n display: inline-block;\n padding: 4px;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.error-message {\n color: red;\n padding: 8px;\n}\n.error-input {\n box-shadow: 0px 0px 2px 1px red;\n}"
15+
}
16+
]
17+
}

test/fixtures/routing.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"files": [
3+
{
4+
"name": "main",
5+
"content": "import { createSignal, onCleanup, Component } from \"solid-js\";\nimport { render, Switch, Match } from \"solid-js/web\";\n\nfunction createRouteHandler() {\n const [location, setLocation] = createSignal(\n window.location.hash.slice(1) || \"home\"\n ),\n locationHandler = () => setLocation(window.location.hash.slice(1));\n window.addEventListener(\"hashchange\", locationHandler);\n onCleanup(() => window.removeEventListener(\"hashchange\", locationHandler));\n return (match: string) => match === location();\n}\n\nconst Home: Component = () => (\n <>\n <h1>Welcome to this Simple Routing Example</h1>\n <p>Click the links in the Navigation above to load different routes.</p>\n </>\n);\n\nconst Profile: Component = () => (\n <>\n <h1>Your Profile</h1>\n <p>This section could be about you.</p>\n </>\n);\n\nconst Settings: Component = () => (\n <>\n <h1>Settings</h1>\n <p>All that configuration you never really ever want to look at.</p>\n </>\n);\n\nconst App = () => {\n const matches = createRouteHandler();\n return (\n <>\n <ul>\n <li>\n <a href=\"#home\">Home</a>\n </li>\n <li>\n <a href=\"#profile\">Profile</a>\n </li>\n <li>\n <a href=\"#settings\">Settings</a>\n </li>\n </ul>\n <Switch>\n <Match when={matches(\"home\")}>\n <Home />\n </Match>\n <Match when={matches(\"profile\")}>\n <Profile />\n </Match>\n <Match when={matches(\"settings\")}>\n <Settings />\n </Match>\n </Switch>\n </>\n );\n};\n\nrender(App, document.getElementById(\"app\"));"
6+
}
7+
]
8+
}

test/fixtures/scoreboard.json

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
{
2+
"name": "Scoreboard",
3+
"description": "A simple standard counter example",
4+
"files": [
5+
{
6+
"name": "main",
7+
"content": [
8+
"import {",
9+
"\tcreateMemo,",
10+
"\tcreateSignal,",
11+
"\tcreateComputed,",
12+
"\tonCleanup,",
13+
"\tFor",
14+
"} from \"solid-js\";",
15+
"import { createStore } from \"solid-js/store\";",
16+
"import { render } from \"solid-js/web\";",
17+
"",
18+
"const App = () => {",
19+
"\tlet newName, newScore;",
20+
"\tconst [state, setState] = createStore({",
21+
"\t\t\tplayers: [",
22+
"\t\t\t\t{ name: \"Mark\", score: 3 },",
23+
"\t\t\t\t{ name: \"Troy\", score: 2 },",
24+
"\t\t\t\t{ name: \"Jenny\", score: 1 },",
25+
"\t\t\t\t{ name: \"David\", score: 8 }",
26+
"\t\t\t]",
27+
"\t\t}),",
28+
"\t\tlastPos = new WeakMap(),",
29+
"\t\tcurPos = new WeakMap(),",
30+
"\t\tgetSorted = createMemo((list = []) => {",
31+
"\t\t\tlist.forEach((p, i) => lastPos.set(p, i));",
32+
"\t\t\tconst newList = state.players.slice().sort((a, b) => {",
33+
"\t\t\t\tif (b.score === a.score) return a.name.localeCompare(b.name); // stabalize the sort",
34+
"\t\t\t\treturn b.score - a.score;",
35+
"\t\t\t});",
36+
"\t\t\tlet updated = newList.length !== list.length;",
37+
"\t\t\tnewList.forEach(",
38+
"\t\t\t\t(p, i) => lastPos.get(p) !== i && (updated = true) && curPos.set(p, i)",
39+
"\t\t\t);",
40+
"\t\t\treturn updated ? newList : list;",
41+
"\t\t}),",
42+
"\t\thandleAddClick = () => {",
43+
"\t\t\tconst name = newName.value,",
44+
"\t\t\t\tscore = +newScore.value;",
45+
"\t\t\tif (!name.length || isNaN(score)) return;",
46+
"\t\t\tsetState(\"players\", (p) => [...p, { name: name, score: score }]);",
47+
"\t\t\tnewName.value = newScore.value = \"\";",
48+
"\t\t},",
49+
"\t\thandleDeleteClick = (player) => {",
50+
"\t\t\tconst idx = state.players.indexOf(player);",
51+
"\t\t\tsetState(\"players\", (p) => [...p.slice(0, idx), ...p.slice(idx + 1)]);",
52+
"\t\t},",
53+
"\t\thandleScoreChange = (player, { target }) => {",
54+
"\t\t\tconst score = +target.value;",
55+
"\t\t\tconst idx = state.players.indexOf(player);",
56+
"\t\t\tif (isNaN(+score) || idx < 0) return;",
57+
"\t\t\tsetState(\"players\", idx, \"score\", score);",
58+
"\t\t},",
59+
"\t\tcreateStyles = (player) => {",
60+
"\t\t\tconst [style, setStyle] = createSignal();",
61+
"\t\t\tcreateComputed(() => {",
62+
"\t\t\t\tgetSorted();",
63+
"\t\t\t\tconst offset = lastPos.get(player) * 18 - curPos.get(player) * 18,",
64+
"\t\t\t\t\tt = setTimeout(() =>",
65+
"\t\t\t\t\t\tsetStyle({ transition: \"250ms\", transform: null })",
66+
"\t\t\t\t\t);",
67+
"\t\t\t\tsetStyle({",
68+
"\t\t\t\t\ttransform: `translateY(${offset}px)`,",
69+
"\t\t\t\t\ttransition: null",
70+
"\t\t\t\t});",
71+
"\t\t\t\tonCleanup(() => clearTimeout(t));",
72+
"\t\t\t});",
73+
"\t\t\treturn style;",
74+
"\t\t};",
75+
"",
76+
"\treturn (",
77+
"\t\t<div id=\"scoreboard\">",
78+
"\t\t\t<div class=\"board\">",
79+
"\t\t\t\t<For each={getSorted()}>",
80+
"\t\t\t\t\t{(player) => {",
81+
"\t\t\t\t\t\tconst getStyles = createStyles(player),",
82+
"\t\t\t\t\t\t\t{ name } = player;",
83+
"\t\t\t\t\t\treturn (",
84+
"\t\t\t\t\t\t\t<div class=\"player\" style={getStyles()}>",
85+
"\t\t\t\t\t\t\t\t<div class=\"name\">{name}</div>",
86+
"\t\t\t\t\t\t\t\t<div class=\"score\">{player.score}</div>",
87+
"\t\t\t\t\t\t\t</div>",
88+
"\t\t\t\t\t\t);",
89+
"\t\t\t\t\t}}",
90+
"\t\t\t\t</For>",
91+
"\t\t\t</div>",
92+
"\t\t\t<form class=\"admin\">",
93+
"\t\t\t\t<For each={state.players}>",
94+
"\t\t\t\t\t{(player) => {",
95+
"\t\t\t\t\t\tconst { name, score } = player;",
96+
"\t\t\t\t\t\treturn (",
97+
"\t\t\t\t\t\t\t<div class=\"player\">",
98+
"\t\t\t\t\t\t\t\t{name}",
99+
"\t\t\t\t\t\t\t\t<input",
100+
"\t\t\t\t\t\t\t\t\tclass=\"score\"",
101+
"\t\t\t\t\t\t\t\t\ttype=\"number\"",
102+
"\t\t\t\t\t\t\t\t\tvalue={score}",
103+
"\t\t\t\t\t\t\t\t\tonInput={[handleScoreChange, player]}",
104+
"\t\t\t\t\t\t\t\t/>",
105+
"\t\t\t\t\t\t\t\t<button type=\"button\" onClick={[handleDeleteClick, player]}>",
106+
"\t\t\t\t\t\t\t\t\tx",
107+
"\t\t\t\t\t\t\t\t</button>",
108+
"\t\t\t\t\t\t\t</div>",
109+
"\t\t\t\t\t\t);",
110+
"\t\t\t\t\t}}",
111+
"\t\t\t\t</For>",
112+
"\t\t\t\t<div class=\"player\">",
113+
"\t\t\t\t\t<input",
114+
"\t\t\t\t\t\ttype=\"text\"",
115+
"\t\t\t\t\t\tname=\"name\"",
116+
"\t\t\t\t\t\tplaceholder=\"New player...\"",
117+
"\t\t\t\t\t\tref={newName}",
118+
"\t\t\t\t\t/>",
119+
"\t\t\t\t\t<input class=\"score\" type=\"number\" name=\"score\" ref={newScore} />",
120+
"\t\t\t\t\t<button type=\"button\" onClick={handleAddClick}>",
121+
"\t\t\t\t\t\tAdd",
122+
"\t\t\t\t\t</button>",
123+
"\t\t\t\t</div>",
124+
"\t\t\t</form>",
125+
"\t\t</div>",
126+
"\t);",
127+
"};",
128+
"",
129+
"render(App, document.getElementById(\"app\"));"
130+
]
131+
}
132+
]
133+
}

0 commit comments

Comments
 (0)