fix: correct website upload path (#483)
* test(wip): add ui tests * fix: correct website upload path * fix: use includes * test: rewrite ui tests * build: remove concurrently * ci: run puppeteer in headless * test: add regression tests * test: add website regression 03 test * test: add react test website * chore: revert newlines Co-authored-by: Cafe137 <aron@aronsoos.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
const axios = require('axios')
|
||||
const puppeteer = require('puppeteer')
|
||||
const { Assert, Click, sleep, Wait } = require('./library')
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @returns {Promise<string>} Swarm hash
|
||||
*/
|
||||
async function selectStampAndUpload(page) {
|
||||
await Click.elementWithText(page, 'button', 'Add Postage Stamp')
|
||||
// select the first available stamp
|
||||
await Click.elementWithClass(page, 'div', '.MuiSelect-select')
|
||||
await Click.elementWithClass(page, 'li', '.MuiListItem-button')
|
||||
await Wait.forEnabledStateXPath(page, 'button', 'Proceed With Selected Stamp')
|
||||
// seems necessary, even though button is enabled by the previous step, it is only highlighted and not clicked
|
||||
await sleep(500)
|
||||
await Click.elementWithText(page, 'button', 'Proceed With Selected Stamp')
|
||||
await Click.elementWithText(page, 'button', 'Upload To Your Node')
|
||||
// check if the upload was successful
|
||||
await Assert.elementWithTextExists(page, 'button', 'Download')
|
||||
await Assert.elementWithTextExists(page, 'button', 'Update Feed')
|
||||
|
||||
// get the swarm hash
|
||||
return page.url().split('/').pop()
|
||||
}
|
||||
|
||||
async function assertUploadedContentAtPath(swarmHash, path, contentType) {
|
||||
const response = await axios.get(`http://localhost:1633/bzz/${swarmHash}/${path}`)
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Expected 200 OK, got ${response.status}`)
|
||||
}
|
||||
|
||||
if (response.headers['content-type'] !== contentType) {
|
||||
throw new Error(`Expected content-type ${contentType}, got ${response.headers['content-type']}`)
|
||||
}
|
||||
|
||||
const { data } = response
|
||||
|
||||
if (data.length === 0) {
|
||||
throw new Error(`Expected non-empty data, got ${data}`)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { selectStampAndUpload, assertUploadedContentAtPath }
|
||||
@@ -0,0 +1,63 @@
|
||||
/* eslint-disable no-console */
|
||||
const handler = require('serve-handler')
|
||||
const http = require('http')
|
||||
const puppeteer = require('puppeteer')
|
||||
const { testFolderUpload } = require('./test-case/FolderUpload')
|
||||
const { testImageFileUpload } = require('./test-case/ImageFileUpload')
|
||||
const { testTextFileUpload } = require('./test-case/TextFileUpload')
|
||||
const { testWebsiteUpload } = require('./test-case/WebsiteUpload')
|
||||
const { testReactWebsiteUpload } = require('./test-case/ReactWebsiteUpload')
|
||||
|
||||
const VIEWPORT = { width: 1366, height: 768 }
|
||||
|
||||
const testCases = [testTextFileUpload, testImageFileUpload, testFolderUpload, testWebsiteUpload, testReactWebsiteUpload]
|
||||
|
||||
async function main() {
|
||||
const server = prepareServer()
|
||||
const { browser, page } = await preparePage()
|
||||
const beforeAll = Date.now()
|
||||
for (const testCase of testCases) {
|
||||
const before = Date.now()
|
||||
console.log('\x1b[34m…\x1b[0m', 'Running', testCase.name)
|
||||
await testCase(page)
|
||||
const delta = Date.now() - before
|
||||
console.log('\x1b[32m✔\x1b[0m', testCase.name, 'passed in', delta, 'ms')
|
||||
}
|
||||
const delta = Date.now() - beforeAll
|
||||
console.log('\x1b[32m✔✔✔\x1b[0m', 'All', testCases.length, 'tests passed in', delta, 'ms')
|
||||
await page.close()
|
||||
await browser.close()
|
||||
server.close()
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<{ browser: puppeteer.Browser, page: puppeteer.Page }>}
|
||||
*/
|
||||
async function preparePage() {
|
||||
const browser = await puppeteer.launch({
|
||||
defaultViewport: null,
|
||||
headless: false,
|
||||
args: [`--window-size=${VIEWPORT.width},${VIEWPORT.height}`],
|
||||
})
|
||||
const page = await browser.newPage()
|
||||
await page.goto('http://localhost:8080' || process.env.PORT, { waitUntil: 'networkidle0' })
|
||||
|
||||
return { browser, page }
|
||||
}
|
||||
|
||||
function prepareServer() {
|
||||
const serverConfig = {
|
||||
public: 'build',
|
||||
trailingSlash: false,
|
||||
rewrites: [{ source: '**', destination: '/index.html' }],
|
||||
}
|
||||
|
||||
const server = http.createServer((request, response) => {
|
||||
return handler(request, response, serverConfig)
|
||||
})
|
||||
server.listen(8080)
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,152 @@
|
||||
const puppeteer = require('puppeteer')
|
||||
|
||||
const SLEEP_MS = 500
|
||||
const SLEEP_ITERATIONS = 20
|
||||
|
||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} selector XPath selector
|
||||
*/
|
||||
async function waitForElementXPath(page, selector) {
|
||||
for (let i = 0; i < SLEEP_ITERATIONS; i++) {
|
||||
const [element] = await page.$x(selector)
|
||||
|
||||
if (element) {
|
||||
return element
|
||||
}
|
||||
await sleep(SLEEP_MS)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} selector CSS selector
|
||||
*/
|
||||
async function waitForElementCss(page, selector) {
|
||||
for (let i = 0; i < SLEEP_ITERATIONS; i++) {
|
||||
const element = await page.$(selector)
|
||||
|
||||
if (element) {
|
||||
return element
|
||||
}
|
||||
await sleep(SLEEP_MS)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
||||
* @param {string} text e.g. `"Submit"`
|
||||
*/
|
||||
function waitForEnabledStateXPath(page, elementType, text) {
|
||||
return waitForElementXPath(page, `//${elementType}[contains(., '${text}')][not(@disabled)]`)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
||||
* @param {string} text e.g. `"Submit"`
|
||||
*/
|
||||
async function clickElementWithText(page, elementType, text) {
|
||||
const element = await waitForElementXPath(page, `//${elementType}[contains(., '${text}')]`)
|
||||
|
||||
if (!element) {
|
||||
throw Error(`clickElementWithText: Could not find <${elementType}> containing "${text}"`)
|
||||
}
|
||||
|
||||
if (element) {
|
||||
await element.click()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
||||
* @param {string} text e.g. `"Submit"`
|
||||
* @param {string} filePath e.g. `"test-data/text.txt"`
|
||||
*/
|
||||
async function clickElementWithTextAndUpload(page, elementType, text, filePath) {
|
||||
const [fileChooser] = await Promise.all([page.waitForFileChooser(), clickElementWithText(page, elementType, text)])
|
||||
await fileChooser.accept([filePath])
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
||||
* @param {string} cssClass CSS class with the dot, e.g. '.MuiSelect-select'
|
||||
*/
|
||||
async function clickElementWithClass(page, elementType, cssClass) {
|
||||
const element = await waitForElementCss(page, `${elementType}${cssClass}`)
|
||||
|
||||
if (!element) {
|
||||
throw Error(`clickElementWithClass: Could not find <${elementType}> with class ${cssClass}`)
|
||||
}
|
||||
|
||||
if (element) {
|
||||
await element.click()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
||||
* @param {string} text e.g. `"Submit"`
|
||||
*/
|
||||
async function assertElementWithTextExists(page, elementType, text) {
|
||||
const element = await waitForElementXPath(page, `//${elementType}[contains(., '${text}')]`)
|
||||
|
||||
if (!element) {
|
||||
throw Error(`assertElementWithTextExists: Could not find <${elementType}> containing "${text}"`)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
||||
* @param {string} attribute HTML attribute, e.g. `alt` or `id`
|
||||
* @param {string} value Expected value of the attribute
|
||||
* @param {string} property Property to return from the queried HTML element
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function queryElementPropertyByAttribute(page, elementType, attribute, value, property) {
|
||||
const element = await waitForElementXPath(page, `//${elementType}[contains(@${attribute}, "${value}")]`)
|
||||
|
||||
return page.evaluate((element, property) => element[property], element, property)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
* @param {string} alt `<img>` `alt` to look for
|
||||
*/
|
||||
function queryImgSrcByAlt(page, alt) {
|
||||
return queryElementPropertyByAttribute(page, 'img', 'alt', alt, 'src')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sleep,
|
||||
Assert: {
|
||||
elementWithTextExists: assertElementWithTextExists,
|
||||
},
|
||||
Click: {
|
||||
elementWithText: clickElementWithText,
|
||||
elementWithClass: clickElementWithClass,
|
||||
elementWithTextAndUpload: clickElementWithTextAndUpload,
|
||||
},
|
||||
Query: {
|
||||
elementPropertyByAttribute: queryElementPropertyByAttribute,
|
||||
imgSrcByAlt: queryImgSrcByAlt,
|
||||
},
|
||||
Wait: {
|
||||
forElementCss: waitForElementCss,
|
||||
forElementXPath: waitForElementXPath,
|
||||
forEnabledStateXPath: waitForEnabledStateXPath,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
const puppeteer = require('puppeteer')
|
||||
const { selectStampAndUpload } = require('../helpers')
|
||||
const { Assert, Click } = require('../library')
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function testFolderUpload(page) {
|
||||
await Click.elementWithText(page, 'a', 'Files')
|
||||
await Click.elementWithTextAndUpload(page, 'button', 'Add Folder', 'test-data/test-folder')
|
||||
await assertUploadPreview(page)
|
||||
await selectStampAndUpload(page)
|
||||
await assertDownloadPreview(page)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertDownloadPreview(page) {
|
||||
await assertUploadPreview(page)
|
||||
await Assert.elementWithTextExists(page, 'p', 'Swarm Hash: 89ef8f3e[…]504e5d1c')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Folder Name: test-folder')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Kind: Folder')
|
||||
await Assert.elementWithTextExists(page, 'h6', '4 items')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertUploadPreview(page) {
|
||||
await Assert.elementWithTextExists(page, 'p', 'Folder Name: test-folder')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Kind: Folder')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Size: 6.56 kB')
|
||||
}
|
||||
|
||||
module.exports = { testFolderUpload }
|
||||
@@ -0,0 +1,33 @@
|
||||
const puppeteer = require('puppeteer')
|
||||
const { Assert, Click } = require('../library')
|
||||
const { selectStampAndUpload } = require('../helpers')
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function testImageFileUpload(page) {
|
||||
await Click.elementWithText(page, 'a', 'Files')
|
||||
await Click.elementWithTextAndUpload(page, 'button', 'Add File', 'test-data/1337x1337.jpg')
|
||||
await assertUploadPreview(page)
|
||||
await selectStampAndUpload(page)
|
||||
await assertDownloadPreview(page)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertUploadPreview(page) {
|
||||
await Assert.elementWithTextExists(page, 'p', 'Filename: 1337x1337.jpg')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Kind: image/jpeg')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Size: 116.88 kB')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertDownloadPreview(page) {
|
||||
await assertUploadPreview(page)
|
||||
await Assert.elementWithTextExists(page, 'p', 'Swarm Hash: 5de1d879[…]3427432d')
|
||||
}
|
||||
|
||||
module.exports = { testImageFileUpload }
|
||||
@@ -0,0 +1,25 @@
|
||||
const puppeteer = require('puppeteer')
|
||||
const { selectStampAndUpload, assertUploadedContentAtPath } = require('../helpers')
|
||||
const { Click } = require('../library')
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function testReactWebsiteUpload(page) {
|
||||
await Click.elementWithText(page, 'a', 'Files')
|
||||
await Click.elementWithTextAndUpload(page, 'button', 'Add Website', 'test-data/test-react-website')
|
||||
const swarmHash = await selectStampAndUpload(page)
|
||||
await assertUploadedContentAtPath(swarmHash, 'index.html', 'text/html; charset=utf-8')
|
||||
await assertUploadedContentAtPath(swarmHash, 'asset-manifest.json', 'application/json')
|
||||
await assertUploadedContentAtPath(swarmHash, 'static/css/main.073c9b0a.css', 'text/css; charset=utf-8')
|
||||
await assertUploadedContentAtPath(swarmHash, 'static/css/main.073c9b0a.css.map', '')
|
||||
await assertUploadedContentAtPath(swarmHash, 'static/js/787.28cb0dcd.chunk.js', 'application/javascript')
|
||||
await assertUploadedContentAtPath(swarmHash, 'static/js/787.28cb0dcd.chunk.js.map', '')
|
||||
await assertUploadedContentAtPath(
|
||||
swarmHash,
|
||||
'static/media/logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg',
|
||||
'image/svg+xml',
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = { testReactWebsiteUpload }
|
||||
@@ -0,0 +1,33 @@
|
||||
const puppeteer = require('puppeteer')
|
||||
const { selectStampAndUpload } = require('../helpers')
|
||||
const { Assert, Click } = require('../library')
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function testTextFileUpload(page) {
|
||||
await Click.elementWithText(page, 'a', 'Files')
|
||||
await Click.elementWithTextAndUpload(page, 'button', 'Add File', 'test-data/text.txt')
|
||||
await assertUploadPreview(page)
|
||||
await selectStampAndUpload(page)
|
||||
await assertDownloadPreview(page)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertUploadPreview(page) {
|
||||
await Assert.elementWithTextExists(page, 'p', 'Filename: text.txt')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Kind: text/plain')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Size: 1.64 kB')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertDownloadPreview(page) {
|
||||
assertUploadPreview(page)
|
||||
await Assert.elementWithTextExists(page, 'p', 'Swarm Hash: da0773a9[…]5f7a1b54')
|
||||
}
|
||||
|
||||
module.exports = { testTextFileUpload }
|
||||
@@ -0,0 +1,36 @@
|
||||
const puppeteer = require('puppeteer')
|
||||
const { selectStampAndUpload } = require('../helpers')
|
||||
const { Assert, Click } = require('../library')
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function testWebsiteUpload(page) {
|
||||
await Click.elementWithText(page, 'a', 'Files')
|
||||
await Click.elementWithTextAndUpload(page, 'button', 'Add Website', 'test-data/test-website')
|
||||
await assertUploadPreview(page)
|
||||
await selectStampAndUpload(page)
|
||||
await assertDownloadPreview(page)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertUploadPreview(page) {
|
||||
await Assert.elementWithTextExists(page, 'p', 'Folder Name: test-website')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Kind: Website')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Size: 390.10 kB')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
||||
*/
|
||||
async function assertDownloadPreview(page) {
|
||||
await assertUploadPreview(page)
|
||||
await Assert.elementWithTextExists(page, 'p', 'Swarm Hash: b9a6d15d[…]d0d48b81')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Folder Name: test-website')
|
||||
await Assert.elementWithTextExists(page, 'p', 'Kind: Website')
|
||||
await Assert.elementWithTextExists(page, 'h6', '3 items')
|
||||
}
|
||||
|
||||
module.exports = { testWebsiteUpload }
|
||||
Reference in New Issue
Block a user