diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 829bbbc2a6..c04d68cfae 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -43,6 +43,8 @@ "test:electron-renderer": "aegir test -t electron-renderer", "test:chrome": "aegir test -t browser -t webworker -- --browsers ChromeHeadless", "test:firefox": "aegir test -t browser -t webworker -- --browsers FirefoxHeadless", + "test:react-native:android": "aegir test -t react-native-android", + "test:react-native:ios": "aegir test -t react-native-ios", "lint": "aegir lint", "build": "npm run build:js && npm run build:types", "build:js": "aegir build", @@ -76,6 +78,7 @@ "nanoid": "^3.1.12", "native-abort-controller": "~0.0.3", "parse-duration": "^0.4.4", + "react-native-fetch-api": "^1.0.2", "stream-to-it": "^0.2.2", "uint8arrays": "^1.1.0" }, @@ -88,8 +91,14 @@ "it-all": "^1.0.4", "it-concat": "^1.0.1", "nock": "^13.0.2", + "react-native-get-random-values": "^1.5.1", + "react-native-polyfill-globals": "^3.0.0", + "react-native-test-runner": "^2.3.0", + "react-native-url-polyfill": "^1.2.0", "rimraf": "^3.0.2", - "typescript": "4.0.x" + "text-encoding": "^0.7.0", + "typescript": "4.0.x", + "web-streams-polyfill": "^3.0.1" }, "engines": { "node": ">=10.3.0", diff --git a/packages/ipfs-http-client/rn-test.config.js b/packages/ipfs-http-client/rn-test.config.js new file mode 100644 index 0000000000..30d497dd8a --- /dev/null +++ b/packages/ipfs-http-client/rn-test.config.js @@ -0,0 +1,17 @@ +'use strict' + +const path = require('path') + +module.exports = { + require: path.join(__dirname, 'rn-test.require.js'), + runner: 'mocha', + nativeModules: [ + 'react-native-get-random-values' + ], + patches: [{ + path: require.resolve('react-native-polyfill-globals/patches/react-native+0.63.3.patch') + }, { + path: require.resolve('react-native-polyfill-globals/patches/react-native-url-polyfill+1.2.0.patch'), + cwd: path.join(__dirname, '../..') + }] +} diff --git a/packages/ipfs-http-client/rn-test.require.js b/packages/ipfs-http-client/rn-test.require.js new file mode 100644 index 0000000000..94762df759 --- /dev/null +++ b/packages/ipfs-http-client/rn-test.require.js @@ -0,0 +1,10 @@ +'use strict' + +require('react-native-get-random-values') +const { polyfill: polyfillReadableStream } = require('react-native-polyfill-globals/src/readable-stream') +const { polyfill: polyfillEncoding } = require('react-native-polyfill-globals/src/encoding') +const { polyfill: polyfillURL } = require('react-native-polyfill-globals/src/url') + +polyfillReadableStream() +polyfillEncoding() +polyfillURL() diff --git a/packages/ipfs-http-client/test/constructor.spec.js b/packages/ipfs-http-client/test/constructor.spec.js index 004dcb2984..d5ac5977fa 100644 --- a/packages/ipfs-http-client/test/constructor.spec.js +++ b/packages/ipfs-http-client/test/constructor.spec.js @@ -8,11 +8,13 @@ const ipfsClient = require('../src/index.js') const globalThis = require('ipfs-utils/src/globalthis') const { isBrowser } = require('ipfs-utils/src/env') +const isReactNative = typeof navigator !== 'undefined' && navigator.product === 'ReactNative' + describe('ipfs-http-client constructor tests', () => { describe('parameter permuations', () => { it('none', () => { const ipfs = ipfsClient() - if (typeof self !== 'undefined') { + if (typeof self !== 'undefined' && !isReactNative) { const { hostname, port } = self.location expectConfig(ipfs, { host: hostname, port }) } else { diff --git a/packages/ipfs-http-client/test/dag.spec.js b/packages/ipfs-http-client/test/dag.spec.js index fb3bdc438b..9bb6b440b5 100644 --- a/packages/ipfs-http-client/test/dag.spec.js +++ b/packages/ipfs-http-client/test/dag.spec.js @@ -11,6 +11,8 @@ const CID = require('cids') const f = require('./utils/factory')() const ipfsHttpClient = require('../src') +const isReactNative = typeof navigator !== 'undefined' && navigator.product === 'ReactNative' + let ipfs describe('.dag', function () { @@ -21,7 +23,12 @@ describe('.dag', function () { after(() => f.clean()) - it('should be able to put and get a DAG node with format dag-pb', async () => { + it('should be able to put and get a DAG node with format dag-pb', async function () { + if (isReactNative) { + // React Native does not support constructing Blobs out of arrays + return this.skip() + } + const data = uint8ArrayFromString('some data') const node = new DAGNode(data) @@ -36,7 +43,12 @@ describe('.dag', function () { expect(result.value.Data).to.deep.equal(data) }) - it('should be able to put and get a DAG node with format dag-cbor', async () => { + it('should be able to put and get a DAG node with format dag-cbor', async function () { + if (isReactNative) { + // React Native does not support constructing Blobs out of arrays + return this.skip() + } + const cbor = { foo: 'dag-cbor-bar' } let cid = await ipfs.dag.put(cbor, { format: 'dag-cbor', hashAlg: 'sha2-256' }) @@ -50,7 +62,9 @@ describe('.dag', function () { }) it('should be able to put and get a DAG node with format raw', async () => { - const node = uint8ArrayFromString('some data') + const textData = 'some data' + const rawData = uint8ArrayFromString(textData) + const node = isReactNative ? textData : rawData let cid = await ipfs.dag.put(node, { format: 'raw', hashAlg: 'sha2-256' }) expect(cid.codec).to.equal('raw') @@ -59,7 +73,7 @@ describe('.dag', function () { const result = await ipfs.dag.get(cid) - expect(result.value).to.deep.equal(node) + expect(result.value).to.deep.equal(rawData) }) it('should error when missing DAG resolver for multicodec from requested CID', async () => { @@ -100,7 +114,12 @@ describe('.dag', function () { expect(askedToLoadFormat).to.be.true() }) - it('should allow formats to be specified without overwriting others', async () => { + it('should allow formats to be specified without overwriting others', async function () { + if (isReactNative) { + // React Native does not support constructing Blobs out of arrays + return this.skip() + } + const ipfs2 = ipfsHttpClient({ url: `http://${ipfs.apiHost}:${ipfs.apiPort}`, ipld: { diff --git a/packages/ipfs-http-client/test/files.spec.js b/packages/ipfs-http-client/test/files.spec.js index 10e2d1c844..013b48aebe 100644 --- a/packages/ipfs-http-client/test/files.spec.js +++ b/packages/ipfs-http-client/test/files.spec.js @@ -6,6 +6,8 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { expect } = require('aegir/utils/chai') const f = require('./utils/factory')() +const isReactNative = typeof navigator !== 'undefined' && navigator.product === 'ReactNative' + describe('.add', function () { this.timeout(20 * 1000) @@ -18,7 +20,8 @@ describe('.add', function () { after(() => f.clean()) it('should ignore metadata until https://github.com/ipfs/go-ipfs/issues/6920 is implemented', async () => { - const data = uint8ArrayFromString('some data') + const textData = 'some data' + const data = isReactNative ? textData : uint8ArrayFromString(textData) const result = await ipfs.add(data, { mode: 0o600, mtime: { diff --git a/packages/ipfs-http-client/test/log.spec.js b/packages/ipfs-http-client/test/log.spec.js index 814ff44887..c186c5ca15 100644 --- a/packages/ipfs-http-client/test/log.spec.js +++ b/packages/ipfs-http-client/test/log.spec.js @@ -6,6 +6,8 @@ const { expect } = require('aegir/utils/chai') const uint8ArrayFromString = require('uint8arrays/from-string') const f = require('./utils/factory')() +const isReactNative = typeof navigator !== 'undefined' && navigator.product === 'ReactNative' + describe('.log', function () { this.timeout(100 * 1000) @@ -20,7 +22,8 @@ describe('.log', function () { it('.log.tail', async () => { const i = setInterval(async () => { try { - await ipfs.add(uint8ArrayFromString('just adding some data to generate logs')) + const textData = 'just adding some data to generate logs' + await ipfs.add(isReactNative ? textData : uint8ArrayFromString(textData)) } catch (_) { // this can error if the test has finished and we're shutting down the node }