mirror of
https://github.com/maputnik/editor.git
synced 2026-08-24 14:07:33 +00:00
Fix firefox ability to load file, add firefox tests back (#1380)
## Launch Checklist This PR fixes the problem with firefox not able to load a file when clicking the open file button. It does so by removing a very old dependency: `react-file-reader-input` It uses the "regular" `<label><a/><input type="file" /><label>` approach. It adds tests for both firefox and chrome although I'm not sure the firefox tests will stay... - [x] Briefly describe the changes in this PR. - [x] Write tests for all new functionality. - [x] Add an entry to `CHANGELOG.md` under the `## main` section.
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
- Fix modal close button possition
|
- Fix modal close button possition
|
||||||
- Fixed an issue with the generation of tranlations
|
- Fixed an issue with the generation of tranlations
|
||||||
- Fix missing spec info when clicking next to a property
|
- Fix missing spec info when clicking next to a property
|
||||||
|
- Fix Firefox open file that stopped working due to react upgrade
|
||||||
- _...Add new stuff here..._
|
- _...Add new stuff here..._
|
||||||
|
|
||||||
## 3.0.0
|
## 3.0.0
|
||||||
|
|||||||
@@ -26,6 +26,22 @@ export default class MaputnikCypressHelper {
|
|||||||
this.helper.when.wait(200);
|
this.helper.when.wait(200);
|
||||||
this.helper.get.elementByTestId(element).realMouseUp();
|
this.helper.get.elementByTestId(element).realMouseUp();
|
||||||
},
|
},
|
||||||
|
openFileByFixture: (fixture: string, buttonTestId: string, inputTestId: string) => {
|
||||||
|
cy.window().then((win) => {
|
||||||
|
const file = {
|
||||||
|
text: cy.stub().resolves(cy.fixture(fixture).then(JSON.stringify)),
|
||||||
|
};
|
||||||
|
const fileHandle = {
|
||||||
|
getFile: cy.stub().resolves(file),
|
||||||
|
};
|
||||||
|
if (!win.showOpenFilePicker) {
|
||||||
|
this.helper.get.elementByTestId(inputTestId).selectFile("cypress/fixtures/" + fixture, { force: true });
|
||||||
|
} else {
|
||||||
|
cy.stub(win, "showOpenFilePicker").resolves([fileHandle]);
|
||||||
|
this.helper.get.elementByTestId(buttonTestId).click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
...this.helper.when,
|
...this.helper.when,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -109,9 +109,9 @@ export class MaputnikDriver {
|
|||||||
this.helper.when.waitForResponse("example-style.json");
|
this.helper.when.waitForResponse("example-style.json");
|
||||||
},
|
},
|
||||||
chooseExampleFile: () => {
|
chooseExampleFile: () => {
|
||||||
this.helper.get
|
this.helper.given.fixture("example-style.json", "example-style.json");
|
||||||
.bySelector("type", "file")
|
this.helper.when.openFileByFixture("example-style.json", "modal:open.file.button", "modal:open.file.input");
|
||||||
.selectFile("cypress/fixtures/example-style.json", { force: true });
|
this.helper.when.wait(200);
|
||||||
},
|
},
|
||||||
setStyle: (
|
setStyle: (
|
||||||
styleProperties: "geojson" | "raster" | "both" | "layer" | "rectangles" | "",
|
styleProperties: "geojson" | "raster" | "both" | "layer" | "rectangles" | "",
|
||||||
|
|||||||
@@ -18,10 +18,9 @@ describe("modals", () => {
|
|||||||
then(get.elementByTestId("modal:open")).shouldNotExist();
|
then(get.elementByTestId("modal:open")).shouldNotExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip("upload", () => {
|
it("upload", () => {
|
||||||
// HM: I was not able to make the following choose file actually to select a file and close the modal...
|
|
||||||
when.chooseExampleFile();
|
when.chooseExampleFile();
|
||||||
then(get.responseBody("example-style.json")).shouldEqualToStoredStyle();
|
then(get.fixture("example-style.json")).shouldEqualToStoredStyle();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when click open url", () => {
|
describe("when click open url", () => {
|
||||||
@@ -334,6 +333,7 @@ describe("modals", () => {
|
|||||||
|
|
||||||
it("add variable", () => {
|
it("add variable", () => {
|
||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
|
when.wait(100);
|
||||||
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
state: { key1: { default: "value" } },
|
state: { key1: { default: "value" } },
|
||||||
});
|
});
|
||||||
@@ -344,6 +344,7 @@ describe("modals", () => {
|
|||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
|
when.wait(100);
|
||||||
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
state: { key1: { default: "value" }, key2: { default: "value" }, key3: { default: "value" } },
|
state: { key1: { default: "value" }, key2: { default: "value" }, key3: { default: "value" } },
|
||||||
});
|
});
|
||||||
@@ -354,6 +355,7 @@ describe("modals", () => {
|
|||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
when.click("global-state-remove-variable", 0);
|
when.click("global-state-remove-variable", 0);
|
||||||
|
when.wait(100);
|
||||||
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
state: { key2: { default: "value" }, key3: { default: "value" } },
|
state: { key2: { default: "value" }, key3: { default: "value" } },
|
||||||
});
|
});
|
||||||
@@ -363,6 +365,7 @@ describe("modals", () => {
|
|||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
when.setValue("global-state-variable-key:0", "mykey");
|
when.setValue("global-state-variable-key:0", "mykey");
|
||||||
when.typeKeys("{enter}");
|
when.typeKeys("{enter}");
|
||||||
|
when.wait(100);
|
||||||
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
state: { mykey: { default: "value" } },
|
state: { mykey: { default: "value" } },
|
||||||
});
|
});
|
||||||
@@ -372,6 +375,7 @@ describe("modals", () => {
|
|||||||
when.click("global-state-add-variable");
|
when.click("global-state-add-variable");
|
||||||
when.setValue("global-state-variable-value:0", "myvalue");
|
when.setValue("global-state-variable-value:0", "myvalue");
|
||||||
when.typeKeys("{enter}");
|
when.typeKeys("{enter}");
|
||||||
|
when.wait(100);
|
||||||
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
state: { key1: { default: "myvalue" } },
|
state: { key1: { default: "myvalue" } },
|
||||||
});
|
});
|
||||||
|
|||||||
Generated
-20
@@ -51,7 +51,6 @@
|
|||||||
"react-collapse": "^5.1.1",
|
"react-collapse": "^5.1.1",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-file-reader-input": "^2.0.0",
|
|
||||||
"react-i18next": "^15.7.3",
|
"react-i18next": "^15.7.3",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
@@ -86,7 +85,6 @@
|
|||||||
"@types/react-collapse": "^5.0.4",
|
"@types/react-collapse": "^5.0.4",
|
||||||
"@types/react-color": "^3.0.13",
|
"@types/react-color": "^3.0.13",
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "^19.1.9",
|
||||||
"@types/react-file-reader-input": "^2.0.4",
|
|
||||||
"@types/string-hash": "^1.1.3",
|
"@types/string-hash": "^1.1.3",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"@types/wicg-file-system-access": "^2023.10.6",
|
"@types/wicg-file-system-access": "^2023.10.6",
|
||||||
@@ -3225,15 +3223,6 @@
|
|||||||
"@types/react": "^19.0.0"
|
"@types/react": "^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-file-reader-input": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-file-reader-input/-/react-file-reader-input-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-Jqrfn+w42j8t8Q3npMXXKPdk+reIM0UHLKVc3ykrA7q7bN3Z62SGhsClZX0+Edlqm66lcKwmDQl+WMm+Xor7Xg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/react": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/reactcss": {
|
"node_modules/@types/reactcss": {
|
||||||
"version": "1.2.12",
|
"version": "1.2.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.12.tgz",
|
||||||
@@ -11681,15 +11670,6 @@
|
|||||||
"react": "^19.1.1"
|
"react": "^19.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-file-reader-input": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-file-reader-input/-/react-file-reader-input-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-1XgkCpwMnNQsuOIy938UCntz8Xzwt9ECwHaH3cCfIQK1SPpH+y7gCYtqEcb6Rm0hAUq7Lp9+Ljoti9zGMswYrQ==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^15.0.0 || ^16.0.0",
|
|
||||||
"react-dom": "^15.0.0 || ^16.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-hot-loader": {
|
"node_modules/react-hot-loader": {
|
||||||
"version": "4.13.1",
|
"version": "4.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.13.1.tgz",
|
||||||
|
|||||||
@@ -66,7 +66,6 @@
|
|||||||
"react-collapse": "^5.1.1",
|
"react-collapse": "^5.1.1",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-file-reader-input": "^2.0.0",
|
|
||||||
"react-i18next": "^15.7.3",
|
"react-i18next": "^15.7.3",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
@@ -118,7 +117,6 @@
|
|||||||
"@types/react-collapse": "^5.0.4",
|
"@types/react-collapse": "^5.0.4",
|
||||||
"@types/react-color": "^3.0.13",
|
"@types/react-color": "^3.0.13",
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "^19.1.9",
|
||||||
"@types/react-file-reader-input": "^2.0.4",
|
|
||||||
"@types/string-hash": "^1.1.3",
|
"@types/string-hash": "^1.1.3",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"@types/wicg-file-system-access": "^2023.10.6",
|
"@types/wicg-file-system-access": "^2023.10.6",
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React, { type FormEvent } from "react";
|
import React, { type FormEvent } from "react";
|
||||||
import {MdFileUpload} from "react-icons/md";
|
import {MdFileUpload} from "react-icons/md";
|
||||||
import {MdAddCircleOutline} from "react-icons/md";
|
import {MdAddCircleOutline} from "react-icons/md";
|
||||||
import FileReaderInput, { type Result } from "react-file-reader-input";
|
|
||||||
import { Trans, type WithTranslation, withTranslation } from "react-i18next";
|
import { Trans, type WithTranslation, withTranslation } from "react-i18next";
|
||||||
|
|
||||||
import ModalLoading from "./ModalLoading";
|
import ModalLoading from "./ModalLoading";
|
||||||
@@ -171,8 +170,10 @@ class ModalOpenInternal extends React.Component<ModalOpenInternalProps, ModalOpe
|
|||||||
|
|
||||||
// it is not guaranteed that the File System Access API is available on all
|
// it is not guaranteed that the File System Access API is available on all
|
||||||
// browsers. If the function is not available, a fallback behavior is used.
|
// browsers. If the function is not available, a fallback behavior is used.
|
||||||
onFileChanged = async (_: any, files: Result[]) => {
|
onFileChanged = (files: FileList | null) => {
|
||||||
const [, file] = files[0];
|
if (!files) return;
|
||||||
|
if (files.length === 0) return;
|
||||||
|
const file = files[0];
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
this.clearError();
|
this.clearError();
|
||||||
|
|
||||||
@@ -246,13 +247,15 @@ class ModalOpenInternal extends React.Component<ModalOpenInternalProps, ModalOpe
|
|||||||
<div>
|
<div>
|
||||||
{typeof window.showOpenFilePicker === "function" ? (
|
{typeof window.showOpenFilePicker === "function" ? (
|
||||||
<InputButton
|
<InputButton
|
||||||
|
data-wd-key="modal:open.file.button"
|
||||||
className="maputnik-big-button"
|
className="maputnik-big-button"
|
||||||
onClick={this.onOpenFile}><MdFileUpload/> {t("Open Style")}
|
onClick={this.onOpenFile}><MdFileUpload/> {t("Open Style")}
|
||||||
</InputButton>
|
</InputButton>
|
||||||
) : (
|
) : (
|
||||||
<FileReaderInput onChange={this.onFileChanged} tabIndex={-1} aria-label={t("Open Style")}>
|
<label>
|
||||||
<InputButton className="maputnik-upload-button"><MdFileUpload /> {t("Open Style")}</InputButton>
|
<a className="maputnik-button maputnik-upload-button" aria-label={t("Open Style")}><MdFileUpload /> {t("Open Style")}</a>
|
||||||
</FileReaderInput>
|
<input data-wd-key="modal:open.file.input" type="file" style={{ display: "none" }} onChange={(e) => this.onFileChanged(e.target.files)} />
|
||||||
|
</label>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Reference in New Issue
Block a user