add first blitz integration test for useQuery (#2193)
* add first blitz integration test for useQuery * link to couple nextjs test files instead of duplicate * CI name tweaks (meta)
This commit is contained in:
@@ -91,6 +91,7 @@ module.exports = {
|
||||
rules: {
|
||||
"import/no-default-export": "off",
|
||||
"require-await": "off",
|
||||
"unicorn/filename-case": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -90,7 +90,7 @@ jobs:
|
||||
key: ${{ github.sha }}
|
||||
|
||||
testBlitzPackages:
|
||||
name: Blitz Packages Tests
|
||||
name: Blitz - Test Packages
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
|
||||
testBlitzExamples:
|
||||
timeout-minutes: 30
|
||||
name: Blitz Example Apps Tests
|
||||
name: Blitz - Test Example Apps
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
|
||||
@@ -34,7 +34,6 @@ module.exports = {
|
||||
"@babel/preset-env",
|
||||
{
|
||||
modules: false,
|
||||
// loose: true,
|
||||
exclude: [
|
||||
"@babel/plugin-transform-async-to-generator",
|
||||
"@babel/plugin-transform-regenerator",
|
||||
@@ -45,5 +44,21 @@ module.exports = {
|
||||
],
|
||||
plugins: [],
|
||||
},
|
||||
{
|
||||
test: "./nextjs/test/**/*",
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
modules: false,
|
||||
exclude: [
|
||||
"@babel/plugin-transform-async-to-generator",
|
||||
"@babel/plugin-transform-regenerator",
|
||||
],
|
||||
},
|
||||
],
|
||||
"blitz/babel",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ module.exports = {
|
||||
verbose: true,
|
||||
rootDir: "test",
|
||||
modulePaths: ["<rootDir>/lib"],
|
||||
moduleNameMapper: {
|
||||
"^lib/(.+)$": "<rootDir>/lib/$1",
|
||||
},
|
||||
globalSetup: "<rootDir>/jest-global-setup.js",
|
||||
globalTeardown: "<rootDir>/jest-global-teardown.js",
|
||||
setupFilesAfterEnv: ["<rootDir>/jest-setup-after-env.js"],
|
||||
|
||||
2
nextjs/test/lib/next-webdriver.d.ts
vendored
2
nextjs/test/lib/next-webdriver.d.ts
vendored
@@ -10,7 +10,7 @@ interface Chain {
|
||||
hasElementByCssSelector: () => Chain
|
||||
click: () => Chain
|
||||
elementsByCss: () => Chain
|
||||
waitForElementByCss: () => Chain
|
||||
waitForElementByCss: (arg: string) => Chain
|
||||
eval: () => Chain
|
||||
log: () => Chain
|
||||
url: () => Chain
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/// <reference types="./next-webdriver" />
|
||||
import fetch from 'node-fetch'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
import fetch from 'node-fetch'
|
||||
import Chain from './wd-chain'
|
||||
import { Builder, By } from 'selenium-webdriver'
|
||||
import { Options as ChromeOptions } from 'selenium-webdriver/chrome'
|
||||
import { Options as SafariOptions } from 'selenium-webdriver/safari'
|
||||
import { Options as FireFoxOptions } from 'selenium-webdriver/firefox'
|
||||
import { waitFor } from 'next-test-utils'
|
||||
import { Options as SafariOptions } from 'selenium-webdriver/safari'
|
||||
import { waitFor } from './next-test-utils'
|
||||
import Chain from './wd-chain'
|
||||
|
||||
const {
|
||||
BROWSER_NAME: browserName = 'chrome',
|
||||
|
||||
3
test/integration/queries/app/queries/getBasic.ts
Normal file
3
test/integration/queries/app/queries/getBasic.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default async function getBasic() {
|
||||
return "basic-result"
|
||||
}
|
||||
@@ -1,11 +1 @@
|
||||
module.exports = {
|
||||
// replace me
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/blog/post/:pid",
|
||||
destination: "/blog/:pid",
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
module.exports = {}
|
||||
|
||||
5
test/integration/queries/pages/_app.tsx
Normal file
5
test/integration/queries/pages/_app.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import {AppProps} from "blitz"
|
||||
|
||||
export default function App({Component, pageProps}: AppProps) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
23
test/integration/queries/pages/_document.tsx
Normal file
23
test/integration/queries/pages/_document.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import {BlitzScript, Document, DocumentHead, Html, Main} from "blitz"
|
||||
|
||||
class MyDocument extends Document {
|
||||
// Only uncomment if you need to customize this behaviour
|
||||
// static async getInitialProps(ctx: DocumentContext) {
|
||||
// const initialProps = await Document.getInitialProps(ctx)
|
||||
// return {...initialProps}
|
||||
// }
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<DocumentHead />
|
||||
<body>
|
||||
<Main />
|
||||
<BlitzScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
||||
@@ -1,16 +0,0 @@
|
||||
import {useRouter} from "blitz"
|
||||
import React from "react"
|
||||
|
||||
const Post = () => {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="as-path">{router.asPath}</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Post.getInitialProps = () => ({hello: "hi"})
|
||||
|
||||
export default Post
|
||||
@@ -1,3 +0,0 @@
|
||||
const page = () => "hello from sub id"
|
||||
page.getInitialProps = () => ({hello: "hi"})
|
||||
export default page
|
||||
@@ -1 +0,0 @@
|
||||
export default () => <p id="normal-text">a normal page</p>
|
||||
20
test/integration/queries/pages/use-query.tsx
Normal file
20
test/integration/queries/pages/use-query.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import getBasic from "app/queries/getBasic"
|
||||
import {useQuery} from "blitz"
|
||||
import {Suspense} from "react"
|
||||
|
||||
function Content() {
|
||||
const [result] = useQuery(getBasic, null)
|
||||
return <div id="content">{result}</div>
|
||||
}
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div id="page">
|
||||
<Suspense fallback={"Loading..."}>
|
||||
<Content />
|
||||
</Suspense>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page
|
||||
@@ -1,81 +1,32 @@
|
||||
import {
|
||||
blitzBuild,
|
||||
blitzStart,
|
||||
File,
|
||||
findPort,
|
||||
killApp,
|
||||
launchApp,
|
||||
renderViaHTTP,
|
||||
} from "blitz-test-utils"
|
||||
import cheerio from "cheerio"
|
||||
/* eslint-env jest */
|
||||
import {findPort, killApp, launchApp, renderViaHTTP} from "lib/blitz-test-utils"
|
||||
import webdriver from "lib/next-webdriver"
|
||||
import {join} from "path"
|
||||
|
||||
const context: any = {}
|
||||
jest.setTimeout(1000 * 60 * 5)
|
||||
let app: any
|
||||
let appPort: number
|
||||
const appDir = join(__dirname, "..")
|
||||
const blitzConfig = new File(join(appDir, "blitz.config.js"))
|
||||
|
||||
const runTests = () => {
|
||||
it("should have gip in __NEXT_DATA__", async () => {
|
||||
const html = await renderViaHTTP(appPort, "/")
|
||||
const $ = cheerio.load(html)
|
||||
expect(JSON.parse($("#__NEXT_DATA__").text()).gip).toBe(true)
|
||||
})
|
||||
|
||||
it("should not have gip in __NEXT_DATA__ for non-GIP page", async () => {
|
||||
const html = await renderViaHTTP(appPort, "/normal")
|
||||
const $ = cheerio.load(html)
|
||||
expect("gip" in JSON.parse($("#__NEXT_DATA__").text())).toBe(false)
|
||||
})
|
||||
|
||||
it("should have correct router.asPath for direct visit dynamic page", async () => {
|
||||
const html = await renderViaHTTP(appPort, "/blog/1")
|
||||
const $ = cheerio.load(html)
|
||||
expect($("#as-path").text()).toBe("/blog/1")
|
||||
})
|
||||
|
||||
it("should have correct router.asPath for direct visit dynamic page rewrite direct", async () => {
|
||||
const html = await renderViaHTTP(appPort, "/blog/post/1")
|
||||
const $ = cheerio.load(html)
|
||||
expect($("#as-path").text()).toBe("/blog/post/1")
|
||||
})
|
||||
}
|
||||
|
||||
describe("getInitialProps", () => {
|
||||
describe("dev mode", () => {
|
||||
beforeAll(async () => {
|
||||
appPort = await findPort()
|
||||
app = await launchApp(appDir, appPort)
|
||||
})
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests()
|
||||
})
|
||||
|
||||
describe("serverless mode", () => {
|
||||
beforeAll(async () => {
|
||||
blitzConfig.replace("// replace me", `target: 'serverless', `)
|
||||
await blitzBuild(appDir)
|
||||
appPort = await findPort()
|
||||
app = await blitzStart(appDir, appPort)
|
||||
})
|
||||
afterAll(async () => {
|
||||
await killApp(app)
|
||||
blitzConfig.restore()
|
||||
describe("Queries", () => {
|
||||
beforeAll(async () => {
|
||||
context.appPort = await findPort()
|
||||
context.server = await launchApp(join(__dirname, "../"), context.appPort, {
|
||||
env: {__NEXT_TEST_WITH_DEVTOOL: 1},
|
||||
})
|
||||
|
||||
runTests()
|
||||
const prerender = ["/use-query"]
|
||||
await Promise.all(prerender.map((route) => renderViaHTTP(context.appPort, route)))
|
||||
})
|
||||
afterAll(() => killApp(context.server))
|
||||
|
||||
describe("production mode", () => {
|
||||
beforeAll(async () => {
|
||||
await blitzBuild(appDir)
|
||||
appPort = await findPort()
|
||||
app = await blitzStart(appDir, appPort)
|
||||
describe("useQuery", () => {
|
||||
it("should render query result", async () => {
|
||||
const browser = await webdriver(context.appPort, "/use-query")
|
||||
let text = await browser.elementByCss("#page").text()
|
||||
expect(text).toMatch(/Loading/)
|
||||
await browser.waitForElementByCss("#content")
|
||||
text = await browser.elementByCss("#content").text()
|
||||
if (browser) await browser.close()
|
||||
expect(text).toMatch(/basic-result/)
|
||||
})
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests()
|
||||
})
|
||||
})
|
||||
|
||||
25
test/integration/queries/tsconfig.json
Normal file
25
test/integration/queries/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"baseUrl": "./",
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": ".tsbuildinfo",
|
||||
"paths": {
|
||||
"lib/*": ["../../lib/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
// my-custom-environment
|
||||
const http = require("http")
|
||||
const getPort = require("get-port")
|
||||
const seleniumServer = require("selenium-standalone")
|
||||
const NodeEnvironment = require("jest-environment-node")
|
||||
|
||||
const {BROWSER_NAME: browserName = "chrome", SKIP_LOCAL_SELENIUM_SERVER} = process.env
|
||||
|
||||
const newTabPg = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>new tab</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="about:blank" target="_blank" id="new">Click me</a>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
class CustomEnvironment extends NodeEnvironment {
|
||||
async setup() {
|
||||
await super.setup()
|
||||
// Since ie11 doesn't like dataURIs we have to spin up a
|
||||
// server to handle the new tab page
|
||||
this.server = http.createServer((req, res) => {
|
||||
res.statusCode = 200
|
||||
res.end(newTabPg)
|
||||
})
|
||||
const newTabPort = await getPort()
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
this.server.listen(newTabPort, (err) => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
let seleniumServerPort
|
||||
|
||||
if (browserName !== "chrome" && SKIP_LOCAL_SELENIUM_SERVER !== "true") {
|
||||
console.log("Installing selenium server")
|
||||
await new Promise((resolve, reject) => {
|
||||
seleniumServer.install((err) => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
console.log("Starting selenium server")
|
||||
await new Promise((resolve, reject) => {
|
||||
seleniumServer.start((err, child) => {
|
||||
if (err) return reject(err)
|
||||
this.seleniumServer = child
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
console.log("Started selenium server")
|
||||
seleniumServerPort = 4444
|
||||
}
|
||||
|
||||
this.global.wd = null
|
||||
this.global._newTabPort = newTabPort
|
||||
this.global.browserName = browserName
|
||||
this.global.seleniumServerPort = seleniumServerPort
|
||||
this.global.browserStackLocalId = global.browserStackLocalId
|
||||
}
|
||||
|
||||
async teardown() {
|
||||
await super.teardown()
|
||||
|
||||
if (this.server) {
|
||||
this.server.close()
|
||||
}
|
||||
if (this.global.wd) {
|
||||
try {
|
||||
await this.global.wd.quit()
|
||||
} catch (err) {
|
||||
console.log(`Failed to quit webdriver instance`, err)
|
||||
}
|
||||
}
|
||||
// must come after wd.quit()
|
||||
if (this.seleniumServer) {
|
||||
this.seleniumServer.kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CustomEnvironment
|
||||
1
test/jest-environment.js
Symbolic link
1
test/jest-environment.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../nextjs/test/jest-environment.js
|
||||
@@ -1,24 +0,0 @@
|
||||
let globalSetup = () => {}
|
||||
|
||||
if (process.env.BROWSERSTACK) {
|
||||
const {Local} = require("browserstack-local")
|
||||
const browserStackLocal = new Local()
|
||||
const localBrowserStackOpts = {
|
||||
key: process.env.BROWSERSTACK_ACCESS_KEY,
|
||||
localIdentifier: new Date().getTime(), // Adding a unique local identifier to run parallel tests on BrowserStack
|
||||
}
|
||||
global.browserStackLocal = browserStackLocal
|
||||
global.browserStackLocalId = localBrowserStackOpts.localIdentifier
|
||||
|
||||
globalSetup = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
browserStackLocal.start(localBrowserStackOpts, (err) => {
|
||||
if (err) return reject(err)
|
||||
console.log("Started BrowserStackLocal", browserStackLocal.isRunning())
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = globalSetup
|
||||
1
test/jest-global-setup.js
Symbolic link
1
test/jest-global-setup.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../nextjs/test/jest-global-setup.js
|
||||
@@ -1,9 +0,0 @@
|
||||
let globalTeardown = () => {}
|
||||
|
||||
if (process.env.BROWSERSTACK) {
|
||||
globalTeardown = () => global.browserStackLocal.killAllProcesses(() => {})
|
||||
}
|
||||
|
||||
module.exports = async () => {
|
||||
await globalTeardown()
|
||||
}
|
||||
1
test/jest-global-teardown.js
Symbolic link
1
test/jest-global-teardown.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../nextjs/test/jest-global-teardown.js
|
||||
1
test/lib/next-webdriver.d.ts
vendored
Symbolic link
1
test/lib/next-webdriver.d.ts
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../../nextjs/test/lib/next-webdriver.d.ts
|
||||
1
test/lib/next-webdriver.js
Symbolic link
1
test/lib/next-webdriver.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../../nextjs/test/lib/next-webdriver.js
|
||||
@@ -4,7 +4,6 @@
|
||||
/* "module": "esnext", */
|
||||
/* "target": "esnext", */
|
||||
"allowJs": true,
|
||||
"baseUrl": "./lib",
|
||||
"resolveJsonModule": true,
|
||||
"noEmit": true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user