diff --git a/src/components/action-menu/action-menu.jsx b/src/components/action-menu/action-menu.jsx
index 36cf5d444..f9e50f3ff 100644
--- a/src/components/action-menu/action-menu.jsx
+++ b/src/components/action-menu/action-menu.jsx
@@ -142,7 +142,7 @@ class ActionMenu extends React.Component {
{(moreButtons || []).map(({img, title, onClick: handleClick,
- fileAccept, fileChange, fileInput}, keyId) => {
+ fileAccept, fileChange, fileInput, fileMultiple}, keyId) => {
const isComingSoon = !handleClick;
const hasFileInput = fileInput;
const tooltipId = `${this.mainTooltipId}-${title}`;
@@ -166,6 +166,7 @@ class ActionMenu extends React.Component {
{
onClick: onBackdropFileUploadClick,
fileAccept: '.svg, .png, .jpg, .jpeg', // Bitmap coming soon
fileChange: onBackdropFileUpload,
- fileInput: fileInputRef
+ fileInput: fileInputRef,
+ fileMultiple: true
}, {
title: intl.formatMessage(messages.addBackdropFromSurprise),
img: surpriseIcon,
diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx
index 39e0419ac..3817c4f3c 100644
--- a/src/containers/costume-tab.jsx
+++ b/src/containers/costume-tab.jsx
@@ -293,7 +293,8 @@ class CostumeTab extends React.Component {
onClick: this.handleFileUploadClick,
fileAccept: '.svg, .png, .jpg, .jpeg',
fileChange: this.handleCostumeUpload,
- fileInput: this.setFileInput
+ fileInput: this.setFileInput,
+ fileMultiple: true
},
{
title: intl.formatMessage(messages.addSurpriseCostumeMsg),
diff --git a/src/containers/sound-tab.jsx b/src/containers/sound-tab.jsx
index 3880de2e5..9db3289d9 100644
--- a/src/containers/sound-tab.jsx
+++ b/src/containers/sound-tab.jsx
@@ -223,7 +223,8 @@ class SoundTab extends React.Component {
onClick: this.handleFileUploadClick,
fileAccept: '.wav, .mp3',
fileChange: this.handleSoundUpload,
- fileInput: this.setFileInput
+ fileInput: this.setFileInput,
+ fileMultiple: true
}, {
title: intl.formatMessage(messages.surpriseSound),
img: surpriseIcon,
diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js
index 74f3c64a8..483f31edf 100644
--- a/src/lib/file-uploader.js
+++ b/src/lib/file-uploader.js
@@ -21,22 +21,25 @@ const extractFileName = function (nameExt) {
* @param {Function} onload The function that handles loading the file
*/
const handleFileUpload = function (fileInput, onload) {
- let thisFile = null;
- const reader = new FileReader();
- reader.onload = () => {
- // Reset the file input value now that we have everything we need
- // so that the user can upload the same sound multiple times if
- // they choose
- fileInput.value = null;
- const fileType = thisFile.type;
- const fileName = extractFileName(thisFile.name);
-
- onload(reader.result, fileType, fileName);
+ const readFile = (i, files) => {
+ if (i === files.length) {
+ // Reset the file input value now that we have everything we need
+ // so that the user can upload the same sound multiple times if
+ // they choose
+ fileInput.value = null;
+ return;
+ }
+ const file = files[i];
+ const reader = new FileReader();
+ reader.onload = () => {
+ const fileType = file.type;
+ const fileName = extractFileName(file.name);
+ onload(reader.result, fileType, fileName);
+ readFile(i + 1, files);
+ };
+ reader.readAsArrayBuffer(file);
};
- if (fileInput.files) {
- thisFile = fileInput.files[0];
- reader.readAsArrayBuffer(thisFile);
- }
+ readFile(0, fileInput.files);
};
/**
diff --git a/test/fixtures/movie.wav b/test/fixtures/movie.wav
new file mode 100644
index 000000000..79c10d214
Binary files /dev/null and b/test/fixtures/movie.wav differ
diff --git a/test/fixtures/sneaker.wav b/test/fixtures/sneaker.wav
new file mode 100644
index 000000000..01c4a1759
Binary files /dev/null and b/test/fixtures/sneaker.wav differ
diff --git a/test/integration/backdrops.test.js b/test/integration/backdrops.test.js
index 9a527b2c9..d0a3e84aa 100644
--- a/test/integration/backdrops.test.js
+++ b/test/integration/backdrops.test.js
@@ -4,6 +4,7 @@ import SeleniumHelper from '../helpers/selenium-helper';
const {
clickText,
clickXpath,
+ findByText,
findByXpath,
getDriver,
getLogs,
@@ -49,4 +50,30 @@ describe('Working with backdrops', () => {
const logs = await getLogs();
await expect(logs).toEqual([]);
});
+
+ test.only('Adding multiple backdrops at the same time', async () => {
+ const files = [
+ path.resolve(__dirname, '../fixtures/gh-3582-png.png'),
+ path.resolve(__dirname, '../fixtures/100-100.svg')
+ ];
+ await loadUri(uri);
+ await clickXpath('//button[@title="Try It"]');
+
+ const buttonXpath = '//button[@aria-label="Choose a Backdrop"]';
+ const fileXpath = `${buttonXpath}/following-sibling::div//input[@type="file"]`;
+
+ const el = await findByXpath(buttonXpath);
+ await driver.actions().mouseMove(el)
+ .perform();
+ await driver.sleep(500); // Wait for thermometer menu to come up
+ const input = await findByXpath(fileXpath);
+ await input.sendKeys(files.join('\n'));
+
+ await clickXpath('//span[text()="Stage"]');
+ await findByText('gh-3582-png', scope.costumesTab);
+ await findByText('100-100', scope.costumesTab);
+
+ const logs = await getLogs();
+ await expect(logs).toEqual([]);
+ });
});
diff --git a/test/integration/costumes.test.js b/test/integration/costumes.test.js
index 5181c429a..803abbdaf 100644
--- a/test/integration/costumes.test.js
+++ b/test/integration/costumes.test.js
@@ -4,6 +4,7 @@ import SeleniumHelper from '../helpers/selenium-helper';
const {
clickText,
clickXpath,
+ findByText,
findByXpath,
getDriver,
getLogs,
@@ -181,4 +182,25 @@ describe('Working with costumes', () => {
await expect(logs).toEqual([]);
});
+ test.only('Adding multiple costumes at the same time', async () => {
+ const files = [
+ path.resolve(__dirname, '../fixtures/gh-3582-png.png'),
+ path.resolve(__dirname, '../fixtures/100-100.svg')
+ ];
+ await loadUri(uri);
+ await clickXpath('//button[@title="Try It"]');
+ await clickText('Costumes');
+ const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
+ await driver.actions().mouseMove(el)
+ .perform();
+ await driver.sleep(500); // Wait for thermometer menu to come up
+ const input = await findByXpath('//input[@type="file"]');
+ await input.sendKeys(files.join('\n'));
+
+ await findByText('gh-3582-png', scope.costumesTab);
+ await findByText('100-100', scope.costumesTab);
+
+ const logs = await getLogs();
+ await expect(logs).toEqual([]);
+ });
});
diff --git a/test/integration/sounds.test.js b/test/integration/sounds.test.js
index 3877ada3f..940e4750c 100644
--- a/test/integration/sounds.test.js
+++ b/test/integration/sounds.test.js
@@ -4,6 +4,7 @@ import SeleniumHelper from '../helpers/selenium-helper';
const {
clickText,
clickXpath,
+ findByText,
findByXpath,
getDriver,
getLogs,
@@ -114,4 +115,26 @@ describe('Working with sounds', () => {
const logs = await getLogs();
await expect(logs).toEqual([]);
});
+
+ test.only('Adding multiple sounds at the same time', async () => {
+ const files = [
+ path.resolve(__dirname, '../fixtures/movie.wav'),
+ path.resolve(__dirname, '../fixtures/sneaker.wav')
+ ];
+ await loadUri(uri);
+ await clickXpath('//button[@title="Try It"]');
+ await clickText('Sounds');
+ const el = await findByXpath('//button[@aria-label="Choose a Sound"]');
+ await driver.actions().mouseMove(el)
+ .perform();
+ await driver.sleep(500); // Wait for thermometer menu to come up
+ const input = await findByXpath('//input[@type="file"]');
+ await input.sendKeys(files.join('\n'));
+
+ await findByText('movie', scope.soundsTab);
+ await findByText('sneaker', scope.soundsTab);
+
+ const logs = await getLogs();
+ await expect(logs).toEqual([]);
+ });
});
diff --git a/test/integration/sprites.test.js b/test/integration/sprites.test.js
index a3dd48cf4..12ab36a5f 100644
--- a/test/integration/sprites.test.js
+++ b/test/integration/sprites.test.js
@@ -159,4 +159,25 @@ describe('Working with sprites', () => {
await expect(logs).toEqual([]);
});
+ test.only('Adding multiple sprites at the same time', async () => {
+ const files = [
+ path.resolve(__dirname, '../fixtures/gh-3582-png.png'),
+ path.resolve(__dirname, '../fixtures/100-100.svg')
+ ];
+ await loadUri(uri);
+ await clickXpath('//button[@title="Try It"]');
+ const el = await findByXpath('//button[@aria-label="Choose a Sprite"]');
+ await driver.actions().mouseMove(el)
+ .perform();
+ await driver.sleep(500); // Wait for thermometer menu to come up
+ const input = await findByXpath('//input[@type="file"]');
+ await input.sendKeys(files.join('\n'));
+
+ await findByText('gh-3582-png', scope.spriteTile);
+ await findByText('100-100', scope.spriteTile);
+
+ const logs = await getLogs();
+ await expect(logs).toEqual([]);
+ });
+
});