From dc47019d9d0f729def447837c77baea0f0cfb8a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Costa=20Lima?= Date: Mon, 1 Feb 2021 13:41:06 +0000 Subject: [PATCH] chore: adapt http client test suite for React Native (iOS and Android) --- packages/ipfs-http-client/package.json | 9 +++++- packages/ipfs-http-client/rn-test.config.js | 16 ++++++++++ packages/ipfs-http-client/rn-test.require.js | 10 +++++++ packages/ipfs-http-client/src/log/tail.js | 1 + .../ipfs-http-client/src/pubsub/subscribe.js | 6 +++- .../ipfs-http-client/test/constructor.spec.js | 4 ++- packages/ipfs-http-client/test/dag.spec.js | 29 +++++++++++++++---- packages/ipfs-http-client/test/files.spec.js | 5 +++- packages/ipfs-http-client/test/log.spec.js | 5 +++- 9 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 packages/ipfs-http-client/rn-test.config.js create mode 100644 packages/ipfs-http-client/rn-test.require.js diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 1555d808bb..bb41d84ec8 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -44,6 +44,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", "prepare": "aegir build --no-bundle", "coverage": "npx nyc -r html npm run test:node -- --bail", @@ -76,6 +78,7 @@ "nanoid": "^3.1.12", "native-abort-controller": "^1.0.3", "parse-duration": "^0.4.4", + "react-native-fetch-api": "^1.0.2", "stream-to-it": "^0.2.2", "uint8arrays": "^2.0.5" }, @@ -89,7 +92,11 @@ "it-concat": "^1.0.1", "it-first": "^1.0.4", "nock": "^13.0.2", - "rimraf": "^3.0.2" + "react-native-polyfill-globals": "^3.0.0", + "react-native-test-runner": "^3.0.2", + "rimraf": "^3.0.2", + "text-encoding": "^0.7.0", + "typescript": "4.0.x" }, "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..d416e2cd8f --- /dev/null +++ b/packages/ipfs-http-client/rn-test.config.js @@ -0,0 +1,16 @@ +'use strict' + +const path = require('path') + +module.exports = { + require: path.join(__dirname, 'rn-test.require.js'), + runner: 'mocha', + modules: [ + 'react-native-get-random-values', + 'react-native-url-polyfill', + 'web-streams-polyfill' + ], + patches: [{ + path: require.resolve('react-native-polyfill-globals/patches/react-native+0.63.3.patch') + }] +} 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/src/log/tail.js b/packages/ipfs-http-client/src/log/tail.js index ab20a35f41..ea4d48953f 100644 --- a/packages/ipfs-http-client/src/log/tail.js +++ b/packages/ipfs-http-client/src/log/tail.js @@ -10,6 +10,7 @@ module.exports = configure(api => { signal: options.signal, searchParams: toUrlSearchParams(options), headers: options.headers, + // Enables text streaming support for React Native when using https://github.com/react-native-community/fetch reactNative: { textStreaming: true } diff --git a/packages/ipfs-http-client/src/pubsub/subscribe.js b/packages/ipfs-http-client/src/pubsub/subscribe.js index ab5ee3c2db..6e8c3a8abd 100644 --- a/packages/ipfs-http-client/src/pubsub/subscribe.js +++ b/packages/ipfs-http-client/src/pubsub/subscribe.js @@ -34,7 +34,11 @@ module.exports = configure((api, options) => { arg: topic, ...options }), - headers: options.headers + headers: options.headers, + // Enables text streaming support for React Native when using https://github.com/react-native-community/fetch + reactNative: { + textStreaming: true + } }) .catch((err) => { // Initial subscribe fail, ensure we clean up diff --git a/packages/ipfs-http-client/test/constructor.spec.js b/packages/ipfs-http-client/test/constructor.spec.js index dc06022c4e..2206f72f63 100644 --- a/packages/ipfs-http-client/test/constructor.spec.js +++ b/packages/ipfs-http-client/test/constructor.spec.js @@ -7,11 +7,13 @@ const f = require('./utils/factory')() const ipfsClient = require('../src/index.js') 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 c23e884537..70053b587a 100644 --- a/packages/ipfs-http-client/test/log.spec.js +++ b/packages/ipfs-http-client/test/log.spec.js @@ -7,6 +7,8 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const f = require('./utils/factory')() const first = require('it-first') +const isReactNative = typeof navigator !== 'undefined' && navigator.product === 'ReactNative' + describe('.log', function () { this.timeout(100 * 1000) @@ -21,7 +23,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 }