fs.spec.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import fsp from 'fs/promises';
  2. import path from 'path';
  3. import { expect } from '@playwright/test'
  4. import { test } from './fixtures';
  5. import { searchPage, captureConsoleWithPrefix, closeSearchBox, createPage, IsWindows, randomString } from './utils';
  6. test('create file on disk then delete', async ({ page, block, graphDir }) => {
  7. // Since have to wait for file watchers
  8. test.slow();
  9. // Special page names: namespaced, chars require escaping, chars require unicode normalization, "%" chars, "%" with 2 hexdigests
  10. const testCases = [
  11. {pageTitle: "User:John", fileName: "User%3AJohn"},
  12. // invalid url decode escaping as %ff is not parsable but match the common URL encode regex
  13. {pageTitle: "#%ff", fileName: "#%ff"},
  14. // valid url decode escaping
  15. {pageTitle: "#%23", fileName: "#%2523"},
  16. {pageTitle: "@!#%", fileName: "@!#%"},
  17. {pageTitle: "aàáâ", fileName: "aàáâ"},
  18. {pageTitle: "#%gggg", fileName: "#%gggg"}
  19. ]
  20. if (!IsWindows)
  21. testCases.push({pageTitle: "User:Bob", fileName: "User:Bob"})
  22. function getFullPath(fileName: string) {
  23. return path.join(graphDir, "pages", `${fileName}.md`);
  24. }
  25. // Test putting files on disk
  26. for (const {pageTitle, fileName} of testCases) {
  27. // Put the file on disk
  28. const filePath = getFullPath(fileName);
  29. await fsp.writeFile(filePath, `- content for ${pageTitle}`);
  30. await captureConsoleWithPrefix(page, "Parsing finished:", 5000)
  31. // Check that the page is created
  32. const results = await searchPage(page, pageTitle);
  33. const firstResultRow = await results[0].innerText()
  34. expect(firstResultRow).toContain(pageTitle);
  35. expect(firstResultRow).not.toContain("Create");
  36. await closeSearchBox(page);
  37. }
  38. // Test removing files on disk
  39. for (const {pageTitle, fileName} of testCases) {
  40. // Remove the file on disk
  41. const filePath = getFullPath(fileName);
  42. await fsp.unlink(filePath);
  43. await captureConsoleWithPrefix(page, "Delete page:", 5000);
  44. // Test that the page is deleted
  45. const results = await searchPage(page, pageTitle);
  46. const firstResultRow = await results[0].innerText()
  47. // expect(firstResultRow).toContain("Create");
  48. await closeSearchBox(page);
  49. }
  50. });
  51. test("Rename file on disk", async ({ page, block, graphDir }) => {
  52. // Since have to wait for file watchers
  53. test.slow();
  54. const testCases = [
  55. // Normal -> NameSpace
  56. {pageTitle: "User:John", fileName: "User%3AJohn",
  57. newPageTitle: "User/John", newFileName: "User___John"},
  58. // NameSpace -> Normal
  59. {pageTitle: "#/%23", fileName: "#___%2523",
  60. newPageTitle: "#%23", newFileName: "#%2523"}
  61. ]
  62. if (!IsWindows)
  63. testCases.push({pageTitle: "User:Bob", fileName: "User:Bob",
  64. newPageTitle: "User/Bob", newFileName: "User___Bob"})
  65. function getFullPath(fileName: string) {
  66. return path.join(graphDir, "pages", `${fileName}.md`);
  67. }
  68. // Test putting files on disk
  69. for (const {pageTitle, fileName} of testCases) {
  70. // Put the file on disk
  71. const filePath = getFullPath(fileName);
  72. await fsp.writeFile(filePath, `- content for ${pageTitle}`);
  73. await captureConsoleWithPrefix(page, "Parsing finished:", 5000)
  74. // Check that the page is created
  75. const results = await searchPage(page, pageTitle);
  76. const firstResultRow = await results[0].innerText()
  77. expect(firstResultRow).toContain(pageTitle);
  78. expect(firstResultRow).not.toContain("Create");
  79. await closeSearchBox(page);
  80. }
  81. // Test renaming files on disk
  82. for (const {pageTitle, fileName, newPageTitle, newFileName} of testCases) {
  83. // Rename the file on disk
  84. const filePath = getFullPath(fileName);
  85. const newFilePath = getFullPath(newFileName);
  86. await fsp.rename(filePath, newFilePath);
  87. await captureConsoleWithPrefix(page, "Parsing finished:", 5000);
  88. await page.waitForTimeout(500);
  89. // Test that the page is renamed
  90. const results = await searchPage(page, newPageTitle);
  91. const firstResultRow = await results[0].innerText()
  92. expect(firstResultRow).toContain(newPageTitle);
  93. expect(firstResultRow).not.toContain(pageTitle);
  94. expect(firstResultRow).not.toContain("Create");
  95. await closeSearchBox(page);
  96. }
  97. })
  98. test('special page names', async ({ page, block, graphDir }) => {
  99. const testCases = [
  100. {pageTitle: "User:John", fileName: "User%3AJohn"},
  101. {pageTitle: "_#%ff", fileName: "_%23%25ff"},
  102. {pageTitle: "@!#%", fileName: "@!%23%"},
  103. {pageTitle: "aàáâ", fileName: "aàáâ"},
  104. {pageTitle: "_#%gggg", fileName: "_%23%gggg"}
  105. ]
  106. // Test putting files on disk
  107. for (const {pageTitle, fileName} of testCases) {
  108. const prefix = randomString(10)
  109. const fullTitle = `${prefix}${pageTitle}`
  110. // Create page in Logseq
  111. await createPage(page, fullTitle)
  112. const text = `content for ${pageTitle}`
  113. await block.mustFill(text)
  114. await page.keyboard.press("Enter", { delay: 50 })
  115. await page.keyboard.press("Escape", { delay: 50 })
  116. // Wait for the file to be created on disk
  117. await page.waitForTimeout(2500);
  118. // Validate that the file is created on disk with the content
  119. const filePath = path.join(graphDir, "pages", `${prefix}${fileName}.md`);
  120. const fileContent = await fsp.readFile(filePath, "utf8");
  121. expect(fileContent).toContain(text);
  122. }
  123. });