cut over to vitest: drop jest config, deps, setup, update CI
This commit is contained in:
@@ -100,7 +100,7 @@ jobs:
|
||||
run: pnpm intl:build
|
||||
- name: Run tests
|
||||
run: |
|
||||
NODE_ENV=test pnpm test --forceExit --shard=${{ matrix.shard }}/${{ strategy.job-total }}
|
||||
pnpm test --shard=${{ matrix.shard }}/${{ strategy.job-total }} --outputFile.junit=junit-${{ matrix.shard }}.xml
|
||||
# Aggregates the sharded test results into a single stable check name so branch
|
||||
# protection can require "Run tests" regardless of how many shards run.
|
||||
# The result is asserted in `run` (not `if`) so a malformed expression can
|
||||
|
||||
@@ -63,6 +63,7 @@ Gemfile.lock
|
||||
# Testing
|
||||
coverage/
|
||||
junit.xml
|
||||
junit-*.xml
|
||||
artifacts
|
||||
|
||||
# Web bundle outputs
|
||||
|
||||
@@ -29,7 +29,7 @@ pnpm ios # Run on iOS
|
||||
|
||||
# Testing & Quality
|
||||
# IMPORTANT: Always use these pnpm scripts, never call the underlying tools directly
|
||||
pnpm test # Run Jest tests
|
||||
pnpm test # Run Vitest tests
|
||||
pnpm lint # Run ESLint
|
||||
pnpm typecheck # Run TypeScript type checking
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import React, {type ReactNode} from 'react'
|
||||
import {FlatList, Modal, ScrollView, TextInput, View} from 'react-native'
|
||||
|
||||
const BottomSheetModalContext = React.createContext(null)
|
||||
BottomSheetModalContext.displayName = 'BottomSheetModalContext'
|
||||
|
||||
const BottomSheetModalProvider = (props: any) => {
|
||||
return <BottomSheetModalContext.Provider {...props} value={{}} />
|
||||
}
|
||||
class BottomSheet extends React.Component<{
|
||||
onClose?: () => void
|
||||
children?: ReactNode
|
||||
}> {
|
||||
snapToIndex() {}
|
||||
snapToPosition() {}
|
||||
expand() {}
|
||||
collapse() {}
|
||||
close() {
|
||||
this.props.onClose?.()
|
||||
}
|
||||
forceClose() {}
|
||||
|
||||
render() {
|
||||
return <View>{this.props.children}</View>
|
||||
}
|
||||
}
|
||||
const BottomSheetModal = (props: any) => <Modal {...props} />
|
||||
|
||||
const BottomSheetBackdrop = (props: any) => <View {...props} />
|
||||
const BottomSheetHandle = (props: any) => <View {...props} />
|
||||
const BottomSheetFooter = (props: any) => <View {...props} />
|
||||
const BottomSheetScrollView = (props: any) => <ScrollView {...props} />
|
||||
const BottomSheetFlatList = (props: any) => <FlatList {...props} />
|
||||
const BottomSheetTextInput = (props: any) => <TextInput {...props} />
|
||||
|
||||
const useBottomSheet = jest.fn()
|
||||
const useBottomSheetModal = jest.fn()
|
||||
const useBottomSheetSpringConfigs = jest.fn()
|
||||
const useBottomSheetTimingConfigs = jest.fn()
|
||||
const useBottomSheetInternal = jest.fn()
|
||||
const useBottomSheetDynamicSnapPoints = jest.fn()
|
||||
|
||||
export {useBottomSheet}
|
||||
export {useBottomSheetModal}
|
||||
export {useBottomSheetSpringConfigs}
|
||||
export {useBottomSheetTimingConfigs}
|
||||
export {useBottomSheetInternal}
|
||||
export {useBottomSheetDynamicSnapPoints}
|
||||
|
||||
export {
|
||||
BottomSheetBackdrop,
|
||||
BottomSheetFlatList,
|
||||
BottomSheetFooter,
|
||||
BottomSheetHandle,
|
||||
BottomSheetModal,
|
||||
BottomSheetModalProvider,
|
||||
BottomSheetScrollView,
|
||||
BottomSheetTextInput,
|
||||
}
|
||||
|
||||
export default BottomSheet
|
||||
@@ -1 +0,0 @@
|
||||
export const Slider = {}
|
||||
@@ -1 +0,0 @@
|
||||
export const getLocales = jest.fn().mockResolvedValue([])
|
||||
@@ -1,3 +0,0 @@
|
||||
export const CID = jest.fn().mockImplementation(() => {
|
||||
return {}
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
export const from = jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
digest: jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve('')
|
||||
}),
|
||||
}
|
||||
})
|
||||
Vendored
-67
@@ -1,67 +0,0 @@
|
||||
// @flow
|
||||
|
||||
// https://github.com/FormidableLabs/react-native-svg-mock
|
||||
import React from 'react'
|
||||
|
||||
const createComponent = function (name) {
|
||||
return class extends React.Component {
|
||||
// overwrite the displayName, since this is a class created dynamically
|
||||
static displayName = name
|
||||
|
||||
render() {
|
||||
return React.createElement(name, this.props, this.props.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mock all react-native-svg exports
|
||||
// from https://github.com/magicismight/react-native-svg/blob/master/index.js
|
||||
const Svg = createComponent('Svg')
|
||||
const Circle = createComponent('Circle')
|
||||
const Ellipse = createComponent('Ellipse')
|
||||
const G = createComponent('G')
|
||||
const Text = createComponent('Text')
|
||||
const TextPath = createComponent('TextPath')
|
||||
const TSpan = createComponent('TSpan')
|
||||
const Path = createComponent('Path')
|
||||
const Polygon = createComponent('Polygon')
|
||||
const Polyline = createComponent('Polyline')
|
||||
const Line = createComponent('Line')
|
||||
const Rect = createComponent('Rect')
|
||||
const Use = createComponent('Use')
|
||||
const Image = createComponent('Image')
|
||||
const Symbol = createComponent('Symbol')
|
||||
const Defs = createComponent('Defs')
|
||||
const LinearGradient = createComponent('LinearGradient')
|
||||
const RadialGradient = createComponent('RadialGradient')
|
||||
const Stop = createComponent('Stop')
|
||||
const ClipPath = createComponent('ClipPath')
|
||||
const Pattern = createComponent('Pattern')
|
||||
const Mask = createComponent('Mask')
|
||||
|
||||
export {
|
||||
Svg,
|
||||
Circle,
|
||||
Ellipse,
|
||||
G,
|
||||
Text,
|
||||
TextPath,
|
||||
TSpan,
|
||||
Path,
|
||||
Polygon,
|
||||
Polyline,
|
||||
Line,
|
||||
Rect,
|
||||
Use,
|
||||
Image,
|
||||
Symbol,
|
||||
Defs,
|
||||
LinearGradient,
|
||||
RadialGradient,
|
||||
Stop,
|
||||
ClipPath,
|
||||
Pattern,
|
||||
Mask,
|
||||
}
|
||||
|
||||
export default Svg
|
||||
@@ -1,3 +0,0 @@
|
||||
jest.mock('sentry-expo', () => ({
|
||||
init: () => jest.fn(),
|
||||
}))
|
||||
@@ -197,8 +197,6 @@ export default defineConfig(
|
||||
'error',
|
||||
{
|
||||
whitelist: [
|
||||
// test files only
|
||||
'@jest/globals',
|
||||
// we only use a really simple util from this, and we know it will be present
|
||||
'expo-modules-core',
|
||||
// this is a dep for @atproto/api, but we absolutely need them in sync, so just
|
||||
@@ -320,7 +318,6 @@ export default defineConfig(
|
||||
files: ['**/__tests__/**/*.{js,jsx,ts,tsx}', '**/*.test.{js,jsx,ts,tsx}'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.jest,
|
||||
...globals.vitest,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/* global jest */
|
||||
import 'react-native-gesture-handler/jestSetup'
|
||||
|
||||
import {configure} from '@testing-library/react-native'
|
||||
|
||||
configure({asyncUtilTimeout: 20000})
|
||||
|
||||
jest.mock('@react-native-async-storage/async-storage', () =>
|
||||
require('@react-native-async-storage/async-storage/jest/async-storage-mock'),
|
||||
)
|
||||
jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter', () => {
|
||||
// eslint-disable-next-line import-x/no-nodejs-modules
|
||||
const {EventEmitter} = require('events')
|
||||
return {
|
||||
__esModule: true,
|
||||
default: EventEmitter,
|
||||
}
|
||||
})
|
||||
|
||||
jest.mock('react-native-safe-area-context', () => {
|
||||
const inset = {top: 0, right: 0, bottom: 0, left: 0}
|
||||
return {
|
||||
SafeAreaProvider: jest.fn().mockImplementation(({children}) => children),
|
||||
SafeAreaConsumer: jest
|
||||
.fn()
|
||||
.mockImplementation(({children}) => children(inset)),
|
||||
useSafeAreaInsets: jest.fn().mockImplementation(() => inset),
|
||||
}
|
||||
})
|
||||
|
||||
jest.mock('expo-file-system/legacy', () => ({
|
||||
getInfoAsync: jest.fn().mockResolvedValue({exists: true, size: 100}),
|
||||
deleteAsync: jest.fn(),
|
||||
moveAsync: jest.fn().mockResolvedValue(undefined),
|
||||
createDownloadResumable: jest.fn(),
|
||||
}))
|
||||
|
||||
jest.mock('expo-image-manipulator', () => ({
|
||||
manipulateAsync: jest.fn().mockResolvedValue({
|
||||
uri: 'file://resized-image',
|
||||
}),
|
||||
SaveFormat: {
|
||||
JPEG: 'jpeg',
|
||||
WEBP: 'webp',
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock('expo-camera', () => ({
|
||||
Camera: {
|
||||
useCameraPermissions: jest.fn(() => [true]),
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock('expo-media-library', () => ({
|
||||
__esModule: true, // this property makes it work
|
||||
default: jest.fn(),
|
||||
usePermissions: jest.fn(() => [true]),
|
||||
}))
|
||||
|
||||
jest.mock('@bsky.app/expo-guess-language', () => ({
|
||||
guessLanguageSync: jest
|
||||
.fn()
|
||||
.mockReturnValue([{language: 'en', confidence: 1}]),
|
||||
guessLanguageAsync: jest
|
||||
.fn()
|
||||
.mockResolvedValue([{language: 'en', confidence: 1}]),
|
||||
}))
|
||||
|
||||
jest.mock('sentry-expo', () => ({
|
||||
init: () => jest.fn(),
|
||||
Native: {
|
||||
ReactNativeTracing: jest.fn().mockImplementation(() => ({
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
})),
|
||||
ReactNavigationInstrumentation: jest.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock('crypto', () => ({}))
|
||||
|
||||
jest.mock('expo-application', () => ({
|
||||
nativeApplicationVersion: '1.0.0',
|
||||
nativeBuildVersion: '1',
|
||||
}))
|
||||
|
||||
jest.mock('expo-modules-core', () => ({
|
||||
requireNativeModule: jest.fn().mockImplementation(moduleName => {
|
||||
if (moduleName === 'ExpoPlatformInfo') {
|
||||
return {
|
||||
getIsReducedMotionEnabled: () => false,
|
||||
}
|
||||
}
|
||||
if (moduleName === 'BottomSheet') {
|
||||
return {
|
||||
dismissAll: () => {},
|
||||
}
|
||||
}
|
||||
}),
|
||||
requireNativeViewManager: jest.fn().mockImplementation(_ => {
|
||||
return () => null
|
||||
}),
|
||||
createPermissionHook: () => () => [true],
|
||||
}))
|
||||
|
||||
jest.mock('expo-localization', () => ({
|
||||
getLocales: () => [],
|
||||
}))
|
||||
+4
-61
@@ -55,13 +55,10 @@
|
||||
"build-embed": "cd bskyembed && pnpm build && pnpm build-snippet && cd .. && node ./scripts/post-embed-build.js",
|
||||
"start": "expo start --dev-client",
|
||||
"start:prod": "expo start --dev-client --no-dev --minify",
|
||||
"test": "NODE_ENV=test jest --forceExit --testTimeout=20000 --bail",
|
||||
"test-watch": "NODE_ENV=test jest --watchAll",
|
||||
"test-ci": "NODE_ENV=test jest --ci --forceExit --reporters=default --reporters=jest-junit",
|
||||
"test-coverage": "NODE_ENV=test jest --coverage",
|
||||
"vitest": "vitest run",
|
||||
"vitest-watch": "vitest",
|
||||
"vitest-coverage": "vitest run --coverage",
|
||||
"test": "vitest run",
|
||||
"test-watch": "vitest",
|
||||
"test-ci": "vitest run",
|
||||
"test-coverage": "vitest run --coverage",
|
||||
"lint": "eslint --cache --quiet src modules",
|
||||
"lint-native": "swiftlint ./modules && ktlint ./modules",
|
||||
"lint-native:fix": "swiftlint --fix ./modules && ktlint --format ./modules",
|
||||
@@ -266,8 +263,6 @@
|
||||
"@react-native/babel-preset": "0.81.5",
|
||||
"@react-native/typescript-config": "^0.81.5",
|
||||
"@sentry/webpack-plugin": "^3.2.2",
|
||||
"@testing-library/react-native": "^13.2.0",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/lodash.chunk": "^4.2.7",
|
||||
"@types/lodash.debounce": "^4.0.7",
|
||||
"@types/lodash.shuffle": "^4.2.7",
|
||||
@@ -277,7 +272,6 @@
|
||||
"@typescript/native-preview": "^7.0.0-dev.20260428.1",
|
||||
"@vitejs/plugin-react": "^6.0.3",
|
||||
"@vitest/coverage-v8": "^4.1.9",
|
||||
"babel-jest": "^29.7.0",
|
||||
"babel-plugin-module-resolver": "^5.0.2",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
||||
"babel-preset-expo": "~54.0.10",
|
||||
@@ -296,9 +290,6 @@
|
||||
"globals": "^17.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"is-ci": "^3.0.1",
|
||||
"jest": "^29.7.0",
|
||||
"jest-expo": "~54.0.17",
|
||||
"jest-junit": "^16.0.0",
|
||||
"lint-staged": "^13.2.3",
|
||||
"prettier": "^3.8.3",
|
||||
"react-native-dotenv": "^3.4.11",
|
||||
@@ -311,54 +302,6 @@
|
||||
"vitest": "^4.1.9",
|
||||
"webpack-bundle-analyzer": "^4.10.1"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "jest-expo/ios",
|
||||
"setupFilesAfterEnv": [
|
||||
"./jest/jestSetup.js"
|
||||
],
|
||||
"moduleFileExtensions": [
|
||||
"ts",
|
||||
"tsx",
|
||||
"js",
|
||||
"jsx",
|
||||
"json",
|
||||
"node"
|
||||
],
|
||||
"transform": {
|
||||
"\\.[jt]sx?$": "babel-jest"
|
||||
},
|
||||
"moduleNameMapper": {
|
||||
"^multiformats$": "<rootDir>/node_modules/multiformats/dist/src/index.js",
|
||||
"^multiformats/cid$": "<rootDir>/node_modules/multiformats/dist/src/cid.js",
|
||||
"^multiformats/bases/base32$": "<rootDir>/node_modules/multiformats/dist/src/bases/base32.js",
|
||||
"^multiformats/hashes/digest$": "<rootDir>/node_modules/multiformats/dist/src/hashes/digest.js",
|
||||
"^multiformats/hashes/sha2$": "<rootDir>/node_modules/multiformats/dist/src/hashes/sha2.js",
|
||||
"^uint8arrays/from-string$": "<rootDir>/node_modules/uint8arrays/dist/src/from-string.js",
|
||||
"^uint8arrays/to-string$": "<rootDir>/node_modules/uint8arrays/dist/src/to-string.js",
|
||||
"^unicode-segmenter/grapheme$": "<rootDir>/node_modules/unicode-segmenter/grapheme.cjs",
|
||||
"^await-lock$": "<rootDir>/node_modules/await-lock/build/AwaitLock.js"
|
||||
},
|
||||
"transformIgnorePatterns": [
|
||||
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|nanoid|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|normalize-url|react-native-svg|@sentry/.*|sentry-expo|bcp-47-match|@atproto/.*|multiformats|uint8arrays|@ipld/.*|cborg|await-lock)"
|
||||
],
|
||||
"modulePathIgnorePatterns": [
|
||||
"__tests__/.*/__mocks__",
|
||||
"__e2e__/.*",
|
||||
"bskylink/.*"
|
||||
],
|
||||
"coveragePathIgnorePatterns": [
|
||||
"<rootDir>/node_modules/",
|
||||
"<rootDir>/src/platform",
|
||||
"<rootDir>/src/third-party",
|
||||
"<rootDir>/src/view/com/util",
|
||||
"<rootDir>/src/state/lib",
|
||||
"<rootDir>/__tests__/test-utils.js"
|
||||
],
|
||||
"reporters": [
|
||||
"default",
|
||||
"jest-junit"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
|
||||
Generated
+50
-1022
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -1,21 +1,21 @@
|
||||
import {AtpAgent} from '@atproto/api'
|
||||
import {describe, expect, it, jest} from '@jest/globals'
|
||||
import {vi} from 'vitest'
|
||||
|
||||
import {agentToSessionAccountOrThrow} from '../agent'
|
||||
import {type Action, getInitialState, reducer, type State} from '../reducer'
|
||||
|
||||
jest.mock('jwt-decode', () => ({
|
||||
vi.mock('jwt-decode', () => ({
|
||||
jwtDecode(_token: string) {
|
||||
return {}
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock('../../birthdate')
|
||||
jest.mock('../../../ageAssurance/data')
|
||||
jest.mock('../../../ageAssurance/state', () => ({
|
||||
vi.mock('../../birthdate')
|
||||
vi.mock('../../../ageAssurance/data')
|
||||
vi.mock('../../../ageAssurance/state', () => ({
|
||||
unsafeGetAndComputeAgeAssurance: () => ({state: {}}),
|
||||
}))
|
||||
jest.mock('#/lib/notifications/notifications', () => ({
|
||||
vi.mock('#/lib/notifications/notifications', () => ({
|
||||
unregisterPushToken(_agents: AtpAgent[]) {
|
||||
return Promise.resolve()
|
||||
},
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
"jsx": "react-jsx",
|
||||
"module": "esnext",
|
||||
"lib": ["dom", "esnext"],
|
||||
"types": ["node", "jest"],
|
||||
"types": ["node", "vitest/globals"],
|
||||
"paths": {
|
||||
"#/*": ["./src/*"],
|
||||
"crypto": ["./src/platform/crypto.ts"],
|
||||
|
||||
Reference in New Issue
Block a user