diff --git a/.size-limits.json b/.size-limits.json index 4777b873e7d..2ccf7b558b0 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { "dist/apollo-client.min.cjs": 40251, - "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 33061 + "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 33060 } diff --git a/package-lock.json b/package-lock.json index bbd7d39cbc3..63c9e55169c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "@testing-library/jest-dom": "6.4.6", "@testing-library/react": "15.0.7", "@testing-library/react-12": "npm:@testing-library/react@^12", + "@testing-library/react-render-stream": "1.0.3", "@testing-library/user-event": "14.5.2", "@tsconfig/node20": "20.1.4", "@types/bytes": "3.1.4", @@ -3576,6 +3577,313 @@ "@types/react": "^17" } }, + "node_modules/@testing-library/react-render-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@testing-library/react-render-stream/-/react-render-stream-1.0.3.tgz", + "integrity": "sha512-CltwyRRrpjZHKbAB6DwIcQo9mcPiGkmW4v3XHL7mWsI9xUHWzEbLzqiqErxuzuDQwI55LzjRF28aQLujrpMygw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^16.0.1", + "jsdom": "^25.0.1", + "rehackt": "^0.1.0" + }, + "peerDependencies": { + "@jest/globals": "*", + "expect": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/@testing-library/react": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz", + "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rrweb-cssom": "^0.7.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@testing-library/react-render-stream/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/@testing-library/react/node_modules/@testing-library/dom": { "version": "10.3.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.3.1.tgz", @@ -5456,10 +5764,11 @@ } }, "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true, + "license": "MIT" }, "node_modules/decode-uri-component": { "version": "0.4.1", @@ -9877,10 +10186,11 @@ } }, "node_modules/nwsapi": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", - "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==", - "dev": true + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "dev": true, + "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", @@ -10171,10 +10481,11 @@ } }, "node_modules/parse5": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", - "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, + "license": "MIT", "dependencies": { "entities": "^4.4.0" }, @@ -10653,10 +10964,11 @@ "dev": true }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11235,6 +11547,13 @@ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", "dev": true }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" + }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -12051,6 +12370,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tldts": { + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", + "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.50" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", + "dev": true, + "license": "MIT" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/package.json b/package.json index 0c611804a7a..afca1f6d5db 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "@testing-library/jest-dom": "6.4.6", "@testing-library/react": "15.0.7", "@testing-library/react-12": "npm:@testing-library/react@^12", + "@testing-library/react-render-stream": "1.0.3", "@testing-library/user-event": "14.5.2", "@tsconfig/node20": "20.1.4", "@types/bytes": "3.1.4", diff --git a/patches/eslint-plugin-testing-library+6.3.0.patch b/patches/eslint-plugin-testing-library+6.3.0.patch new file mode 100644 index 00000000000..f148d2d82f0 --- /dev/null +++ b/patches/eslint-plugin-testing-library+6.3.0.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/eslint-plugin-testing-library/dist/rules/render-result-naming-convention.js b/node_modules/eslint-plugin-testing-library/dist/rules/render-result-naming-convention.js +index d1bf177..b72688f 100644 +--- a/node_modules/eslint-plugin-testing-library/dist/rules/render-result-naming-convention.js ++++ b/node_modules/eslint-plugin-testing-library/dist/rules/render-result-naming-convention.js +@@ -5,7 +5,7 @@ const utils_1 = require("@typescript-eslint/utils"); + const create_testing_library_rule_1 = require("../create-testing-library-rule"); + const node_utils_1 = require("../node-utils"); + exports.RULE_NAME = 'render-result-naming-convention'; +-const ALLOWED_VAR_NAMES = ['view', 'utils']; ++const ALLOWED_VAR_NAMES = ['view', 'utils', 'renderStream']; + const ALLOWED_VAR_NAMES_TEXT = ALLOWED_VAR_NAMES.map((name) => `\`${name}\``) + .join(', ') + .replace(/, ([^,]*)$/, ', or $1'); diff --git a/src/config/jest/setup.ts b/src/config/jest/setup.ts index e6bbe2c43c0..fcae6fde31b 100644 --- a/src/config/jest/setup.ts +++ b/src/config/jest/setup.ts @@ -1,4 +1,8 @@ import gql from "graphql-tag"; +import { TextEncoder, TextDecoder } from "util"; +global.TextEncoder ??= TextEncoder; +// @ts-ignore +global.TextDecoder ??= TextDecoder; import "@testing-library/jest-dom"; import { loadErrorMessageHandler } from "../../dev/loadErrorMessageHandler.js"; import "../../testing/matchers/index.js"; diff --git a/src/react/components/__tests__/client/Query.test.tsx b/src/react/components/__tests__/client/Query.test.tsx index d8027c0c509..3d179dc037f 100644 --- a/src/react/components/__tests__/client/Query.test.tsx +++ b/src/react/components/__tests__/client/Query.test.tsx @@ -11,7 +11,7 @@ import { ApolloProvider } from "../../../context"; import { itAsync, MockedProvider, mockSingleLink } from "../../../../testing"; import { Query } from "../../Query"; import { QueryResult } from "../../../types/types"; -import { profile } from "../../../../testing/internal"; +import { renderToRenderStream } from "@testing-library/react-render-stream"; const allPeopleQuery: DocumentNode = gql` query people { @@ -1493,30 +1493,26 @@ describe("Query component", () => { return ( {(r: any) => { - ProfiledContainer.replaceSnapshot(r); + replaceSnapshot(r); return null; }} ); } - const ProfiledContainer = profile({ - Component: Container, - }); - - render( + const { takeRender, replaceSnapshot } = renderToRenderStream( - + ); { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(true); } { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(false); expect(snapshot.data.allPeople).toEqual(data.allPeople); // First result is loaded, run a refetch to get the second result @@ -1527,13 +1523,13 @@ describe("Query component", () => { } { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); // Waiting for the second result to load expect(snapshot.loading).toBe(true); } { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(false); expect(snapshot.error).toBeTruthy(); // The error arrived, run a refetch to get the third result @@ -1544,13 +1540,13 @@ describe("Query component", () => { } { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(true); expect(snapshot.error).toBeFalsy(); } { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(false); expect(snapshot.error).toBeFalsy(); expect(snapshot.data.allPeople).toEqual(dataTwo.allPeople); diff --git a/src/react/components/__tests__/client/Subscription.test.tsx b/src/react/components/__tests__/client/Subscription.test.tsx index 1604623810f..cc95def897b 100644 --- a/src/react/components/__tests__/client/Subscription.test.tsx +++ b/src/react/components/__tests__/client/Subscription.test.tsx @@ -8,7 +8,8 @@ import { ApolloProvider } from "../../../context"; import { ApolloLink, DocumentNode, Operation } from "../../../../link/core"; import { itAsync, MockSubscriptionLink } from "../../../../testing"; import { Subscription } from "../../Subscription"; -import { profile, spyOnConsole } from "../../../../testing/internal"; +import { spyOnConsole } from "../../../../testing/internal"; +import { renderToRenderStream } from "@testing-library/react-render-stream"; const results = [ "Luke Skywalker", @@ -428,26 +429,23 @@ describe("should update", () => { return ( {(r: any) => { - ProfiledContainer.replaceSnapshot(r); + replaceSnapshot(r); return null; }} ); } - const ProfiledContainer = profile({ - Component: Container, - }); - - const { rerender } = render( - - - - ); - + const { takeRender, replaceSnapshot, renderResultPromise } = + renderToRenderStream( + + + + ); + const { rerender } = await renderResultPromise; { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeTruthy(); expect(data).toBeUndefined(); } @@ -457,23 +455,23 @@ describe("should update", () => { { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeFalsy(); expect(data).toEqual(results[0].result.data); } - await expect(ProfiledContainer).not.toRerender({ timeout: 50 }); + await expect(takeRender).not.toRerender({ timeout: 50 }); rerender( - + ); { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeTruthy(); expect(data).toBeUndefined(); } @@ -483,12 +481,12 @@ describe("should update", () => { { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeFalsy(); expect(data).toEqual(results[1].result.data); } - await expect(ProfiledContainer).not.toRerender({ timeout: 50 }); + await expect(takeRender).not.toRerender({ timeout: 50 }); }); it("if the query changes", async () => { @@ -527,29 +525,24 @@ describe("should update", () => { return ( {(r: any) => { - ProfiledContainer.replaceSnapshot(r); + replaceSnapshot(r); return null; }} ); } - const ProfiledContainer = profile({ - Component: Container, - }); - - const { rerender } = render( - , - { + const { takeRender, replaceSnapshot, renderResultPromise } = + renderToRenderStream(, { wrapper: ({ children }) => ( {children} ), - } - ); + }); + const { rerender } = await renderResultPromise; { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeTruthy(); expect(data).toBeUndefined(); } @@ -558,18 +551,18 @@ describe("should update", () => { { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeFalsy(); expect(data).toEqual(results[0].result.data); } - await expect(ProfiledContainer).not.toRerender({ timeout: 50 }); + await expect(takeRender).not.toRerender({ timeout: 50 }); - rerender(); + rerender(); { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeTruthy(); expect(data).toBeUndefined(); } @@ -579,12 +572,12 @@ describe("should update", () => { { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeFalsy(); expect(data).toEqual(heroResult.result.data); } - await expect(ProfiledContainer).not.toRerender({ timeout: 50 }); + await expect(takeRender).not.toRerender({ timeout: 50 }); }); it("if the variables change", async () => { @@ -625,29 +618,24 @@ describe("should update", () => { variables={variables} > {(r: any) => { - ProfiledContainer.replaceSnapshot(r); + replaceSnapshot(r); return null; }} ); } - const ProfiledContainer = profile({ - Component: Container, - }); - - const { rerender } = render( - , - { + const { takeRender, renderResultPromise, replaceSnapshot } = + renderToRenderStream(, { wrapper: ({ children }) => ( {children} ), - } - ); + }); + const { rerender } = await renderResultPromise; { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeTruthy(); expect(data).toBeUndefined(); } @@ -656,19 +644,19 @@ describe("should update", () => { { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeFalsy(); expect(data).toEqual(dataLuke); } - await expect(ProfiledContainer).not.toRerender({ timeout: 50 }); + await expect(takeRender).not.toRerender({ timeout: 50 }); - rerender(); + rerender(); { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeTruthy(); expect(data).toBeUndefined(); } @@ -678,12 +666,12 @@ describe("should update", () => { { const { snapshot: { loading, data }, - } = await ProfiledContainer.takeRender(); + } = await takeRender(); expect(loading).toBeFalsy(); expect(data).toEqual(dataHan); } - await expect(ProfiledContainer).not.toRerender({ timeout: 50 }); + await expect(takeRender).not.toRerender({ timeout: 50 }); }); }); diff --git a/src/react/hoc/__tests__/queries/lifecycle.test.tsx b/src/react/hoc/__tests__/queries/lifecycle.test.tsx index cf460af964a..5fcf588c856 100644 --- a/src/react/hoc/__tests__/queries/lifecycle.test.tsx +++ b/src/react/hoc/__tests__/queries/lifecycle.test.tsx @@ -10,7 +10,7 @@ import { mockSingleLink } from "../../../../testing"; import { Query as QueryComponent } from "../../../components"; import { graphql } from "../../graphql"; import { ChildProps, DataValue } from "../../types"; -import { profile } from "../../../../testing/internal"; +import { renderToRenderStream } from "@testing-library/react-render-stream"; describe("[queries] lifecycle", () => { // lifecycle @@ -52,46 +52,44 @@ describe("[queries] lifecycle", () => { })( class extends React.Component> { render() { - ProfiledApp.replaceSnapshot(this.props.data!); + replaceSnapshot(this.props.data!); return null; } } ); - const ProfiledApp = profile, Vars>({ - Component: Container, - }); - - const { rerender } = render(, { - wrapper: ({ children }) => ( - {children} - ), - }); + const { takeRender, replaceSnapshot, renderResultPromise } = + renderToRenderStream>(, { + wrapper: ({ children }) => ( + {children} + ), + }); + const { rerender } = await renderResultPromise; { - const { snapshot } = await ProfiledApp.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot!.loading).toBe(true); expect(snapshot!.allPeople).toBe(undefined); } { - const { snapshot } = await ProfiledApp.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot!.loading).toBe(false); expect(snapshot!.variables).toEqual(variables1); expect(snapshot!.allPeople).toEqual(data1.allPeople); } - rerender(); + rerender(); { - const { snapshot } = await ProfiledApp.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot!.loading).toBe(true); expect(snapshot!.variables).toEqual(variables2); expect(snapshot!.allPeople).toBe(undefined); } { - const { snapshot } = await ProfiledApp.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot!.loading).toBe(false); expect(snapshot!.variables).toEqual(variables2); expect(snapshot!.allPeople).toEqual(data2.allPeople); diff --git a/src/react/hoc/__tests__/queries/loading.test.tsx b/src/react/hoc/__tests__/queries/loading.test.tsx index 387a6803fb5..5054d9ebb52 100644 --- a/src/react/hoc/__tests__/queries/loading.test.tsx +++ b/src/react/hoc/__tests__/queries/loading.test.tsx @@ -13,7 +13,7 @@ import { InMemoryCache as Cache } from "../../../../cache"; import { itAsync, mockSingleLink } from "../../../../testing"; import { graphql } from "../../graphql"; import { ChildProps, DataValue } from "../../types"; -import { profile } from "../../../../testing/internal"; +import { createRenderStream } from "@testing-library/react-render-stream"; describe("[queries] loading", () => { // networkStatus / loading @@ -407,13 +407,17 @@ describe("[queries] loading", () => { })( class extends React.Component> { render() { - ProfiledContainer.replaceSnapshot(this.props.data!); + replaceSnapshot(this.props.data!); return null; } } ); - const ProfiledContainer = profile< + const wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} + ); + + const { takeRender, replaceSnapshot, render } = createRenderStream< DataValue<{ allPeople: { people: { @@ -421,43 +425,39 @@ describe("[queries] loading", () => { }[]; }; }> - >({ - Component: Container, - }); + >(); - const App = ( - - - - ); - - render(App); + render(, { + wrapper, + }); { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(true); expect(snapshot.allPeople).toBeUndefined(); } { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(false); expect(snapshot.allPeople?.people[0].name).toMatch(/Darth Skywalker - /); } - render(App); + render(, { + wrapper, + }); // Loading after remount { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.loading).toBe(true); expect(snapshot.allPeople).toBeUndefined(); } { - const { snapshot } = await ProfiledContainer.takeRender(); + const { snapshot } = await takeRender(); // Fetched data loading after remount expect(snapshot.loading).toBe(false); expect(snapshot.allPeople!.people[0].name).toMatch(/Darth Skywalker - /); } - await expect(ProfiledContainer).toRenderExactlyTimes(5, { + await expect(takeRender).toRenderExactlyTimes(5, { timeout: 100, }); diff --git a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx index ac0ef98b87a..d0ebaa39016 100644 --- a/src/react/hooks/__tests__/useBackgroundQuery.test.tsx +++ b/src/react/hooks/__tests__/useBackgroundQuery.test.tsx @@ -46,20 +46,22 @@ import { import { skipToken } from "../constants"; import { PaginatedCaseData, - Profiler, SimpleCaseData, VariablesCaseData, VariablesCaseVariables, - createProfiler, - renderWithClient, - renderWithMocks, + createMockWrapper, + createClientWrapper, setupPaginatedCase, setupSimpleCase, setupVariablesCase, spyOnConsole, - useTrackRenders, } from "../../../testing/internal"; import { SubscribeToMoreFunction } from "../useSuspenseQuery"; +import { + RenderStream, + createRenderStream, + useTrackRenders, +} from "@testing-library/react-render-stream"; afterEach(() => { jest.useRealTimers(); @@ -70,7 +72,7 @@ function createDefaultTrackedComponents< TData = Snapshot["result"] extends UseReadQueryResult | null ? TData : unknown, ->(Profiler: Profiler) { +>(renderStream: RenderStream) { function SuspenseFallback() { useTrackRenders(); return
Loading
; @@ -78,7 +80,7 @@ function createDefaultTrackedComponents< function ReadQueryHook({ queryRef }: { queryRef: QueryRef }) { useTrackRenders(); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result: useReadQuery(queryRef), } as Partial); @@ -89,11 +91,11 @@ function createDefaultTrackedComponents< } function createTrackedErrorComponents( - Profiler: Profiler + renderStream: RenderStream ) { function ErrorFallback({ error }: FallbackProps) { useTrackRenders({ name: "ErrorFallback" }); - Profiler.mergeSnapshot({ error } as Partial); + renderStream.mergeSnapshot({ error } as Partial); return
Error
; } @@ -110,7 +112,7 @@ function createTrackedErrorComponents( } function createErrorProfiler() { - return createProfiler({ + return createRenderStream({ initialSnapshot: { error: null as Error | null, result: null as UseReadQueryResult | null, @@ -119,7 +121,7 @@ function createErrorProfiler() { } function createDefaultProfiler() { - return createProfiler({ + return createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -129,10 +131,10 @@ function createDefaultProfiler() { it("fetches a simple query with minimal config", async () => { const { query, mocks } = setupSimpleCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -145,16 +147,16 @@ it("fetches a simple query with minimal config", async () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -164,7 +166,7 @@ it("fetches a simple query with minimal config", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("tears down the query on unmount", async () => { @@ -173,9 +175,9 @@ it("tears down the query on unmount", async () => { link: new MockLink(mocks), cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -188,13 +190,15 @@ it("tears down the query on unmount", async () => { ); } - const { unmount } = renderWithClient(, { client, wrapper: Profiler }); + const { unmount } = renderStream.render(, { + wrapper: createClientWrapper(client), + }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -293,9 +297,9 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -312,13 +316,13 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); expect(client.getObservableQueries().size).toBe(1); expect(client).toHaveSuspenseCacheEntryUsing(query); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -332,7 +336,7 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { await act(() => user.click(screen.getByText("Toggle"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -348,7 +352,7 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -358,7 +362,7 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("auto resubscribes when mounting useReadQuery after naturally disposed by useReadQuery", async () => { @@ -369,9 +373,9 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -388,7 +392,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); const toggleButton = screen.getByText("Toggle"); @@ -396,13 +400,13 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use expect(client).toHaveSuspenseCacheEntryUsing(query); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -412,7 +416,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use } await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(client.getObservableQueries().size).toBe(0); @@ -427,7 +431,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use expect(client).toHaveSuspenseCacheEntryUsing(query); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -443,7 +447,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -453,7 +457,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("does not recreate queryRef and execute a network request when rerendering useBackgroundQuery after queryRef is disposed", async () => { @@ -474,9 +478,9 @@ it("does not recreate queryRef and execute a network request when rerendering us cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -495,18 +499,20 @@ it("does not recreate queryRef and execute a network request when rerendering us ); } - const { rerender } = renderWithClient(, { client, wrapper: Profiler }); + const { rerender } = renderStream.render(, { + wrapper: createClientWrapper(client), + }); const toggleButton = screen.getByText("Toggle"); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -516,18 +522,18 @@ it("does not recreate queryRef and execute a network request when rerendering us } await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); rerender(); - await Profiler.takeRender(); + await renderStream.takeRender(); expect(fetchCount).toBe(1); await act(() => user.click(toggleButton)); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -539,7 +545,7 @@ it("does not recreate queryRef and execute a network request when rerendering us expect(fetchCount).toBe(1); - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); // https://github.com/apollographql/apollo-client/issues/11815 @@ -561,14 +567,14 @@ it("does not recreate queryRef or execute a network request when rerendering use cache: new InMemoryCache(), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { queryRef: null as QueryRef | null, result: null as UseReadQueryResult | null, }, }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -577,7 +583,7 @@ it("does not recreate queryRef or execute a network request when rerendering use // another network request was made const [queryRef] = useBackgroundQuery(query, { fetchPolicy: "no-cache" }); - Profiler.mergeSnapshot({ queryRef }); + renderStream.mergeSnapshot({ queryRef }); return ( <> @@ -591,37 +597,32 @@ it("does not recreate queryRef or execute a network request when rerendering use ); } - renderWithClient(, { - client, - wrapper: ({ children }) => ( - - {children} - - ), + renderStream.render(, { + wrapper: createClientWrapper(client, React.StrictMode), }); const incrementButton = screen.getByText("Increment"); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } // eslint-disable-next-line testing-library/render-result-naming-convention - const firstRender = await Profiler.takeRender(); + const firstRender = await renderStream.takeRender(); const initialQueryRef = firstRender.snapshot.queryRef; await act(() => user.click(incrementButton)); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.queryRef).toBe(initialQueryRef); expect(fetchCount).toBe(1); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("disposes of the queryRef when unmounting before it is used by useReadQuery", async () => { @@ -631,7 +632,7 @@ it("disposes of the queryRef when unmounting before it is used by useReadQuery", cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); function App() { useTrackRenders(); @@ -640,13 +641,15 @@ it("disposes of the queryRef when unmounting before it is used by useReadQuery", return null; } - const { unmount } = renderWithClient(, { client, wrapper: Profiler }); + const { unmount } = renderStream.render(, { + wrapper: createClientWrapper(client), + }); expect(client.getObservableQueries().size).toBe(1); expect(client).toHaveSuspenseCacheEntryUsing(query); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -665,7 +668,7 @@ it("disposes of old queryRefs when changing variables before the queryRef is use cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); function App({ id }: { id: string }) { useTrackRenders(); @@ -674,9 +677,8 @@ it("disposes of old queryRefs when changing variables before the queryRef is use return null; } - const { rerender } = renderWithClient(, { - client, - wrapper: Profiler, + const { rerender } = renderStream.render(, { + wrapper: createClientWrapper(client), }); expect(client.getObservableQueries().size).toBe(1); @@ -685,7 +687,7 @@ it("disposes of old queryRefs when changing variables before the queryRef is use }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -710,7 +712,7 @@ it("does not prematurely dispose of the queryRef when using strict mode", async cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); function App() { useTrackRenders(); @@ -719,17 +721,12 @@ it("does not prematurely dispose of the queryRef when using strict mode", async return null; } - renderWithClient(, { - client, - wrapper: ({ children }) => ( - - {children} - - ), + renderStream.render(, { + wrapper: createClientWrapper(client, React.StrictMode), }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -748,7 +745,7 @@ it("disposes of the queryRef when unmounting before it is used by useReadQuery e }); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); function App() { useTrackRenders(); @@ -763,16 +760,15 @@ it("disposes of the queryRef when unmounting before it is used by useReadQuery e ); } - const { unmount } = renderWithClient(, { - client, - wrapper: Profiler, + const { unmount } = renderStream.render(, { + wrapper: createClientWrapper(client), }); const button = screen.getByText("Increment"); await act(() => user.click(button)); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -804,10 +800,10 @@ it("allows the client to be overridden", async () => { cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -820,16 +816,16 @@ it("allows the client to be overridden", async () => { ); } - renderWithClient(, { client: globalClient, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(globalClient) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -839,7 +835,7 @@ it("allows the client to be overridden", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("passes context to the link", async () => { @@ -858,10 +854,10 @@ it("passes context to the link", async () => { }); }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -876,16 +872,16 @@ it("passes context to the link", async () => { ); } - renderWithMocks(, { link, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ link }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { context: { valueA: "A", valueB: "B" } }, @@ -932,10 +928,10 @@ it('enables canonical results when canonizeResults is "true"', async () => { cache.writeQuery({ query, data: { results } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -948,11 +944,11 @@ it('enables canonical results when canonizeResults is "true"', async () => { ); } - renderWithMocks(, { cache, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ cache }) }); const { snapshot: { result }, - } = await Profiler.takeRender(); + } = await renderStream.takeRender(); const resultSet = new Set(result!.data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -1001,10 +997,10 @@ it("can disable canonical results when the cache's canonizeResults setting is tr cache.writeQuery({ query, data: { results } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1017,9 +1013,9 @@ it("can disable canonical results when the cache's canonizeResults setting is tr ); } - renderWithMocks(, { cache, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ cache }) }); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const result = snapshot.result!; const resultSet = new Set(result.data.results); @@ -1044,10 +1040,10 @@ it("returns initial cache data followed by network data when the fetch policy is cache.writeQuery({ query, data: { greeting: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1062,10 +1058,10 @@ it("returns initial cache data followed by network data when the fetch policy is ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1076,7 +1072,7 @@ it("returns initial cache data followed by network data when the fetch policy is } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1086,7 +1082,7 @@ it("returns initial cache data followed by network data when the fetch policy is }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("all data is present in the cache, no network request is made", async () => { @@ -1108,10 +1104,10 @@ it("all data is present in the cache, no network request is made", async () => { cache.writeQuery({ query, data: { greeting: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1126,9 +1122,9 @@ it("all data is present in the cache, no network request is made", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1139,7 +1135,7 @@ it("all data is present in the cache, no network request is made", async () => { expect(fetchCount).toBe(0); - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("partial data is present in the cache so it is ignored and network request is made", async () => { @@ -1165,10 +1161,10 @@ it("partial data is present in the cache so it is ignored and network request is cache.writeQuery({ query, data: { hello: "from cache" } }); } - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1183,16 +1179,16 @@ it("partial data is present in the cache so it is ignored and network request is ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { foo: "bar", hello: "from link" }, @@ -1201,7 +1197,7 @@ it("partial data is present in the cache so it is ignored and network request is }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("existing data in the cache is ignored when fetchPolicy is 'network-only'", async () => { @@ -1217,10 +1213,10 @@ it("existing data in the cache is ignored when fetchPolicy is 'network-only'", a cache.writeQuery({ query, data: { greeting: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1235,16 +1231,16 @@ it("existing data in the cache is ignored when fetchPolicy is 'network-only'", a ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "from link" }, @@ -1257,7 +1253,7 @@ it("existing data in the cache is ignored when fetchPolicy is 'network-only'", a ROOT_QUERY: { __typename: "Query", greeting: "from link" }, }); - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("fetches data from the network but does not update the cache when fetchPolicy is 'no-cache'", async () => { @@ -1273,10 +1269,10 @@ it("fetches data from the network but does not update the cache when fetchPolicy cache.writeQuery({ query, data: { greeting: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1289,16 +1285,16 @@ it("fetches data from the network but does not update the cache when fetchPolicy ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "from link" }, @@ -1311,7 +1307,7 @@ it("fetches data from the network but does not update the cache when fetchPolicy ROOT_QUERY: { __typename: "Query", greeting: "from cache" }, }); - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("works with startTransition to change variables", async () => { @@ -1363,7 +1359,7 @@ it("works with startTransition to change variables", async () => { cache: new InMemoryCache(), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { isPending: false, result: null as UseReadQueryResult | null, @@ -1371,7 +1367,7 @@ it("works with startTransition to change variables", async () => { }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1381,7 +1377,7 @@ it("works with startTransition to change variables", async () => { variables: { id }, }); - Profiler.mergeSnapshot({ isPending }); + renderStream.mergeSnapshot({ isPending }); return ( <> @@ -1403,16 +1399,16 @@ it("works with startTransition to change variables", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot).toEqual({ @@ -1428,7 +1424,7 @@ it("works with startTransition to change variables", async () => { await act(() => user.click(screen.getByText("Change todo"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); // startTransition will avoid rendering the suspense fallback for already // revealed content if the state update inside the transition causes the @@ -1450,7 +1446,7 @@ it("works with startTransition to change variables", async () => { } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); // Eventually we should see the updated todo content once its done // suspending. @@ -1502,10 +1498,10 @@ it('does not suspend deferred queries with data in the cache and using a "cache- }); const client = new ApolloClient({ cache, link }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1520,10 +1516,10 @@ it('does not suspend deferred queries with data in the cache and using a "cache- ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1549,7 +1545,7 @@ it('does not suspend deferred queries with data in the cache and using a "cache- }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1581,7 +1577,7 @@ it('does not suspend deferred queries with data in the cache and using a "cache- }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1597,7 +1593,7 @@ it('does not suspend deferred queries with data in the cache and using a "cache- }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("reacts to cache updates", async () => { @@ -1608,10 +1604,10 @@ it("reacts to cache updates", async () => { cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1624,16 +1620,16 @@ it("reacts to cache updates", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1648,7 +1644,7 @@ it("reacts to cache updates", async () => { }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1664,7 +1660,7 @@ it("reacts to cache updates", async () => { }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1674,16 +1670,16 @@ it("reacts to cache updates", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("reacts to variables updates", async () => { const { query, mocks } = setupVariablesCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App({ id }: { id: string }) { useTrackRenders(); @@ -1696,19 +1692,18 @@ it("reacts to variables updates", async () => { ); } - const { rerender } = renderWithMocks(, { - mocks, - wrapper: Profiler, + const { rerender } = renderStream.render(, { + wrapper: createMockWrapper({ mocks }), }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1722,13 +1717,13 @@ it("reacts to variables updates", async () => { rerender(); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1739,15 +1734,15 @@ it("reacts to variables updates", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("does not suspend when `skip` is true", async () => { const { query, mocks } = setupSimpleCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1760,21 +1755,21 @@ it("does not suspend when `skip` is true", async () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("does not suspend when using `skipToken` in options", async () => { const { query, mocks } = setupSimpleCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1787,22 +1782,22 @@ it("does not suspend when using `skipToken` in options", async () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("suspends when `skip` becomes `false` after it was `true`", async () => { const { query, mocks } = setupSimpleCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1819,10 +1814,10 @@ it("suspends when `skip` becomes `false` after it was `true`", async () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -1830,13 +1825,13 @@ it("suspends when `skip` becomes `false` after it was `true`", async () => { await act(() => user.click(screen.getByText("Run query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1845,16 +1840,16 @@ it("suspends when `skip` becomes `false` after it was `true`", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("suspends when switching away from `skipToken` in options", async () => { const { query, mocks } = setupSimpleCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1871,10 +1866,10 @@ it("suspends when switching away from `skipToken` in options", async () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -1882,13 +1877,13 @@ it("suspends when switching away from `skipToken` in options", async () => { await act(() => user.click(screen.getByText("Run query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1897,16 +1892,16 @@ it("suspends when switching away from `skipToken` in options", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("renders skip result, does not suspend, and maintains `data` when `skip` becomes `true` after it was `false`", async () => { const { query, mocks } = setupSimpleCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1923,16 +1918,16 @@ it("renders skip result, does not suspend, and maintains `data` when `skip` beco ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1944,7 +1939,7 @@ it("renders skip result, does not suspend, and maintains `data` when `skip` beco await act(() => user.click(screen.getByText("Toggle skip"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1954,15 +1949,15 @@ it("renders skip result, does not suspend, and maintains `data` when `skip` beco }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("renders skip result, does not suspend, and maintains `data` when switching back to `skipToken`", async () => { const { query, mocks } = setupSimpleCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -1979,16 +1974,16 @@ it("renders skip result, does not suspend, and maintains `data` when switching b ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2000,7 +1995,7 @@ it("renders skip result, does not suspend, and maintains `data` when switching b await act(() => user.click(screen.getByText("Toggle skip"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -2010,7 +2005,7 @@ it("renders skip result, does not suspend, and maintains `data` when switching b }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("does not make network requests when `skip` is `true`", async () => { @@ -2041,9 +2036,9 @@ it("does not make network requests when `skip` is `true`", async () => { cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -2060,10 +2055,10 @@ it("does not make network requests when `skip` is `true`", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial skipped result - await Profiler.takeRender(); + await renderStream.takeRender(); expect(fetchCount).toBe(0); // Toggle skip to `false` @@ -2071,13 +2066,13 @@ it("does not make network requests when `skip` is `true`", async () => { expect(fetchCount).toBe(1); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2091,7 +2086,7 @@ it("does not make network requests when `skip` is `true`", async () => { expect(fetchCount).toBe(1); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2103,9 +2098,9 @@ it("does not make network requests when `skip` is `true`", async () => { it("does not make network requests when `skipToken` is used", async () => { const { query, mocks } = setupSimpleCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const user = userEvent.setup(); let fetchCount = 0; @@ -2147,10 +2142,10 @@ it("does not make network requests when `skipToken` is used", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial skipped result - await Profiler.takeRender(); + await renderStream.takeRender(); expect(fetchCount).toBe(0); // Toggle skip to `false` @@ -2158,13 +2153,13 @@ it("does not make network requests when `skipToken` is used", async () => { expect(fetchCount).toBe(1); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2178,7 +2173,7 @@ it("does not make network requests when `skipToken` is used", async () => { expect(fetchCount).toBe(1); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2190,9 +2185,9 @@ it("does not make network requests when `skipToken` is used", async () => { it("does not make network requests when `skipToken` is used in strict mode", async () => { const { query, mocks } = setupSimpleCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const user = userEvent.setup(); let fetchCount = 0; @@ -2234,25 +2229,20 @@ it("does not make network requests when `skipToken` is used in strict mode", asy ); } - renderWithClient(, { - client, - wrapper: ({ children }) => ( - - {children} - - ), + renderStream.render(, { + wrapper: createClientWrapper(client, React.StrictMode), }); // initial skipped result - await Profiler.takeRender(); + await renderStream.takeRender(); expect(fetchCount).toBe(0); // Toggle skip to `false` await act(() => user.click(screen.getByText("Toggle skip"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2267,7 +2257,7 @@ it("does not make network requests when `skipToken` is used in strict mode", asy await act(() => user.click(screen.getByText("Toggle skip"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2278,14 +2268,14 @@ it("does not make network requests when `skipToken` is used in strict mode", asy expect(fetchCount).toBe(1); - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("does not make network requests when using `skip` option in strict mode", async () => { const { query, mocks } = setupSimpleCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const user = userEvent.setup(); let fetchCount = 0; @@ -2327,25 +2317,20 @@ it("does not make network requests when using `skip` option in strict mode", asy ); } - renderWithClient(, { - client, - wrapper: ({ children }) => ( - - {children} - - ), + renderStream.render(, { + wrapper: createClientWrapper(client, React.StrictMode), }); // initial skipped result - await Profiler.takeRender(); + await renderStream.takeRender(); expect(fetchCount).toBe(0); // Toggle skip to `false` await act(() => user.click(screen.getByText("Toggle skip"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2360,7 +2345,7 @@ it("does not make network requests when using `skip` option in strict mode", asy await act(() => user.click(screen.getByText("Toggle skip"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2371,7 +2356,7 @@ it("does not make network requests when using `skip` option in strict mode", asy expect(fetchCount).toBe(1); - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("result is referentially stable", async () => { @@ -2379,9 +2364,9 @@ it("result is referentially stable", async () => { let result: UseReadQueryResult | null = null; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -2394,16 +2379,18 @@ it("result is referentially stable", async () => { ); } - const { rerender } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { rerender } = renderStream.render(, { + wrapper: createMockWrapper({ mocks }), + }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2417,7 +2404,7 @@ it("result is referentially stable", async () => { rerender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toBe(result); } @@ -2427,14 +2414,14 @@ it("`skip` option works with `startTransition`", async () => { const { query, mocks } = setupSimpleCase(); const user = userEvent.setup(); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { isPending: false, result: null as UseReadQueryResult | null, }, }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -2442,7 +2429,7 @@ it("`skip` option works with `startTransition`", async () => { const [isPending, startTransition] = React.useTransition(); const [queryRef] = useBackgroundQuery(query, { skip }); - Profiler.mergeSnapshot({ isPending }); + renderStream.mergeSnapshot({ isPending }); return ( <> @@ -2463,10 +2450,10 @@ it("`skip` option works with `startTransition`", async () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -2475,7 +2462,7 @@ it("`skip` option works with `startTransition`", async () => { await act(() => user.click(screen.getByText("Toggle skip"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); expect(snapshot).toEqual({ @@ -2485,7 +2472,7 @@ it("`skip` option works with `startTransition`", async () => { } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -2498,14 +2485,14 @@ it("`skip` option works with `startTransition`", async () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("`skipToken` works with `startTransition`", async () => { const { query, mocks } = setupSimpleCase(); const user = userEvent.setup(); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { isPending: false, result: null as UseReadQueryResult | null, @@ -2513,7 +2500,7 @@ it("`skipToken` works with `startTransition`", async () => { }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -2521,7 +2508,7 @@ it("`skipToken` works with `startTransition`", async () => { const [isPending, startTransition] = React.useTransition(); const [queryRef] = useBackgroundQuery(query, skip ? skipToken : undefined); - Profiler.mergeSnapshot({ isPending }); + renderStream.mergeSnapshot({ isPending }); return ( <> @@ -2542,10 +2529,10 @@ it("`skipToken` works with `startTransition`", async () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -2554,7 +2541,7 @@ it("`skipToken` works with `startTransition`", async () => { await act(() => user.click(screen.getByText("Toggle skip"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); expect(snapshot).toEqual({ @@ -2564,7 +2551,7 @@ it("`skipToken` works with `startTransition`", async () => { } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -2577,7 +2564,7 @@ it("`skipToken` works with `startTransition`", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("applies `errorPolicy` on next fetch when it changes between renders", async () => { @@ -2599,10 +2586,10 @@ it("applies `errorPolicy` on next fetch when it changes between renders", async }, ]; - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + createDefaultTrackedComponents(renderStream); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); function App() { useTrackRenders(); @@ -2626,13 +2613,13 @@ it("applies `errorPolicy` on next fetch when it changes between renders", async ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -2642,13 +2629,13 @@ it("applies `errorPolicy` on next fetch when it changes between renders", async } await act(() => user.click(screen.getByText("Change error policy"))); - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Refetch greeting"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot).toEqual({ @@ -2687,9 +2674,9 @@ it("applies `context` on next fetch when it changes between renders", async () = const client = new ApolloClient({ link, cache: new InMemoryCache() }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -2709,16 +2696,16 @@ it("applies `context` on next fetch when it changes between renders", async () = ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { context: { phase: "initial" } }, @@ -2728,13 +2715,13 @@ it("applies `context` on next fetch when it changes between renders", async () = } await act(() => user.click(screen.getByText("Update context"))); - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { context: { phase: "rerender" } }, @@ -2789,9 +2776,9 @@ it("returns canonical results immediately when `canonizeResults` changes from `f data: { results }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -2812,10 +2799,10 @@ it("returns canonical results immediately when `canonizeResults` changes from `f ); } - renderWithMocks(, { cache, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ cache }) }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const result = snapshot.result!; const resultSet = new Set(result.data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -2829,7 +2816,7 @@ it("returns canonical results immediately when `canonizeResults` changes from `f await act(() => user.click(screen.getByText("Canonize results"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const result = snapshot.result!; const resultSet = new Set(result.data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -2895,9 +2882,9 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -2927,13 +2914,13 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -2944,10 +2931,10 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren } await act(() => user.click(screen.getByText("Refetch next"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] }, @@ -2964,13 +2951,13 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren } await act(() => user.click(screen.getByText("Change refetch write policy"))); - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Refetch last"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [31, 37, 41, 43, 47] }, @@ -3050,9 +3037,9 @@ it("applies `returnPartialData` on next fetch when it changes between renders", cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -3071,13 +3058,13 @@ it("applies `returnPartialData` on next fetch when it changes between renders", ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3089,7 +3076,7 @@ it("applies `returnPartialData` on next fetch when it changes between renders", } await act(() => user.click(screen.getByText("Update partial data"))); - await Profiler.takeRender(); + await renderStream.takeRender(); cache.modify({ id: cache.identify({ __typename: "Character", id: "1" }), @@ -3099,7 +3086,7 @@ it("applies `returnPartialData` on next fetch when it changes between renders", }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { __typename: "Character", id: "1" } }, @@ -3109,7 +3096,7 @@ it("applies `returnPartialData` on next fetch when it changes between renders", } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3148,9 +3135,9 @@ it("applies updated `fetchPolicy` on next fetch when it changes between renders" cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { const [fetchPolicy, setFetchPolicy] = @@ -3174,10 +3161,10 @@ it("applies updated `fetchPolicy` on next fetch when it changes between renders" ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3194,7 +3181,7 @@ it("applies updated `fetchPolicy` on next fetch when it changes between renders" await act(() => user.click(screen.getByText("Change fetch policy"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); // ensure we haven't changed the result yet just by changing the fetch policy expect(snapshot.result).toEqual({ @@ -3211,10 +3198,10 @@ it("applies updated `fetchPolicy` on next fetch when it changes between renders" } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3283,10 +3270,10 @@ it("properly handles changing options along with changing `variables`", async () cache, }); - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + createDefaultTrackedComponents(renderStream); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); function App() { useTrackRenders(); @@ -3311,10 +3298,10 @@ it("properly handles changing options along with changing `variables`", async () ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -3333,10 +3320,10 @@ it("properly handles changing options along with changing `variables`", async () } await act(() => user.click(screen.getByText("Get second character"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -3357,7 +3344,7 @@ it("properly handles changing options along with changing `variables`", async () await act(() => user.click(screen.getByText("Get first character"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -3376,10 +3363,10 @@ it("properly handles changing options along with changing `variables`", async () } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); // Ensure we render the inline error instead of the error boundary, which // tells us the error policy was properly applied. @@ -3421,9 +3408,9 @@ it('does not suspend when partial data is in the cache and using a "cache-first" cache, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -3440,10 +3427,10 @@ it('does not suspend when partial data is in the cache and using a "cache-first" ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3454,7 +3441,7 @@ it('does not suspend when partial data is in the cache and using a "cache-first" } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3466,7 +3453,7 @@ it('does not suspend when partial data is in the cache and using a "cache-first" }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('suspends and does not use partial data from other variables in the cache when changing variables and using a "cache-first" fetch policy with returnPartialData: true', async () => { @@ -3487,9 +3474,9 @@ it('suspends and does not use partial data from other variables in the cache whe variables: { id: "1" }, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App({ id }: { id: string }) { useTrackRenders(); @@ -3506,14 +3493,12 @@ it('suspends and does not use partial data from other variables in the cache whe ); } - const { rerender } = renderWithMocks(, { - cache, - mocks, - wrapper: Profiler, + const { rerender } = renderStream.render(, { + wrapper: createMockWrapper({ cache, mocks }), }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3524,7 +3509,7 @@ it('suspends and does not use partial data from other variables in the cache whe } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3539,13 +3524,13 @@ it('suspends and does not use partial data from other variables in the cache whe rerender(); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3557,7 +3542,7 @@ it('suspends and does not use partial data from other variables in the cache whe }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('suspends when partial data is in the cache and using a "network-only" fetch policy with returnPartialData', async () => { @@ -3584,9 +3569,9 @@ it('suspends when partial data is in the cache and using a "network-only" fetch cache, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -3603,16 +3588,16 @@ it('suspends when partial data is in the cache and using a "network-only" fetch ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3623,7 +3608,7 @@ it('suspends when partial data is in the cache and using a "network-only" fetch }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('suspends when partial data is in the cache and using a "no-cache" fetch policy with returnPartialData', async () => { @@ -3651,9 +3636,9 @@ it('suspends when partial data is in the cache and using a "no-cache" fetch poli cache, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -3670,16 +3655,16 @@ it('suspends when partial data is in the cache and using a "no-cache" fetch poli ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3690,7 +3675,7 @@ it('suspends when partial data is in the cache and using a "no-cache" fetch poli }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('warns when using returnPartialData with a "no-cache" fetch policy', async () => { @@ -3751,9 +3736,9 @@ it('does not suspend when partial data is in the cache and using a "cache-and-ne cache, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -3770,10 +3755,10 @@ it('does not suspend when partial data is in the cache and using a "cache-and-ne ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3784,7 +3769,7 @@ it('does not suspend when partial data is in the cache and using a "cache-and-ne } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3796,7 +3781,7 @@ it('does not suspend when partial data is in the cache and using a "cache-and-ne }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('suspends and does not use partial data when changing variables and using a "cache-and-network" fetch policy with returnPartialData', async () => { @@ -3817,9 +3802,9 @@ it('suspends and does not use partial data when changing variables and using a " variables: { id: "1" }, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App({ id }: { id: string }) { useTrackRenders(); @@ -3836,14 +3821,12 @@ it('suspends and does not use partial data when changing variables and using a " ); } - const { rerender } = renderWithMocks(, { - cache, - mocks, - wrapper: Profiler, + const { rerender } = renderStream.render(, { + wrapper: createMockWrapper({ cache, mocks }), }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3854,7 +3837,7 @@ it('suspends and does not use partial data when changing variables and using a " } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3869,13 +3852,13 @@ it('suspends and does not use partial data when changing variables and using a " rerender(); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3887,7 +3870,7 @@ it('suspends and does not use partial data when changing variables and using a " }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('does not suspend deferred queries with partial data in the cache and using a "cache-first" fetch policy with `returnPartialData`', async () => { @@ -3935,9 +3918,9 @@ it('does not suspend deferred queries with partial data in the cache and using a const client = new ApolloClient({ link, cache }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -3953,10 +3936,10 @@ it('does not suspend deferred queries with partial data in the cache and using a ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3981,7 +3964,7 @@ it('does not suspend deferred queries with partial data in the cache and using a }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4016,7 +3999,7 @@ it('does not suspend deferred queries with partial data in the cache and using a ); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4032,7 +4015,7 @@ it('does not suspend deferred queries with partial data in the cache and using a }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it.each([ @@ -4049,9 +4032,9 @@ it.each([ link: new MockLink(mocks), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -4064,23 +4047,18 @@ it.each([ ); } - renderWithClient(, { - client, - wrapper: ({ children }) => ( - - {children} - - ), + renderStream.render(, { + wrapper: createClientWrapper(client, React.StrictMode), }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -4095,7 +4073,7 @@ it.each([ }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Updated hello" }, @@ -4104,7 +4082,7 @@ it.each([ }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); } ); @@ -4112,9 +4090,9 @@ describe("refetch", () => { it("re-suspends when calling `refetch`", async () => { const { query, mocks: defaultMocks } = setupVariablesCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const mocks: MockedResponse[] = [ ...defaultMocks, @@ -4149,16 +4127,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -4177,13 +4155,13 @@ describe("refetch", () => { { // parent component re-suspends - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -4198,15 +4176,15 @@ describe("refetch", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("re-suspends when calling `refetch` with new variables", async () => { const { query, mocks } = setupVariablesCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -4224,16 +4202,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -4251,13 +4229,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -4272,15 +4250,15 @@ describe("refetch", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("re-suspends multiple times when calling `refetch` multiple times", async () => { const { query, mocks: defaultMocks } = setupVariablesCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const mocks: MockedResponse[] = [ ...defaultMocks, @@ -4328,16 +4306,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -4353,13 +4331,13 @@ describe("refetch", () => { await act(() => user.click(button)); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -4377,13 +4355,13 @@ describe("refetch", () => { await act(() => user.click(button)); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -4398,7 +4376,7 @@ describe("refetch", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("throws errors when errors are returned after calling `refetch`", async () => { @@ -4416,10 +4394,10 @@ describe("refetch", () => { }, ]; - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + createDefaultTrackedComponents(renderStream); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); function App() { useTrackRenders(); @@ -4439,16 +4417,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -4469,13 +4447,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ErrorFallback"]); expect(snapshot.error).toEqual( @@ -4485,7 +4463,7 @@ describe("refetch", () => { ); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('ignores errors returned after calling `refetch` when errorPolicy is set to "ignore"', async () => { @@ -4502,10 +4480,10 @@ describe("refetch", () => { }, ]; - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + createDefaultTrackedComponents(renderStream); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); function App() { useTrackRenders(); @@ -4526,16 +4504,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -4556,13 +4534,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -4580,7 +4558,7 @@ describe("refetch", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('returns errors after calling `refetch` when errorPolicy is set to "all"', async () => { @@ -4597,10 +4575,10 @@ describe("refetch", () => { }, ]; - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + createDefaultTrackedComponents(renderStream); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); function App() { useTrackRenders(); @@ -4621,16 +4599,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -4651,13 +4629,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -4677,7 +4655,7 @@ describe("refetch", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it('handles partial data results after calling `refetch` when errorPolicy is set to "all"', async () => { @@ -4695,10 +4673,10 @@ describe("refetch", () => { }, ]; - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + createDefaultTrackedComponents(renderStream); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); function App() { useTrackRenders(); @@ -4719,16 +4697,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -4749,13 +4727,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ error: null, @@ -4775,7 +4753,7 @@ describe("refetch", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("can refetch after error is encountered", async () => { @@ -4821,12 +4799,12 @@ describe("refetch", () => { }, ]; - const Profiler = createErrorProfiler(); - const { SuspenseFallback } = createDefaultTrackedComponents(Profiler); + const renderStream = createErrorProfiler(); + const { SuspenseFallback } = createDefaultTrackedComponents(renderStream); function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) { useTrackRenders(); - Profiler.mergeSnapshot({ error }); + renderStream.mergeSnapshot({ error }); return ; } @@ -4851,15 +4829,15 @@ describe("refetch", () => { function Todo({ queryRef }: { queryRef: QueryRef }) { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } @@ -4867,7 +4845,7 @@ describe("refetch", () => { { // Disable error message shown in the console due to an uncaught error. using _consoleSpy = spyOnConsole("error"); - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ErrorFallback]); expect(snapshot).toEqual({ @@ -4881,13 +4859,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Retry"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([Todo]); expect(snapshot).toEqual({ @@ -4951,12 +4929,12 @@ describe("refetch", () => { }, ]; - const Profiler = createErrorProfiler(); - const { SuspenseFallback } = createDefaultTrackedComponents(Profiler); + const renderStream = createErrorProfiler(); + const { SuspenseFallback } = createDefaultTrackedComponents(renderStream); function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) { useTrackRenders(); - Profiler.mergeSnapshot({ error }); + renderStream.mergeSnapshot({ error }); return ; } @@ -4981,21 +4959,21 @@ describe("refetch", () => { function Todo({ queryRef }: { queryRef: QueryRef }) { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ErrorFallback]); expect(snapshot).toEqual({ @@ -5009,13 +4987,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Retry"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ErrorFallback]); expect(snapshot).toEqual({ @@ -5069,7 +5047,7 @@ describe("refetch", () => { }, ]; - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { isPending: false, result: null as UseReadQueryResult | null, @@ -5077,7 +5055,7 @@ describe("refetch", () => { }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -5086,7 +5064,7 @@ describe("refetch", () => { variables: { id: "1" }, }); - Profiler.mergeSnapshot({ isPending }); + renderStream.mergeSnapshot({ isPending }); return ( <> @@ -5106,16 +5084,16 @@ describe("refetch", () => { ); } - renderWithMocks(, { mocks, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ mocks }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ isPending: false, @@ -5138,7 +5116,7 @@ describe("refetch", () => { // suspends until the todo is finished loading. Seeing the suspense // fallback is an indication that we are suspending the component too late // in the process. - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -5152,7 +5130,7 @@ describe("refetch", () => { } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); // Eventually we should see the updated todo content once its done // suspending. @@ -5212,9 +5190,9 @@ describe("refetch", () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const client = new ApolloClient({ link: new MockLink(mocks), @@ -5238,16 +5216,16 @@ describe("refetch", () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -5260,13 +5238,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] }, @@ -5332,9 +5310,9 @@ describe("refetch", () => { cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -5352,16 +5330,16 @@ describe("refetch", () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -5374,13 +5352,13 @@ describe("refetch", () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [13, 17, 19, 23, 29] }, @@ -5408,9 +5386,9 @@ describe("fetchMore", () => { }, }); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -5430,16 +5408,18 @@ describe("fetchMore", () => { ); } - renderWithMocks(, { cache, link, wrapper: Profiler }); + renderStream.render(, { + wrapper: createMockWrapper({ cache, link }), + }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { letters: [ @@ -5455,13 +5435,13 @@ describe("fetchMore", () => { await act(() => user.click(screen.getByText("Fetch more"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { letters: [ @@ -5474,15 +5454,15 @@ describe("fetchMore", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("properly uses `updateQuery` when calling `fetchMore`", async () => { const { query, link } = setupPaginatedCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); @@ -5509,16 +5489,16 @@ describe("fetchMore", () => { ); } - renderWithMocks(, { link, wrapper: Profiler }); + renderStream.render(, { wrapper: createMockWrapper({ link }) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { letters: [ @@ -5534,13 +5514,13 @@ describe("fetchMore", () => { await act(() => user.click(screen.getByText("Fetch more"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -5556,15 +5536,15 @@ describe("fetchMore", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("properly uses cache field policies when calling `fetchMore` without `updateQuery`", async () => { const { query, link } = setupPaginatedCase(); const user = userEvent.setup(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const client = new ApolloClient({ link, @@ -5597,16 +5577,16 @@ describe("fetchMore", () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { letters: [ @@ -5622,13 +5602,13 @@ describe("fetchMore", () => { await act(() => user.click(screen.getByText("Fetch more"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -5644,7 +5624,7 @@ describe("fetchMore", () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("`fetchMore` works with startTransition to allow React to show stale UI until finished suspending", async () => { @@ -5710,14 +5690,14 @@ describe("fetchMore", () => { }, ]; - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { isPending: false, result: null as UseReadQueryResult | null, }, }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const client = new ApolloClient({ link: new MockLink(mocks), @@ -5739,7 +5719,7 @@ describe("fetchMore", () => { variables: { offset: 0 }, }); - Profiler.mergeSnapshot({ isPending }); + renderStream.mergeSnapshot({ isPending }); return ( <> @@ -5759,16 +5739,16 @@ describe("fetchMore", () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ isPending: false, @@ -5799,7 +5779,7 @@ describe("fetchMore", () => { // Here we should not see the suspense fallback while the component suspends // until the todo is finished loading. Seeing the suspense fallback is an // indication that we are suspending the component too late in the process. - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -5824,7 +5804,7 @@ describe("fetchMore", () => { { // Eventually we should see the updated todos content once its done // suspending. - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -5852,7 +5832,7 @@ describe("fetchMore", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); // https://github.com/apollographql/apollo-client/issues/11708 @@ -5917,7 +5897,7 @@ describe("fetchMore", () => { }, ]; - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { isPending: false, result: null as UseReadQueryResult | null, @@ -5925,7 +5905,7 @@ describe("fetchMore", () => { }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); const client = new ApolloClient({ link: new MockLink(mocks), @@ -5952,7 +5932,7 @@ describe("fetchMore", () => { variables: { offset: 0 }, }); - Profiler.mergeSnapshot({ isPending }); + renderStream.mergeSnapshot({ isPending }); return ( <> @@ -5972,16 +5952,16 @@ describe("fetchMore", () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ isPending: false, @@ -6005,7 +5985,7 @@ describe("fetchMore", () => { await act(() => user.click(screen.getByText("Load more"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -6028,7 +6008,7 @@ describe("fetchMore", () => { } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -6056,7 +6036,7 @@ describe("fetchMore", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("can subscribe to subscriptions and react to cache updates via `subscribeToMore`", async () => { @@ -6101,7 +6081,7 @@ describe("fetchMore", () => { const client = new ApolloClient({ link, cache: new InMemoryCache() }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { subscribeToMore: null as SubscribeToMoreFunction< SimpleCaseData, @@ -6112,13 +6092,13 @@ describe("fetchMore", () => { }); const { SuspenseFallback, ReadQueryHook } = - createDefaultTrackedComponents(Profiler); + createDefaultTrackedComponents(renderStream); function App() { useTrackRenders(); const [queryRef, { subscribeToMore }] = useBackgroundQuery(query); - Profiler.mergeSnapshot({ subscribeToMore }); + renderStream.mergeSnapshot({ subscribeToMore }); return ( }> @@ -6127,16 +6107,16 @@ describe("fetchMore", () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -6153,7 +6133,7 @@ describe("fetchMore", () => { return { greeting: data.greetingUpdated }; }); - const { snapshot } = Profiler.getCurrentRender(); + const { snapshot } = renderStream.getCurrentRender(); snapshot.subscribeToMore!({ document: subscription, updateQuery }); @@ -6166,7 +6146,7 @@ describe("fetchMore", () => { }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ diff --git a/src/react/hooks/__tests__/useFragment.test.tsx b/src/react/hooks/__tests__/useFragment.test.tsx index 378f48f9a4d..bd0c6ad74a5 100644 --- a/src/react/hooks/__tests__/useFragment.test.tsx +++ b/src/react/hooks/__tests__/useFragment.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable testing-library/render-result-naming-convention */ import * as React from "react"; import { render, @@ -29,7 +30,11 @@ import { concatPagination } from "../../../utilities"; import assert from "assert"; import { expectTypeOf } from "expect-type"; import { SubscriptionObserver } from "zen-observable-ts"; -import { profile, profileHook, spyOnConsole } from "../../../testing/internal"; +import { + renderHookToSnapshotStream, + renderToRenderStream, +} from "@testing-library/react-render-stream"; +import { spyOnConsole } from "../../../testing/internal"; describe("useFragment", () => { it("is importable and callable", () => { @@ -1420,18 +1425,19 @@ describe("useFragment", () => { data: { __typename: "User", id: 2, name: "Charlie" }, }); - const ProfiledHook = profileHook(({ id }: { id: number }) => - useFragment({ fragment, from: { __typename: "User", id } }) + const { takeSnapshot, rerender } = renderHookToSnapshotStream( + ({ id }: { id: number }) => + useFragment({ fragment, from: { __typename: "User", id } }), + { + wrapper: ({ children }) => ( + {children} + ), + initialProps: { id: 1 }, + } ); - const { rerender } = render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot).toEqual({ complete: true, @@ -1439,10 +1445,10 @@ describe("useFragment", () => { }); } - rerender(); + rerender({ id: 2 }); { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot).toEqual({ complete: true, @@ -1450,7 +1456,7 @@ describe("useFragment", () => { }); } - await expect(ProfiledHook).not.toRerender(); + await expect(takeSnapshot).not.toRerender(); }); it("does not rerender when fields with @nonreactive change", async () => { @@ -1483,18 +1489,17 @@ describe("useFragment", () => { }, }); - const ProfiledHook = profileHook(() => - useFragment({ fragment, from: { __typename: "Post", id: 1 } }) + const { takeSnapshot } = renderHookToSnapshotStream( + () => useFragment({ fragment, from: { __typename: "Post", id: 1 } }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot).toEqual({ complete: true, @@ -1517,7 +1522,7 @@ describe("useFragment", () => { }, }); - await expect(ProfiledHook).not.toRerender(); + await expect(takeSnapshot).not.toRerender(); }); it("does not rerender when fields with @nonreactive on nested fragment change", async () => { @@ -1555,22 +1560,22 @@ describe("useFragment", () => { }, }); - const ProfiledHook = profileHook(() => - useFragment({ - fragment, - fragmentName: "PostFragment", - from: { __typename: "Post", id: 1 }, - }) + const { takeSnapshot } = renderHookToSnapshotStream( + () => + useFragment({ + fragment, + fragmentName: "PostFragment", + from: { __typename: "Post", id: 1 }, + }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot).toEqual({ complete: true, @@ -1594,7 +1599,7 @@ describe("useFragment", () => { }, }); - await expect(ProfiledHook).not.toRerender(); + await expect(takeSnapshot).not.toRerender(); }); describe("tests with incomplete data", () => { @@ -1731,23 +1736,23 @@ describe("useFragment", () => { using _ = spyOnConsole("warn"); const cache = new InMemoryCache(); - const ProfiledHook = profileHook(() => - useFragment({ - fragment: ItemFragment, - // Force a value that results in cache.identify === undefined - from: { __typename: "Item" }, - }) + const { takeSnapshot } = renderHookToSnapshotStream( + () => + useFragment({ + fragment: ItemFragment, + // Force a value that results in cache.identify === undefined + from: { __typename: "Item" }, + }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - expect(console.warn).not.toHaveBeenCalled(); - const { data, complete } = await ProfiledHook.takeSnapshot(); + const { data, complete } = await takeSnapshot(); // TODO: Update when https://github.com/apollographql/apollo-client/issues/12003 is fixed expect(complete).toBe(true); @@ -1791,27 +1796,26 @@ describe("has the same timing as `useQuery`", () => { from: initialItem, }); - ProfiledComponent.replaceSnapshot({ queryData, fragmentData }); + replaceSnapshot({ queryData, fragmentData }); return complete ? JSON.stringify(fragmentData) : "loading"; } - const ProfiledComponent = profile({ - Component, - initialSnapshot: { - queryData: undefined as any, - fragmentData: undefined as any, - }, - }); - - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); + const { takeRender, replaceSnapshot } = renderToRenderStream( + , + { + initialSnapshot: { + queryData: undefined as any, + fragmentData: undefined as any, + }, + wrapper: ({ children }) => ( + {children} + ), + } + ); { - const { snapshot } = await ProfiledComponent.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.queryData).toBe(undefined); expect(snapshot.fragmentData).toStrictEqual({}); } @@ -1821,7 +1825,7 @@ describe("has the same timing as `useQuery`", () => { observer.complete(); { - const { snapshot } = await ProfiledComponent.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.queryData).toStrictEqual({ item: initialItem }); expect(snapshot.fragmentData).toStrictEqual(initialItem); } @@ -1829,7 +1833,7 @@ describe("has the same timing as `useQuery`", () => { cache.writeQuery({ query, data: { item: updatedItem } }); { - const { snapshot } = await ProfiledComponent.takeRender(); + const { snapshot } = await takeRender(); expect(snapshot.queryData).toStrictEqual({ item: updatedItem }); expect(snapshot.fragmentData).toStrictEqual(updatedItem); } @@ -1878,8 +1882,7 @@ describe("has the same timing as `useQuery`", () => { return <>{JSON.stringify({ item: data })}; } - const ProfiledParent = profile({ - Component: Parent, + const { takeRender } = renderToRenderStream(, { snapshotDOM: true, onRender() { const parent = screen.getByTestId("parent"); @@ -1891,16 +1894,13 @@ describe("has the same timing as `useQuery`", () => { within(children).queryAllByText(/Item #2/).length ); }, - }); - - render(, { wrapper: ({ children }) => ( {children} ), }); { - const { withinDOM } = await ProfiledParent.takeRender(); + const { withinDOM } = await takeRender(); expect(withinDOM().queryAllByText(/Item #2/).length).toBe(2); } @@ -1909,11 +1909,11 @@ describe("has the same timing as `useQuery`", () => { }); { - const { withinDOM } = await ProfiledParent.takeRender(); + const { withinDOM } = await takeRender(); expect(withinDOM().queryAllByText(/Item #2/).length).toBe(0); } - await expect(ProfiledParent).toRenderExactlyTimes(2); + await expect(takeRender).toRenderExactlyTimes(2); }); /** @@ -1973,8 +1973,7 @@ describe("has the same timing as `useQuery`", () => { return <>{JSON.stringify(data)}; } - const ProfiledParent = profile({ - Component: Parent, + const { takeRender } = renderToRenderStream(, { onRender() { const parent = screen.getByTestId("parent"); const children = screen.getByTestId("children"); @@ -1985,16 +1984,13 @@ describe("has the same timing as `useQuery`", () => { within(children).queryAllByText(/Item #2/).length ); }, - }); - - render(, { wrapper: ({ children }) => ( {children} ), }); { - const { withinDOM } = await ProfiledParent.takeRender(); + const { withinDOM } = await takeRender(); expect(withinDOM().queryAllByText(/Item #2/).length).toBe(2); } @@ -2006,11 +2002,11 @@ describe("has the same timing as `useQuery`", () => { ); { - const { withinDOM } = await ProfiledParent.takeRender(); + const { withinDOM } = await takeRender(); expect(withinDOM().queryAllByText(/Item #2/).length).toBe(0); } - await expect(ProfiledParent).toRenderExactlyTimes(3); + await expect(takeRender).toRenderExactlyTimes(3); }); }); diff --git a/src/react/hooks/__tests__/useLazyQuery.test.tsx b/src/react/hooks/__tests__/useLazyQuery.test.tsx index e96dc5d09b0..7d296aada1e 100644 --- a/src/react/hooks/__tests__/useLazyQuery.test.tsx +++ b/src/react/hooks/__tests__/useLazyQuery.test.tsx @@ -1,7 +1,7 @@ import React from "react"; import { GraphQLError } from "graphql"; import gql from "graphql-tag"; -import { act, render, renderHook, waitFor } from "@testing-library/react"; +import { act, renderHook, waitFor } from "@testing-library/react"; import { ApolloClient, @@ -24,8 +24,8 @@ import { } from "../../../testing"; import { useLazyQuery } from "../useLazyQuery"; import { QueryResult } from "../../types/types"; -import { profileHook } from "../../../testing/internal"; import { InvariantError } from "../../../utilities/globals"; +import { renderHookToSnapshotStream } from "@testing-library/react-render-stream"; describe("useLazyQuery Hook", () => { const helloQuery: TypedDocumentNode<{ @@ -99,31 +99,32 @@ describe("useLazyQuery Hook", () => { }, ]; - const ProfiledHook = profileHook(() => useLazyQuery(helloQuery)); - - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useLazyQuery(helloQuery), + { + wrapper: ({ children }) => ( + {children} + ), + } + ); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.called).toBe(false); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.called).toBe(true); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.called).toBe(true); } @@ -138,32 +139,32 @@ describe("useLazyQuery Hook", () => { }, ]; - const ProfiledHook = profileHook( + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( // skip isn’t actually an option on the types - () => useLazyQuery(helloQuery, { skip: true } as any) + () => useLazyQuery(helloQuery, { skip: true } as any), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.called).toBe(false); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.called).toBe(true); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.called).toBe(true); } @@ -184,31 +185,32 @@ describe("useLazyQuery Hook", () => { }, ]; - const ProfiledHook = profileHook(() => - useLazyQuery(query, { - variables: { id: 1 }, - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useLazyQuery(query, { + variables: { id: 1 }, + }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); } @@ -542,30 +544,32 @@ describe("useLazyQuery Hook", () => { ]; const cache = new InMemoryCache(); - const ProfiledHook = profileHook(() => useLazyQuery(query1)); - render(, { - wrapper: ({ children }) => ( - - {children} - - ), - }); + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useLazyQuery(query1), + { + wrapper: ({ children }) => ( + + {children} + + ), + } + ); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBe(undefined); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world" }); } @@ -573,12 +577,12 @@ describe("useLazyQuery Hook", () => { setTimeout(() => execute({ query: query2 })); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ name: "changed" }); } @@ -598,32 +602,32 @@ describe("useLazyQuery Hook", () => { }, ]; - const ProfiledHook = profileHook(() => - useLazyQuery(helloQuery, { - fetchPolicy: "network-only", - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useLazyQuery(helloQuery, { + fetchPolicy: "network-only", + }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); } @@ -631,12 +635,12 @@ describe("useLazyQuery Hook", () => { setTimeout(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toEqual({ hello: "world 1" }); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 2" }); } @@ -656,51 +660,51 @@ describe("useLazyQuery Hook", () => { }, ]; - const ProfiledHook = profileHook(() => - useLazyQuery(helloQuery, { - notifyOnNetworkStatusChange: true, - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useLazyQuery(helloQuery, { + notifyOnNetworkStatusChange: true, + }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBe(undefined); expect(result.previousData).toBe(undefined); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.previousData).toBe(undefined); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); expect(result.previousData).toBe(undefined); } - const refetch = ProfiledHook.getCurrentSnapshot()[1].refetch; + const refetch = getCurrentSnapshot()[1].refetch; setTimeout(() => refetch!()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toEqual({ hello: "world 1" }); expect(result.previousData).toEqual({ hello: "world 1" }); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 2" }); expect(result.previousData).toEqual({ hello: "world 1" }); @@ -728,45 +732,46 @@ describe("useLazyQuery Hook", () => { {children} ); - const ProfiledHook = profileHook(() => useLazyQuery(helloQuery)); - - render(, { wrapper }); + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useLazyQuery(helloQuery), + { wrapper } + ); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBe(undefined); } await tick(); - ProfiledHook.getCurrentSnapshot()[1].startPolling(10); + getCurrentSnapshot()[1].startPolling(10); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 2" }); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 3" }); } - ProfiledHook.getCurrentSnapshot()[1].stopPolling(); + getCurrentSnapshot()[1].stopPolling(); - expect(ProfiledHook).not.toRerender(); + expect(takeSnapshot).not.toRerender(); }); it("should persist previous data when a query is re-run and variable changes", async () => { @@ -808,30 +813,32 @@ describe("useLazyQuery Hook", () => { }, ]; - const ProfiledHook = profileHook(() => useLazyQuery(CAR_QUERY_BY_ID)); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useLazyQuery(CAR_QUERY_BY_ID), + { + wrapper: ({ children }) => ( + {children} + ), + } + ); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBe(undefined); expect(result.previousData).toBe(undefined); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(() => execute({ variables: { id: 1 } })); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.previousData).toBe(undefined); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual(data1); expect(result.previousData).toBe(undefined); @@ -840,13 +847,13 @@ describe("useLazyQuery Hook", () => { setTimeout(() => execute({ variables: { id: 2 } })); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.previousData).toEqual(data1); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual(data2); expect(result.previousData).toEqual(data1); @@ -1083,18 +1090,19 @@ describe("useLazyQuery Hook", () => { }, ]; - const ProfiledHook = profileHook(() => useLazyQuery(helloQuery)); - - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); + const { takeSnapshot, peekSnapshot } = renderHookToSnapshotStream( + () => useLazyQuery(helloQuery), + { + wrapper: ({ children }) => ( + {children} + ), + } + ); - const [execute] = await ProfiledHook.peekSnapshot(); + const [execute] = await peekSnapshot(); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBeUndefined(); } @@ -1102,14 +1110,14 @@ describe("useLazyQuery Hook", () => { const executePromise = Promise.resolve().then(() => execute()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBeUndefined(); expect(result.error).toBe(undefined); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBeUndefined(); expect(result.error).toEqual( @@ -1126,7 +1134,7 @@ describe("useLazyQuery Hook", () => { execute(); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBeUndefined(); expect(result.error).toEqual( @@ -1135,7 +1143,7 @@ describe("useLazyQuery Hook", () => { } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBeUndefined(); expect(result.error).toEqual( @@ -1749,34 +1757,35 @@ describe("useLazyQuery Hook", () => { ), }); - const ProfiledHook = profileHook(() => - useLazyQuery(helloQuery, { - errorPolicy, - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useLazyQuery(helloQuery, { + errorPolicy, + }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.networkStatus).toBe(NetworkStatus.ready); expect(result.data).toBeUndefined(); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; setTimeout(execute); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.networkStatus).toBe(NetworkStatus.loading); expect(result.data).toBeUndefined(); } { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.networkStatus).toBe(NetworkStatus.error); expect(result.data).toBeUndefined(); @@ -1933,25 +1942,27 @@ describe("useLazyQuery Hook", () => { link, cache: new InMemoryCache(), }); - const ProfiledHook = profileHook(() => useLazyQuery(helloQuery)); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useLazyQuery(helloQuery), + { + wrapper: ({ children }) => ( + {children} + ), + } + ); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBeUndefined(); } - const execute = ProfiledHook.getCurrentSnapshot()[0]; + const execute = getCurrentSnapshot()[0]; const promise = execute(); expect(requests).toBe(1); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBeUndefined(); } @@ -1970,7 +1981,7 @@ describe("useLazyQuery Hook", () => { ); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBeUndefined(); expect(result.error).toEqual( @@ -1983,7 +1994,7 @@ describe("useLazyQuery Hook", () => { } link.simulateResult({ result: { data: { hello: "Greetings" } } }, true); - await expect(ProfiledHook).not.toRerender({ timeout: 50 }); + await expect(takeSnapshot).not.toRerender({ timeout: 50 }); expect(requests).toBe(1); }); }); diff --git a/src/react/hooks/__tests__/useLoadableQuery.test.tsx b/src/react/hooks/__tests__/useLoadableQuery.test.tsx index 9c83a0bd6c5..50d228fb0ed 100644 --- a/src/react/hooks/__tests__/useLoadableQuery.test.tsx +++ b/src/react/hooks/__tests__/useLoadableQuery.test.tsx @@ -5,7 +5,6 @@ import { screen, renderHook, waitFor, - RenderOptions, } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { ErrorBoundary as ReactErrorBoundary } from "react-error-boundary"; @@ -53,15 +52,17 @@ import { } from "../useSuspenseQuery"; import invariant, { InvariantError } from "ts-invariant"; import { - Profiler, SimpleCaseData, - createProfiler, setupPaginatedCase, setupSimpleCase, spyOnConsole, - useTrackRenders, } from "../../../testing/internal"; +import { + RenderStream, + createRenderStream, + useTrackRenders, +} from "@testing-library/react-render-stream"; const IS_REACT_19 = React.version.startsWith("19"); afterEach(() => { @@ -169,7 +170,7 @@ function usePaginatedQueryCase() { } function createDefaultProfiler() { - return createProfiler({ + return createRenderStream({ initialSnapshot: { error: null as Error | null, result: null as UseReadQueryResult | null, @@ -186,7 +187,7 @@ function createDefaultProfiledComponents< TData = Snapshot["result"] extends UseReadQueryResult | null ? TData : unknown, ->(profiler: Profiler) { +>(profiler: RenderStream) { function SuspenseFallback() { useTrackRenders(); return

Loading

; @@ -226,18 +227,14 @@ function createDefaultProfiledComponents< function renderWithMocks( ui: React.ReactElement, - { - wrapper: Wrapper = React.Fragment, - ...props - }: MockedProviderProps & { wrapper?: RenderOptions["wrapper"] } + props: MockedProviderProps, + { render: doRender } = { render } ) { const user = userEvent.setup(); - const utils = render(ui, { + const utils = doRender(ui, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); @@ -246,16 +243,15 @@ function renderWithMocks( function renderWithClient( ui: React.ReactElement, - options: { client: ApolloClient; wrapper?: RenderOptions["wrapper"] } + options: { client: ApolloClient }, + { render: doRender } = { render } ) { - const { client, wrapper: Wrapper = React.Fragment } = options; + const { client } = options; const user = userEvent.setup(); - const utils = render(ui, { + const utils = doRender(ui, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); @@ -265,10 +261,10 @@ function renderWithClient( it("loads a query and suspends when the load query function is called", async () => { const { query, mocks } = useSimpleQueryCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -284,10 +280,16 @@ it("loads a query and suspends when the load query function is called", async () ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -295,13 +297,13 @@ it("loads a query and suspends when the load query function is called", async () await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -316,10 +318,10 @@ it("loads a query and suspends when the load query function is called", async () it("loads a query with variables and suspends by passing variables to the loadQuery function", async () => { const { query, mocks } = useVariablesQueryCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -335,10 +337,16 @@ it("loads a query with variables and suspends by passing variables to the loadQu ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -346,13 +354,13 @@ it("loads a query with variables and suspends by passing variables to the loadQu await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -362,7 +370,7 @@ it("loads a query with variables and suspends by passing variables to the loadQu }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("tears down the query on unmount", async () => { @@ -373,9 +381,9 @@ it("tears down the query on unmount", async () => { link: new MockLink(mocks), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -391,18 +399,21 @@ it("tears down the query on unmount", async () => { ); } - const { user, unmount } = renderWithClient(, { - client, - wrapper: Profiler, - }); + const { user, unmount } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -505,9 +516,9 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -525,17 +536,23 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); expect(client.getObservableQueries().size).toBe(1); expect(client).toHaveSuspenseCacheEntryUsing(query); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -549,7 +566,7 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { await act(() => user.click(screen.getByText("Toggle"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -565,7 +582,7 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -575,7 +592,7 @@ it("will resubscribe after disposed when mounting useReadQuery", async () => { }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("auto resubscribes when mounting useReadQuery after naturally disposed by useReadQuery", async () => { @@ -585,9 +602,9 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -605,24 +622,30 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); const toggleButton = screen.getByText("Toggle"); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); expect(client.getObservableQueries().size).toBe(1); expect(client).toHaveSuspenseCacheEntryUsing(query); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -632,7 +655,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use } await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(client.getObservableQueries().size).toBe(0); @@ -647,7 +670,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use expect(client).not.toHaveSuspenseCacheEntryUsing(query); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -663,7 +686,7 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -673,16 +696,16 @@ it("auto resubscribes when mounting useReadQuery after naturally disposed by use }); } - await expect(Profiler).not.toRerender({ timeout: 50 }); + await expect(renderStream).not.toRerender({ timeout: 50 }); }); it("changes variables on a query and resuspends when passing new variables to the loadQuery function", async () => { const { query, mocks } = useVariablesQueryCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); const App = () => { useTrackRenders(); @@ -703,10 +726,16 @@ it("changes variables on a query and resuspends when passing new variables to th ); }; - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); } @@ -714,13 +743,13 @@ it("changes variables on a query and resuspends when passing new variables to th await act(() => user.click(screen.getByText("Load 1st character"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -733,13 +762,13 @@ it("changes variables on a query and resuspends when passing new variables to th await act(() => user.click(screen.getByText("Load 2nd character"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -749,7 +778,7 @@ it("changes variables on a query and resuspends when passing new variables to th }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("resets the `queryRef` to null and disposes of it when calling the `reset` function", async () => { @@ -760,9 +789,9 @@ it("resets the `queryRef` to null and disposes of it when calling the `reset` fu link: new MockLink(mocks), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -770,7 +799,7 @@ it("resets the `queryRef` to null and disposes of it when calling the `reset` fu // Resetting the result allows us to detect when ReadQueryHook is unmounted // since it won't render and overwrite the `null` - Profiler.mergeSnapshot({ result: null }); + renderStream.mergeSnapshot({ result: null }); return ( <> @@ -783,16 +812,22 @@ it("resets the `queryRef` to null and disposes of it when calling the `reset` fu ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -804,7 +839,7 @@ it("resets the `queryRef` to null and disposes of it when calling the `reset` fu await act(() => user.click(screen.getByText("Reset query"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); expect(snapshot.result).toBeNull(); @@ -842,10 +877,10 @@ it("allows the client to be overridden", async () => { cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -863,18 +898,21 @@ it("allows the client to be overridden", async () => { ); } - const { user } = renderWithClient(, { - client: globalClient, - wrapper: Profiler, - }); + const { user } = renderWithClient( + , + { + client: globalClient, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "local hello" }, @@ -907,10 +945,10 @@ it("passes context to the link", async () => { }), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -928,15 +966,21 @@ it("passes context to the link", async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { context: { valueA: "A", valueB: "B" } }, @@ -990,10 +1034,10 @@ it('enables canonical results when canonizeResults is "true"', async () => { link: new MockLink([]), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1011,14 +1055,20 @@ it('enables canonical results when canonizeResults is "true"', async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const resultSet = new Set(snapshot.result?.data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -1073,9 +1123,9 @@ it("can disable canonical results when the cache's canonizeResults setting is tr data: { results }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1093,14 +1143,20 @@ it("can disable canonical results when the cache's canonizeResults setting is tr ); } - const { user } = renderWithMocks(, { cache, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + cache, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const resultSet = new Set(snapshot.result!.data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -1133,10 +1189,10 @@ it("returns initial cache data followed by network data when the fetch policy is cache.writeQuery({ query, data: { hello: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1154,15 +1210,21 @@ it("returns initial cache data followed by network data when the fetch policy is ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1173,7 +1235,7 @@ it("returns initial cache data followed by network data when the fetch policy is } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1206,9 +1268,9 @@ it("all data is present in the cache, no network request is made", async () => { cache.writeQuery({ query, data: { hello: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1224,14 +1286,20 @@ it("all data is present in the cache, no network request is made", async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1240,7 +1308,7 @@ it("all data is present in the cache, no network request is made", async () => { error: undefined, }); - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("partial data is present in the cache so it is ignored and network request is made", async () => { @@ -1271,9 +1339,9 @@ it("partial data is present in the cache so it is ignored and network request is cache.writeQuery({ query, data: { hello: "from cache" } }); } - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1289,21 +1357,27 @@ it("partial data is present in the cache so it is ignored and network request is ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { foo: "bar", hello: "from link" }, @@ -1335,9 +1409,9 @@ it("existing data in the cache is ignored when `fetchPolicy` is 'network-only'", cache.writeQuery({ query, data: { hello: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1355,21 +1429,27 @@ it("existing data in the cache is ignored when `fetchPolicy` is 'network-only'", ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { hello: "from link" }, @@ -1398,9 +1478,9 @@ it("fetches data from the network but does not update the cache when `fetchPolic cache.writeQuery({ query, data: { hello: "from cache" } }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1418,21 +1498,27 @@ it("fetches data from the network but does not update the cache when `fetchPolic ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { hello: "from link" }, @@ -1614,9 +1700,9 @@ it('does not suspend deferred queries with data in the cache and using a "cache- }); const client = new ApolloClient({ cache, link }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1633,15 +1719,21 @@ it('does not suspend deferred queries with data in the cache and using a "cache- ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load todo"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); @@ -1668,7 +1760,7 @@ it('does not suspend deferred queries with data in the cache and using a "cache- }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1703,7 +1795,7 @@ it('does not suspend deferred queries with data in the cache and using a "cache- ); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1719,7 +1811,7 @@ it('does not suspend deferred queries with data in the cache and using a "cache- }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("reacts to cache updates", async () => { @@ -1729,14 +1821,14 @@ it("reacts to cache updates", async () => { link: new MockLink(mocks), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, }); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1752,16 +1844,22 @@ it("reacts to cache updates", async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1777,7 +1875,7 @@ it("reacts to cache updates", async () => { }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1787,7 +1885,7 @@ it("reacts to cache updates", async () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("applies `errorPolicy` on next fetch when it changes between renders", async () => { @@ -1808,9 +1906,9 @@ it("applies `errorPolicy` on next fetch when it changes between renders", async }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook, ErrorBoundary, ErrorFallback } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1835,16 +1933,22 @@ it("applies `errorPolicy` on next fetch when it changes between renders", async ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1854,13 +1958,13 @@ it("applies `errorPolicy` on next fetch when it changes between renders", async } await act(() => user.click(screen.getByText("Change error policy"))); - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Refetch greeting"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); // Ensure we aren't rendering the error boundary and instead rendering the // error message in the hook component. @@ -1902,9 +2006,9 @@ it("applies `context` on next fetch when it changes between renders", async () = cache: new InMemoryCache(), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -1925,16 +2029,22 @@ it("applies `context` on next fetch when it changes between renders", async () = ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result!.data).toEqual({ phase: "initial", @@ -1942,13 +2052,13 @@ it("applies `context` on next fetch when it changes between renders", async () = } await act(() => user.click(screen.getByText("Update context"))); - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result!.data).toEqual({ phase: "rerender", @@ -2004,9 +2114,9 @@ it("returns canonical results immediately when `canonizeResults` changes from `f cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2028,15 +2138,21 @@ it("returns canonical results immediately when `canonizeResults` changes from `f ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const { data } = snapshot.result!; const resultSet = new Set(data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -2049,7 +2165,7 @@ it("returns canonical results immediately when `canonizeResults` changes from `f await act(() => user.click(screen.getByText("Canonize results"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const { data } = snapshot.result!; const resultSet = new Set(data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -2112,9 +2228,9 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2146,16 +2262,22 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const { primes } = snapshot.result!.data; expect(primes).toEqual([2, 3, 5, 7, 11]); @@ -2163,10 +2285,10 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren } await act(() => user.click(screen.getByText("Refetch next"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const { primes } = snapshot.result!.data; expect(primes).toEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29]); @@ -2180,13 +2302,13 @@ it("applies changed `refetchWritePolicy` to next fetch when changing between ren } await act(() => user.click(screen.getByText("Change refetch write policy"))); - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Refetch last"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const { primes } = snapshot.result!.data; expect(primes).toEqual([31, 37, 41, 43, 47]); @@ -2277,9 +2399,9 @@ it("applies `returnPartialData` on next fetch when it changes between renders", cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2302,16 +2424,22 @@ it("applies `returnPartialData` on next fetch when it changes between renders", ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -2323,7 +2451,7 @@ it("applies `returnPartialData` on next fetch when it changes between renders", } await act(() => user.click(screen.getByText("Update partial data"))); - await Profiler.takeRender(); + await renderStream.takeRender(); cache.modify({ id: cache.identify({ __typename: "Character", id: "1" }), @@ -2333,7 +2461,7 @@ it("applies `returnPartialData` on next fetch when it changes between renders", }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -2346,7 +2474,7 @@ it("applies `returnPartialData` on next fetch when it changes between renders", } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -2416,9 +2544,9 @@ it("applies updated `fetchPolicy` on next fetch when it changes between renders" cache, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2443,15 +2571,21 @@ it("applies updated `fetchPolicy` on next fetch when it changes between renders" ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -2467,13 +2601,13 @@ it("applies updated `fetchPolicy` on next fetch when it changes between renders" } await act(() => user.click(screen.getByText("Change fetch policy"))); - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -2520,9 +2654,9 @@ it("re-suspends when calling `refetch`", async () => { }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2539,21 +2673,27 @@ it("re-suspends when calling `refetch`", async () => { ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Spider-Man" } }, @@ -2565,13 +2705,13 @@ it("re-suspends when calling `refetch`", async () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Spider-Man (updated)" } }, @@ -2580,7 +2720,7 @@ it("re-suspends when calling `refetch`", async () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("re-suspends when calling `refetch` with new variables", async () => { @@ -2603,9 +2743,9 @@ it("re-suspends when calling `refetch` with new variables", async () => { }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2622,21 +2762,27 @@ it("re-suspends when calling `refetch` with new variables", async () => { ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Captain Marvel" } }, @@ -2648,13 +2794,13 @@ it("re-suspends when calling `refetch` with new variables", async () => { await act(() => user.click(screen.getByText("Refetch with ID 2"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "2", name: "Captain America" } }, @@ -2663,7 +2809,7 @@ it("re-suspends when calling `refetch` with new variables", async () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("re-suspends multiple times when calling `refetch` multiple times", async () => { @@ -2680,10 +2826,10 @@ it("re-suspends multiple times when calling `refetch` multiple times", async () }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2700,21 +2846,27 @@ it("re-suspends multiple times when calling `refetch` multiple times", async () ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Spider-Man" } }, @@ -2728,13 +2880,13 @@ it("re-suspends multiple times when calling `refetch` multiple times", async () await act(() => user.click(button)); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Spider-Man" } }, @@ -2746,13 +2898,13 @@ it("re-suspends multiple times when calling `refetch` multiple times", async () await act(() => user.click(button)); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Spider-Man" } }, @@ -2761,7 +2913,7 @@ it("re-suspends multiple times when calling `refetch` multiple times", async () }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("throws errors when errors are returned after calling `refetch`", async () => { @@ -2786,10 +2938,10 @@ it("throws errors when errors are returned after calling `refetch`", async () => }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook, ErrorBoundary, ErrorFallback } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2808,16 +2960,22 @@ it("throws errors when errors are returned after calling `refetch`", async () => ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Captain Marvel" } }, @@ -2827,10 +2985,10 @@ it("throws errors when errors are returned after calling `refetch`", async () => } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ErrorFallback]); expect(snapshot.error).toEqual( @@ -2861,10 +3019,10 @@ it('ignores errors returned after calling `refetch` when errorPolicy is set to " }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook, ErrorBoundary, ErrorFallback } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2885,16 +3043,22 @@ it('ignores errors returned after calling `refetch` when errorPolicy is set to " ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toStrictEqual({ data: { character: { id: "1", name: "Captain Marvel" } }, @@ -2904,10 +3068,10 @@ it('ignores errors returned after calling `refetch` when errorPolicy is set to " } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(snapshot.error).toBeNull(); expect(snapshot.result).toEqual({ @@ -2919,7 +3083,7 @@ it('ignores errors returned after calling `refetch` when errorPolicy is set to " expect(renderedComponents).not.toContain(ErrorFallback); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it('returns errors after calling `refetch` when errorPolicy is set to "all"', async () => { @@ -2942,10 +3106,10 @@ it('returns errors after calling `refetch` when errorPolicy is set to "all"', as }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook, ErrorBoundary, ErrorFallback } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -2966,16 +3130,22 @@ it('returns errors after calling `refetch` when errorPolicy is set to "all"', as ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Captain Marvel" } }, @@ -2985,10 +3155,10 @@ it('returns errors after calling `refetch` when errorPolicy is set to "all"', as } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).not.toContain(ErrorFallback); expect(snapshot.error).toBeNull(); @@ -3001,7 +3171,7 @@ it('returns errors after calling `refetch` when errorPolicy is set to "all"', as }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it('handles partial data results after calling `refetch` when errorPolicy is set to "all"', async () => { @@ -3025,10 +3195,10 @@ it('handles partial data results after calling `refetch` when errorPolicy is set }, ]; - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook, ErrorBoundary, ErrorFallback } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -3049,16 +3219,22 @@ it('handles partial data results after calling `refetch` when errorPolicy is set ); } - const { user } = renderWithMocks(, { mocks, wrapper: Profiler }); + const { user } = renderWithMocks( + , + { + mocks, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Captain Marvel" } }, @@ -3068,10 +3244,10 @@ it('handles partial data results after calling `refetch` when errorPolicy is set } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).not.toContain(ErrorFallback); expect(snapshot.error).toBeNull(); @@ -3084,7 +3260,7 @@ it('handles partial data results after calling `refetch` when errorPolicy is set }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("`refetch` works with startTransition to allow React to show stale UI until finished suspending", async () => { @@ -3232,9 +3408,9 @@ it("re-suspends when calling `fetchMore` with different variables", async () => }), }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -3255,16 +3431,22 @@ it("re-suspends when calling `fetchMore` with different variables", async () => ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3281,13 +3463,13 @@ it("re-suspends when calling `fetchMore` with different variables", async () => await act(() => user.click(screen.getByText("Fetch more"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -3302,14 +3484,14 @@ it("re-suspends when calling `fetchMore` with different variables", async () => }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("properly uses `updateQuery` when calling `fetchMore`", async () => { const { query, client } = usePaginatedQueryCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -3337,16 +3519,22 @@ it("properly uses `updateQuery` when calling `fetchMore`", async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3361,10 +3549,10 @@ it("properly uses `updateQuery` when calling `fetchMore`", async () => { } await act(() => user.click(screen.getByText("Fetch more"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3383,14 +3571,14 @@ it("properly uses `updateQuery` when calling `fetchMore`", async () => { // TODO investigate: this test highlights a React render // that actually doesn't rerender any user-provided components // so we need to use `skipNonTrackingRenders` - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("properly uses cache field policies when calling `fetchMore` without `updateQuery`", async () => { const { query, link } = usePaginatedQueryCase(); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); const client = new ApolloClient({ link, @@ -3424,16 +3612,22 @@ it("properly uses cache field policies when calling `fetchMore` without `updateQ ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3448,10 +3642,10 @@ it("properly uses cache field policies when calling `fetchMore` without `updateQ } await act(() => user.click(screen.getByText("Fetch more"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -3470,7 +3664,7 @@ it("properly uses cache field policies when calling `fetchMore` without `updateQ // TODO investigate: this test highlights a React render // that actually doesn't rerender any user-provided components // so we need to use `skipNonTrackingRenders` - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("`fetchMore` works with startTransition to allow React to show stale UI until finished suspending", async () => { @@ -3682,9 +3876,9 @@ it('honors refetchWritePolicy set to "merge"', async () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); const client = new ApolloClient({ link: new MockLink(mocks), @@ -3710,16 +3904,22 @@ it('honors refetchWritePolicy set to "merge"', async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -3730,10 +3930,10 @@ it('honors refetchWritePolicy set to "merge"', async () => { } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] }, @@ -3749,7 +3949,7 @@ it('honors refetchWritePolicy set to "merge"', async () => { ]); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it('defaults refetchWritePolicy to "overwrite"', async () => { @@ -3796,9 +3996,9 @@ it('defaults refetchWritePolicy to "overwrite"', async () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); const client = new ApolloClient({ link: new MockLink(mocks), @@ -3822,16 +4022,22 @@ it('defaults refetchWritePolicy to "overwrite"', async () => { ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial load - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -3842,10 +4048,10 @@ it('defaults refetchWritePolicy to "overwrite"', async () => { } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [13, 17, 19, 23, 29] }, @@ -3891,9 +4097,9 @@ it('does not suspend when partial data is in the cache and using a "cache-first" }, ]; - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); const cache = new InMemoryCache(); @@ -3921,15 +4127,21 @@ it('does not suspend when partial data is in the cache and using a "cache-first" ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial load - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1" } }, @@ -3941,7 +4153,7 @@ it('does not suspend when partial data is in the cache and using a "cache-first" } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Doctor Strange" } }, @@ -3952,7 +4164,7 @@ it('does not suspend when partial data is in the cache and using a "cache-first" expect(renderedComponents).toStrictEqual([ReadQueryHook]); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it('suspends and does not use partial data from other variables in the cache when changing variables and using a "cache-first" fetch policy with returnPartialData: true', async () => { @@ -3974,9 +4186,9 @@ it('suspends and does not use partial data from other variables in the cache whe variables: { id: "1" }, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -3996,19 +4208,22 @@ it('suspends and does not use partial data from other variables in the cache whe ); } - const { user } = renderWithMocks(, { - mocks, - cache, - wrapper: Profiler, - }); + const { user } = renderWithMocks( + , + { + mocks, + cache, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1" } }, @@ -4020,7 +4235,7 @@ it('suspends and does not use partial data from other variables in the cache whe } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Spider-Man" } }, @@ -4034,13 +4249,13 @@ it('suspends and does not use partial data from other variables in the cache whe await act(() => user.click(screen.getByText("Change variables"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "2", name: "Black Widow" } }, @@ -4051,7 +4266,7 @@ it('suspends and does not use partial data from other variables in the cache whe expect(renderedComponents).toStrictEqual([ReadQueryHook]); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it('suspends when partial data is in the cache and using a "network-only" fetch policy with returnPartialData', async () => { @@ -4086,9 +4301,9 @@ it('suspends when partial data is in the cache and using a "network-only" fetch }, ]; - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); const cache = new InMemoryCache(); @@ -4114,25 +4329,28 @@ it('suspends when partial data is in the cache and using a "network-only" fetch ); } - const { user } = renderWithMocks(, { - mocks, - cache, - wrapper: Profiler, - }); + const { user } = renderWithMocks( + , + { + mocks, + cache, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Doctor Strange" } }, @@ -4141,7 +4359,7 @@ it('suspends when partial data is in the cache and using a "network-only" fetch }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it('suspends when partial data is in the cache and using a "no-cache" fetch policy with returnPartialData', async () => { @@ -4185,9 +4403,9 @@ it('suspends when partial data is in the cache and using a "no-cache" fetch poli data: { character: { id: "1" } }, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -4206,25 +4424,28 @@ it('suspends when partial data is in the cache and using a "no-cache" fetch poli ); } - const { user } = renderWithMocks(, { - mocks, - cache, - wrapper: Profiler, - }); + const { user } = renderWithMocks( + , + { + mocks, + cache, + }, + renderStream + ); // initial load - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Doctor Strange" } }, @@ -4301,9 +4522,9 @@ it('does not suspend when partial data is in the cache and using a "cache-and-ne data: { character: { id: "1" } }, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -4322,19 +4543,22 @@ it('does not suspend when partial data is in the cache and using a "cache-and-ne ); } - const { user } = renderWithMocks(, { - mocks, - cache, - wrapper: Profiler, - }); + const { user } = renderWithMocks( + , + { + mocks, + cache, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4345,7 +4569,7 @@ it('does not suspend when partial data is in the cache and using a "cache-and-ne } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "1", name: "Doctor Strange" } }, @@ -4374,9 +4598,9 @@ it('suspends and does not use partial data when changing variables and using a " variables: { id: "1" }, }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -4396,19 +4620,22 @@ it('suspends and does not use partial data when changing variables and using a " ); } - const { user } = renderWithMocks(, { - mocks, - cache, - wrapper: Profiler, - }); + const { user } = renderWithMocks( + , + { + mocks, + cache, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4419,7 +4646,7 @@ it('suspends and does not use partial data when changing variables and using a " } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4432,13 +4659,13 @@ it('suspends and does not use partial data when changing variables and using a " await act(() => user.click(screen.getByText("Change variables"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { character: { id: "2", name: "Black Widow" } }, @@ -4494,9 +4721,9 @@ it('does not suspend deferred queries with partial data in the cache and using a const client = new ApolloClient({ link, cache }); - const Profiler = createDefaultProfiler>(); + const renderStream = createDefaultProfiler>(); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); @@ -4515,15 +4742,21 @@ it('does not suspend deferred queries with partial data in the cache and using a ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load todo"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4548,7 +4781,7 @@ it('does not suspend deferred queries with partial data in the cache and using a }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4583,7 +4816,7 @@ it('does not suspend deferred queries with partial data in the cache and using a ); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4599,7 +4832,7 @@ it('does not suspend deferred queries with partial data in the cache and using a }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("throws when calling loadQuery on first render", async () => { @@ -4716,7 +4949,7 @@ it("can subscribe to subscriptions and react to cache updates via `subscribeToMo const client = new ApolloClient({ link, cache: new InMemoryCache() }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { subscribeToMore: null as SubscribeToMoreFunction< SimpleCaseData, @@ -4727,13 +4960,13 @@ it("can subscribe to subscriptions and react to cache updates via `subscribeToMo }); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); const [loadQuery, queryRef, { subscribeToMore }] = useLoadableQuery(query); - Profiler.mergeSnapshot({ subscribeToMore }); + renderStream.mergeSnapshot({ subscribeToMore }); return (
@@ -4745,20 +4978,26 @@ it("can subscribe to subscriptions and react to cache updates via `subscribeToMo ); } - const { user } = renderWithClient(, { client, wrapper: Profiler }); + const { user } = renderWithClient( + , + { + client, + }, + renderStream + ); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4775,7 +5014,7 @@ it("can subscribe to subscriptions and react to cache updates via `subscribeToMo return { greeting: data.greetingUpdated }; }); - const { snapshot } = Profiler.getCurrentRender(); + const { snapshot } = renderStream.getCurrentRender(); snapshot.subscribeToMore!({ document: subscription, updateQuery }); @@ -4788,7 +5027,7 @@ it("can subscribe to subscriptions and react to cache updates via `subscribeToMo }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -4844,7 +5083,7 @@ it("throws when calling `subscribeToMore` before loading the query", async () => const client = new ApolloClient({ link, cache: new InMemoryCache() }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { subscribeToMore: null as SubscribeToMoreFunction< SimpleCaseData, @@ -4855,13 +5094,13 @@ it("throws when calling `subscribeToMore` before loading the query", async () => }); const { SuspenseFallback, ReadQueryHook } = - createDefaultProfiledComponents(Profiler); + createDefaultProfiledComponents(renderStream); function App() { useTrackRenders(); const [loadQuery, queryRef, { subscribeToMore }] = useLoadableQuery(query); - Profiler.mergeSnapshot({ subscribeToMore }); + renderStream.mergeSnapshot({ subscribeToMore }); return (
@@ -4873,11 +5112,11 @@ it("throws when calling `subscribeToMore` before loading the query", async () => ); } - renderWithClient(, { client, wrapper: Profiler }); + renderWithClient(, { client }, renderStream); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); - const { snapshot } = Profiler.getCurrentRender(); + const { snapshot } = renderStream.getCurrentRender(); expect(() => { snapshot.subscribeToMore!({ document: subscription }); diff --git a/src/react/hooks/__tests__/useMutation.test.tsx b/src/react/hooks/__tests__/useMutation.test.tsx index da26fd2c87d..2e3d22856fd 100644 --- a/src/react/hooks/__tests__/useMutation.test.tsx +++ b/src/react/hooks/__tests__/useMutation.test.tsx @@ -31,7 +31,8 @@ import { useQuery } from "../useQuery"; import { useMutation } from "../useMutation"; import { BatchHttpLink } from "../../../link/batch-http"; import { FetchResult } from "../../../link/core"; -import { profileHook, spyOnConsole } from "../../../testing/internal"; +import { spyOnConsole } from "../../../testing/internal"; +import { renderHookToSnapshotStream } from "@testing-library/react-render-stream"; describe("useMutation Hook", () => { interface Todo { @@ -750,26 +751,24 @@ describe("useMutation Hook", () => { }, ]; - const ProfiledHook = profileHook(() => - useMutation< - { createTodo: Todo }, - { priority: string; description: string } - >(CREATE_TODO_MUTATION) + const { takeSnapshot } = renderHookToSnapshotStream( + () => + useMutation< + { createTodo: Todo }, + { priority: string; description: string } + >(CREATE_TODO_MUTATION), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - - let createTodo: Awaited>[0]; - let reset: Awaited< - ReturnType - >[1]["reset"]; + let createTodo: Awaited>[0]; + let reset: Awaited>[1]["reset"]; { - const [mutate, result] = await ProfiledHook.takeSnapshot(); + const [mutate, result] = await takeSnapshot(); createTodo = mutate; reset = result.reset; //initial value @@ -786,7 +785,7 @@ describe("useMutation Hook", () => { }); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); // started loading expect(result.data).toBe(undefined); expect(result.loading).toBe(true); @@ -796,7 +795,7 @@ describe("useMutation Hook", () => { act(() => reset()); { - const [, result] = await ProfiledHook.takeSnapshot(); + const [, result] = await takeSnapshot(); // reset to initial value expect(result.data).toBe(undefined); expect(result.loading).toBe(false); @@ -805,7 +804,7 @@ describe("useMutation Hook", () => { expect(await fetchResult).toEqual({ data: CREATE_TODO_DATA }); - await expect(ProfiledHook).not.toRerender(); + await expect(takeSnapshot).not.toRerender(); }); }); diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index d521a96a0c3..09e48b99a6e 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -31,10 +31,8 @@ import { QueryResult } from "../../types/types"; import { useQuery } from "../useQuery"; import { useMutation } from "../useMutation"; import { - createProfiler, disableActWarnings, PaginatedCaseData, - profileHook, setupPaginatedCase, spyOnConsole, } from "../../../testing/internal"; @@ -42,6 +40,10 @@ import { useApolloClient } from "../useApolloClient"; import { useLazyQuery } from "../useLazyQuery"; import { mockFetchQuery } from "../../../core/__tests__/ObservableQuery"; import { InvariantError } from "../../../utilities/globals"; +import { + createRenderStream, + renderHookToSnapshotStream, +} from "@testing-library/react-render-stream"; const IS_REACT_17 = React.version.startsWith("17"); @@ -790,18 +792,17 @@ describe("useQuery Hook", () => { link, cache: new InMemoryCache(), }); - const ProfiledHook = profileHook(() => [ - useQuery(query1, { fetchPolicy: "no-cache" }), - useQuery(query2), - ]); - const { rerender } = render(, { - wrapper: ({ children }) => ( - {children} - ), - }); + const { takeSnapshot, rerender } = renderHookToSnapshotStream( + () => [useQuery(query1, { fetchPolicy: "no-cache" }), useQuery(query2)], + { + wrapper: ({ children }) => ( + {children} + ), + } + ); { - const [result0, result1] = await ProfiledHook.takeSnapshot(); + const [result0, result1] = await takeSnapshot(); expect(result0.loading).toBe(true); expect(result0.data).toStrictEqual(undefined); expect(result1.loading).toBe(true); @@ -809,7 +810,7 @@ describe("useQuery Hook", () => { } { - const [result0, result1] = await ProfiledHook.takeSnapshot(); + const [result0, result1] = await takeSnapshot(); expect(result0.loading).toBe(false); expect(result0.data).toStrictEqual(allPeopleData); expect(result1.loading).toBe(true); @@ -817,22 +818,22 @@ describe("useQuery Hook", () => { } { - const [result0, result1] = await ProfiledHook.takeSnapshot(); + const [result0, result1] = await takeSnapshot(); expect(result0.loading).toBe(false); expect(result0.data).toStrictEqual(allPeopleData); expect(result1.loading).toBe(false); expect(result1.data).toStrictEqual(allThingsData); } - rerender(); + rerender({}); { - const [result0, result1] = await ProfiledHook.takeSnapshot(); + const [result0, result1] = await takeSnapshot(); expect(result0.loading).toBe(false); expect(result0.data).toStrictEqual(allPeopleData); expect(result1.loading).toBe(false); expect(result1.data).toStrictEqual(allThingsData); } - await expect(ProfiledHook).not.toRerender(); + await expect(takeSnapshot).not.toRerender(); }); it("changing queries", async () => { @@ -1696,51 +1697,53 @@ describe("useQuery Hook", () => { ]; const cache = new InMemoryCache(); - const ProfiledUseQuery = profileHook(({ skip }: { skip?: boolean }) => - useQuery(query, { pollInterval: 10, skip }) + const { takeSnapshot, rerender } = renderHookToSnapshotStream( + ({ skip }: { skip?: boolean }) => + useQuery(query, { pollInterval: 10, skip }), + { + initialProps: {}, + wrapper: ({ children }) => ( + + {children} + + ), + } ); - const { rerender } = render(, { - wrapper: ({ children }) => ( - - {children} - - ), - }); { - const result = await ProfiledUseQuery.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); } { - const result = await ProfiledUseQuery.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); } - rerender(); + rerender({ skip: true }); { - const snapshot = await ProfiledUseQuery.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot.loading).toBe(false); expect(snapshot.data).toEqual(undefined); } - await expect(ProfiledUseQuery).not.toRerender({ timeout: 100 }); + await expect(takeSnapshot).not.toRerender({ timeout: 100 }); - rerender(); + rerender({ skip: false }); { - const result = await ProfiledUseQuery.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); } { - const result = await ProfiledUseQuery.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 2" }); } { - const result = await ProfiledUseQuery.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 3" }); } @@ -1826,20 +1829,19 @@ describe("useQuery Hook", () => { ); - const ProfiledHook = profileHook(() => - useQuery(query, { pollInterval: 20 }) + const { takeSnapshot, unmount } = renderHookToSnapshotStream( + () => useQuery(query, { pollInterval: 20 }), + { wrapper } ); - const { unmount } = render(, { wrapper }); - { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); expect(requestSpy).toHaveBeenCalled(); @@ -1903,31 +1905,34 @@ describe("useQuery Hook", () => { const onErrorFn = jest.fn(); link.setOnError(onErrorFn); - const ProfiledHook = profileHook(() => - useQuery(query, { pollInterval: 10, fetchPolicy: "cache-and-network" }) - ); - const client = new ApolloClient({ queryDeduplication: false, link, cache, }); - const { unmount } = render(, { - wrapper: ({ children }: any) => ( - {children} - ), - }); + const { takeSnapshot, unmount } = renderHookToSnapshotStream( + () => + useQuery(query, { + pollInterval: 10, + fetchPolicy: "cache-and-network", + }), + { + wrapper: ({ children }: any) => ( + {children} + ), + } + ); { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot.loading).toBe(true); expect(snapshot.data).toBeUndefined(); } { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot.loading).toBe(false); expect(snapshot.data).toEqual({ hello: "world 1" }); @@ -1937,7 +1942,7 @@ describe("useQuery Hook", () => { await wait(10); { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot.loading).toBe(false); expect(snapshot.data).toEqual({ hello: "world 2" }); @@ -1946,7 +1951,7 @@ describe("useQuery Hook", () => { unmount(); - await expect(ProfiledHook).not.toRerender({ timeout: 50 }); + await expect(takeSnapshot).not.toRerender({ timeout: 50 }); // TODO rarely seeing 3 here (also old `useQuery` implementation) expect(requestSpy).toHaveBeenCalledTimes(2); @@ -2060,29 +2065,32 @@ describe("useQuery Hook", () => { const onErrorFn = jest.fn(); link.setOnError(onErrorFn); - const ProfiledHook = profileHook(() => - useQuery(query, { pollInterval: 10, fetchPolicy: "cache-and-network" }) - ); - const client = new ApolloClient({ link, cache }); - const { unmount } = render(, { - wrapper: ({ children }: any) => ( - - {children} - - ), - }); + const { takeSnapshot, unmount } = renderHookToSnapshotStream( + () => + useQuery(query, { + pollInterval: 10, + fetchPolicy: "cache-and-network", + }), + { + wrapper: ({ children }: any) => ( + + {children} + + ), + } + ); { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot.loading).toBe(true); expect(snapshot.data).toBeUndefined(); } { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot.loading).toBe(false); expect(snapshot.data).toEqual({ hello: "world 1" }); @@ -2092,7 +2100,7 @@ describe("useQuery Hook", () => { await wait(10); { - const snapshot = await ProfiledHook.takeSnapshot(); + const snapshot = await takeSnapshot(); expect(snapshot.loading).toBe(false); expect(snapshot.data).toEqual({ hello: "world 2" }); @@ -2101,7 +2109,7 @@ describe("useQuery Hook", () => { unmount(); - await expect(ProfiledHook).not.toRerender({ timeout: 50 }); + await expect(takeSnapshot).not.toRerender({ timeout: 50 }); // TODO rarely seeing 3 here investigate further expect(requestSpy).toHaveBeenCalledTimes(2); expect(onErrorFn).toHaveBeenCalledTimes(0); @@ -3541,20 +3549,20 @@ describe("useQuery Hook", () => { ); - const ProfiledHook = profileHook(() => - useQuery(query, { notifyOnNetworkStatusChange: true }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useQuery(query, { notifyOnNetworkStatusChange: true }), + { wrapper } ); - render(, { wrapper }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.error).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBe(undefined); expect(result.error).toBeInstanceOf(ApolloError); @@ -3562,16 +3570,16 @@ describe("useQuery Hook", () => { } const catchFn = jest.fn(); - ProfiledHook.getCurrentSnapshot().refetch().catch(catchFn); + getCurrentSnapshot().refetch().catch(catchFn); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.error).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBe(undefined); expect(result.error).toBeInstanceOf(ApolloError); @@ -3684,49 +3692,49 @@ describe("useQuery Hook", () => { ); - const ProfiledHook = profileHook(() => - useQuery(query, { notifyOnNetworkStatusChange: true }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useQuery(query, { notifyOnNetworkStatusChange: true }), + { wrapper } ); - render(, { wrapper }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.error).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBe(undefined); expect(result.error).toBeInstanceOf(ApolloError); expect(result.error!.message).toBe("same error"); } - ProfiledHook.getCurrentSnapshot().refetch(); + getCurrentSnapshot().refetch(); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.error).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world" }); expect(result.error).toBe(undefined); } const catchFn = jest.fn(); - ProfiledHook.getCurrentSnapshot().refetch().catch(catchFn); + getCurrentSnapshot().refetch().catch(catchFn); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toEqual({ hello: "world" }); expect(result.error).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); // TODO: Is this correct behavior here? expect(result.data).toEqual({ hello: "world" }); @@ -4074,24 +4082,24 @@ describe("useQuery Hook", () => { const client = new ApolloClient({ cache: new InMemoryCache(), link }); - const ProfiledHook = profileHook(() => - useQuery(query, { fetchPolicy: "no-cache", variables: { limit: 2 } }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { fetchPolicy: "no-cache", variables: { limit: 2 } }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - // loading - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); // finished loading - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); expect(fetches).toStrictEqual([{ variables: { limit: 2 } }]); - const { fetchMore } = ProfiledHook.getCurrentSnapshot(); + const { fetchMore } = getCurrentSnapshot(); await act(() => fetchMore({ @@ -4111,23 +4119,22 @@ describe("useQuery Hook", () => { const client = new ApolloClient({ cache: new InMemoryCache(), link }); - const ProfiledHook = profileHook(() => - useQuery(query, { - notifyOnNetworkStatusChange: true, - fetchPolicy: "no-cache", - variables: { limit: 2 }, - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { + notifyOnNetworkStatusChange: true, + fetchPolicy: "no-cache", + variables: { limit: 2 }, + }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - { - const { loading, networkStatus, data } = - await ProfiledHook.takeSnapshot(); + const { loading, networkStatus, data } = await takeSnapshot(); expect(loading).toBe(true); expect(networkStatus).toBe(NetworkStatus.loading); @@ -4135,8 +4142,7 @@ describe("useQuery Hook", () => { } { - const { loading, networkStatus, data } = - await ProfiledHook.takeSnapshot(); + const { loading, networkStatus, data } = await takeSnapshot(); expect(loading).toBe(false); expect(networkStatus).toBe(NetworkStatus.ready); @@ -4149,7 +4155,7 @@ describe("useQuery Hook", () => { } let fetchMorePromise!: Promise>; - const { fetchMore } = ProfiledHook.getCurrentSnapshot(); + const { fetchMore } = getCurrentSnapshot(); act(() => { fetchMorePromise = fetchMore({ @@ -4161,8 +4167,7 @@ describe("useQuery Hook", () => { }); { - const { loading, networkStatus, data } = - await ProfiledHook.takeSnapshot(); + const { loading, networkStatus, data } = await takeSnapshot(); expect(loading).toBe(true); expect(networkStatus).toBe(NetworkStatus.fetchMore); @@ -4176,7 +4181,7 @@ describe("useQuery Hook", () => { { const { loading, networkStatus, data, observable } = - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); expect(loading).toBe(false); expect(networkStatus).toBe(NetworkStatus.ready); @@ -4211,7 +4216,7 @@ describe("useQuery Hook", () => { networkStatus: NetworkStatus.ready, }); - await expect(ProfiledHook).not.toRerender(); + await expect(takeSnapshot).not.toRerender(); act(() => { fetchMorePromise = fetchMore({ @@ -4221,8 +4226,7 @@ describe("useQuery Hook", () => { }); { - const { data, loading, networkStatus } = - await ProfiledHook.takeSnapshot(); + const { data, loading, networkStatus } = await takeSnapshot(); expect(loading).toBe(true); expect(networkStatus).toBe(NetworkStatus.fetchMore); @@ -4238,7 +4242,7 @@ describe("useQuery Hook", () => { { const { data, loading, networkStatus, observable } = - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); expect(loading).toBe(false); expect(networkStatus).toBe(NetworkStatus.ready); @@ -4268,7 +4272,7 @@ describe("useQuery Hook", () => { networkStatus: NetworkStatus.ready, }); - await expect(ProfiledHook).not.toRerender(); + await expect(takeSnapshot).not.toRerender(); }); it("throws when using fetchMore without updateQuery for no-cache queries", async () => { @@ -4276,22 +4280,22 @@ describe("useQuery Hook", () => { const client = new ApolloClient({ cache: new InMemoryCache(), link }); - const ProfiledHook = profileHook(() => - useQuery(query, { fetchPolicy: "no-cache", variables: { limit: 2 } }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { fetchPolicy: "no-cache", variables: { limit: 2 } }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - // loading - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); // finished loading - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); - const { fetchMore } = ProfiledHook.getCurrentSnapshot(); + const { fetchMore } = getCurrentSnapshot(); expect(() => fetchMore({ variables: { offset: 2 } })).toThrow( new InvariantError( @@ -4317,23 +4321,23 @@ describe("useQuery Hook", () => { const client = new ApolloClient({ cache: new InMemoryCache(), link }); - const ProfiledHook = profileHook(() => - useQuery(query, { fetchPolicy: "no-cache", variables: { limit: 2 } }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { fetchPolicy: "no-cache", variables: { limit: 2 } }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - // initial loading - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); // Initial result - await ProfiledHook.takeSnapshot(); + await takeSnapshot(); - const { fetchMore } = ProfiledHook.getCurrentSnapshot(); + const { fetchMore } = getCurrentSnapshot(); await act(() => fetchMore({ variables: { offset: 2 }, @@ -4483,7 +4487,7 @@ describe("useQuery Hook", () => { } `; - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { useQueryResult: null as QueryResult | null, useLazyQueryResult: null as QueryResult | null, @@ -4523,7 +4527,7 @@ describe("useQuery Hook", () => { variables: { id: 1 }, }); - Profiler.replaceSnapshot({ useQueryResult, useLazyQueryResult }); + renderStream.replaceSnapshot({ useQueryResult, useLazyQueryResult }); return ( <> @@ -4542,16 +4546,14 @@ describe("useQuery Hook", () => { ); } - render(, { + renderStream.render(, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4568,7 +4570,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4590,7 +4592,7 @@ describe("useQuery Hook", () => { await act(() => user.click(screen.getByText("Run 2nd query"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4610,7 +4612,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4647,7 +4649,7 @@ describe("useQuery Hook", () => { await act(() => user.click(screen.getByText("Reload 1st query"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4664,7 +4666,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4698,7 +4700,7 @@ describe("useQuery Hook", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("rerenders errored query for full cache write", async () => { @@ -4744,7 +4746,7 @@ describe("useQuery Hook", () => { } `; - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { useQueryResult: null as QueryResult | null, useLazyQueryResult: null as QueryResult | null, @@ -4790,21 +4792,19 @@ describe("useQuery Hook", () => { variables: { id: 1 }, }); - Profiler.replaceSnapshot({ useQueryResult, useLazyQueryResult }); + renderStream.replaceSnapshot({ useQueryResult, useLazyQueryResult }); return ; } - render(, { + renderStream.render(, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4821,7 +4821,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4843,7 +4843,7 @@ describe("useQuery Hook", () => { await act(() => user.click(screen.getByText("Run 2nd query"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -4863,7 +4863,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); // We don't see the update from the cache for one more render cycle, hence // why this is still showing the error result even though the result from @@ -4893,7 +4893,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: { @@ -4922,7 +4922,7 @@ describe("useQuery Hook", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("does not rerender or refetch queries with errors for partial cache writes with returnPartialData: true", async () => { @@ -4968,7 +4968,7 @@ describe("useQuery Hook", () => { } `; - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { useQueryResult: null as QueryResult | null, useLazyQueryResult: null as QueryResult | null, @@ -5014,21 +5014,19 @@ describe("useQuery Hook", () => { variables: { id: 1 }, }); - Profiler.replaceSnapshot({ useQueryResult, useLazyQueryResult }); + renderStream.replaceSnapshot({ useQueryResult, useLazyQueryResult }); return ; } - render(, { + renderStream.render(, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -5045,7 +5043,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -5067,7 +5065,7 @@ describe("useQuery Hook", () => { await act(() => user.click(screen.getByText("Run 2nd query"))); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -5087,7 +5085,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -5112,7 +5110,7 @@ describe("useQuery Hook", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("delivers the full network response when a merge function returns an incomplete result", async () => { @@ -5129,7 +5127,7 @@ describe("useQuery Hook", () => { } `; - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { useQueryResult: null as QueryResult | null, }, @@ -5174,21 +5172,19 @@ describe("useQuery Hook", () => { function App() { const useQueryResult = useQuery(query); - Profiler.replaceSnapshot({ useQueryResult }); + renderStream.replaceSnapshot({ useQueryResult }); return null; } - render(, { + renderStream.render(, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -5198,7 +5194,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: { @@ -5217,7 +5213,7 @@ describe("useQuery Hook", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); it("triggers a network request and rerenders with the new result when a mutation causes a partial cache update due to an incomplete merge function result", async () => { @@ -5250,7 +5246,7 @@ describe("useQuery Hook", () => { const user = userEvent.setup(); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { useQueryResult: null as QueryResult | null, }, @@ -5335,21 +5331,19 @@ describe("useQuery Hook", () => { const useQueryResult = useQuery(query); const [mutate] = useMutation(mutation); - Profiler.replaceSnapshot({ useQueryResult }); + renderStream.replaceSnapshot({ useQueryResult }); return ; } - render(, { + renderStream.render(, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: undefined, @@ -5359,7 +5353,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: { @@ -5379,10 +5373,10 @@ describe("useQuery Hook", () => { } await act(() => user.click(screen.getByText("Run mutation"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: { @@ -5402,7 +5396,7 @@ describe("useQuery Hook", () => { } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.useQueryResult).toMatchObject({ data: { @@ -5425,7 +5419,7 @@ describe("useQuery Hook", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); describe("Refetching", () => { @@ -5455,32 +5449,32 @@ describe("useQuery Hook", () => { ); - const ProfiledHook = profileHook(() => - useQuery(query, { - variables: { id: 1 }, - notifyOnNetworkStatusChange: true, - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { + variables: { id: 1 }, + notifyOnNetworkStatusChange: true, + }), + { wrapper } ); - - render(, { wrapper }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 1" }); } - ProfiledHook.getCurrentSnapshot().refetch({ id: 2 }); + getCurrentSnapshot().refetch({ id: 2 }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world 2" }); } @@ -5511,56 +5505,56 @@ describe("useQuery Hook", () => { const cache = new InMemoryCache(); - const ProfiledHook = profileHook(() => - useQuery(query, { - notifyOnNetworkStatusChange: true, - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { + notifyOnNetworkStatusChange: true, + }), + { + wrapper: ({ children }) => ( + + {children} + + ), + } ); - render(, { - wrapper: ({ children }) => ( - - {children} - - ), - }); - { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.error).toBe(undefined); expect(result.data).toEqual({ hello: "world 1" }); } - ProfiledHook.getCurrentSnapshot().refetch(); + getCurrentSnapshot().refetch(); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.error).toBe(undefined); expect(result.data).toEqual({ hello: "world 1" }); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.error).toBeInstanceOf(ApolloError); expect(result.data).toEqual({ hello: "world 1" }); } - ProfiledHook.getCurrentSnapshot().refetch(); + getCurrentSnapshot().refetch(); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.error).toBe(undefined); expect(result.data).toEqual({ hello: "world 1" }); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.error).toBe(undefined); expect(result.data).toEqual({ hello: "world 2" }); @@ -5820,25 +5814,25 @@ describe("useQuery Hook", () => { {children} ); - const ProfiledHook = profileHook(() => - useQuery(query, { - variables: { min: 0, max: 12 }, - notifyOnNetworkStatusChange: true, - // Intentionally not passing refetchWritePolicy. - }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { + variables: { min: 0, max: 12 }, + notifyOnNetworkStatusChange: true, + // Intentionally not passing refetchWritePolicy. + }), + { wrapper } ); - render(, { wrapper }); - { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.error).toBe(undefined); expect(result.data).toBe(undefined); expect(typeof result.refetch).toBe("function"); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.error).toBeUndefined(); expect(result.data).toEqual({ primes: [2, 3, 5, 7, 11] }); @@ -5846,12 +5840,10 @@ describe("useQuery Hook", () => { } const thenFn = jest.fn(); - ProfiledHook.getCurrentSnapshot() - .refetch({ min: 12, max: 30 }) - .then(thenFn); + getCurrentSnapshot().refetch({ min: 12, max: 30 }).then(thenFn); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.error).toBe(undefined); expect(result.data).toEqual({ @@ -5864,7 +5856,7 @@ describe("useQuery Hook", () => { } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.error).toBe(undefined); expect(result.data).toEqual({ primes: [13, 17, 19, 23, 29] }); @@ -6322,52 +6314,53 @@ describe("useQuery Hook", () => { const cache = new InMemoryCache(); const onCompleted = jest.fn(); - const ProfiledHook = profileHook(() => - useQuery(query, { - onCompleted, - notifyOnNetworkStatusChange: true, - pollInterval: 110, - }) + const { takeSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { + onCompleted, + notifyOnNetworkStatusChange: true, + pollInterval: 110, + }), + { + wrapper: ({ children }) => ( + + {children} + + ), + } ); - render(, { - wrapper: ({ children }) => ( - - {children} - - ), - }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.data).toEqual(undefined); expect(result.loading).toBe(true); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.data).toEqual({ hello: "world 1" }); expect(result.loading).toBe(false); expect(onCompleted).toHaveBeenCalledTimes(1); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.data).toEqual({ hello: "world 1" }); expect(result.loading).toBe(true); expect(onCompleted).toHaveBeenCalledTimes(1); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.data).toEqual({ hello: "world 2" }); expect(result.loading).toBe(false); expect(onCompleted).toHaveBeenCalledTimes(2); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.data).toEqual({ hello: "world 2" }); expect(result.loading).toBe(true); expect(onCompleted).toHaveBeenCalledTimes(2); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.data).toEqual({ hello: "world 3" }); expect(result.loading).toBe(false); expect(onCompleted).toHaveBeenCalledTimes(3); @@ -6616,51 +6609,53 @@ describe("useQuery Hook", () => { ); const onError = jest.fn(); - const ProfiledHook = profileHook(() => ({ - mutation: useMutation(mutation, { - optimisticResponse: { addCar: carData }, - update(cache, { data }) { - cache.modify({ - fields: { - cars(existing, { readField }) { - const newCarRef = cache.writeFragment({ - data: data!.addCar, - fragment: gql` - fragment NewCar on Car { - id - make - model - } - `, - }); - - if ( - existing.some( - (ref: Reference) => - readField("id", ref) === data!.addCar.id - ) - ) { - return existing; - } - - return [...existing, newCarRef]; + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => ({ + mutation: useMutation(mutation, { + optimisticResponse: { addCar: carData }, + update(cache, { data }) { + cache.modify({ + fields: { + cars(existing, { readField }) { + const newCarRef = cache.writeFragment({ + data: data!.addCar, + fragment: gql` + fragment NewCar on Car { + id + make + model + } + `, + }); + + if ( + existing.some( + (ref: Reference) => + readField("id", ref) === data!.addCar.id + ) + ) { + return existing; + } + + return [...existing, newCarRef]; + }, }, - }, - }); - }, - onError, + }); + }, + onError, + }), + query: useQuery(query), }), - query: useQuery(query), - })); - render(, { wrapper }); + { wrapper } + ); { - const { query } = await ProfiledHook.takeSnapshot(); + const { query } = await takeSnapshot(); expect(query.loading).toBe(true); } - const mutate = ProfiledHook.getCurrentSnapshot().mutation[0]; + const mutate = getCurrentSnapshot().mutation[0]; { - const { query } = await ProfiledHook.takeSnapshot(); + const { query } = await takeSnapshot(); expect(query.loading).toBe(false); expect(query.loading).toBe(false); expect(query.data).toEqual(carsData); @@ -6672,13 +6667,13 @@ describe("useQuery Hook", () => { // The mutation ran and is loading the result. The query stays at not // loading as nothing has changed for the query, but optimistic data is // rendered. - let { query, mutation } = await ProfiledHook.takeSnapshot(); + let { query, mutation } = await takeSnapshot(); while (!mutation[1].loading) { // useMutation seems to sometimes have an extra render // before it enters `loading` state - this test doesn't test // that part of that hook so we just work around it - ({ query, mutation } = await ProfiledHook.takeSnapshot()); + ({ query, mutation } = await takeSnapshot()); } expect(mutation[1].loading).toBe(true); expect(query.loading).toBe(false); @@ -6687,7 +6682,7 @@ describe("useQuery Hook", () => { expect(onError).toHaveBeenCalledTimes(0); { - const { query, mutation } = await ProfiledHook.takeSnapshot(); + const { query, mutation } = await takeSnapshot(); // The mutation ran and is loading the result. The query stays at // not loading as nothing has changed for the query. expect(mutation[1].loading).toBe(true); @@ -6695,7 +6690,7 @@ describe("useQuery Hook", () => { } { - const { query, mutation } = await ProfiledHook.takeSnapshot(); + const { query, mutation } = await takeSnapshot(); // The mutation has completely finished, leaving the query with access to // the original cache data. expect(mutation[1].loading).toBe(false); @@ -6878,17 +6873,17 @@ describe("useQuery Hook", () => { {children} ); - const ProfiledHook = profileHook(() => - useQuery(query, { - partialRefetch: true, - notifyOnNetworkStatusChange: true, - }) + const { takeSnapshot } = renderHookToSnapshotStream( + () => + useQuery(query, { + partialRefetch: true, + notifyOnNetworkStatusChange: true, + }), + { wrapper } ); - render(, { wrapper }); - { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.error).toBe(undefined); @@ -6896,7 +6891,7 @@ describe("useQuery Hook", () => { } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.networkStatus).toBe(NetworkStatus.refetch); expect(result.loading).toBe(true); expect(result.error).toBe(undefined); @@ -6911,7 +6906,7 @@ describe("useQuery Hook", () => { expect(calls[0][0]).toMatch("Missing field"); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.networkStatus).toBe(NetworkStatus.ready); expect(result.loading).toBe(false); expect(result.data).toEqual({ hello: "world" }); @@ -7844,21 +7839,20 @@ describe("useQuery Hook", () => { ); - const ProfiledHook = profileHook(() => - useQuery(query, { notifyOnNetworkStatusChange: true }) + const { takeSnapshot } = renderHookToSnapshotStream( + () => useQuery(query, { notifyOnNetworkStatusChange: true }), + { wrapper } ); - render(, { wrapper }); - { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); expect(result.previousData).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual(data1); expect(result.previousData).toBe(undefined); @@ -7867,14 +7861,14 @@ describe("useQuery Hook", () => { } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toEqual(data1); expect(result.previousData).toEqual(data1); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toEqual(data2); expect(result.previousData).toEqual(data1); @@ -8305,22 +8299,23 @@ describe("useQuery Hook", () => { ); - const ProfiledHook = profileHook(({ gender }: { gender: string }) => - useQuery(query, { - variables: { gender }, - fetchPolicy: "network-only", - }) + const { takeSnapshot, rerender } = renderHookToSnapshotStream( + ({ gender }: { gender: string }) => + useQuery(query, { + variables: { gender }, + fetchPolicy: "network-only", + }), + { wrapper, initialProps: { gender: "all" } } ); - const { rerender } = render(, { wrapper }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.networkStatus).toBe(NetworkStatus.loading); expect(result.data).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.networkStatus).toBe(NetworkStatus.ready); expect(result.data).toEqual({ @@ -8328,17 +8323,17 @@ describe("useQuery Hook", () => { }); } - rerender(); + rerender({ gender: "female" }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.networkStatus).toBe(NetworkStatus.setVariables); expect(result.data).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.networkStatus).toBe(NetworkStatus.ready); expect(result.data).toEqual({ @@ -8348,16 +8343,16 @@ describe("useQuery Hook", () => { }); } - rerender(); + rerender({ gender: "nonbinary" }); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.networkStatus).toBe(NetworkStatus.setVariables); expect(result.data).toBe(undefined); } { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.networkStatus).toBe(NetworkStatus.ready); expect(result.data).toEqual({ @@ -10096,8 +10091,7 @@ describe("useQuery Hook", () => { link, cache: new InMemoryCache(), }); - const ProfiledHook = profileHook(() => useQuery(query)); - render(, { + const { takeSnapshot } = renderHookToSnapshotStream(() => useQuery(query), { wrapper: ({ children }) => ( {children} ), @@ -10105,7 +10099,7 @@ describe("useQuery Hook", () => { expect(requests).toBe(1); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBeUndefined(); } @@ -10113,7 +10107,7 @@ describe("useQuery Hook", () => { client.clearStore(); { - const result = await ProfiledHook.takeSnapshot(); + const result = await takeSnapshot(); expect(result.loading).toBe(false); expect(result.data).toBeUndefined(); expect(result.error).toEqual( @@ -10126,7 +10120,7 @@ describe("useQuery Hook", () => { } link.simulateResult({ result: { data: { hello: "Greetings" } } }, true); - await expect(ProfiledHook).not.toRerender({ timeout: 50 }); + await expect(takeSnapshot).not.toRerender({ timeout: 50 }); expect(requests).toBe(1); }); @@ -10155,18 +10149,17 @@ describe("useQuery Hook", () => { }, ]; - const ProfiledHook = profileHook(() => - useQuery(query, { notifyOnNetworkStatusChange: true }) + const { takeSnapshot, getCurrentSnapshot } = renderHookToSnapshotStream( + () => useQuery(query, { notifyOnNetworkStatusChange: true }), + { + wrapper: ({ children }) => ( + {children} + ), + } ); - render(, { - wrapper: ({ children }) => ( - {children} - ), - }); - { - const { loading, data, error } = await ProfiledHook.takeSnapshot(); + const { loading, data, error } = await takeSnapshot(); expect(loading).toBe(true); expect(data).toBeUndefined(); @@ -10174,21 +10167,20 @@ describe("useQuery Hook", () => { } { - const { loading, data, error } = await ProfiledHook.takeSnapshot(); + const { loading, data, error } = await takeSnapshot(); expect(loading).toBe(false); expect(data).toBeUndefined(); expect(error).toEqual(new ApolloError({ graphQLErrors: [graphQLError] })); } - const { refetch } = ProfiledHook.getCurrentSnapshot(); + const { refetch } = getCurrentSnapshot(); refetch().catch(() => {}); refetch().catch(() => {}); { - const { loading, networkStatus, data, error } = - await ProfiledHook.takeSnapshot(); + const { loading, networkStatus, data, error } = await takeSnapshot(); expect(loading).toBe(true); expect(data).toBeUndefined(); @@ -10197,8 +10189,7 @@ describe("useQuery Hook", () => { } { - const { loading, networkStatus, data, error } = - await ProfiledHook.takeSnapshot(); + const { loading, networkStatus, data, error } = await takeSnapshot(); expect(loading).toBe(false); expect(data).toBeUndefined(); @@ -10206,7 +10197,7 @@ describe("useQuery Hook", () => { expect(error).toEqual(new ApolloError({ graphQLErrors: [graphQLError] })); } - await expect(ProfiledHook).not.toRerender({ timeout: 200 }); + await expect(takeSnapshot).not.toRerender({ timeout: 200 }); }); }); diff --git a/src/react/hooks/__tests__/useQueryRefHandlers.test.tsx b/src/react/hooks/__tests__/useQueryRefHandlers.test.tsx index 536d8ca2edb..e22c2256128 100644 --- a/src/react/hooks/__tests__/useQueryRefHandlers.test.tsx +++ b/src/react/hooks/__tests__/useQueryRefHandlers.test.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { act, render, screen } from "@testing-library/react"; +import { act, screen } from "@testing-library/react"; import { ApolloClient, InMemoryCache, @@ -15,13 +15,11 @@ import { MockedResponse, } from "../../../testing"; import { + createClientWrapper, PaginatedCaseData, SimpleCaseData, - createProfiler, - renderWithClient, setupPaginatedCase, setupSimpleCase, - useTrackRenders, } from "../../../testing/internal"; import { useQueryRefHandlers } from "../useQueryRefHandlers"; import { UseReadQueryResult, useReadQuery } from "../useReadQuery"; @@ -33,6 +31,10 @@ import { QueryRef } from "../../internal"; import { useBackgroundQuery } from "../useBackgroundQuery"; import { useLoadableQuery } from "../useLoadableQuery"; import { concatPagination, getMainDefinition } from "../../../utilities"; +import { + createRenderStream, + useTrackRenders, +} from "@testing-library/react-render-stream"; test("does not interfere with updates from useReadQuery", async () => { const { query, mocks } = setupSimpleCase(); @@ -42,7 +44,7 @@ test("does not interfere with updates from useReadQuery", async () => { link: new MockLink(mocks), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -58,7 +60,7 @@ test("does not interfere with updates from useReadQuery", async () => { function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -77,16 +79,17 @@ test("does not interfere with updates from useReadQuery", async () => { ); } - const { rerender } = renderWithClient(, { client, wrapper: Profiler }); - + const { rerender } = renderStream.render(, { + wrapper: createClientWrapper(client), + }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -98,7 +101,7 @@ test("does not interfere with updates from useReadQuery", async () => { client.writeQuery({ query, data: { greeting: "Hello again" } }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -111,7 +114,7 @@ test("does not interfere with updates from useReadQuery", async () => { rerender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -141,7 +144,7 @@ test("refetches and resuspends when calling refetch", async () => { link: new MockLink(mocks), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -156,7 +159,7 @@ test("refetches and resuspends when calling refetch", async () => { } function ReadQueryHook() { - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -175,16 +178,16 @@ test("refetches and resuspends when calling refetch", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -196,13 +199,13 @@ test("refetches and resuspends when calling refetch", async () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello again" }, @@ -262,7 +265,7 @@ test('honors refetchWritePolicy set to "merge"', async () => { cache, }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -280,7 +283,7 @@ test('honors refetchWritePolicy set to "merge"', async () => { } function ReadQueryHook() { - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -299,13 +302,13 @@ test('honors refetchWritePolicy set to "merge"', async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -316,10 +319,10 @@ test('honors refetchWritePolicy set to "merge"', async () => { } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] }, @@ -335,7 +338,7 @@ test('honors refetchWritePolicy set to "merge"', async () => { ]); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test('honors refetchWritePolicy set to "overwrite"', async () => { @@ -388,7 +391,7 @@ test('honors refetchWritePolicy set to "overwrite"', async () => { cache, }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -406,7 +409,7 @@ test('honors refetchWritePolicy set to "overwrite"', async () => { } function ReadQueryHook() { - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -425,13 +428,13 @@ test('honors refetchWritePolicy set to "overwrite"', async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -442,10 +445,10 @@ test('honors refetchWritePolicy set to "overwrite"', async () => { } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [13, 17, 19, 23, 29] }, @@ -458,7 +461,7 @@ test('honors refetchWritePolicy set to "overwrite"', async () => { ]); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test('defaults refetchWritePolicy to "overwrite"', async () => { @@ -511,7 +514,7 @@ test('defaults refetchWritePolicy to "overwrite"', async () => { cache, }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -528,7 +531,7 @@ test('defaults refetchWritePolicy to "overwrite"', async () => { } function ReadQueryHook() { - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -547,13 +550,13 @@ test('defaults refetchWritePolicy to "overwrite"', async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [2, 3, 5, 7, 11] }, @@ -564,10 +567,10 @@ test('defaults refetchWritePolicy to "overwrite"', async () => { } await act(() => user.click(screen.getByText("Refetch"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { primes: [13, 17, 19, 23, 29] }, @@ -580,7 +583,7 @@ test('defaults refetchWritePolicy to "overwrite"', async () => { ]); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("`refetch` works with startTransition", async () => { @@ -629,7 +632,7 @@ test("`refetch` works with startTransition", async () => { cache: new InMemoryCache(), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { isPending: false, result: null as UseReadQueryResult | null, @@ -644,7 +647,7 @@ test("`refetch` works with startTransition", async () => { const { refetch } = useQueryRefHandlers(queryRef); const [isPending, startTransition] = React.useTransition(); - Profiler.mergeSnapshot({ isPending }); + renderStream.mergeSnapshot({ isPending }); return ( <> @@ -675,7 +678,7 @@ test("`refetch` works with startTransition", async () => { const result = useReadQuery(queryRef); const { todo } = result.data; - Profiler.mergeSnapshot({ result }); + renderStream.mergeSnapshot({ result }); return (
@@ -685,16 +688,16 @@ test("`refetch` works with startTransition", async () => { ); } - render(, { wrapper: Profiler }); + renderStream.render(); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot).toEqual({ isPending: false, @@ -710,7 +713,7 @@ test("`refetch` works with startTransition", async () => { await act(() => user.click(button)); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, Todo]); expect(snapshot).toEqual({ @@ -724,7 +727,7 @@ test("`refetch` works with startTransition", async () => { } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, Todo]); expect(snapshot).toEqual({ @@ -737,7 +740,7 @@ test("`refetch` works with startTransition", async () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("`refetch` works with startTransition from useBackgroundQuery and usePreloadedQueryHandlers", async () => { @@ -764,7 +767,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa link: new MockLink(mocks), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { useBackgroundQueryIsPending: false, usePreloadedQueryHandlersIsPending: false, @@ -782,7 +785,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa const [isPending, startTransition] = React.useTransition(); const { refetch } = useQueryRefHandlers(queryRef); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ usePreloadedQueryHandlersIsPending: isPending, result: useReadQuery(queryRef), }); @@ -805,7 +808,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa const [isPending, startTransition] = React.useTransition(); const [queryRef, { refetch }] = useBackgroundQuery(query); - Profiler.mergeSnapshot({ useBackgroundQueryIsPending: isPending }); + renderStream.mergeSnapshot({ useBackgroundQueryIsPending: isPending }); return ( <> @@ -825,16 +828,16 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -846,7 +849,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa await act(() => user.click(screen.getByText("Refetch from parent"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -861,7 +864,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot).toEqual({ @@ -878,7 +881,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa await act(() => user.click(screen.getByText("Refetch from child"))); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot).toEqual({ @@ -893,7 +896,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([ReadQueryHook]); expect(snapshot).toEqual({ @@ -907,7 +910,7 @@ test("`refetch` works with startTransition from useBackgroundQuery and usePreloa }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("refetches from queryRefs produced by useBackgroundQuery", async () => { @@ -929,7 +932,7 @@ test("refetches from queryRefs produced by useBackgroundQuery", async () => { link: new MockLink(mocks), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -942,7 +945,7 @@ test("refetches from queryRefs produced by useBackgroundQuery", async () => { function ReadQueryHook({ queryRef }: { queryRef: QueryRef }) { const { refetch } = useQueryRefHandlers(queryRef); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return ; } @@ -960,16 +963,16 @@ test("refetches from queryRefs produced by useBackgroundQuery", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -981,13 +984,13 @@ test("refetches from queryRefs produced by useBackgroundQuery", async () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello again" }, @@ -1016,7 +1019,7 @@ test("refetches from queryRefs produced by useLoadableQuery", async () => { link: new MockLink(mocks), }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -1029,7 +1032,7 @@ test("refetches from queryRefs produced by useLoadableQuery", async () => { function ReadQueryHook({ queryRef }: { queryRef: QueryRef }) { const { refetch } = useQueryRefHandlers(queryRef); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return ; } @@ -1048,21 +1051,21 @@ test("refetches from queryRefs produced by useLoadableQuery", async () => { ); } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); await act(() => user.click(screen.getByText("Load query"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1074,13 +1077,13 @@ test("refetches from queryRefs produced by useLoadableQuery", async () => { await act(() => user.click(screen.getByText("Refetch"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello again" }, @@ -1109,7 +1112,7 @@ test("resuspends when calling `fetchMore`", async () => { }); const preloadQuery = createQueryPreloader(client); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -1122,7 +1125,7 @@ test("resuspends when calling `fetchMore`", async () => { function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -1146,16 +1149,16 @@ test("resuspends when calling `fetchMore`", async () => { } const queryRef = preloadQuery(query); - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1172,13 +1175,13 @@ test("resuspends when calling `fetchMore`", async () => { await act(() => user.click(screen.getByText("Load next"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1201,7 +1204,7 @@ test("properly uses `updateQuery` when calling `fetchMore`", async () => { const client = new ApolloClient({ cache: new InMemoryCache(), link }); const preloadQuery = createQueryPreloader(client); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -1214,7 +1217,7 @@ test("properly uses `updateQuery` when calling `fetchMore`", async () => { function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -1245,16 +1248,16 @@ test("properly uses `updateQuery` when calling `fetchMore`", async () => { } const queryRef = preloadQuery(query); - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1271,13 +1274,13 @@ test("properly uses `updateQuery` when calling `fetchMore`", async () => { await act(() => user.click(screen.getByText("Load next"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1313,7 +1316,7 @@ test("properly uses cache field policies when calling `fetchMore` without `updat }); const preloadQuery = createQueryPreloader(client); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -1326,7 +1329,7 @@ test("properly uses cache field policies when calling `fetchMore` without `updat function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -1350,16 +1353,16 @@ test("properly uses cache field policies when calling `fetchMore` without `updat } const queryRef = preloadQuery(query); - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1376,13 +1379,13 @@ test("properly uses cache field policies when calling `fetchMore` without `updat await act(() => user.click(screen.getByText("Load next"))); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -1416,7 +1419,7 @@ test("paginates from queryRefs produced by useBackgroundQuery", async () => { link, }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -1435,7 +1438,7 @@ test("paginates from queryRefs produced by useBackgroundQuery", async () => { useTrackRenders(); const { fetchMore } = useQueryRefHandlers(queryRef); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return (
}>{children} - - - ), - }); + renderStream.render( + Loading...
}> + + , + { + wrapper: ({ children }) => ( + {children} + ), + } + ); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App]); expect(snapshot.result?.data).toEqual({ @@ -10537,10 +10537,10 @@ describe("useSuspenseQuery", () => { } await act(() => user.click(screen.getByText("Fetch next"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ letters: [ @@ -10553,10 +10553,10 @@ describe("useSuspenseQuery", () => { } await act(() => user.click(screen.getByText("Fetch next"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ letters: [ @@ -10568,7 +10568,7 @@ describe("useSuspenseQuery", () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); describe.skip("type tests", () => { diff --git a/src/react/query-preloader/__tests__/createQueryPreloader.test.tsx b/src/react/query-preloader/__tests__/createQueryPreloader.test.tsx index 8ab59054dd6..a0d60a66a96 100644 --- a/src/react/query-preloader/__tests__/createQueryPreloader.test.tsx +++ b/src/react/query-preloader/__tests__/createQueryPreloader.test.tsx @@ -20,21 +20,23 @@ import { expectTypeOf } from "expect-type"; import { PreloadedQueryRef, QueryRef, unwrapQueryRef } from "../../internal"; import { DeepPartial, Observable } from "../../../utilities"; import { + createClientWrapper, SimpleCaseData, - createProfiler, spyOnConsole, setupSimpleCase, - useTrackRenders, setupVariablesCase, - renderWithClient, VariablesCaseData, } from "../../../testing/internal"; import { ApolloProvider } from "../../context"; -import { act, render, renderHook, screen } from "@testing-library/react"; +import { act, renderHook, screen } from "@testing-library/react"; import { UseReadQueryResult, useReadQuery } from "../../hooks"; import { GraphQLError } from "graphql"; import { ErrorBoundary } from "react-error-boundary"; import userEvent from "@testing-library/user-event"; +import { + createRenderStream, + useTrackRenders, +} from "@testing-library/react-render-stream"; function createDefaultClient(mocks: MockedResponse[]) { return new ApolloClient({ @@ -50,7 +52,7 @@ function renderDefaultTestApp({ client: ApolloClient; queryRef: QueryRef; }) { - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, error: null as Error | null, @@ -59,7 +61,7 @@ function renderDefaultTestApp({ function ReadQueryHook() { useTrackRenders({ name: "ReadQueryHook" }); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } @@ -71,7 +73,7 @@ function renderDefaultTestApp({ function ErrorFallback({ error }: { error: Error }) { useTrackRenders({ name: "ErrorFallback" }); - Profiler.mergeSnapshot({ error }); + renderStream.mergeSnapshot({ error }); return null; } @@ -88,11 +90,9 @@ function renderDefaultTestApp({ ); } - const utils = render(, { + const utils = renderStream.render(, { wrapper: ({ children }) => ( - - {children} - + {children} ), }); @@ -100,7 +100,7 @@ function renderDefaultTestApp({ return utils.rerender(); } - return { ...utils, rerender, Profiler }; + return { ...utils, rerender, renderStream }; } test("loads a query and suspends when passed to useReadQuery", async () => { @@ -110,16 +110,16 @@ test("loads a query and suspends when passed to useReadQuery", async () => { const queryRef = preloadQuery(query); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -138,16 +138,16 @@ test("loads a query with variables and suspends when passed to useReadQuery", as variables: { id: "1" }, }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -256,7 +256,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => }); }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -288,20 +288,20 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); const toggleButton = screen.getByText("Toggle"); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 1" }, @@ -315,7 +315,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => // unmount ReadQueryHook await act(() => user.click(toggleButton)); await wait(0); - await Profiler.takeRender(); + await renderStream.takeRender(); expect(queryRef).toBeDisposed(); @@ -325,7 +325,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => // Ensure we aren't refetching the data by checking we still render the same // cache result { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -342,7 +342,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => // Ensure we can get cache updates again after remounting { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello (cached)" }, @@ -353,7 +353,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -369,7 +369,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => // Ensure we read the newest cache result changed while this queryRef was // disposed { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "While you were away" }, @@ -382,7 +382,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -407,13 +407,13 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => expect(queryRef).not.toBeDisposed(); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 2" }, @@ -422,7 +422,7 @@ test("useReadQuery auto-resubscribes the query after its disposed", async () => }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("useReadQuery handles auto-resubscribe with returnPartialData", async () => { @@ -449,7 +449,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => }); }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult> | null, }, @@ -484,20 +484,20 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); const toggleButton = screen.getByText("Toggle"); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -513,7 +513,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => // unmount ReadQueryHook await act(() => user.click(toggleButton)); await wait(0); - await Profiler.takeRender(); + await renderStream.takeRender(); expect(queryRef).toBeDisposed(); @@ -523,7 +523,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => // Ensure we aren't refetching the data by checking we still render the same // cache result { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -552,7 +552,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => // Ensure we can get cache updates again after remounting { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -569,7 +569,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -595,7 +595,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => // Ensure we read the newest cache result changed while this queryRef was // disposed { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -614,7 +614,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -640,7 +640,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => expect(queryRef).not.toBeDisposed(); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -651,7 +651,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -664,7 +664,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); // Ensure that remounting without data in the cache will fetch and suspend @@ -676,13 +676,13 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => expect(fetchCount).toBe(3); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { @@ -693,7 +693,7 @@ test("useReadQuery handles auto-resubscribe with returnPartialData", async () => }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("useReadQuery handles auto-resubscribe on network-only fetch policy", async () => { @@ -710,7 +710,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async }); }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -742,20 +742,20 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); const toggleButton = screen.getByText("Toggle"); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 1" }, @@ -769,7 +769,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async // unmount ReadQueryHook await act(() => user.click(toggleButton)); await wait(0); - await Profiler.takeRender(); + await renderStream.takeRender(); expect(queryRef).toBeDisposed(); @@ -779,7 +779,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async // Ensure we aren't refetching the data by checking we still render the same // cache result { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -796,7 +796,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async // Ensure we can get cache updates again after remounting { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello (cached)" }, @@ -807,7 +807,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -823,7 +823,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async // Ensure we read the newest cache result changed while this queryRef was // disposed { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "While you were away" }, @@ -836,7 +836,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -859,13 +859,13 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async expect(queryRef).not.toBeDisposed(); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 2" }, @@ -874,7 +874,7 @@ test("useReadQuery handles auto-resubscribe on network-only fetch policy", async }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", async () => { @@ -891,7 +891,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", }); }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -923,20 +923,20 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); const toggleButton = screen.getByText("Toggle"); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 1" }, @@ -950,7 +950,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", // unmount ReadQueryHook await act(() => user.click(toggleButton)); await wait(0); - await Profiler.takeRender(); + await renderStream.takeRender(); expect(queryRef).toBeDisposed(); @@ -960,7 +960,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", // Ensure we aren't refetching the data by checking we still render the same // cache result { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -977,7 +977,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", // Ensure we can get cache updates again after remounting { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello (cached)" }, @@ -988,7 +988,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -1004,7 +1004,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", // Ensure we read the newest cache result changed while this queryRef was // disposed { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "While you were away" }, @@ -1017,7 +1017,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -1040,13 +1040,13 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", expect(queryRef).not.toBeDisposed(); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, SuspenseFallback]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 2" }, @@ -1055,7 +1055,7 @@ test("useReadQuery handles auto-resubscribe on cache-and-network fetch policy", }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () => { @@ -1072,7 +1072,7 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () }); }); - const Profiler = createProfiler({ + const renderStream = createRenderStream({ initialSnapshot: { result: null as UseReadQueryResult | null, }, @@ -1104,20 +1104,20 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () function ReadQueryHook() { useTrackRenders(); - Profiler.mergeSnapshot({ result: useReadQuery(queryRef) }); + renderStream.mergeSnapshot({ result: useReadQuery(queryRef) }); return null; } - renderWithClient(, { client, wrapper: Profiler }); + renderStream.render(, { wrapper: createClientWrapper(client) }); const toggleButton = screen.getByText("Toggle"); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 1" }, @@ -1131,7 +1131,7 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () // unmount ReadQueryHook await act(() => user.click(toggleButton)); await wait(0); - await Profiler.takeRender(); + await renderStream.takeRender(); expect(queryRef).toBeDisposed(); @@ -1141,7 +1141,7 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () // Ensure we aren't refetching the data by checking we still render the same // result { - const { renderedComponents, snapshot } = await Profiler.takeRender(); + const { renderedComponents, snapshot } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1157,11 +1157,11 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () // Ensure caches writes for the query are ignored by the hook client.writeQuery({ query, data: { greeting: "Hello (cached)" } }); - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -1175,7 +1175,7 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () // Ensure we continue to read the same value { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello 1" }, @@ -1188,7 +1188,7 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () // unmount ReadQueryHook await act(() => user.click(toggleButton)); - await Profiler.takeRender(); + await renderStream.takeRender(); await wait(0); expect(queryRef).toBeDisposed(); @@ -1213,7 +1213,7 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () // Ensure we are still rendering the same result and haven't refetched // anything based on missing cache data { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual([App, ReadQueryHook]); expect(snapshot.result).toEqual({ @@ -1223,7 +1223,7 @@ test("useReadQuery handles auto-resubscribe on no-cache fetch policy", async () }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("reacts to cache updates", async () => { @@ -1233,16 +1233,16 @@ test("reacts to cache updates", async () => { const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1257,7 +1257,7 @@ test("reacts to cache updates", async () => { }); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello (updated)" }, @@ -1278,16 +1278,16 @@ test("ignores cached result and suspends when `fetchPolicy` is network-only", as fetchPolicy: "network-only", }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1307,16 +1307,16 @@ test("does not cache results when `fetchPolicy` is no-cache", async () => { fetchPolicy: "no-cache", }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { greeting: "Hello" }, @@ -1339,10 +1339,10 @@ test("returns initial cache data followed by network data when `fetchPolicy` is fetchPolicy: "cache-and-network", }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1353,7 +1353,7 @@ test("returns initial cache data followed by network data when `fetchPolicy` is } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1373,10 +1373,10 @@ test("returns cached data when all data is present in the cache", async () => { const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1386,7 +1386,7 @@ test("returns cached data when all data is present in the cache", async () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("suspends and ignores partial data in the cache", async () => { @@ -1417,16 +1417,16 @@ test("suspends and ignores partial data in the cache", async () => { const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1436,7 +1436,7 @@ test("suspends and ignores partial data in the cache", async () => { }); } - await expect(Profiler).not.toRerender(); + await expect(renderStream).not.toRerender(); }); test("throws when error is returned", async () => { @@ -1452,16 +1452,16 @@ test("throws when error is returned", async () => { const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ErrorFallback"]); expect(snapshot.error).toEqual( @@ -1483,16 +1483,16 @@ test("returns error when error policy is 'all'", async () => { const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query, { errorPolicy: "all" }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1517,16 +1517,16 @@ test("discards error when error policy is 'ignore'", async () => { const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query, { errorPolicy: "ignore" }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1567,12 +1567,12 @@ test("passes context to the link", async () => { context: { valueA: "A", valueB: "B" }, }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); // initial render - await Profiler.takeRender(); + await renderStream.takeRender(); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result).toEqual({ data: { context: { valueA: "A", valueB: "B" } }, @@ -1633,10 +1633,10 @@ test("does not suspend and returns partial data when `returnPartialData` is `tru returnPartialData: true, }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1647,7 +1647,7 @@ test("does not suspend and returns partial data when `returnPartialData` is `tru } { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1705,9 +1705,9 @@ test('enables canonical results when canonizeResults is "true"', async () => { const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query, { canonizeResults: true }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const resultSet = new Set(snapshot.result?.data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -1763,9 +1763,9 @@ test("can disable canonical results when the cache's canonizeResults setting is const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query, { canonizeResults: false }); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); const resultSet = new Set(snapshot.result!.data.results); const values = Array.from(resultSet).map((item) => item.value); @@ -1798,10 +1798,10 @@ test("suspends deferred queries until initial chunk loads then rerenders with de const preloadQuery = createQueryPreloader(client); const queryRef = preloadQuery(query); - const { Profiler } = renderDefaultTestApp({ client, queryRef }); + const { renderStream } = renderDefaultTestApp({ client, queryRef }); { - const { renderedComponents } = await Profiler.takeRender(); + const { renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["App", "SuspenseFallback"]); } @@ -1814,7 +1814,7 @@ test("suspends deferred queries until initial chunk loads then rerenders with de }); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ReadQueryHook"]); expect(snapshot.result).toEqual({ @@ -1843,7 +1843,7 @@ test("suspends deferred queries until initial chunk loads then rerenders with de ); { - const { snapshot, renderedComponents } = await Profiler.takeRender(); + const { snapshot, renderedComponents } = await renderStream.takeRender(); expect(renderedComponents).toStrictEqual(["ReadQueryHook"]); expect(snapshot.result).toEqual({ diff --git a/src/testing/experimental/__tests__/createTestSchema.test.tsx b/src/testing/experimental/__tests__/createTestSchema.test.tsx index 60ad1e08bd5..5904e707e65 100644 --- a/src/testing/experimental/__tests__/createTestSchema.test.tsx +++ b/src/testing/experimental/__tests__/createTestSchema.test.tsx @@ -6,12 +6,7 @@ import { gql, } from "../../../core/index.js"; import type { TypedDocumentNode } from "../../../core/index.js"; -import { - Profiler, - createProfiler, - renderWithClient, - spyOnConsole, -} from "../../internal/index.js"; +import { spyOnConsole, createClientWrapper } from "../../internal/index.js"; import { createTestSchema } from "../createTestSchema.js"; import { buildSchema } from "graphql"; import type { UseSuspenseQueryResult } from "../../../react/index.js"; @@ -24,6 +19,10 @@ import { ErrorBoundary as ReactErrorBoundary, } from "react-error-boundary"; import { InvariantError } from "ts-invariant"; +import { + RenderStream, + createRenderStream, +} from "@testing-library/react-render-stream"; const typeDefs = /* GraphQL */ ` type User { @@ -88,7 +87,7 @@ const schemaWithTypeDefs = buildSchema(typeDefs); const uri = "https://localhost:3000/graphql"; function createDefaultProfiler() { - return createProfiler({ + return createRenderStream({ initialSnapshot: { result: null as UseSuspenseQueryResult | null, }, @@ -96,7 +95,7 @@ function createDefaultProfiler() { } function createErrorProfiler() { - return createProfiler({ + return createRenderStream({ initialSnapshot: { error: null as Error | null, result: null as UseSuspenseQueryResult | null, @@ -105,10 +104,10 @@ function createErrorProfiler() { } function createTrackedErrorComponents( - Profiler: Profiler + renderStream: RenderStream ) { function ErrorFallback({ error }: FallbackProps) { - Profiler.mergeSnapshot({ error } as Partial); + renderStream.mergeSnapshot({ error } as Partial); return
Error
; } @@ -170,7 +169,7 @@ describe("schema proxy", () => { }); it("mocks scalars and resolvers", async () => { - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); using _fetch = createSchemaFetch(schema).mockGlobal(); @@ -209,23 +208,22 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, }); return
Hello
; }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -258,7 +256,7 @@ describe("schema proxy", () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); using _fetch = createSchemaFetch(forkedSchema).mockGlobal(); @@ -297,23 +295,22 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); return
Hello
; }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -336,7 +333,7 @@ describe("schema proxy", () => { }); it("schema.fork does not pollute the original schema", async () => { - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); schema.fork({ resolvers: { @@ -388,23 +385,22 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); return
Hello
; }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -439,7 +435,7 @@ describe("schema proxy", () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); using _fetch = createSchemaFetch(forkedSchema).mockGlobal(); @@ -478,23 +474,22 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); return
Hello
; }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -556,7 +551,7 @@ describe("schema proxy", () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); using _fetch = createSchemaFetch(forkedSchema).mockGlobal(); @@ -590,7 +585,7 @@ describe("schema proxy", () => { const result = useSuspenseQuery(query); const [changeViewerName] = useMutation(mutation); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); @@ -604,16 +599,15 @@ describe("schema proxy", () => { const user = userEvent.setup(); - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -635,9 +629,9 @@ describe("schema proxy", () => { await act(() => user.click(screen.getByText("Change name"))); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -692,9 +686,9 @@ describe("schema proxy", () => { }, }); - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); using _fetch = createSchemaFetch(forkedSchema).mockGlobal(); @@ -720,23 +714,22 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); return
Hello
; }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.error).toEqual( new ApolloError({ @@ -768,9 +761,9 @@ describe("schema proxy", () => { // invalid schema const forkedSchema = { foo: "bar" }; - const Profiler = createErrorProfiler(); + const renderStream = createErrorProfiler(); - const { ErrorBoundary } = createTrackedErrorComponents(Profiler); + const { ErrorBoundary } = createTrackedErrorComponents(renderStream); // @ts-expect-error - we're intentionally passing an invalid schema using _fetch = createSchemaFetch(forkedSchema).mockGlobal(); @@ -797,23 +790,22 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); return
Hello
; }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.error).toEqual( new ApolloError({ @@ -892,7 +884,7 @@ describe("schema proxy", () => { }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); using _fetch = createSchemaFetch(forkedSchema).mockGlobal(); @@ -944,7 +936,7 @@ describe("schema proxy", () => { const result = useSuspenseQuery(query); const [changeViewerName] = useMutation(mutation); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); @@ -958,16 +950,15 @@ describe("schema proxy", () => { const user = userEvent.setup(); - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -988,9 +979,9 @@ describe("schema proxy", () => { await act(() => user.click(screen.getByText("Change name"))); - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -1034,7 +1025,7 @@ describe("schema proxy", () => { }, }, }); - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); resetTestSchema.add({ resolvers: { @@ -1089,7 +1080,7 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); @@ -1100,16 +1091,15 @@ describe("schema proxy", () => { ); }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -1135,10 +1125,10 @@ describe("schema proxy", () => { await act(() => user.click(screen.getByText("Refetch"))); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); { - const { snapshot } = await Profiler.takeRender(); + const { snapshot } = await renderStream.takeRender(); expect(snapshot.result?.data).toEqual({ viewer: { @@ -1159,7 +1149,7 @@ describe("schema proxy", () => { }); it("createSchemaFetch respects min and max delay", async () => { - const Profiler = createDefaultProfiler(); + const renderStream = createDefaultProfiler(); const minDelay = 1500; const maxDelay = 2000; @@ -1203,25 +1193,24 @@ describe("schema proxy", () => { const Child = () => { const result = useSuspenseQuery(query); - Profiler.mergeSnapshot({ + renderStream.mergeSnapshot({ result, } as Partial<{}>); return
Hello
; }; - renderWithClient(, { - client, - wrapper: Profiler, + renderStream.render(, { + wrapper: createClientWrapper(client), }); // initial suspended render - await Profiler.takeRender(); + await renderStream.takeRender(); - await expect(Profiler).not.toRerender({ timeout: minDelay - 100 }); + await expect(renderStream).not.toRerender({ timeout: minDelay - 100 }); { - const { snapshot } = await Profiler.takeRender({ + const { snapshot } = await renderStream.takeRender({ // This timeout doesn't start until after our `minDelay - 100` // timeout above, so we don't have to wait the full `maxDelay` // here. diff --git a/src/testing/internal/index.ts b/src/testing/internal/index.ts index 9f8b3faae9a..05a44e39429 100644 --- a/src/testing/internal/index.ts +++ b/src/testing/internal/index.ts @@ -1,4 +1,3 @@ -export * from "./profile/index.js"; export * from "./disposables/index.js"; export { ObservableStream } from "./ObservableStream.js"; @@ -19,4 +18,9 @@ export type { RenderWithClientOptions, RenderWithMocksOptions, } from "./renderHelpers.js"; -export { renderWithClient, renderWithMocks } from "./renderHelpers.js"; +export { + renderWithClient, + renderWithMocks, + createMockWrapper, + createClientWrapper, +} from "./renderHelpers.js"; diff --git a/src/testing/internal/profile/Render.tsx b/src/testing/internal/profile/Render.tsx deleted file mode 100644 index 913693855d0..00000000000 --- a/src/testing/internal/profile/Render.tsx +++ /dev/null @@ -1,203 +0,0 @@ -/* istanbul ignore file */ - -/* -Something in this file does not compile correctly while measuring code coverage -and will lead to a - Uncaught [ReferenceError: cov_1zb8w312au is not defined] -if we do not ignore this file in code coverage. - -As we only use this file in our internal tests, we can safely ignore it. -*/ - -import { within, screen } from "@testing-library/dom"; -import { JSDOM, VirtualConsole } from "jsdom"; -import { applyStackTrace, captureStackTrace } from "./traces.js"; - -/** @internal */ -export interface BaseRender { - id: string; - phase: "mount" | "update" | "nested-update"; - actualDuration: number; - baseDuration: number; - startTime: number; - commitTime: number; - /** - * The number of renders that have happened so far (including this render). - */ - count: number; -} - -type Screen = typeof screen; -/** @internal */ -export type SyncScreen = { - [K in keyof Screen]: K extends `find${string}` ? - { - /** @deprecated A snapshot is static, so avoid async queries! */ - (...args: Parameters): ReturnType; - } - : Screen[K]; -}; - -/** @internal */ -export interface Render extends BaseRender { - /** - * The snapshot, as returned by the `takeSnapshot` option of `profile`. - * (If using `profileHook`, this is the return value of the hook.) - */ - snapshot: Snapshot; - /** - * A DOM snapshot of the rendered component, if the `snapshotDOM` - * option of `profile` was enabled. - */ - readonly domSnapshot: HTMLElement; - /** - * Returns a callback to receive a `screen` instance that is scoped to the - * DOM snapshot of this `Render` instance. - * Note: this is used as a callback to prevent linter errors. - * @example - * ```diff - * const { withinDOM } = RenderedComponent.takeRender(); - * -expect(screen.getByText("foo")).toBeInTheDocument(); - * +expect(withinDOM().getByText("foo")).toBeInTheDocument(); - * ``` - */ - withinDOM: () => SyncScreen; - - renderedComponents: Array; -} - -/** @internal */ -export class RenderInstance implements Render { - id: string; - phase: "mount" | "update" | "nested-update"; - actualDuration: number; - baseDuration: number; - startTime: number; - commitTime: number; - count: number; - - constructor( - baseRender: BaseRender, - public snapshot: Snapshot, - private stringifiedDOM: string | undefined, - public renderedComponents: Array - ) { - this.id = baseRender.id; - this.phase = baseRender.phase; - this.actualDuration = baseRender.actualDuration; - this.baseDuration = baseRender.baseDuration; - this.startTime = baseRender.startTime; - this.commitTime = baseRender.commitTime; - this.count = baseRender.count; - } - - private _domSnapshot: HTMLElement | undefined; - get domSnapshot() { - if (this._domSnapshot) return this._domSnapshot; - if (!this.stringifiedDOM) { - throw new Error( - "DOM snapshot is not available - please set the `snapshotDOM` option" - ); - } - - const virtualConsole = new VirtualConsole(); - const stackTrace = captureStackTrace("RenderInstance.get"); - virtualConsole.on("jsdomError", (error) => { - throw applyStackTrace(error, stackTrace); - }); - - const snapDOM = new JSDOM(this.stringifiedDOM, { - runScripts: "dangerously", - virtualConsole, - }); - const document = snapDOM.window.document; - const body = document.body; - const script = document.createElement("script"); - script.type = "text/javascript"; - script.text = ` - ${errorOnDomInteraction.toString()}; - ${errorOnDomInteraction.name}(); - `; - body.appendChild(script); - body.removeChild(script); - - return (this._domSnapshot = body); - } - - get withinDOM(): () => SyncScreen { - const snapScreen = Object.assign(within(this.domSnapshot), { - debug: ( - ...[dom = this.domSnapshot, ...rest]: Parameters - ) => screen.debug(dom, ...rest), - logTestingPlaygroundURL: ( - ...[dom = this.domSnapshot, ...rest]: Parameters< - typeof screen.logTestingPlaygroundURL - > - ) => screen.logTestingPlaygroundURL(dom, ...rest), - }); - return () => snapScreen; - } -} -/** @internal */ -export function errorOnDomInteraction() { - const events: Array = [ - "auxclick", - "blur", - "change", - "click", - "copy", - "cut", - "dblclick", - "drag", - "dragend", - "dragenter", - "dragleave", - "dragover", - "dragstart", - "drop", - "focus", - "focusin", - "focusout", - "input", - "keydown", - "keypress", - "keyup", - "mousedown", - "mouseenter", - "mouseleave", - "mousemove", - "mouseout", - "mouseover", - "mouseup", - "paste", - "pointercancel", - "pointerdown", - "pointerenter", - "pointerleave", - "pointermove", - "pointerout", - "pointerover", - "pointerup", - "scroll", - "select", - "selectionchange", - "selectstart", - "submit", - "toggle", - "touchcancel", - "touchend", - "touchmove", - "touchstart", - "wheel", - ]; - function warnOnDomInteraction() { - throw new Error(` - DOM interaction with a snapshot detected in test. - Please don't interact with the DOM you get from \`withinDOM\`, - but still use \`screen\' to get elements for simulating user interaction. - `); - } - events.forEach((event) => { - document.addEventListener(event, warnOnDomInteraction); - }); -} diff --git a/src/testing/internal/profile/context.tsx b/src/testing/internal/profile/context.tsx deleted file mode 100644 index a8488e73a6c..00000000000 --- a/src/testing/internal/profile/context.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import * as React from "react"; - -export interface ProfilerContextValue { - renderedComponents: Array; -} - -const ProfilerContext = React.createContext( - undefined -); - -export function ProfilerContextProvider({ - children, - value, -}: { - children: React.ReactNode; - value: ProfilerContextValue; -}) { - const parentContext = useProfilerContext(); - - if (parentContext) { - throw new Error("Profilers should not be nested in the same tree"); - } - - return ( - - {children} - - ); -} - -export function useProfilerContext() { - return React.useContext(ProfilerContext); -} diff --git a/src/testing/internal/profile/index.ts b/src/testing/internal/profile/index.ts deleted file mode 100644 index 3d9ddd55559..00000000000 --- a/src/testing/internal/profile/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type { - NextRenderOptions, - Profiler, - ProfiledComponent, - ProfiledHook, -} from "./profile.js"; -export { - createProfiler, - profile, - profileHook, - useTrackRenders, - WaitForRenderTimeoutError, -} from "./profile.js"; - -export type { SyncScreen } from "./Render.js"; diff --git a/src/testing/internal/profile/profile.tsx b/src/testing/internal/profile/profile.tsx deleted file mode 100644 index d1c7731ec2a..00000000000 --- a/src/testing/internal/profile/profile.tsx +++ /dev/null @@ -1,469 +0,0 @@ -import * as React from "react"; - -import { TextEncoder, TextDecoder } from "util"; - -global.TextEncoder ??= TextEncoder; -// @ts-ignore -global.TextDecoder ??= TextDecoder; -import type { Render, BaseRender } from "./Render.js"; -import { RenderInstance } from "./Render.js"; -import { applyStackTrace, captureStackTrace } from "./traces.js"; -import type { ProfilerContextValue } from "./context.js"; -import { ProfilerContextProvider, useProfilerContext } from "./context.js"; -import { disableActWarnings } from "../disposables/index.js"; - -type ValidSnapshot = void | (object & { /* not a function */ call?: never }); - -/** only used for passing around data internally */ -const _stackTrace = Symbol(); -/** @internal */ -export interface NextRenderOptions { - timeout?: number; - [_stackTrace]?: string; -} - -/** @internal */ -interface ProfilerProps { - children: React.ReactNode; -} - -/** @internal */ -export interface Profiler - extends React.FC, - ProfiledComponentFields, - ProfiledComponentOnlyFields {} - -interface ReplaceSnapshot { - (newSnapshot: Snapshot): void; - (updateSnapshot: (lastSnapshot: Readonly) => Snapshot): void; -} - -interface MergeSnapshot { - (partialSnapshot: Partial): void; - ( - updatePartialSnapshot: ( - lastSnapshot: Readonly - ) => Partial - ): void; -} - -interface ProfiledComponentOnlyFields { - // Allows for partial updating of the snapshot by shallow merging the results - mergeSnapshot: MergeSnapshot; - // Performs a full replacement of the snapshot - replaceSnapshot: ReplaceSnapshot; -} -interface ProfiledComponentFields { - /** - * An array of all renders that have happened so far. - * Errors thrown during component render will be captured here, too. - */ - renders: Array< - Render | { phase: "snapshotError"; count: number; error: unknown } - >; - /** - * Peeks the next render from the current iterator position, without advancing the iterator. - * If no render has happened yet, it will wait for the next render to happen. - * @throws {WaitForRenderTimeoutError} if no render happens within the timeout - */ - peekRender(options?: NextRenderOptions): Promise>; - /** - * Iterates to the next render and returns it. - * If no render has happened yet, it will wait for the next render to happen. - * @throws {WaitForRenderTimeoutError} if no render happens within the timeout - */ - takeRender(options?: NextRenderOptions): Promise>; - /** - * Returns the total number of renders. - */ - totalRenderCount(): number; - /** - * Returns the current render. - * @throws {Error} if no render has happened yet - */ - getCurrentRender(): Render; - /** - * Waits for the next render to happen. - * Does not advance the render iterator. - */ - waitForNextRender(options?: NextRenderOptions): Promise>; -} - -export interface ProfiledComponent - extends React.FC, - ProfiledComponentFields, - ProfiledComponentOnlyFields {} - -/** @internal */ -export function profile({ - Component, - ...options -}: Parameters>[0] & { - Component: React.ComponentType; -}): ProfiledComponent { - const Profiler = createProfiler(options); - - return Object.assign( - function ProfiledComponent(props: Props) { - return ( - - - - ); - }, - { - mergeSnapshot: Profiler.mergeSnapshot, - replaceSnapshot: Profiler.replaceSnapshot, - getCurrentRender: Profiler.getCurrentRender, - peekRender: Profiler.peekRender, - takeRender: Profiler.takeRender, - totalRenderCount: Profiler.totalRenderCount, - waitForNextRender: Profiler.waitForNextRender, - get renders() { - return Profiler.renders; - }, - } - ); -} - -/** @internal */ -export function createProfiler({ - onRender, - snapshotDOM = false, - initialSnapshot, - skipNonTrackingRenders, -}: { - onRender?: ( - info: BaseRender & { - snapshot: Snapshot; - replaceSnapshot: ReplaceSnapshot; - mergeSnapshot: MergeSnapshot; - } - ) => void; - snapshotDOM?: boolean; - initialSnapshot?: Snapshot; - /** - * This will skip renders during which no renders tracked by - * `useTrackRenders` occured. - */ - skipNonTrackingRenders?: boolean; -} = {}) { - let nextRender: Promise> | undefined; - let resolveNextRender: ((render: Render) => void) | undefined; - let rejectNextRender: ((error: unknown) => void) | undefined; - function resetNextRender() { - nextRender = resolveNextRender = rejectNextRender = undefined; - } - const snapshotRef = { current: initialSnapshot }; - const replaceSnapshot: ReplaceSnapshot = (snap) => { - if (typeof snap === "function") { - if (!initialSnapshot) { - throw new Error( - "Cannot use a function to update the snapshot if no initial snapshot was provided." - ); - } - snapshotRef.current = snap( - typeof snapshotRef.current === "object" ? - // "cheap best effort" to prevent accidental mutation of the last snapshot - { ...snapshotRef.current! } - : snapshotRef.current! - ); - } else { - snapshotRef.current = snap; - } - }; - - const mergeSnapshot: MergeSnapshot = (partialSnapshot) => { - replaceSnapshot((snapshot) => ({ - ...snapshot, - ...(typeof partialSnapshot === "function" ? - partialSnapshot(snapshot) - : partialSnapshot), - })); - }; - - const profilerContext: ProfilerContextValue = { - renderedComponents: [], - }; - - const profilerOnRender: React.ProfilerOnRenderCallback = ( - id, - phase, - actualDuration, - baseDuration, - startTime, - commitTime - ) => { - if ( - skipNonTrackingRenders && - profilerContext.renderedComponents.length === 0 - ) { - return; - } - const baseRender = { - id, - phase, - actualDuration, - baseDuration, - startTime, - commitTime, - count: Profiler.renders.length + 1, - }; - try { - /* - * The `onRender` function could contain `expect` calls that throw - * `JestAssertionError`s - but we are still inside of React, where errors - * might be swallowed. - * So we record them and re-throw them in `takeRender` - * Additionally, we reject the `waitForNextRender` promise. - */ - onRender?.({ - ...baseRender, - replaceSnapshot, - mergeSnapshot, - snapshot: snapshotRef.current!, - }); - - const snapshot = snapshotRef.current as Snapshot; - const domSnapshot = - snapshotDOM ? window.document.body.innerHTML : undefined; - const render = new RenderInstance( - baseRender, - snapshot, - domSnapshot, - profilerContext.renderedComponents - ); - profilerContext.renderedComponents = []; - Profiler.renders.push(render); - resolveNextRender?.(render); - } catch (error) { - Profiler.renders.push({ - phase: "snapshotError", - count: Profiler.renders.length, - error, - }); - rejectNextRender?.(error); - } finally { - resetNextRender(); - } - }; - - let iteratorPosition = 0; - const Profiler: Profiler = Object.assign( - ({ children }: ProfilerProps) => { - return ( - - - {children} - - - ); - }, - { - replaceSnapshot, - mergeSnapshot, - } satisfies ProfiledComponentOnlyFields, - { - renders: new Array< - | Render - | { phase: "snapshotError"; count: number; error: unknown } - >(), - totalRenderCount() { - return Profiler.renders.length; - }, - async peekRender(options: NextRenderOptions = {}) { - if (iteratorPosition < Profiler.renders.length) { - const render = Profiler.renders[iteratorPosition]; - - if (render.phase === "snapshotError") { - throw render.error; - } - - return render; - } - return Profiler.waitForNextRender({ - [_stackTrace]: captureStackTrace(Profiler.peekRender), - ...options, - }); - }, - async takeRender(options: NextRenderOptions = {}) { - // In many cases we do not control the resolution of the suspended - // promise which results in noisy tests when the profiler due to - // repeated act warnings. - using _disabledActWarnings = disableActWarnings(); - - let error: unknown = undefined; - - try { - return await Profiler.peekRender({ - [_stackTrace]: captureStackTrace(Profiler.takeRender), - ...options, - }); - } catch (e) { - error = e; - throw e; - } finally { - if (!(error && error instanceof WaitForRenderTimeoutError)) { - iteratorPosition++; - } - } - }, - getCurrentRender() { - // The "current" render should point at the same render that the most - // recent `takeRender` call returned, so we need to get the "previous" - // iterator position, otherwise `takeRender` advances the iterator - // to the next render. This means we need to call `takeRender` at least - // once before we can get a current render. - const currentPosition = iteratorPosition - 1; - - if (currentPosition < 0) { - throw new Error( - "No current render available. You need to call `takeRender` before you can get the current render." - ); - } - - const render = Profiler.renders[currentPosition]; - - if (render.phase === "snapshotError") { - throw render.error; - } - return render; - }, - waitForNextRender({ - timeout = 1000, - // capture the stack trace here so its stack trace is as close to the calling code as possible - [_stackTrace]: stackTrace = captureStackTrace( - Profiler.waitForNextRender - ), - }: NextRenderOptions = {}) { - if (!nextRender) { - nextRender = Promise.race>([ - new Promise>((resolve, reject) => { - resolveNextRender = resolve; - rejectNextRender = reject; - }), - new Promise>((_, reject) => - setTimeout(() => { - reject( - applyStackTrace(new WaitForRenderTimeoutError(), stackTrace) - ); - resetNextRender(); - }, timeout) - ), - ]); - } - return nextRender; - }, - } satisfies ProfiledComponentFields - ); - return Profiler; -} - -/** @internal */ -export class WaitForRenderTimeoutError extends Error { - constructor() { - super("Exceeded timeout waiting for next render."); - Object.setPrototypeOf(this, new.target.prototype); - } -} - -type StringReplaceRenderWithSnapshot = - T extends `${infer Pre}Render${infer Post}` ? `${Pre}Snapshot${Post}` : T; - -type ResultReplaceRenderWithSnapshot = - T extends (...args: infer Args) => Render ? - (...args: Args) => Snapshot - : T extends (...args: infer Args) => Promise> ? - (...args: Args) => Promise - : T; - -type ProfiledHookFields = - ProfiledComponentFields extends infer PC ? - { - [K in keyof PC as StringReplaceRenderWithSnapshot< - K & string - >]: ResultReplaceRenderWithSnapshot; - } - : never; - -/** @internal */ -export interface ProfiledHook - extends React.FC, - ProfiledHookFields { - Profiler: Profiler; -} - -/** @internal */ -export function profileHook( - renderCallback: (props: Props) => ReturnValue -): ProfiledHook { - const Profiler = createProfiler(); - - const ProfiledHook = (props: Props) => { - Profiler.replaceSnapshot(renderCallback(props)); - return null; - }; - - return Object.assign( - function App(props: Props) { - return ( - - - - ); - }, - { - Profiler, - }, - { - renders: Profiler.renders, - totalSnapshotCount: Profiler.totalRenderCount, - async peekSnapshot(options) { - return (await Profiler.peekRender(options)).snapshot; - }, - async takeSnapshot(options) { - return (await Profiler.takeRender(options)).snapshot; - }, - getCurrentSnapshot() { - return Profiler.getCurrentRender().snapshot; - }, - async waitForNextSnapshot(options) { - return (await Profiler.waitForNextRender(options)).snapshot; - }, - } satisfies ProfiledHookFields - ); -} - -function resolveR18HookOwner(): React.ComponentType | undefined { - return (React as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - ?.ReactCurrentOwner?.current?.elementType; -} - -function resolveR19HookOwner(): React.ComponentType | undefined { - return ( - React as any - ).__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE?.A?.getOwner() - .elementType; -} - -export function useTrackRenders({ name }: { name?: string } = {}) { - const component = name || resolveR18HookOwner() || resolveR19HookOwner(); - - if (!component) { - throw new Error( - "useTrackRender: Unable to determine component. Please ensure the hook is called inside a rendered component or provide a `name` option." - ); - } - - const ctx = useProfilerContext(); - - if (!ctx) { - throw new Error( - "useTrackComponentRender: A Profiler must be created and rendered to track component renders" - ); - } - - React.useLayoutEffect(() => { - ctx.renderedComponents.unshift(component); - }); -} diff --git a/src/testing/internal/profile/traces.ts b/src/testing/internal/profile/traces.ts deleted file mode 100644 index 9dfbc59e82a..00000000000 --- a/src/testing/internal/profile/traces.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Captures a StackTrace and (if passed) cuts off - * the first lines including the calling function. - */ -export function captureStackTrace(callingFunction?: string | (() => {})) { - let stack = ""; - try { - throw new Error(""); - } catch (e: any) { - ({ stack } = e); - } - - const callerName = - typeof callingFunction === "string" ? callingFunction - : callingFunction ? callingFunction.name - : undefined; - - if (callerName && stack.includes(callerName)) { - const lines = stack.split("\n"); - - stack = lines - .slice( - // @ts-expect-error this is too old of a TS target, but node has it - lines.findLastIndex((line: string) => line.includes(callerName)) + 1 - ) - .join("\n"); - } - - return stack; -} - -export function applyStackTrace(error: Error, stackTrace: string) { - error.stack = error.message + "\n" + stackTrace; - return error; -} diff --git a/src/testing/internal/renderHelpers.tsx b/src/testing/internal/renderHelpers.tsx index c47a533d09c..de744abff6c 100644 --- a/src/testing/internal/renderHelpers.tsx +++ b/src/testing/internal/renderHelpers.tsx @@ -15,6 +15,23 @@ export interface RenderWithClientOptions< client: ApolloClient; } +export function createClientWrapper( + client: ApolloClient, + Wrapper: React.JSXElementConstructor<{ + children: React.ReactNode; + }> = React.Fragment +): React.JSXElementConstructor<{ + children: React.ReactNode; +}> { + return ({ children }) => { + return ( + + {children} + + ); + }; +} + export function renderWithClient< Q extends Queries = typeof queries, Container extends Element | DocumentFragment = HTMLElement, @@ -23,19 +40,13 @@ export function renderWithClient< ui: ReactElement, { client, - wrapper: Wrapper = React.Fragment, + wrapper, ...renderOptions }: RenderWithClientOptions ) { return render(ui, { ...renderOptions, - wrapper: ({ children }) => { - return ( - - {children} - - ); - }, + wrapper: createClientWrapper(client, wrapper), }); } @@ -46,6 +57,23 @@ export interface RenderWithMocksOptions< > extends RenderOptions, MockedProviderProps {} +export function createMockWrapper( + renderOptions: MockedProviderProps, + Wrapper: React.JSXElementConstructor<{ + children: React.ReactNode; + }> = React.Fragment +): React.JSXElementConstructor<{ + children: React.ReactNode; +}> { + return ({ children }) => { + return ( + + {children} + + ); + }; +} + export function renderWithMocks< Q extends Queries = typeof queries, Container extends Element | DocumentFragment = HTMLElement, @@ -53,18 +81,12 @@ export function renderWithMocks< >( ui: ReactElement, { - wrapper: Wrapper = React.Fragment, + wrapper, ...renderOptions }: RenderWithMocksOptions ) { return render(ui, { ...renderOptions, - wrapper: ({ children }) => { - return ( - - {children} - - ); - }, + wrapper: createMockWrapper(renderOptions, wrapper), }); } diff --git a/src/testing/matchers/ProfiledComponent.ts b/src/testing/matchers/ProfiledComponent.ts deleted file mode 100644 index 435c24a29a6..00000000000 --- a/src/testing/matchers/ProfiledComponent.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { MatcherFunction } from "expect"; -import { WaitForRenderTimeoutError } from "../internal/index.js"; -import type { - NextRenderOptions, - Profiler, - ProfiledComponent, - ProfiledHook, -} from "../internal/index.js"; - -export const toRerender: MatcherFunction<[options?: NextRenderOptions]> = - async function (actual, options) { - const _profiler = actual as - | Profiler - | ProfiledComponent - | ProfiledHook; - const profiler = "Profiler" in _profiler ? _profiler.Profiler : _profiler; - const hint = this.utils.matcherHint("toRerender", "ProfiledComponent", ""); - let pass = true; - try { - await profiler.peekRender({ timeout: 100, ...options }); - } catch (e) { - if (e instanceof WaitForRenderTimeoutError) { - pass = false; - } else { - throw e; - } - } - - return { - pass, - message() { - return ( - hint + - `\n\nExpected component to${pass ? " not" : ""} rerender, ` + - `but it did${pass ? "" : " not"}.` - ); - }, - }; - }; - -/** to be thrown to "break" test execution and fail it */ -const failed = {}; - -export const toRenderExactlyTimes: MatcherFunction< - [times: number, options?: NextRenderOptions] -> = async function (actual, times, optionsPerRender) { - const _profiler = actual as - | Profiler - | ProfiledComponent - | ProfiledHook; - const profiler = "Profiler" in _profiler ? _profiler.Profiler : _profiler; - const options = { timeout: 100, ...optionsPerRender }; - const hint = this.utils.matcherHint("toRenderExactlyTimes"); - let pass = true; - try { - if (profiler.totalRenderCount() > times) { - throw failed; - } - try { - while (profiler.totalRenderCount() < times) { - await profiler.waitForNextRender(options); - } - } catch (e) { - // timeouts here should just fail the test, rethrow other errors - throw e instanceof WaitForRenderTimeoutError ? failed : e; - } - try { - await profiler.waitForNextRender(options); - } catch (e) { - // we are expecting a timeout here, so swallow that error, rethrow others - if (!(e instanceof WaitForRenderTimeoutError)) { - throw e; - } - } - } catch (e) { - if (e === failed) { - pass = false; - } else { - throw e; - } - } - return { - pass, - message() { - return ( - hint + - ` Expected component to${pass ? " not" : ""} render exactly ${times}.` + - ` It rendered ${profiler.totalRenderCount()} times.` - ); - }, - }; -}; diff --git a/src/testing/matchers/index.d.ts b/src/testing/matchers/index.d.ts index 65fbcc37ba9..7dc37ea8bb7 100644 --- a/src/testing/matchers/index.d.ts +++ b/src/testing/matchers/index.d.ts @@ -4,12 +4,8 @@ import type { OperationVariables, } from "../../core/index.js"; import type { QueryRef } from "../../react/index.js"; -import { - NextRenderOptions, - Profiler, - ProfiledComponent, - ProfiledHook, -} from "../internal/index.js"; +import { NextRenderOptions } from "../internal/index.js"; +import { RenderStreamMatchers } from "@testing-library/react-render-stream/expect"; interface ApolloCustomMatchers { /** @@ -36,24 +32,14 @@ interface ApolloCustomMatchers { ) => R : { error: "matcher needs to be called on an ApolloClient instance" }; - toRerender: T extends ( - Profiler | ProfiledComponent | ProfiledHook - ) ? - (options?: NextRenderOptions) => Promise - : { error: "matcher needs to be called on a ProfiledComponent instance" }; - - toRenderExactlyTimes: T extends ( - Profiler | ProfiledComponent | ProfiledHook - ) ? - (count: number, options?: NextRenderOptions) => Promise - : { error: "matcher needs to be called on a ProfiledComponent instance" }; - toBeGarbageCollected: T extends WeakRef ? () => Promise : { error: "matcher needs to be called on a WeakRef instance" }; } declare global { namespace jest { - interface Matchers extends ApolloCustomMatchers {} + interface Matchers + extends ApolloCustomMatchers, + RenderStreamMatchers {} } } diff --git a/src/testing/matchers/index.ts b/src/testing/matchers/index.ts index c4f88544f14..1ba62d09215 100644 --- a/src/testing/matchers/index.ts +++ b/src/testing/matchers/index.ts @@ -1,7 +1,6 @@ import { expect } from "@jest/globals"; import { toMatchDocument } from "./toMatchDocument.js"; import { toHaveSuspenseCacheEntryUsing } from "./toHaveSuspenseCacheEntryUsing.js"; -import { toRerender, toRenderExactlyTimes } from "./ProfiledComponent.js"; import { toBeGarbageCollected } from "./toBeGarbageCollected.js"; import { toBeDisposed } from "./toBeDisposed.js"; @@ -9,7 +8,5 @@ expect.extend({ toBeDisposed, toHaveSuspenseCacheEntryUsing, toMatchDocument, - toRerender, - toRenderExactlyTimes, toBeGarbageCollected, }); diff --git a/src/tsconfig.json b/src/tsconfig.json index d7e90510ecc..5a06c379eb7 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -7,8 +7,13 @@ "noEmit": true, "declaration": false, "declarationMap": false, - "lib": ["es2015", "esnext.asynciterable", "ES2021.WeakRef"], - "types": ["jest", "node", "./testing/matchers/index.d.ts"] + "lib": ["DOM", "es2015", "esnext.asynciterable", "ES2021.WeakRef"], + "types": [ + "jest", + "node", + "./testing/matchers/index.d.ts", + "@testing-library/react-render-stream/expect" + ] }, "extends": "../tsconfig.json", "include": ["./**/*.ts", "./**/*.tsx"],