diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..8c56e190 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +## 0.2.0 + +### Breaking Changes + +- Expose Typescript types + +### New Features + +- Migrate codebase to Typescript +- Replace query-string with node's querystring + +## 0.1.0 + +Initial release diff --git a/README.md b/README.md index 56735852..93526ccf 100644 --- a/README.md +++ b/README.md @@ -40,13 +40,13 @@ Next page tester will take care of: ## Options -| Property | Description | type | Default | -| ------------------ | ---------------------------------------------------------------------------------- | ------------------ | ------- | -| **route** | Next route (must start with `/`) | - | - | -| **pagesDirectory** | Absolute path of Next's `/pages` folder | - | - | -| **req** | Override default mocked [request object][req-docs]
(`getServerSideProps` only) | `res => res` | - | -| **res** | Override default mocked [response object][res-docs]
(`getServerSideProps` only) | `req => req` | - | -| **router** | Override default mocked [Next router object][next-docs-router] | `router => router` | - | +| Property | Description | type | Default | +| ------------------ | -------------------------------------------------------------------------------- | ------------------ | ------- | +| **route** | Next route (must start with `/`) | - | - | +| **pagesDirectory** | Absolute path of Next's `/pages` folder | - | - | +| **req** | Access default mocked [request object][req-docs]
(`getServerSideProps` only) | `res => res` | - | +| **res** | Access default mocked [response object][res-docs]
(`getServerSideProps` only) | `req => req` | - | +| **router** | Access default mocked [Next router object][next-docs-router] | `router => router` | - | ## Notes @@ -61,6 +61,7 @@ It might be necessary to install `@types/react-dom` and `@types/webpack` when us - Make available dynamic api routes under `/pages/api` - Consider adding custom App and Document - Consider adding a `getPage` factory +- Consider reusing Next.js code parts (not only types) [ci]: https://travis-ci.com/toomuchdesign/next-page-tester [ci-badge]: https://travis-ci.com/toomuchdesign/next-page-tester.svg?branch=master diff --git a/package-lock.json b/package-lock.json index 4df010ca..53141a8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3916,7 +3916,8 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true }, "dedent": { "version": "0.7.0", @@ -7554,16 +7555,6 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "query-string": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.1.tgz", - "integrity": "sha512-RfoButmcK+yCta1+FuU8REvisx1oEzhMKwhLUNcepQTPGcNMp1sIqjnfCtfnvGSQZQEhaBHvccujtWoUV3TTbA==", - "requires": { - "decode-uri-component": "^0.2.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -8912,11 +8903,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -9072,11 +9058,6 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" - }, "string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", diff --git a/package.json b/package.json index 443dec04..95b064f2 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "clean": "rm -rf dist", "compile": "npm run clean && tsc", "test": "jest ./src", - "test:source": "npm t -- --coverage", + "test:source": "npm run test:ts && npm t -- --coverage", + "test:ts": "tsc --noEmit", "prepare": "npm run test:source && npm run compile", "preversion": "npm run prepare", "version": "git add package.json", @@ -61,7 +62,6 @@ "@types/express": "^4.17.8", "@types/recursive-readdir": "^2.2.0", "node-mocks-http": "^1.9.0", - "query-string": "^6.13.1", "recursive-readdir": "^2.2.2" }, "peerDependencies": { @@ -89,7 +89,7 @@ "lint-staged": { "**/*.{js,ts,json}": [ "prettier", - "npm t -- ." + "npm run test:source -- ." ], "**/*.{md}": [ "prettier" diff --git a/src/commonTypes.ts b/src/commonTypes.ts index 8e739771..5ce1cf47 100644 --- a/src/commonTypes.ts +++ b/src/commonTypes.ts @@ -12,8 +12,8 @@ type Res = ReturnType; export type Options = { route: string; pagesDirectory: string; - req?: (req: Req) => { [name: string]: any }; - res?: (res: Res) => { [name: string]: any }; + req?: (req: Req) => Req; + res?: (res: Res) => Res; router?: (router: NextRouter) => NextRouter; }; diff --git a/src/preparePage.ts b/src/preparePage.ts index 2d364bef..7ae5a6e8 100644 --- a/src/preparePage.ts +++ b/src/preparePage.ts @@ -1,20 +1,19 @@ import React, { ReactNode } from 'react'; -import queryString from 'query-string'; import { RouterContext } from 'next/dist/next-server/lib/router-context'; import type { NextRouter } from 'next/router'; -import { parseRoute, removeFileExtension } from './utils'; +import { parseRoute, removeFileExtension, parseQueryString } from './utils'; import type { Options, PageObject } from './commonTypes'; // https://github.com/vercel/next.js/issues/7479#issuecomment-659859682 -function makeDefaultRouterMock(props = {}): NextRouter { +function makeDefaultRouterMock(props?: Partial): NextRouter { const routerMock = { basePath: '', pathname: '/', route: '/', asPath: '/', query: {}, - push: async () => true, - replace: async () => true, + push: /* istanbul ignore next */ async () => true, + replace: /* istanbul ignore next */ async () => true, reload: () => {}, back: () => {}, prefetch: async () => {}, @@ -47,7 +46,7 @@ export default function preparePage({ makeDefaultRouterMock({ asPath: pathname + search + hash, // Includes querystring and anchor pathname: removeFileExtension({ path: pagePath }), // Page component path without extension - query: { ...params, ...queryString.parse(search) }, // Route params + parsed querystring + query: { ...params, ...parseQueryString({ queryString: search }) }, // Route params + parsed querystring route: removeFileExtension({ path: pagePath }), // Page component path without extension }) ), diff --git a/src/utils.ts b/src/utils.ts index 9f51f144..e1c06087 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,16 @@ -const url = require('url'); +import { URL } from 'url'; +import querystring from 'querystring'; export function parseRoute({ route }: { route: string }) { - return url.parse(`http://test.com${route}`); + return new URL(`http://test.com${route}`); +} + +export function parseQueryString({ queryString }: { queryString: string }) { + const qs = queryString.startsWith('?') + ? queryString.substring(1) + : queryString; + + return querystring.parse(qs); } export function sleep(ms: number) {