https://serverless-stack.com/ logo
#help
Title
# help
r

Ross Gerbasi

03/08/2022, 1:18 AM
Hey @thdxr I notice after upgrading to 0.67.0 we lost jest, ts-jest and babel from the dependencies. So when i run
npm run test
it can't find jest. Is this expected? If so do we need to install jest and configure TS for it ourselves now?
t

thdxr

03/08/2022, 1:20 AM
we stopped using babel for our tests a while ago and I removed it since it was unused
r

Ross Gerbasi

03/08/2022, 1:21 AM
So right now when i do
npm run test
i am seeing unable to find jest. So after installing jest it is not able to deal with TS files. So do we also need to configure babel for our local tests?
t

thdxr

03/08/2022, 1:21 AM
is that using the sst test command or directly calling jest?
r

Ross Gerbasi

03/08/2022, 1:21 AM
sst test
t

thdxr

03/08/2022, 1:22 AM
ah the direction we're going in we're likely going to remove that command and recommend calling jest directly. Either way I think this breakage wasn't intentional let me figure out what happened
r

Ross Gerbasi

03/08/2022, 1:22 AM
Had another dev pull this down from git, and do a clean
npm i
same situation
oh ok, so we should just install and configure jest oursevles and swap the script to probably ts-jest
t

thdxr

03/08/2022, 1:24 AM
I don't really recommend ts-jest on its own since it's super slow. Are you using esm?
r

Ross Gerbasi

03/08/2022, 1:24 AM
no not yet, still on common js. we can go the babel route then if you think thats better?
t

thdxr

03/08/2022, 1:26 AM
If you're not using esm then the recommend jest setup I'd suggest is using this: https://github.com/folke/esbuild-runner
way faster than both babel and ts-jest
sst test actually uses it already, so you shouldn't need the babel stuff
r

Ross Gerbasi

03/08/2022, 1:29 AM
I think its choking on our custom TS paths now. we need to configure esbuild runner to use them
t

thdxr

03/08/2022, 1:29 AM
the aliases?
r

Ross Gerbasi

03/08/2022, 1:30 AM
yeah path aliases
t

thdxr

03/08/2022, 1:30 AM
this was what sst test was using
Copy code
const config = {
    collectCoverageFrom: ["./**/*.{js,jsx,ts,tsx}"],
    testEnvironment: "node",
    testMatch: [
      "<rootDir>/**/__tests__/**/*.{js,jsx,ts,tsx}",
      "<rootDir>/**/*.{spec,test}.{js,jsx,ts,tsx}",
    ],
    transform: {
      "\\.ts$": "esbuild-runner/jest",
      "\\.js$": "esbuild-runner/jest",
    },
    transformIgnorePatterns: [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$",
    ],
  };
r

Ross Gerbasi

03/08/2022, 1:35 AM
ok, so i think we got them running however with SST magic we lost our dotenv environmental variables haha
so we need to add that back ourselves as well
t

thdxr

03/08/2022, 1:37 AM
you could continue to use the sst jest command in that case, I'm adding the deps back to it
r

Ross Gerbasi

03/08/2022, 1:37 AM
its ok, we are swapping :)
What was the logic for envs for tests. I am guessing it loaded .env and then .env.test
I am actually not opposed to it being ripped out and letting users add their own test runners. just wanna make sure we get it right. maybe some documentation as well..
t

thdxr

03/08/2022, 1:39 AM
search apths are
Copy code
.env.test, .env.local, .env
we're trying to get rid of the need for .env as well for tests
r

Ross Gerbasi

03/08/2022, 1:42 AM
oh really? we are using envs to specific SSM names, so we will need them in tests as well
t

thdxr

03/08/2022, 1:48 AM
I have a nice testing setup I need to publish
but I have unit, integration, whatever tests working without any fiddling with env vars
r

Ross Gerbasi

03/08/2022, 1:49 AM
oh nice, well that sounds useful haha ours are just jest tests but they pull in ENVs and reads the
outputs.json
to add them as ENVs as well. all in globalSetup. pretty basic stuff.
I think we got everything running again with esbuild-runner. However having a problem with node-fetch 3.0 now. As it is ESM only and causing the test to break. need to see if we can fix that or may need to downgrade since we are not all in on esm
t

thdxr

03/08/2022, 1:51 AM
I had to do something to node fetch at some point, think I pinned to 2.x
r

Ross Gerbasi

03/08/2022, 1:51 AM
yeah, i upgraded to 3 in my project, and its working fine, its just the tests that cant resolve it sadly.
Wasnt a huge deal to upgrade to 3, but I did like that
response.json()
for is typed unknown instead of any. But it wont be the worst if I need to downgrade. Just seems a bit annoying as its all working except the tests. So much transpiling to just get down to the javascript haha
FYI for anyone else coming across this, we just downgraded to node-fetch@2, and used esbuild-runner with jest and dotenv ourselves.
r

Ross Coundon

03/08/2022, 7:50 AM
Do either of you use any static classes in TypeScript? I just tried switching over to esbuild-runner after seeing this thread and some of the code it’s dealing with uses static classes. Running the jest tests I see this message each time a static method of a class is called
Copy code
TypeError: Cannot read property 'someFunc' of undefined
I imagine there some esbuild config I need to pass in
esbuild-runner.config.js
just haven’t worked out what it is yet
I’d thought
Copy code
esbuild: {
    target: 'esnext',
  },
might do it but no
r

Ross Gerbasi

03/08/2022, 7:59 AM
I actually got stuck in a similar area, trying to configure the esbuild runner. Then I realized I can just gave up on all this haha. Since SST removed jest and all the baggage that came with I swapped over to vitest, it all just worked OOTB. I was able to switch over to ESM for my functions and everything played well together.
r

Ross Coundon

03/08/2022, 8:00 AM
Interesting, I’ve seen a lot of buzz about vitest, I’ll check it out
r

Ross Gerbasi

03/08/2022, 8:04 AM
If it helps here is some random info haha This is what I swapped my test script to
Copy code
"test": "vitest run -r test"
then I just added a
vitest.config.ts
in my test folder. added a
globalSetup.ts
and put it in the config also a few custom paths I use (
~
, etc) using vite's resolve:alias syntax. If going ESM and typescript I ended up using
Copy code
"module": "ES2022",
    "moduleResolution": "Node",
So that VSCode was cool with top level await and JSON modules. Last step was adding
Copy code
bundle: {
      format: 'esm',
    },
to the defaultFunctionProps for my stack.
r

Ross Coundon

03/08/2022, 8:05 AM
Great, thank you - do you mind sharing your vitest.config.ts?
r

Ross Gerbasi

03/08/2022, 8:06 AM
Copy code
import path from 'path'
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    globalSetup: path.resolve(__dirname, 'globalSetup.ts'),
  },
  resolve: {
    alias: {
      '~': path.resolve(__dirname, '..', 'src'),
      '~schema': path.resolve(__dirname, '..', 'schema'),
      '~test': path.resolve(__dirname),
    },
  },
})
alias's are very much optional, just something we got going with so its stuck around.
r

Ross Coundon

03/08/2022, 8:07 AM
Perfect, thank you!
t

thdxr

03/08/2022, 1:32 PM
Woah maybe we should do vitest instead
I thought it wouldn't work with backend initially
r

Ross Coundon

03/08/2022, 2:23 PM
I can’t get it to play nicely with some stuff like sharp at the moment. Vitest has the ‘not production ready’ caveat on it at the moment too. I do like the look of it though, very fast
r

Ross Gerbasi

03/08/2022, 2:24 PM
@thdxr I mean I am all for all things vite 🙂 heck I bet even the live lambda/esbuild guts could be swapped out for vite , but that might be a bit intense. I guess the question is, is SST trying to be opinionated or open? Documenting different test setups is also a fine option. However maybe you all are looking to provide a more guided experience. @Ross Coundon issues with Sharp the image processing library?
t

thdxr

03/08/2022, 2:25 PM
I've been trying to get SST to do less, which means less will work out of the box but we can supplement with templates
and I've wanted to get a vitest setup going
r

Ross Gerbasi

03/08/2022, 2:27 PM
I am guessing some folks could get pretty opinionated about as test setup, so maybe it is best to take that out of SST and move to docs or maybe another command?
sst add jest
or some kind of magic
r

Ross Coundon

03/08/2022, 2:27 PM
Yeah, it was throwing an error regarding it not being able to register the sharp module.
Copy code
Something went wrong installing the "sharp" module Module did not self-register
I tried marking it as external but same issue. Also had a weird V8 error which I haven’t tracked down
Copy code
FATAL ERROR: v8::FromJust Maybe value is Nothing
t

thdxr

03/08/2022, 2:30 PM
@Ross Gerbasi yeah exactly, we've been thinking about either 1. Making template generation interactive or 2. Have addon commands like you suggested (even for things like vscode config)
r

Ross Gerbasi

03/08/2022, 2:34 PM
@thdxr that sounds cool, could even allow for people to add plugins this way. Write our own stuff to manipulate CF or the build chain.
t

thdxr

03/08/2022, 2:34 PM
yeah plugins would be cool
r

Ross Gerbasi

03/08/2022, 2:35 PM
@Ross Coundon so i just threw this together quick in my project. Maybe its to simplistic for your setup?
Copy code
import { describe, expect, it } from 'vitest'
import sharp from 'sharp'

describe('Sharp Test', () => {
  it('Should test sharp', async () => {
    const { info } = await sharp({
      create: {
        width: 24,
        height: 48,
        channels: 4,
        background: { r: 255, g: 0, b: 0, alpha: 0.5 },
      },
    })
      .rotate(90)
      .toBuffer({ resolveWithObject: true })

    expect(info.width).toBe(48)
    expect(info.height).toBe(24)
  })
})
I am on Node v14.18.3 FYI
r

Ross Coundon

03/08/2022, 2:37 PM
Interesting. thank you. We’re not doing much more than that, just a resize. The sharp module is loaded from within a file containing a class with static functions and it’s used by one of those functions. Did you do anything special in the vitest config ?
Same node version here
r

Ross Gerbasi

03/08/2022, 2:38 PM
Not to my setup, just added that test.. lemme try it in a class
Alright that passed also
Sharp.class.ts
Copy code
import sharp from 'sharp'

export default class SharpThing {
  static async rotateThatThing() {
    const { info } = await sharp({
      create: {
        width: 24,
        height: 48,
        channels: 4,
        background: { r: 255, g: 0, b: 0, alpha: 0.5 },
      },
    })
      .rotate(90)
      .toBuffer({ resolveWithObject: true })

    return info
  }
}
sharp.test.ts
Copy code
import { describe, expect, it } from 'vitest'
import SharpThing from '~/Sharp.class'

describe('Sharp Test', () => {
  it('Should test sharp', async () => {
    const info = await SharpThing.rotateThatThing()

    expect(info.width).toBe(48)
    expect(info.height).toBe(24)
  })
})
~/
for me is just
src/
"sharp": "^0.30.2",
in my package json as well, maybe if that's a difference?
r

Ross Coundon

03/08/2022, 3:05 PM
I have
"sharp": "0.29.3",
so that’s a difference, waiting on an update to this to upgrade (submitted a PR a while back but no feedback) - anyway, this means sharp is a devDependency for us
Upgrading locally to see if that helps
r

Ross Gerbasi

03/08/2022, 3:06 PM
ooo i see you're stuck on a layer upgrading. Dependencies of dependencies are the worst
r

Ross Coundon

03/08/2022, 3:08 PM
Indeed. Still hates me - wonder if it’s a Mac thing. What’s your machine?
r

Ross Gerbasi

03/08/2022, 3:09 PM
oh interesting. I am on windows, but I am using WSL2 so its ubuntu
r

Ross Coundon

03/08/2022, 3:35 PM
Yeah, I’ve tried a rebuild and an install with
Copy code
--ignore-scripts=false
I’ve also deleted node_modules and package-lock.json but still the same, very odd indeed.