'Jest: mock out Expo releaseChannels
Been trying trying out a lot of things but without luck. I'm trying to test out my configuration for different release channels in expo.
My latest attempt looks like this:
import * as Updates from 'expo-updates'
import { Platform } from 'react-native'
export const BUILD_PROFILES = ['local', 'development', 'preview', 'production'] as const
type BuildProfile = typeof BUILD_PROFILES[number]
export default function Configuration() {
type EnvironmentVariables = {
API_URL: string
}
console.log({ releaseChannel: Updates.releaseChannel })
switch (Updates.releaseChannel as BuildProfile) {
case 'local': {
const env: EnvironmentVariables = {
API_URL: Platform.OS === 'android' ? 'http://10.0.2.2:3001' : 'http://localhost:3001',
}
return env
}
case 'development': {
const env: EnvironmentVariables = {
API_URL: 'http://test.company.com',
}
return env
}
default: {
const env: EnvironmentVariables = {
API_URL: 'http://test.company.com',
}
return env
}
}
}
import { Platform } from 'react-native'
import * as CONFIG from '.'
const easJson = require('~/eas.json')
describe('Config.ts', () => {
afterEach(() => {
jest.restoreAllMocks()
})
it('has all the build profiles in eas["build"]', () => {
Object.keys(easJson.build).forEach((key) => {
expect(CONFIG.BUILD_PROFILES).toContain(key)
})
})
describe('Development', () => {
describe('Locally (on the MacBook)', () => {
beforeEach(() => {
jest.spyOn('expo-updates', 'releaseChannel', 'get').mockReturnValue('local')
})
describe('iPhone Simulator', () => {
beforeEach(() => {
jest.mock('react-native/Libraries/Utilities/Platform', () => ({
OS: 'ios',
select: () => null,
}))
Platform.OS = 'ios'
})
it('has API_URL with localhost', () => {
expect(CONFIG.default().API_URL).toEqual('http://localhost:3001')
})
})
describe('Android Emulator', () => {
beforeEach(() => {
jest.mock('react-native/Libraries/Utilities/Platform', () => ({
OS: 'android',
select: () => null,
}))
Platform.OS = 'android'
})
it('has API_URL WITHOUT localhost', () => {
expect(CONFIG.default().API_URL).toEqual('http://10.0.2.2:3001')
})
})
describe('web browser', () => {
beforeEach(() => {
jest.mock('react-native/Libraries/Utilities/Platform', () => ({
OS: 'web',
select: () => null,
}))
Platform.OS = 'web'
})
it('has API_URL with localhost', () => {
expect(CONFIG.default().API_URL).toEqual('http://localhost:3001')
})
})
})
})
})
But it seems to still just do
console.log
{ releaseChannel: 'default' }
My jest configuration looks like:
/** @type {import('@jest/types').Config.InitialOptions} */
module.exports = {
preset: 'jest-expo',
rootDir: '../../',
setupFilesAfterEnv: ['./test/jest/setup.js'], // Setup life-cycle for jest tests.
automock: false, // it means it will not run the __mocks__ folder by default (so we have to manually mock it in each test or in the setup.js file)
clearMocks: true, // https://marek-rozmus.medium.com/jest-mock-and-spy-mockclear-vs-mockreset-vs-mockrestore-f52395581950
moduleDirectories: ['node_modules'],
modulePathIgnorePatterns: ['<rootDir>/.fttemplates/*'],
moduleNameMapper: {
// scape out non-supported NodeJS files
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/test/jest/assetsTransformer.js',
'\\.(css|scss|less)$': '<rootDir>/test/jest/assetsTransformer.js',
},
transformIgnorePatterns: [
// transpiling non-transpiled packages
'node_modules/(?!(jest-)?react-native|@react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base)',
],
collectCoverage: true,
collectCoverageFrom: [
'**/*.{js,jsx,ts,tsx}',
// Don't include the following
'!.*.{js,jsx,ts,tsx}',
'!**/coverage/**',
'!**/node_modules/**',
'!**/.fttemplates/**',
'!**/babel.config.{js,ts}',
'!**/jest.config.{js,ts}',
'!**/jest.setup.{js,ts}',
'!**/prettier.config.{js,ts}',
],
}
Update
found out that putting it at the top does mock it out
jest.mock('expo-updates', () => ({
releaseChannel: 'local',
}))
describe('Config.ts', () => {
afterEach(() => {
jest.restoreAllMocks()
})
...
but then I'm not able to change it from 'local' to 'development' for my other test cases
Solution 1:[1]
Finally figured it out:
/* eslint-disable import/namespace */
import * as Updates from 'expo-updates'
import { Platform } from 'react-native'
import * as CONFIG from '.'
const easJson = require('~/eas.json')
jest.mock('expo-updates', () => ({
__esModule: true,
releaseChannel: null,
}))
describe('Config.ts', () => {
afterEach(() => {
jest.restoreAllMocks()
})
it('has all the build profiles in eas["build"]', () => {
Object.keys(easJson.build).forEach((key) => {
expect(CONFIG.BUILD_PROFILES).toContain(key)
})
})
describe('Development', () => {
describe('Locally (on the MacBook)', () => {
beforeEach(() => {
// @ts-ignore
Updates.releaseChannel = 'local'
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Norfeldt |
