2023-12-24

2023 retrospective

 Kind of personal. As 2024 approaches, looking back how 2023 has been for me and people around. 



In my family the year has completed the cycle of learning. All kids graduated in the subjects of their choice. Myself personally gone over being the performing force to the subject of steering the things around. The initiatives from ideas and POCs become real projects thanks to colleagues and management in Bluescape. This has laid the foundation for a new role I am looking forward to take for next year as the founder and owner in the Cyber Security space. The final separation from Bluescape had cut off the unnecessary obligations, opening the clean and fresh start. 


What 2023 taught me? The motto “BE CURIOUS, LEARN AND ADOPT KNOWLEDGE, SEEK THE PATH, STATE THE GOALS AND OVERCOME” become a powerful set of principles. The curiosity on things around along with learning and comparing allowed me to approach the challenges as on business as on technology sides. The curiosity extended to the team’ challenges, along with learning following the discoveries and sharing brought people closer. Resulting in efficient cooperation and expanding the personal abilities to the team synergy. It also exposed that working in the team is a level of magnitude more efficient. 


In 2023 AI has stepped into professional life. Not much as the syntax and ‘tune’ checker for public writing, but rather an efficient helper on search services for relatively simple solutions which are not yet covered by someone’s blog or Q&A site like stackoverflow or Reddit. The coding with AI itself is not yet powerful, though great for algorithm and unit tests stubs generation.


AI vs team. The AI at its current level is not a replacement for a team at all. It allowed me to write up my own thoughts, but when it comes to cognitive analysis and critical thinking, there is no replacement for a team. Next year, I plan to try different AI services as it has been proven to be a great time saver.


Once again, the statement “in software there is no impossible, it is just a matter of time and available resources” have been proven. Ability to explore the options from different angles and not limiting to seem to be easiest solutions, allowed to beat the border between native executable and web microapplication. The nodeJs CLI app can be packaged as native executable. But there was no reference on how to make it in-browser application. The answer was in implementing node APIs when assembling the web app. Many Open Source projects paved the base for the Cloud version of CLI I made, which inspired me to contribute more to OSS. 


2023 being an apogee in my OSS efforts. With the help of web stack leaders from W3C groups, the Declarative Web Application has been shaped into a useful NO-JS UI platform, with Declarative Custom Element at the forefront. Apparently that became an answer to the Cyber Security Office challenge on safe programming languages, frameworks and app engines. The RFI we created would lay out the basis for my activities for the next few years. However, to make a real impact, the idea must become a sustainable business. This is another challenge I plan to tackle in 2024.


Be Dragon in you! Wise and powerful.

-s



2023-03-12

How to integrate MSW queries mocking with @web/test-runner and StoryBook

In short, follow the comments in Pool Request

TLDR


The serious WebComponents and UI components development SDLC needs the TDD ability to create UI, visually test with incremental changes, apply the unit tests for functional parts, CI/CD integration for visual and functional regression. 

Those tasks are perfectly covered by 

  • StoryBook as component based UI development media. It allows to do the development per component detached from main application/library. In addition to development of single use case, it gives ability to change the component parameters, and its behavior in various external conditions like high contrast/dark/light display mode, blurred vision, etc. Which is a must during development of accessible UI components and components with parameter driven variations.  
  • @web/test-runner - the browser based unit test runner. The perfect combo of CLI and in-browser development. 
Both, a visual development in StoryBook, and functional unit testing need the data mocking which is provided by
  • MockServiceWorker - MSW helper for interrupting the back-end HTTP calls and simulating the response behavior with headers, data and errors.   
All sounds as a perfect combo till the moment trying to make a plumbing in real project. It happen that many nuances are not covered by docs and some aspects of MSW deployment strategies become impossible to resolve. Till now. 

MSW packaging includes CJS( node kind of modules ) and IILF (ES5 no-module) formats. In StoryBook it works out of the box as it is based on WebPack build which resolves CJS and bundles-in the MSW code. 
Unfortunately it become an issue in non-compile based environments including @web/test-runner. There is no es6 module which can be imported directly. 

The top-level await become a savior. IILF formatted script can be loaded by SCRIPT tag and its variables re-exported by es6 module. msw.js module source
const msw = await new Promise((resolve,reject)=>
{
    ((d, s)=>
    {   s = d.createElement('script')
        s.setAttribute('src','node_modules/msw/lib/iife/index.js');
        s.onload = ()=> resolve( window.MockServiceWorker );
        d.head.append(s)
    })(document)
});

export const    { GraphQLHandler
                , MockedRequest
                , RESTMethods
                , RequestHandler
                , RestHandler
                , SetupApi
                , SetupWorkerApi
                , cleanUrl
                , compose
                , context
                , createResponseComposition
                , defaultContext
                , defaultResponse
                , graphql
                , graphqlContext
                , handleRequest
                , matchRequestUrl
                , response
                , rest
                , restContext
                , setupWorker
                } = msw;
This module is used by unit test config and in mock handlers. To make it compatible with usual use by StoryBook compatible code, add the import maps support in web-test-runner.config.mjs
plugins:[
        importMapsPlugin({
      inject: {
        importMap: {
          imports: {
            'msw': '/src/mocks/msw.js',
          },
        },
      },
    }),
    ]
Which would make the import in StoryBook and in unit test alike. handlers.js:
import { rest } from 'msw'

import pokemonsMock from "../../stories/pokemons.mock";

export const handlers =
[   rest.get("*/api/v2/pokemon", (req, res, ctx) =>
    {
        return res(ctx.json(pokemonsMock));
    }),
    rest.get("*/noreturn", (req, res, ctx) =>
            {   console.log(req.url, 'trapped')
                return new Promise((resolve)=>{ setTimeout(()=>
                {   console.log(req.url, 'resolving')
                    resolve(res(ctx.json(pokemonsMock)))
                }, 10000)}); // 1 second to be able to catch the initial state before the full data returned;
            }),
]
The service worker needs a bit of tuning to be reused by StoryBook and unit tests. First comes initialization on root level:

npx msw init "./" --save

Then in .storybook/main.js
module.exports = {
    staticDirs: [
        {from: '../mockServiceWorker.js', to: '/mockServiceWorker.js'} // MSW support
    ],

}
and in .storybook/preview.js
import { initialize, mswDecorator } from "msw-storybook-addon";

import {handlers} from "../src/mocks/handlers";

export const parameters = {
    msw: {handlers},
};

// Initialize MSW
initialize();

// Provide the MSW addon decorator globally
export const decorators = [mswDecorator];
The unit test MSW setup is a bit trickier. Besides configuration of the import maps to simulated JS msw module above, in each test you would need to import browser.js
// src/mocks/browser.js
import { setupWorker } from './msw.js'
import { handlers } from './handlers.js'

// This configures a Service Worker with the given request handlers.
export const worker = setupWorker(...handlers)
await worker.start({ serviceWorker: { url: '/mockServiceWorker.js' } });
Hopefully that is sufficient. If not, take a look into notes on PR or bug me.

Happy coding!