Skip to content

Commit

Permalink
test(e2e): fs testings - file create, rename, unlink
Browse files Browse the repository at this point in the history
  • Loading branch information
cnrpman committed Mar 16, 2023
1 parent eee7d06 commit 3bd3991
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 114 deletions.
105 changes: 105 additions & 0 deletions e2e-tests/fs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import fsp from 'fs/promises';
import path from 'path';
import { expect } from '@playwright/test'
import { test } from './fixtures';
import { searchPage, captureConsoleWithPrefix, closeSearchBox } from './utils';

test('create file on disk then delete', async ({ page, block, graphDir }) => {
// Since have to wait for file watchers
test.slow();

// Special page names: namespaced, chars require escaping, chars require unicode normalization, "%" chars, "%" with 2 hexdigests
const testCases = [
{pageTitle: "User:John", fileName: "User:John"},
// invalid url decode escaping as %ff is not parsable but match the common URL encode regex
{pageTitle: ":#%ff", fileName: ":#%ff"},
// valid url decode escaping
{pageTitle: ":#%23", fileName: ":#%2523"},
{pageTitle: "@!#%", fileName: "@!#%"},
{pageTitle: "aàáâ", fileName: "aàáâ"},
{pageTitle: ":#%gggg", fileName: ":#%gggg"}
]

function getFullPath(fileName: string) {
return path.join(graphDir, "pages", `${fileName}.md`);
}

// Test putting files on disk
for (const {pageTitle, fileName} of testCases) {
// Put the file on disk
const filePath = getFullPath(fileName);
await fsp.writeFile(filePath, `- content for ${pageTitle}`);
await captureConsoleWithPrefix(page, "Parsing finished:", 5000)

// Check that the page is created
const results = await searchPage(page, pageTitle);
const firstResultRow = await results[0].innerText()
expect(firstResultRow).toContain(pageTitle);
expect(firstResultRow).not.toContain("New");
await closeSearchBox(page);
}

// Test removing files on disk
for (const {pageTitle, fileName} of testCases) {
// Remove the file on disk
const filePath = getFullPath(fileName);
await fsp.unlink(filePath);
await captureConsoleWithPrefix(page, "Delete page:", 5000);

// Test that the page is deleted
const results = await searchPage(page, pageTitle);
const firstResultRow = await results[0].innerText()
expect(firstResultRow).toContain("New");
await closeSearchBox(page);
}
});

test("Rename file on disk", async ({ page, block, graphDir }) => {
// Since have to wait for file watchers
test.slow();

const testCases = [
// Normal -> NameSpace
{pageTitle: "User:John", fileName: "User:John",
newPageTitle: "User/John", newFileName: "User___John"},
// NameSpace -> Normal
{pageTitle: ":#/%23", fileName: ":#___%2523",
newPageTitle: ":#%23", newFileName: ":#%2523"}
]

function getFullPath(fileName: string) {
return path.join(graphDir, "pages", `${fileName}.md`);
}

// Test putting files on disk
for (const {pageTitle, fileName} of testCases) {
// Put the file on disk
const filePath = getFullPath(fileName);
await fsp.writeFile(filePath, `- content for ${pageTitle}`);
await captureConsoleWithPrefix(page, "Parsing finished:", 5000)

// Check that the page is created
const results = await searchPage(page, pageTitle);
const firstResultRow = await results[0].innerText()
expect(firstResultRow).toContain(pageTitle);
expect(firstResultRow).not.toContain("New");
await closeSearchBox(page);
}

// Test renaming files on disk
for (const {pageTitle, fileName, newPageTitle, newFileName} of testCases) {
// Rename the file on disk
const filePath = getFullPath(fileName);
const newFilePath = getFullPath(newFileName);
await fsp.rename(filePath, newFilePath);
await captureConsoleWithPrefix(page, "Parsing finished:", 5000);

// Test that the page is renamed
const results = await searchPage(page, newPageTitle);
const firstResultRow = await results[0].innerText()
expect(firstResultRow).toContain(newPageTitle);
expect(firstResultRow).not.toContain(pageTitle);
expect(firstResultRow).not.toContain("New");
await closeSearchBox(page);
}
})
48 changes: 12 additions & 36 deletions e2e-tests/page-search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect, Page } from '@playwright/test'
import { test } from './fixtures'
import { Block } from './types'
import { modKey, createRandomPage, newBlock, newInnerBlock, randomString, lastBlock, enterNextBlock } from './utils'
import { searchPage, closeSearchBox } from './util/search-modal'

/***
* Test alias features
Expand Down Expand Up @@ -37,18 +38,9 @@ test('Search page and blocks (diacritics)', async ({ page, block }) => {
await page.keyboard.press(hotkeyBack)

// check if diacritics are indexed
await page.click('#search-button')
await page.waitForSelector('[placeholder="Search or create page"]')
await page.type('[placeholder="Search or create page"]', 'Einführung in die Allgemeine Sprachwissenschaft' + rand, { delay: 10 })

await page.waitForTimeout(2000) // wait longer for search contents to render
// 2 blocks + 1 page + 1 page content
const searchResults = page.locator('#ui__ac-inner>div')
await expect(searchResults).toHaveCount(5) // 1 page + 2 block + 2 page content

await page.keyboard.press("Escape") // escape search box typing
await page.waitForTimeout(500)
await page.keyboard.press("Escape") // escape modal
const results = await searchPage(page, 'Einführung in die Allgemeine Sprachwissenschaft' + rand)
await expect(results.length).toEqual(5) // 1 page + 2 block + 2 page content
await closeSearchBox(page)
})

test('Search CJK', async ({ page, block }) => {
Expand All @@ -67,19 +59,10 @@ test('Search CJK', async ({ page, block }) => {

await page.waitForTimeout(500)

// check if diacritics are indexed
await page.click('#search-button')
await page.waitForSelector('[placeholder="Search or create page"]')
await page.type('[placeholder="Search or create page"]', '进度', { delay: 10 })

await page.waitForTimeout(2000) // wait longer for search contents to render
// 2 blocks + 1 page + 1 page content
const searchResults = page.locator('#ui__ac-inner>div')
await expect(searchResults).toHaveCount(4) // 1 new page + 1 page + 1 block + 1 page content

await page.keyboard.press("Escape") // escape search box typing
await page.waitForTimeout(500)
await page.keyboard.press("Escape") // escape modal
// check if CJK are indexed
const results = await searchPage(page, '进度')
await expect(results.length).toEqual(4) // 1 page + 1 block + 1 page content
await closeSearchBox(page)
})

async function alias_test(block: Block, page: Page, page_name: string, search_kws: string[]) {
Expand Down Expand Up @@ -165,13 +148,8 @@ async function alias_test(block: Block, page: Page, page_name: string, search_kw
for (let kw of search_kws) {
let kw_name = kw + ' alias ' + rand

await page.click('#search-button')
await page.waitForSelector('[placeholder="Search or create page"]')
await page.type('[placeholder="Search or create page"]', kw_name)
await page.waitForTimeout(500)

const results = await page.$$('#ui__ac-inner>div')
expect(results.length).toEqual(5) // page + block + alias property + page content
const results = await searchPage(page, kw_name)
await expect(results.length).toEqual(5) // page + block + alias property + page content

// test search results
expect(await results[0].innerText()).toContain("Alias -> " + target_name)
Expand All @@ -186,10 +164,8 @@ async function alias_test(block: Block, page: Page, page_name: string, search_kw
expect(await page.locator('.ls-block span.inline >> nth=2').innerHTML()).toBe(alias_test_content_3)

// test search clicking (block)
await page.click('#search-button')
await page.waitForSelector('[placeholder="Search or create page"]')
await page.type('[placeholder="Search or create page"]', kw_name)
await page.waitForTimeout(500)
await searchPage(page, kw_name)

page.click(":nth-match(.search-result, 3)")
await page.waitForNavigation()
await page.waitForSelector('.selected a.page-ref')
Expand Down
42 changes: 42 additions & 0 deletions e2e-tests/util/basic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// This file is used to store basic functions that are used in other utils
// Should have no dependency on other utils

import * as process from 'process'

export const IsMac = process.platform === 'darwin'
export const IsLinux = process.platform === 'linux'
export const IsWindows = process.platform === 'win32'
export const IsCI = process.env.CI === 'true'
export const modKey = IsMac ? 'Meta' : 'Control'

export function randomString(length: number) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

let result = '';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}

return result;
}

export function randomLowerString(length: number) {
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';

let result = '';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}

return result;
}

export function randomInt(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1) + min)
}

export function randomBoolean(): boolean {
return Math.random() < 0.5;
}
63 changes: 63 additions & 0 deletions e2e-tests/util/search-modal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Page, Locator, ElementHandle } from '@playwright/test'
import { randomString } from './basic'

export async function createRandomPage(page: Page) {
const randomTitle = randomString(20)

// Click #search-button
await page.click('#search-button')
// Fill [placeholder="Search or create page"]
await page.fill('[placeholder="Search or create page"]', randomTitle)
// Click text=/.*New page: "new page".*/
await page.click('text=/.*New page: ".*/')
// Wait for h1 to be from our new page
await page.waitForSelector(`h1 >> text="${randomTitle}"`, { state: 'visible' })
// wait for textarea of first block
await page.waitForSelector('textarea >> nth=0', { state: 'visible' })

return randomTitle;
}

export async function createPage(page: Page, page_name: string) {// Click #search-button
await page.click('#search-button')
// Fill [placeholder="Search or create page"]
await page.fill('[placeholder="Search or create page"]', page_name)
// Click text=/.*New page: "new page".*/
await page.click('text=/.*New page: ".*/')
// wait for textarea of first block
await page.waitForSelector('textarea >> nth=0', { state: 'visible' })

return page_name;
}

export async function searchAndJumpToPage(page: Page, pageTitle: string) {
await page.click('#search-button')
await page.type('[placeholder="Search or create page"]', pageTitle)
await page.waitForSelector(`[data-page-ref="${pageTitle}"]`, { state: 'visible' })
page.click(`[data-page-ref="${pageTitle}"]`)
await page.waitForNavigation()
return pageTitle;
}

/**
* type a search query into the search box
* stop at the point where search box shows up
*
* @param page the pw page object
* @param query the search query to type into the search box
* @returns the HTML element for the search results ui
*/
export async function searchPage(page: Page, query: string): Promise<ElementHandle<SVGElement | HTMLElement>[]>{
await page.click('#search-button')
await page.waitForSelector('[placeholder="Search or create page"]')
await page.type('[placeholder="Search or create page"]', query, { delay: 10 })
await page.waitForTimeout(2000) // wait longer for search contents to render

return page.$$('#ui__ac-inner>div');
}

export async function closeSearchBox(page: Page): Promise<void> {
await page.keyboard.press("Escape") // escape (potential) search box typing
await page.waitForTimeout(500)
await page.keyboard.press("Escape") // escape modal
}
Loading

0 comments on commit 3bd3991

Please sign in to comment.