├── .config └── dotnet-tools.json ├── .devcontainer ├── devcontainer.json └── post-install.sh ├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── codeql │ └── codeql-config.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── ci.yml │ ├── docs-deploy.yml │ ├── prepare-release.yml │ └── release.yml ├── .gitignore ├── .vscode └── tasks.json ├── CHANGELOG.md ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md ├── Directory.Build.props ├── Directory.Packages.props ├── LICENSE ├── MIGRATION.md ├── NOTICE.md ├── NuGet.Config ├── README.md ├── bunit-logo.png ├── bunit.sln ├── docs ├── .editorconfig ├── Directory.Build.props ├── README.md ├── samples │ ├── .editorconfig │ ├── components │ │ ├── Alert.razor │ │ ├── AlertType.cs │ │ ├── AsyncComponentLoader.razor │ │ ├── AsyncData.razor │ │ ├── AsyncDisposableComponent.razor │ │ ├── Bar.razor │ │ ├── Calc.razor │ │ ├── CalcWithLoading.razor │ │ ├── CalcWithReturnValue.razor │ │ ├── CascadingParams.razor │ │ ├── CheckList.razor │ │ ├── ChildContentParams.cs │ │ ├── ClickMe.razor │ │ ├── Counter.razor │ │ ├── CounterWithFancyParagraph.razor │ │ ├── DisposableComponent.razor │ │ ├── EventCallbackParams.cs │ │ ├── ExceptionInDisposeAsyncComponent.razor │ │ ├── ExceptionInDisposeComponent.razor │ │ ├── FancyParagraph.razor │ │ ├── FancyTable.razor │ │ ├── Foo.razor │ │ ├── Heading.razor │ │ ├── HelloWorld.razor │ │ ├── InjectAuthService.razor │ │ ├── Item.razor │ │ ├── ListItem.razor │ │ ├── NonBlazorTypesParams.cs │ │ ├── PrintCascadingValue.razor │ │ ├── RenderFragmentParams.cs │ │ ├── SimpleTodo.razor │ │ ├── TemplateParams.razor │ │ ├── TwoWayBinding.razor │ │ ├── UnmatchedParams.cs │ │ ├── UserInfo.razor │ │ ├── UserRights.razor │ │ ├── WeatherForecastService.cs │ │ ├── WeatherForecastTabel.razor │ │ ├── WeatherForecasts.razor │ │ ├── Wrapper.razor │ │ ├── _Imports.razor │ │ └── bunit.docs.samples.csproj │ ├── samples.sln │ └── tests │ │ ├── Directory.Build.props │ │ ├── mstest │ │ ├── HelloWorldExplicitContextTest.cs │ │ ├── HelloWorldRazorTest.razor │ │ ├── HelloWorldTest.cs │ │ ├── _Imports.razor │ │ └── bunit.docs.mstest.samples.csproj │ │ ├── nunit │ │ ├── HelloWorldExplicitContextTest.cs │ │ ├── HelloWorldInstancePerTestCase.cs │ │ ├── HelloWorldRazorInstancePerTestCase.razor │ │ ├── HelloWorldRazorTest.razor │ │ ├── HelloWorldTest.cs │ │ ├── _Imports.razor │ │ └── bunit.docs.nunit.samples.csproj │ │ ├── razor │ │ ├── CascadingParams1Test.razor │ │ ├── CascadingParams2Test.razor │ │ ├── CascadingParams3Test.razor │ │ ├── ChildContentParams1Test.razor │ │ ├── ChildContentParams2Test.razor │ │ ├── ChildContentParams3Test.razor │ │ ├── ChildContentParams4Test.razor │ │ ├── ClickMeTest.razor │ │ ├── CounterTest.razor │ │ ├── EventCallbackParamsTest.razor │ │ ├── NestedComponentTest.razor │ │ ├── NonBlazorTypesParamsTest.razor │ │ ├── RenderFragmentParams1Test.razor │ │ ├── RenderFragmentParams2Test.razor │ │ ├── RenderFragmentParams3Test.razor │ │ ├── RenderFragmentParams4Test.razor │ │ ├── TemplateParams1Test.razor │ │ ├── TemplateParams2Test.razor │ │ ├── TwoWayBindingTest.razor │ │ ├── UnmatchedParamsTest.razor │ │ ├── _Imports.razor │ │ └── bunit.docs.razor.samples.csproj │ │ └── xunit │ │ ├── AsyncDataTest.cs │ │ ├── CascadingParams1Test.cs │ │ ├── CascadingParams2Test.cs │ │ ├── CascadingParams3Test.cs │ │ ├── ChildContentParams1Test.cs │ │ ├── ChildContentParams2Test.cs │ │ ├── ChildContentParams3Test.cs │ │ ├── ChildContentParams4Test.cs │ │ ├── ClickMeTest.cs │ │ ├── ComponentFactoryExampleTest.cs │ │ ├── CounterTest.cs │ │ ├── CounterTestWithCtx.cs │ │ ├── CounterWithFancyParagraphTest.cs │ │ ├── CustomServiceProviderFactory.cs │ │ ├── CustomServiceProviderFactoryUsage.cs │ │ ├── DisposeComponentsTest.cs │ │ ├── EventCallbackParamsTest.cs │ │ ├── FallBackServiceProviderUsage.cs │ │ ├── FallbackServiceProvider.cs │ │ ├── FooBarComponentFactory.cs │ │ ├── HelloWorldExplicitContextRazorTest.razor │ │ ├── HelloWorldExplicitContextTest.cs │ │ ├── HelloWorldImplicitContextRazorTest.razor │ │ ├── HelloWorldRazorTest.razor │ │ ├── HelloWorldTest.cs │ │ ├── InjectAuthServiceTest.cs │ │ ├── MockHttpClientBunitHelpers.cs │ │ ├── NestedComponentTest.cs │ │ ├── NonBlazorTypesParamsTest.cs │ │ ├── ReRenderTest.cs │ │ ├── RenderFragmentParams1Test.cs │ │ ├── RenderFragmentParams2Test.cs │ │ ├── RenderFragmentParams3Test.cs │ │ ├── RenderFragmentParams4Test.cs │ │ ├── RenderTreeTest.cs │ │ ├── SemanticHtmlTest.cs │ │ ├── TemplateParams1Test.cs │ │ ├── TemplateParams2Test.cs │ │ ├── TwoWayBindingTest.cs │ │ ├── UnmatchedParamsTest.cs │ │ ├── UserInfoTest.cs │ │ ├── UserRightsTest.cs │ │ ├── VerifyMarkupExamples.cs │ │ ├── WaitForComponentTest.cs │ │ ├── WeatherForecastsTest.cs │ │ ├── _Imports.razor │ │ └── bunit.docs.xunit.samples.csproj └── site │ ├── .gitignore │ ├── Properties │ └── launchsettings.json │ ├── android-chrome-192x192.png │ ├── android-chrome-256x256.png │ ├── api │ └── .gitignore │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── docfx.json │ ├── docs │ ├── code-of-conduct.md │ ├── contribute.md │ ├── extensions │ │ ├── bunit-generators.md │ │ └── index.md │ ├── external-resources.md │ ├── getting-started │ │ ├── create-test-project.md │ │ ├── index.md │ │ └── writing-tests.md │ ├── interaction │ │ ├── awaiting-async-state.md │ │ ├── dispose-components.md │ │ ├── index.md │ │ ├── render-modes.md │ │ ├── trigger-event-handlers.md │ │ └── trigger-renders.md │ ├── migrations │ │ ├── 1to2.md │ │ └── index.md │ ├── misc-test-tips.md │ ├── providing-input │ │ ├── configure-3rd-party-libs.md │ │ ├── controlling-component-instantiation.md │ │ ├── index.md │ │ ├── inject-services-into-components.md │ │ ├── passing-parameters-to-components.md │ │ ├── root-render-tree.md │ │ └── substituting-components.md │ ├── test-doubles │ │ ├── auth.md │ │ ├── emulating-ijsruntime.md │ │ ├── fake-webassemblyhostenvironment.md │ │ ├── index.md │ │ ├── input-file.md │ │ ├── mocking-httpclient.md │ │ ├── mocking-localizer.md │ │ ├── navigation-manager.md │ │ └── persistentcomponentstate.md │ ├── toc.md │ └── verification │ │ ├── async-assertion.md │ │ ├── index.md │ │ ├── semantic-html-comparison.md │ │ ├── verify-component-state.md │ │ └── verify-markup.md │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── images │ ├── bunit-logo.png │ ├── github-logo.svg │ ├── rendered-fragment-diagram.png │ ├── test-context-rendered-fragment-diagram.png │ └── testcontext-diagram.png │ ├── index.md │ ├── mstile-150x150.png │ ├── site.webmanifest │ ├── sponsors │ ├── dotnetfoundation_v4_purple.svg │ ├── packt-retina-logo.png │ ├── progress-ad-2022-dark-mode.svg │ ├── progress-ad-2022-light-mode.svg │ ├── progress-blazor-2022-300x300.png │ ├── progress-blazor-2022-dec-300x300.png │ ├── progress-blazor-300x250.png │ └── telerik-ad-site.svg │ ├── templates │ └── bunit │ │ ├── layout │ │ └── _master.tmpl │ │ └── public │ │ ├── cshtml-razor.js │ │ ├── cshtml-razor.min.js │ │ ├── main.css │ │ └── main.js │ └── toc.md ├── global.json ├── key.snk ├── src ├── .editorconfig ├── Directory.Build.props ├── bunit.generators.internal │ ├── Blazor │ │ └── EventDispatcherExtensionGenerator.cs │ ├── Directory.Build.props │ ├── README.md │ ├── Web.AngleSharp │ │ ├── GeneratorConfig.cs │ │ ├── IElementWrapper.cs │ │ ├── IElementWrapperFactory.cs │ │ ├── WrapperBase.cs │ │ ├── WrapperElementGenerator.cs │ │ └── WrapperElementsGenerator.cs │ └── bunit.generators.internal.csproj ├── bunit.generators │ ├── README.md │ ├── Web.Stubs │ │ ├── AddStubMethodStubGenerator │ │ │ └── AddStubGenerator.cs │ │ ├── AttributeLineGenerator.cs │ │ ├── AttributeStubGenerator │ │ │ ├── ComponentStubAttribute.cs │ │ │ └── ComponentStubAttributeGenerator.cs │ │ ├── HeaderProvider.cs │ │ ├── MemberRetriever.cs │ │ └── SupportedAttributes.cs │ └── bunit.generators.csproj ├── bunit.template │ ├── bunit.template.csproj │ └── template │ │ ├── .template.config │ │ ├── dotnetcli.host.json │ │ └── template.json │ │ ├── Company.BlazorTests1.csproj │ │ ├── Counter.razor │ │ ├── CounterCSharpTest.cs │ │ ├── CounterRazorTests.razor │ │ └── _Imports.razor ├── bunit.web.query │ ├── ByLabelTextElementFactory.cs │ ├── Labels │ │ ├── ByLabelTextOptions.cs │ │ ├── LabelElementExtensions.cs │ │ ├── LabelNotFoundException.cs │ │ ├── LabelQueryExtensions.cs │ │ └── Strategies │ │ │ ├── ILabelTextQueryStrategy.cs │ │ │ ├── LabelTextUsingAriaLabelStrategy.cs │ │ │ ├── LabelTextUsingAriaLabelledByStrategy.cs │ │ │ ├── LabelTextUsingForAttributeStrategy.cs │ │ │ └── LabelTextUsingWrappedElementStrategy.cs │ ├── NodeListExtensions.cs │ └── bunit.web.query.csproj └── bunit │ ├── Asserting │ ├── ActualExpectedAssertException.cs │ ├── AssertionMethodAttribute.cs │ ├── CompareToExtensions.cs │ ├── FocusAsyncAssertJSInteropExtensions.cs │ ├── FocusOnNavigateAssertJSInteropExtensions.cs │ ├── HtmlEqualException.cs │ ├── JSInvokeCountExpectedException.cs │ ├── JSRuntimeAssertExtensions.cs │ ├── MarkupMatchesAssertExtensions.cs │ └── XUnitExceptions │ │ ├── IAssertionException.cs │ │ └── ITestTimeoutException.cs │ ├── BunitContext.Obsoletes.cs │ ├── BunitContext.cs │ ├── BunitServiceProvider.cs │ ├── ComponentFactories │ ├── ConditionalComponentFactory.cs │ ├── GenericComponentFactory{TComponent,TSubstituteComponent}.cs │ ├── InstanceComponentFactory{TComponent}.cs │ ├── StubComponentFactory.cs │ └── TypeBasedComponentFactory{TComponent}.cs │ ├── ComponentFactoryCollection.cs │ ├── ComponentParameter.cs │ ├── ComponentParameterCollection.cs │ ├── ComponentParameterCollectionBuilder.cs │ ├── Diffing │ ├── BlazorDiffingHelpers.cs │ ├── DiffMarkupFormatter.cs │ └── HtmlComparer.cs │ ├── EventDispatchExtensions │ ├── InputEventDispatchExtensions.cs │ ├── Key.cs │ ├── KeyboardEventDispatchExtensions.cs │ ├── MissingEventHandlerException.cs │ └── TriggerEventDispatchExtensions.cs │ ├── Extensions │ ├── BlazorExtensions.cs │ ├── BunitServiceProviderExtensions.cs │ ├── ComponentFactoryCollectionExtensions.cs │ ├── ElementNotFoundException.cs │ ├── ElementRemovedFromDomException.cs │ ├── EnumerableExtensions.cs │ ├── InputFile │ │ ├── BUnitBrowserFile.cs │ │ ├── InputFileContent.cs │ │ └── InputFileExtensions.cs │ ├── Internal │ │ ├── AngleSharpExtensions.cs │ │ ├── AngleSharpWrapperExtensions.cs │ │ └── CssSelectorElementFactory.cs │ ├── LoggerHelperExtensions.cs │ ├── NodePrintExtensions.cs │ ├── RenderedComponentExtensions.cs │ ├── RenderedComponentInvokeAsyncExtensions.cs │ ├── RenderedComponentRenderExtensions.cs │ ├── StubComponentFactoryCollectionExtensions.cs │ └── WaitForHelpers │ │ ├── RenderedComponentWaitForHelperExtensions.WaitForElement.cs │ │ ├── RenderedComponentWaitForHelperExtensions.WaitForState.cs │ │ ├── RenderedComponentWaitForhelperExtensions.WaitForComponent.cs │ │ ├── WaitForAssertionHelper.cs │ │ ├── WaitForElementHelper.cs │ │ ├── WaitForElementsHelper.cs │ │ ├── WaitForFailedException.cs │ │ ├── WaitForHelper.cs │ │ ├── WaitForHelperLoggerExtensions.cs │ │ └── WaitForStateHelper.cs │ ├── IComponentFactory.cs │ ├── InternalsVisibleTo.cs │ ├── JSInterop │ ├── BunitJSInterop.cs │ ├── BunitJSInteropSetupExtensions.cs │ ├── BunitJSModuleInterop.cs │ ├── Implementation │ │ ├── BunitJSObjectReference.cs │ │ ├── BunitJSRuntime.cs │ │ ├── BunitJSRuntime.net8.cs │ │ └── JSRuntimeExtensions.cs │ ├── InvocationHandlers │ │ ├── Implementation │ │ │ ├── FocusAsyncInvocationHandler.cs │ │ │ ├── FocusOnNavigateHandler.cs │ │ │ ├── InputFileInvocationHandler.cs │ │ │ ├── JSObjectReferenceInvocationHandler.cs │ │ │ ├── LooseModeJSObjectReferenceInvocationHandler.cs │ │ │ ├── NavigationLockDisableNavigationPromptInvocationHandler.cs │ │ │ ├── NavigationLockEnableNavigationPromptInvocationHandler.cs │ │ │ └── VirtualizeJSRuntimeInvocationHandler.cs │ │ ├── JSRuntimeInvocationHandler.cs │ │ ├── JSRuntimeInvocationHandlerBase{TResult}.cs │ │ └── JSRuntimeInvocationHandler{TResult}.cs │ ├── InvocationMatcher.cs │ ├── JSRuntimeInvocation.cs │ ├── JSRuntimeInvocationDictionary.cs │ ├── JSRuntimeInvocationNotSetException.cs │ ├── JSRuntimeMode.cs │ └── JSRuntimeUnhandledInvocationException.cs │ ├── Rendering │ ├── BunitComponentActivator.cs │ ├── BunitHtmlParser.cs │ ├── BunitRenderer.cs │ ├── BunitRendererLoggerExtensions.cs │ ├── BunitRootComponent.cs │ ├── ComponentDisposedException.cs │ ├── ComponentNotFoundException.cs │ ├── IRenderedComponent.cs │ ├── IRenderedComponent{TComponent}.cs │ ├── Internal │ │ ├── BunitHtmlParserHelpers.cs │ │ └── Htmlizer.cs │ ├── MissingRendererInfoException.cs │ ├── RenderModeMisMatchException.cs │ ├── RenderedComponent.cs │ ├── RootComponent.cs │ ├── RootRenderTree.cs │ ├── RootRenderTreeRegistration.cs │ └── UnknownEventHandlerIdException.cs │ ├── TestContext.cs │ ├── TestDoubles │ ├── Authorization │ │ ├── AuthorizationState.cs │ │ ├── BunitAuthenticationStateProvider.cs │ │ ├── BunitAuthorizationContext.cs │ │ ├── BunitAuthorizationExtensions.cs │ │ ├── BunitAuthorizationPolicyProvider.cs │ │ ├── BunitAuthorizationService.cs │ │ ├── MissingBunitAuthorizationException.cs │ │ ├── PlaceholderAuthenticationStateProvider.cs │ │ ├── PlaceholderAuthorizationService.cs │ │ └── TestPolicyRequirement.cs │ ├── Components │ │ ├── CapturedParameterView{TComponent}.cs │ │ ├── ComponentDoubleBase{TComponent}.cs │ │ ├── ParameterNotFoundException.cs │ │ └── Stub{TComponent}.cs │ ├── ErrorBoundary │ │ └── BunitErrorBoundaryLogger.cs │ ├── HttpClient │ │ ├── MissingMockHttpClientException.cs │ │ └── PlaceholderHttpClient.cs │ ├── Localization │ │ ├── MissingMockStringLocalizationException.cs │ │ └── PlaceholderStringLocalization.cs │ ├── NavigationInterception │ │ └── BunitNavigationInterception.cs │ ├── NavigationManager │ │ ├── BunitNavigationManager.cs │ │ ├── BunitSignOutSessionStateManager.cs │ │ ├── NavigationHistory.cs │ │ └── NavigationState.cs │ ├── PersistentComponentState │ │ ├── BunitPersistentComponentState.cs │ │ ├── BunitPersistentComponentStateStore.cs │ │ └── TestContextExtensions.cs │ ├── ScrollToLocationHash │ │ └── BunitScrollToLocationHash.cs │ └── WebAssemblyHostEnvironment │ │ └── BunitWebAssemblyHostEnvironment.cs │ └── bunit.csproj ├── tests ├── .editorconfig ├── Directory.Build.props ├── bunit.generators.tests │ ├── VerifyInitializer.cs │ ├── Web.AngleSharp │ │ ├── WrapperElementsGeneratorTest.Generator#ElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlAnchorElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlAreaElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlAudioElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlBaseElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlBodyElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlBreakRowElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlButtonElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlCanvasElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlCommandElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlDataElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlDataListElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlDetailsElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlDialogElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlDivElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlEmbedElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlFieldSetElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlFormElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlHeadElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlHeadingElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlHrElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlHtmlElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlImageElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlInlineFrameElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlInputElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlKeygenElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlLabelElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlLegendElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlLinkElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlListItemElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlMapElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlMarqueeElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlMediaElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlMenuElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlMenuItemElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlMetaElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlMeterElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlModElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlObjectElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlOptionElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlOptionsGroupElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlOrderedListElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlOutputElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlParagraphElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlParamElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlPictureElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlPreElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlProgressElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlQuoteElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlScriptElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlSelectElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlSlotElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlSourceElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlSpanElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlStyleElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableCaptionElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableCellElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableColumnElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableDataCellElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableHeaderCellElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableRowElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTableSectionElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTemplateElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTextAreaElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTimeElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTitleElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlTrackElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlUnknownElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlUnorderedListElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#HtmlVideoElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#IElementWrapper.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#IElementWrapperFactory.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#WrapperBase.g.verified.cs │ │ ├── WrapperElementsGeneratorTest.Generator#WrapperExtensions.g.verified.cs │ │ └── WrapperElementsGeneratorTest.cs │ ├── Web.Stub │ │ ├── AddStubGeneratorTest.cs │ │ └── Components │ │ │ ├── ButtonComponent.cs │ │ │ ├── ContainerComponent.cs │ │ │ ├── CounterComponent.cs │ │ │ └── ParentComponent.cs │ └── bunit.generators.tests.csproj ├── bunit.testassets │ ├── AssertExtensions │ │ └── CollectionAssertExtensions.cs │ ├── BlazorE2E │ │ ├── AddRemoveChildComponents.razor │ │ ├── AsyncEventHandlerComponent.razor │ │ ├── ComponentRefComponent.razor │ │ ├── ComponentWithEscapableCharacters.razor │ │ ├── ConcurrentRenderChild.razor │ │ ├── ConcurrentRenderParent.razor │ │ ├── CounterComponent.razor │ │ ├── CounterComponentUsingChild.razor │ │ ├── CounterComponentWrapper.razor │ │ ├── DataDashComponent.razor │ │ ├── DispatchingComponent.razor │ │ ├── DuplicateAttributesComponent.razor │ │ ├── DuplicateAttributesOnElementChildComponent.razor │ │ ├── ElementRefComponent.razor │ │ ├── HierarchicalImportsTest │ │ │ ├── Subdir │ │ │ │ ├── ComponentUsingImports.razor │ │ │ │ └── _Imports.razor │ │ │ └── _Imports.razor │ │ ├── HtmlBlockChildContent.razor │ │ ├── HtmlEncodedChildContent.razor │ │ ├── HtmlMixedChildContent.razor │ │ ├── KeyPressEventComponent.razor │ │ ├── LabelQueryCounter.razor │ │ ├── LogicalElementInsertionCases.razor │ │ ├── MarkupBlockComponent.razor │ │ ├── MessageComponent.razor │ │ ├── MovingCheckboxesComponent.razor │ │ ├── MultipleChildContent.razor │ │ ├── NOTICE.md │ │ ├── OrderedList.razor │ │ ├── ParentChildComponent.razor │ │ ├── PassThroughContentComponent.razor │ │ ├── PropertiesChangedHandlerChild.razor │ │ ├── PropertiesChangedHandlerParent.razor │ │ ├── RazorTemplates.razor │ │ ├── RedTextComponent.razor │ │ ├── RenderFragmentToggler.razor │ │ ├── SvgCircleComponent.razor │ │ ├── SvgComponent.razor │ │ ├── SvgWithChildComponent.razor │ │ ├── TemplatedTable.razor │ │ ├── TextOnlyComponent.razor │ │ └── _Imports.razor │ ├── ComponentWithButton.razor │ ├── DumpCapture.cs │ ├── ExcludeFromCodeCoverage.cs │ ├── RenderModes │ │ ├── ComponentThatPrintsAssignedRenderMode.razor │ │ ├── ComponentWithChildContent.razor │ │ ├── ComponentWithServerRenderMode.razor │ │ ├── ComponentWithWebAssemblyRenderMode.razor │ │ ├── ComponentWithoutRenderMode.razor │ │ ├── InteractiveAutoComponent.razor │ │ ├── InteractiveServerComponent.razor │ │ ├── InteractiveWebAssemblyComponent.razor │ │ ├── RendererInfoComponent.cs │ │ └── SectionOutletComponent.cs │ ├── SampleComponents │ │ ├── AllTypesOfParams.cs │ │ ├── App.razor │ │ ├── AsyncRenderChangesProperty.razor │ │ ├── AsyncRenderOfSubComponentDuringInit.razor │ │ ├── AuthCascading.razor │ │ ├── BasicComponent.cs │ │ ├── BubbleEventsRemoveTriggers.razor │ │ ├── BubbleEventsThrows.razor │ │ ├── ButtonsInsideForm.razor │ │ ├── ClickAddsLi.razor │ │ ├── ClickCounter.razor │ │ ├── ClickEventBubbling.razor │ │ ├── ClickRemovesEventHandler.razor │ │ ├── ComponentWithRelativeUnitAsWidth.razor │ │ ├── ConstructorInjectionComponent.cs │ │ ├── CounterComponentDynamic.razor │ │ ├── CustomElement.razor │ │ ├── CustomPasteSample.razor │ │ ├── CustomPasteSample.razor.cs │ │ ├── Data │ │ │ ├── AsyncNameDep.cs │ │ │ ├── Cars.cs │ │ │ ├── Foo.cs │ │ │ ├── FooTypeConverter.cs │ │ │ ├── IAsyncTestDep.cs │ │ │ ├── ITestDep.cs │ │ │ └── ThemeInfo.cs │ │ ├── DelayRemovedRenderFragment.razor │ │ ├── DelayRenderFragment.razor │ │ ├── DispatcherException.razor │ │ ├── DisposeComponents │ │ │ ├── ChildDispose.razor │ │ │ ├── DisposeFragments.razor │ │ │ └── ParentDispose.razor │ │ ├── EventBubbles.cs │ │ ├── EventHandlerThrows.razor │ │ ├── FormNameComponent.razor │ │ ├── FormWithButton.razor │ │ ├── FormWithValidation.razor │ │ ├── FullBind.cs │ │ ├── HidesButton.razor │ │ ├── InputChangeEventSample.razor │ │ ├── InvokeAsyncInsideContinueWith.razor │ │ ├── LifeCycleTracker.razor │ │ ├── LoadingComponent.razor │ │ ├── MainLayout.razor │ │ ├── MultipleStateHasChangedInOnParametersSet.cs │ │ ├── NoArgs.razor │ │ ├── OnChangeBindSample.razor │ │ ├── OnChangeMultipleBindSample.razor │ │ ├── OnsubmitButton.razor │ │ ├── PersistentComponentStateSample.razor │ │ ├── PersistentComponentStateSample.razor.cs │ │ ├── PrintCascadingValue.razor │ │ ├── PrintCurrentUrl.razor │ │ ├── RefToSimple1Child.razor │ │ ├── RenderCounter.razor │ │ ├── RenderOnClick.razor │ │ ├── ScopedCssElements.razor │ │ ├── ScopedCssElements.razor.css │ │ ├── SignOutSessionManagerLoginDisplay.razor │ │ ├── Simple1.cs │ │ ├── SimpleAuthView.razor │ │ ├── SimpleAuthViewWithClaims.razor │ │ ├── SimpleAuthViewWithCustomAuthType.razor │ │ ├── SimpleAuthViewWithPolicy.razor │ │ ├── SimpleAuthViewWithRole.razor │ │ ├── SimpleBind.cs │ │ ├── SimplePage.razor │ │ ├── SimpleSvg.razor │ │ ├── SimpleUsingLocalizer.razor │ │ ├── SimpleUsingWebAssemblyHostEnvironment.razor │ │ ├── SimpleWithAyncDeps.razor │ │ ├── SimpleWithDeps.razor │ │ ├── SimpleWithHttpClient.razor │ │ ├── SimpleWithJSRuntimeDep.razor │ │ ├── SimpleWithTemplate.razor │ │ ├── SubmitFormOnClick.razor │ │ ├── ThemedButton.razor │ │ ├── ThrowsOnParameterSet.cs │ │ ├── ToggleChildComponent.razor │ │ ├── ToggleClickHandler.razor │ │ ├── ToggleableDetails.razor │ │ ├── TriggerChildContentRerenderViaClick.razor │ │ ├── TriggerTester.cs │ │ ├── TwoChildren.razor │ │ ├── TwoComponentWrapper.cs │ │ ├── TwoRendersTwoChanges.razor │ │ ├── Wrapper.cs │ │ └── WrapperDiv.cs │ ├── Serilog.Sinks.XUnit │ │ ├── NOTICE.md │ │ ├── TestOutputSink.cs │ │ └── XUnitLoggerConfigurationExtensions.cs │ ├── ServiceCollectionLoggingExtensions.cs │ ├── XunitExtensions │ │ ├── RepeatAttribute.cs │ │ ├── TheoryDataExtensions.cs │ │ └── UseCultureAttribute.cs │ ├── _Imports.razor │ └── bunit.testassets.csproj ├── bunit.tests │ ├── Assembly.cs │ ├── Asserting │ │ ├── CompareToDiffingExtensionsTest.cs │ │ ├── JSRuntimeAssertExtensionsTest.cs │ │ ├── MarkupMatchesAssertExtensionsTest.cs │ │ └── MarkupMatchesTest.razor │ ├── BlazorE2E │ │ └── ComponentRenderingTest.cs │ ├── BunitContextTest.cs │ ├── BunitServiceProviderTest.cs │ ├── ComponentFactories │ │ ├── ConditionalComponentFactoryTest.cs │ │ ├── GenericComponentFactoryTest.cs │ │ ├── InstanceComponentFactoryTest.cs │ │ ├── StubComponentFactoryTest.cs │ │ └── TypeBasedComponentFactoryTest.cs │ ├── ComponentParameterCollectionBuilderTest.cs │ ├── ComponentParameterCollectionBuilderTests.razor │ ├── ComponentParameterCollectionTest.cs │ ├── EventDispatchExtensions │ │ ├── ClipboardEventDispatchExtensionsTest.cs │ │ ├── DetailsElementEventDispatcherExtensionsTest.cs │ │ ├── DragEventDispatchExtensionsTest.cs │ │ ├── EventDispatchExtensionsTest.cs │ │ ├── FocusEventDispatchExtensionsTest.cs │ │ ├── FormDispatchExtensionTest.cs │ │ ├── GeneralEventDispatchExtensionsTest.cs │ │ ├── InputEventDispatchExtensionsTest.cs │ │ ├── KeyTest.cs │ │ ├── KeyboardEventDispatchExtensionsTest.cs │ │ ├── MouseEventDispatchExtensionsTest.cs │ │ ├── PointerEventDispatchExtensionsTest.cs │ │ ├── ProgressEventDispatchExtensionsTest.cs │ │ ├── TouchEventDispatchExtensionsTest.cs │ │ ├── TriggerEventSpy.cs │ │ └── WheelEventDispatchExtensionsTest.cs │ ├── Extensions │ │ ├── InputFile │ │ │ └── InputFileTest.cs │ │ ├── RefreshingWrappedElementTest.cs │ │ ├── RenderedComponentRenderExtensionsTest.cs │ │ └── WaitForHelpers │ │ │ ├── RenderedComponentWaitForElementsHelperExtensions.Test.cs │ │ │ ├── RenderedComponentWaitForElementsHelperExtensionsTest.cs │ │ │ └── RenderedComponentWaitForHelperExtensions.cs │ ├── JSInterop │ │ ├── BunitJSInteropTest.cs │ │ ├── BunitJsObjectReferenceTest.cs │ │ ├── InvocationHandlers │ │ │ ├── FocusAsyncInvocationHandlerTest.cs │ │ │ ├── FocusOnNavigateHandlerTest.cs │ │ │ └── VirtualizeJsRuntimeInvocationHandlerTest.cs │ │ ├── JSRuntimeInvocationTest.cs │ │ └── JSRuntimeUnhandledInvocationExceptionTest.cs │ ├── Rendering │ │ ├── BunitComponentActivatorTest.cs │ │ ├── BunitHtmlParserTest.cs │ │ ├── BunitRendererTest.cs │ │ ├── ComponentParameterTest.cs │ │ ├── Internal │ │ │ └── HtmlizerTest.cs │ │ ├── RenderModeTest.razor │ │ ├── RenderedComponentTest.cs │ │ └── RootRenderTreeTest.cs │ ├── ShouldlyExtensions.cs │ ├── TestDoubles │ │ ├── Authorization │ │ │ ├── AuthorizationTest.cs │ │ │ ├── BunitAuthenticationStateProviderTest.cs │ │ │ ├── BunitAuthorizationContextTest.cs │ │ │ ├── BunitAuthorizationPolicyProviderTest.cs │ │ │ └── BunitAuthorizationServiceTest.cs │ │ ├── BunitSignOutSessionStateManagerTest.cs │ │ ├── BunitWebAssemblyHostEnvironmentTest.cs │ │ ├── Components │ │ │ ├── CapturedParameterViewTest.cs │ │ │ ├── ComponentDoubleBaseTest.cs │ │ │ └── StubTest.cs │ │ ├── NavigationManager │ │ │ ├── BunitNavigationInterceptionTest.cs │ │ │ └── BunitNavigationManagerTest.cs │ │ └── PersistentComponentState │ │ │ └── BunitPersistentComponentStateTest.cs │ ├── TestUtilities │ │ └── JSRuntimeInvocationAssertionHelpers.cs │ ├── _Imports.razor │ ├── bunit.tests.csproj │ └── xunit.runner.json ├── bunit.web.query.tests │ ├── Labels │ │ └── LabelQueryExtensionsTest.cs │ └── bunit.web.query.tests.csproj ├── run-tests.ps1 └── xunit.runner.json └── version.json /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-serve": { 6 | "version": "1.10.175", 7 | "commands": [ 8 | "dotnet-serve" 9 | ], 10 | "rollForward": false 11 | }, 12 | "docfx": { 13 | "version": "2.78.2", 14 | "commands": [ 15 | "docfx" 16 | ], 17 | "rollForward": false 18 | }, 19 | "dotnet-dump": { 20 | "version": "9.0.553101", 21 | "commands": [ 22 | "dotnet-dump" 23 | ], 24 | "rollForward": false 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /.devcontainer/post-install.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | # Install docfx (should be aligned with docs-deploy.yml) 4 | dotnet tool restore 5 | 6 | # Trust dotnet developer certs 7 | dotnet dev-certs https --check --trust 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [bUnit-dev] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | #patreon: # Replace with a single Patreon username 5 | #open_collective: # Replace with a single Open Collective username 6 | #ko_fi: # Replace with a single Ko-fi username 7 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | #liberapay: # Replace with a single Liberapay username 10 | #issuehunt: # Replace with a single IssueHunt username 11 | #otechie: # Replace with a single Otechie username 12 | #custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Questions and Discussions 4 | url: https://github.com/egil/bUnit/discussions/new 5 | about: Is your issue perhaps more of a discussion or question? Please open topics for discussion or questions using the new GitHub Discussions feature. Remember to choose the right category. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea or enhancement for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | **Is the feature request related to a problem? Please elaborate.** 13 | 14 | 15 | 16 | **The suggested solution** 17 | 18 | 19 | 20 | **Describe any alternative solutions** 21 | 22 | 23 | 24 | **Additional context** 25 | 26 | 27 | -------------------------------------------------------------------------------- /.github/codeql/codeql-config.yml: -------------------------------------------------------------------------------- 1 | queries: 2 | - uses: security-and-quality 3 | 4 | paths: 5 | - src -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "nuget" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "daily" -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Pull request description 2 | 6 | 7 | ### PR meta checklist 8 | - [ ] Pull request is targeted at `main` branch for code 9 | or targeted at `stable` branch for documentation that is live on bunit.dev. 10 | - [ ] Pull request is linked to all related issues, if any. 11 | - [ ] I have read the _CONTRIBUTING.md_ document. 12 | 13 | ### Code PR specific checklist 14 | - [ ] My code follows the code style of this project and AspNetCore coding guidelines. 15 | - [ ] My change requires a change to the documentation. 16 | - [ ] I have updated the documentation accordingly. 17 | - [ ] I have updated the appropriate sub section in the _CHANGELOG.md_. 18 | - [ ] I have added, updated or removed tests to according to my changes. 19 | - [ ] All tests passed. 20 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Serve Docs (Without Build)", 8 | "type": "shell", 9 | "command": "dotnet docfx metadata docs/site/docfx.json && dotnet docfx docs/site/docfx.json --serve" 10 | }, 11 | { 12 | "label": "Serve Docs (With Build for API Documentation)", 13 | "type": "shell", 14 | "command": "dotnet build -c Release && dotnet docfx metadata docs/site/docfx.json && docfx docs/site/docfx.json --serve" 15 | }, 16 | { 17 | "label": "Run all tests (Release Mode)", 18 | "type": "shell", 19 | "command": "dotnet test -c Release" 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. 2 | For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). 3 | -------------------------------------------------------------------------------- /NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /bunit-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bUnit-dev/bUnit/f1cb385597097f6883731c99cecdd2ea3d9efb37/bunit-logo.png -------------------------------------------------------------------------------- /docs/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | tab_size = 2 5 | indent_style = space 6 | indent_size = 2 7 | indent_width = 2 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = false 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [*.{cs,razor}] 16 | tab_size = 2 17 | indent_style = space 18 | indent_size = 2 19 | indent_width = 2 20 | 21 | dotnet_diagnostic.BL0001.severity = none 22 | dotnet_diagnostic.BL0002.severity = none 23 | dotnet_diagnostic.BL0003.severity = none 24 | dotnet_diagnostic.BL0004.severity = none 25 | dotnet_diagnostic.BL0005.severity = none 26 | dotnet_diagnostic.BL0006.severity = none -------------------------------------------------------------------------------- /docs/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/samples/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | tab_size = 2 6 | indent_size = 2 7 | indent_width = 2 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = false 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [*.{cs,razor}] 16 | tab_size = 2 17 | indent_style = space 18 | indent_size = 2 19 | indent_width = 2 20 | 21 | dotnet_diagnostic.BL0001.severity = none 22 | dotnet_diagnostic.BL0002.severity = none 23 | dotnet_diagnostic.BL0003.severity = none 24 | dotnet_diagnostic.BL0004.severity = none 25 | dotnet_diagnostic.BL0005.severity = none 26 | dotnet_diagnostic.BL0006.severity = none 27 | dotnet_diagnostic.BL0007.severity = none -------------------------------------------------------------------------------- /docs/samples/components/Alert.razor: -------------------------------------------------------------------------------- 1 | @code { 2 | [Parameter] public string Heading { get; set; } 3 | [Parameter] public AlertType Type { get; set; } 4 | [Parameter] public RenderFragment ChildContent { get; set; } 5 | } 6 | -------------------------------------------------------------------------------- /docs/samples/components/AlertType.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Docs.Samples 2 | { 3 | public enum AlertType 4 | { 5 | Info, 6 | Warning, 7 | Error 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/samples/components/AsyncComponentLoader.razor: -------------------------------------------------------------------------------- 1 | @if (isLoading) 2 | { 3 |

Loading...

4 | } 5 | else 6 | { 7 | @foreach (var item in Items) 8 | { 9 | 10 | } 11 | } 12 | 13 | @code { 14 | [Parameter] public List Items { get; set; } = new(); 15 | 16 | private bool isLoading = true; 17 | 18 | protected override async Task OnInitializedAsync() 19 | { 20 | // Simulate async loading 21 | await Task.Delay(100); 22 | isLoading = false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/samples/components/AsyncData.razor: -------------------------------------------------------------------------------- 1 |

@text

2 | 3 | @code 4 | { 5 | string text = string.Empty; 6 | [Parameter] public Task TextService { get; set; } 7 | 8 | protected override async Task OnInitializedAsync() 9 | { 10 | text = await TextService; 11 | } 12 | } -------------------------------------------------------------------------------- /docs/samples/components/AsyncDisposableComponent.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @implements IAsyncDisposable 3 | @inject IJSRuntime JSRuntime 4 | @code { 5 | 6 | public async ValueTask DisposeAsync() 7 | { 8 | await JSRuntime.InvokeVoidAsync("dispose"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /docs/samples/components/Bar.razor: -------------------------------------------------------------------------------- 1 | Bar -------------------------------------------------------------------------------- /docs/samples/components/Calc.razor: -------------------------------------------------------------------------------- 1 | @result 2 | 3 | @code 4 | { 5 | int result = 0; 6 | 7 | public void Calculate(int x, int y) 8 | { 9 | result = x + y; 10 | StateHasChanged(); 11 | } 12 | } -------------------------------------------------------------------------------- /docs/samples/components/CalcWithLoading.razor: -------------------------------------------------------------------------------- 1 | @(result is null ? "Loading" : result.ToString()) 2 | 3 | @code 4 | { 5 | int? result = 0; 6 | 7 | public async Task Calculate(int x, int y) 8 | { 9 | result = null; 10 | StateHasChanged(); 11 | // Simulate an asynchronous operation, like fetching data. 12 | await Task.Delay(500); 13 | result = x + y; 14 | StateHasChanged(); 15 | } 16 | } -------------------------------------------------------------------------------- /docs/samples/components/CalcWithReturnValue.razor: -------------------------------------------------------------------------------- 1 | @result 2 | 3 | @code 4 | { 5 | int result = 0; 6 | 7 | public int Calculate(int x, int y) 8 | { 9 | result = x + y; 10 | StateHasChanged(); 11 | return result; 12 | } 13 | } -------------------------------------------------------------------------------- /docs/samples/components/CascadingParams.razor: -------------------------------------------------------------------------------- 1 | @code 2 | { 3 | [CascadingParameter] 4 | public bool IsDarkTheme { get; set; } 5 | 6 | [CascadingParameter(Name = "LoggedInUser")] 7 | public string UserName { get; set; } 8 | 9 | [CascadingParameter(Name = "LoggedInEmail")] 10 | public string Email { get; set; } 11 | } -------------------------------------------------------------------------------- /docs/samples/components/CheckList.razor: -------------------------------------------------------------------------------- 1 | 4 |
    5 | @foreach (var item in items) 6 | { 7 |
  • @item
  • 8 | } 9 |
10 | @code 11 | { 12 | private string newItemValue = string.Empty; 13 | private List items = new List(); 14 | 15 | private void OnTextInput(KeyboardEventArgs args) 16 | { 17 | if(args.Key == "Enter") 18 | { 19 | items.Add(newItemValue); 20 | newItemValue = string.Empty; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /docs/samples/components/ChildContentParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Components; 6 | using Microsoft.AspNetCore.Components.Web; 7 | 8 | namespace Bunit.Docs.Samples 9 | { 10 | public class ChildContentParams : ComponentBase 11 | { 12 | [Parameter] 13 | public RenderFragment ChildContent { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docs/samples/components/ClickMe.razor: -------------------------------------------------------------------------------- 1 | 2 | @code 3 | { 4 | void ClickHandler(MouseEventArgs args) 5 | { 6 | // ... 7 | } 8 | } -------------------------------------------------------------------------------- /docs/samples/components/Counter.razor: -------------------------------------------------------------------------------- 1 |

Counter

2 | 3 |

4 | Current count: @currentCount 5 |

6 | 7 | 8 | 9 | @code { 10 | int currentCount = 0; 11 | 12 | void IncrementCount() 13 | { 14 | currentCount++; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/samples/components/CounterWithFancyParagraph.razor: -------------------------------------------------------------------------------- 1 |

Counter

2 | 3 | 4 | 5 | 6 | 7 | @code { 8 | int currentCount = 0; 9 | 10 | void IncrementCount() 11 | { 12 | currentCount++; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /docs/samples/components/DisposableComponent.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Routing 2 | @implements IDisposable 3 | @inject NavigationManager NavigationManager 4 | @code { 5 | [Parameter] public Action LocationChangedCallback { get; set; } 6 | 7 | protected override void OnInitialized() 8 | { 9 | NavigationManager.LocationChanged += OnLocationChanged; 10 | } 11 | 12 | public void Dispose() 13 | { 14 | NavigationManager.LocationChanged -= OnLocationChanged; 15 | } 16 | 17 | private void OnLocationChanged(object sender, LocationChangedEventArgs e) 18 | { 19 | LocationChangedCallback(e.Location); 20 | } 21 | } -------------------------------------------------------------------------------- /docs/samples/components/EventCallbackParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Components; 6 | using Microsoft.AspNetCore.Components.Web; 7 | 8 | namespace Bunit.Docs.Samples 9 | { 10 | public class EventCallbackParams : ComponentBase 11 | { 12 | [Parameter] 13 | public EventCallback OnClick { get; set; } 14 | 15 | [Parameter] 16 | public EventCallback OnSomething { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/samples/components/ExceptionInDisposeAsyncComponent.razor: -------------------------------------------------------------------------------- 1 | @implements IAsyncDisposable 2 | @code { 3 | public async ValueTask DisposeAsync() 4 | { 5 | await Task.Delay(10); 6 | throw new NotSupportedException(); 7 | } 8 | } -------------------------------------------------------------------------------- /docs/samples/components/ExceptionInDisposeComponent.razor: -------------------------------------------------------------------------------- 1 | @implements IDisposable 2 | @code { 3 | public void Dispose() 4 | { 5 | throw new NotSupportedException(); 6 | } 7 | } -------------------------------------------------------------------------------- /docs/samples/components/FancyParagraph.razor: -------------------------------------------------------------------------------- 1 |

@Text

2 | @code { 3 | [Parameter] 4 | public string Text { get; set; } 5 | } -------------------------------------------------------------------------------- /docs/samples/components/FancyTable.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
Lorem lipsum captium
FooBar
BazBoo
-------------------------------------------------------------------------------- /docs/samples/components/Foo.razor: -------------------------------------------------------------------------------- 1 | Foo -------------------------------------------------------------------------------- /docs/samples/components/Heading.razor: -------------------------------------------------------------------------------- 1 |

2 | Heading text 3 | 4 | Secondary text 5 | 6 |

-------------------------------------------------------------------------------- /docs/samples/components/HelloWorld.razor: -------------------------------------------------------------------------------- 1 |

Hello world from Blazor

-------------------------------------------------------------------------------- /docs/samples/components/InjectAuthService.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | @inject AuthenticationStateProvider AuthenticationStateProvider 3 | 4 |

Test Component

5 | 6 | @if (isAuthenticated) 7 | { 8 |

User: @userName

9 | } 10 | 11 | @code{ 12 | bool isAuthenticated = false; 13 | string userName; 14 | 15 | protected override async Task OnInitializedAsync() 16 | { 17 | var state = await AuthenticationStateProvider.GetAuthenticationStateAsync().ConfigureAwait(false); 18 | if (state != null) 19 | { 20 | this.isAuthenticated = state.User.Identity.IsAuthenticated; 21 | this.userName = state.User.Identity.Name; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/samples/components/Item.razor: -------------------------------------------------------------------------------- 1 | @Value 2 | @code 3 | { 4 | [Parameter] 5 | public string Value { get; set; } 6 | } -------------------------------------------------------------------------------- /docs/samples/components/ListItem.razor: -------------------------------------------------------------------------------- 1 |
@Value
2 | 3 | @code { 4 | [Parameter] public string Value { get; set; } = string.Empty; 5 | } 6 | -------------------------------------------------------------------------------- /docs/samples/components/NonBlazorTypesParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Components; 6 | using Microsoft.AspNetCore.Components.Web; 7 | 8 | namespace Bunit.Docs.Samples 9 | { 10 | public class NonBlazorTypesParams : ComponentBase 11 | { 12 | [Parameter] 13 | public int Numbers { get; set; } 14 | 15 | [Parameter] 16 | public List Lines { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/samples/components/PrintCascadingValue.razor: -------------------------------------------------------------------------------- 1 | Cascading value: @Value 2 | @code 3 | { 4 | [CascadingParameter] 5 | public string Value { get; set; } 6 | } -------------------------------------------------------------------------------- /docs/samples/components/RenderFragmentParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNetCore.Components; 5 | using Microsoft.AspNetCore.Components.Web; 6 | 7 | namespace Bunit.Docs.Samples 8 | { 9 | public class RenderFragmentParams : ComponentBase 10 | { 11 | [Parameter] 12 | public RenderFragment Content { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /docs/samples/components/SimpleTodo.razor: -------------------------------------------------------------------------------- 1 | @inject List Tasks 2 | 3 |
4 | 5 | 6 |
7 |
    8 | @foreach (var task in Tasks) 9 | { 10 |
  • @task
  • 11 | } 12 |
13 | @code { 14 | [CascadingParameter(Name = "Theme")] 15 | public string ThemeClass { get; set; } = string.Empty; 16 | 17 | private string newTaskValue = string.Empty; 18 | 19 | private void HandleTaskAdded() 20 | { 21 | if (!string.IsNullOrWhiteSpace(newTaskValue)) 22 | Tasks.Add(newTaskValue); 23 | 24 | newTaskValue = string.Empty; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/samples/components/TemplateParams.razor: -------------------------------------------------------------------------------- 1 | @typeparam TItem 2 | 3 |
4 | @foreach (var item in Items) 5 | { 6 | @Template(item) 7 | } 8 |
9 | 10 | @code 11 | { 12 | [Parameter] 13 | public IEnumerable Items { get; set; } 14 | 15 | [Parameter] 16 | public RenderFragment Template { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /docs/samples/components/TwoWayBinding.razor: -------------------------------------------------------------------------------- 1 | @code { 2 | [Parameter] public string Value { get; set; } = string.Empty; 3 | [Parameter] public EventCallback ValueChanged { get; set; } 4 | } -------------------------------------------------------------------------------- /docs/samples/components/UnmatchedParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Components; 6 | using Microsoft.AspNetCore.Components.Web; 7 | 8 | namespace Bunit.Docs.Samples 9 | { 10 | public class UnmatchedParams : ComponentBase 11 | { 12 | [Parameter(CaptureUnmatchedValues = true)] 13 | public Dictionary InputAttributes { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /docs/samples/components/UserInfo.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | @inject AuthenticationStateProvider AuthenticationStateProvider 3 | 4 | @if (isAuthenticated) 5 | { 6 |

Welcome @userName

7 | } 8 | @if (!isAuthenticated) 9 | { 10 |

Please log in!

11 | } 12 | 13 | 14 |

State: Authorized

15 |
16 | 17 |

State: Authorizing

18 |
19 | 20 |

State: Not authorized

21 |
22 |
23 | @code 24 | { 25 | bool isAuthenticated = false; 26 | string userName; 27 | 28 | protected override async Task OnParametersSetAsync() 29 | { 30 | var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); 31 | isAuthenticated = state.User.Identity.IsAuthenticated; 32 | userName = state.User.Identity.Name; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/samples/components/WeatherForecastService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | 5 | namespace Bunit.Docs.Samples 6 | { 7 | public interface IWeatherForecastService 8 | { 9 | Task GetForecastAsync(DateTime startDate); 10 | } 11 | 12 | public class WeatherForecast 13 | { 14 | public DateTime Date { get; set; } 15 | 16 | public int TemperatureC { get; set; } 17 | 18 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 19 | 20 | public string Summary { get; set; } 21 | } 22 | 23 | public class WeatherForecastService : IWeatherForecastService 24 | { 25 | public Task GetForecastAsync(DateTime startDate) 26 | => Task.FromResult(Array.Empty()); 27 | } 28 | } -------------------------------------------------------------------------------- /docs/samples/components/WeatherForecastTabel.razor: -------------------------------------------------------------------------------- 1 | @code 2 | { 3 | [Parameter] public IEnumerable Forecasts { get; set; } 4 | } -------------------------------------------------------------------------------- /docs/samples/components/WeatherForecasts.razor: -------------------------------------------------------------------------------- 1 | @inject IWeatherForecastService ForecastService 2 | 3 |

Weather forecast

4 | 5 |

This component demonstrates fetching data from a service.

6 | 7 | @if (Forecasts is null) 8 | { 9 |

Loading...

10 | } 11 | else 12 | { 13 | 14 | } 15 | 16 | @code 17 | { 18 | public WeatherForecast[] Forecasts { get; private set; } 19 | 20 | protected override async Task OnInitializedAsync() 21 | { 22 | Forecasts = await ForecastService.GetForecastAsync(DateTime.Now); 23 | } 24 | } -------------------------------------------------------------------------------- /docs/samples/components/Wrapper.razor: -------------------------------------------------------------------------------- 1 | @ChildContent 2 | 3 | @code 4 | { 5 | [Parameter] 6 | public RenderFragment ChildContent { get; set; } 7 | } -------------------------------------------------------------------------------- /docs/samples/components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @namespace Bunit.Docs.Samples 2 | @using Microsoft.AspNetCore.Components 3 | @using Microsoft.AspNetCore.Components.Web 4 | -------------------------------------------------------------------------------- /docs/samples/components/bunit.docs.samples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0;net9.0;net10.0 5 | Bunit.Docs.Samples 6 | enable 7 | CA1014,NU5104 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/samples/tests/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0;net9.0;net10.0 4 | false 5 | true 6 | false 7 | true 8 | latest 9 | enable 10 | CA1014,NU5104,xUnit1031 11 | false 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/samples/tests/mstest/HelloWorldExplicitContextTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Bunit; 3 | 4 | namespace Bunit.Docs.Samples; 5 | 6 | [TestClass] 7 | public class HelloWorldExplicitContext 8 | { 9 | [TestMethod] 10 | public void HelloWorldComponentRendersCorrectly() 11 | { 12 | // Arrange 13 | using var ctx = new Bunit.BunitContext(); 14 | 15 | // Act 16 | var cut = ctx.Render(); 17 | 18 | // Assert 19 | cut.MarkupMatches("

Hello world from Blazor

"); 20 | } 21 | } -------------------------------------------------------------------------------- /docs/samples/tests/mstest/HelloWorldRazorTest.razor: -------------------------------------------------------------------------------- 1 | @attribute [TestClass] 2 | @inherits BunitContext 3 | @code 4 | { 5 | [TestMethod] 6 | public void HelloWorldComponentRendersCorrectly() 7 | { 8 | // Act 9 | var cut = Render(@); 10 | 11 | // Assert 12 | cut.MarkupMatches(@

Hello world from Blazor

); 13 | } 14 | } -------------------------------------------------------------------------------- /docs/samples/tests/mstest/HelloWorldTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Docs.Samples; 2 | 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using Bunit; 5 | 6 | [TestClass] 7 | public class HelloWorldTest : BunitContext 8 | { 9 | [TestMethod] 10 | public void HelloWorldComponentRendersCorrectly() 11 | { 12 | // Act 13 | var cut = Render(); 14 | 15 | // Assert 16 | cut.MarkupMatches("

Hello world from Blazor

"); 17 | } 18 | } -------------------------------------------------------------------------------- /docs/samples/tests/mstest/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Forms 2 | @using Microsoft.AspNetCore.Components.Web 3 | @using Microsoft.JSInterop 4 | @using Microsoft.Extensions.DependencyInjection 5 | @using AngleSharp.Dom 6 | @using Bunit 7 | @using Bunit.TestDoubles 8 | @using Microsoft.VisualStudio.TestTools.UnitTesting -------------------------------------------------------------------------------- /docs/samples/tests/mstest/bunit.docs.mstest.samples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bunit.Docs.Samples 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/samples/tests/nunit/HelloWorldExplicitContextTest.cs: -------------------------------------------------------------------------------- 1 | using Bunit; 2 | using NUnit.Framework; 3 | 4 | namespace Bunit.Docs.Samples; 5 | 6 | public class HelloWorldExplicitContext 7 | { 8 | [Test] 9 | public void HelloWorldComponentRendersCorrectly() 10 | { 11 | // Arrange 12 | using var ctx = new Bunit.BunitContext(); 13 | 14 | // Act 15 | var cut = ctx.Render(); 16 | 17 | // Assert 18 | cut.MarkupMatches("

Hello world from Blazor

"); 19 | } 20 | } -------------------------------------------------------------------------------- /docs/samples/tests/nunit/HelloWorldInstancePerTestCase.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Bunit.Docs.Samples; 4 | 5 | [FixtureLifeCycle(LifeCycle.InstancePerTestCase)] 6 | public class HelloWorldInstancePerTestCase : Bunit.BunitContext 7 | { 8 | [Test] 9 | public void HelloWorldComponentRendersCorrectly() 10 | { 11 | // Act 12 | var cut = Render(); 13 | 14 | // Assert 15 | cut.MarkupMatches("

Hello world from Blazor

"); 16 | } 17 | } -------------------------------------------------------------------------------- /docs/samples/tests/nunit/HelloWorldRazorInstancePerTestCase.razor: -------------------------------------------------------------------------------- 1 | @attribute [FixtureLifeCycle(LifeCycle.InstancePerTestCase)] 2 | @inherits Bunit.BunitContext 3 | 4 | @code { 5 | [Test] 6 | public void HelloWorldComponentRendersCorrectly() 7 | { 8 | // Act 9 | var cut = Render(@); 10 | 11 | // Assert 12 | cut.MarkupMatches(@

Hello world from Blazor

); 13 | } 14 | } -------------------------------------------------------------------------------- /docs/samples/tests/nunit/HelloWorldRazorTest.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | @code 3 | { 4 | [Test] 5 | public void HelloWorldComponentRendersCorrectly() 6 | { 7 | // Act 8 | var cut = Render(@); 9 | 10 | // Assert 11 | cut.MarkupMatches(@

Hello world from Blazor

); 12 | } 13 | } -------------------------------------------------------------------------------- /docs/samples/tests/nunit/HelloWorldTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Docs.Samples; 2 | 3 | using Bunit; 4 | using NUnit.Framework; 5 | 6 | public class HelloWorldTest : BunitContext 7 | { 8 | [Test] 9 | public void HelloWorldComponentRendersCorrectly() 10 | { 11 | // Act 12 | var cut = Render(); 13 | 14 | // Assert 15 | cut.MarkupMatches("

Hello world from Blazor

"); 16 | } 17 | } -------------------------------------------------------------------------------- /docs/samples/tests/nunit/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Forms 2 | @using Microsoft.AspNetCore.Components.Web 3 | @using Microsoft.JSInterop 4 | @using Microsoft.Extensions.DependencyInjection 5 | @using AngleSharp.Dom 6 | @using Bunit 7 | @using Bunit.TestDoubles 8 | @using NUnit.Framework -------------------------------------------------------------------------------- /docs/samples/tests/nunit/bunit.docs.nunit.samples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bunit.Docs.Samples 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/samples/tests/razor/CascadingParams1Test.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | var isDarkTheme = true; 9 | 10 | var cut = Render(@ 11 | 12 | ); 13 | } 14 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/CascadingParams2Test.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | var cut = Render(@ 9 | 10 | ); 11 | } 12 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/CascadingParams3Test.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | var isDarkTheme = true; 9 | 10 | var cut = Render(@ 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | } 18 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/ChildContentParams1Test.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | var cut = Render(@ 9 |

Hello World

10 |
); 11 | } 12 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/ChildContentParams2Test.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | var cut = Render(@ 9 | 10 | ); 11 | } 12 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/ChildContentParams3Test.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | var cut = Render(@ 9 | 10 |

Hello World

11 |
12 |
); 13 | } 14 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/ChildContentParams4Test.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | var cut = Render(@ 9 |

Below you will find a most interesting alert!

10 | 11 |

Hello World

12 |
13 |
); 14 | } 15 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/ClickMeTest.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | 3 | @code 4 | { 5 | [Fact] 6 | public void Test() 7 | { 8 | // Arrange 9 | var cut = Render(@); 10 | var buttonElement = cut.Find("button"); 11 | 12 | // Act 13 | buttonElement.Click(); 14 | buttonElement.Click(new MouseEventArgs { Detail = 3, CtrlKey = true }); 15 | buttonElement.Click(new MouseEventArgs()); 16 | 17 | // Assert 18 | // ... 19 | } 20 | } -------------------------------------------------------------------------------- /docs/samples/tests/razor/CounterTest.razor: -------------------------------------------------------------------------------- 1 | @inherits BunitContext 2 | @code { 3 | [Fact] 4 | public void CounterShouldIncrementWhenClicked() 5 | { 6 | // Arrange: render the Counter.razor component 7 | var cut = Render(@); 8 | 9 | // Act: find and click the 8 | 9 | @code { 10 | int currentCount = 0; 11 | 12 | void IncrementCount() 13 | { 14 | currentCount++; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/bunit.template/template/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @using Microsoft.JSInterop 3 | @using Microsoft.Extensions.DependencyInjection 4 | @using Bunit 5 | @using Bunit.TestDoubles 6 | @*#if (testFramework_xunit)*@ 7 | @using Xunit 8 | @*#elif (testFramework_xunitv3)*@ 9 | @using Xunit 10 | @*#elif (testFramework_nunit)*@ 11 | @using NUnit.Framework 12 | @*#elif (testFramework_mstest)*@ 13 | @using Microsoft.VisualStudio.TestTools.UnitTesting 14 | @*#endif*@ 15 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/ByLabelTextOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | /// Allows overrides of behavior for FindByLabelText method 5 | /// 6 | public record class ByLabelTextOptions 7 | { 8 | /// 9 | /// The default behavior used by FindByLabelText if no overrides are specified 10 | /// 11 | internal static readonly ByLabelTextOptions Default = new(); 12 | 13 | /// 14 | /// The StringComparison used for comparing the desired Label Text to the resulting HTML. Defaults to Ordinal (case sensitive). 15 | /// 16 | public StringComparison ComparisonType { get; set; } = StringComparison.Ordinal; 17 | } 18 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/LabelElementExtensions.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Dom; 2 | 3 | namespace Bunit; 4 | 5 | internal static class LabelElementExtensions 6 | { 7 | internal static bool IsHtmlElementThatCanHaveALabel(this IElement element) => element.NodeName switch 8 | { 9 | "INPUT" => true, 10 | "SELECT" => true, 11 | "TEXTAREA" => true, 12 | "BUTTON" => true, 13 | "METER" => true, 14 | "OUTPUT" => true, 15 | "PROGRESS" => true, 16 | _ => false 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/LabelNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | /// Represents a failure to find an element in the searched target 5 | /// using the Label's text. 6 | /// 7 | public sealed class LabelNotFoundException : Exception 8 | { 9 | /// 10 | /// Gets the Label Text used to search with. 11 | /// 12 | public string LabelText { get; } 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// 18 | public LabelNotFoundException(string labelText) 19 | : base($"Unable to find a label with the text of '{labelText}'.") 20 | { 21 | LabelText = labelText; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/Strategies/ILabelTextQueryStrategy.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Dom; 2 | 3 | namespace Bunit.Labels.Strategies; 4 | 5 | internal interface ILabelTextQueryStrategy 6 | { 7 | IElement? FindElement(IRenderedComponent renderedComponent, string labelText, ByLabelTextOptions options); 8 | } 9 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/Strategies/LabelTextUsingAriaLabelStrategy.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Dom; 2 | using Bunit.Web.AngleSharp; 3 | 4 | namespace Bunit.Labels.Strategies; 5 | 6 | internal sealed class LabelTextUsingAriaLabelStrategy : ILabelTextQueryStrategy 7 | { 8 | public IElement? FindElement(IRenderedComponent renderedComponent, string labelText, ByLabelTextOptions options) 9 | { 10 | var caseSensitivityQualifier = options.ComparisonType switch 11 | { 12 | StringComparison.OrdinalIgnoreCase => "i", 13 | StringComparison.InvariantCultureIgnoreCase => "i", 14 | StringComparison.CurrentCultureIgnoreCase => "i", 15 | _ => "" 16 | }; 17 | 18 | var element = renderedComponent.Nodes.TryQuerySelector($"[aria-label='{labelText}'{caseSensitivityQualifier}]"); 19 | 20 | if (element is null) 21 | return null; 22 | 23 | return element.WrapUsing(new ByLabelTextElementFactory(renderedComponent, labelText, options)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/Strategies/LabelTextUsingAriaLabelledByStrategy.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Dom; 2 | using Bunit.Web.AngleSharp; 3 | 4 | namespace Bunit.Labels.Strategies; 5 | 6 | internal sealed class LabelTextUsingAriaLabelledByStrategy : ILabelTextQueryStrategy 7 | { 8 | public IElement? FindElement(IRenderedComponent renderedComponent, string labelText, ByLabelTextOptions options) 9 | { 10 | var elementsWithAriaLabelledBy = renderedComponent.Nodes.TryQuerySelectorAll("[aria-labelledby]"); 11 | 12 | foreach (var element in elementsWithAriaLabelledBy) 13 | { 14 | var labelElement = renderedComponent.Nodes.TryQuerySelector($"#{element.GetAttribute("aria-labelledby")}"); 15 | if (labelElement is not null && labelElement.GetInnerText().Equals(labelText, options.ComparisonType)) 16 | return element.WrapUsing(new ByLabelTextElementFactory(renderedComponent, labelText, options)); 17 | } 18 | 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/Strategies/LabelTextUsingForAttributeStrategy.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Dom; 2 | using Bunit.Web.AngleSharp; 3 | 4 | namespace Bunit.Labels.Strategies; 5 | 6 | internal sealed class LabelTextUsingForAttributeStrategy : ILabelTextQueryStrategy 7 | { 8 | public IElement? FindElement(IRenderedComponent renderedComponent, string labelText, ByLabelTextOptions options) 9 | { 10 | var matchingLabel = renderedComponent.Nodes.TryQuerySelectorAll("label") 11 | .SingleOrDefault(l => l.TextContent.Trim().Equals(labelText, options.ComparisonType)); 12 | 13 | if (matchingLabel is null) 14 | return null; 15 | 16 | var matchingElement = renderedComponent.Nodes.TryQuerySelector($"#{matchingLabel.GetAttribute("for")}"); 17 | 18 | if (matchingElement is null) 19 | return null; 20 | 21 | return matchingElement.WrapUsing(new ByLabelTextElementFactory(renderedComponent, labelText, options)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/bunit.web.query/Labels/Strategies/LabelTextUsingWrappedElementStrategy.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Dom; 2 | using Bunit.Web.AngleSharp; 3 | 4 | namespace Bunit.Labels.Strategies; 5 | 6 | internal sealed class LabelTextUsingWrappedElementStrategy : ILabelTextQueryStrategy 7 | { 8 | public IElement? FindElement(IRenderedComponent renderedComponent, string labelText, ByLabelTextOptions options) 9 | { 10 | var matchingLabel = renderedComponent.Nodes.TryQuerySelectorAll("label") 11 | .SingleOrDefault(l => l.GetInnerText().Trim().StartsWith(labelText, options.ComparisonType)); 12 | 13 | var matchingElement = matchingLabel? 14 | .Children 15 | .SingleOrDefault(n => n.IsHtmlElementThatCanHaveALabel()); 16 | 17 | return matchingElement?.WrapUsing(new ByLabelTextElementFactory(renderedComponent, labelText, options)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/bunit/Asserting/AssertionMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Asserting; 2 | 3 | /// 4 | /// Add this attribute to assertion methods to indicate to 5 | /// 3rd party analyzers that the method is an assertion method. 6 | /// See more here: https://rules.sonarsource.com/csharp/RSPEC-2699. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public sealed class AssertionMethodAttribute : Attribute { } 10 | -------------------------------------------------------------------------------- /src/bunit/Asserting/XUnitExceptions/IAssertionException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Asserting.XUnitExceptions; 2 | 3 | /// 4 | /// This is a marker interface for xUnit.v3 that will cause xUnit to consider the failure cause to be an assertion failure. 5 | /// 6 | internal interface IAssertionException; 7 | -------------------------------------------------------------------------------- /src/bunit/Asserting/XUnitExceptions/ITestTimeoutException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Asserting.XUnitExceptions; 2 | 3 | /// 4 | /// This is a marker interface for xUnit.v3 that will cause xUnit to consider the failure cause to be a timeout. 5 | /// 6 | internal interface ITestTimeoutException; 7 | -------------------------------------------------------------------------------- /src/bunit/ComponentFactories/ConditionalComponentFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.ComponentFactories; 2 | 3 | internal sealed class ConditionalComponentFactory : IComponentFactory 4 | { 5 | private readonly Predicate condition; 6 | private readonly Func factory; 7 | 8 | public ConditionalComponentFactory(Predicate condition, Func factory) 9 | { 10 | this.condition = condition; 11 | this.factory = factory; 12 | } 13 | 14 | public bool CanCreate(Type componentType) 15 | => condition(componentType); 16 | 17 | public IComponent Create(Type componentType) 18 | => factory(componentType); 19 | } 20 | -------------------------------------------------------------------------------- /src/bunit/ComponentFactories/GenericComponentFactory{TComponent,TSubstituteComponent}.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.ComponentFactories; 2 | 3 | internal sealed class GenericComponentFactory : IComponentFactory 4 | where TComponent : IComponent 5 | where TSubstituteComponent : IComponent, new() 6 | { 7 | public bool CanCreate(Type componentType) => componentType == typeof(TComponent); 8 | 9 | public IComponent Create(Type componentType) => new TSubstituteComponent(); 10 | } 11 | -------------------------------------------------------------------------------- /src/bunit/ComponentFactories/InstanceComponentFactory{TComponent}.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.ComponentFactories; 2 | 3 | internal sealed class InstanceComponentFactory : IComponentFactory 4 | where TComponent : IComponent 5 | { 6 | private readonly TComponent instance; 7 | private int createCount; 8 | 9 | public InstanceComponentFactory(TComponent instance) 10 | => this.instance = instance; 11 | 12 | public bool CanCreate(Type componentType) 13 | => componentType == typeof(TComponent); 14 | 15 | public IComponent Create(Type componentType) 16 | { 17 | if (createCount == 1) 18 | { 19 | throw new InvalidOperationException( 20 | $"The instance object passed to the" + 21 | $"{nameof(BunitContext.ComponentFactories)}.{nameof(ComponentFactoryCollectionExtensions.Add)}<{typeof(TComponent).Name}>(instance) method can only be used to replace " + 22 | $"one {typeof(TComponent)} component in the render tree."); 23 | } 24 | 25 | createCount++; 26 | 27 | return instance; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/bunit/ComponentFactories/StubComponentFactory.cs: -------------------------------------------------------------------------------- 1 | using Bunit.TestDoubles; 2 | 3 | namespace Bunit.ComponentFactories; 4 | 5 | internal sealed class StubComponentFactory : IComponentFactory 6 | { 7 | private static readonly Type StubType = typeof(Stub<>); 8 | 9 | private readonly Predicate componentTypePredicate; 10 | private readonly object? replacementContent; 11 | 12 | public StubComponentFactory(Predicate componentTypePredicate, object? replacementContent) 13 | { 14 | this.componentTypePredicate = componentTypePredicate; 15 | this.replacementContent = replacementContent; 16 | } 17 | 18 | public bool CanCreate(Type componentType) 19 | => componentTypePredicate.Invoke(componentType); 20 | 21 | public IComponent Create(Type componentType) 22 | { 23 | var typeToCreate = StubType.MakeGenericType(componentType); 24 | return (IComponent)Activator.CreateInstance(typeToCreate, replacementContent)!; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/bunit/ComponentFactories/TypeBasedComponentFactory{TComponent}.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.ComponentFactories; 2 | 3 | internal sealed class TypeBasedComponentFactory : IComponentFactory 4 | where TComponent : IComponent 5 | { 6 | private readonly Func componentFactory; 7 | 8 | public TypeBasedComponentFactory(Func componentFactory) 9 | => this.componentFactory = componentFactory; 10 | 11 | public bool CanCreate(Type componentType) 12 | => componentType == typeof(TComponent); 13 | 14 | public IComponent Create(Type componentType) 15 | => componentFactory.Invoke(); 16 | } 17 | -------------------------------------------------------------------------------- /src/bunit/Extensions/BlazorExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Extensions; 2 | 3 | /// 4 | /// Extensions for Blazor types. 5 | /// 6 | internal static class BlazorExtensions 7 | { 8 | /// 9 | /// Creates a that will render the . 10 | /// 11 | /// Markup to render. 12 | /// The . 13 | public static RenderFragment ToMarkupRenderFragment([StringSyntax("Html")]this string? markup) 14 | { 15 | if (string.IsNullOrEmpty(markup)) 16 | return _ => { }; 17 | return 18 | builder => builder.AddMarkupContent(0, markup); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/bunit/Extensions/ElementNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | /// Represents a failure to find an element in the searched target 5 | /// using a CSS selector. 6 | /// 7 | public class ElementNotFoundException : Exception 8 | { 9 | /// 10 | /// Gets the CSS selector used to search with. 11 | /// 12 | public string CssSelector { get; } 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public ElementNotFoundException(string cssSelector) 18 | : base($"No elements were found that matches the selector '{cssSelector}'") 19 | { 20 | CssSelector = cssSelector; 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | protected ElementNotFoundException(string message, string cssSelector) 27 | : base(message) 28 | { 29 | CssSelector = cssSelector; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/bunit/Extensions/ElementRemovedFromDomException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | /// Represents an exception that is thrown when trying to access an element 5 | /// that was previously found in the DOM. 6 | /// 7 | public sealed class ElementRemovedFromDomException : ElementNotFoundException 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public ElementRemovedFromDomException(string cssSelector) 13 | : base($"The DOM element you tried to access, which you previously found with the CSS selector \"{cssSelector}\", is no longer available in the DOM tree. It has probably been removed after a render.", cssSelector) 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/bunit/Extensions/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Extensions; 2 | 3 | /// 4 | /// Helper methods for working with . 5 | /// 6 | internal static class EnumerableExtensions 7 | { 8 | /// 9 | /// Returns true if the enumerable is null or empty. 10 | /// 11 | public static bool IsNullOrEmpty([NotNullWhen(false)] this IEnumerable? enumerable) 12 | { 13 | return enumerable is null || !enumerable.Any(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/bunit/Extensions/InputFile/BUnitBrowserFile.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Forms; 2 | 3 | namespace Bunit; 4 | 5 | internal class BUnitBrowserFile : IBrowserFile 6 | { 7 | public string Name { get; } 8 | public DateTimeOffset LastModified { get; } 9 | public long Size { get; } 10 | public string ContentType { get; } 11 | public byte[] Content { get; } 12 | 13 | public BUnitBrowserFile( 14 | string name, 15 | DateTimeOffset lastModified, 16 | long size, 17 | string contentType, 18 | byte[] content) 19 | { 20 | Name = name; 21 | LastModified = lastModified; 22 | Size = size; 23 | ContentType = contentType; 24 | Content = content; 25 | } 26 | 27 | public Stream OpenReadStream(long maxAllowedSize = 512000, CancellationToken cancellationToken = default) 28 | { 29 | if (Size > maxAllowedSize) 30 | { 31 | throw new IOException($"Supplied file with size {Size} bytes exceeds the maximum of {maxAllowedSize} bytes."); 32 | } 33 | 34 | return new MemoryStream(Content); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/bunit/Extensions/LoggerHelperExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using Microsoft.Extensions.Logging.Abstractions; 3 | 4 | namespace Bunit.Extensions; 5 | 6 | /// 7 | /// Helper extension methods for getting a logger. 8 | /// 9 | internal static class LoggerHelperExtensions 10 | { 11 | /// 12 | /// Creates a logger from the registered in the . 13 | /// 14 | /// The service to get the from. 15 | /// The category for the logger. 16 | /// The . 17 | public static ILogger CreateLogger(this IServiceProvider services) 18 | { 19 | var loggerFactory = services.GetService() ?? NullLoggerFactory.Instance; 20 | return loggerFactory.CreateLogger(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/bunit/IComponentFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | /// Represents a component factory. 5 | /// 6 | public interface IComponentFactory 7 | { 8 | /// 9 | /// Check if the factory can create a component of type or a replacement for it. 10 | /// 11 | /// The type that should be created or replaced. 12 | /// True if the factory can create the type; false otherwise. 13 | bool CanCreate(Type componentType); 14 | 15 | /// 16 | /// Create a component of type or a replacement for it. 17 | /// 18 | /// The type of component to create. 19 | IComponent Create(Type componentType); 20 | } 21 | -------------------------------------------------------------------------------- /src/bunit/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Bunit.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010001be6b1a2ca57b09b7040e2ab0993e515296ae22aef4031a4fe388a1336fe21f69c7e8610e9935de6ed18d94b5c98429f99ef62ce3d0af28a7088f856239368ea808ad4c448aa2a8075ed581f989f36ed0d0b8b1cfcaf1ff6a4506c8a99b7024b6eb56996d08e3c9c1cf5db59bff96fcc63ccad155ef7fc63aab6a69862437b6")] 2 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/InvocationHandlers/Implementation/FocusAsyncInvocationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.JSInterop.InvocationHandlers.Implementation; 2 | 3 | /// 4 | /// Represents a handler for Blazor's 5 | /// feature. 6 | /// 7 | internal sealed class FocusAsyncInvocationHandler : JSRuntimeInvocationHandler 8 | { 9 | /// 10 | /// The internal identifier used by 11 | /// to call it JavaScript. 12 | /// 13 | public const string FocusIdentifier = "Blazor._internal.domWrapper.focus"; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | internal FocusAsyncInvocationHandler() 19 | : base(inv => inv.Identifier.Equals(FocusIdentifier, StringComparison.Ordinal), isCatchAllHandler: false) 20 | { 21 | SetVoidResult(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/InvocationHandlers/Implementation/FocusOnNavigateHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.JSInterop.InvocationHandlers.Implementation; 2 | 3 | /// 4 | /// Represents a handler for Blazor's 5 | /// feature. 6 | /// 7 | internal sealed class FocusOnNavigateHandler : JSRuntimeInvocationHandler 8 | { 9 | /// 10 | /// The internal identifier used by 11 | /// to call it JavaScript. 12 | /// 13 | public const string Identifier = "Blazor._internal.domWrapper.focusBySelector"; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | internal FocusOnNavigateHandler() 19 | : base(inv => inv.Identifier.Equals(Identifier, StringComparison.Ordinal), isCatchAllHandler: true) 20 | { 21 | SetVoidResult(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/InvocationHandlers/Implementation/InputFileInvocationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.JSInterop.InvocationHandlers.Implementation; 2 | 3 | internal sealed class InputFileInvocationHandler : JSRuntimeInvocationHandler 4 | { 5 | private const string Identifier = "Blazor._internal.InputFile.init"; 6 | 7 | internal InputFileInvocationHandler() 8 | : base(inv => inv.Identifier.Equals(Identifier, StringComparison.Ordinal), isCatchAllHandler: true) 9 | { 10 | SetVoidResult(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/InvocationHandlers/Implementation/LooseModeJSObjectReferenceInvocationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.JSInterop.InvocationHandlers.Implementation; 2 | 3 | /// 4 | /// Special mode invocation handler for . 5 | /// Will match all loose mode calls of the parent . 6 | /// 7 | internal sealed class LooseModeJSObjectReferenceInvocationHandler : JSRuntimeInvocationHandler 8 | { 9 | [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "BunitJSObjectReference doesn't have any disposable resources, it just implements the methods to be compatible with the interfaces it implements.")] 10 | internal LooseModeJSObjectReferenceInvocationHandler(BunitJSInterop parent) 11 | : base(_ => parent.Mode == JSRuntimeMode.Loose, isCatchAllHandler: true) 12 | { 13 | SetResult(new BunitJSObjectReference(parent)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/InvocationHandlers/Implementation/NavigationLockDisableNavigationPromptInvocationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.JSInterop.InvocationHandlers.Implementation; 2 | 3 | internal sealed class NavigationLockDisableNavigationPromptInvocationHandler : JSRuntimeInvocationHandler 4 | { 5 | private const string Identifier = "Blazor._internal.NavigationLock.disableNavigationPrompt"; 6 | 7 | internal NavigationLockDisableNavigationPromptInvocationHandler() 8 | : base(inv => inv.Identifier.Equals(Identifier, StringComparison.Ordinal), isCatchAllHandler: true) 9 | { 10 | SetVoidResult(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/InvocationHandlers/Implementation/NavigationLockEnableNavigationPromptInvocationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.JSInterop.InvocationHandlers.Implementation; 2 | 3 | internal sealed class NavigationLockEnableNavigationPromptInvocationHandler : JSRuntimeInvocationHandler 4 | { 5 | private const string Identifier = "Blazor._internal.NavigationLock.enableNavigationPrompt"; 6 | 7 | internal NavigationLockEnableNavigationPromptInvocationHandler() 8 | : base(inv => inv.Identifier.Equals(Identifier, StringComparison.Ordinal), isCatchAllHandler: true) 9 | { 10 | SetVoidResult(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/InvocationMatcher.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | /// Represents a invocation matcher / predicate, that is used to determine 5 | /// if a matches a specific 6 | /// . 7 | /// 8 | /// The invocation to match against. 9 | /// True if the can handle the invocation, false otherwise. 10 | public delegate bool InvocationMatcher(JSRuntimeInvocation invocation); 11 | -------------------------------------------------------------------------------- /src/bunit/JSInterop/JSRuntimeMode.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | /// The execution mode of the . 5 | /// 6 | public enum JSRuntimeMode 7 | { 8 | /// 9 | /// configures the to return default TValue 10 | /// for calls. 11 | /// 12 | Loose = 0, 13 | 14 | /// 15 | /// configures the to throw an 16 | /// exception when a call to 17 | /// for has not been 18 | /// setup. 19 | /// 20 | Strict, 21 | } 22 | -------------------------------------------------------------------------------- /src/bunit/Rendering/ComponentDisposedException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Rendering; 2 | 3 | /// 4 | /// Represents an exception that is thrown when a 's 5 | /// properties is accessed after the underlying component has been disposed by the renderer. 6 | /// 7 | public sealed class ComponentDisposedException : Exception 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// Id of the disposed component. 13 | public ComponentDisposedException(int componentId) 14 | : base($"The component has been removed from the render tree by the renderer and is no longer available for inspection. ComponentId = {componentId}.") 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/bunit/Rendering/ComponentNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Rendering; 2 | 3 | /// 4 | /// Represents an exception that is thrown when a search for a component did not succeed. 5 | /// 6 | public sealed class ComponentNotFoundException : Exception 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The type of component that was not found. 12 | public ComponentNotFoundException(Type componentType) 13 | : base($"A component of type {componentType?.Name} was not found in the render tree.") 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/bunit/Rendering/IRenderedComponent.cs: -------------------------------------------------------------------------------- 1 | using Bunit.Rendering; 2 | 3 | namespace Bunit; 4 | 5 | internal interface IRenderedComponent : IDisposable 6 | { 7 | /// 8 | /// Gets the id of the rendered component or fragment. 9 | /// 10 | int ComponentId { get; } 11 | 12 | /// 13 | /// Called by the owning when it finishes a render. 14 | /// 15 | void UpdateState(bool hasRendered, bool isMarkupGenerationRequired); 16 | } 17 | -------------------------------------------------------------------------------- /src/bunit/Rendering/RootComponent.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Rendering; 2 | 3 | /// 4 | /// Wrapper class that provides access to a . 5 | /// 6 | internal sealed class BunitRootComponent : IComponent 7 | { 8 | private readonly RenderFragment renderFragment; 9 | private RenderHandle renderHandle; 10 | 11 | public BunitRootComponent(RenderFragment renderFragment) => this.renderFragment = renderFragment; 12 | 13 | public void Attach(RenderHandle renderHandle) => this.renderHandle = renderHandle; 14 | 15 | public Task SetParametersAsync(ParameterView parameters) 16 | => throw new InvalidOperationException($"{nameof(BunitRootComponent)} shouldn't receive any parameters"); 17 | 18 | public void Render() => renderHandle.Render(renderFragment); 19 | 20 | public void Detach() => renderHandle.Render(_ => { }); 21 | } 22 | -------------------------------------------------------------------------------- /src/bunit/TestContext.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | /// 4 | [Obsolete($"Use {nameof(BunitContext)} instead. TestContext will be removed in a future release.", false, UrlFormat = "https://bunit.dev/docs/migrations")] 5 | public class TestContext : BunitContext 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/Authorization/AuthorizationState.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles; 2 | 3 | /// 4 | /// Enumeration that represents the user's authorization state. 5 | /// 6 | public enum AuthorizationState 7 | { 8 | /// 9 | /// Represents unauthorized user state. 10 | /// 11 | Unauthorized, 12 | 13 | /// 14 | /// Represents authorized user state. 15 | /// 16 | Authorized, 17 | 18 | /// 19 | /// Represents authorizing user state. 20 | /// 21 | Authorizing, 22 | } 23 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/Authorization/PlaceholderAuthenticationStateProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Authorization; 2 | 3 | namespace Bunit.TestDoubles; 4 | 5 | internal sealed class PlaceholderAuthenticationStateProvider : AuthenticationStateProvider 6 | { 7 | public override Task GetAuthenticationStateAsync() 8 | { 9 | throw new MissingBunitAuthorizationException(nameof(AuthenticationStateProvider)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/Authorization/PlaceholderAuthorizationService.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using Microsoft.AspNetCore.Authorization; 3 | 4 | namespace Bunit.TestDoubles; 5 | 6 | internal sealed class PlaceholderAuthorizationService : IAuthorizationService 7 | { 8 | public Task AuthorizeAsync(ClaimsPrincipal user, object? resource, IEnumerable requirements) 9 | { 10 | throw new MissingBunitAuthorizationException(nameof(IAuthorizationService)); 11 | } 12 | 13 | public Task AuthorizeAsync(ClaimsPrincipal user, object? resource, string policyName) 14 | { 15 | throw new MissingBunitAuthorizationException(nameof(IAuthorizationService)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/Authorization/TestPolicyRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace Bunit.TestDoubles; 4 | 5 | /// 6 | /// Test requirement that supports the minimum requirement - just a policy name. 7 | /// 8 | public class TestPolicyRequirement : IAuthorizationRequirement 9 | { 10 | /// 11 | /// Gets or sets the policy name for this requirement. 12 | /// 13 | public string PolicyName { get; set; } = string.Empty; 14 | } 15 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/Components/ParameterNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles; 2 | 3 | /// 4 | /// Represents an exception which is thrown when the 5 | /// 6 | /// is used to get a parameter that was not passed to the doubled component. 7 | /// 8 | public sealed class ParameterNotFoundException : Exception 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// 14 | /// 15 | public ParameterNotFoundException(string parameterName, string componentName) 16 | : base($"The parameter '{parameterName}' was not passed to the component '{componentName}' when it was rendered.") 17 | { } 18 | } 19 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/HttpClient/PlaceholderHttpClient.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles; 2 | 3 | /// 4 | /// This PlaceholderHttpClient is used to provide users with helpful exceptions if they fail to provide a mock when required. 5 | /// 6 | internal sealed class PlaceholderHttpClient : HttpClient 7 | { 8 | private const string PlaceholderBaseAddress = "http://localhost"; 9 | 10 | [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by base HttpClient.")] 11 | public PlaceholderHttpClient() 12 | : base(new PlaceholderHttpMessageHandler(), disposeHandler: true) 13 | { 14 | BaseAddress = new Uri(PlaceholderBaseAddress); 15 | } 16 | 17 | private sealed class PlaceholderHttpMessageHandler : HttpMessageHandler 18 | { 19 | protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 20 | => throw new MissingMockHttpClientException(request); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/NavigationInterception/BunitNavigationInterception.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Routing; 2 | 3 | namespace Bunit.TestDoubles; 4 | 5 | internal sealed class BunitNavigationInterception : INavigationInterception 6 | { 7 | public Task EnableNavigationInterceptionAsync() => Task.CompletedTask; 8 | } 9 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/NavigationManager/NavigationState.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles; 2 | 3 | /// 4 | /// Describes the possible enumerations when a navigation gets intercepted. 5 | /// 6 | public enum NavigationState 7 | { 8 | /// 9 | /// The navigation was successfully executed. 10 | /// 11 | Succeeded, 12 | 13 | /// 14 | /// The navigation was prevented. 15 | /// 16 | Prevented, 17 | 18 | /// 19 | /// The OnBeforeInternalNavigation event handler threw an exception and the navigation did not complete. 20 | /// 21 | Faulted 22 | } 23 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/PersistentComponentState/BunitPersistentComponentStateStore.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles; 2 | 3 | internal class BunitPersistentComponentStateStore : IPersistentComponentStateStore 4 | { 5 | private readonly Dictionary state = new(StringComparer.Ordinal); 6 | 7 | public void Add(string key, byte[] value) 8 | { 9 | state[key] = value; 10 | } 11 | 12 | public Task> GetPersistedStateAsync() 13 | => Task.FromResult>(state); 14 | 15 | public Task PersistStateAsync(IReadOnlyDictionary state) 16 | { 17 | foreach (var (key, value) in state) 18 | { 19 | Add(key, value); 20 | } 21 | 22 | return Task.CompletedTask; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/PersistentComponentState/TestContextExtensions.cs: -------------------------------------------------------------------------------- 1 | using Bunit.TestDoubles; 2 | using Microsoft.AspNetCore.Components.Infrastructure; 3 | 4 | namespace Bunit; 5 | 6 | public partial class BunitContext 7 | { 8 | /// 9 | /// Adds and returns a to the services of this . 10 | /// 11 | /// The added . 12 | public BunitPersistentComponentState AddBunitPersistentComponentState() 13 | { 14 | Services.AddSingleton(); 15 | Services.AddSingleton(s => s.GetRequiredService().State); 16 | return new BunitPersistentComponentState(Services); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/bunit/TestDoubles/ScrollToLocationHash/BunitScrollToLocationHash.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Routing; 2 | 3 | namespace Bunit.TestDoubles; 4 | 5 | internal sealed class BunitScrollToLocationHash : IScrollToLocationHash 6 | { 7 | public Task RefreshScrollPositionForHash(string locationAbsolute) => Task.CompletedTask; 8 | } 9 | -------------------------------------------------------------------------------- /tests/bunit.generators.tests/VerifyInitializer.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace Bunit; 4 | 5 | internal static class VerifyInitializer 6 | { 7 | [ModuleInitializer] 8 | public static void Init() => 9 | VerifySourceGenerators.Initialize(); 10 | } -------------------------------------------------------------------------------- /tests/bunit.generators.tests/Web.AngleSharp/WrapperElementsGeneratorTest.Generator#IElementWrapper.g.verified.cs: -------------------------------------------------------------------------------- 1 | //HintName: IElementWrapper.g.cs 2 | #nullable enable 3 | using AngleSharp.Dom; 4 | using System.CodeDom.Compiler; 5 | 6 | namespace Bunit.Web.AngleSharp; 7 | 8 | /// 9 | /// Represents a wrapper around an . 10 | /// 11 | [GeneratedCodeAttribute("Bunit.Web.AngleSharp", "1.0.0.0")] 12 | public interface IElementWrapper where TElement : class, IElement 13 | { 14 | /// 15 | /// Gets the wrapped element. 16 | /// 17 | TElement WrappedElement { get; } 18 | } 19 | #nullable restore 20 | -------------------------------------------------------------------------------- /tests/bunit.generators.tests/Web.Stub/Components/ButtonComponent.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Bunit.Web.Stub.Components; 5 | 6 | public class ButtonComponent : ComponentBase 7 | { 8 | [Parameter] public string Text { get; set; } 9 | [Parameter] public EventCallback OnClick { get; set; } 10 | [CascadingParameter(Name = "Test")] public string Cascading { get; set; } 11 | [Required] public string Unused { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /tests/bunit.generators.tests/Web.Stub/Components/ContainerComponent.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Web.Stub.Components; 2 | 3 | public class ContainerComponent : ComponentBase 4 | { 5 | [Parameter] 6 | public RenderFragment ChildContent { get; set; } 7 | 8 | protected override void BuildRenderTree(RenderTreeBuilder builder) 9 | { 10 | builder.OpenElement(0, "div"); 11 | builder.AddContent(1, ChildContent); 12 | builder.CloseElement(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/bunit.generators.tests/Web.Stub/Components/CounterComponent.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Bunit.Web.Stub.Components; 5 | 6 | public class CounterComponent : ComponentBase 7 | { 8 | [Parameter] public int Count { get; set; } 9 | [CascadingParameter(Name = "Cascading")] public int CascadingCount { get; set; } 10 | 11 | [Parameter(CaptureUnmatchedValues = true)] 12 | private Dictionary? UnmatchedValues { get; set; } 13 | 14 | [SuppressMessage("Design", "CS0246: The type or namespace name could not be found", 15 | Justification = "This is on purpose")] 16 | [Required] 17 | public string Unused { get; set; } = default!; 18 | } 19 | -------------------------------------------------------------------------------- /tests/bunit.generators.tests/Web.Stub/Components/ParentComponent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Rendering; 3 | 4 | namespace Bunit.Web.Stub.Components; 5 | 6 | public class ParentComponent : ComponentBase 7 | { 8 | protected override void BuildRenderTree(RenderTreeBuilder builder) 9 | { 10 | builder.OpenComponent(1); 11 | builder.AddAttribute(2, "Count", 2); 12 | builder.CloseComponent(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/bunit.testassets/AssertExtensions/CollectionAssertExtensions.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Bunit; 4 | 5 | /// 6 | /// Collection test assertions. 7 | /// 8 | public static class CollectionAssertExtensions 9 | { 10 | /// 11 | /// Verifies that a collection contains exactly a given number of elements, which 12 | /// meet the criteria provided by the element inspectors. 13 | /// 14 | /// The collection to be inspected. 15 | /// The element inspectors, which inspect each element in turn. The total number of element inspectors must exactly match the number of elements in the collection. 16 | public static void ShouldAllBe(this IEnumerable collection, params Action[] elementInspectors) 17 | { 18 | Assert.Collection(collection, elementInspectors); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/AddRemoveChildComponents.razor: -------------------------------------------------------------------------------- 1 | Child components follow. 2 | 3 | 4 | 5 | @foreach (var message in currentChildrenMessages) 6 | { 7 |

8 | } 9 | 10 | @code { 11 | int numAdded = 0; 12 | private readonly List currentChildrenMessages = new List(); 13 | 14 | void AddChild() 15 | { 16 | numAdded++; 17 | currentChildrenMessages.Add($"Child {numAdded}"); 18 | } 19 | 20 | void RemoveChild() 21 | { 22 | if (currentChildrenMessages.Count > 0) 23 | { 24 | currentChildrenMessages.RemoveAt(currentChildrenMessages.Count - 1); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/AsyncEventHandlerComponent.razor: -------------------------------------------------------------------------------- 1 |
2 | @state 3 | 4 | 5 |
6 | 7 | @code 8 | { 9 | #nullable disable 10 | TaskCompletionSource _tcs; 11 | string state = "Stopped"; 12 | Task Tick(MouseEventArgs e) 13 | { 14 | if (_tcs == null) 15 | { 16 | _tcs = new TaskCompletionSource(); 17 | 18 | state = "Started"; 19 | return _tcs.Task.ContinueWith((_) => 20 | { 21 | state = "Stopped"; 22 | _tcs = null; 23 | }); 24 | } 25 | 26 | return Task.CompletedTask; 27 | } 28 | 29 | void Tock(MouseEventArgs e) 30 | { 31 | _tcs.TrySetResult(null); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/ComponentWithEscapableCharacters.razor: -------------------------------------------------------------------------------- 1 |

@Escaped

2 | 3 | @code { 4 | [Parameter] 5 | public string Escaped { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/ConcurrentRenderChild.razor: -------------------------------------------------------------------------------- 1 | @(isAfterDelay ? "😊" :"WAITING") 2 | @code 3 | { 4 | protected bool isAfterDelay; 5 | 6 | protected override async Task OnInitializedAsync() 7 | { 8 | // If there are lots of instances of this component, the following delay 9 | // will result in a lot of them triggering a re-render simultaneously 10 | // on different threads. 11 | // This test is to verify that the renderer correctly accepts all the 12 | // simultaneous render requests. 13 | await Task.Delay(1000); 14 | isAfterDelay = true; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/ConcurrentRenderParent.razor: -------------------------------------------------------------------------------- 1 |

2 | After a 1 second delay, the output should be 100x😊, with no remaining "WAITING" markers. 3 |

4 | 5 |
6 | @for (var i = 0; i < 100; i++) {} 7 |
8 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/CounterComponent.razor: -------------------------------------------------------------------------------- 1 |

Counter

2 |

Current count: @currentCount

3 |

4 | 5 | 9 | 10 | @if (handleClicks) 11 | { 12 |

Listening

13 | } 14 | 15 | @code { 16 | private Action OnClickHandler 17 | { 18 | get 19 | { 20 | if (handleClicks) 21 | return IncrementCount; 22 | else 23 | return default!; 24 | } 25 | } 26 | 27 | int currentCount = 0; 28 | bool handleClicks = true; 29 | 30 | void IncrementCount() 31 | { 32 | currentCount++; 33 | } 34 | 35 | public void Reset() 36 | { 37 | currentCount = 0; 38 | StateHasChanged(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/CounterComponentUsingChild.razor: -------------------------------------------------------------------------------- 1 |

Counter

2 | 3 | 4 |

Current count:

5 | 6 | 7 | 8 | @code { 9 | int currentCount = 0; 10 | 11 | void IncrementCount() 12 | { 13 | currentCount++; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/CounterComponentWrapper.razor: -------------------------------------------------------------------------------- 1 | 

Counter wrapper

2 | 3 | This is the parent component. Here comes the counter: 4 | 5 | 6 | 7 | Finished. 8 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/DataDashComponent.razor: -------------------------------------------------------------------------------- 1 |
@TabId
2 | 3 | @code { 4 | private readonly string TabId = "17"; 5 | } 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/DuplicateAttributesComponent.razor: -------------------------------------------------------------------------------- 1 |
2 | 6 |
7 | 8 |
9 | 13 |
14 | 15 | @functions { 16 | private readonly Dictionary elementValues = new Dictionary 17 | { 18 | { "bool", true }, 19 | { "string", "middle-value" }, 20 | { "unmatched", "unmatched-value" }, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/DuplicateAttributesOnElementChildComponent.razor: -------------------------------------------------------------------------------- 1 | @if (StringAttributeBefore != null) 2 | { 3 |
6 |
7 | } 8 | else 9 | { 10 |
13 |
14 | } 15 | 16 | @code { 17 | #nullable disable 18 | [Parameter] public string StringAttributeBefore { get; set; } 19 | [Parameter] public bool BoolAttributeBefore { get; set; } 20 | [Parameter] public string StringAttributeAfter { get; set; } 21 | [Parameter] public bool? BoolAttributeAfter { get; set; } 22 | 23 | [Parameter(CaptureUnmatchedValues = true)] public Dictionary UnmatchedValues { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/HierarchicalImportsTest/Subdir/ComponentUsingImports.razor: -------------------------------------------------------------------------------- 1 | The following two outputs rely on "using" directives in _ViewImports files at the current and ancestor levels. 2 | 3 |

@(typeof(Complex).FullName)

4 | 5 |

@(typeof(AssemblyHashAlgorithm).FullName)

6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/HierarchicalImportsTest/Subdir/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Configuration.Assemblies 2 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/HierarchicalImportsTest/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Numerics 2 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/HtmlBlockChildContent.razor: -------------------------------------------------------------------------------- 1 |

Some-Static-Text

-------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/HtmlEncodedChildContent.razor: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Some-Static-Text

4 |
<span>More-Static-Text</span>
5 |
@("Some-Dynamic-Text")But this is static
6 |
7 |
-------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/HtmlMixedChildContent.razor: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Some-Static-Text

4 |
More-Static-Text
5 |
@("Some-Dynamic-Text")But this is static
6 |
7 |
-------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/KeyPressEventComponent.razor: -------------------------------------------------------------------------------- 1 | @using System.Text.Json 2 | 3 | Type here: 4 |
    5 | @foreach (var key in keysPressed) 6 | { 7 |
  • @key
  • 8 | } 9 |
10 | 11 | @code { 12 | private readonly List keysPressed = new List(); 13 | 14 | void OnKeyPressed(KeyboardEventArgs eventArgs) 15 | { 16 | Console.WriteLine(JsonSerializer.Serialize(eventArgs)); 17 | keysPressed.Add(eventArgs.Key); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/LabelQueryCounter.razor: -------------------------------------------------------------------------------- 1 | @* Testing we get back the re-rendered element for an aria-label *@ 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 |

Re-rendered input with Aria Labelledby

12 | 13 | 14 | 15 | 16 | @code { 17 | private int _count; 18 | public void IncrementCount() => _count++; 19 | } 20 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/LogicalElementInsertionCases.razor: -------------------------------------------------------------------------------- 1 |  8 | First 9 | Second 10 | Third 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/MessageComponent.razor: -------------------------------------------------------------------------------- 1 | @Message 2 | @code { 3 | #nullable disable 4 | [Parameter] public string Message { get; set; } 5 | } 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/NOTICE.md: -------------------------------------------------------------------------------- 1 | All files in this folder (BlazorE2E) was copied from 2 | https://github.com/dotnet/aspnetcore/tree/main/src/Components/test/testassets. 3 | 4 | See the NOTICE.md at the root of this repository for a copy 5 | of the license from the aspnetcore repository. 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/OrderedList.razor: -------------------------------------------------------------------------------- 1 | @typeparam TItem 2 | 3 |
    4 | @{ 5 | var index = 1; 6 | } 7 | @foreach (var item in Items) 8 | { 9 | @Template(new Context { Index = index++, Item = item, }) 10 | } 11 |
12 | 13 | @code{ 14 | #nullable disable 15 | [Parameter] public IEnumerable Items { get; set; } 16 | 17 | [Parameter] public RenderFragment Template { get; set; } 18 | 19 | public class Context 20 | { 21 | public int Index { get; set; } 22 | 23 | public TItem Item { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/ParentChildComponent.razor: -------------------------------------------------------------------------------- 1 | 
2 | Parent component 3 | 4 |
5 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/PassThroughContentComponent.razor: -------------------------------------------------------------------------------- 1 | @ChildContent 2 | @code { 3 | // Note: The lack of any whitespace or other output besides @ChildContent is important for 4 | // what scenarios this component is used for in E2E tests. 5 | #nullable disable 6 | [Parameter] public RenderFragment ChildContent { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/PropertiesChangedHandlerChild.razor: -------------------------------------------------------------------------------- 1 | 
You supplied: @SuppliedValue
2 |
I computed: @computedValue
3 | 4 | @code { 5 | [Parameter] 6 | public int SuppliedValue { get; set; } 7 | 8 | private int computedValue; 9 | 10 | protected override void OnParametersSet() 11 | { 12 | computedValue = SuppliedValue * 2; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/PropertiesChangedHandlerParent.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @code { 5 | private int valueToSupply = 100; 6 | } 7 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/RazorTemplates.razor: -------------------------------------------------------------------------------- 1 | @{ 2 | var items = new string[] { "A", "B", "c", }; 3 | } 4 | 5 |
6 | @{ 7 | RenderFragment.Context> template = context => @
  • #@context.Index - @context.Item.ToLower()
  • ; 8 | } 9 | 10 |
    11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/RedTextComponent.razor: -------------------------------------------------------------------------------- 1 | 

    Hello, world!

    2 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/RenderFragmentToggler.razor: -------------------------------------------------------------------------------- 1 |
    2 |

    Fragment will be toggled below

    3 | 4 | @if (showFragment) 5 | { 6 | @ExampleFragment 7 | } 8 | 9 | 10 |

    The end

    11 |
    12 | 13 | @code { 14 | bool showFragment; 15 | 16 | static RenderFragment ExampleFragment = builder => 17 | { 18 | builder.OpenElement(100, "p"); 19 | builder.AddAttribute(101, "name", "fragment-element"); 20 | builder.AddAttribute(102, "style", "color: red"); 21 | builder.AddContent(103, "This is from the fragment"); 22 | builder.CloseElement(); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/SvgCircleComponent.razor: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/SvgComponent.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | @code { 8 | int radius = 10; 9 | } 10 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/SvgWithChildComponent.razor: -------------------------------------------------------------------------------- 1 |

    SVG with Child Component

    2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/TemplatedTable.razor: -------------------------------------------------------------------------------- 1 | @typeparam TItem 2 | 3 | @if (Header != null) 4 | { 5 | 6 | @Header 7 | 8 | } 9 | 10 | @for (var i = 0; i < Items.Count; i++) 11 | { 12 | var item = Items[i]; 13 | @ItemTemplate(item) 14 | } 15 | 16 | 17 | @if (Footer != null) 18 | { 19 | @Footer 20 | } 21 |
    22 | 23 | @code { 24 | #nullable disable 25 | [Parameter] 26 | public RenderFragment Header { get; set; } 27 | 28 | [Parameter] 29 | public RenderFragment ItemTemplate { get; set; } 30 | 31 | [Parameter] 32 | public RenderFragment Footer { get; set; } 33 | 34 | [Parameter] 35 | public IReadOnlyList Items { get; set; } 36 | } 37 | -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/TextOnlyComponent.razor: -------------------------------------------------------------------------------- 1 | Hello from TextOnlyComponent -------------------------------------------------------------------------------- /tests/bunit.testassets/BlazorE2E/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web -------------------------------------------------------------------------------- /tests/bunit.testassets/ComponentWithButton.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | @code { 4 | [Parameter] 5 | public bool IsDisabled { get; set; } 6 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/ExcludeFromCodeCoverage.cs: -------------------------------------------------------------------------------- 1 | [assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] 2 | -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/ComponentThatPrintsAssignedRenderMode.razor: -------------------------------------------------------------------------------- 1 | @{ 2 | #if NET9_0_OR_GREATER 3 | } 4 | 5 |

    Assigned Render Mode: @AssignedRenderMode?.GetType().Name

    6 | 7 | @{ 8 | #endif 9 | } 10 | -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/ComponentWithChildContent.razor: -------------------------------------------------------------------------------- 1 | @ChildContent 2 | @code { 3 | 4 | [Parameter] public RenderFragment ChildContent { get; set; } = default!; 5 | 6 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/ComponentWithServerRenderMode.razor: -------------------------------------------------------------------------------- 1 | @{ 2 | #if NET9_0_OR_GREATER 3 | } 4 | 5 | @rendermode Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveServer 6 |
    @(ChildContent is not null ? "Parent assigned" : "Assigned") render mode: @AssignedRenderMode?.GetType().Name
    7 | @ChildContent 8 | 9 | @code { 10 | [Parameter] public RenderFragment? ChildContent { get; set; } 11 | } 12 | 13 | @{ 14 | #endif 15 | } 16 | -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/ComponentWithWebAssemblyRenderMode.razor: -------------------------------------------------------------------------------- 1 | @{ 2 | #if NET9_0_OR_GREATER 3 | } 4 | 5 | @rendermode Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveWebAssembly 6 |
    @(ChildContent is not null ? "Parent assigned" : "Assigned") render mode: @AssignedRenderMode?.GetType().Name
    7 | @ChildContent 8 | 9 | @code { 10 | [Parameter] public RenderFragment? ChildContent { get; set; } 11 | } 12 | 13 | @{ 14 | #endif 15 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/ComponentWithoutRenderMode.razor: -------------------------------------------------------------------------------- 1 | @{ 2 | #if NET9_0_OR_GREATER 3 | } 4 | 5 |
    @(ChildContent is not null ? "Parent assigned" : "Assigned") render mode: @AssignedRenderMode?.GetType().Name
    6 | @ChildContent 7 | 8 | @code { 9 | [Parameter] public RenderFragment? ChildContent { get; set; } 10 | } 11 | 12 | @{ 13 | #endif 14 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/InteractiveAutoComponent.razor: -------------------------------------------------------------------------------- 1 | @rendermode RenderMode.InteractiveAuto 2 |

    Hello world @RenderMode.InteractiveAuto

    3 | -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/InteractiveServerComponent.razor: -------------------------------------------------------------------------------- 1 | @rendermode RenderMode.InteractiveServer 2 |

    Hello world @RenderMode.InteractiveServer

    3 | -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/InteractiveWebAssemblyComponent.razor: -------------------------------------------------------------------------------- 1 | @rendermode RenderMode.InteractiveWebAssembly 2 |

    Hello world @RenderMode.InteractiveWebAssembly

    3 | -------------------------------------------------------------------------------- /tests/bunit.testassets/RenderModes/RendererInfoComponent.cs: -------------------------------------------------------------------------------- 1 | #if NET9_0_OR_GREATER 2 | 3 | namespace Bunit.TestAssets.RenderModes; 4 | 5 | public class RendererInfoComponent : ComponentBase 6 | { 7 | protected override void BuildRenderTree(RenderTreeBuilder builder) 8 | { 9 | builder.OpenElement(0, "p"); 10 | builder.AddContent(1, "Is interactive: "); 11 | builder.AddContent(2, RendererInfo.IsInteractive); 12 | builder.CloseElement(); 13 | 14 | builder.OpenElement(3, "p"); 15 | builder.AddContent(4, "Rendermode: "); 16 | builder.AddContent(5, RendererInfo.Name); 17 | builder.CloseElement(); 18 | } 19 | } 20 | #endif -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @FoundTemplate(@routeData) 5 | 6 | 7 | 8 |

    Sorry, there's nothing at this address.

    9 |
    10 |
    11 |
    12 | @code 13 | { 14 | [Parameter] public RenderFragment FoundTemplate { get; set; } 15 | } 16 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/AsyncRenderChangesProperty.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | @code { 4 | private readonly TaskCompletionSource _tcs = new TaskCompletionSource(); 5 | public int Counter; 6 | 7 | private Task Tick() 8 | { 9 | Counter++; 10 | return _tcs.Task.ContinueWith(_ => { Counter++; }); 11 | } 12 | 13 | private void Tock() 14 | { 15 | _tcs.TrySetResult(null); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/AsyncRenderOfSubComponentDuringInit.razor: -------------------------------------------------------------------------------- 1 | @inject ILogger log 2 | 3 | @if (_eitherOr) 4 | { 5 | 6 | 7 | 8 | } 9 | else 10 | { 11 | 12 | 13 | 14 | } 15 | 16 | 17 | @code 18 | { 19 | private bool _eitherOr = true; 20 | 21 | [Parameter] public Task EitherOr { get; set; } = Task.CompletedTask; 22 | 23 | protected override async Task OnInitializedAsync() 24 | { 25 | log.LogDebug($"Before awaiting {nameof(EitherOr)}"); 26 | await EitherOr; 27 | log.LogDebug($"After awaiting {nameof(EitherOr)}"); 28 | _eitherOr = false; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/AuthCascading.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | 3 |

    @isInRole

    4 | 5 | @code { 6 | private bool isInRole; 7 | 8 | [Parameter] public string ExpectedRole { get; set; } = string.Empty; 9 | 10 | [CascadingParameter] public Task AuthenticationStateTask { get; set; } = default!; 11 | 12 | protected override async Task OnInitializedAsync() 13 | { 14 | var authenticationState = await AuthenticationStateTask; 15 | isInRole = authenticationState.User.IsInRole(ExpectedRole); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/BasicComponent.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class BasicComponent : IComponent 4 | { 5 | private RenderHandle renderHandle; 6 | 7 | public void Attach(RenderHandle renderHandle) 8 | { 9 | this.renderHandle = renderHandle; 10 | } 11 | 12 | public Task SetParametersAsync(ParameterView parameters) 13 | { 14 | renderHandle.Render(builder => builder.AddMarkupContent(0, nameof(BasicComponent))); 15 | return Task.CompletedTask; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/BubbleEventsRemoveTriggers.razor: -------------------------------------------------------------------------------- 1 |
    2 | @if (!BtnClicked) 3 | { 4 |
    5 | 6 |
    7 | } 8 |
    9 | @code { 10 | public bool BtnClicked { get; private set; } = false; 11 | public bool MiddleDivClicked { get; private set; } = false; 12 | public bool TopDivClicked { get; private set; } = false; 13 | } 14 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/BubbleEventsThrows.razor: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 |
    5 |
    6 | 7 |

    @BtnClicked

    8 |

    @MiddleDivClicked

    9 |

    @TopDivClicked

    10 | 11 | @code { 12 | [Parameter] public string ExceptionMessage { get; set; } 13 | 14 | public bool BtnClicked { get; private set; } = false; 15 | public bool MiddleDivClicked { get; private set; } = false; 16 | public bool TopDivClicked { get; private set; } = false; 17 | 18 | private void MiddleDivHandler() => throw new Exception(ExceptionMessage); 19 | } 20 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ButtonsInsideForm.razor: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 7 |
    8 | @code { 9 | public bool Clicked; 10 | } 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ClickAddsLi.razor: -------------------------------------------------------------------------------- 1 | 
      2 | @foreach (var x in Enumerable.Range(0, Counter)) 3 | { 4 |
    • @x
    • 5 | } 6 |
    7 | 8 | @code { 9 | public int Counter { get; set; } = 0; 10 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ClickCounter.razor: -------------------------------------------------------------------------------- 1 |  2 |

    @Count

    3 | 4 | @code { 5 | public int Count { get; private set; } = 0; 6 | void IncreaseCount() => Count++; 7 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ClickEventBubbling.razor: -------------------------------------------------------------------------------- 1 |
    2 |

    3 | CLICK ME 4 |

    5 | 6 |
    7 | @code 8 | { 9 | public int SpanClickCount { get; set; } = 0; 10 | public int HeaderClickCount { get; set; } = 0; 11 | } 12 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ClickRemovesEventHandler.razor: -------------------------------------------------------------------------------- 1 | 2 | @if (visible) 3 | { 4 | 5 | } 6 | @code { 7 | private bool visible = true; 8 | public bool SecondButtonClicked { get; private set; } 9 | } 10 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ComponentWithRelativeUnitAsWidth.razor: -------------------------------------------------------------------------------- 1 |
    2 |
    -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ConstructorInjectionComponent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace Bunit.TestAssets.SampleComponents; 4 | 5 | public class ConstructorInjectionComponent : ComponentBase 6 | { 7 | public IJSRuntime JSRuntime { get; } 8 | 9 | public ConstructorInjectionComponent(IJSRuntime jsRuntime) 10 | { 11 | JSRuntime = jsRuntime; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/CounterComponentDynamic.razor: -------------------------------------------------------------------------------- 1 |

    Counter Dynamic

    2 | @foreach (var index in _values) 3 | { 4 | 7 | } 8 | 9 | @code { 10 | private int[] _values = new int[0]; 11 | 12 | protected override async Task OnInitializedAsync() 13 | { 14 | await Task.Delay(1); 15 | _values = new[] { 1 }; 16 | await InvokeAsync(StateHasChanged); 17 | } 18 | 19 | private void OnClick(int index) 20 | { 21 | _values = Enumerable.Range(1, index + 1).ToArray(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/CustomElement.razor: -------------------------------------------------------------------------------- 1 |
    2 |
    Custom Metadata Definitions
    3 | 4 |
    -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/CustomPasteSample.razor: -------------------------------------------------------------------------------- 1 |

    Try pasting into the following text box:

    2 | 3 |

    @message

    4 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Data/AsyncNameDep.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents.Data; 2 | 3 | public class AsyncNameDep : IAsyncTestDep 4 | { 5 | private TaskCompletionSource completionSource = new TaskCompletionSource(); 6 | 7 | public Task GetDataAsync() => completionSource.Task; 8 | 9 | public void SetResult(string name) 10 | { 11 | var prevSource = completionSource; 12 | completionSource = new TaskCompletionSource(); 13 | prevSource.SetResult(name); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Data/Cars.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents.Data; 2 | 3 | public enum Cars 4 | { 5 | Audi, 6 | Jeep, 7 | Opel, 8 | Saab, 9 | Volvo 10 | } 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Data/Foo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Bunit.TestAssets.SampleComponents; 4 | 5 | [TypeConverter(typeof(FooTypeConverter))] 6 | public class Foo 7 | { 8 | public int Age { get; set; } 9 | 10 | public string Name { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Data/IAsyncTestDep.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents.Data; 2 | 3 | public interface IAsyncTestDep 4 | { 5 | Task GetDataAsync(); 6 | } 7 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Data/ITestDep.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents.Data; 2 | 3 | public interface ITestDep 4 | { 5 | string Name { get; } 6 | } 7 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Data/ThemeInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents.Data; 2 | 3 | public class ThemeInfo 4 | { 5 | public string? Value { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/DelayRemovedRenderFragment.razor: -------------------------------------------------------------------------------- 1 | @code { 2 | private int renderCountDown = 2; 3 | 4 | [Parameter] public RenderFragment ChildContent { get; set; } 5 | 6 | protected override async Task OnAfterRenderAsync(bool firstRender) 7 | { 8 | if (renderCountDown <= 0) 9 | return; 10 | 11 | await Task.Delay(1); 12 | renderCountDown--; 13 | StateHasChanged(); 14 | } 15 | } 16 |

    RenderCountDown: @renderCountDown

    17 | @if(renderCountDown > 0) 18 | { 19 |
    20 | @ChildContent 21 |
    22 | } 23 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/DelayRenderFragment.razor: -------------------------------------------------------------------------------- 1 | @code { 2 | private int renderCountDown = 2; 3 | 4 | [Parameter] public RenderFragment ChildContent { get; set; } 5 | 6 | protected override async Task OnAfterRenderAsync(bool firstRender) 7 | { 8 | if (renderCountDown <= 0) 9 | return; 10 | 11 | await Task.Delay(1); 12 | renderCountDown--; 13 | StateHasChanged(); 14 | } 15 | } 16 |

    RenderCountDown: @renderCountDown

    17 | @if(renderCountDown <= 0) 18 | { 19 |
    20 | @ChildContent 21 |
    22 | } 23 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/DispatcherException.razor: -------------------------------------------------------------------------------- 1 | @if(show) 2 | { 3 |
    4 | 5 |
    6 | } 7 | @code { 8 | bool show = true; 9 | } 10 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/DisposeComponents/ChildDispose.razor: -------------------------------------------------------------------------------- 1 | @implements IDisposable 2 |

    Test

    3 | @code { 4 | [CascadingParameter] 5 | public ICollection CallStack { get; set; } = Array.Empty(); 6 | 7 | public void Dispose() 8 | { 9 | CallStack.Add(nameof(ChildDispose)); 10 | } 11 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/DisposeComponents/DisposeFragments.razor: -------------------------------------------------------------------------------- 1 | @code { 2 | public static RenderFragment ChildDisposeAsFragment(List callStack) 3 | { 4 | return @ 5 | 6 | ; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/DisposeComponents/ParentDispose.razor: -------------------------------------------------------------------------------- 1 | @implements IDisposable 2 | 3 | 4 | 5 | @code { 6 | [CascadingParameter] 7 | public ICollection CallStack { get; set; } = Array.Empty(); 8 | 9 | public void Dispose() 10 | { 11 | CallStack.Add(nameof(ParentDispose)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/EventHandlerThrows.razor: -------------------------------------------------------------------------------- 1 | 2 | @code { 3 | [Parameter] public string ExceptionMessage { get; set; } 4 | private void Handler() => throw new Exception(ExceptionMessage); 5 | } 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/FormNameComponent.razor: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/FormWithButton.razor: -------------------------------------------------------------------------------- 1 |
    2 | @if (HasSubmitType) 3 | { 4 | 5 | } 6 | else 7 | { 8 | 9 | 10 | } 11 |
    12 | 13 | @code { 14 | public bool SubmitWasCalled { get; private set; } 15 | 16 | [Parameter] 17 | public bool HasSubmitType { get; set; } = true; 18 | 19 | private void Callback() 20 | { 21 | SubmitWasCalled = true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/FormWithValidation.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | @code { 9 | 10 | [Parameter] 11 | public bool Invoked { get; set; } 12 | 13 | private Model model = new(); 14 | 15 | private void SetInvoked() 16 | { 17 | Invoked = true; 18 | model = new Model(); 19 | } 20 | 21 | public sealed class Model 22 | { 23 | public string? Title { get; set; } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/FullBind.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace Bunit.TestAssets.SampleComponents; 4 | 5 | public class FullBind : ComponentBase 6 | { 7 | [Parameter] public string Foo { get; set; } = string.Empty; 8 | [Parameter] public EventCallback FooChanged { get; set; } 9 | [Parameter] public Expression> FooExpression { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/HidesButton.razor: -------------------------------------------------------------------------------- 1 | @if (showButton) 2 | { 3 | 4 | } 5 | 6 | @code 7 | { 8 | private bool showButton = true; 9 | 10 | private void ClickHandler() 11 | { 12 | showButton = false; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/InputChangeEventSample.razor: -------------------------------------------------------------------------------- 1 | 2 | @code { 3 | 4 | public object? ReceivedValue { get; set; } 5 | 6 | private void HandleChange(ChangeEventArgs args) 7 | { 8 | ReceivedValue = args.Value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/LoadingComponent.razor: -------------------------------------------------------------------------------- 1 | @text 2 | @code { 3 | [Parameter] 4 | public Task Task { get; set; } 5 | 6 | private string text = "loading"; 7 | protected override async Task OnInitializedAsync() 8 | { 9 | await Task; 10 | text = "done"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | @Body 3 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/MultipleStateHasChangedInOnParametersSet.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class MultipleStateHasChangedInOnParametersSet : ComponentBase 4 | { 5 | [Parameter] 6 | public int Value { get; set; } 7 | 8 | protected override void OnParametersSet() 9 | { 10 | base.OnParametersSet(); 11 | StateHasChanged(); 12 | StateHasChanged(); 13 | StateHasChanged(); 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/NoArgs.razor: -------------------------------------------------------------------------------- 1 |

    Hello world

    2 | @code { 3 | [Parameter(CaptureUnmatchedValues = true)] 4 | public IReadOnlyDictionary? Attributes { get; set; } 5 | } 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/OnChangeBindSample.razor: -------------------------------------------------------------------------------- 1 | @typeparam T 2 | @code { 3 | [Parameter] public T BindValue { get; set; } 4 | [Parameter] public object? OnChangeValue { get; set; } 5 | [Parameter] public object? OnInputValue { get; set; } 6 | } 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/OnChangeMultipleBindSample.razor: -------------------------------------------------------------------------------- 1 | @typeparam T 2 | @code { 3 | [Parameter] public T[] Options { get; set; } 4 | [Parameter] public T[] BindValues { get; set; } = Array.Empty(); 5 | [Parameter] public object? OnChangeValue { get; set; } 6 | [Parameter] public object? OnInputValue { get; set; } 7 | } 8 | 14 | 20 | 26 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/OnsubmitButton.razor: -------------------------------------------------------------------------------- 1 | 
    2 | 3 |
    4 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/PersistentComponentStateSample.razor: -------------------------------------------------------------------------------- 1 | @foreach (var f in Forecasts) 2 | { 3 |

    @f.Temperature

    4 | } 5 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/PrintCascadingValue.razor: -------------------------------------------------------------------------------- 1 |

    @Value

    2 | @code 3 | { 4 | [CascadingParameter] public string? Value { get; set; } 5 | } 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/PrintCurrentUrl.razor: -------------------------------------------------------------------------------- 1 | @implements IDisposable 2 | @inject NavigationManager NavMan 3 | 4 | 5 |

    @url

    6 | 7 | @code { 8 | private string url; 9 | 10 | [Parameter] public string GoToUrl { get; set; } = string.Empty; 11 | 12 | protected override void OnInitialized() 13 | => NavMan.LocationChanged += OnLocationChanged; 14 | 15 | public void Dispose() 16 | => NavMan.LocationChanged -= OnLocationChanged; 17 | 18 | private void OnLocationChanged(object? sender, LocationChangedEventArgs e) 19 | { 20 | url = e.Location; 21 | StateHasChanged(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/RefToSimple1Child.razor: -------------------------------------------------------------------------------- 1 | 2 |
    Has ref = @(simple1 is not null)
    3 | @code 4 | { 5 | Simple1? simple1; 6 | 7 | protected override void OnAfterRender(bool firstRender) 8 | { 9 | if(firstRender && simple1 is not null) 10 | { 11 | StateHasChanged(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/RenderCounter.razor: -------------------------------------------------------------------------------- 1 | Rendered: @counter 2 | @code{ 3 | int counter = 0; 4 | 5 | protected override void OnParametersSet() 6 | { 7 | counter += 1; 8 | } 9 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/RenderOnClick.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | @code { 4 | public int RenderCount { get; private set; } 5 | 6 | void IncreaseCount() 7 | { 8 | // Left empty on purpose 9 | } 10 | 11 | protected override void OnAfterRender(bool firstRender) => RenderCount++; 12 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ScopedCssElements.razor: -------------------------------------------------------------------------------- 1 |

    Hello Pink World!

    2 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ScopedCssElements.razor.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: deeppink; 3 | } 4 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SignOutSessionManagerLoginDisplay.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | @using Microsoft.AspNetCore.Components.WebAssembly.Authentication 3 | 4 | 5 | 6 | 9 | 10 | 11 | Log in 12 | 13 | 14 | 15 | @code { 16 | #pragma warning disable CS0618 17 | [Inject] SignOutSessionStateManager SignOutManager { get;set;} = default!; 18 | #pragma warning restore CS0618 19 | 20 | private async Task BeginSignOut(MouseEventArgs args) 21 | { 22 | await SignOutManager.SetSignOutState(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Simple1.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class Simple1 : ComponentBase 4 | { 5 | [Parameter] public string Header { get; set; } = string.Empty; 6 | 7 | [Parameter] public string AttrValue { get; set; } = string.Empty; 8 | 9 | protected override void BuildRenderTree(RenderTreeBuilder builder) 10 | { 11 | builder.OpenElement(0, "h1"); 12 | builder.AddAttribute(1, "id", "header"); 13 | builder.AddAttribute(2, "attr", AttrValue); 14 | builder.AddContent(3, Header); 15 | builder.CloseElement(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleAuthView.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | 3 | 4 | 5 | 6 | Authorized! 7 | 8 | 9 | Authorizing... 10 | 11 | 12 | Not authorized? 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleAuthViewWithClaims.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | @using System.Security.Claims 3 | @inject AuthenticationStateProvider AuthenticationStateProvider 4 | 5 | 6 |
    Authorized!
    7 |
    Name: @userName
    8 | @if (hasUserEmail) 9 | { 10 |
    Email: @userEmail
    11 | } 12 | @if (hasUserId) 13 | { 14 |
    Id: @userId
    15 | } 16 |
    17 | 18 | @code { 19 | string userName = ""; 20 | string? userEmail = ""; 21 | string? userId = ""; 22 | bool hasUserEmail => userEmail != null; 23 | bool hasUserId => userId != null; 24 | 25 | protected override async Task OnParametersSetAsync() 26 | { 27 | var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); 28 | userName = state?.User?.Identity?.Name ?? string.Empty; 29 | userEmail = state?.User?.FindFirst(ClaimTypes.Email)?.Value; 30 | userId = state?.User?.FindFirst(ClaimTypes.Sid)?.Value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleAuthViewWithCustomAuthType.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | 3 | 4 | @if (context.User.Identity?.AuthenticationType == "custom-auth-type") 5 | { 6 |

    Authorized content with custom auth type.

    7 | } 8 |
    9 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleAuthViewWithPolicy.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | 3 | 4 | Authorized for content viewers. 5 | 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleAuthViewWithRole.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | 3 | 4 | Authorized content for admins. 5 | 6 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleBind.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | public class SimpleBind : ComponentBase 3 | { 4 | [Parameter] public string Value { get; set; } = string.Empty; 5 | [Parameter] public EventCallback ValueChanged { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimplePage.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleSvg.razor: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleUsingLocalizer.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.Extensions.Localization 2 | @inject IStringLocalizer StringLocalizer 3 | 4 |

    SimpleUsingLocalizer

    5 | 6 | @code { 7 | protected override void OnInitialized() 8 | { 9 | _ = StringLocalizer["StringName"]; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleUsingWebAssemblyHostEnvironment.razor: -------------------------------------------------------------------------------- 1 | @inject IWebAssemblyHostEnvironment HostEnvironment 2 | 3 |

    Hello @(HostEnvironment.IsDevelopment() ? "Developers" : "World"). The base URL is: @HostEnvironment.BaseAddress

    4 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleWithAyncDeps.razor: -------------------------------------------------------------------------------- 1 | @inject IAsyncTestDep testDep 2 |

    @name

    3 | @code{ 4 | string name = string.Empty; 5 | 6 | protected override async Task OnInitializedAsync() 7 | { 8 | name = await testDep.GetDataAsync(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleWithDeps.razor: -------------------------------------------------------------------------------- 1 | @inject ITestDep testDep 2 |

    @testDep.Name

    -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleWithHttpClient.razor: -------------------------------------------------------------------------------- 1 | @inject HttpClient HttpClient 2 | 3 | 4 |

    SimpleWithHttpClient

    5 | 6 | @code { 7 | protected override async Task OnInitializedAsync() 8 | { 9 | await HttpClient.GetAsync("/api/weather"); 10 | StateHasChanged(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleWithJSRuntimeDep.razor: -------------------------------------------------------------------------------- 1 | @inject IJSRuntime jsRuntime 2 |

    @name

    3 | @code{ 4 | string name = string.Empty; 5 | 6 | protected override async Task OnAfterRenderAsync(bool firstRender) 7 | { 8 | if (firstRender) 9 | { 10 | name = await jsRuntime.InvokeAsync("getdata"); 11 | StateHasChanged(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/SimpleWithTemplate.razor: -------------------------------------------------------------------------------- 1 | @typeparam T 2 | @foreach (var d in Data) 3 | { 4 | @Template?.Invoke(d) 5 | } 6 | @code 7 | { 8 | [Parameter] public RenderFragment? Template { get; set; } 9 | [Parameter] public IReadOnlyList Data { get; set; } = Array.Empty(); 10 | } 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ThemedButton.razor: -------------------------------------------------------------------------------- 1 | 7 | @code { 8 | [Parameter(CaptureUnmatchedValues = true)] 9 | public IReadOnlyDictionary? Attributes { get; set; } 10 | 11 | [CascadingParameter] public ThemeInfo? Theme { get; set; } 12 | [CascadingParameter(Name = nameof(Title))] public ThemeInfo? Title { get; set; } 13 | [Parameter] public RenderFragment? ChildContent { get; set; } 14 | [Parameter] public EventCallback OnClick { get; set; } 15 | 16 | private Task HandleOnClick(MouseEventArgs args) => OnClick.InvokeAsync(args); 17 | } 18 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ThrowsOnParameterSet.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class ThrowsOnParameterSet : ComponentBase 4 | { 5 | private readonly string value = string.Empty; 6 | 7 | [Parameter] 8 | public string Value 9 | { 10 | get => value; 11 | set => throw new ArgumentOutOfRangeException(nameof(value), $"{nameof(value)} is invalid"); 12 | } 13 | } -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ToggleChildComponent.razor: -------------------------------------------------------------------------------- 1 | @if (ShowChild) 2 | { 3 | 4 | } 5 | @code { 6 | [Parameter] 7 | public bool ShowChild { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ToggleClickHandler.razor: -------------------------------------------------------------------------------- 1 |

    2 | 3 | @code { 4 | public int Counter { get; set; } 5 | 6 | [Parameter] 7 | public bool HandleClicks { get; set; } = true; 8 | 9 | void IncrementCount() { Counter++; } 10 | } 11 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/ToggleableDetails.razor: -------------------------------------------------------------------------------- 1 |
    2 | @if (detailsExpanded) 3 | { 4 |

    Read the details carefully!

    5 | } 6 |
    7 | Summary 8 |

    Detailed content

    9 |
    10 |
    11 | 12 | @code { 13 | bool detailsExpanded; 14 | 15 | void OnToggle() 16 | { 17 | detailsExpanded = !detailsExpanded; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/TriggerChildContentRerenderViaClick.razor: -------------------------------------------------------------------------------- 1 | @* TriggerChildContentRerenderViaClick.razor *@ 2 | 3 | 4 | @code { 5 | int counter; 6 | } 7 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/TriggerTester.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class TriggerTester : ComponentBase 4 | where TEventArgs : EventArgs, new() 5 | { 6 | [Parameter] public string Element { get; set; } = "p"; 7 | [Parameter] public string EventName { get; set; } = "p"; 8 | [Parameter] public EventCallback? TriggeredEvent { get; set; } 9 | 10 | protected override void BuildRenderTree(RenderTreeBuilder builder) 11 | { 12 | ArgumentNullException.ThrowIfNull(builder); 13 | if (TriggeredEvent is null) 14 | throw new InvalidOperationException($"{nameof(TriggeredEvent)} is null"); 15 | 16 | builder.OpenElement(0, Element); 17 | builder.AddAttribute(1, EventName, EventCallback.Factory.Create(this, TriggeredEvent.Value)); 18 | builder.CloseElement(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/TwoChildren.razor: -------------------------------------------------------------------------------- 1 | 

    2 | 3 |

    4 |
    5 | 6 |
    -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/TwoComponentWrapper.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class TwoComponentWrapper : ComponentBase 4 | { 5 | [Parameter] 6 | public RenderFragment? First { get; set; } 7 | 8 | [Parameter] 9 | public RenderFragment? Second { get; set; } 10 | 11 | protected override void BuildRenderTree(RenderTreeBuilder builder) 12 | { 13 | builder.OpenElement(0, "div"); 14 | builder.AddAttribute(1, "class", "first"); 15 | builder.AddContent(2, First); 16 | builder.CloseElement(); 17 | 18 | builder.OpenElement(10, "div"); 19 | builder.AddAttribute(11, "class", "second"); 20 | builder.AddContent(12, Second); 21 | builder.CloseElement(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/TwoRendersTwoChanges.razor: -------------------------------------------------------------------------------- 1 |
    2 | @state 3 | 4 | 5 |
    6 | 7 | @code 8 | { 9 | public bool tockEnabled = false; 10 | public TaskCompletionSource? _tcs; 11 | public string state = "Stopped"; 12 | 13 | public Task Tick(MouseEventArgs e) 14 | { 15 | if (_tcs is null) 16 | { 17 | _tcs = new TaskCompletionSource(); 18 | 19 | state = "Started"; 20 | tockEnabled = true; 21 | return _tcs.Task.ContinueWith(_ => 22 | { 23 | state = "Stopped"; 24 | _tcs = null; 25 | }); 26 | } 27 | 28 | return Task.CompletedTask; 29 | } 30 | 31 | public void Tock(MouseEventArgs e) 32 | { 33 | tockEnabled = false; 34 | _tcs?.TrySetResult(null); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/Wrapper.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class Wrapper : ComponentBase 4 | { 5 | [Parameter] public RenderFragment? ChildContent { get; set; } 6 | 7 | protected override void BuildRenderTree(RenderTreeBuilder builder) => builder.AddContent(0, ChildContent); 8 | } 9 | -------------------------------------------------------------------------------- /tests/bunit.testassets/SampleComponents/WrapperDiv.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestAssets.SampleComponents; 2 | 3 | public class WrapperDiv : ComponentBase 4 | { 5 | [Parameter] public RenderFragment? ChildContent { get; set; } 6 | 7 | protected override void BuildRenderTree(RenderTreeBuilder builder) 8 | { 9 | builder.OpenElement(0, "div"); 10 | builder.AddAttribute(1, "class", "wrapper"); 11 | builder.AddContent(10, ChildContent); 12 | builder.CloseElement(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/bunit.testassets/Serilog.Sinks.XUnit/NOTICE.md: -------------------------------------------------------------------------------- 1 | # LEGAL NOTICE 2 | 3 | The files in this folder has been copied from https://github.com/trbenning/serilog-sinks-xunit, 4 | since the project does not use strong name signing. 5 | -------------------------------------------------------------------------------- /tests/bunit.testassets/ServiceCollectionLoggingExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using Serilog; 3 | using Serilog.Events; 4 | using Serilog.Templates; 5 | 6 | namespace Xunit; 7 | 8 | public static class ServiceCollectionLoggingExtensions 9 | { 10 | public static IServiceCollection AddXunitLogger(this IServiceCollection services, ITestOutputHelper outputHelper) 11 | { 12 | var serilogLogger = new LoggerConfiguration() 13 | .MinimumLevel.Verbose() 14 | .WriteTo.TestOutput( 15 | testOutputHelper: outputHelper, 16 | formatter: new ExpressionTemplate("[{UtcDateTime(@t):mm:ss.ffffff} | {@l:u3} | {Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)} | {Coalesce(EventId.Name, '')}] {@m}\n{@x}"), 17 | restrictedToMinimumLevel: LogEventLevel.Verbose) 18 | .CreateLogger(); 19 | 20 | services.AddSingleton(_ => new LoggerFactory().AddSerilog(serilogLogger, dispose: true)); 21 | services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); 22 | return services; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/bunit.testassets/XunitExtensions/RepeatAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Xunit.Sdk; 3 | using Xunit.v3; 4 | 5 | namespace Xunit; 6 | 7 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 8 | public sealed class RepeatAttribute : DataAttribute 9 | { 10 | public int Count { get; } 11 | 12 | public RepeatAttribute(int count) 13 | { 14 | if (count < 1) 15 | { 16 | throw new ArgumentOutOfRangeException( 17 | paramName: nameof(count), 18 | message: "Repeat count must be greater than 0."); 19 | } 20 | 21 | Count = count; 22 | } 23 | 24 | public override ValueTask> GetData(MethodInfo testMethod, 25 | DisposalTracker disposalTracker) 26 | { 27 | var rows = Enumerable.Range(1, Count).Select(i => new TheoryDataRow(new object[] { i })).ToArray(); 28 | return new ValueTask>(rows); 29 | } 30 | 31 | public override bool SupportsDiscoveryEnumeration() => false; 32 | } 33 | -------------------------------------------------------------------------------- /tests/bunit.testassets/XunitExtensions/TheoryDataExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Xunit; 2 | 3 | public static class TheoryDataExtensions 4 | { 5 | public static TheoryData Clone(this TheoryData existing) 6 | { 7 | var result = new TheoryData(); 8 | foreach (var item in existing) 9 | { 10 | result.Add(item); 11 | } 12 | return result; 13 | } 14 | 15 | public static TheoryData AddRange(this TheoryData theoryData, IEnumerable items) 16 | { 17 | foreach (var item in items) 18 | { 19 | theoryData.Add(item); 20 | } 21 | return theoryData; 22 | } 23 | 24 | public static TheoryData AddRange(this TheoryData theoryData, params T[] items) 25 | { 26 | foreach (var item in items) 27 | { 28 | theoryData.Add(item); 29 | } 30 | return theoryData; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/bunit.testassets/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Forms 2 | @using Microsoft.AspNetCore.Components.Routing 3 | @using Microsoft.AspNetCore.Components.Web 4 | @using Microsoft.AspNetCore.Components.WebAssembly.Hosting 5 | @using Microsoft.Extensions.DependencyInjection 6 | @using Microsoft.Extensions.Logging 7 | @using Microsoft.JSInterop 8 | @using Bunit.TestAssets.SampleComponents 9 | @using Bunit.TestAssets.SampleComponents.Data 10 | -------------------------------------------------------------------------------- /tests/bunit.tests/Assembly.cs: -------------------------------------------------------------------------------- 1 | [assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] 2 | -------------------------------------------------------------------------------- /tests/bunit.tests/EventDispatchExtensions/ClipboardEventDispatchExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | public class ClipboardEventDispatchExtensionsTest : EventDispatchExtensionsTest 4 | { 5 | public ClipboardEventDispatchExtensionsTest(ITestOutputHelper outputHelper) : base(outputHelper) 6 | { 7 | } 8 | 9 | protected override string ElementName => "textarea"; 10 | 11 | [Theory(DisplayName = "Clipboard events are raised correctly through helpers")] 12 | [MemberData(nameof(GetEventHelperMethods))] 13 | public void CanRaiseEvents(MethodInfo helper) 14 | { 15 | var expected = new ClipboardEventArgs 16 | { 17 | Type = "SOME TYPE", 18 | }; 19 | 20 | VerifyEventRaisesCorrectly(helper, expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/bunit.tests/EventDispatchExtensions/DetailsElementEventDispatcherExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.EventDispatchExtensions; 2 | 3 | public class DetailsElementEventDispatcherExtensionsTest : BunitContext 4 | { 5 | [Fact(DisplayName = "Toggle raises ontoggle events")] 6 | public void Test200() 7 | { 8 | var cut = Render(); 9 | cut.FindAll("div > p").Count.ShouldBe(0); 10 | 11 | cut.Find("details").Toggle(); 12 | 13 | cut.FindAll("div > p").Count.ShouldBe(1); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/bunit.tests/EventDispatchExtensions/DragEventDispatchExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | public class DragEventDispatchExtensionsTest : EventDispatchExtensionsTest 4 | { 5 | public DragEventDispatchExtensionsTest(ITestOutputHelper outputHelper) : base(outputHelper) 6 | { 7 | } 8 | 9 | protected override string ElementName => "textarea"; 10 | 11 | [Theory(DisplayName = "Drag events are raised correctly through helpers")] 12 | [MemberData(nameof(GetEventHelperMethods))] 13 | public void CanRaiseEvents(MethodInfo helper) 14 | { 15 | var expected = new DragEventArgs 16 | { 17 | Detail = 2, 18 | ScreenX = 3, 19 | ScreenY = 4, 20 | ClientX = 5, 21 | ClientY = 6, 22 | Button = 7, 23 | Buttons = 8, 24 | CtrlKey = true, 25 | AltKey = true, 26 | MetaKey = true, 27 | ShiftKey = true, 28 | Type = "TYPE", 29 | DataTransfer = new DataTransfer(), 30 | }; 31 | 32 | VerifyEventRaisesCorrectly(helper, expected); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/bunit.tests/EventDispatchExtensions/FocusEventDispatchExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | public class FocusEventDispatchExtensionsTest : EventDispatchExtensionsTest 4 | { 5 | public FocusEventDispatchExtensionsTest(ITestOutputHelper outputHelper) : base(outputHelper) 6 | { 7 | } 8 | 9 | protected override string ElementName => "p"; 10 | 11 | [Theory(DisplayName = "Focus events are raised correctly through helpers")] 12 | [MemberData(nameof(GetEventHelperMethods))] 13 | public void CanRaiseEvents(MethodInfo helper) 14 | { 15 | var expected = new FocusEventArgs 16 | { 17 | Type = "SOME TYPE", 18 | }; 19 | 20 | VerifyEventRaisesCorrectly(helper, expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/bunit.tests/EventDispatchExtensions/FormDispatchExtensionTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.EventDispatchExtensions; 2 | 3 | public class FormDispatchExtensionTest : BunitContext 4 | { 5 | [Fact] 6 | public void ClickingOnSubmitButtonTriggersOnsubmitOfForm() 7 | { 8 | var cut = Render(p => p.Add(s => s.HasSubmitType, true)); 9 | 10 | cut.Find("#submitter").Click(); 11 | 12 | cut.Instance.SubmitWasCalled.ShouldBeTrue(); 13 | } 14 | 15 | [Fact] 16 | public void ButtonWithoutTypeIsConsideredSubmitAndTriggersOnsubmitOfForm() 17 | { 18 | var cut = Render(p => p.Add(s => s.HasSubmitType, false)); 19 | 20 | cut.Find("#submitter").Click(); 21 | 22 | cut.Instance.SubmitWasCalled.ShouldBeTrue(); 23 | } 24 | 25 | [Fact] 26 | public void ButtonThatIsNotSubmitShouldNotTrigger() 27 | { 28 | var cut = Render(p => p.Add(s => s.HasSubmitType, false)); 29 | 30 | cut.Find("#other").Click(); 31 | 32 | cut.Instance.SubmitWasCalled.ShouldBeFalse(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/bunit.tests/EventDispatchExtensions/ProgressEventDispatchExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | public class ProgressEventDispatchExtensionsTest : EventDispatchExtensionsTest 4 | { 5 | public ProgressEventDispatchExtensionsTest(ITestOutputHelper outputHelper) : base(outputHelper) 6 | { 7 | } 8 | 9 | protected override string ElementName => "div"; 10 | 11 | [Theory(DisplayName = "Progress events are raised correctly through helpers")] 12 | [MemberData(nameof(GetEventHelperMethods))] 13 | public void CanRaiseEvents(MethodInfo helper) 14 | { 15 | var expected = new ProgressEventArgs 16 | { 17 | LengthComputable = true, 18 | Loaded = 42L, 19 | Total = 1337L, 20 | Type = "FILE", 21 | }; 22 | 23 | VerifyEventRaisesCorrectly(helper, expected); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/bunit.tests/EventDispatchExtensions/TouchEventDispatchExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | public class TouchEventDispatchExtensionsTest : EventDispatchExtensionsTest 4 | { 5 | public TouchEventDispatchExtensionsTest(ITestOutputHelper outputHelper) : base(outputHelper) 6 | { 7 | } 8 | 9 | protected override string ElementName => "p"; 10 | 11 | [Theory(DisplayName = "Touch events are raised correctly through helpers")] 12 | [MemberData(nameof(GetEventHelperMethods))] 13 | public void CanRaiseEvents(MethodInfo helper) 14 | { 15 | var expected = new TouchEventArgs 16 | { 17 | AltKey = true, 18 | ChangedTouches = Array.Empty(), 19 | CtrlKey = true, 20 | Detail = 13L, 21 | MetaKey = true, 22 | ShiftKey = true, 23 | TargetTouches = Array.Empty(), 24 | Touches = Array.Empty(), 25 | Type = "TOUCH", 26 | }; 27 | 28 | VerifyEventRaisesCorrectly(helper, expected); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/bunit.tests/Extensions/RenderedComponentRenderExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit; 2 | 3 | public class RenderedComponentRenderExtensionsTest : BunitContext 4 | { 5 | [Fact(DisplayName = "Render rethrows exceptions from SetParameterAsync")] 6 | public void Test001() 7 | { 8 | var cut = Render(); 9 | 10 | var exception = Should.Throw( 11 | () => cut.Render(ps => ps.Add(qt => qt.Value, "something"))); 12 | exception.InnerException.ShouldBeOfType(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/bunit.tests/Rendering/ComponentParameterTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.Rendering; 2 | 3 | public class ComponentParameterTest 4 | { 5 | [Fact(DisplayName = "Creating a cascading value with null throws")] 6 | public void Test001() 7 | { 8 | Should.Throw(() => ComponentParameter.CreateCascadingValue(null, null!)); 9 | } 10 | 11 | [Fact(DisplayName = "Creating a regular parameter without a name throws")] 12 | public void Test002() 13 | { 14 | Should.Throw(() => ComponentParameter.CreateParameter(null!, null)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/bunit.tests/TestDoubles/BunitSignOutSessionStateManagerTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles; 2 | 3 | public class BunitSignOutSessionStateManagerTest : BunitContext 4 | { 5 | [Theory, AutoData] 6 | public void ShouldSignOut(string randomUserName) 7 | { 8 | AddAuthorization().SetAuthorized(randomUserName); 9 | var cut = Render(); 10 | 11 | cut.Find("button").Click(); 12 | 13 | Services.GetService()! 14 | .IsSignedOut 15 | .ShouldBeTrue(); 16 | } 17 | 18 | [Fact] 19 | public async Task ShouldReturnSignOutStateOnValidateSignOutState() 20 | { 21 | var cut = new BunitSignOutSessionStateManager(Substitute.For()); 22 | await cut.SetSignOutState(); 23 | 24 | var wasValidate = await cut.ValidateSignOutState(); 25 | 26 | wasValidate.ShouldBeTrue(); 27 | cut.IsSignedOut.ShouldBeFalse(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/bunit.tests/TestDoubles/Components/ComponentDoubleBaseTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles.Components; 2 | 3 | public class ComponentDoubleBaseTest : BunitContext 4 | { 5 | private sealed class ComponentDouble : ComponentDoubleBase 6 | where TComponent : IComponent 7 | { } 8 | 9 | [Theory(DisplayName = "Double captures unmatched parameters")] 10 | [AutoData] 11 | public void Test022(string attrName, string attrValue) 12 | { 13 | var cut = Render>>(ps => ps 14 | .AddUnmatched(attrName, attrValue)); 15 | 16 | cut.Instance.Parameters[attrName].ShouldBe(attrValue); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/bunit.tests/TestDoubles/Components/StubTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles.Components; 2 | 3 | public class StubTest : BunitContext 4 | { 5 | [Fact(DisplayName = "Stub renders nothing without a replacement template")] 6 | public void Test001() 7 | { 8 | var cut = Render>(); 9 | 10 | cut.Nodes.Length.ShouldBe(0); 11 | } 12 | 13 | [Theory(DisplayName = "Stub captures parameters passed to TComponent")] 14 | [AutoData] 15 | public void Test002(string header, string attrValue) 16 | { 17 | var cut = Render>(ps => ps 18 | .AddUnmatched(nameof(Simple1.Header), header) 19 | .AddUnmatched(nameof(Simple1.AttrValue), attrValue)); 20 | 21 | cut.Instance 22 | .Parameters 23 | .ShouldSatisfyAllConditions( 24 | ps => ps.ShouldContain(x => x.Key == nameof(Simple1.Header) && header.Equals(x.Value)), 25 | ps => ps.ShouldContain(x => x.Key == nameof(Simple1.AttrValue) && attrValue.Equals(x.Value)), 26 | ps => ps.Count.ShouldBe(2)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/bunit.tests/TestDoubles/NavigationManager/BunitNavigationInterceptionTest.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.TestDoubles; 2 | 3 | public class BunitNavigationInterceptionTest 4 | { 5 | [Fact(DisplayName = "EnableNavigationInterceptionAsync returns completed task")] 6 | public void Test001() 7 | { 8 | new BunitNavigationInterception() 9 | .EnableNavigationInterceptionAsync() 10 | .IsCompletedSuccessfully 11 | .ShouldBeTrue(); 12 | } 13 | 14 | [Fact(DisplayName = "FakeNavigationInterception is registered as the default INavigationInterception")] 15 | public void Test002() 16 | { 17 | using var ctx = new BunitContext(); 18 | ctx.Services.GetService() 19 | .ShouldBeOfType(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/bunit.tests/TestUtilities/JSRuntimeInvocationAssertionHelpers.cs: -------------------------------------------------------------------------------- 1 | namespace Bunit.JSInterop; 2 | 3 | public static class JSRuntimeInvocationAssertionHelpers 4 | { 5 | public static void ShouldBe(this JSRuntimeInvocation actual, JSRuntimeInvocation expected) 6 | { 7 | actual.ShouldSatisfyAllConditions( 8 | x => x.Identifier.ShouldBe(expected.Identifier), 9 | x => x.Arguments.ShouldBe(expected.Arguments), 10 | x => x.CancellationToken.ShouldBe(expected.CancellationToken), 11 | x => x.InvocationMethodName.ShouldBe(expected.InvocationMethodName), 12 | x => x.IsVoidResultInvocation.ShouldBe(expected.IsVoidResultInvocation), 13 | x => x.ResultType.ShouldBe(expected.ResultType)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/bunit.tests/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Bunit.TestAssets.SampleComponents 2 | @using Bunit.TestAssets.SampleComponents.Data 3 | @using Shouldly 4 | -------------------------------------------------------------------------------- /tests/bunit.tests/bunit.tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0;net9.0;net10.0 5 | Bunit 6 | Bunit.Tests 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/bunit.tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "diagnosticMessages": false 4 | } 5 | -------------------------------------------------------------------------------- /tests/bunit.web.query.tests/bunit.web.query.tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0;net9.0;net10.0 5 | Bunit 6 | Bunit.Web.Query.Tests 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/run-tests.ps1: -------------------------------------------------------------------------------- 1 | $maxRuns = $args[0] 2 | $mode = $args[1] 3 | $filter = $args[2] 4 | 5 | dotnet build ..\bunit.sln -c $mode --nologo 6 | 7 | for ($num = 1 ; $num -le $maxRuns ; $num++) 8 | { 9 | Write-Output "### TEST RUN $num ###" 10 | 11 | if($filter) 12 | { 13 | dotnet test ..\bunit.sln -c $mode --no-restore --no-build --blame --nologo --filter $filter 14 | } 15 | else 16 | { 17 | dotnet test ..\bunit.sln -c $mode --no-restore --no-build --blame --nologo 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "diagnosticMessages": false, 4 | "methodDisplayOptions": "all", 5 | "parallelAlgorithm": "conservative", 6 | "maxParallelThreads": "2x", 7 | "parallelizeTestCollections": true 8 | } 9 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "2.0-preview", 4 | "assemblyVersion": { 5 | "precision": "revision" 6 | }, 7 | "nuGetPackageVersion": { 8 | "semVer": 2.0 9 | }, 10 | "publicReleaseRefSpec": [ 11 | "^refs/heads/stable$" 12 | ], 13 | "cloudBuild": { 14 | "buildNumber": { 15 | "enabled": true 16 | } 17 | }, 18 | "release": { 19 | "branchName": "release/v{version}", 20 | "firstUnstableTag": "preview" 21 | }, 22 | "pathFilters": [ 23 | "./src" 24 | ] 25 | } 26 | --------------------------------------------------------------------------------