2024-09-30


Can the expenses for creating mock data in unit tests become a source of business profit? Absolutely! Here’s how.


Most web applications, whether they are healthcare portals or shopping carts, require seed data with a user set that reflects all variations of application data associated with those users. This set is a crucial part of the deployment process to run integration and end-to-end tests. It is also essential for smoke testing before A/B deployment activates the infrastructure components with new code.This is a well-known pattern used in most enterprise-quality software products.


Restricting such valuable data solely to the deployment process is a missed opportunity in various business use cases and throughout the Software Development Life Cycle (SDLC).


You might wonder how this data can have any business value?It seems like just an unavoidable product maintenance cost. And you would be right—until your app needs to be indexed by search engines and operable by AI assistants for user-specific parts of the application. Of course, exposing private user data is not an option. This is where synthetic personas from seed data become invaluable. Since this data set does not contain any real personal information, it is safe to expose to search engines and AI crawlers. If the app is developed with accessibility compliance and SEO in mind, these business goals can be achieved.


In SDLC the seed data can ( IMO should ) be propagated into mock data for the UI components and pages to be used in

* StoryBook

* unit tests

* serverless UI run

* e2e integration tests.


Data can be saved as a module, better with strict typing in place. If your project uses TypeScript, Java, or C#, that is the format to use. 


One of the advantages of GraphQL is its ability to generate client code for target languages such as TypeScript or Java. In similar fashion your script can crawl through all graphql queries in application and execute them on behalf of each synthetic persona in the data seed. The same mock generation routine should also generate the Mock Service Worker (MSW) handler to be used in StoryBook, unit tests, and serverless mode.


If your mocking frame with seed data that can be created ahead of UI components,  it would be a huge time saver for developers and QA as there will be no difference on data protocol on all those aspects of application front-end. 


Once the mocking is available for each synthetic persona, the MSW would help to run the front-end without back-end helping to validate the UI in isolation with the same test set as the full e2e/integration test. It would enable you to identify the tier which is responsible for the failed test without the need for manual troubleshooting for finding the guilty front-, back-, or DB side and forwarding to responsible team members if your tiers are implemented by different folks. Or just simplify the fix if your people are full stack developers. 


While SEO, search engine indexing, and AI vectors are separate topics,  here I just want to point out that pages with synthetic persona data would be publicly available, improving your site visibility and empowering your application users with AI assistants. 


My team has implemented most of the design outlined above, and is currently finalizing the business use. I would be glad to discuss the impact of such an approach on your product. 



Happy coding!


2024-04-10

UI TDD with StoryBook

 The Test Driven Development process assumes the incremental steps of module logic improving starting with unit test following the implementation in the source code. As unit test is created, it immediately should fail as the logic still has to be done. Once logic is in place, the next feature added to the unit test and the cycle repeats…


The UI development used to be different as there was no ability to do the checks and incremental code improvements. The module (UI component) used to be tested within the web application without insulation and ability to visualize the variations without app state change or the following the whole flow leading to the UI variation. Till the StoryBook became a natural part of UI SDLC. 


What is a StoryBook? It is a toolkit for various aspects for UI development. 


When installed inside of the web UI project as a NPM module, it allows to run the components collection with all variations within the StoryBook interface which is not attached to the actual web app your team is working on. Instead, it exposes the collection of UI components hierarchically organized and exposes the samples of the UI variations and use cases.


Of course the UI has a lot of aspects besides basic variations. Those include but not limited to:

  • Color theming: dark, light, high contrast light/dark

  • Language switch

  • Various screen sizes and mobile variations

  • Accessibility: 

    • blurred vision, limited colors, etc.

    • Screen reader 

    • Keyboard navigation

  • Set of mocked user roles

And so on… All the listed is covered by StoryBook making it “a must” part of the UI development stack. Which is especially important for enterprise grade applications bound by various compliance requirements.


Compliances aside, StoryBook gives the frame to practice TDD during UI component development. Once the SB UI is running, developers would be able to work on individual UI component in insulation. 

( in examples I use the “native” JS web components, the React or Angular typescript module work in similar fashion )

  1. For xxx module, create the xxx.stories.ts file either in the folder for component or in directory dedicated for stories

  2. Inside of .stories.tx file you would keep the UI variations of component (similar to unit tests variations). Those would export

    1. Parameters set for SB which should cover all use cases 

  1. Template to render component UI with parameters ^^

  2. Use cases. A template to particular parameters binding.

Once the use cases created, they would be listed in SB interface. To work with component in insulation, there is a “Open Canvas in new tab” button:

That is where the primary development for your component would be shown:

As SB is served in the browser, the dev tools at your service to inspect the UI styles, debug code, etc. The code hot reload allows you to change the code and immediately see the affected UI.


StoryBook gives you the ability to integrate with Figma and other UI design services. The link inside of your story would lead to the UI design to compare the components against design.


Once your component is ready and becomes a part of the application, it is important to check whether following changes break any UI appearance. The pixel comparison tools like Chromatic or SauceLabs Selenium would give you ability to:

  • See the pixel difference between original and code in pool request

  • Engage UX team in visual changes approval

That assures there are no UI regressions introduced by pool request.


Here we touched just UI TDD aspects, but other features by SB are not less important in enterprise grade UI.

The StoryBook is well detailed on https://storybook.js.org and covered by multiple web and video blogs. 


<custom-element> test project used as example. Happy coding!

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!




2021-12-19

npx dockerize-npm-module


Thinking aloud on challenge I am facing as JS developer.

Problem: NPM-based projects often require specific dependencies versions installation and version tune up which is 

  • time consuming ( curse of node-gyp or sass )
  • could mess up machine environment for other projects. 
Such dev and build dependencies could be pre-configured and jailed within docker image exposing only input/output folders and working ports on developer's machine.  

GitHub and other code management repositories are given ability to run continuous integration (CI) steps as Docker container actions

Those actions could be run as part of CI during deployment but also locally to prevent aforementioned problems. 

Solutionhttps://github.com/nektos/act - locally installed "act' app.

PROS: almost complete CI/CD cycle coverage. 

CONS: requires installation and ? per-project tune-up.

Proposal: npx dockerize-npm-module [NPM_SCRIPT_COMMAND]

Seamless as non-installable CLI to run all package.json commands in preconfigured image for docker container.

+ config generation/load

? reuse GitHub container actions  

+ upgrade package.json with safe:xxx scripts meant to run same NPM commands in docker container or add docker CI/CD steps. 

2021-10-31

HTML5 SLOT tag for content management explained

Web Components stack includes efficient and well thought through templating solution with TEMPLATE and SLOT tags. While those have been widely adopted in web components world for multiple reasons, the shadow DOM behind of this tech prevents to use it in environments where UI styles managed separately and often driven by heavy legacy content: while styling in shadow DOM has own perks like css insulation, it does not work well with global css styling. 

I would suggest to utilize the concept of slot in template  in content management environments with classic css use. You could implement the convention by yourself with showing/hiding the slot with name  


el.querySelector('slot[name="final"]').hidden = false;

To avoid the UI flickering , make sure the initial HTML includes the visibility state meant to be shown before JS is able to act:


<slot name="initial">Please wait while loading...</slot>
<slot name="final" hidden> initially is hidden, filled by JS and then shown </slot>

 

NOTE. The hidden attribute behavior is self-explanatory and works out of the box, no need for CSS. But if your environment is a CMS like Adobe AEM, Liferay, or Drupal, the CSS on the page is most likely a product of multiple people/teams over the years. Here the default behavior could be tricked by different CSS rules and you would need to elevate:
        
slot[hidden]{ display:none!important;}

Of course the page level javascript and HTML would limit only one slot name a time. Wrapping slots combinations into identifiable by JS container would help to handle multiple UI components with same kind of UI pattern(template). Like the avatar in the list and in profile UI. 

The most convenient way to connect JS and HTML element is a custom element, i.e. Web Component with own tag. `this` in its methods would point to html element of own tag which would be triggered every time the tag appear in HTM, initially or dynamically later. In CMS it would prevent the messing with page, document, and script load handlers, a huge win for code maintenance when the code is spread across developers/teams and time.

Web Component does not dictate the use of ShadowDOM and allows to pick any way of template implementation. There are multiple "frameworks" with opinionated ways of templates handling. The HTML content meant to be handled by middle tier in classic CMS. Where the templates also play important role in content lifecycle. Adding another templating engine is not just increasing the complexity but also created the conflict between different approaches and handling the content variations like multi-lingual support or cohort targeting.  Hence ability to reuse the CMS HTML capabilities along with template/slot concept would be most beneficial.

As CMS usually is not designed to serve the dynamic data, the fusion of externally served data and UI from CMS becomes a data plumbing task on UI tier. During this "data plumbing" process the UI should support multiple states including initial waiting, loading, error of multiple kind, and final with rendered data, perhaps with variations on data internals.

slotted-element comes handy for eliminating the coding for data plumbing in simplest cases and simplifying the programming otherwise. 

Here this custom element is a sample for typical data plumbing to CMS driven HTML tasks.

  • switch between slots to be shown. Hide all, display only one. 
  • clone slot content to be filled with data
  • add customized slot. Could be more than once for list.
  • data retrieval layer: url/method/headers/body, status, error handling, fetched data conversion.
  • UI sub-elements access and manipulation convenience methods.

Whether you choose to use slotted-element, extend it, or decide to create own, keep in mind the list ^^. 

Links:

Using templates and slots



2021-07-11

XSLT 1.0 in-browser Q&A

  • How to get XSLT path from within XSLT?

<xsl:value-of select="substring-before(substring-after(/processing-instruction('xml-stylesheet'),'href=&quot;'),'&quot;')"/>

XML: <?xml-stylesheet type="text/xsl" href="../AsTable.xsl" ?>

Gives: ../AsTable.xsl

  • How to get relative URL of  specific XSLT from XML?

<xsl:value-of select="substring-before(substring-after(/processing-instruction('xml-stylesheet'),'href=&quot;'),'AsTable.xsl&quot;')"/>

    Gives: ../


    • How to get Javascript URL relative to XSLT applied to XML as processing instruction?
    XSLT:
    <xsl:param name="baseUrl" select="substring-before(substring-after(/processing-instruction('xml-stylesheet'),'href=&quot;'),'AsTable.xsl&quot;')"  />
    <script type="module" src="{$baseUrl}XmlView.js">/**/</script> 

    Gives: ../XmlView.js


      • list of unique children tags (each last)
      *[ not( name() = name(following-sibling::*) ) ]
      • how to output XSL from XSL
      Add namespace with altered URL, namespace-alias, use the namespace in output:
      <xsl:stylesheet version="1.0"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xvxsl="http://www.w3.org/1999/XSL/TransformAlias">
      <!--
      * get entries for table presentation and
      * fills in xsl:template mode="DisplayAs" for each
      -->
      <xsl:output method="xml" />
      <xsl:namespace-alias stylesheet-prefix="xvxsl" result-prefix="xsl"/> ...
      <xvxsl:template mode="DisplayAs" match="{$xPath}">
      • how to debug XSL? 
      Currently the most convenient way is given by Visual Studio Pro edition. Trial available.