diff --git a/.gitignore b/.gitignore
index 81570d99..5f596190 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,6 @@ buck-out/
# Ruby / CocoaPods
/ios/Pods/
/vendor/bundle/
+
+# Testing
+coverage/
\ No newline at end of file
diff --git a/__mocks__/@react-native-camera-roll/camera-roll.js b/__mocks__/@react-native-camera-roll/camera-roll.js
new file mode 100644
index 00000000..43f40208
--- /dev/null
+++ b/__mocks__/@react-native-camera-roll/camera-roll.js
@@ -0,0 +1,3 @@
+export default {
+ CameraRoll: jest.fn(),
+}
diff --git a/__mocks__/async-storage.js b/__mocks__/async-storage.js
deleted file mode 100644
index 32e39bc7..00000000
--- a/__mocks__/async-storage.js
+++ /dev/null
@@ -1 +0,0 @@
-export default from '@react-native-async-storage/async-storage/jest/async-storage-mock'
diff --git a/__mocks__/react-native-image-crop-picker.js b/__mocks__/react-native-image-crop-picker.js
new file mode 100644
index 00000000..9f2298a7
--- /dev/null
+++ b/__mocks__/react-native-image-crop-picker.js
@@ -0,0 +1,3 @@
+export default {
+ openPicker: jest.fn().mockImplementation(() => Promise.resolve(result)),
+}
diff --git a/__mocks__/rn-fetch-blob.js b/__mocks__/rn-fetch-blob.js
new file mode 100644
index 00000000..dedfbdf8
--- /dev/null
+++ b/__mocks__/rn-fetch-blob.js
@@ -0,0 +1,10 @@
+jest.mock('rn-fetch-blob', () => {
+ return {
+ __esModule: true,
+ default: {
+ fs: {
+ unlink: jest.fn(),
+ },
+ },
+ }
+})
diff --git a/__tests__/App-test.tsx b/__tests__/App-test.tsx
deleted file mode 100644
index db34ec61..00000000
--- a/__tests__/App-test.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-// /**
-// * @format
-// */
-
-// import 'react-native'
-// import React from 'react'
-// import App from '../src/App'
-
-// // Note: test renderer must be required after react-native.
-// import renderer from 'react-test-renderer'
-
-// it('renders correctly', () => {
-// renderer.act(() => {
-// renderer.create()
-// })
-// })
diff --git a/__tests__/lib/download.test.ts b/__tests__/lib/download.test.ts
new file mode 100644
index 00000000..d90e8c89
--- /dev/null
+++ b/__tests__/lib/download.test.ts
@@ -0,0 +1,93 @@
+import {downloadAndResize, DownloadAndResizeOpts} from '../../src/lib/download'
+import ImageResizer from '@bam.tech/react-native-image-resizer'
+import RNFetchBlob from 'rn-fetch-blob'
+
+jest.mock('rn-fetch-blob', () => ({
+ config: jest.fn().mockReturnThis(),
+ cancel: jest.fn(),
+ fetch: jest.fn(),
+}))
+jest.mock('@bam.tech/react-native-image-resizer', () => ({
+ createResizedImage: jest.fn(),
+}))
+
+describe('downloadAndResize', () => {
+ const errorSpy = jest.spyOn(global.console, 'error')
+
+ const mockResizedImage = {
+ path: jest.fn().mockReturnValue('file://resized-image.jpg'),
+ }
+
+ beforeEach(() => {
+ jest.clearAllMocks()
+
+ const mockedCreateResizedImage =
+ ImageResizer.createResizedImage as jest.Mock
+ mockedCreateResizedImage.mockResolvedValue(mockResizedImage)
+ })
+
+ it('should return resized image for valid URI and options', async () => {
+ const mockedFetch = RNFetchBlob.fetch as jest.Mock
+ mockedFetch.mockResolvedValueOnce({
+ path: jest.fn().mockReturnValue('file://downloaded-image.jpg'),
+ flush: jest.fn(),
+ })
+
+ const opts: DownloadAndResizeOpts = {
+ uri: 'https://example.com/image.jpg',
+ width: 100,
+ height: 100,
+ mode: 'cover',
+ timeout: 10000,
+ }
+
+ const result = await downloadAndResize(opts)
+ expect(result).toEqual(mockResizedImage)
+ expect(RNFetchBlob.config).toHaveBeenCalledWith({
+ fileCache: true,
+ appendExt: 'jpeg',
+ })
+ expect(RNFetchBlob.fetch).toHaveBeenCalledWith(
+ 'GET',
+ 'https://example.com/image.jpg',
+ )
+ expect(ImageResizer.createResizedImage).toHaveBeenCalledWith(
+ 'file://downloaded-image.jpg',
+ 100,
+ 100,
+ 'JPEG',
+ 0.7,
+ undefined,
+ undefined,
+ undefined,
+ {mode: 'cover'},
+ )
+ })
+
+ it('should return undefined for invalid URI', async () => {
+ const opts: DownloadAndResizeOpts = {
+ uri: 'invalid-uri',
+ width: 100,
+ height: 100,
+ mode: 'cover',
+ timeout: 10000,
+ }
+
+ const result = await downloadAndResize(opts)
+ expect(errorSpy).toHaveBeenCalled()
+ expect(result).toBeUndefined()
+ })
+
+ it('should return undefined for unsupported file type', async () => {
+ const opts: DownloadAndResizeOpts = {
+ uri: 'https://example.com/image.bmp',
+ width: 100,
+ height: 100,
+ mode: 'cover',
+ timeout: 10000,
+ }
+
+ const result = await downloadAndResize(opts)
+ expect(result).toBeUndefined()
+ })
+})
diff --git a/__tests__/lib/errors.test.ts b/__tests__/lib/errors.test.ts
new file mode 100644
index 00000000..b9549e6d
--- /dev/null
+++ b/__tests__/lib/errors.test.ts
@@ -0,0 +1,19 @@
+import {isNetworkError} from '../../src/lib/errors'
+
+describe('isNetworkError', () => {
+ const inputs = [
+ 'TypeError: Network request failed',
+ 'Uncaught TypeError: Cannot read property x of undefined',
+ 'Uncaught RangeError',
+ 'Error: Aborted',
+ ]
+ const outputs = [true, false, false, true]
+
+ it('correctly distinguishes network errors', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const input = inputs[i]
+ const result = isNetworkError(input)
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
diff --git a/__tests__/link-meta-utils.ts b/__tests__/lib/link-meta.test.ts
similarity index 78%
rename from __tests__/link-meta-utils.ts
rename to __tests__/lib/link-meta.test.ts
index f6cf8b4f..5df5153e 100644
--- a/__tests__/link-meta-utils.ts
+++ b/__tests__/lib/link-meta.test.ts
@@ -1,4 +1,4 @@
-import {LikelyType, getLinkMeta} from '../src/lib/link-meta'
+import {LikelyType, getLinkMeta, getLikelyType} from '../../src/lib/link-meta'
const exampleComHtml = `
@@ -57,7 +57,9 @@ describe('getLinkMeta', () => {
'https://example.com/image.png',
'https://example.com/video.avi',
'https://example.com/audio.ogg',
+ 'https://example.com/text.txt',
'https://example.com/javascript.js',
+ 'https://bsky.app/index.html',
]
const outputs = [
{
@@ -94,15 +96,29 @@ describe('getLinkMeta', () => {
likelyType: LikelyType.Audio,
url: 'https://example.com/audio.ogg',
},
+ {
+ likelyType: LikelyType.Text,
+ url: 'https://example.com/text.txt',
+ },
{
likelyType: LikelyType.Other,
url: 'https://example.com/javascript.js',
},
+ {
+ likelyType: LikelyType.AtpData,
+ url: '/index.html',
+ title: 'Not found',
+ },
+ {
+ likelyType: LikelyType.Other,
+ url: '',
+ title: '',
+ },
]
it('correctly handles a set of text inputs', async () => {
for (let i = 0; i < inputs.length; i++) {
global.fetch = jest.fn().mockImplementationOnce(() => {
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, _reject) => {
resolve({
ok: true,
status: 200,
@@ -116,3 +132,15 @@ describe('getLinkMeta', () => {
}
})
})
+
+describe('getLikelyType', () => {
+ it('correctly handles non-parsed url', async () => {
+ const output = await getLikelyType('https://example.com')
+ expect(output).toEqual(LikelyType.HTML)
+ })
+
+ it('handles non-string urls without crashing', async () => {
+ const output = await getLikelyType('123')
+ expect(output).toEqual(LikelyType.Other)
+ })
+})
diff --git a/__tests__/lib/numbers.test.ts b/__tests__/lib/numbers.test.ts
new file mode 100644
index 00000000..be92d6c0
--- /dev/null
+++ b/__tests__/lib/numbers.test.ts
@@ -0,0 +1,24 @@
+import {clamp} from '../../src/lib/numbers'
+
+describe('clamp', () => {
+ const inputs: [number, number, number][] = [
+ [100, 0, 200],
+ [100, 0, 100],
+ [0, 0, 100],
+ [100, 0, -1],
+ [4, 1, 1],
+ [100, -100, 0],
+ [400, 100, -100],
+ [70, -1, 1],
+ [Infinity, Infinity, Infinity],
+ ]
+ const outputs = [100, 100, 0, -1, 1, 0, -100, 1, Infinity]
+
+ it('correctly clamps any given number and range', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const input = inputs[i]
+ const result = clamp(...input)
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
diff --git a/__tests__/string-utils.ts b/__tests__/lib/string.test.ts
similarity index 67%
rename from __tests__/string-utils.ts
rename to __tests__/lib/string.test.ts
index a1bd59fe..d8a56b36 100644
--- a/__tests__/string-utils.ts
+++ b/__tests__/lib/string.test.ts
@@ -2,7 +2,17 @@ import {
extractEntities,
detectLinkables,
extractHtmlMeta,
-} from '../src/lib/strings'
+ pluralize,
+ makeRecordUri,
+ ago,
+ makeValidHandle,
+ createFullHandle,
+ enforceLen,
+ cleanError,
+ toNiceDomain,
+ toShortUrl,
+ toShareUrl,
+} from '../../src/lib/strings'
describe('extractEntities', () => {
const knownHandles = new Set(['handle.com', 'full123.test-of-chars'])
@@ -317,3 +327,206 @@ describe('extractHtmlMeta', () => {
}
})
})
+
+describe('pluralize', () => {
+ const inputs: [number, string, string?][] = [
+ [1, 'follower'],
+ [1, 'member'],
+ [100, 'post'],
+ [1000, 'repost'],
+ [10000, 'upvote'],
+ [100000, 'other'],
+ [2, 'man', 'men'],
+ ]
+ const outputs = [
+ 'follower',
+ 'member',
+ 'posts',
+ 'reposts',
+ 'upvotes',
+ 'others',
+ 'men',
+ ]
+
+ it('correctly pluralizes a set of words', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const input = inputs[i]
+ const output = pluralize(...input)
+ expect(output).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('makeRecordUri', () => {
+ const inputs: [string, string, string][] = [
+ ['alice.test', 'app.bsky.feed.post', '3jk7x4irgv52r'],
+ ]
+ const outputs = ['at://alice.test/app.bsky.feed.post/3jk7x4irgv52r']
+
+ it('correctly builds a record URI', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const input = inputs[i]
+ const result = makeRecordUri(...input)
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('ago', () => {
+ const inputs = [
+ 1671461038,
+ '04 Dec 1995 00:12:00 GMT',
+ new Date(),
+ new Date().setMinutes(new Date().getMinutes() - 10),
+ new Date().setHours(new Date().getHours() - 1),
+ new Date().setDate(new Date().getDate() - 1),
+ new Date().setMonth(new Date().getMonth() - 1),
+ ]
+ const outputs = [
+ new Date(1671461038).toLocaleDateString(),
+ new Date('04 Dec 1995 00:12:00 GMT').toLocaleDateString(),
+ '0s',
+ '10m',
+ '1h',
+ '1d',
+ '1mo',
+ ]
+
+ it('correctly calculates how much time passed, in a string', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const result = ago(inputs[i])
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('makeValidHandle', () => {
+ const inputs = [
+ 'test-handle-123',
+ 'test!"#$%&/()=?_',
+ 'this-handle-should-be-too-big',
+ ]
+ const outputs = ['test-handle-123', 'test', 'this-handle-should-b']
+
+ it('correctly parses and corrects handles', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const result = makeValidHandle(inputs[i])
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('createFullHandle', () => {
+ const inputs: [string, string][] = [
+ ['test-handle-123', 'test'],
+ ['.test.handle', 'test.test.'],
+ ['test.handle.', '.test.test'],
+ ]
+ const outputs = [
+ 'test-handle-123.test',
+ '.test.handle.test.test.',
+ 'test.handle.test.test',
+ ]
+
+ it('correctly parses and corrects handles', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const input = inputs[i]
+ const result = createFullHandle(...input)
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('enforceLen', () => {
+ const inputs: [string, number][] = [
+ ['Hello World!', 5],
+ ['Hello World!', 20],
+ ['', 5],
+ ]
+ const outputs = ['Hello', 'Hello World!', '']
+
+ it('correctly enforces defined length on a given string', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const input = inputs[i]
+ const result = enforceLen(...input)
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('cleanError', () => {
+ const inputs = [
+ 'TypeError: Network request failed',
+ 'Error: Aborted',
+ 'Error: TypeError "x" is not a function',
+ 'Error: SyntaxError unexpected token "export"',
+ 'Some other error',
+ ]
+ const outputs = [
+ 'Unable to connect. Please check your internet connection and try again.',
+ 'Unable to connect. Please check your internet connection and try again.',
+ 'TypeError "x" is not a function',
+ 'SyntaxError unexpected token "export"',
+ 'Some other error',
+ ]
+
+ it('removes extra content from error message', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const result = cleanError(inputs[i])
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('toNiceDomain', () => {
+ const inputs = [
+ 'https://example.com/index.html',
+ 'https://bsky.app',
+ 'https://bsky.social',
+ '#123123123',
+ ]
+ const outputs = ['example.com', 'bsky.app', 'Bluesky Social', '#123123123']
+
+ it("displays the url's host in a easily readable manner", () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const result = toNiceDomain(inputs[i])
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('toShortUrl', () => {
+ const inputs = [
+ 'https://bsky.app',
+ 'https://bsky.app/3jk7x4irgv52r',
+ 'https://bsky.app/3jk7x4irgv52r2313y182h9',
+ ]
+ const outputs = [
+ 'bsky.app',
+ 'bsky.app/3jk7x4irgv52r',
+ 'bsky.app/3jk7x4irgv52r2313y...',
+ ]
+
+ it('shortens the url', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const result = toShortUrl(inputs[i])
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
+
+describe('toShareUrl', () => {
+ const inputs = ['https://bsky.app', '/3jk7x4irgv52r', 'item/test/123']
+ const outputs = [
+ 'https://bsky.app',
+ 'https://bsky.app/3jk7x4irgv52r',
+ 'https://bsky.app/item/test/123',
+ ]
+
+ it('appends https, when not present', () => {
+ for (let i = 0; i < inputs.length; i++) {
+ const result = toShareUrl(inputs[i])
+ expect(result).toEqual(outputs[i])
+ }
+ })
+})
diff --git a/__tests__/view/screens/Contacts.test.tsx b/__tests__/view/screens/Contacts.test.tsx
new file mode 100644
index 00000000..8dc4e56e
--- /dev/null
+++ b/__tests__/view/screens/Contacts.test.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import {Contacts} from '../../../src/view/screens/Contacts'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Contacts', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {},
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/Home.test.tsx b/__tests__/view/screens/Home.test.tsx
new file mode 100644
index 00000000..353d4ea5
--- /dev/null
+++ b/__tests__/view/screens/Home.test.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import {Home} from '../../../src/view/screens/Home'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Home', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {},
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/Login.test.tsx b/__tests__/view/screens/Login.test.tsx
new file mode 100644
index 00000000..d9faf08a
--- /dev/null
+++ b/__tests__/view/screens/Login.test.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+import {Login} from '../../../src/view/screens/Login'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Login', () => {
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/NotFound.test.tsx b/__tests__/view/screens/NotFound.test.tsx
new file mode 100644
index 00000000..047d309e
--- /dev/null
+++ b/__tests__/view/screens/NotFound.test.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+import {NotFound} from '../../../src/view/screens/NotFound'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('NotFound', () => {
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/Notifications.test.tsx b/__tests__/view/screens/Notifications.test.tsx
new file mode 100644
index 00000000..2c5e32cd
--- /dev/null
+++ b/__tests__/view/screens/Notifications.test.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import {Notifications} from '../../../src/view/screens/Notifications'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Notifications', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {},
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/Onboard.test.tsx b/__tests__/view/screens/Onboard.test.tsx
new file mode 100644
index 00000000..69d6f0a7
--- /dev/null
+++ b/__tests__/view/screens/Onboard.test.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+import {Onboard} from '../../../src/view/screens/Onboard'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Onboard', () => {
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/PostDownvotedBy.test.tsx b/__tests__/view/screens/PostDownvotedBy.test.tsx
new file mode 100644
index 00000000..8c4119b4
--- /dev/null
+++ b/__tests__/view/screens/PostDownvotedBy.test.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import {PostDownvotedBy} from '../../../src/view/screens/PostDownvotedBy'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('PostDownvotedBy', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ rkey: '123123123',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/PostRepostedBy.test.tsx b/__tests__/view/screens/PostRepostedBy.test.tsx
new file mode 100644
index 00000000..00122435
--- /dev/null
+++ b/__tests__/view/screens/PostRepostedBy.test.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import {PostRepostedBy} from '../../../src/view/screens/PostRepostedBy'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('PostRepostedBy', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ rkey: '123123123',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/PostThread.test.tsx b/__tests__/view/screens/PostThread.test.tsx
new file mode 100644
index 00000000..87164ed7
--- /dev/null
+++ b/__tests__/view/screens/PostThread.test.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import {PostThread} from '../../../src/view/screens/PostThread'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('PostThread', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ rkey: '123123123',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/PostUpvotedBy.test.tsx b/__tests__/view/screens/PostUpvotedBy.test.tsx
new file mode 100644
index 00000000..97912ded
--- /dev/null
+++ b/__tests__/view/screens/PostUpvotedBy.test.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import {PostUpvotedBy} from '../../../src/view/screens/PostUpvotedBy'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('PostUpvotedBy', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ rkey: '123123123',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/Profile.test.tsx b/__tests__/view/screens/Profile.test.tsx
new file mode 100644
index 00000000..8912cbfb
--- /dev/null
+++ b/__tests__/view/screens/Profile.test.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import {Profile} from '../../../src/view/screens/Profile'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Profile', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ user: 'test.user',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/ProfileFollowers.test.tsx b/__tests__/view/screens/ProfileFollowers.test.tsx
new file mode 100644
index 00000000..230209aa
--- /dev/null
+++ b/__tests__/view/screens/ProfileFollowers.test.tsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import {ProfileFollowers} from '../../../src/view/screens/ProfileFollowers'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('ProfileFollowers', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/ProfileFollows.test.tsx b/__tests__/view/screens/ProfileFollows.test.tsx
new file mode 100644
index 00000000..e4571b5c
--- /dev/null
+++ b/__tests__/view/screens/ProfileFollows.test.tsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import {ProfileFollows} from '../../../src/view/screens/ProfileFollows'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('ProfileFollows', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/ProfileMembers.test.tsx b/__tests__/view/screens/ProfileMembers.test.tsx
new file mode 100644
index 00000000..a33e03a1
--- /dev/null
+++ b/__tests__/view/screens/ProfileMembers.test.tsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import {ProfileMembers} from '../../../src/view/screens/ProfileMembers'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('ProfileMembers', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/Search.test.tsx b/__tests__/view/screens/Search.test.tsx
new file mode 100644
index 00000000..477e077a
--- /dev/null
+++ b/__tests__/view/screens/Search.test.tsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import {Search} from '../../../src/view/screens/Search'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Search', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {
+ name: 'test name',
+ },
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/Settings.test.tsx b/__tests__/view/screens/Settings.test.tsx
new file mode 100644
index 00000000..475639eb
--- /dev/null
+++ b/__tests__/view/screens/Settings.test.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import {Settings} from '../../../src/view/screens/Settings'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Settings', () => {
+ const mockedProps = {
+ navIdx: [0, 0] as [number, number],
+ params: {},
+ visible: true,
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/screens/__snapshots__/Contacts.test.tsx.snap b/__tests__/view/screens/__snapshots__/Contacts.test.tsx.snap
new file mode 100644
index 00000000..61a85708
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Contacts.test.tsx.snap
@@ -0,0 +1,205 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Contacts renders correctly 1`] = `
+
+
+
+ Contacts
+
+
+
+
+ <
+ icon="magnifying-glass"
+ size={16}
+ style={
+ Object {
+ "color": "#645454",
+ "marginRight": 8,
+ }
+ }
+ />
+
+
+
+
+
+
+
+ All
+
+
+
+
+ Following
+
+
+
+
+ Scenes
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/Home.test.tsx.snap b/__tests__/view/screens/__snapshots__/Home.test.tsx.snap
new file mode 100644
index 00000000..4d2c5109
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Home.test.tsx.snap
@@ -0,0 +1,594 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Home renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bluesky
+
+
+ Private Beta
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ What's up?
+
+
+
+
+ Post
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/Login.test.tsx.snap b/__tests__/view/screens/__snapshots__/Login.test.tsx.snap
new file mode 100644
index 00000000..b86d8656
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Login.test.tsx.snap
@@ -0,0 +1,371 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Login renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bluesky
+
+
+ [ private beta ]
+
+
+
+
+
+ Create a new account
+
+
+
+
+
+
+
+
+
+
+ or
+
+
+
+
+ Sign in
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/NotFound.test.tsx.snap b/__tests__/view/screens/__snapshots__/NotFound.test.tsx.snap
new file mode 100644
index 00000000..a9365718
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/NotFound.test.tsx.snap
@@ -0,0 +1,431 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NotFound renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Page not found
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+ Page not found
+
+
+
+
+ Home
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/Notifications.test.tsx.snap b/__tests__/view/screens/__snapshots__/Notifications.test.tsx.snap
new file mode 100644
index 00000000..6c1eef57
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Notifications.test.tsx.snap
@@ -0,0 +1,378 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Notifications renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Notifications
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/Onboard.test.tsx.snap b/__tests__/view/screens/__snapshots__/Onboard.test.tsx.snap
new file mode 100644
index 00000000..5422fb0d
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Onboard.test.tsx.snap
@@ -0,0 +1,388 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Onboard renders correctly 1`] = `
+
+
+
+
+
+
+
+
+ Welcome to
+
+ Bluesky
+
+
+
+ Let's do a quick tour through the new features.
+
+
+
+
+
+
+
+
+
+
+
+
+ °
+
+
+
+
+ °
+
+
+
+
+
+
+
+
+ Skip
+
+
+
+
+
+ Next
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/PostDownvotedBy.test.tsx.snap b/__tests__/view/screens/__snapshots__/PostDownvotedBy.test.tsx.snap
new file mode 100644
index 00000000..aa41d7fb
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/PostDownvotedBy.test.tsx.snap
@@ -0,0 +1,368 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PostDownvotedBy renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Downvoted by
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/PostRepostedBy.test.tsx.snap b/__tests__/view/screens/__snapshots__/PostRepostedBy.test.tsx.snap
new file mode 100644
index 00000000..f6af5ec5
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/PostRepostedBy.test.tsx.snap
@@ -0,0 +1,368 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PostRepostedBy renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reposted by
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/PostThread.test.tsx.snap b/__tests__/view/screens/__snapshots__/PostThread.test.tsx.snap
new file mode 100644
index 00000000..abb36931
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/PostThread.test.tsx.snap
@@ -0,0 +1,437 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PostThread renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Post
+
+
+ by test name
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+ }
+ refreshing={false}
+ removeClippedSubviews={false}
+ renderItem={[Function]}
+ scrollEventThrottle={50}
+ stickyHeaderIndices={Array []}
+ style={
+ Object {
+ "flex": 1,
+ }
+ }
+ viewabilityConfigCallbackPairs={Array []}
+ >
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/PostUpvotedBy.test.tsx.snap b/__tests__/view/screens/__snapshots__/PostUpvotedBy.test.tsx.snap
new file mode 100644
index 00000000..a7bb6aae
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/PostUpvotedBy.test.tsx.snap
@@ -0,0 +1,368 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PostUpvotedBy renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Upvoted by
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/Profile.test.tsx.snap b/__tests__/view/screens/__snapshots__/Profile.test.tsx.snap
new file mode 100644
index 00000000..e9640b6e
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Profile.test.tsx.snap
@@ -0,0 +1,513 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Profile renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test name
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/ProfileFollowers.test.tsx.snap b/__tests__/view/screens/__snapshots__/ProfileFollowers.test.tsx.snap
new file mode 100644
index 00000000..237773b4
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/ProfileFollowers.test.tsx.snap
@@ -0,0 +1,386 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ProfileFollowers renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Followers
+
+
+ of test name
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/ProfileFollows.test.tsx.snap b/__tests__/view/screens/__snapshots__/ProfileFollows.test.tsx.snap
new file mode 100644
index 00000000..cba1a734
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/ProfileFollows.test.tsx.snap
@@ -0,0 +1,386 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ProfileFollows renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Followed
+
+
+ by test name
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/ProfileMembers.test.tsx.snap b/__tests__/view/screens/__snapshots__/ProfileMembers.test.tsx.snap
new file mode 100644
index 00000000..e36a4b08
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/ProfileMembers.test.tsx.snap
@@ -0,0 +1,386 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ProfileMembers renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Members
+
+
+ of test name
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/Search.test.tsx.snap b/__tests__/view/screens/__snapshots__/Search.test.tsx.snap
new file mode 100644
index 00000000..13055207
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Search.test.tsx.snap
@@ -0,0 +1,514 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Search renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Search
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/screens/__snapshots__/Settings.test.tsx.snap b/__tests__/view/screens/__snapshots__/Settings.test.tsx.snap
new file mode 100644
index 00000000..77402da2
--- /dev/null
+++ b/__tests__/view/screens/__snapshots__/Settings.test.tsx.snap
@@ -0,0 +1,631 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Settings renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Settings
+
+
+
+ <
+ icon="plus"
+ size={18}
+ />
+
+
+
+
+
+
+
+
+
+ <
+ icon="signal"
+ size={18}
+ style={
+ Array [
+ Object {
+ "color": "#000000",
+ },
+ ]
+ }
+ />
+ <
+ icon="x"
+ size={12}
+ style={
+ Object {
+ "backgroundColor": "#ffffff",
+ "color": "#d1106f",
+ "left": -4,
+ "position": "relative",
+ "top": 6,
+ }
+ }
+ />
+
+
+
+
+
+ Signed in as
+
+
+
+
+ Sign out
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @
+
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/shell/mobile/Composer.test.tsx b/__tests__/view/shell/mobile/Composer.test.tsx
new file mode 100644
index 00000000..7b84cfd8
--- /dev/null
+++ b/__tests__/view/shell/mobile/Composer.test.tsx
@@ -0,0 +1,23 @@
+import React from 'react'
+import {Composer} from '../../../../src/view/shell/mobile/Composer'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Composer', () => {
+ const mockedProps = {
+ active: true,
+ winHeight: 844,
+ replyTo: {
+ author: {avatar: undefined, displayName: 'Alice', handle: 'alice.test'},
+ cid: 'bafyreieucrv36ylxrut4dr4jj264q2jj2vt2vfvhjfchgw3vua4gksvzia',
+ text: 'Captain, maybe we ought to turn on the searchlights now. No… that’s just what they’ll be expecting us to do.',
+ uri: 'at://did:plc:v3xz273ea2dzjpu2szsjzfue/app.bsky.feed.post/3jkcir3fhqv2u',
+ },
+ onPost: jest.fn(),
+ onClose: jest.fn(),
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/shell/mobile/Menu.test.tsx b/__tests__/view/shell/mobile/Menu.test.tsx
new file mode 100644
index 00000000..5305bd77
--- /dev/null
+++ b/__tests__/view/shell/mobile/Menu.test.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import {Menu} from '../../../../src/view/shell/mobile/Menu'
+import renderer from 'react-test-renderer'
+// import {render} from '../../../../jest/test-utils'
+
+describe('Menu', () => {
+ const mockedProps = {
+ visible: true,
+ onClose: jest.fn(),
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create(
).toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/shell/mobile/TabsSelector.test.tsx b/__tests__/view/shell/mobile/TabsSelector.test.tsx
new file mode 100644
index 00000000..7908f442
--- /dev/null
+++ b/__tests__/view/shell/mobile/TabsSelector.test.tsx
@@ -0,0 +1,17 @@
+import React from 'react'
+import {Animated} from 'react-native'
+import renderer from 'react-test-renderer'
+import {TabsSelector} from '../../../../src/view/shell/mobile/TabsSelector'
+// import {render} from '../../../../jest/test-utils'
+
+describe('TabsSelector', () => {
+ const mockedProps = {
+ active: true,
+ tabMenuInterp: new Animated.Value(0),
+ onClose: jest.fn(),
+ }
+ it('renders correctly', () => {
+ const tree = renderer.create().toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/__tests__/view/shell/mobile/__snapshots__/Composer.test.tsx.snap b/__tests__/view/shell/mobile/__snapshots__/Composer.test.tsx.snap
new file mode 100644
index 00000000..6ced9871
--- /dev/null
+++ b/__tests__/view/shell/mobile/__snapshots__/Composer.test.tsx.snap
@@ -0,0 +1,659 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Composer renders correctly 1`] = `
+
+
+
+
+
+
+ Cancel
+
+
+
+
+
+
+ Reply
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Alice
+
+
+ Captain, maybe we ought to turn on the searchlights now. No… that’s just what they’ll be expecting us to do.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <
+ icon={
+ Array [
+ "far",
+ "image",
+ ]
+ }
+ size={24}
+ style={
+ Object {
+ "color": "#0085ff",
+ }
+ }
+ />
+
+
+
+ 256
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/shell/mobile/__snapshots__/Menu.test.tsx.snap b/__tests__/view/shell/mobile/__snapshots__/Menu.test.tsx.snap
new file mode 100644
index 00000000..78c34b96
--- /dev/null
+++ b/__tests__/view/shell/mobile/__snapshots__/Menu.test.tsx.snap
@@ -0,0 +1,837 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Menu renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Search
+
+
+
+
+
+
+
+
+
+
+
+
+ Home
+
+
+
+
+
+
+
+
+
+
+
+
+ Notifications
+
+
+
+
+
+ Scenes
+
+
+
+
+
+
+
+
+
+
+
+
+ Create a scene
+
+
+
+
+
+
+
+
+
+
+
+
+ Settings
+
+
+
+
+
+ Build version
+ (
+ )
+
+
+
+`;
diff --git a/__tests__/view/shell/mobile/__snapshots__/TabsSelector.test.tsx.snap b/__tests__/view/shell/mobile/__snapshots__/TabsSelector.test.tsx.snap
new file mode 100644
index 00000000..03e0636d
--- /dev/null
+++ b/__tests__/view/shell/mobile/__snapshots__/TabsSelector.test.tsx.snap
@@ -0,0 +1,651 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`TabsSelector renders correctly 1`] = `
+
+
+
+
+
+
+ <
+ icon="share"
+ size={16}
+ />
+
+
+ Share
+
+
+
+
+ <
+ icon={
+ Array [
+ "far",
+ "clone",
+ ]
+ }
+ size={16}
+ />
+
+
+ Clone tab
+
+
+
+
+ <
+ icon="plus"
+ size={16}
+ />
+
+
+ New tab
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <
+ icon="house"
+ size={20}
+ />
+
+
+ /
+
+
+
+ <
+ icon="x"
+ size={14}
+ style={
+ Object {
+ "color": "#655",
+ }
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <
+ icon="bell"
+ size={20}
+ />
+
+
+ /notifications
+
+
+
+ <
+ icon="x"
+ size={14}
+ style={
+ Object {
+ "color": "#655",
+ }
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/shell/mobile/__snapshots__/index.test.tsx.snap b/__tests__/view/shell/mobile/__snapshots__/index.test.tsx.snap
new file mode 100644
index 00000000..793668b7
--- /dev/null
+++ b/__tests__/view/shell/mobile/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,421 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`MobileShell renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bluesky
+
+
+ [ private beta ]
+
+
+
+
+
+ Create a new account
+
+
+
+
+
+
+
+
+
+
+ or
+
+
+
+
+ Sign in
+
+
+
+
+
+
+
+
+
+`;
diff --git a/__tests__/view/shell/mobile/index.test.tsx b/__tests__/view/shell/mobile/index.test.tsx
new file mode 100644
index 00000000..96f16126
--- /dev/null
+++ b/__tests__/view/shell/mobile/index.test.tsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import {MobileShell} from '../../../../src/view/shell/mobile'
+import renderer from 'react-test-renderer'
+import {SafeAreaProvider} from 'react-native-safe-area-context'
+// import {render} from '../../../../jest/test-utils'
+
+describe('MobileShell', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create(
+
+
+ ,
+ )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/jest.js b/jest.js
deleted file mode 100644
index eb2d4165..00000000
--- a/jest.js
+++ /dev/null
@@ -1,3 +0,0 @@
-jest.mock('@react-native-async-storage/async-storage', () =>
- require('@react-native-async-storage/async-storage/jest/async-storage-mock'),
-)
diff --git a/jest/jestSetup.js b/jest/jestSetup.js
new file mode 100644
index 00000000..7a2f10d2
--- /dev/null
+++ b/jest/jestSetup.js
@@ -0,0 +1,39 @@
+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')
+
+jest.mock('@fortawesome/react-native-fontawesome', () => ({
+ FontAwesomeIcon: '',
+}))
+
+require('react-native-reanimated/lib/reanimated2/jestUtils').setUpTests()
+
+// Silence the warning: Animated: `useNativeDriver` is not supported
+jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
+
+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('@gorhom/bottom-sheet', () => {
+ const react = require('react-native')
+ return {
+ __esModule: true,
+ default: react.View,
+ namedExport: {
+ ...require('react-native-reanimated/mock'),
+ ...jest.requireActual('@gorhom/bottom-sheet'),
+ BottomSheetFlatList: react.FlatList,
+ },
+ }
+})
+
+jest.useFakeTimers()
diff --git a/jest/test-utils.tsx b/jest/test-utils.tsx
new file mode 100644
index 00000000..a5946ed0
--- /dev/null
+++ b/jest/test-utils.tsx
@@ -0,0 +1,32 @@
+import React from 'react'
+import RN from 'react-native'
+import {render} from '@testing-library/react-native'
+import {GestureHandlerRootView} from 'react-native-gesture-handler'
+import {RootSiblingParent} from 'react-native-root-siblings'
+import {SafeAreaProvider} from 'react-native-safe-area-context'
+import {DEFAULT_SERVICE, RootStoreModel, RootStoreProvider} from '../src/state'
+import {SessionServiceClient} from '../src/third-party/api/src'
+import {sessionClient as AtpApi} from '../src/third-party/api'
+
+const WrappedComponent = ({children}: any) => {
+ const api = AtpApi.service(DEFAULT_SERVICE) as SessionServiceClient
+ const rootStore = new RootStoreModel(api)
+ return (
+
+
+
+ {children}
+
+
+
+ )
+}
+
+const customRender = (ui: any, options?: any) =>
+ render(ui, {wrapper: WrappedComponent, ...options})
+
+// re-export everything
+export * from '@testing-library/react-native'
+
+// override render method
+export {customRender as render}
diff --git a/package.json b/package.json
index 73abfc5f..3a11ba35 100644
--- a/package.json
+++ b/package.json
@@ -8,8 +8,9 @@
"web": "react-scripts start",
"start": "react-native start",
"clean-cache": "rm -rf node_modules/.cache/babel-loader/*",
- "test": "jest",
- "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
+ "test": "jest --coverage",
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
+ "postinstall": "patch-package"
},
"dependencies": {
"@atproto/api": "^0.0.2",
@@ -31,6 +32,7 @@
"lru_map": "^0.4.1",
"mobx": "^6.6.1",
"mobx-react-lite": "^3.4.0",
+ "patch-package": "^6.5.0",
"react": "17.0.2",
"react-circular-progressbar": "^2.1.0",
"react-dom": "17.0.2",
@@ -61,6 +63,8 @@
"@babel/core": "^7.12.9",
"@babel/runtime": "^7.12.5",
"@react-native-community/eslint-config": "^2.0.0",
+ "@testing-library/jest-native": "^5.3.3",
+ "@testing-library/react-native": "^11.5.0",
"@types/he": "^1.1.2",
"@types/jest": "^26.0.23",
"@types/lodash.chunk": "^4.2.7",
@@ -85,8 +89,10 @@
"jest": {
"preset": "react-native",
"setupFiles": [
- "./jest.js"
+ "./jest/jestSetup.js",
+ "./node_modules/react-native-gesture-handler/jestSetup.js"
],
+ "setupFilesAfterEnv": ["@testing-library/jest-native/extend-expect"],
"moduleFileExtensions": [
"ts",
"tsx",
@@ -97,6 +103,12 @@
],
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|rollbar-react-native|@fortawesome|@react-native|@react-navigation)"
+ ],
+ "coveragePathIgnorePatterns": [
+ "/node_modules/",
+ "/src/platform",
+ "/src/third-party",
+ "/__tests__/test-utils.js"
]
},
"browserslist": {
diff --git a/patches/react-native-pager-view+5.4.1.patch b/patches/react-native-pager-view+5.4.1.patch
new file mode 100644
index 00000000..31690e5d
--- /dev/null
+++ b/patches/react-native-pager-view+5.4.1.patch
@@ -0,0 +1,125 @@
+# HOTFIX - https://github.com/satya164/react-native-tab-view/issues/1104
+
+diff --git a/node_modules/react-native-pager-view/lib/commonjs/PagerView.js b/node_modules/react-native-pager-view/lib/commonjs/PagerView.js
+index 40afb41..850c151 100644
+--- a/node_modules/react-native-pager-view/lib/commonjs/PagerView.js
++++ b/node_modules/react-native-pager-view/lib/commonjs/PagerView.js
+@@ -131,17 +131,20 @@ class PagerView extends _react.default.Component {
+ }
+
+ render() {
+- return /*#__PURE__*/_react.default.createElement(_PagerViewNative.PagerViewViewManager, _extends({}, this.props, {
+- ref: this.PagerView
+- /** TODO: Fix ref type */
+- ,
++ const {
++ children,
++ forwardedRef,
++ ...rest
++ } = this.props;
++ return /*#__PURE__*/_react.default.createElement(_PagerViewNative.PagerViewViewManager, _extends({}, rest, {
++ // ref={this.PagerView as any /** TODO: Fix ref type */}
+ style: this.props.style,
+ layoutDirection: this.deducedLayoutDirection,
+ onPageScroll: this._onPageScroll,
+ onPageScrollStateChanged: this._onPageScrollStateChanged,
+ onPageSelected: this._onPageSelected,
+ onMoveShouldSetResponderCapture: this._onMoveShouldSetResponderCapture,
+- children: (0, _utils.childrenWithOverriddenStyle)(this.props.children)
++ children: (0, _utils.childrenWithOverriddenStyle)(children)
+ }));
+ }
+
+diff --git a/node_modules/react-native-pager-view/lib/commonjs/PagerView.js.map b/node_modules/react-native-pager-view/lib/commonjs/PagerView.js.map
+index ce9ff7f..c55d898 100644
+--- a/node_modules/react-native-pager-view/lib/commonjs/PagerView.js.map
++++ b/node_modules/react-native-pager-view/lib/commonjs/PagerView.js.map
+@@ -1 +1 @@
+-{"version":3,"sources":["PagerView.tsx"],"names":["PagerView","React","Component","createRef","current","getInnerViewNode","e","props","onPageScroll","Platform","OS","keyboardDismissMode","Keyboard","dismiss","onPageScrollStateChanged","isScrolling","nativeEvent","pageScrollState","onPageSelected","selectedPage","UIManager","dispatchViewManagerCommand","ReactNative","findNodeHandle","Commands","setPage","setPageWithoutAnimation","scrollEnabled","setScrollEnabled","deducedLayoutDirection","shouldUseDeviceRtlSetup","layoutDirection","I18nManager","isRTL","render","style","_onPageScroll","_onPageScrollStateChanged","_onPageSelected","_onMoveShouldSetResponderCapture","children"],"mappings":"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","sourcesContent":["import React, { ReactElement } from 'react';\nimport { Platform, UIManager, Keyboard } from 'react-native';\nimport ReactNative, { I18nManager } from 'react-native';\nimport type {\n PagerViewOnPageScrollEvent,\n PagerViewOnPageSelectedEvent,\n PageScrollStateChangedNativeEvent,\n PagerViewProps,\n} from './types';\n\nimport { childrenWithOverriddenStyle } from './utils';\nimport { getViewManagerConfig, PagerViewViewManager } from './PagerViewNative';\n\n/**\n * Container that allows to flip left and right between child views. Each\n * child view of the `PagerView` will be treated as a separate page\n * and will be stretched to fill the `PagerView`.\n *\n * It is important all children are ``s and not composite components.\n * You can set style properties like `padding` or `backgroundColor` for each\n * child. It is also important that each child have a `key` prop.\n *\n * Example:\n *\n * ```\n * render: function() {\n * return (\n * \n * \n * First page\n * \n * \n * Second page\n * \n * \n * );\n * }\n *\n * ...\n *\n * var styles = {\n * ...\n * PagerView: {\n * flex: 1\n * },\n * pageStyle: {\n * alignItems: 'center',\n * padding: 20,\n * }\n * }\n * ```\n */\n\nexport class PagerView extends React.Component {\n private isScrolling = false;\n private PagerView = React.createRef();\n\n public getInnerViewNode = (): ReactElement => {\n return this.PagerView.current!.getInnerViewNode();\n };\n\n private _onPageScroll = (e: PagerViewOnPageScrollEvent) => {\n if (this.props.onPageScroll) {\n this.props.onPageScroll(e);\n }\n // Not implemented on iOS yet\n if (Platform.OS === 'android') {\n if (this.props.keyboardDismissMode === 'on-drag') {\n Keyboard.dismiss();\n }\n }\n };\n\n private _onPageScrollStateChanged = (\n e: PageScrollStateChangedNativeEvent\n ) => {\n if (this.props.onPageScrollStateChanged) {\n this.props.onPageScrollStateChanged(e);\n }\n this.isScrolling = e.nativeEvent.pageScrollState === 'dragging';\n };\n\n private _onPageSelected = (e: PagerViewOnPageSelectedEvent) => {\n if (this.props.onPageSelected) {\n this.props.onPageSelected(e);\n }\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will be animated.\n */\n public setPage = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPage,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will *not* be animated.\n */\n public setPageWithoutAnimation = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPageWithoutAnimation,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to enable/disable scroll imperatively\n * The recommended way is using the scrollEnabled prop, however, there might be a case where a\n * imperative solution is more useful (e.g. for not blocking an animation)\n */\n public setScrollEnabled = (scrollEnabled: boolean) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setScrollEnabled,\n [scrollEnabled]\n );\n };\n\n private _onMoveShouldSetResponderCapture = () => {\n return this.isScrolling;\n };\n\n private get deducedLayoutDirection() {\n const shouldUseDeviceRtlSetup =\n !this.props.layoutDirection || this.props.layoutDirection === 'locale';\n\n if (shouldUseDeviceRtlSetup) {\n return I18nManager.isRTL ? 'rtl' : 'ltr';\n } else {\n return this.props.layoutDirection;\n }\n }\n\n render() {\n return (\n \n );\n }\n}\n"]}
+\ No newline at end of file
++{"version":3,"sources":["PagerView.tsx"],"names":["PagerView","React","Component","createRef","current","getInnerViewNode","e","props","onPageScroll","Platform","OS","keyboardDismissMode","Keyboard","dismiss","onPageScrollStateChanged","isScrolling","nativeEvent","pageScrollState","onPageSelected","selectedPage","UIManager","dispatchViewManagerCommand","ReactNative","findNodeHandle","Commands","setPage","setPageWithoutAnimation","scrollEnabled","setScrollEnabled","deducedLayoutDirection","shouldUseDeviceRtlSetup","layoutDirection","I18nManager","isRTL","render","children","forwardedRef","rest","style","_onPageScroll","_onPageScrollStateChanged","_onPageSelected","_onMoveShouldSetResponderCapture"],"mappings":"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","sourcesContent":["import React, { ReactElement } from 'react';\nimport { Platform, UIManager, Keyboard } from 'react-native';\nimport ReactNative, { I18nManager } from 'react-native';\nimport type {\n PagerViewOnPageScrollEvent,\n PagerViewOnPageSelectedEvent,\n PageScrollStateChangedNativeEvent,\n PagerViewProps,\n} from './types';\n\nimport { childrenWithOverriddenStyle } from './utils';\nimport { getViewManagerConfig, PagerViewViewManager } from './PagerViewNative';\n\n/**\n * Container that allows to flip left and right between child views. Each\n * child view of the `PagerView` will be treated as a separate page\n * and will be stretched to fill the `PagerView`.\n *\n * It is important all children are ``s and not composite components.\n * You can set style properties like `padding` or `backgroundColor` for each\n * child. It is also important that each child have a `key` prop.\n *\n * Example:\n *\n * ```\n * render: function() {\n * return (\n * \n * \n * First page\n * \n * \n * Second page\n * \n * \n * );\n * }\n *\n * ...\n *\n * var styles = {\n * ...\n * PagerView: {\n * flex: 1\n * },\n * pageStyle: {\n * alignItems: 'center',\n * padding: 20,\n * }\n * }\n * ```\n */\n\nexport class PagerView extends React.Component {\n private isScrolling = false;\n private PagerView = React.createRef();\n\n public getInnerViewNode = (): ReactElement => {\n return this.PagerView.current!.getInnerViewNode();\n };\n\n private _onPageScroll = (e: PagerViewOnPageScrollEvent) => {\n if (this.props.onPageScroll) {\n this.props.onPageScroll(e);\n }\n // Not implemented on iOS yet\n if (Platform.OS === 'android') {\n if (this.props.keyboardDismissMode === 'on-drag') {\n Keyboard.dismiss();\n }\n }\n };\n\n private _onPageScrollStateChanged = (\n e: PageScrollStateChangedNativeEvent\n ) => {\n if (this.props.onPageScrollStateChanged) {\n this.props.onPageScrollStateChanged(e);\n }\n this.isScrolling = e.nativeEvent.pageScrollState === 'dragging';\n };\n\n private _onPageSelected = (e: PagerViewOnPageSelectedEvent) => {\n if (this.props.onPageSelected) {\n this.props.onPageSelected(e);\n }\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will be animated.\n */\n public setPage = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPage,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will *not* be animated.\n */\n public setPageWithoutAnimation = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPageWithoutAnimation,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to enable/disable scroll imperatively\n * The recommended way is using the scrollEnabled prop, however, there might be a case where a\n * imperative solution is more useful (e.g. for not blocking an animation)\n */\n public setScrollEnabled = (scrollEnabled: boolean) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setScrollEnabled,\n [scrollEnabled]\n );\n };\n\n private _onMoveShouldSetResponderCapture = () => {\n return this.isScrolling;\n };\n\n private get deducedLayoutDirection() {\n const shouldUseDeviceRtlSetup =\n !this.props.layoutDirection || this.props.layoutDirection === 'locale';\n\n if (shouldUseDeviceRtlSetup) {\n return I18nManager.isRTL ? 'rtl' : 'ltr';\n } else {\n return this.props.layoutDirection;\n }\n }\n\n render() {\n const { children, forwardedRef, ...rest } = this.props;\n\n return (\n \n );\n }\n}\n"]}
+\ No newline at end of file
+diff --git a/node_modules/react-native-pager-view/lib/module/PagerView.js b/node_modules/react-native-pager-view/lib/module/PagerView.js
+index dc1ddc5..f95b242 100644
+--- a/node_modules/react-native-pager-view/lib/module/PagerView.js
++++ b/node_modules/react-native-pager-view/lib/module/PagerView.js
+@@ -116,17 +116,20 @@ export class PagerView extends React.Component {
+ }
+
+ render() {
+- return /*#__PURE__*/React.createElement(PagerViewViewManager, _extends({}, this.props, {
+- ref: this.PagerView
+- /** TODO: Fix ref type */
+- ,
++ const {
++ children,
++ forwardedRef,
++ ...rest
++ } = this.props;
++ return /*#__PURE__*/React.createElement(PagerViewViewManager, _extends({}, rest, {
++ // ref={this.PagerView as any /** TODO: Fix ref type */}
+ style: this.props.style,
+ layoutDirection: this.deducedLayoutDirection,
+ onPageScroll: this._onPageScroll,
+ onPageScrollStateChanged: this._onPageScrollStateChanged,
+ onPageSelected: this._onPageSelected,
+ onMoveShouldSetResponderCapture: this._onMoveShouldSetResponderCapture,
+- children: childrenWithOverriddenStyle(this.props.children)
++ children: childrenWithOverriddenStyle(children)
+ }));
+ }
+
+diff --git a/node_modules/react-native-pager-view/lib/module/PagerView.js.map b/node_modules/react-native-pager-view/lib/module/PagerView.js.map
+index 6c26c01..ea08ccc 100644
+--- a/node_modules/react-native-pager-view/lib/module/PagerView.js.map
++++ b/node_modules/react-native-pager-view/lib/module/PagerView.js.map
+@@ -1 +1 @@
+-{"version":3,"sources":["PagerView.tsx"],"names":["React","Platform","UIManager","Keyboard","ReactNative","I18nManager","childrenWithOverriddenStyle","getViewManagerConfig","PagerViewViewManager","PagerView","Component","createRef","current","getInnerViewNode","e","props","onPageScroll","OS","keyboardDismissMode","dismiss","onPageScrollStateChanged","isScrolling","nativeEvent","pageScrollState","onPageSelected","selectedPage","dispatchViewManagerCommand","findNodeHandle","Commands","setPage","setPageWithoutAnimation","scrollEnabled","setScrollEnabled","deducedLayoutDirection","shouldUseDeviceRtlSetup","layoutDirection","isRTL","render","style","_onPageScroll","_onPageScrollStateChanged","_onPageSelected","_onMoveShouldSetResponderCapture","children"],"mappings":"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","sourcesContent":["import React, { ReactElement } from 'react';\nimport { Platform, UIManager, Keyboard } from 'react-native';\nimport ReactNative, { I18nManager } from 'react-native';\nimport type {\n PagerViewOnPageScrollEvent,\n PagerViewOnPageSelectedEvent,\n PageScrollStateChangedNativeEvent,\n PagerViewProps,\n} from './types';\n\nimport { childrenWithOverriddenStyle } from './utils';\nimport { getViewManagerConfig, PagerViewViewManager } from './PagerViewNative';\n\n/**\n * Container that allows to flip left and right between child views. Each\n * child view of the `PagerView` will be treated as a separate page\n * and will be stretched to fill the `PagerView`.\n *\n * It is important all children are ``s and not composite components.\n * You can set style properties like `padding` or `backgroundColor` for each\n * child. It is also important that each child have a `key` prop.\n *\n * Example:\n *\n * ```\n * render: function() {\n * return (\n * \n * \n * First page\n * \n * \n * Second page\n * \n * \n * );\n * }\n *\n * ...\n *\n * var styles = {\n * ...\n * PagerView: {\n * flex: 1\n * },\n * pageStyle: {\n * alignItems: 'center',\n * padding: 20,\n * }\n * }\n * ```\n */\n\nexport class PagerView extends React.Component {\n private isScrolling = false;\n private PagerView = React.createRef();\n\n public getInnerViewNode = (): ReactElement => {\n return this.PagerView.current!.getInnerViewNode();\n };\n\n private _onPageScroll = (e: PagerViewOnPageScrollEvent) => {\n if (this.props.onPageScroll) {\n this.props.onPageScroll(e);\n }\n // Not implemented on iOS yet\n if (Platform.OS === 'android') {\n if (this.props.keyboardDismissMode === 'on-drag') {\n Keyboard.dismiss();\n }\n }\n };\n\n private _onPageScrollStateChanged = (\n e: PageScrollStateChangedNativeEvent\n ) => {\n if (this.props.onPageScrollStateChanged) {\n this.props.onPageScrollStateChanged(e);\n }\n this.isScrolling = e.nativeEvent.pageScrollState === 'dragging';\n };\n\n private _onPageSelected = (e: PagerViewOnPageSelectedEvent) => {\n if (this.props.onPageSelected) {\n this.props.onPageSelected(e);\n }\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will be animated.\n */\n public setPage = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPage,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will *not* be animated.\n */\n public setPageWithoutAnimation = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPageWithoutAnimation,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to enable/disable scroll imperatively\n * The recommended way is using the scrollEnabled prop, however, there might be a case where a\n * imperative solution is more useful (e.g. for not blocking an animation)\n */\n public setScrollEnabled = (scrollEnabled: boolean) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setScrollEnabled,\n [scrollEnabled]\n );\n };\n\n private _onMoveShouldSetResponderCapture = () => {\n return this.isScrolling;\n };\n\n private get deducedLayoutDirection() {\n const shouldUseDeviceRtlSetup =\n !this.props.layoutDirection || this.props.layoutDirection === 'locale';\n\n if (shouldUseDeviceRtlSetup) {\n return I18nManager.isRTL ? 'rtl' : 'ltr';\n } else {\n return this.props.layoutDirection;\n }\n }\n\n render() {\n return (\n \n );\n }\n}\n"]}
+\ No newline at end of file
++{"version":3,"sources":["PagerView.tsx"],"names":["React","Platform","UIManager","Keyboard","ReactNative","I18nManager","childrenWithOverriddenStyle","getViewManagerConfig","PagerViewViewManager","PagerView","Component","createRef","current","getInnerViewNode","e","props","onPageScroll","OS","keyboardDismissMode","dismiss","onPageScrollStateChanged","isScrolling","nativeEvent","pageScrollState","onPageSelected","selectedPage","dispatchViewManagerCommand","findNodeHandle","Commands","setPage","setPageWithoutAnimation","scrollEnabled","setScrollEnabled","deducedLayoutDirection","shouldUseDeviceRtlSetup","layoutDirection","isRTL","render","children","forwardedRef","rest","style","_onPageScroll","_onPageScrollStateChanged","_onPageSelected","_onMoveShouldSetResponderCapture"],"mappings":"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","sourcesContent":["import React, { ReactElement } from 'react';\nimport { Platform, UIManager, Keyboard } from 'react-native';\nimport ReactNative, { I18nManager } from 'react-native';\nimport type {\n PagerViewOnPageScrollEvent,\n PagerViewOnPageSelectedEvent,\n PageScrollStateChangedNativeEvent,\n PagerViewProps,\n} from './types';\n\nimport { childrenWithOverriddenStyle } from './utils';\nimport { getViewManagerConfig, PagerViewViewManager } from './PagerViewNative';\n\n/**\n * Container that allows to flip left and right between child views. Each\n * child view of the `PagerView` will be treated as a separate page\n * and will be stretched to fill the `PagerView`.\n *\n * It is important all children are ``s and not composite components.\n * You can set style properties like `padding` or `backgroundColor` for each\n * child. It is also important that each child have a `key` prop.\n *\n * Example:\n *\n * ```\n * render: function() {\n * return (\n * \n * \n * First page\n * \n * \n * Second page\n * \n * \n * );\n * }\n *\n * ...\n *\n * var styles = {\n * ...\n * PagerView: {\n * flex: 1\n * },\n * pageStyle: {\n * alignItems: 'center',\n * padding: 20,\n * }\n * }\n * ```\n */\n\nexport class PagerView extends React.Component {\n private isScrolling = false;\n private PagerView = React.createRef();\n\n public getInnerViewNode = (): ReactElement => {\n return this.PagerView.current!.getInnerViewNode();\n };\n\n private _onPageScroll = (e: PagerViewOnPageScrollEvent) => {\n if (this.props.onPageScroll) {\n this.props.onPageScroll(e);\n }\n // Not implemented on iOS yet\n if (Platform.OS === 'android') {\n if (this.props.keyboardDismissMode === 'on-drag') {\n Keyboard.dismiss();\n }\n }\n };\n\n private _onPageScrollStateChanged = (\n e: PageScrollStateChangedNativeEvent\n ) => {\n if (this.props.onPageScrollStateChanged) {\n this.props.onPageScrollStateChanged(e);\n }\n this.isScrolling = e.nativeEvent.pageScrollState === 'dragging';\n };\n\n private _onPageSelected = (e: PagerViewOnPageSelectedEvent) => {\n if (this.props.onPageSelected) {\n this.props.onPageSelected(e);\n }\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will be animated.\n */\n public setPage = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPage,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to scroll to a specific page in the PagerView.\n * The transition between pages will *not* be animated.\n */\n public setPageWithoutAnimation = (selectedPage: number) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setPageWithoutAnimation,\n [selectedPage]\n );\n };\n\n /**\n * A helper function to enable/disable scroll imperatively\n * The recommended way is using the scrollEnabled prop, however, there might be a case where a\n * imperative solution is more useful (e.g. for not blocking an animation)\n */\n public setScrollEnabled = (scrollEnabled: boolean) => {\n UIManager.dispatchViewManagerCommand(\n ReactNative.findNodeHandle(this),\n getViewManagerConfig().Commands.setScrollEnabled,\n [scrollEnabled]\n );\n };\n\n private _onMoveShouldSetResponderCapture = () => {\n return this.isScrolling;\n };\n\n private get deducedLayoutDirection() {\n const shouldUseDeviceRtlSetup =\n !this.props.layoutDirection || this.props.layoutDirection === 'locale';\n\n if (shouldUseDeviceRtlSetup) {\n return I18nManager.isRTL ? 'rtl' : 'ltr';\n } else {\n return this.props.layoutDirection;\n }\n }\n\n render() {\n const { children, forwardedRef, ...rest } = this.props;\n\n return (\n \n );\n }\n}\n"]}
+\ No newline at end of file
+diff --git a/node_modules/react-native-pager-view/lib/typescript/PagerView.d.ts b/node_modules/react-native-pager-view/lib/typescript/PagerView.d.ts
+index f70d3bc..5610963 100644
+--- a/node_modules/react-native-pager-view/lib/typescript/PagerView.d.ts
++++ b/node_modules/react-native-pager-view/lib/typescript/PagerView.d.ts
+@@ -41,7 +41,9 @@ import type { PagerViewProps } from './types';
+ * }
+ * ```
+ */
+-export declare class PagerView extends React.Component {
++export declare class PagerView extends React.Component {
+ private isScrolling;
+ private PagerView;
+ getInnerViewNode: () => ReactElement;
+diff --git a/node_modules/react-native-pager-view/lib/typescript/__tests__/index.test.d.ts b/node_modules/react-native-pager-view/lib/typescript/__tests__/index.test.d.ts
+new file mode 100644
+index 0000000..e69de29
+diff --git a/node_modules/react-native-pager-view/src/PagerView.tsx b/node_modules/react-native-pager-view/src/PagerView.tsx
+index f7585d5..ee9843b 100644
+--- a/node_modules/react-native-pager-view/src/PagerView.tsx
++++ b/node_modules/react-native-pager-view/src/PagerView.tsx
+@@ -141,17 +141,19 @@ export class PagerView extends React.Component {
+ }
+
+ render() {
++ const {children, forwardedRef, ...rest} = this.props;
++
+ return (
+
+ );
+ }
\ No newline at end of file
diff --git a/src/lib/download.ts b/src/lib/download.ts
index 96d93fc2..c53d809b 100644
--- a/src/lib/download.ts
+++ b/src/lib/download.ts
@@ -1,7 +1,7 @@
import RNFetchBlob from 'rn-fetch-blob'
import ImageResizer from '@bam.tech/react-native-image-resizer'
-interface DownloadAndResizeOpts {
+export interface DownloadAndResizeOpts {
uri: string
width: number
height: number
diff --git a/src/lib/strings.ts b/src/lib/strings.ts
index c665c0b0..b13ac39e 100644
--- a/src/lib/strings.ts
+++ b/src/lib/strings.ts
@@ -23,7 +23,7 @@ export function makeRecordUri(
collection: string,
rkey: string,
) {
- const urip = new AtUri(`at://host/`)
+ const urip = new AtUri('at://host/')
urip.host = didOrName
urip.collection = collection
urip.rkey = rkey
@@ -63,7 +63,9 @@ export function ago(date: number | string | Date): string {
export function isValidDomain(str: string): boolean {
return !!TLDs.find(tld => {
let i = str.lastIndexOf(tld)
- if (i === -1) return false
+ if (i === -1) {
+ return false
+ }
return str.charAt(i - 1) === '.' && i === str.length - tld.length
})
}
diff --git a/src/view/shell/mobile/TabsSelector.tsx b/src/view/shell/mobile/TabsSelector.tsx
index d44a8e0c..41b18a33 100644
--- a/src/view/shell/mobile/TabsSelector.tsx
+++ b/src/view/shell/mobile/TabsSelector.tsx
@@ -175,7 +175,10 @@ export const TabsSelector = observer(
isClosing ? closingTabAnimStyle : undefined,
]}>
(tabRefs[tabIndex] = ref)}
style={[
styles.tab,
styles.existing,
diff --git a/yarn.lock b/yarn.lock
index 708aa54c..51e8861b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1683,6 +1683,13 @@
dependencies:
"@sinclair/typebox" "^0.24.1"
+"@jest/schemas@^29.0.0":
+ version "29.0.0"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a"
+ integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==
+ dependencies:
+ "@sinclair/typebox" "^0.24.1"
+
"@jest/source-map@^26.6.2":
version "26.6.2"
resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535"
@@ -2347,6 +2354,24 @@
"@svgr/plugin-svgo" "^5.5.0"
loader-utils "^2.0.0"
+"@testing-library/jest-native@^5.3.3":
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/@testing-library/jest-native/-/jest-native-5.3.3.tgz#8f7c97504d1373d20ded0704586e110a26f9ba1a"
+ integrity sha512-oakP6c4xHR5PyLbw6H6NiUxvTZmsIHNjQRMsI6P3aSLhDSBvzRQ3+KdEwhlhiU2oNMWW45XQakKZN3cf2BG5Dw==
+ dependencies:
+ chalk "^4.1.2"
+ jest-diff "^29.0.1"
+ jest-matcher-utils "^29.0.1"
+ pretty-format "^29.0.3"
+ redent "^3.0.0"
+
+"@testing-library/react-native@^11.5.0":
+ version "11.5.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-11.5.0.tgz#b043c5db7b15eca42a65e95d3f3ae196fab9493b"
+ integrity sha512-seV+qebsbX4E5CWk/wizU1+2wVLsPyqEzG7sTgrhJ81cgAawg7ay06fIZR9IS75pDeWn2KZVd4mGk1pjJ3i3Zw==
+ dependencies:
+ pretty-format "^29.0.0"
+
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@@ -2993,6 +3018,11 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+"@yarnpkg/lockfile@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
+ integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
+
"@zxing/text-encoding@^0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b"
@@ -4348,7 +4378,7 @@ cross-fetch@^3.1.5:
dependencies:
node-fetch "2.6.7"
-cross-spawn@^6.0.0:
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@@ -4787,6 +4817,11 @@ diff-sequences@^27.5.1:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
+diff-sequences@^29.3.1:
+ version "29.3.1"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e"
+ integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==
+
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -5873,6 +5908,13 @@ find-up@^5.0.0:
locate-path "^6.0.0"
path-exists "^4.0.0"
+find-yarn-workspace-root@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd"
+ integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==
+ dependencies:
+ micromatch "^4.0.2"
+
flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
@@ -5974,6 +6016,15 @@ fs-extra@^10.0.0:
jsonfile "^6.0.1"
universalify "^2.0.0"
+fs-extra@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+ integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
@@ -6566,6 +6617,11 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@@ -6917,7 +6973,7 @@ is-wsl@^1.1.0:
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==
-is-wsl@^2.2.0:
+is-wsl@^2.1.1, is-wsl@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
@@ -7162,6 +7218,16 @@ jest-diff@^27.5.1:
jest-get-type "^27.5.1"
pretty-format "^27.5.1"
+jest-diff@^29.0.1, jest-diff@^29.3.1:
+ version "29.3.1"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527"
+ integrity sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^29.3.1"
+ jest-get-type "^29.2.0"
+ pretty-format "^29.3.1"
+
jest-docblock@^26.0.0:
version "26.0.0"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5"
@@ -7258,6 +7324,11 @@ jest-get-type@^27.5.1:
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
+jest-get-type@^29.2.0:
+ version "29.2.0"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408"
+ integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==
+
jest-haste-map@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa"
@@ -7382,6 +7453,16 @@ jest-matcher-utils@^27.5.1:
jest-get-type "^27.5.1"
pretty-format "^27.5.1"
+jest-matcher-utils@^29.0.1:
+ version "29.3.1"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz#6e7f53512f80e817dfa148672bd2d5d04914a572"
+ integrity sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^29.3.1"
+ jest-get-type "^29.2.0"
+ pretty-format "^29.3.1"
+
jest-message-util@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07"
@@ -8065,6 +8146,13 @@ kind-of@^6.0.0, kind-of@^6.0.2:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+klaw-sync@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c"
+ integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==
+ dependencies:
+ graceful-fs "^4.1.11"
+
klaw@^1.0.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439"
@@ -8671,6 +8759,11 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
mini-css-extract-plugin@^2.4.5:
version "2.6.1"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz#9a1251d15f2035c342d99a468ab9da7a0451b71e"
@@ -9088,6 +9181,14 @@ open@^6.2.0:
dependencies:
is-wsl "^1.1.0"
+open@^7.4.2:
+ version "7.4.2"
+ resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321"
+ integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==
+ dependencies:
+ is-docker "^2.0.0"
+ is-wsl "^2.1.1"
+
open@^8.0.9, open@^8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
@@ -9153,7 +9254,7 @@ ora@^5.4.1:
strip-ansi "^6.0.0"
wcwidth "^1.0.1"
-os-tmpdir@^1.0.0:
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
@@ -9272,6 +9373,26 @@ pascalcase@^0.1.1:
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==
+patch-package@^6.5.0:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.0.tgz#feb058db56f0005da59cfa316488321de585e88a"
+ integrity sha512-tC3EqJmo74yKqfsMzELaFwxOAu6FH6t+FzFOsnWAuARm7/n2xB5AOeOueE221eM9gtMuIKMKpF9tBy/X2mNP0Q==
+ dependencies:
+ "@yarnpkg/lockfile" "^1.1.0"
+ chalk "^4.1.2"
+ cross-spawn "^6.0.5"
+ find-yarn-workspace-root "^2.0.0"
+ fs-extra "^7.0.1"
+ is-ci "^2.0.0"
+ klaw-sync "^6.0.0"
+ minimist "^1.2.6"
+ open "^7.4.2"
+ rimraf "^2.6.3"
+ semver "^5.6.0"
+ slash "^2.0.0"
+ tmp "^0.0.33"
+ yaml "^1.10.2"
+
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -9997,6 +10118,15 @@ pretty-format@^28.1.3:
ansi-styles "^5.0.0"
react-is "^18.0.0"
+pretty-format@^29.0.0, pretty-format@^29.0.3, pretty-format@^29.3.1:
+ version "29.3.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da"
+ integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==
+ dependencies:
+ "@jest/schemas" "^29.0.0"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -10581,6 +10711,14 @@ recursive-readdir@^2.2.2:
dependencies:
minimatch "3.0.4"
+redent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+ integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+ dependencies:
+ indent-string "^4.0.0"
+ strip-indent "^3.0.0"
+
regenerate-unicode-properties@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
@@ -10799,7 +10937,7 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-rimraf@^2.5.4:
+rimraf@^2.5.4, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -11174,6 +11312,11 @@ sisteransi@^1.0.5:
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
+slash@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+ integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+
slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@@ -11555,6 +11698,13 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
@@ -11804,6 +11954,13 @@ tlds@^1.234.0:
resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.234.0.tgz#f61fe73f6e85c51f8503181f47dcfbd18c6910db"
integrity sha512-TNDfeyDIC+oroH44bMbWC+Jn/2qNrfRvDK2EXt1icOXYG5NMqoRyUosADrukfb4D8lJ3S1waaBWSvQro0erdng==
+tmp@^0.0.33:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+ dependencies:
+ os-tmpdir "~1.0.2"
+
tmpl@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"