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:
Cafe137
2022-07-25 11:24:32 +02:00
committed by GitHub
parent f01477ea70
commit 186d0352cf
35 changed files with 1521 additions and 1 deletions
+45
View File
@@ -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 }
+63
View File
@@ -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()
+152
View File
@@ -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,
},
}
+36
View File
@@ -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 }
+33
View File
@@ -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 }
+25
View File
@@ -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 }
+33
View File
@@ -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 }
+36
View File
@@ -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 }