Html2canvas vs jspdf can't export svg in PDF file - reactjs

I use html2canvas vs jsPDF in my Reactjs project and I had a required that's export a DOM node to PDF file. When I exported, HTML and CSS was keeped just SVG can't. I dont know why. Have another package on client can help me? Thank for your attetion.
Here is my code to export
const filename = 'TyVan.pdf';
html2canvas(document.querySelector('#buivanty'),{scale: quality}).then(canvas => {
let pdf = new jsPDF('l', 'mm', 'a4', true)
pdf.addImage(canvas.toDataURL('image/png', 1.0), 'png', 10, 10, 180, 150);
pdf.save(filename);
})

I was able to resolve it by doing post processing using onClone option
const options = {
scale: 1,
foreignObjectRendering: true,
onclone: (element) => {
const svgElements: any[] = element.body.getElementsByTagName('svg');
Array.from(svgElements).forEach((svgElement) => {
const bBox: any = svgElement.getBBox();
svgElement.setAttribute('width', bBox.width);
svgElement.setAttribute('height', bBox.height);
});
},
};
html2canvas(<HTMLScriptElement>document.querySelector('.main-container'), options).then(canvas => {
this.clipImage = canvas.toDataURL('image/png');
});

Related

Export React Big Scheduler view to PDF / CSV

Has anyone succeeded in exporting the React Scheduler library view(day/week) into PDF or CSV?
Am working on a project that has ability to export to either PDF or CSV.
I have tried html2Canvas and pdfMake solution and the page seem blank.
Kindly help if you have.
Here is how i convert elements to canvas to generate pdf.
const handleExportToPDF = async () => {
html2canvas(document.querySelector('#printpdf'), {height: 1000, width: 800}).then(canvas => {
var data = canvas.toDataURL();
console.log(canvas)
var pdfExportSetting = {
content: [
{
image: await data,
width: 500
}
]
};
pdfMake.createPdf(pdfExportSetting).download("test_file.pdf");
});
};
Here is my scheduler
<span ref={scheduleRef} id='printpdf'>
<Scheduler
schedulerData={schedulerData}
prevClick={prevClick}
nextClick={nextClick}
onSelectDate={onSelectDate}
/>
</span>
Will appreciate.

React: Test cases are failing even when output is as expected

So I'm getting started with React testing. I have developed a basic Catalog Viewer Application which should be working fine but it is failing the test cases. One basic test is to click on a thumbnail and image should reflect the changes. It works when I do it manually but the test case is getting failed.
This is the application when I clicked the "white-light-candle.jpg":
As you can see, the preview thumbnail has been updated but the test case still failed:
This is the test script that is developed:
import "#testing-library/jest-dom/extend-expect";
import { act, cleanup, fireEvent, render } from "#testing-library/react";
import React from "react";
import App from "./App";
import { image1, image2, image3, image4 } from "./assets/images";
jest.useFakeTimers();
const TEST_IDS = {
viewerId: "catalog-view",
prevBtnId: "prev-slide-btn",
nextBtnId: "next-slide-btn",
thumbBtnPrefix: "thumb-button-",
toggleSlideShowBtnId: "toggle-slide-show-button",
};
describe("Catalog Viewer", () => {
let getByTestId;
let viewer;
let prevBtn;
let nextBtn;
let toggleSlideShowBtn;
let catalogs;
let thumbBtn2;
let thumbBtn4;
beforeEach(() => {
const app = render(<App />);
getByTestId = app.getByTestId;
viewer = getByTestId(TEST_IDS.viewerId);
prevBtn = getByTestId(TEST_IDS.prevBtnId);
nextBtn = getByTestId(TEST_IDS.nextBtnId);
thumbBtn2 = getByTestId(TEST_IDS.thumbBtnPrefix + "1");
thumbBtn4 = getByTestId(TEST_IDS.thumbBtnPrefix + "3");
toggleSlideShowBtn = getByTestId(TEST_IDS.toggleSlideShowBtnId);
catalogs = [
{
thumb: image1,
image: image1,
},
{
thumb: image2,
image: image2,
},
{
thumb: image3,
image: image3,
},
{
thumb: image4,
image: image4,
},
];
});
afterEach(() => {
cleanup();
});
test("clicking on any catalog thumbnail should show the appropriate image", () => {
fireEvent.click(thumbBtn2, { button: "0" });
expect(viewer.src).toContain(catalogs[1].image);
fireEvent.click(thumbBtn4, { button: "0" });
expect(viewer.src).toContain(catalogs[3].image);
});
});
Can anyone suggest where I should look to debug this problem? At this point I just ran out of options.
I can't unfortunately upload on Codepen at the moment. Here is the code for my application if anyone can help please:
Update-1
Modified the test case to include waitFor and changed extension to .jpg but it didn't help:
test("clicking on any catalog thumbnail should show the appropriate image", async () => {
fireEvent.click(thumbBtn2, { button: "0" });
await waitFor(() => {
expect(viewer.src).toContain(catalogs[1].image);
});
fireEvent.click(thumbBtn4, { button: "0" });
await waitFor(() => {
expect(viewer.src).toContain(catalogs[3].image);
});
});
The image src is "http://localhost/tea-light-candle.jpeg" and you are expecting "white-light-candle.jpg"
the src of the image is the full path of where the image is located. You are comparing to the wrong string, add the path and also verify the src of the image, because the real src says
"tea-light-candle"
and you wrote
"white-light-candle"
I know it's a bit late, but i have recently implemented the project and all testcase are running fine you can have a look at https://github.com/MSaddamKamal/react-catalog-viewer also make sure in your src/assets/images folder white-light-candle.jpg exists.
If every thing is fine then all test cases will pass as below

Error: Can't find end of central directory : is this a zip file ? in React & docxtemplater

I am facing an issue in using docxtemplater library to generate a doc file from my react application.
If anybody know how to solve this please help me.
import React from "react";
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
import Sample from './sample.js';
function loadFile(url, callback) {
PizZipUtils.getBinaryContent(url, callback);
}
function App(){
//const generateDocument = () => {
// fetch("http://localhost:5000/api/doc")
// .then(res => console.log(res))
//};
const generateDocument = () => {
loadFile("./assets/docs/newTemplate.docx",function (error, content) {
if (error) {
throw error;
}
console.log(content);
const zip = new PizZip(content);
const doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
});
// render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
doc.render({
client_name: "John",
});
const out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
}); //Output the document using Data-URI
saveAs(out, "output.docx");
}
)};
return (
<div className="p-2">
<button onClick={generateDocument}>
Generate document
</button>
<Sample></Sample>
</div>
);
};
export default App;
My template file is in assets/docs folder.
I tried various ways of using template in same folder & changing template with new templates but nothing worked. Please help me!
It might be caused by the name of the file containing Upper case, fix that - et voilĂ !

Testing react-map-gl with jest and react testing library timeout

I am currently trying to test a Component wrapped with third party library which is react-map-gl marker.
It keep throwing error like project undefined. so I looked into the react-map-gl code.
let [x, y] = this._context.viewport.project([longitude, latitude]);
Then, I went to see how react-map-gl test its own stuff. Then, I tried to miminc how they do.
But it just timeout no matter how much time I put. Am I missing something?
import {_MapContext as MapContext} from 'react-map-gl'
import WebMercatorViewport from 'viewport-mercator-project'
const mockStaticContext = {
viewport: new WebMercatorViewport({
width: 800,
height: 600,
longitude: -122.58,
latitude: 37.74,
zoom: 14
})
};
const mockInteractiveContext = Object.assign({}, mockStaticContext, {
eventManager: {
on: sinon.spy(),
off: sinon.spy(),
watch: sinon.spy()
}
})
describe('<ListingMarker />', () => {
it('should not explode', async (t) => {
render(
<MapContext.Provider value={mockInteractiveContext}>
<AppMarker cluster={marker} />
</MapContext.Provider>
)
}, 30000)
})
I tried to follow their way of testing.
https://github.com/visgl/react-map-gl/blob/master/test/src/components/marker.spec.js

how to add spinner for jspdf + html2canvas

I am trying to use jspdf and html2canvas for my project. It works great but if the page is large in size, it takes time to process after clicking the button to download the pdf. I would like to add a spinner as soon as the user clicks on the render PDF button. Though I have set the state for the loading property to true in react, the value is not rendered/displayed but it is displayed right before the pdf is downloaded.
Any thoughts ?
Code
printDocument() {
const input = document.getElementById('container');
this.setState({
isDownloading: true
});
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
const pdf = new pdfConverter("p", "mm", "a4");
var width = pdf.internal.pageSize.width;
var height = pdf.internal.pageSize.height;
pdf.addImage(imgData, 'JPEG', 0, 0,width,height);
pdf.save("download.pdf");
this.setState({
isDownloading: false
})
})
;
}

Resources