This commit is contained in:
Greg Johnston
2025-07-16 07:47:30 -04:00
parent b746c2ac4e
commit eb9ebc870f
7 changed files with 106 additions and 3 deletions

View File

@@ -0,0 +1,15 @@
@duplicate_names
Feature: Lazy functions can share the same name
Scenario: Two functions with the same name both work.
Given I see the app
Then I see the page is View A
When I click the button First
When I wait for a second
Then I see the result is {"a":"First Value","b":1}
When I click the button Second
When I wait for a second
Then I see the result is {"a":"Second Value","b":2}
When I click the button Third
When I wait for a second
Then I see the result is Third value.

View File

@@ -0,0 +1,9 @@
@shared_chunks
Feature: Shared code splitting works correctly
Scenario: Two functions using same serde code both work.
Given I see the app
Then I see the page is View A
When I click the button First
When I wait for a second
Then I see the result is {"a":"First Value","b":1}

View File

@@ -15,3 +15,9 @@ pub async fn click_link(client: &Client, text: &str) -> Result<()> {
link.click().await?;
Ok(())
}
pub async fn click_button(client: &Client, id: &str) -> Result<()> {
let btn = find::element_by_id(&client, &id).await?;
btn.click().await?;
Ok(())
}

View File

@@ -9,6 +9,12 @@ pub async fn page_name_is(client: &Client, expected_text: &str) -> Result<()> {
Ok(())
}
pub async fn result_is(client: &Client, expected_text: &str) -> Result<()> {
let actual = find::text_at_id(client, "result").await?;
assert_eq!(&actual, expected_text);
Ok(())
}
pub async fn navigating_appears(client: &Client) -> Result<()> {
let actual = find::text_at_id(client, "navigating").await?;
assert_eq!(&actual, "Navigating...");

View File

@@ -27,6 +27,14 @@ async fn i_select_the_link(world: &mut AppWorld, text: String) -> Result<()> {
Ok(())
}
#[when(regex = "^I click the button (.*)$")]
async fn i_click_the_button(world: &mut AppWorld, id: String) -> Result<()> {
let client = &world.client;
action::click_button(client, &id).await?;
Ok(())
}
#[when(expr = "I select the following links")]
async fn i_select_the_following_links(
world: &mut AppWorld,

View File

@@ -16,6 +16,13 @@ async fn i_see_the_page_is(world: &mut AppWorld, text: String) -> Result<()> {
Ok(())
}
#[then(regex = r"^I see the result is (.*)$")]
async fn i_see_the_result_is(world: &mut AppWorld, text: String) -> Result<()> {
let client = &world.client;
check::result_is(client, &text).await?;
Ok(())
}
#[then(regex = r"^I see the navbar$")]
async fn i_see_the_navbar(world: &mut AppWorld) -> Result<()> {
let client = &world.client;

View File

@@ -1,9 +1,9 @@
use leptos::prelude::*;
use leptos::{prelude::*, task::spawn_local};
use leptos_router::{
components::{Route, Router, Routes},
lazy_route, Lazy, LazyRoute, StaticSegment,
};
use serde::Deserialize;
use serde::{Deserialize, Serialize};
pub fn shell(options: LeptosOptions) -> impl IntoView {
view! {
@@ -54,7 +54,25 @@ pub fn App() -> impl IntoView {
#[component]
pub fn ViewA() -> impl IntoView {
leptos::logging::log!("View A");
view! { <p id="page">"View A"</p> }
let result = RwSignal::new("Click a button to see the result".to_string());
view! {
<p id="page">"View A"</p>
<pre id="result">{result}</pre>
<button id="First" on:click=move |_| spawn_local(async move { result.set(first_value().await); })>"First"</button>
<button id="Second" on:click=move |_| spawn_local(async move { result.set(second_value().await); })>"Second"</button>
// test to make sure duplicate names in different scopes can be used
<button id="Third" on:click=move |_| {
#[lazy]
pub async fn second_value() -> String {
"Third value.".to_string()
}
spawn_local(async move {
result.set(second_value().await);
});
}>"Third"</button>
}
}
// View B: lazy-loaded route with lazy-loaded data
@@ -206,3 +224,37 @@ impl LazyRoute for ViewC {
.into_any()
}
}
// When two functions have shared code, that shared code will be split out automatically
// into an additional file. For example, the shared serde code here will be split into a single file,
// and then loaded lazily once when the first of the two functions is called
#[lazy]
pub async fn first_value() -> String {
#[derive(Serialize)]
struct FirstValue {
a: String,
b: i32,
}
serde_json::to_string(&FirstValue {
a: "First Value".into(),
b: 1,
})
.unwrap()
}
#[lazy]
pub async fn second_value() -> String {
#[derive(Serialize)]
struct SecondValue {
a: String,
b: i32,
}
serde_json::to_string(&SecondValue {
a: "Second Value".into(),
b: 2,
})
.unwrap()
}