<?xml version="1.0" encoding="utf-8"?>

			<rss version="2.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://web.resource.org/cc/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/">

			<channel>
			<title>Jeffry Houser&apos;s Blog</title>
			<link>https://www.jeffryhouser.com/index.cfm</link>
			<description>Jeffry Houser&apos;s Blog</description>
			<language>en-us</language>
			<pubDate>Sat, 07 Mar 2026 10:27:32 -0700</pubDate>
			<lastBuildDate>Mon, 22 Dec 2025 10:54:00 -0700</lastBuildDate>
			<generator>BlogCFC</generator>
			<docs>http://blogs.law.harvard.edu/tech/rss</docs>
			
			<managingEditor>&#106;&#104;&#98;&#108;&#111;&#103;&#64;&#102;&#97;&#114;&#99;&#114;&#121;&#102;&#108;&#121;&#46;&#99;&#111;&#109;</managingEditor>
			<webMaster>&#106;&#104;&#98;&#108;&#111;&#103;&#64;&#102;&#97;&#114;&#99;&#114;&#121;&#102;&#108;&#121;&#46;&#99;&#111;&#109;</webMaster>
			<media:copyright>Copyright 2008-2026, DotComIt LLC</media:copyright>
			<media:thumbnail url="" />
            <media:keywords></media:keywords>
            <media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology/Software How-To</media:category>
            <media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology/Tech News</media:category>
			<itunes:subtitle></itunes:subtitle>
			<itunes:summary></itunes:summary>
			<itunes:category text="Technology" />
			<itunes:category text="Technology">
				<itunes:category text="Software How-To" />
			</itunes:category>
			<itunes:category text="Technology">
				<itunes:category text="Podcasting" />
			</itunes:category>
			<itunes:category text="Technology">
				<itunes:category text="Tech News" />
			</itunes:category>
			<itunes:keywords></itunes:keywords>
			<itunes:author>Jeffry Houser</itunes:author>
			<itunes:owner>
				<itunes:email>jhblog@farcryfly.com</itunes:email>
				<itunes:name>Jeffry Houser</itunes:name>
			</itunes:owner>
			
			<itunes:explicit>no</itunes:explicit>
			
			<item>
				<title>Help! I can&apos;t checkout my Git repository on Windows because the filepaths are too long</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/12/22/Help-I-cant-checkout-my-Git-repository-on-Windows-because-the-filepaths-are-too-long</link>
				<description>
				
				I was onboarding onto a new project and got an error when trying to checkout the repository.  The filepaths were too long.  How do I fix this? 

It turns out there is a git setting exactly for this issue. I just had to change my global setting.  First, check the value:

&lt;code&gt;
git config --global core.longpaths
&lt;/code&gt;

For me, I got no response when running the command, which mean the longpaths value had no value at all.  I set it to true:

&lt;code&gt;
git config --global core.longpaths
&lt;/code&gt;

And could check out my repo and I&apos;m off to the races.
				</description>
				
				<category>Git</category>
				
				<category>Professional</category>
				
				<pubDate>Mon, 22 Dec 2025 10:54:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/12/22/Help-I-cant-checkout-my-Git-repository-on-Windows-because-the-filepaths-are-too-long</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How do I check a File out from Github with a colon in it&apos;s name?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/12/12/How-do-I-check-a-File-out-from-Github-with-a-colon-in-its-name</link>
				<description>
				
				If this came up in a Google search, welcome Windows Developers.  

After decades of experience across multiple different stacks, I finally ran into a puzzling problem.  I couldn&apos;t check out a repo some of the files had colons in the file name.  That&apos;s a first for me.  

Apparently, a colon in the file name is not allowed on Windows machines, but is okay on various forms of Linux, which includes Macs.  

Since renaming the file was not an option, I ended up going into my WSL.  First install it if you haven&apos;t already: 

&lt;code&gt;
sudo apt install git -y
&lt;/code&gt;

Then I used:

&lt;code&gt;
git switch main
&lt;/code&gt;

To go to the main branch.  After that I was able to load the repo into SourceTree / GitHub desktop.

The files show up in my (windows) IntelliJ, but with a weird character where the colon should be.  I&apos;m not sure what will happen if I try to save those files / recommit then yet.  

Definitely something that was not on my bingo card for this year. I wish there was a more native way to do this.
				</description>
				
				<category>Git</category>
				
				<category>Professional</category>
				
				<pubDate>Fri, 12 Dec 2025 11:20:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/12/12/How-do-I-check-a-File-out-from-Github-with-a-colon-in-its-name</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How do I convert tests that used fakeAsync() and tick() to a Zoneless Angular Application?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/11/18/How-do-I-convert-tests-that-used-fakeAsync-and-tick-to-a-Zoneless-Angular-Application</link>
				<description>
				
				I&apos;m working with a team that is upgrading to a modern Angular version that no longer uses the zone.js library.  This upgrade help makes angular work more effectively, but is beyond the scope of this article.

In our test suite, we had some tests like this:

&lt;code&gt;
it(&apos;some test&apos;, fakeAsync(() =&gt; {
 // do something
 tick(1000);
 // check something
}));
&lt;/code&gt;

The ticks were, primarily, in the code because we were using a timer, and the tick() method was an easy way to increment the timer.

The fakeAsync() block code did not work in the context of a zoneless application.  There are some instructions out there for setting up zone.js just for application testing, however I decided to dig a bit deeper and look for a different solution.  

I found the answer in the &lt;a href=&quot;https://jasmine.github.io/api/5.12/Clock&quot;&gt;jasmine.clock()&lt;/a&gt;  

First, in my tests I had to set it up:

&lt;code&gt;
jasmine.clock().unistall();
jasmine.clock().install();
&lt;/code&gt;

Why did I have to uninstall it, then install it?  &lt;a href=&quot;https://github.com/gruntjs/grunt-contrib-jasmine/issues/213&quot;&gt;Because of some weird bug&lt;/a&gt;, which I hope will be fixed and no longer be a future issue.

The next step is to initialize the clock with a mockDate():

&lt;code&gt;
jasmine.clock().mockDate(new Date(2025, 0, 1));
&lt;/code&gt;

Now, in our test, we can use the jasmine.clock().tick():

&lt;code&gt;
// do stuff
jasmine.clock().tick(1000);
// check stuff
&lt;/code&gt;

And the code started working.  

At the end of the test, I have been uninstalling the clock:

&lt;code&gt;
jasmine.clock().unistall();
&lt;/code&gt;

A full, psuedocode sample test, so you can see all the lines in context:

&lt;code&gt;
it(&apos;some test&apos;, fakeAsync(() =&gt; {
 // set up Jasmine clock
 jasmine.clock().uninstall();
 jasmine.clock().install();
 jasmine.clock().mockDate(new Date(2025, 0, 1));

 // do something
 jasmine.clock().tick(1000);
 // check stuff

 // remove Jasmine clock
 jasmine.clock().uninstall();
}));
&lt;/code&gt;

My code started working wonderfully.  I have a video cast series about the various ways to test asnyc code with Angular, maybe I should add another to cover this.  What do you think?
				</description>
				
				<category>Professional</category>
				
				<category>Angular</category>
				
				<category>Jasmine</category>
				
				<pubDate>Tue, 18 Nov 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/11/18/How-do-I-convert-tests-that-used-fakeAsync-and-tick-to-a-Zoneless-Angular-Application</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How can I use Vue&apos;s ToRaw() in Svelte?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/11/5/How-can-I-use-Vues-ToRaw-in-Svelte</link>
				<description>
				
				Both Vue and Svelte us something that I call Runes.  These are special functions that have special meaning to the framework.  I find these concepts parallel.  Svelte uses $derived(), which is similar to Vue&apos;s computed().  Svelte uses $state(), which is similar to Vue&apos;s Ref().

These special functions are often used to wrap the variable values you want to use.  For normal use the framework makes the rune transparent, but for debugging you get a function or something similar--not the actual value.  

Vue provides a function, &lt;a href=&quot;https://vuejs.org/api/reactivity-advanced#toraw&quot;&gt;toRaw()&lt;/a&gt; for debugging purposes to dump the value.  

But, is there a Svelte equivalent?  

Yes, there is! 

It is called &lt;A href=&quot;https://svelte.dev/docs/svelte/$state#$state.snapshot&quot;&gt;$state.snapshot()&lt;/a&gt;.  I had to use this today when making a deep copy of an array with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone&quot;&gt;structuredClone()&lt;/a&gt;. I could not make a copy of the $state() proxy, because that is not supported by structuredClone(), so I had to use the snapshot to get the value.
				</description>
				
				<category>JavaScript</category>
				
				<category>vue</category>
				
				<category>Svelte</category>
				
				<category>Professional</category>
				
				<pubDate>Wed, 05 Nov 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/11/5/How-can-I-use-Vues-ToRaw-in-Svelte</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How do I fix &quot;Cannot apply unknown utility class&quot; with Svelte and Tailwind?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/10/29/How-do-I-fix-Cannot-apply-unknown-utility-class-with-SVelte-and-Tailwind</link>
				<description>
				
				I&apos;m working on a Svelte app that uses Tailwind.  I recently upgraded from Tailwind 3 to 4, and was getting this error:

&lt;blockquote&gt;
Cannot apply unknown utility class text-blue-200. Are you using CSS modules or similar and missing @reference? https://tailwindcss.com/docs/functions-and-directives#reference-directive
&lt;/blockquote&gt;

It took a while to find the source, but the app had a Svelte, whose CSS imported a CSS File, like this:

&lt;code&gt;
&lt;style&gt;
	@import &apos;../my-shared.css&apos;;
&lt;/style&gt;
&lt;/code&gt;

And that file used the &lt;a href=&quot;https://tailwindcss.com/docs/functions-and-directives#apply-directive&quot;&gt;@apply directive&lt;/a&gt;, like this:


&lt;code&gt;
.myStyle {
    @apply text-blue-200;
}
&lt;/code&gt;

The info from the error, about setting up references did not help.  

Off to my trusty AI tools, which told me the issue was a mix of Tailwind 3 and 4 configurations, and kept downleveling the project back to Tailwind 3, which left me in a really weird state.  

All I had to do was:

&lt;code&gt;
@import &apos;tailwindcss&apos;;
&lt;/code&gt;

At the top of the shared CSS file.  And all my problems went away.
				</description>
				
				<category>Tailwind</category>
				
				<category>Svelte</category>
				
				<pubDate>Wed, 29 Oct 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/10/29/How-do-I-fix-Cannot-apply-unknown-utility-class-with-SVelte-and-Tailwind</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>Why does Git keep changing my line endings?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/10/21/Why-does-Git-keep-changing-my-line-endings</link>
				<description>
				
				I have been working on projects with Git for over a decade.  

I&apos;m primarily a Windows user.  

This shouldn&apos;t be a problem.

For the first time ever, this year, I have been having a lot of trouble with line endings.  When I check files out, Git was converting all the line endings to windows based line endings (CRLF), even though the Repo has linux based line endings (LF).

Recommitting would change the line endings back to LF, so there was no issue for my mac based colleagues.

However, Docker was having a ton of issues w/ the line endings.  I&apos;d have to go manually change line endings inside IntelliJ for any of my docker images to build and work properly.  You can do this with an option in the bottom right of IntelliJ

&lt;img src=&quot;https://www.jeffryhouser.com/images/Screenshot 2025-10-03 124812.png&quot; /&gt;

And that fixed everything.  I&apos;ve been working Docker for over 5 years, so why have I never had these issues before?  I honestly have no idea, but I did find a fix.  There is a git property named &lt;a href=&quot;https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration&quot;&gt;autocrlf&lt;/a&gt; that helps this.

This property can have three values:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;false&lt;/strong&gt;: If set to false, no line ending conversions are needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;true&lt;/strong&gt;: If this property is set to true, then when you checkout, line endings are converted to crlf.  When you commit, line endings are set back to lf&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;input&lt;/strong&gt;: If the property is set to input, then crlf line endings are set to lf when you commit a file, but no conversion happens on checkout.&lt;/li&gt;
&lt;/ul&gt;

Even though I&apos;m a Windows user, I use IDEs that can support any line ending, and I do not need Windows specific line endings ever.

I ran this command to change the value globally, I suddenly started having less issues.

&lt;code&gt;
git config --global core.autocrlf input
&lt;/code&gt;

And the world is happy again.
				</description>
				
				<category>Git</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 21 Oct 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/10/21/Why-does-Git-keep-changing-my-line-endings</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How do I fix issues with Storybook, Svelte, and TypeScript Interfaces</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/10/14/How-do-I-fix-issues-with-Storybook-Svelte-and-TypeScript-Interfaces</link>
				<description>
				
				I&apos;m working on a Svelte Library, that imports a TypeScript library.  The TypeScript library has an interface, which is used in a Svelte component.  When using this setup in a Svelte application, everything worked great. 

However, I was trying to write some Storybook stories for the Svelte-Lib component, and was getting this error like this:

&lt;blockquote&gt;
The requested module &apos;/node_modules/.cache/storybook/longnumericalstring/vite/deps/my-typescript-lib; does not provide an export named of a &quot;MyInterface&quot;
&lt;/blockquote&gt;

My svelte component had a line like this:

&lt;code&gt;
&lt;script&gt;
  import { 
    MyClass1,
    MyClass2,
    MyInterface
  } from my-typescript-lib
&lt;/script&gt;
&lt;/code&gt;

First, I had complete control of the typescript library, and can guarantee that the interface was exported properly.

As I said earlier, Svelte loved this line and was able to process this as a Svelte component w/ no issues.  

But, for some reason, Storybook did not like that.  It broke all my storybook stories, even if I deleted the stories that referenced the component that used the interface.  

After some iteration, I found a new way to import the interface:

&lt;code&gt;
&lt;script&gt;
  import { 
    MyClass1,
    MyClass2,
  } from my-typescript-lib
  import type { 
    MyInterface
  } from my-typescript-lib
&lt;/script&gt;
&lt;/code&gt;

Instead of using a normal input, I had to add the &apos;type&apos; keyword to import the interface.  Then Storybook started working fine.  I didn&apos;t have to change how the library exported the interfaces, or the tsconfig, or the vite config.  I just had to change how the interface was imported.  

Svelte worked fine with change too.

Live and learn.  I hope this helps someone.
				</description>
				
				<category>Svelte</category>
				
				<category>Professional</category>
				
				<category>TypeScript</category>
				
				<category>Storybook</category>
				
				<pubDate>Tue, 14 Oct 2025 10:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/10/14/How-do-I-fix-issues-with-Storybook-Svelte-and-TypeScript-Interfaces</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How to Unit Test a Flowbite Svelte Modal with Vitest with Mock Timers</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/9/30/How-to-Unit-Test-a-Flowbite-Svelte-Modal-with-Vitest-with-Mock-Timers</link>
				<description>
				
				I&apos;ve been working on a Svelte project that integrates with an auth server.  If the user&apos;s session cookie expires, the app shows a modal to the user prompting them to login.  The modal persists until the user logs in.  &lt;a href=&quot;https://www.jeffryhouser.com/index.cfm/2025/9/16/How-to-Create-a-Modal-with-Svelte-and-Flowbite&quot;&gt;Creating this modal was easy&lt;/a&gt;.  Unit testing the modal was not  

If you&apos;re following along, I already &lt;a href=&quot;https://www.jeffryhouser.com/index.cfm/2025/9/23/How-to-Unit-Test-a-Flowbite-Svelte-Modal-with-Vitest-in-real-time&quot;&gt;showed you how to test the modal in real time&lt;/a&gt;.  This post will focus on testing the modal with fake timers. 

&lt;h2&gt;Write the Real Time Tests&lt;/h2&gt;

Let&apos;s write the tests!  Start with the describe block:

&lt;code&gt;
describe(&apos;MyModal.svelte&apos;, () =&gt; {
}
&lt;/code&gt;

Before jumping into the test, let&apos;s add an afterEach() block:


&lt;code&gt;
  afterEach(() =&gt; {
    vi.resetAllMocks();
    cleanup();
})
&lt;/code&gt;

The afterEach() block will reset all Mocks, and run a clean up script which scrubs the virtual DOM, so every test starts fresh.

Then, start your test:

&lt;code&gt;
it(&apos;should close modal after clicking &quot;Do Something&quot; with Fake Timers&apos;, async () =&gt; {
})
&lt;/code&gt;

First step in the test is to enable the fake timers: 

&lt;code&gt;
vi.useFakeTimers();
&lt;/code&gt;

This tells the vitest framework to enable spy&apos;s on things like setTimeout() and interval() methods, so we can manually control them.

Then, render the modal.  Pass in the isModalOpen property as true, so the modal is open by default:

&lt;code&gt;
const { getByText, queryByRole } = render(MyModal, { props: { isModalOpen: true } });
&lt;/code&gt;

I am pulling two functions out of the render object: getByText() and queryByRole().  First, we&apos;ll use getByText() to grab the modal&apos;s button:

&lt;code&gt;
const button = getByText(&apos;Do Something&apos;);
&lt;/code&gt;

And then we&apos;ll click the button:

&lt;code&gt;
await fireEvent.click(button);
&lt;/code&gt;

This should trigger the button handler inside the modal, which starts the interval countdown to close the modal.  Next, we have to increment the timer:

&lt;code&gt;
vi.advanceTimersByTime(1000);
&lt;/code&gt;

In practice, this should increment the timer, cause the interval function to execute, and close the modal.  Then we can use the queryByRole() method to get the Modal and validate whether it is in the document--or not:

&lt;code&gt;
const dialog = queryByRole(&apos;dialog&apos;);
await expect.element(dialog).not.toBeInTheDocument();
&lt;/code&gt;

Finally, reset the test framework to use real timers:

&lt;code&gt;
vi.useRealTimers();
&lt;/code&gt;

In practice this should work!  In reality, it doesn&apos;t yet.  You&apos;ll see two errors along the lines of this:

&lt;blockquote&gt;
Error: Matcher did not succeed in time.
Caused by: Error: expect(element).not.toBeInTheDocument() 
&lt;/blockquote&gt;

Along with a dump of the current dom, which shows the modal dialog still init:

&lt;img src=&quot;https://www.jeffryhouser.com/images/04FkeTimerUnitTestError.png&quot; width=&quot;600&quot;/&gt;

If you step through the code, you&apos;ll see that the final assertion fails, and despite efforts with ticking forward the timer; the close fade animation never executes, and the modal never disappears.  Even with a longer timeout, the test will still fail.

Spoiler alert: We solved this in the previous article about using real timers.  The same solutions apply here.  But I&apos;m going to repeat them just in case you didn&apos;t read the previous post.

After much experimentation, and stepping through code I discovered that the issue lies with the animation to remove the dialog.  We can solve that by spying on the animations.  I&apos;m going to create a method, which will mock the animate method, along with some of the modal methods:

&lt;code&gt;
const mockMissingProps = () =&gt; {
    Element.prototype.animate = vi.fn().mockImplementation(()=&gt; ({
        cancel: () =&gt; Promise.resolve(undefined)
    }))
    HTMLDialogElement.prototype.showModal = vi.fn().mockImplementation(() =&gt; {
        Promise.resolve();
    })
    HTMLDialogElement.prototype.close = vi.fn().mockImplementation(() =&gt; {
        Promise.resolve();
    })
}
&lt;/code&gt;

Add a call to this method as the first line in the unit test:

&lt;code&gt;
mockMissingProps();
&lt;/code&gt;


We need to do two more things. I dug out &lt;a href=&quot;https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/modal/Modal.svelte&quot;&gt;the actual Modal Code&lt;/a&gt; to discover it uses the Svelte fade transition.  We want to mock this so that the transition is immediate, with no delays or duration:

&lt;code&gt;
vi.mock(&apos;svelte/transition&apos;, () =&gt; ({
    fade: () =&gt; ({delay: 0, duration: 0})
}))
&lt;/code&gt;

We also want to extend the timeout for this test.  This is done by adding a property to the it() statement after the test function, sort of like this:

&lt;code&gt;
it(&apos;should close modal after clicking &quot;Do Something&quot; with fake Timers&apos;, async () =&gt; {
 // all the test code here
}), 5000)
&lt;/code&gt;

I added 5000 milliseconds, which gives us plenty of room for the modal to close, although I hate to forcefully add that much time to the test.    

Now, re run the tests:

&lt;img src=&quot;https://www.jeffryhouser.com/images/05FakeTimerUnitTestingSuccess.png&quot; width=&quot;600&quot; /&gt;

Success!  

&lt;h2&gt;Final Thoughts&lt;/h2&gt;
Like the real time tests, it took me quite a few days to discover everything that had to be mocked by this.  Even with the help of AI tools, such as Amazon Q and Github Copilot, I had to debug these errors on my own.  

Writing these posts were harder than I expected them to be. A few versions of some node library had ticked up since I worked on this at the day job.  Out of the box, Svelte tests did not run.  I &lt;a href=&quot;https://github.com/sveltejs/svelte/issues/16663&quot;&gt;filed a bug&lt;/a&gt; against Svelte because tests did not run with a new project setup.  I also had issues debugging unit tests through IntelliJ, and &lt;a href=&quot;https://youtrack.jetbrains.com/issue/IDEA-378481/Breakpoints-not-working-with-Svelte-Vitest-Unit-Tests-in-IntelliJ-Ultimate.&quot;&gt;filed a bug against IntelliJ&lt;/a&gt;.  Both have been verified, but as of yet unfixed.  

I also, surprisingly, discovered that tests were also sporadic, for example if I ran them  in headless mode, things worked better than if I ran them in a headful mode.  And the watch mode seemed to have less issues than running once.  Weird things I have not experienced in other UI frameworks.
 
That said, I hope these articles help someone.  Let me know!
				</description>
				
				<category>flowbite-svelte</category>
				
				<category>Svelte</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 30 Sep 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/9/30/How-to-Unit-Test-a-Flowbite-Svelte-Modal-with-Vitest-with-Mock-Timers</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How to Unit Test a Flowbite Svelte Modal with Vitest in real time</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/9/23/How-to-Unit-Test-a-Flowbite-Svelte-Modal-with-Vitest-in-real-time</link>
				<description>
				
				I&apos;ve been working on a Svelte project that integrates with an auth server.  If the user&apos;s session cookie expires, the app shows a modal to the user prompting them to login.  The modal persists until the user logs in.  &lt;a href=&quot;https://www.jeffryhouser.com/index.cfm/2025/9/16/How-to-Create-a-Modal-with-Svelte-and-Flowbite&quot;&gt;Creating this modal was easy&lt;/a&gt;.  Unit testing the modal was not.  

This article is all about writing unit tests for the modal using real timers.

&lt;h2&gt;Write some Tests&lt;/h2&gt;

Start with the describe block:
&lt;code&gt;
describe(&apos;MyModal.svelte&apos;, () =&gt; {
}
&lt;/code&gt;

Before jumping into the test, let&apos;s add an afterEach() block:

&lt;code&gt;
  afterEach(() =&gt; {
    vi.resetAllMocks();
    cleanup();
})
&lt;/code&gt;

The afterEach() block will reset all Mocks, and run a clean up script which scrubs the virtual DOM, so every test starts fresh.

Then, start your test:

&lt;code&gt;
it(&apos;should close modal after clicking &quot;Do Something&quot; with Real Timers&apos;, async () =&gt; {
})
&lt;/code&gt;

First step in the test is to render the modal.  We&apos;re going to render it as an open modal:

&lt;code&gt;
const { getByText, queryByRole } = render(MyModal, { props: { isModalOpen: true } });
&lt;/code&gt;

I am pulling two functions out of the render object, getByText(), and queryByRole().  

First, we&apos;ll use getByText() to grab the modal&apos;s button:

&lt;code&gt;
const button = getByText(&apos;Do Something&apos;);
&lt;/code&gt;

And then we&apos;ll click the button:

&lt;code&gt;
await fireEvent.click(button);
&lt;/code&gt;

This should trigger the button handler inside the modal, which starts the interval countdown to close the modal.  Next, we have to increment the timer:

&lt;code&gt;
await tick();
&lt;/code&gt;

This should close the Modal.  So, we can use the queryByRole() method to get the Modal and validate whether it is in the document--or not:

&lt;code&gt;
const dialog = queryByRole(&apos;dialog&apos;);
await expect.element(dialog).not.toBeInTheDocument();
&lt;/code&gt;

In practice this should work!  In reality, it doesn&apos;t yet.  You&apos;ll see an error like this:


&lt;blockquote&gt;
If this is a long-running test, pass a timeout value as the last argument or configure it globally with &quot;testTimeout&quot;.
&lt;/blockquote&gt;

Or a screenshot:

&lt;img src=&quot;https://www.jeffryhouser.com/images/02UnitTestError.png&quot; width=&quot;600&quot; /&gt;


If you step through the code, you&apos;ll see that the final assertion that checks whether or not the dialog is closed executes before the method inside the interval that toggles the close.  Even with a longer timeout, the test will still fail.

After much experimentation, and stepping through code I discovered that the issue lies with the animation to remove the dialog.  We can solve that by spying on the animations.  I&apos;m going to create a method, which will mock the animate method, along with some of the modal methods:

&lt;code&gt;
const mockMissingProps = () =&gt; {
    Element.prototype.animate = vi.fn().mockImplementation(()=&gt; ({
        cancel: () =&gt; Promise.resolve(undefined)
    }))
    HTMLDialogElement.prototype.showModal = vi.fn().mockImplementation(() =&gt; {
        Promise.resolve();
    })
    HTMLDialogElement.prototype.close = vi.fn().mockImplementation(() =&gt; {
        Promise.resolve();
    })
}
&lt;/code&gt;

Add a call to this method as the first line in the unit test:

&lt;code&gt;
mockMissingProps();
&lt;/code&gt;

We need to do one more thing. I dug out the &lt;a href=&quot;https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/modal/Modal.svelte&quot;&gt;actual Modal Code&lt;/a&gt; to discover it uses the Svelte fade transition.  We want to mock this so that the transition is immediate, with no delays or duration:

&lt;code&gt;
vi.mock(&apos;svelte/transition&apos;, () =&gt; ({
    fade: () =&gt; ({delay: 0, duration: 0})
}))
&lt;/code&gt;

This mock is added at the top of the test file, outside of the describe() statement. Now, re run the tests:

&lt;img src=&quot;https://www.jeffryhouser.com/images/03UnitTestSuccessRealTime.png&quot; width=&quot;600&quot;/&gt;

Success!  

&lt;h2&gt;Final Thoughts&lt;/h2&gt;

It took me four days and a lot of errors, even with the help of AI tools, to determine what mocks needed to be set up to get this test working.  

Along the way I also created a version of this test using fake timers.  That will be the topic of my next post.

Be sure to check out my Blog&apos;s repo &lt;a href=&quot;https://github.com/Reboog711/JeffryHouserBlogSamplesSource/tree/master/2025/SvelteModals&quot;&gt;for samples and follow along&lt;/a&gt;.
				</description>
				
				<category>vitest</category>
				
				<category>flowbite-svelte</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 23 Sep 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/9/23/How-to-Unit-Test-a-Flowbite-Svelte-Modal-with-Vitest-in-real-time</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How to Create a Modal with Svelte and Flowbite</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/9/16/How-to-Create-a-Modal-with-Svelte-and-Flowbite</link>
				<description>
				
				This took me a lot longer to figure out than I feel it should have, so as always, I thought I&apos;d write about it. 

I&apos;ve been working on a project where a Svelte application integrates with an Auth server.  If the app discovers that the user is logged out, it displays a modal prompting the user to login.  When the clicks the login button, a new tab is open, prompting the user through the login process, redirecting to the app, then closing the tab.  The modal checks for the user&apos;s JWT using an interval timer, and closes the tab once it is set, allowing the user to continue to use the application exactly where they left off.  

The system works great, and I&apos;ve built something similar in multiple UI frameworks.  But, writing unit tests for this in Svelte with Vitest turned out to be a much harder task than I expected.  I&apos;m gonna write a few blog posts on this.  this is the first one that will tell you how to create and use the modal.

&lt;h2&gt;The Setup&lt;/h2&gt;

First, create a Svelte app following &lt;A href=&quot;https://svelte.dev/docs/svelte/getting-started&quot;&gt;the instructions&lt;/a&gt;.  

Then &lt;a href=&quot;https://flowbite-svelte.com/docs/pages/introduction&quot;&gt;setup Flowbite-Svelte&lt;/a&gt;, a UI Component Library built for Tailwind and Svelte.

Or you can just check out this repo for &lt;a href=&quot;https://github.com/Reboog711/JeffryHouserBlogSamplesSource/tree/master/2025/SvelteModals&quot;&gt;these samples and follow along&lt;/a&gt;.

Specific steps are beyond the scope of this of this article.

&lt;h2&gt;Create the Modal&lt;/h2&gt;

Create a new Svelte component, MyModal.svelte.  First, import the Modal and Button from Flowbite Svelte:

&lt;code&gt;
&lt;script lang=&quot;ts&quot;&gt;
    import { Modal, Button } from &quot;flowbite-svelte&quot;;
&lt;/script&gt;
&lt;/code&gt;

Then, create the Modal template:

&lt;code&gt;
&lt;Modal title=&quot;My Modal&quot; bind:open={opened} size=&quot;md&quot; permanent&gt;
&lt;/Modal&gt;
&lt;/code&gt;

We gave the Modal a title and a size, which is a Tailwind convention defining this as a mid-size modal.  We also gave it the permanent property, which prevents the modal from being closed--although in my experience that does not quite work yet.  Then we bind to a property named opened.  This is how we determine whether or not the modal is displayed as part of the app, or completely hidden.

Back to TypeScript, create an input property to open or close the Modal: 

&lt;code&gt;
let { isModalOpen = false } = $props();
&lt;/code&gt;

Then create a open property, using the $state rune:

&lt;code&gt;
let opened = $state(isModalOpen);
&lt;/code&gt;

And finally, add an effect so that when the isModalOpen input prop changes, so does the opened state:

&lt;code&gt;
$effect(() =&gt; {
    opened = isModalOpen;
})
&lt;/code&gt;

Back to the HTML section of this component, let&apos;s populate the rest of the Modal.  Give it a body:

&lt;code&gt;
    &lt;p class=&quot;mb-4 text-gray-500 dark:text-gray-400&quot;&gt;
        This is a modal example using Flowbite-Svelte.
    &lt;/p&gt;
&lt;/code&gt;

This is just some HTML and Tailwind styles.

Then give it a footer:

&lt;code&gt;
    {#snippet footer()}
        &lt;div class=&quot;flex justify-end&quot;&gt;
            &lt;Button color=&quot;gray&quot; onclick={doSomething}&gt;Do Something&lt;/Button&gt;
        &lt;/div&gt;
    {/snippet}
&lt;/code&gt;

The footer includes the Flowbite Svelte button, when clicked runs the doSomething () method.  Create that in our TypeScript block:

&lt;code&gt;
const doSomething = () =&gt; {
    const timer = setInterval(() =&gt; {
        opened = false;
        clearInterval(timer);
    }, 1000)
}
&lt;/code&gt;

The click handler method sets an interval() and use that to close the modal.  In my real-world use case, the method would start the user authentication flow to reset the User&apos;s JWT and then do a cookie check inside the interval.  But, for the purposes of this sample, we&apos;re just gonna simulate that with an automatic delayed close.

&lt;h2&gt;Use the Modal&lt;/h2&gt;
Now, move to your default Svelte page, +page.svelte, and set up the Modal.  First, some imports in your TypeScript block:

&lt;code&gt;
&lt;script&gt;
  import { Button } from &quot;flowbite-svelte&quot;;
  import MyModal from &quot;$lib/MyModal.svelte&quot;;
&lt;/script&gt;
&lt;/code&gt;

Then in the HTML portion of the template set up a button that will show the Modal, and the actual Modal:

&lt;code&gt;
&lt;div class=&quot;p-8&quot;&gt;
  &lt;Button onclick={openModal}&gt;
    Show Modal
  &lt;/Button&gt;

  &lt;MyModal bind:isModalOpen={opened}&gt;&lt;/MyModal&gt;
&lt;/div&gt;
&lt;/code&gt;

We need to add two items to the TypeScript block, from this: The openModal() Click Handler, and the opened state value:

&lt;code&gt;
let opened = $state(false);

const openModal = () =&gt; {
  opened = !opened;
}
&lt;/code&gt;

Run the app, and you should see the Modal pop up, then close shortly thereafter:

&lt;img src=&quot;https://www.jeffryhouser.com/images/01OpeningModal.gif&quot; width=&quot;600&quot;&gt;


&lt;h2&gt;Final Thoughts&lt;/h2&gt;

Building the Modal was very easy, but when it came time to write unit tests that was a whole other story. In the next two parts of this article, I&apos;m going to show you how I wrote tests for this using both fake timers, and real timers.
				</description>
				
				<category>flowbite-svelte</category>
				
				<category>Svelte</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 16 Sep 2025 10:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/9/16/How-to-Create-a-Modal-with-Svelte-and-Flowbite</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>Why won&apos;t my new Svelte project run unit tests?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/9/2/Why-wont-my-new-Svelte-project-run-unit-tests</link>
				<description>
				
				I&apos;ve been doing a Svelte project for work, and therefore experimenting with it in my free time.  I noticed that after generating a brand new project, using the Svelte instructions, the unit test command does not work.  

I got so frustrated with this I opened up a &lt;a href=&quot;https://github.com/sveltejs/svelte/issues/16663&quot;&gt;bug report&lt;/a&gt;.

The error I see is something like this:

&lt;blockquote&gt;
12:55:39 PM [vite] (ssr) Error when evaluating SSR module /@fs/C:/Projects/blog/svelte-test-2/node_modules/@sveltejs/kit/src/runtime/server/index.js: transport was disconnected, cannot call &quot;fetchModule&quot;
&lt;/blockquote&gt;

It turns out the issue goes away if I tell the tests to use the headless browser.  Change the vite.config.ts to make this happen. Find code like this:

&lt;code&gt;
browser: {
	enabled: true,
	provider: &apos;playwright&apos;,
	instances: [{ browser: &apos;chromium&apos; }]
},
&lt;/code&gt;  

And change the instances section, to add the headless option:

&lt;code&gt;
browser: {
	enabled: true,
	provider: &apos;playwright&apos;,
	instances: [{ browser: &apos;chromium&apos;, headless: true }]
},
&lt;/code&gt;  

That solved the problem for me.  Although, sometimes I like to use the headful browser to debug unit tests, so this is not quite perfect.  But, at least I can keep moving forward with my own experiments.
				</description>
				
				<category>vitest</category>
				
				<category>Svelte</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 02 Sep 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/9/2/Why-wont-my-new-Svelte-project-run-unit-tests</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How is Hanging a Basement Shelf like Software Development?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/8/26/How-is-Hanging-a-Basement-Shelf-like-Software-Development</link>
				<description>
				
				I want to install a tool shelf in my basement.  I thought I&apos;d just wash the wall, drill some holes, hang the shelf and be done with it in a few hours.  It took 7 days! 
I will relate this to software development if you bear with  me.  

&lt;h2&gt;The Home Project&lt;/h2&gt;

First, I needed some supplies.  I needed a masonry drill bits for my drill, because I was pretty sure I&apos;d be drilling into some brick or concrete.  That&apos;s the first trip to Home Depot.

Then, I decided I didn&apos;t want to hang the shelf on a dirty wall, because there was a stain from a leak fixed long ago.  So, I wash the wall with some soapy water.  That helped, but I decided I should recoat this wall with some drylock paint and make it look snappy.  

I had a gallon and a half of the paint from way back when we moved in, but did my second trip to Home Depot for a masony paint brush and some painter&apos;s coveralls.  
My basement wall is not a solid wall; it is split into two sections.  The bottom half rocky and not smooth. The top half is brick, and there is a notable lip between the two.  I also picked up a 2x4, with the hopes I could drill the 2x4 into the wall, and the shelf into the 2x4.  Fewer holes in the brick foundation sounds like a good idea.

I lay down some painter&apos;s cloth, move a ton of stuff in the basement, and put on the painter coveralls.  Then I open the first Drylock Paint can.  It is all hardened and unusable.  Ugh! Then I open the unopened Drylock paint can.  The paint had separated, with the top being a clear liquid and the bottom being a white hard sludgy mess.  I thought I could have taken it back to Home Depot and had them remix it in one of their fancy paint mixers, however I was already suited up for painting.  So, I decided to mix it myself with a wooden painter stick and see if I could get it usable.  It was tedious, frustrating, and messy.  I spilled way too much of that clear stuff.  I ended up with a gloopy mix, and decided to give that a shot painting the wall.  I got about three quarters of the way through the wall before I ran out of paint.  The bottom half of the paint can was so hard, it broke my painter&apos;s stick trying to mix it.  Back to Home Depot for a new can of paint.  This new can had a significantly better texture, and I was able to finish painting the wall and even give it a second coat.  

I will tie this back to software, I promise!

Unfortunately, the screws that came with the shelf were deeper than the board&apos;s depth.  I decided to drill through the wood into brick, for all 18 holes required by the shelf.  I put the shelf on the wood, marked the hole spots with a marker, removed the shelf, and started drilling.  This was slow going because the drill bit kept overheating, so I could only do 3-4 holes per session.  

Once done, things didn&apos;t like up perfectly, and I was stymied.  I messed up one hole significantly, and I think two others are just slightly off.  I decided to take a different tact.  I took the board outside and put it on sawhorses, and redrilled--really widened--the holes so the shelf would fit.  Then back to the wall, and some redrilling into the brick.  I think I can make it work.

Now I had 18 drilled holes, but red dust all over the place, and wanted to clean that up.  I removed the board, did some more cleanup, and put down another coat of paint.  Then I hung up the board and painted the board.  After that dried, I started hanging the shelves.  All screws fit except one.  I took a smaller masonry drill bit and drilled through the shelf screw hole, the painted wood board, and into the brick.  That solved it.  I now had a hanging shelf.

My one day task took a full week and I had three trips to Home Depot.  Why is this like building software?

&lt;h2&gt;Back to Tech&lt;/h2&gt;

Most of the software tasks I have taken on in the past year have gone as smoothly as hanging this shelf.  As an experienced engineer, we should be able to think about code 10 steps ahead and make sure we do not back our project into a corner.  Sometimes each story has some refactoring built in. Sometimes there is more discovery and learning than expected, especially when dealing with new technology. 

Let&apos;s drill into an example (no pun intended).  I am building an integration library for Svelte with an internal auth microservice.  Someone had previously build a POC, but my job was to move it into a library so it would be &quot;drop in&quot; easy to real applications.  The team thought it&apos;d be a lift and shift from the prototype to the lib.  However, a more experienced Svelte developer in the company strongly recommended we rework to make use SvelteKit, the server-side rendering piece of Svelte. 

In UI code, we often store user session data as a global value, possibly injecting it where it is needed.  However, on the server side it would be considered an anti-pattern to persist session data associated with an individual user in memory.  This required significant refactoring for the code, for every time it referenced the user object; the user object had to be created with the current session data.  

Also, a Typescript lib that this ticket relied upon only output, CommonJS files, and not modern ECMAScript (EMS) files.  That was causing some build issues which needed to be fixed. 

Oh, and no one had set up a unit testing framework on the Svelte lib, so I had to do that too.  

My 1 week ticket took close to a month.   

&lt;h2&gt;Final Thoughts&lt;/h2&gt;

What seemed like a simple task, complicated itself as I started to peel back layers. Sometimes you estimate tasks wrong, and sometimes there is work not immediately obvious when you evaluate a project.  But, we plow through it and adjust as we need to in order to bring business value out of the software we build.

Here is my Shelf:

&lt;img src=&quot;https://www.jeffryhouser.com/images/20250809_084742.jpg&quot; width=&quot;500&quot; height=&quot;500&quot; /&gt;
				</description>
				
				<category>Software Development</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 26 Aug 2025 11:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/8/26/How-is-Hanging-a-Basement-Shelf-like-Software-Development</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How do I solve &quot; Failed to resolve import &quot;$app/paths&quot; with Svelte and Vitest</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/7/17/How-do-I-solve--Failed-to-resolve-import-apppaths-with-Svelte-and-Vitest</link>
				<description>
				
				I have been working on Svelte library, and I just started configuring and writing unit tests for it.  Vitest was set up and configured, but when running tests I Was getting an error like this:


&lt;code&gt;
 FAIL  src/tests/my-class.spec.ts [ src/tests/my-class.spec.ts ]
Error: Failed to resolve import &quot;$app/paths&quot; from &quot;src/lib/my-class.ts&quot;. Does the file exist?
  Plugin: vite:import-analysis
  File: C:/Dev/src/lib/my-class.ts:5:21
  1  |  import { base } from &quot;$app/paths&quot;;
&lt;/code&gt;

The &lt;a href=&quot;https://svelte.dev/docs/kit/$app-paths&quot;&gt;$app/paths import is part of SvelteKit&lt;/a&gt;, a server side rendering tool often used with the Svelte UI Framework.  

My problem came from the vitest.config.ts file. I was setting up some plugins like this:


&lt;code&gt;
import { svelte } from &apos;@sveltejs/vite-plugin-svelte&apos;;
import {svelteTesting} from &quot;@testing-library/svelte/vite&quot;;

export default defineConfig({
  plugins: [svelte(), svelteTesting()],
// other configs
})
&lt;/code&gt;

I needed to replace the svelte() plugin with a svelteKit plugin.  Super easy fix:

&lt;code&gt;
import { sveltekit } from &apos;@sveltejs/kit/vite&apos;;
import {svelteTesting} from &quot;@testing-library/svelte/vite&quot;;

export default defineConfig({
  plugins: [sveltekit(), svelteTesting()],
// other configs
})
&lt;/code&gt;

Then my code started running properly.  

Six out of the seven Copilot generated tests failed, but that is perhaps a story for another day.
				</description>
				
				<category>vitest</category>
				
				<category>Svelte</category>
				
				<category>Professional</category>
				
				<pubDate>Thu, 17 Jul 2025 09:52:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/7/17/How-do-I-solve--Failed-to-resolve-import-apppaths-with-Svelte-and-Vitest</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>What is the Difference between public and src/assets in a Vite project?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/6/17/What-is-the-Difference-between-public-and-srcassets-in-a-Vite-project</link>
				<description>
				
				I&apos;m doing some research for an article I&apos;m writing about building VueJS libraries.  Creating a default VueJS application with Vite creates a public directory in the root directory--which includes a vite.svg file.  And it creates an assets directory under the src, which contains a vue.svg file.  Both are referenced in the main App.vue. 

The directory structure looks like this:

&lt;img src=&quot;https://www.jeffryhouser.com/images/08FileSTructure.png&quot; height=&quot;400&quot; /&gt;

And you can see both files in there.

When I was at work, I saw this and didn&apos;t think much about it.  But, writing an article, I wanted to better understand why there were two separate directories for what seemed like the exact same thing.

Off to the Internet I went.  Eventually, I found &lt;a href=&quot;https://cli.vuejs.org/guide/html-and-static-assets.html#static-assets-handling&quot;&gt;this page in the Vue docs&lt;/a&gt;.

The public folder is for files that are copied, verbatim, in the build.  They are accessible via the root directory, but not processed in any way.  Examples of this might be a robots.txt file, or universal image.  

Files in the assets directory, on the other hand, will be processed by the Vite build scripts.  It is expected that these files will be imported, and used, by application components.

I do not understand why the vue.svg is put in the assets folder instead of the public folder for this template, though.  Based on my current understanding, it seems it would be better off in public.  

I hope this helped someone.
				</description>
				
				<category>Vite</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 17 Jun 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/6/17/What-is-the-Difference-between-public-and-srcassets-in-a-Vite-project</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			
			<item>
				<title>How do I nextTick() in Vitest without Vue?</title>
				<link>https://www.jeffryhouser.com/index.cfm/2025/6/10/How-do-I-nextTick-in-Vitest-without-Vue</link>
				<description>
				
				I wrote a bunch of tests on a &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue project&lt;/a&gt; using &lt;a href=&quot;https://vitest.dev/&quot;&gt;Vitest&lt;/a&gt;, and had pretty good success with it.  Quite a few tests deal with asynchronous code, such as a service call that returns a promise.  

&lt;h2&gt;Tick&apos;s in Vue&lt;/h2&gt;

To test this, I would mock the Promise and then force it to resolve an answer you have control over.  Something, conceptually, like this:

&lt;code&gt;
import { myService} from &quot;./my-service&quot; 
import { nextTick } from &quot;vue&quot; 

it(&apos;Some Test&apos;, () =&gt; {
 let myResolve : Function;

 axios.post = vi.fun(() =&gt; {
    return new Promise((resolve) =&gt; {
      myResolve = resolve;
   })
 });
 
 service.myFunctionalThatCallsAxiosPost().then((result) =&gt; {
   // assertions here 
 });
 myResolve(&apos;some result value&apos;);
 nextTick();
})
&lt;/code&gt;

This should be considered psuedo-code, but is very similar to what I might write in the real world.  First, we mock axios&apos;s post() function, and save the Promise&apos;s resolve function into a variable.  

 Then we call a function that will make the axios post, and return the promise, and we listen for the results. 
 
 The nextTick() function is what forces the promise to actually resolve.  This is all under the hood stuff about mock timers, and how testing works with the JavaScript event loop.

 Throw some assertions in the result handler, and you&apos;re good to go.

&lt;h2&gt;Node&apos;s process.nextTick()&lt;/h2&gt;

Fast forward to today, and I&apos;m using Vitest on a TypeScript only project.  But, you&apos;ll notice that the `nextTick()` in the previous section is actually a Vue import.  What is one to do? 

Well, I googled it and got a lot of suggestions that I use processTick. first you&apos;ll want to Google it.  And the Google AI results told me to use &lt;a href=&quot;https://nodejs.org/api/process.html#processnexttickcallback-args&quot;&gt;process.nextTick&lt;/a&gt;.

Modified code like this:

&lt;code&gt;
import { myService} from &quot;./my-service&quot; 

it(&apos;Some Test&apos;, async () =&gt; {
 let myResolve : Function;

 axios.post = vi.fun(() =&gt; {
    return new Promise((resolve) =&gt; {
      myResolve = resolve;
   })
 });
 
 service.myFunctionalThatCallsAxiosPost().then((result) =&gt; {
   // assertions here 
 });
 myResolve(&apos;some result value&apos;);
 await process.nextTick();
})
&lt;/code&gt;

The code block is almost identical, except for the removal of Vue&apos;s nextTick() function, being replaced w/ NodeJS nextTick() function.

This worked great when I was writing and testing individual tests, however once I ran the test suite, I had all sorts of issues.  It turns out the process.nextTick() function was resolving promises after the test suite ran, not as part of an individual tests.  As such, the test would sporadically fail, because different tests would change different values, properties, and cause different behavior inside the class I was testing.  

The behavior surprised me a bit, since I tested it with and without await on the test function and async on the tick.  It just didn&apos;t seem to wait for the actual tick.

This didn&apos;t work for me.

&lt;h2&gt;Flush Promises&lt;/h2&gt;  

The solution was to use an npm library named &lt;a href=&quot;https://www.npmjs.com/package/flush-promises&quot;&gt;Flush-promises&lt;/a&gt;. 

&lt;code&gt;
import { myService} from &quot;./my-service&quot; 
import { flushPromises } from &quot;flush-promioses

it(&apos;Some Test&apos;, async () =&gt; {
 let myResolve : Function;

 axios.post = vi.fun(() =&gt; {
    return new Promise((resolve) =&gt; {
      myResolve = resolve;
   })
 });
 
 service.myFunctionalThatCallsAxiosPost().then((result) =&gt; {
   // assertions here 
 });
 myResolve(&apos;some result value&apos;);
 await flushPromises();
})
&lt;/code&gt;

This was the magic sauce I needed.  Import the new library, and run it after you resolve your promise.  Now the promises resolve as part of the test, before any future tests can change values causing unexpected test behavior, and assertions to fail.  


&lt;h2&gt;Final Thoughts&lt;/h2&gt;

Over the past year I&apos;ve written unit tests in Vitest, Karma/Jasmine, and Jest.  I was under the impression that Jest was the preferred method in the industry, however Vitest has really grown on me.
				</description>
				
				<category>vitest</category>
				
				<category>Professional</category>
				
				<pubDate>Tue, 10 Jun 2025 09:00:00 -0700</pubDate>
				<guid>https://www.jeffryhouser.com/index.cfm/2025/6/10/How-do-I-nextTick-in-Vitest-without-Vue</guid>
				
                <author>jhblog@farcryfly.com (Jeffry Houser)</author>
				
			</item>
			</channel></rss>