asp.net core – How to do functional test with blazor server page that contains a client connection to signalR hub

Lost as to how to perform functional test for a blazor server page that contains a signalR client hub connection.

So far I have tried spinning up a WebApplicationFactory(WAF) from the SUT Startup class. I then copy the required services from the WAF over into the services of the BUnit test context.

The issue comes when the Blazor server page tries to connect to the signalR hub provided by the WAF. A System.Net.Http.HttpRequestException: Connection refused exception occurs (see listings below). I think this is because the WAF is not using sockets, i.e. it offers an in-memory server??

How are others performing tests for a similar scenario with signalR and Blazor?

Test so far

  (Fact)
        public async Task Test_RendersImage()
        {
            // initialise BUnit with services from WebApplicationFactory
            InitialiseBUnitServices();

            // publish an mqtt message to trigger sending event from signalR to Blazor server page
            // this is triggering back-end services as expected
            await _Server.MqttClient.PublishAsync(CreateMessageFromStream(_Stream));
            await Task.Delay(3000);

            // request bUnit to render the client page and listen for data from signal R here
           // fails to connect to signalR hub here
            var cut = RenderComponent<WebApp.Pages.Index>();

            // output markup to check that client page rendered the incoming data
            _Output.WriteLine($"{cut.Markup}");

            // await CompletedTask to allow compilation of this async test stub 
            await Task.CompletedTask;
        }


        /// <summary>Create an mqtt message from stream</summary>
        private ManagedMqttApplicationMessage CreateMessageFromStream(MemoryStream stream)
        {
            const string Topic = "shinobi/group/monitor/trigger";

            var message = new MqttApplicationMessageBuilder()
                .WithTopic(Topic)
                .WithPayload(stream.ToArray())
                .Build();

            return new ManagedMqttApplicationMessageBuilder()
                .WithApplicationMessage(message)
                .Build();
        }

        private void InitialiseBUnitServices()
        {
            // get services from WebApplicationFactory and inject into bUnit
            var hubProxyFactory = _Server.Factory.Services.GetRequiredService<IHubProxyFactory>();
            var loggerDetectionConverter = _Server.Factory.Services.GetRequiredService<ILogger<MotionDetectionConverter>>();
            var loggerIndexPage = _Server.Factory.Services.GetRequiredService<ILogger<WebApp.Pages.Index>>();
            var loggerInfoConverter = _Server.Factory.Services.GetRequiredService<ILogger<MotionInfoConverter>>();
            var loggerJsonVisitor = _Server.Factory.Services.GetRequiredService<ILogger<JsonVisitor>>();
            var loggerRepository = _Server.Factory.Services.GetRequiredService<ILogger<MotionDetectionRepository>>();
            var navManager = _Server.Factory.Services.GetRequiredService<NavigationManager>();
            var repository = _Server.Factory.Services.GetRequiredService<IMotionDetectionRepository>();

            Services.AddSingleton(typeof(IHubProxyFactory), hubProxyFactory);
            Services.AddScoped<ILogger<MotionDetectionConverter>>(sp => loggerDetectionConverter);
            Services.AddScoped<ILogger<WebApp.Pages.Index>>(sp => loggerIndexPage);
            Services.AddScoped<ILogger<MotionInfoConverter>>(sp => loggerInfoConverter);
            Services.AddScoped<ILogger<JsonVisitor>>(sp => loggerJsonVisitor);
            Services.AddScoped<ILogger<IMotionDetectionRepository>>(sp => loggerRepository);
            Services.AddScoped<MockNavigationManager>(sp => new MockNavigationManager());
            Services.AddScoped<IMotionDetectionRepository>(sp => repository);
        }

Blazor Server Page

  protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                /// <summary>
                /// Looks like abstract base class NavigationManager also needs a mock or sub class for unit testing.
                /// Cannot resolve RemoteNavigationManager from container, it is an internal class. So for mocking purposes have injected a subclass for bUnit tests.
                /// </summary>
                var hubUrl = NavigationManager.BaseUri.TrimEnd('/') + "/motionhub";
                hubUrl = "http://localhost:5000/motionhub"; // hard code url for now 
                try
                {
                    /// <summary> Using wrapper to allow unit testing!</summary>
                    Logger.LogInformation("Index.razor page is performing initial render, connecting to secondary signalR hub");
                    Logger.LogInformation($"hubUrl is {hubUrl}");
                    hubConnection = HubConnectionBuilder.Create(
                        hubUrl,
                        JsonConvertersFactory.CreateDefaultJsonConverters
                        (
                            LoggerMotionDetection,
                            LoggerMotionInfo,
                            LoggerJsonVisitor
                        )
                    );

                    hubConnection.On<MotionDetection>("ReceiveMotionDetection", ReceiveMessage);
                    hubConnection.Closed += CloseHandler;

                    Logger.LogInformation("Starting HubConnection");
                    await hubConnection.StartAsync();
                    Logger.LogInformation("Index Razor Page initialised, listening on signalR hub => " + hubUrl.ToString());
                }
                catch (Exception e)
                {
                    Logger.LogError(e, "Encountered exception => " + e);
                }
            }
        }
  Encountered exception => System.Net.Http.HttpRequestException: Connection refused
       ---> System.Net.Sockets.SocketException (61): Connection refused
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         --- End of inner exception stack trace ---
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.AccessTokenHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)
         at WebApp.Pages.Index.OnAfterRenderAsync(Boolean firstRender) in /Users/simon/Development/Dotnet/CamFrontEnd/Src/WebApp/Pages/Index.razor.cs:line 167
      System.Net.Http.HttpRequestException: Connection refused
       ---> System.Net.Sockets.SocketException (61): Connection refused
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         --- End of inner exception stack trace ---
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.AccessTokenHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)

javascript – Functional programming FizzBuzz

I tried to code the fizzbuzz program following the functional programming rules in javascript. Please check my code and give feedback. thank you.

const isDivisible = (number, fizz) => number % fizz === 0;
const getSubstitutes = (
  number,
  substitutes,
  { currentIndex = 0, result = "" } = {}
) => {
  if (currentIndex === substitutes.length) return result;
  const { divisor, substitute } = substitutes(currentIndex);
  const newResult = result + (isDivisible(number, divisor) ? substitute : "");
  return getSubstitutes(number, substitutes, {
        currentIndex: currentIndex + 1,
        result: newResult,
  });
};
const fizzBuzz = (number, substitutes, currentIndex = 1) => {
  if (number < currentIndex) return;
  console.log(getSubstitutes(currentIndex, substitutes) || currentIndex);
  fizzBuzz(number, substitutes, ++currentIndex);
};
const substitutes = (
  {
        divisor: 3,
        substitute: "fizz",
  },
  {
        divisor: 5,
        substitute: "buzz",
  },
);
fizzBuzz(100, substitutes);

object oriented – JavaScript, looping, and functional approach

Data Structure coming back from the server

(
  {
    id: 1,
    type: "Pickup",
    items: (
      { 
        id: 1, 
        description: "Item 1"
      }
    )
  },
  {
    id: 2,
    type: "Drop",
    items: (
      { 
        id: 0, 
        description: "Item 0"
      }
    )
  },
  {
    id: 3,
    type: "Drop",
    items: (
      { 
        id: 1, 
        description: "Item 1"
      },
      { 
        id: 2, 
        description: "Item 2"
      }
    )
  },
  {
    id: 0,
    type: "Pickup",
    items: (
      { 
        id: 0, 
        description: "Item 0"
      },
      { 
        id: 2, 
        description: "Item 2"
      }
    )
  }
);
  • Each element represents an event.
  • Each event is only a pickup or drop.
  • Each event can have one or more items.

Initial State

On initial load, loop over the response coming from the server and add an extra property called isSelected to each event, each item, and set it as false as default. — Done.

This isSelected property is for UI purpose only and tells user(s) which event(s) and/or item(s) has/have been selected.

// shove the response coming from the server here and add extra property called isSelected and set it to default value (false)
const initialState = {
  events: ()
}

moveEvent method:

const moveEvent = ({ events }, selectedEventId) => {
  // de-dupe selected items 
  const selectedItemIds = {};
  
  // grab and find the selected event by id
  let foundSelectedEvent = events.find(event => event.id === selectedEventId);
  
  // update the found event and all its items' isSelected property to true
  foundSelectedEvent = {
    ...foundSelectedEvent, 
    isSelected: true,
    items: foundSelectedEvent.items.map(item => {
      item = { ...item, isSelected: true };
      // Keep track of the selected items to update the other events.
      selectedItemIds(item.id) = item.id;
      return item;
    }) 
  };

  events = events.map(event => {
    // update events array to have the found selected event
    if(event.id === foundSelectedEvent.id) {
      return foundSelectedEvent;
    }
    
    // Loop over the rest of the non selected events
    event.items = event.items.map(item => {
      // if the same item exists in the selected event's items, then set item's isSelected to true.
      const foundItem = selectedItemIds(item.id);
      // foundItem is the id of an item, so 0 is valid
      if(foundItem >= 0) {
        return { ...item, isSelected: true };
      }
      return item;  
    });
    
    const itemCount = event.items.length;
    const selectedItemCount = event.items.filter(item => item.isSelected).length;
    
    // If all items in the event are set to isSelected true, then mark the event to isSelected true as well.
    if(itemCount === selectedItemCount) {
      event = { ...event, isSelected: true };
    }

    return event;
  });

  return { events }
}

Personally, I don’t like the way I’ve implemented the moveEvent method, and it seems like an imperative approach even though I’m using find, filter, and map.
All this moveEvent method is doing is flipping the isSelected flag.

  1. Is there a better solution?
  2. Is there a way to reduce the amount of looping? Maybe events should be an object and even its items. At least, the lookup would be fast for finding an event, and I don’t have to use Array.find initially. However, I still have to either loop over each other non selected events’ properties or convert them back and forth using Object.entries and/or Object.values.
  3. Is there more a functional approach? Can recursion resolve this?

Usage and Result

// found the event with id 0
const newState = moveEvent(initialState, 0);

// output
(
  {
    id: 1,
    type: 'Pickup',
    isSelected: false,
    items: ( { id: 1, isSelected: false, description: 'Item 1' } )
  }
  {
    id: 2,
    type: 'Drop',
    // becasue all items' isSelected properties are set to true (even though it is just one), then set this event's isSelected to true
    isSelected: true,
    // set this to true because event id 0 has the same item (id 1)
    items: ( { id: 0, isSelected: true, description: 'Item 0' } )
  }
  {
    id: 3,
    type: 'Drop',
    // since all items' isSelected properties are not set to true, then this should remain false.
    isSelected: false,
    items: (
      { id: 1, isSelected: false, description: 'Item 1' },
      // set this to true because event id 0 has the same item (id 2)
      { id: 2, isSelected: true, description: 'Item 2' }
   )
  }
  {
    id: 0,
    type: 'Pickup',
    // set isSelected to true because the selected event id is 0
    isSelected: true,
    items: (
      // since this belongs to the selected event id of 0, then set all items' isSelected to true
      { id: 0, isSelected: true, description: 'Item 0' },
      { id: 2, isSelected: true, description: 'Item 2' }
    )
  }
)

functional analysis – Question on sequences on banach spaces

I am trying to do this exercise: Suppose $X$ is a Banach Space and $(x_j)_{j=1}^{infty}$ a sequence in $X$. Suppose $f in X^{*}$ with $sum_{j=1}^{infty}left|fleft(x_{j}right)right|<infty$. Prove that there is a constant $M>0$ such that $sup _{k in mathrm{N}}left|sum_{j=1}^{k} epsilon_{j} x_{j}right|_{X} leq M$ for any sequence $left(epsilon_{j}right)_{j=1}^{infty}left(epsilon_{j}=pm 1right)$.

I tried to use the fact that
$$sup _{k in mathrm{N}}left|sum_{j=1}^{k} epsilon_{j} x_{j}right|_{X} leq sup _{k in mathrm{N}}sum_{j=1}^{k}left| epsilon_{j} x_{j}right|_{X} leq sup _{k in mathrm{N}}sum_{j=1}^{k}left| x_{j}right|_{X},$$
together with defining $hat{x}_n in X^{**}$ such that $hat{x}_n(f)=f(x_n)$ and somehow try to use the uniform boundedness principle to connect both, but I am not sure how to do it, and I am a bit confussed on how to use it, because maybe I can define a sequence of operators using the partial sums or something similar. Can you give me please some hint. Thanks

functional analysis – Classic excecise of $L^p$ spaces but using uniform boundedness principle

I have the following exercise:
Let $f$ a real-valued Lebesgue measurable function on $(0,1 )$, if $fg$ is Lebesgue integrable on $(0,1)$ for any function $gin L^p((0,1),mathbb{R})$ with $p in (1,infty) $, then $fin L^{frac{p}{p-1}}((0,1),mathbb{R})$.

This is an exercise I remember from my Lebesgue Measure course, I think we proved the results for simple functions and then extend the result to $f$. But here I need to use the uniform boundedness principle, so I think I somehow need a sequence of operators, but I really don’t know how to do this.

Any hints appreciated!

Second monitor functional but frozen in Ubuntu 20.04

I’m currently experiencing an issue where my second monitor is detected, displayed, and is functional. However, my screen will instantly freeze and capture whatever is on my screen at the time of activation. I can still drag apps over there, select things, and use my taskbar. My mouse can also move across my monitor like it’s nothing. I haven’t seen any cases of other people experiencing this issue, so this may be hard to solve. I experience this issue with all monitors, and it’s not a hardware issue because I was previously duel booting this exact system on my PC. I’m using Ubuntu 20.04.

matrices – Functional relation for Whittaker-like functions

Let $G = GL_r$ and consider functions such that $phi(ng) = theta(n)phi(g)$ for all $g in G$ and $n$ in the subgroup of upper triangular unipotent matrices. Here, $theta$ is the character on $N$ defined by $theta(n) = prod_i psi(n_{i, i+1})$ where $psi$ is a fixed additive character. I read the following relation
$$phileft(pmatrix{g &0 \ 0 & 1}pmatrix{I_{r-1} & u \ 0 & 1} right) = phileft(pmatrix{g &0 \ 0 & 1} right) psi((0, ldots, 0, 1)gu).$$

Here $u$ is a column vector. I do not make sense of this relation; I keep trying to toy with the matrices but I don”t find this specific form.

interaction design – How do you define functional continuity/unity regarding UX?

Lately, the issue of functional continuity keeps coming up at work. I’m interested in how other UX/UI designers think of continuity when they design.

The way I’ve seen it, the user needs to comfortably recognise what the UI does. What does a primary button look like? Is it always on the left or the right? What do disabled buttons look like? Things need to be represented consistently and similarly.

I’m working on a visual renewal of a pretty complex system with lots of functionalities, user processes, different levels of access rights, what have you. There are different views where the user can perform different actions, and it keeps coming up that people (people being coworkers) want everything to work exactly the same way in every view.

I understand where they are coming from, but I’m also struggling to put into words how I feel about it. Let’s say in one view, a button the user can’t use yet is disabled, and in another one the user is allowed to make the mistake of pressing the button and they receive an error message. I think both are valid options and one might work better for each use case. However, people are constantly bringing it up when discussing the designs. “Why does this work differently here? Why is it not the same in every view?”

How do you feel about it? Is this something I should improve on, or can I decide these things per use case? I’m still a bit new in the field, and I’d like to hear some opinions. I hope this made some sense!

functional analysis – AC[0,1] is completion of the space C$_1^1$[0,1]

Prove that space AC[0,1] is completion of the space C$_1^1$[0,1] and therefore it is isomorphic to W$_1^1$[0,1].

How to solve this problem by using this theorem? Could you help me?

Theorem: there is completion for any normed vector space. And if Y1 and Y2 are completions of the same space X, hence they are isometric isomorphic for each other.

functional analysis – $X$ is complete and $T$ is an onto open map, then $Y$ is complete

I am trying to prove sort of a converse to open mapping theorem. If $X, Y$ are normed linear spaces where $X$ is complete, and $T in B(X, Y)$ is open, onto then I have to show Y is complete. I came across this answer here: https://math.stackexchange.com/a/1446979/698050
and my doubt is the following:

I have proved the proposition that is mentioned, it says
$∀y ∈ Y$ there is an $x in T^{−1}(y)$ such that
$∥x∥_X ≤ C ∥y∥_Y$
.

But now to prove pullback of a Cauchy sequence in $Y$ is Cauchy in $X$, say I have $x_n$ and $x_m$ in $X$ having their norms bounded by corresponding $C||y_n||$ and $C||y_m||$. This does not imply $||x_n – x_m|| le C||y_n – y_m||$ as we can have some other $x in X$ satisfying the proposition for $(y_n – y_m)$. How do I conclude the sequence in $X$ is Cauchy then?