//// A module for testing novdom components. \ //// Use it in combination with `novdom_testing/testing` to test initilize tests and render components. import gleam/string import novdom/internals/component.{type Component} import novdom/internals/parameter.{ type Event, type Parameter, Attribute, Listener, } /// Check if a component is visible to the user. pub fn be_visible(component: Component) -> Component { case component_visible_js(component) { True -> component False -> panic as string.concat([ "\n", current_step(), ":\n Component is not visible", ]) } } /// Check if a component is hidden from the user. This is the opposite of `be_visible` pub fn be_hidden(component: Component) -> Component { case component_visible_js(component) { False -> component True -> panic as string.concat(["\n", current_step(), ":\n Component is visible"]) } } /// Check if a component has a specific attribute. pub fn have_attribute(component: Component, attribute: Parameter) -> Component { let assert Attribute(key, value) = attribute case has_attribute_js(component, key, value) { True -> component False -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " does not have ", key, " \"", value, "\"", ]) } } /// Check if a component does not have a specific attribute. This is the opposite of `have_attribute` pub fn not_have_attribute( component: Component, attribute: Parameter, ) -> Component { let assert Attribute(key, value) = attribute case has_attribute_js(component, key, value) { False -> component True -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " has ", key, " \"", value, "\"", ]) } } /// Check if a component has a specific listener (callback is not checked). \ /// If a specific callback needs to be checked, use `have_listener_callback`. pub fn have_listener( component: Component, listener_fn: fn(fn(Event) -> Nil) -> Parameter, ) -> Component { case has_listener_js(component, listener_fn) { #(True, _) -> component #(False, name) -> panic as string.concat([ "\n", current_step(), ":\n", component |> description("Component"), "does not have listener \"", name, "\"", ]) } } /// Check if a component does not have a specific listener. This is the opposite of `have_listener` pub fn not_have_listener( component: Component, listener_fn: fn(fn(Event) -> Nil) -> Parameter, ) -> Component { case has_listener_js(component, listener_fn) { #(False, _) -> component #(True, name) -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " has listener \"", name, "\"", ]) } } /// Check if a component has a specific listener with a specific callback. \ /// If only the listener needs to be checked, use `have_listener`. pub fn have_listener_callback( component: Component, listener: Parameter, ) -> Component { let assert Listener(name, callback) = listener case has_listener_callback_js(component, name, callback) { True -> component False -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " does not have listener \"", name, "\" with specified callback", ]) } } /// Check if a component does not have a specific listener with a specific callback. This is the opposite of `have_listener_callback` pub fn not_have_listener_callback( component: Component, listener: Parameter, ) -> Component { let assert Listener(name, callback) = listener case has_listener_callback_js(component, name, callback) { False -> component True -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " has listener \"", name, "\" with specified callback", ]) } } /// Check if a component has a specific child. pub fn have_child(parent: Component, child: Component) -> Component { case has_child_js(parent, child) { True -> parent False -> panic as string.concat([ "\n", current_step(), ":\n ", parent |> description("Component"), " does not have specified ", child |> description("child"), ]) } } /// Check if a component does not have a specific child. This is the opposite of `have_child` pub fn not_have_child(parent: Component, child: Component) -> Component { case has_child_js(parent, child) { False -> parent True -> panic as string.concat([ "\n", current_step(), ":\n ", parent |> description("Component"), " has specified ", child |> description("child"), ]) } } /// Check if a component shows a specific text. pub fn show_text(component: Component, text: String) -> Component { case shows_text_js(component, text) { True -> component False -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " does not show text \"", text, "\"", ]) } } /// Check if a component exclusively shows a specific text. pub fn exclusively_show_text(component: Component, text: String) -> Component { case exclusively_shows_text_js(component, text) { True -> component False -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " does not exclusively show text \"", text, "\"", ]) } } /// Check if a component does not show a specific text. This is the opposite of `show_text` pub fn not_show_text(component: Component, text: String) -> Component { case shows_text_js(component, text) { False -> component True -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " shows text \"", text, "\"", ]) } } /// Check if a component has a specific HTML tag. pub fn have_tag(component: Component, tag: String) -> Component { case has_tag_js(component, tag) { True -> component False -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " does not have tag \"", tag, "\"", ]) } } /// Check if a component does not have a specific HTML tag. This is the opposite of `have_tag` pub fn not_have_tag(component: Component, tag: String) -> Component { case has_tag_js(component, tag) { False -> component True -> panic as string.concat([ "\n", current_step(), ":\n ", component |> description("Component"), " has tag \"", tag, "\"", ]) } } /// Returns the value of an attribute @external(javascript, "../testing_ffi.mjs", "attribute") pub fn attribute(component: Component, name: String) -> String @external(javascript, "../testing_ffi.mjs", "component_visible") fn component_visible_js(component: Component) -> Bool @external(javascript, "../testing_ffi.mjs", "has_attribute") fn has_attribute_js(component: Component, key: String, value: String) -> Bool @external(javascript, "../testing_ffi.mjs", "has_listener") fn has_listener_js( component: Component, listener_fn: fn(fn(Event) -> Nil) -> Parameter, ) -> #(Bool, String) @external(javascript, "../testing_ffi.mjs", "has_listener_callback") fn has_listener_callback_js( component: Component, name: String, callback: fn(Event) -> Nil, ) -> Bool @external(javascript, "../testing_ffi.mjs", "has_child") fn has_child_js(component: Component, child: Component) -> Bool @external(javascript, "../testing_ffi.mjs", "shows_text") fn shows_text_js(component: Component, text: String) -> Bool @external(javascript, "../testing_ffi.mjs", "exclusively_shows_text") fn exclusively_shows_text_js(component: Component, text: String) -> Bool @external(javascript, "../testing_ffi.mjs", "has_tag") fn has_tag_js(component: Component, tag: String) -> Bool @external(javascript, "../testing_ffi.mjs", "current_step") fn current_step() -> String @external(javascript, "../testing_ffi.mjs", "get_description") fn description(component: Component, default: String) -> String