costumes.test.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import path from 'path';
  2. import SeleniumHelper from '../helpers/selenium-helper';
  3. const {
  4. clickText,
  5. clickXpath,
  6. findByText,
  7. findByXpath,
  8. getDriver,
  9. getLogs,
  10. loadUri,
  11. rightClickText,
  12. scope
  13. } = new SeleniumHelper();
  14. const uri = path.resolve(__dirname, '../../build/index.html');
  15. let driver;
  16. describe('Working with costumes', () => {
  17. beforeAll(() => {
  18. driver = getDriver();
  19. });
  20. afterAll(async () => {
  21. await driver.quit();
  22. });
  23. test('Adding a costume through the library', async () => {
  24. // This is needed when running the tests all at once or it just fails...
  25. await driver.quit();
  26. driver = getDriver();
  27. await loadUri(uri);
  28. await driver.sleep(500);
  29. await clickText('Costumes');
  30. await clickXpath('//button[@aria-label="Choose a Costume"]');
  31. const el = await findByXpath("//input[@placeholder='Search']");
  32. await el.sendKeys('abb');
  33. await clickText('Abby-a'); // Should close the modal, then click the costumes in the selector
  34. await findByXpath("//input[@value='Abby-a']"); // Should show editor for new costume
  35. const logs = await getLogs();
  36. await expect(logs).toEqual([]);
  37. });
  38. test('Adding a costume by surprise button', async () => {
  39. await loadUri(uri);
  40. await clickText('Costumes');
  41. const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
  42. await driver.actions().mouseMove(el)
  43. .perform();
  44. await driver.sleep(500); // Wait for thermometer menu to come up
  45. await clickXpath('//button[@aria-label="Surprise"]');
  46. const logs = await getLogs();
  47. await expect(logs).toEqual([]);
  48. });
  49. test('Adding a costume by paint button', async () => {
  50. await loadUri(uri);
  51. await clickText('Costumes');
  52. const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
  53. await driver.actions().mouseMove(el)
  54. .perform();
  55. await driver.sleep(500); // Wait for thermometer menu to come up
  56. await clickXpath('//button[@aria-label="Paint"]');
  57. const logs = await getLogs();
  58. await expect(logs).toEqual([]);
  59. });
  60. test('Duplicating a costume', async () => {
  61. await loadUri(uri);
  62. await clickText('Costumes');
  63. await rightClickText('costume1', scope.costumesTab);
  64. await clickText('duplicate', scope.costumesTab);
  65. await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for duplication to finish
  66. // Make sure the duplicated costume is named correctly.
  67. await clickText('costume3', scope.costumesTab);
  68. const logs = await getLogs();
  69. await expect(logs).toEqual([]);
  70. });
  71. test('Converting bitmap/vector in paint editor', async () => {
  72. await loadUri(uri);
  73. await clickText('Costumes');
  74. // Convert the first costume to bitmap.
  75. await clickText('costume1', scope.costumesTab);
  76. await clickText('Convert to Bitmap', scope.costumesTab);
  77. // Make sure mode switches back to vector for vector costume.
  78. await clickText('costume2', scope.costumesTab);
  79. await clickText('Convert to Bitmap', scope.costumesTab);
  80. // Make sure bitmap is saved by switching back and converting to vector.
  81. await clickText('Sounds');
  82. await clickText('Costumes');
  83. await clickText('Convert to Vector', scope.costumesTab); // costume2
  84. await clickText('costume1', scope.costumesTab);
  85. await clickText('Convert to Vector', scope.costumesTab);
  86. const logs = await getLogs();
  87. await expect(logs).toEqual([]);
  88. });
  89. test('Undo/redo in the paint editor', async () => {
  90. await loadUri(uri);
  91. await clickText('Costumes');
  92. await clickText('costume1', scope.costumesTab);
  93. await clickText('Convert to Bitmap', scope.costumesTab);
  94. await clickXpath('//img[@alt="Undo"]');
  95. await clickText('Convert to Bitmap', scope.costumesTab);
  96. await clickXpath('//img[@alt="Undo"]');
  97. await clickXpath('//img[@alt="Redo"]');
  98. await clickText('Convert to Vector', scope.costumesTab);
  99. const logs = await getLogs();
  100. await expect(logs).toEqual([]);
  101. });
  102. test('Adding an svg from file', async () => {
  103. await loadUri(uri);
  104. await clickText('Costumes');
  105. const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
  106. await driver.actions().mouseMove(el)
  107. .perform();
  108. await driver.sleep(500); // Wait for thermometer menu to come up
  109. const input = await findByXpath('//input[@type="file"]');
  110. await input.sendKeys(path.resolve(__dirname, '../fixtures/100-100.svg'));
  111. await clickText('100-100', scope.costumesTab); // Name from filename
  112. await clickText('100 x 100', scope.costumesTab); // Size is right
  113. const logs = await getLogs();
  114. await expect(logs).toEqual([]);
  115. });
  116. test('Adding a png from file (gh-3582)', async () => {
  117. await loadUri(uri);
  118. await clickText('Costumes');
  119. const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
  120. await driver.actions().mouseMove(el)
  121. .perform();
  122. await driver.sleep(500); // Wait for thermometer menu to come up
  123. const input = await findByXpath('//input[@type="file"]');
  124. await input.sendKeys(path.resolve(__dirname, '../fixtures/gh-3582-png.png'));
  125. await clickText('gh-3582-png', scope.costumesTab);
  126. const logs = await getLogs();
  127. await expect(logs).toEqual([]);
  128. });
  129. test('Adding several costumes with a gif', async () => {
  130. await loadUri(uri);
  131. await clickText('Costumes');
  132. const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
  133. await driver.actions().mouseMove(el)
  134. .perform();
  135. await driver.sleep(500); // Wait for thermometer menu to come up
  136. const input = await findByXpath('//input[@type="file"]');
  137. await input.sendKeys(path.resolve(__dirname, '../fixtures/paddleball.gif'));
  138. await findByText('paddleball', scope.costumesTab);
  139. await findByText('paddleball2', scope.costumesTab);
  140. await findByText('paddleball3', scope.costumesTab);
  141. await findByText('paddleball4', scope.costumesTab);
  142. await findByText('paddleball5', scope.costumesTab);
  143. await findByText('paddleball6', scope.costumesTab);
  144. const logs = await getLogs();
  145. await expect(logs).toEqual([]);
  146. });
  147. test('Adding a letter costume through the Letters filter in the library', async () => {
  148. await loadUri(uri);
  149. await driver.manage()
  150. .window()
  151. .setSize(1244, 768); // Letters filter not visible at 1024 width
  152. await clickText('Costumes');
  153. await clickXpath('//button[@aria-label="Choose a Costume"]');
  154. await clickText('Letters');
  155. await clickText('Block-a', scope.modal); // Closes modal
  156. await rightClickText('Block-a', scope.costumesTab); // Make sure it is there
  157. const logs = await getLogs();
  158. await expect(logs).toEqual([]);
  159. });
  160. test('Costumes animate on mouseover', async () => {
  161. await loadUri(uri);
  162. await clickXpath('//button[@aria-label="Choose a Sprite"]');
  163. const searchElement = await findByXpath("//input[@placeholder='Search']");
  164. await searchElement.sendKeys('abb');
  165. const abbyElement = await findByXpath('//*[span[text()="Abby"]]');
  166. driver.actions()
  167. .mouseMove(abbyElement)
  168. .perform();
  169. // wait for one of Abby's alternate costumes to appear
  170. await findByXpath('//img[@src="https://cdn.assets.scratch.mit.edu/internalapi/asset/b6e23922f23b49ddc6f62f675e77417c.svg/get/"]');
  171. const logs = await getLogs();
  172. await expect(logs).toEqual([]);
  173. });
  174. test('Adding multiple costumes at the same time', async () => {
  175. const files = [
  176. path.resolve(__dirname, '../fixtures/gh-3582-png.png'),
  177. path.resolve(__dirname, '../fixtures/100-100.svg')
  178. ];
  179. await loadUri(uri);
  180. await clickText('Costumes');
  181. const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
  182. await driver.actions().mouseMove(el)
  183. .perform();
  184. await driver.sleep(500); // Wait for thermometer menu to come up
  185. const input = await findByXpath('//input[@type="file"]');
  186. await input.sendKeys(files.join('\n'));
  187. await findByText('gh-3582-png', scope.costumesTab);
  188. await findByText('100-100', scope.costumesTab);
  189. const logs = await getLogs();
  190. await expect(logs).toEqual([]);
  191. });
  192. });